cregit-Linux how code gets into the kernel

Release 4.7 drivers/pci/proc.c

Directory: drivers/pci
/*
 *      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 <asm/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
pre-gitpre-git2045.45%120.00%
al viroal viro1636.36%240.00%
greg kroah-hartmangreg kroah-hartman511.36%120.00%
andrew mortonandrew 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
pre-gitpre-git35091.38%535.71%
al viroal viro133.39%428.57%
huang yinghuang ying102.61%17.14%
brian kingbrian king51.31%17.14%
harvey harrisonharvey harrison30.78%17.14%
greg kroah-hartmangreg 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
pre-gitpre-git30985.12%216.67%
al viroal viro154.13%433.33%
greg kroah-hartmangreg kroah-hartman113.03%216.67%
huang yinghuang ying102.75%18.33%
david rientjesdavid rientjes71.93%18.33%
harvey harrisonharvey harrison61.65%18.33%
brian kingbrian 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: fpriv->mmap_state = pci_mmap_io; break; case PCIIOC_MMAP_IS_MEM: fpriv->mmap_state = pci_mmap_mem; break; case PCIIOC_WRITE_COMBINE: if (arg) fpriv->write_combine = 1; else fpriv->write_combine = 0; break; #endif /* HAVE_PCI_MMAP */ default: ret = -EINVAL; break; } return ret; }

Contributors

PersonTokensPropCommitsCommitProp
linus torvaldslinus torvalds11589.84%116.67%
al viroal viro86.25%350.00%
matthew wilcoxmatthew wilcox32.34%116.67%
mathieu segaudmathieu segaud21.56%116.67%
Total128100.00%6100.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; if (!capable(CAP_SYS_RAWIO)) return -EPERM; /* Make sure the caller is mapping a real resource for this device */ for (i = 0; i < PCI_ROM_RESOURCE; i++) { if (pci_mmap_fits(dev, i, vma, PCI_MMAP_PROCFS)) break; } if (i >= PCI_ROM_RESOURCE) return -ENODEV; ret = pci_mmap_page_range(dev, vma, fpriv->mmap_state, fpriv->write_combine); if (ret < 0) return ret; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
linus torvaldslinus torvalds7459.68%228.57%
jesse barnesjesse barnes4032.26%114.29%
al viroal viro86.45%342.86%
martin wilckmartin wilck21.61%114.29%
Total124100.00%7100.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 torvaldslinus 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 torvaldslinus 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 torvaldslinus torvalds2657.78%120.00%
greg kroah-hartmangreg kroah-hartman715.56%120.00%
rolf eike beerrolf eike beer613.33%120.00%
pre-gitpre-git613.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 torvaldslinus torvalds3165.96%133.33%
greg kroah-hartmangreg kroah-hartman1429.79%133.33%
pre-gitpre-git24.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-hartmangreg kroah-hartman1854.55%250.00%
linus torvaldslinus torvalds1442.42%125.00%
pre-gitpre-git13.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
pre-gitpre-git14655.94%650.00%
michael ellermanmichael ellerman5721.84%18.33%
linus torvaldslinus torvalds3914.94%18.33%
greg kroah-hartmangreg kroah-hartman145.36%325.00%
yu zhaoyu 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
pre-gitpre-git11162.01%333.33%
matthew wilcoxmatthew wilcox4625.70%222.22%
greg kroah-hartmangreg kroah-hartman126.70%222.22%
denis v. lunevdenis v. lunev63.35%111.11%
david howellsdavid 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
pre-gitpre-git2492.31%266.67%
david howellsdavid howells27.69%133.33%
Total26100.00%3100.00%


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

Contributors

PersonTokensPropCommitsCommitProp
linus torvaldslinus torvalds1890.00%266.67%
david howellsdavid 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 torvaldslinus torvalds1560.00%133.33%
pre-gitpre-git832.00%133.33%
patrick mochelpatrick 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
pre-gitpre-git3769.81%440.00%
greg kroah-hartmangreg kroah-hartman611.32%220.00%
denis v. lunevdenis v. lunev35.66%110.00%
linus torvaldslinus torvalds35.66%110.00%
vasiliy kulikovvasiliy kulikov23.77%110.00%
alexey dobriyanalexey dobriyan23.77%110.00%
Total53100.00%10100.00%

device_initcall(pci_proc_init);

Overall Contributors

PersonTokensPropCommitsCommitProp
pre-gitpre-git105151.95%1523.44%
linus torvaldslinus torvalds51525.46%46.25%
greg kroah-hartmangreg kroah-hartman974.79%914.06%
al viroal viro602.97%57.81%
michael ellermanmichael ellerman572.82%11.56%
matthew wilcoxmatthew wilcox492.42%34.69%
jesse barnesjesse barnes401.98%11.56%
art haasart haas321.58%11.56%
huang yinghuang ying200.99%11.56%
denis v. lunevdenis v. lunev190.94%11.56%
brian kingbrian king100.49%11.56%
harvey harrisonharvey harrison90.44%11.56%
david howellsdavid howells80.40%23.12%
david rientjesdavid rientjes70.35%11.56%
rolf eike beerrolf eike beer60.30%11.56%
patrick mochelpatrick mochel60.30%23.12%
alexey dobriyanalexey dobriyan50.25%23.12%
yu zhaoyu zhao50.25%11.56%
arnd bergmannarnd bergmann50.25%11.56%
mathieu segaudmathieu segaud30.15%11.56%
ivan kokshayskyivan kokshaysky30.15%11.56%
andrew mortonandrew morton30.15%11.56%
tejun heotejun heo30.15%11.56%
vasiliy kulikovvasiliy kulikov20.10%11.56%
arjan van de venarjan van de ven20.10%11.56%
martin wilckmartin wilck20.10%11.56%
jan engelhardtjan engelhardt10.05%11.56%
christoph hellwigchristoph hellwig10.05%11.56%
adrian bunkadrian bunk10.05%11.56%
robert p. j. dayrobert p. j. day10.05%11.56%
ryan desfossesryan desfosses0.00%00.00%
Total2023100.00%64100.00%
Directory: drivers/pci
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
{% endraw %}