cregit-Linux how code gets into the kernel

Release 4.14 drivers/pci/proc.c

Directory: drivers/pci
// SPDX-License-Identifier: GPL-2.0
/*
 *      Procfs interface for the PCI bus.
 *
 *      Copyright (c) 1997--1999 Martin Mares <mj@ucw.cz>
 */

#include <linux/init.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/capability.h>
#include <linux/uaccess.h>
#include <asm/byteorder.h>
#include "pci.h"


static int proc_initialized;	
/* = 0 */


static loff_t proc_bus_pci_lseek(struct file *file, loff_t off, int whence) { struct pci_dev *dev = PDE_DATA(file_inode(file)); return fixed_size_llseek(file, off, whence, dev->cfg_size); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)2045.45%120.00%
Al Viro1636.36%240.00%
Greg Kroah-Hartman511.36%120.00%
Andrew Morton36.82%120.00%
Total44100.00%5100.00%


static ssize_t proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) { struct pci_dev *dev = PDE_DATA(file_inode(file)); unsigned int pos = *ppos; unsigned int cnt, size; /* * Normal users can read only the standardized portion of the * configuration space as several chips lock up when trying to read * undefined locations (think of Intel PIIX4 as a typical example). */ if (capable(CAP_SYS_ADMIN)) size = dev->cfg_size; else if (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) size = 128; else size = 64; if (pos >= size) return 0; if (nbytes >= size) nbytes = size; if (pos + nbytes > size) nbytes = size - pos; cnt = nbytes; if (!access_ok(VERIFY_WRITE, buf, cnt)) return -EINVAL; pci_config_pm_runtime_get(dev); if ((pos & 1) && cnt) { unsigned char val; pci_user_read_config_byte(dev, pos, &val); __put_user(val, buf); buf++; pos++; cnt--; } if ((pos & 3) && cnt > 2) { unsigned short val; pci_user_read_config_word(dev, pos, &val); __put_user(cpu_to_le16(val), (__le16 __user *) buf); buf += 2; pos += 2; cnt -= 2; } while (cnt >= 4) { unsigned int val; pci_user_read_config_dword(dev, pos, &val); __put_user(cpu_to_le32(val), (__le32 __user *) buf); buf += 4; pos += 4; cnt -= 4; } if (cnt >= 2) { unsigned short val; pci_user_read_config_word(dev, pos, &val); __put_user(cpu_to_le16(val), (__le16 __user *) buf); buf += 2; pos += 2; cnt -= 2; } if (cnt) { unsigned char val; pci_user_read_config_byte(dev, pos, &val); __put_user(val, buf); buf++; pos++; cnt--; } pci_config_pm_runtime_put(dev); *ppos = pos; return nbytes; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)35091.38%535.71%
Al Viro133.39%428.57%
Huang Ying102.61%17.14%
Brian King51.31%17.14%
Harvey Harrison30.78%17.14%
Greg Kroah-Hartman20.52%214.29%
Total383100.00%14100.00%


static ssize_t proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, loff_t *ppos) { struct inode *ino = file_inode(file); struct pci_dev *dev = PDE_DATA(ino); int pos = *ppos; int size = dev->cfg_size; int cnt; if (pos >= size) return 0; if (nbytes >= size) nbytes = size; if (pos + nbytes > size) nbytes = size - pos; cnt = nbytes; if (!access_ok(VERIFY_READ, buf, cnt)) return -EINVAL; pci_config_pm_runtime_get(dev); if ((pos & 1) && cnt) { unsigned char val; __get_user(val, buf); pci_user_write_config_byte(dev, pos, val); buf++; pos++; cnt--; } if ((pos & 3) && cnt > 2) { __le16 val; __get_user(val, (__le16 __user *) buf); pci_user_write_config_word(dev, pos, le16_to_cpu(val)); buf += 2; pos += 2; cnt -= 2; } while (cnt >= 4) { __le32 val; __get_user(val, (__le32 __user *) buf); pci_user_write_config_dword(dev, pos, le32_to_cpu(val)); buf += 4; pos += 4; cnt -= 4; } if (cnt >= 2) { __le16 val; __get_user(val, (__le16 __user *) buf); pci_user_write_config_word(dev, pos, le16_to_cpu(val)); buf += 2; pos += 2; cnt -= 2; } if (cnt) { unsigned char val; __get_user(val, buf); pci_user_write_config_byte(dev, pos, val); buf++; pos++; cnt--; } pci_config_pm_runtime_put(dev); *ppos = pos; i_size_write(ino, dev->cfg_size); return nbytes; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)30985.12%216.67%
Al Viro154.13%433.33%
Greg Kroah-Hartman113.03%216.67%
Huang Ying102.75%18.33%
David Rientjes71.93%18.33%
Harvey Harrison61.65%18.33%
Brian King51.38%18.33%
Total363100.00%12100.00%

struct pci_filp_private { enum pci_mmap_state mmap_state; int write_combine; };
static long proc_bus_pci_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct pci_dev *dev = PDE_DATA(file_inode(file)); #ifdef HAVE_PCI_MMAP struct pci_filp_private *fpriv = file->private_data; #endif /* HAVE_PCI_MMAP */ int ret = 0; switch (cmd) { case PCIIOC_CONTROLLER: ret = pci_domain_nr(dev->bus); break; #ifdef HAVE_PCI_MMAP case PCIIOC_MMAP_IS_IO: if (!arch_can_pci_mmap_io()) return -EINVAL; fpriv->mmap_state = pci_mmap_io; break; case PCIIOC_MMAP_IS_MEM: fpriv->mmap_state = pci_mmap_mem; break; case PCIIOC_WRITE_COMBINE: if (arch_can_pci_mmap_wc()) { if (arg) fpriv->write_combine = 1; else fpriv->write_combine = 0; break; } /* If arch decided it can't, fall through... */ #endif /* HAVE_PCI_MMAP */ default: ret = -EINVAL; break; } return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds11578.77%112.50%
David Woodhouse1812.33%225.00%
Al Viro85.48%337.50%
Matthew Wilcox32.05%112.50%
Mathieu Segaud21.37%112.50%
Total146100.00%8100.00%

#ifdef HAVE_PCI_MMAP
static int proc_bus_pci_mmap(struct file *file, struct vm_area_struct *vma) { struct pci_dev *dev = PDE_DATA(file_inode(file)); struct pci_filp_private *fpriv = file->private_data; int i, ret, write_combine = 0, res_bit = IORESOURCE_MEM; if (!capable(CAP_SYS_RAWIO)) return -EPERM; if (fpriv->mmap_state == pci_mmap_io) { if (!arch_can_pci_mmap_io()) return -EINVAL; res_bit = IORESOURCE_IO; } /* Make sure the caller is mapping a real resource for this device */ for (i = 0; i < PCI_ROM_RESOURCE; i++) { if (dev->resource[i].flags & res_bit && pci_mmap_fits(dev, i, vma, PCI_MMAP_PROCFS)) break; } if (i >= PCI_ROM_RESOURCE) return -ENODEV; if (fpriv->mmap_state == pci_mmap_mem && fpriv->write_combine) { if (dev->resource[i].flags & IORESOURCE_PREFETCH) write_combine = 1; else return -EINVAL; } ret = pci_mmap_page_range(dev, i, vma, fpriv->mmap_state, write_combine); if (ret < 0) return ret; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds7235.47%216.67%
David Woodhouse6632.51%433.33%
Jesse Barnes4019.70%18.33%
Björn Helgaas157.39%18.33%
Al Viro83.94%325.00%
Martin Wilck20.99%18.33%
Total203100.00%12100.00%


static int proc_bus_pci_open(struct inode *inode, struct file *file) { struct pci_filp_private *fpriv = kmalloc(sizeof(*fpriv), GFP_KERNEL); if (!fpriv) return -ENOMEM; fpriv->mmap_state = pci_mmap_io; fpriv->write_combine = 0; file->private_data = fpriv; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds62100.00%1100.00%
Total62100.00%1100.00%


static int proc_bus_pci_release(struct inode *inode, struct file *file) { kfree(file->private_data); file->private_data = NULL; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds32100.00%1100.00%
Total32100.00%1100.00%

#endif /* HAVE_PCI_MMAP */ static const struct file_operations proc_bus_pci_operations = { .owner = THIS_MODULE, .llseek = proc_bus_pci_lseek, .read = proc_bus_pci_read, .write = proc_bus_pci_write, .unlocked_ioctl = proc_bus_pci_ioctl, .compat_ioctl = proc_bus_pci_ioctl, #ifdef HAVE_PCI_MMAP .open = proc_bus_pci_open, .release = proc_bus_pci_release, .mmap = proc_bus_pci_mmap, #ifdef HAVE_ARCH_PCI_GET_UNMAPPED_AREA .get_unmapped_area = get_pci_unmapped_area, #endif /* HAVE_ARCH_PCI_GET_UNMAPPED_AREA */ #endif /* HAVE_PCI_MMAP */ }; /* iterator */
static void *pci_seq_start(struct seq_file *m, loff_t *pos) { struct pci_dev *dev = NULL; loff_t n = *pos; for_each_pci_dev(dev) { if (!n--) break; } return dev; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds2657.78%120.00%
Greg Kroah-Hartman715.56%120.00%
Rolf Eike Beer613.33%120.00%
Linus Torvalds (pre-git)613.33%240.00%
Total45100.00%5100.00%


static void *pci_seq_next(struct seq_file *m, void *v, loff_t *pos) { struct pci_dev *dev = v; (*pos)++; dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev); return dev; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds3165.96%133.33%
Greg Kroah-Hartman1429.79%133.33%
Linus Torvalds (pre-git)24.26%133.33%
Total47100.00%3100.00%


static void pci_seq_stop(struct seq_file *m, void *v) { if (v) { struct pci_dev *dev = v; pci_dev_put(dev); } }

Contributors

PersonTokensPropCommitsCommitProp
Greg Kroah-Hartman1854.55%250.00%
Linus Torvalds1442.42%125.00%
Linus Torvalds (pre-git)13.03%125.00%
Total33100.00%4100.00%


static int show_device(struct seq_file *m, void *v) { const struct pci_dev *dev = v; const struct pci_driver *drv; int i; if (dev == NULL) return 0; drv = pci_dev_driver(dev); seq_printf(m, "%02x%02x\t%04x%04x\t%x", dev->bus->number, dev->devfn, dev->vendor, dev->device, dev->irq); /* only print standard and ROM resources to preserve compatibility */ for (i = 0; i <= PCI_ROM_RESOURCE; i++) { resource_size_t start, end; pci_resource_to_user(dev, i, &dev->resource[i], &start, &end); seq_printf(m, "\t%16llx", (unsigned long long)(start | (dev->resource[i].flags & PCI_REGION_FLAG_MASK))); } for (i = 0; i <= PCI_ROM_RESOURCE; i++) { resource_size_t start, end; pci_resource_to_user(dev, i, &dev->resource[i], &start, &end); seq_printf(m, "\t%16llx", dev->resource[i].start < dev->resource[i].end ? (unsigned long long)(end - start) + 1 : 0); } seq_putc(m, '\t'); if (drv) seq_printf(m, "%s", drv->name); seq_putc(m, '\n'); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)14655.94%650.00%
Michael Ellerman5721.84%18.33%
Linus Torvalds3914.94%18.33%
Greg Kroah-Hartman145.36%325.00%
Yu Zhao51.92%18.33%
Total261100.00%12100.00%

static const struct seq_operations proc_bus_pci_devices_op = { .start = pci_seq_start, .next = pci_seq_next, .stop = pci_seq_stop, .show = show_device }; static struct proc_dir_entry *proc_bus_pci_dir;
int pci_proc_attach_device(struct pci_dev *dev) { struct pci_bus *bus = dev->bus; struct proc_dir_entry *e; char name[16]; if (!proc_initialized) return -EACCES; if (!bus->procdir) { if (pci_proc_domain(bus)) { sprintf(name, "%04x:%02x", pci_domain_nr(bus), bus->number); } else { sprintf(name, "%02x", bus->number); } bus->procdir = proc_mkdir(name, proc_bus_pci_dir); if (!bus->procdir) return -ENOMEM; } sprintf(name, "%02x.%x", PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); e = proc_create_data(name, S_IFREG | S_IRUGO | S_IWUSR, bus->procdir, &proc_bus_pci_operations, dev); if (!e) return -ENOMEM; proc_set_size(e, dev->cfg_size); dev->procent = e; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)11162.01%333.33%
Matthew Wilcox4625.70%222.22%
Greg Kroah-Hartman126.70%222.22%
Denis V. Lunev63.35%111.11%
David Howells42.23%111.11%
Total179100.00%9100.00%


int pci_proc_detach_device(struct pci_dev *dev) { proc_remove(dev->procent); dev->procent = NULL; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)2492.31%150.00%
David Howells27.69%150.00%
Total26100.00%2100.00%


int pci_proc_detach_bus(struct pci_bus *bus) { proc_remove(bus->procdir); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds1890.00%266.67%
David Howells210.00%133.33%
Total20100.00%3100.00%


static int proc_bus_pci_dev_open(struct inode *inode, struct file *file) { return seq_open(file, &proc_bus_pci_devices_op); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds1560.00%133.33%
Linus Torvalds (pre-git)832.00%133.33%
Patrick Mochel28.00%133.33%
Total25100.00%3100.00%

static const struct file_operations proc_bus_pci_dev_operations = { .owner = THIS_MODULE, .open = proc_bus_pci_dev_open, .read = seq_read, .llseek = seq_lseek, .release = seq_release, };
static int __init pci_proc_init(void) { struct pci_dev *dev = NULL; proc_bus_pci_dir = proc_mkdir("bus/pci", NULL); proc_create("devices", 0, proc_bus_pci_dir, &proc_bus_pci_dev_operations); proc_initialized = 1; for_each_pci_dev(dev) pci_proc_attach_device(dev); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)3769.81%440.00%
Greg Kroah-Hartman611.32%220.00%
Linus Torvalds35.66%110.00%
Denis V. Lunev35.66%110.00%
Vasiliy Kulikov23.77%110.00%
Alexey Dobriyan23.77%110.00%
Total53100.00%10100.00%

device_initcall(pci_proc_init);

Overall Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)105049.50%1520.83%
Linus Torvalds51424.23%56.94%
Greg Kroah-Hartman984.62%1013.89%
David Woodhouse843.96%56.94%
Al Viro602.83%56.94%
Michael Ellerman572.69%11.39%
Matthew Wilcox492.31%34.17%
Jesse Barnes401.89%11.39%
Art Haas321.51%11.39%
Huang Ying200.94%11.39%
Denis V. Lunev190.90%11.39%
Björn Helgaas150.71%11.39%
Brian King100.47%11.39%
Harvey Harrison90.42%11.39%
David Howells80.38%22.78%
David Rientjes70.33%11.39%
Patrick Mochel60.28%22.78%
Rolf Eike Beer60.28%11.39%
Alexey Dobriyan50.24%22.78%
Yu Zhao50.24%11.39%
Arnd Bergmann50.24%11.39%
Mathieu Segaud30.14%11.39%
Andrew Morton30.14%11.39%
Tejun Heo30.14%11.39%
Ivan Kokshaysky30.14%11.39%
Vasiliy Kulikov20.09%11.39%
Martin Wilck20.09%11.39%
Arjan van de Ven20.09%11.39%
Christoph Hellwig10.05%11.39%
Robert P. J. Day10.05%11.39%
Adrian Bunk10.05%11.39%
Jan Engelhardt10.05%11.39%
Ryan Desfosses0.00%00.00%
Total2121100.00%72100.00%
Directory: drivers/pci
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.