linux/drivers/pci/pci-sysfs.c
<<
>>
Prefs
   1/*
   2 * drivers/pci/pci-sysfs.c
   3 *
   4 * (C) Copyright 2002-2004 Greg Kroah-Hartman <greg@kroah.com>
   5 * (C) Copyright 2002-2004 IBM Corp.
   6 * (C) Copyright 2003 Matthew Wilcox
   7 * (C) Copyright 2003 Hewlett-Packard
   8 * (C) Copyright 2004 Jon Smirl <jonsmirl@yahoo.com>
   9 * (C) Copyright 2004 Silicon Graphics, Inc. Jesse Barnes <jbarnes@sgi.com>
  10 *
  11 * File attributes for PCI devices
  12 *
  13 * Modeled after usb's driverfs.c 
  14 *
  15 */
  16
  17
  18#include <linux/kernel.h>
  19#include <linux/sched.h>
  20#include <linux/pci.h>
  21#include <linux/stat.h>
  22#include <linux/topology.h>
  23#include <linux/mm.h>
  24#include <linux/capability.h>
  25#include <linux/pci-aspm.h>
  26#include "pci.h"
  27
  28static int sysfs_initialized;   /* = 0 */
  29
  30/* show configuration fields */
  31#define pci_config_attr(field, format_string)                           \
  32static ssize_t                                                          \
  33field##_show(struct device *dev, struct device_attribute *attr, char *buf)                              \
  34{                                                                       \
  35        struct pci_dev *pdev;                                           \
  36                                                                        \
  37        pdev = to_pci_dev (dev);                                        \
  38        return sprintf (buf, format_string, pdev->field);               \
  39}
  40
  41pci_config_attr(vendor, "0x%04x\n");
  42pci_config_attr(device, "0x%04x\n");
  43pci_config_attr(subsystem_vendor, "0x%04x\n");
  44pci_config_attr(subsystem_device, "0x%04x\n");
  45pci_config_attr(class, "0x%06x\n");
  46pci_config_attr(irq, "%u\n");
  47
  48static ssize_t broken_parity_status_show(struct device *dev,
  49                                         struct device_attribute *attr,
  50                                         char *buf)
  51{
  52        struct pci_dev *pdev = to_pci_dev(dev);
  53        return sprintf (buf, "%u\n", pdev->broken_parity_status);
  54}
  55
  56static ssize_t broken_parity_status_store(struct device *dev,
  57                                          struct device_attribute *attr,
  58                                          const char *buf, size_t count)
  59{
  60        struct pci_dev *pdev = to_pci_dev(dev);
  61        unsigned long val;
  62
  63        if (strict_strtoul(buf, 0, &val) < 0)
  64                return -EINVAL;
  65
  66        pdev->broken_parity_status = !!val;
  67
  68        return count;
  69}
  70
  71static ssize_t local_cpus_show(struct device *dev,
  72                        struct device_attribute *attr, char *buf)
  73{               
  74        const struct cpumask *mask;
  75        int len;
  76
  77        mask = cpumask_of_pcibus(to_pci_dev(dev)->bus);
  78        len = cpumask_scnprintf(buf, PAGE_SIZE-2, mask);
  79        buf[len++] = '\n';
  80        buf[len] = '\0';
  81        return len;
  82}
  83
  84
  85static ssize_t local_cpulist_show(struct device *dev,
  86                        struct device_attribute *attr, char *buf)
  87{
  88        const struct cpumask *mask;
  89        int len;
  90
  91        mask = cpumask_of_pcibus(to_pci_dev(dev)->bus);
  92        len = cpulist_scnprintf(buf, PAGE_SIZE-2, mask);
  93        buf[len++] = '\n';
  94        buf[len] = '\0';
  95        return len;
  96}
  97
  98/* show resources */
  99static ssize_t
 100resource_show(struct device * dev, struct device_attribute *attr, char * buf)
 101{
 102        struct pci_dev * pci_dev = to_pci_dev(dev);
 103        char * str = buf;
 104        int i;
 105        int max;
 106        resource_size_t start, end;
 107
 108        if (pci_dev->subordinate)
 109                max = DEVICE_COUNT_RESOURCE;
 110        else
 111                max = PCI_BRIDGE_RESOURCES;
 112
 113        for (i = 0; i < max; i++) {
 114                struct resource *res =  &pci_dev->resource[i];
 115                pci_resource_to_user(pci_dev, i, res, &start, &end);
 116                str += sprintf(str,"0x%016llx 0x%016llx 0x%016llx\n",
 117                               (unsigned long long)start,
 118                               (unsigned long long)end,
 119                               (unsigned long long)res->flags);
 120        }
 121        return (str - buf);
 122}
 123
 124static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf)
 125{
 126        struct pci_dev *pci_dev = to_pci_dev(dev);
 127
 128        return sprintf(buf, "pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02x\n",
 129                       pci_dev->vendor, pci_dev->device,
 130                       pci_dev->subsystem_vendor, pci_dev->subsystem_device,
 131                       (u8)(pci_dev->class >> 16), (u8)(pci_dev->class >> 8),
 132                       (u8)(pci_dev->class));
 133}
 134
 135static ssize_t is_enabled_store(struct device *dev,
 136                                struct device_attribute *attr, const char *buf,
 137                                size_t count)
 138{
 139        struct pci_dev *pdev = to_pci_dev(dev);
 140        unsigned long val;
 141        ssize_t result = strict_strtoul(buf, 0, &val);
 142
 143        if (result < 0)
 144                return result;
 145
 146        /* this can crash the machine when done on the "wrong" device */
 147        if (!capable(CAP_SYS_ADMIN))
 148                return -EPERM;
 149
 150        if (!val) {
 151                if (atomic_read(&pdev->enable_cnt) != 0)
 152                        pci_disable_device(pdev);
 153                else
 154                        result = -EIO;
 155        } else
 156                result = pci_enable_device(pdev);
 157
 158        return result < 0 ? result : count;
 159}
 160
 161static ssize_t is_enabled_show(struct device *dev,
 162                               struct device_attribute *attr, char *buf)
 163{
 164        struct pci_dev *pdev;
 165
 166        pdev = to_pci_dev (dev);
 167        return sprintf (buf, "%u\n", atomic_read(&pdev->enable_cnt));
 168}
 169
 170#ifdef CONFIG_NUMA
 171static ssize_t
 172numa_node_show(struct device *dev, struct device_attribute *attr, char *buf)
 173{
 174        return sprintf (buf, "%d\n", dev->numa_node);
 175}
 176#endif
 177
 178static ssize_t
 179msi_bus_show(struct device *dev, struct device_attribute *attr, char *buf)
 180{
 181        struct pci_dev *pdev = to_pci_dev(dev);
 182
 183        if (!pdev->subordinate)
 184                return 0;
 185
 186        return sprintf (buf, "%u\n",
 187                        !(pdev->subordinate->bus_flags & PCI_BUS_FLAGS_NO_MSI));
 188}
 189
 190static ssize_t
 191msi_bus_store(struct device *dev, struct device_attribute *attr,
 192              const char *buf, size_t count)
 193{
 194        struct pci_dev *pdev = to_pci_dev(dev);
 195        unsigned long val;
 196
 197        if (strict_strtoul(buf, 0, &val) < 0)
 198                return -EINVAL;
 199
 200        /* bad things may happen if the no_msi flag is changed
 201         * while some drivers are loaded */
 202        if (!capable(CAP_SYS_ADMIN))
 203                return -EPERM;
 204
 205        /* Maybe pci devices without subordinate busses shouldn't even have this
 206         * attribute in the first place?  */
 207        if (!pdev->subordinate)
 208                return count;
 209
 210        /* Is the flag going to change, or keep the value it already had? */
 211        if (!(pdev->subordinate->bus_flags & PCI_BUS_FLAGS_NO_MSI) ^
 212            !!val) {
 213                pdev->subordinate->bus_flags ^= PCI_BUS_FLAGS_NO_MSI;
 214
 215                dev_warn(&pdev->dev, "forced subordinate bus to%s support MSI,"
 216                         " bad things could happen\n", val ? "" : " not");
 217        }
 218
 219        return count;
 220}
 221
 222struct device_attribute pci_dev_attrs[] = {
 223        __ATTR_RO(resource),
 224        __ATTR_RO(vendor),
 225        __ATTR_RO(device),
 226        __ATTR_RO(subsystem_vendor),
 227        __ATTR_RO(subsystem_device),
 228        __ATTR_RO(class),
 229        __ATTR_RO(irq),
 230        __ATTR_RO(local_cpus),
 231        __ATTR_RO(local_cpulist),
 232        __ATTR_RO(modalias),
 233#ifdef CONFIG_NUMA
 234        __ATTR_RO(numa_node),
 235#endif
 236        __ATTR(enable, 0600, is_enabled_show, is_enabled_store),
 237        __ATTR(broken_parity_status,(S_IRUGO|S_IWUSR),
 238                broken_parity_status_show,broken_parity_status_store),
 239        __ATTR(msi_bus, 0644, msi_bus_show, msi_bus_store),
 240        __ATTR_NULL,
 241};
 242
 243static ssize_t
 244pci_read_config(struct kobject *kobj, struct bin_attribute *bin_attr,
 245                char *buf, loff_t off, size_t count)
 246{
 247        struct pci_dev *dev = to_pci_dev(container_of(kobj,struct device,kobj));
 248        unsigned int size = 64;
 249        loff_t init_off = off;
 250        u8 *data = (u8*) buf;
 251
 252        /* Several chips lock up trying to read undefined config space */
 253        if (capable(CAP_SYS_ADMIN)) {
 254                size = dev->cfg_size;
 255        } else if (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) {
 256                size = 128;
 257        }
 258
 259        if (off > size)
 260                return 0;
 261        if (off + count > size) {
 262                size -= off;
 263                count = size;
 264        } else {
 265                size = count;
 266        }
 267
 268        if ((off & 1) && size) {
 269                u8 val;
 270                pci_user_read_config_byte(dev, off, &val);
 271                data[off - init_off] = val;
 272                off++;
 273                size--;
 274        }
 275
 276        if ((off & 3) && size > 2) {
 277                u16 val;
 278                pci_user_read_config_word(dev, off, &val);
 279                data[off - init_off] = val & 0xff;
 280                data[off - init_off + 1] = (val >> 8) & 0xff;
 281                off += 2;
 282                size -= 2;
 283        }
 284
 285        while (size > 3) {
 286                u32 val;
 287                pci_user_read_config_dword(dev, off, &val);
 288                data[off - init_off] = val & 0xff;
 289                data[off - init_off + 1] = (val >> 8) & 0xff;
 290                data[off - init_off + 2] = (val >> 16) & 0xff;
 291                data[off - init_off + 3] = (val >> 24) & 0xff;
 292                off += 4;
 293                size -= 4;
 294        }
 295
 296        if (size >= 2) {
 297                u16 val;
 298                pci_user_read_config_word(dev, off, &val);
 299                data[off - init_off] = val & 0xff;
 300                data[off - init_off + 1] = (val >> 8) & 0xff;
 301                off += 2;
 302                size -= 2;
 303        }
 304
 305        if (size > 0) {
 306                u8 val;
 307                pci_user_read_config_byte(dev, off, &val);
 308                data[off - init_off] = val;
 309                off++;
 310                --size;
 311        }
 312
 313        return count;
 314}
 315
 316static ssize_t
 317pci_write_config(struct kobject *kobj, struct bin_attribute *bin_attr,
 318                 char *buf, loff_t off, size_t count)
 319{
 320        struct pci_dev *dev = to_pci_dev(container_of(kobj,struct device,kobj));
 321        unsigned int size = count;
 322        loff_t init_off = off;
 323        u8 *data = (u8*) buf;
 324
 325        if (off > dev->cfg_size)
 326                return 0;
 327        if (off + count > dev->cfg_size) {
 328                size = dev->cfg_size - off;
 329                count = size;
 330        }
 331        
 332        if ((off & 1) && size) {
 333                pci_user_write_config_byte(dev, off, data[off - init_off]);
 334                off++;
 335                size--;
 336        }
 337        
 338        if ((off & 3) && size > 2) {
 339                u16 val = data[off - init_off];
 340                val |= (u16) data[off - init_off + 1] << 8;
 341                pci_user_write_config_word(dev, off, val);
 342                off += 2;
 343                size -= 2;
 344        }
 345
 346        while (size > 3) {
 347                u32 val = data[off - init_off];
 348                val |= (u32) data[off - init_off + 1] << 8;
 349                val |= (u32) data[off - init_off + 2] << 16;
 350                val |= (u32) data[off - init_off + 3] << 24;
 351                pci_user_write_config_dword(dev, off, val);
 352                off += 4;
 353                size -= 4;
 354        }
 355        
 356        if (size >= 2) {
 357                u16 val = data[off - init_off];
 358                val |= (u16) data[off - init_off + 1] << 8;
 359                pci_user_write_config_word(dev, off, val);
 360                off += 2;
 361                size -= 2;
 362        }
 363
 364        if (size) {
 365                pci_user_write_config_byte(dev, off, data[off - init_off]);
 366                off++;
 367                --size;
 368        }
 369
 370        return count;
 371}
 372
 373static ssize_t
 374read_vpd_attr(struct kobject *kobj, struct bin_attribute *bin_attr,
 375              char *buf, loff_t off, size_t count)
 376{
 377        struct pci_dev *dev =
 378                to_pci_dev(container_of(kobj, struct device, kobj));
 379
 380        if (off > bin_attr->size)
 381                count = 0;
 382        else if (count > bin_attr->size - off)
 383                count = bin_attr->size - off;
 384
 385        return pci_read_vpd(dev, off, count, buf);
 386}
 387
 388static ssize_t
 389write_vpd_attr(struct kobject *kobj, struct bin_attribute *bin_attr,
 390               char *buf, loff_t off, size_t count)
 391{
 392        struct pci_dev *dev =
 393                to_pci_dev(container_of(kobj, struct device, kobj));
 394
 395        if (off > bin_attr->size)
 396                count = 0;
 397        else if (count > bin_attr->size - off)
 398                count = bin_attr->size - off;
 399
 400        return pci_write_vpd(dev, off, count, buf);
 401}
 402
 403#ifdef HAVE_PCI_LEGACY
 404/**
 405 * pci_read_legacy_io - read byte(s) from legacy I/O port space
 406 * @kobj: kobject corresponding to file to read from
 407 * @buf: buffer to store results
 408 * @off: offset into legacy I/O port space
 409 * @count: number of bytes to read
 410 *
 411 * Reads 1, 2, or 4 bytes from legacy I/O port space using an arch specific
 412 * callback routine (pci_legacy_read).
 413 */
 414static ssize_t
 415pci_read_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr,
 416                   char *buf, loff_t off, size_t count)
 417{
 418        struct pci_bus *bus = to_pci_bus(container_of(kobj,
 419                                                      struct device,
 420                                                      kobj));
 421
 422        /* Only support 1, 2 or 4 byte accesses */
 423        if (count != 1 && count != 2 && count != 4)
 424                return -EINVAL;
 425
 426        return pci_legacy_read(bus, off, (u32 *)buf, count);
 427}
 428
 429/**
 430 * pci_write_legacy_io - write byte(s) to legacy I/O port space
 431 * @kobj: kobject corresponding to file to read from
 432 * @buf: buffer containing value to be written
 433 * @off: offset into legacy I/O port space
 434 * @count: number of bytes to write
 435 *
 436 * Writes 1, 2, or 4 bytes from legacy I/O port space using an arch specific
 437 * callback routine (pci_legacy_write).
 438 */
 439static ssize_t
 440pci_write_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr,
 441                    char *buf, loff_t off, size_t count)
 442{
 443        struct pci_bus *bus = to_pci_bus(container_of(kobj,
 444                                                      struct device,
 445                                                      kobj));
 446        /* Only support 1, 2 or 4 byte accesses */
 447        if (count != 1 && count != 2 && count != 4)
 448                return -EINVAL;
 449
 450        return pci_legacy_write(bus, off, *(u32 *)buf, count);
 451}
 452
 453/**
 454 * pci_mmap_legacy_mem - map legacy PCI memory into user memory space
 455 * @kobj: kobject corresponding to device to be mapped
 456 * @attr: struct bin_attribute for this file
 457 * @vma: struct vm_area_struct passed to mmap
 458 *
 459 * Uses an arch specific callback, pci_mmap_legacy_mem_page_range, to mmap
 460 * legacy memory space (first meg of bus space) into application virtual
 461 * memory space.
 462 */
 463static int
 464pci_mmap_legacy_mem(struct kobject *kobj, struct bin_attribute *attr,
 465                    struct vm_area_struct *vma)
 466{
 467        struct pci_bus *bus = to_pci_bus(container_of(kobj,
 468                                                      struct device,
 469                                                      kobj));
 470
 471        return pci_mmap_legacy_page_range(bus, vma, pci_mmap_mem);
 472}
 473
 474/**
 475 * pci_mmap_legacy_io - map legacy PCI IO into user memory space
 476 * @kobj: kobject corresponding to device to be mapped
 477 * @attr: struct bin_attribute for this file
 478 * @vma: struct vm_area_struct passed to mmap
 479 *
 480 * Uses an arch specific callback, pci_mmap_legacy_io_page_range, to mmap
 481 * legacy IO space (first meg of bus space) into application virtual
 482 * memory space. Returns -ENOSYS if the operation isn't supported
 483 */
 484static int
 485pci_mmap_legacy_io(struct kobject *kobj, struct bin_attribute *attr,
 486                   struct vm_area_struct *vma)
 487{
 488        struct pci_bus *bus = to_pci_bus(container_of(kobj,
 489                                                      struct device,
 490                                                      kobj));
 491
 492        return pci_mmap_legacy_page_range(bus, vma, pci_mmap_io);
 493}
 494
 495/**
 496 * pci_create_legacy_files - create legacy I/O port and memory files
 497 * @b: bus to create files under
 498 *
 499 * Some platforms allow access to legacy I/O port and ISA memory space on
 500 * a per-bus basis.  This routine creates the files and ties them into
 501 * their associated read, write and mmap files from pci-sysfs.c
 502 *
 503 * On error unwind, but don't propogate the error to the caller
 504 * as it is ok to set up the PCI bus without these files.
 505 */
 506void pci_create_legacy_files(struct pci_bus *b)
 507{
 508        int error;
 509
 510        b->legacy_io = kzalloc(sizeof(struct bin_attribute) * 2,
 511                               GFP_ATOMIC);
 512        if (!b->legacy_io)
 513                goto kzalloc_err;
 514
 515        b->legacy_io->attr.name = "legacy_io";
 516        b->legacy_io->size = 0xffff;
 517        b->legacy_io->attr.mode = S_IRUSR | S_IWUSR;
 518        b->legacy_io->read = pci_read_legacy_io;
 519        b->legacy_io->write = pci_write_legacy_io;
 520        b->legacy_io->mmap = pci_mmap_legacy_io;
 521        error = device_create_bin_file(&b->dev, b->legacy_io);
 522        if (error)
 523                goto legacy_io_err;
 524
 525        /* Allocated above after the legacy_io struct */
 526        b->legacy_mem = b->legacy_io + 1;
 527        b->legacy_mem->attr.name = "legacy_mem";
 528        b->legacy_mem->size = 1024*1024;
 529        b->legacy_mem->attr.mode = S_IRUSR | S_IWUSR;
 530        b->legacy_mem->mmap = pci_mmap_legacy_mem;
 531        error = device_create_bin_file(&b->dev, b->legacy_mem);
 532        if (error)
 533                goto legacy_mem_err;
 534
 535        return;
 536
 537legacy_mem_err:
 538        device_remove_bin_file(&b->dev, b->legacy_io);
 539legacy_io_err:
 540        kfree(b->legacy_io);
 541        b->legacy_io = NULL;
 542kzalloc_err:
 543        printk(KERN_WARNING "pci: warning: could not create legacy I/O port "
 544               "and ISA memory resources to sysfs\n");
 545        return;
 546}
 547
 548void pci_remove_legacy_files(struct pci_bus *b)
 549{
 550        if (b->legacy_io) {
 551                device_remove_bin_file(&b->dev, b->legacy_io);
 552                device_remove_bin_file(&b->dev, b->legacy_mem);
 553                kfree(b->legacy_io); /* both are allocated here */
 554        }
 555}
 556#endif /* HAVE_PCI_LEGACY */
 557
 558#ifdef HAVE_PCI_MMAP
 559
 560int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct *vma)
 561{
 562        unsigned long nr, start, size;
 563
 564        nr = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
 565        start = vma->vm_pgoff;
 566        size = ((pci_resource_len(pdev, resno) - 1) >> PAGE_SHIFT) + 1;
 567        if (start < size && size - start >= nr)
 568                return 1;
 569        WARN(1, "process \"%s\" tried to map 0x%08lx-0x%08lx on %s BAR %d (size 0x%08lx)\n",
 570                current->comm, start, start+nr, pci_name(pdev), resno, size);
 571        return 0;
 572}
 573
 574/**
 575 * pci_mmap_resource - map a PCI resource into user memory space
 576 * @kobj: kobject for mapping
 577 * @attr: struct bin_attribute for the file being mapped
 578 * @vma: struct vm_area_struct passed into the mmap
 579 * @write_combine: 1 for write_combine mapping
 580 *
 581 * Use the regular PCI mapping routines to map a PCI resource into userspace.
 582 */
 583static int
 584pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr,
 585                  struct vm_area_struct *vma, int write_combine)
 586{
 587        struct pci_dev *pdev = to_pci_dev(container_of(kobj,
 588                                                       struct device, kobj));
 589        struct resource *res = (struct resource *)attr->private;
 590        enum pci_mmap_state mmap_type;
 591        resource_size_t start, end;
 592        int i;
 593
 594        for (i = 0; i < PCI_ROM_RESOURCE; i++)
 595                if (res == &pdev->resource[i])
 596                        break;
 597        if (i >= PCI_ROM_RESOURCE)
 598                return -ENODEV;
 599
 600        if (!pci_mmap_fits(pdev, i, vma))
 601                return -EINVAL;
 602
 603        /* pci_mmap_page_range() expects the same kind of entry as coming
 604         * from /proc/bus/pci/ which is a "user visible" value. If this is
 605         * different from the resource itself, arch will do necessary fixup.
 606         */
 607        pci_resource_to_user(pdev, i, res, &start, &end);
 608        vma->vm_pgoff += start >> PAGE_SHIFT;
 609        mmap_type = res->flags & IORESOURCE_MEM ? pci_mmap_mem : pci_mmap_io;
 610
 611        if (res->flags & IORESOURCE_MEM && iomem_is_exclusive(start))
 612                return -EINVAL;
 613
 614        return pci_mmap_page_range(pdev, vma, mmap_type, write_combine);
 615}
 616
 617static int
 618pci_mmap_resource_uc(struct kobject *kobj, struct bin_attribute *attr,
 619                     struct vm_area_struct *vma)
 620{
 621        return pci_mmap_resource(kobj, attr, vma, 0);
 622}
 623
 624static int
 625pci_mmap_resource_wc(struct kobject *kobj, struct bin_attribute *attr,
 626                     struct vm_area_struct *vma)
 627{
 628        return pci_mmap_resource(kobj, attr, vma, 1);
 629}
 630
 631/**
 632 * pci_remove_resource_files - cleanup resource files
 633 * @dev: dev to cleanup
 634 *
 635 * If we created resource files for @dev, remove them from sysfs and
 636 * free their resources.
 637 */
 638static void
 639pci_remove_resource_files(struct pci_dev *pdev)
 640{
 641        int i;
 642
 643        for (i = 0; i < PCI_ROM_RESOURCE; i++) {
 644                struct bin_attribute *res_attr;
 645
 646                res_attr = pdev->res_attr[i];
 647                if (res_attr) {
 648                        sysfs_remove_bin_file(&pdev->dev.kobj, res_attr);
 649                        kfree(res_attr);
 650                }
 651
 652                res_attr = pdev->res_attr_wc[i];
 653                if (res_attr) {
 654                        sysfs_remove_bin_file(&pdev->dev.kobj, res_attr);
 655                        kfree(res_attr);
 656                }
 657        }
 658}
 659
 660static int pci_create_attr(struct pci_dev *pdev, int num, int write_combine)
 661{
 662        /* allocate attribute structure, piggyback attribute name */
 663        int name_len = write_combine ? 13 : 10;
 664        struct bin_attribute *res_attr;
 665        int retval;
 666
 667        res_attr = kzalloc(sizeof(*res_attr) + name_len, GFP_ATOMIC);
 668        if (res_attr) {
 669                char *res_attr_name = (char *)(res_attr + 1);
 670
 671                if (write_combine) {
 672                        pdev->res_attr_wc[num] = res_attr;
 673                        sprintf(res_attr_name, "resource%d_wc", num);
 674                        res_attr->mmap = pci_mmap_resource_wc;
 675                } else {
 676                        pdev->res_attr[num] = res_attr;
 677                        sprintf(res_attr_name, "resource%d", num);
 678                        res_attr->mmap = pci_mmap_resource_uc;
 679                }
 680                res_attr->attr.name = res_attr_name;
 681                res_attr->attr.mode = S_IRUSR | S_IWUSR;
 682                res_attr->size = pci_resource_len(pdev, num);
 683                res_attr->private = &pdev->resource[num];
 684                retval = sysfs_create_bin_file(&pdev->dev.kobj, res_attr);
 685        } else
 686                retval = -ENOMEM;
 687
 688        return retval;
 689}
 690
 691/**
 692 * pci_create_resource_files - create resource files in sysfs for @dev
 693 * @dev: dev in question
 694 *
 695 * Walk the resources in @dev creating files for each resource available.
 696 */
 697static int pci_create_resource_files(struct pci_dev *pdev)
 698{
 699        int i;
 700        int retval;
 701
 702        /* Expose the PCI resources from this device as files */
 703        for (i = 0; i < PCI_ROM_RESOURCE; i++) {
 704
 705                /* skip empty resources */
 706                if (!pci_resource_len(pdev, i))
 707                        continue;
 708
 709                retval = pci_create_attr(pdev, i, 0);
 710                /* for prefetchable resources, create a WC mappable file */
 711                if (!retval && pdev->resource[i].flags & IORESOURCE_PREFETCH)
 712                        retval = pci_create_attr(pdev, i, 1);
 713
 714                if (retval) {
 715                        pci_remove_resource_files(pdev);
 716                        return retval;
 717                }
 718        }
 719        return 0;
 720}
 721#else /* !HAVE_PCI_MMAP */
 722static inline int pci_create_resource_files(struct pci_dev *dev) { return 0; }
 723static inline void pci_remove_resource_files(struct pci_dev *dev) { return; }
 724#endif /* HAVE_PCI_MMAP */
 725
 726/**
 727 * pci_write_rom - used to enable access to the PCI ROM display
 728 * @kobj: kernel object handle
 729 * @buf: user input
 730 * @off: file offset
 731 * @count: number of byte in input
 732 *
 733 * writing anything except 0 enables it
 734 */
 735static ssize_t
 736pci_write_rom(struct kobject *kobj, struct bin_attribute *bin_attr,
 737              char *buf, loff_t off, size_t count)
 738{
 739        struct pci_dev *pdev = to_pci_dev(container_of(kobj, struct device, kobj));
 740
 741        if ((off ==  0) && (*buf == '0') && (count == 2))
 742                pdev->rom_attr_enabled = 0;
 743        else
 744                pdev->rom_attr_enabled = 1;
 745
 746        return count;
 747}
 748
 749/**
 750 * pci_read_rom - read a PCI ROM
 751 * @kobj: kernel object handle
 752 * @buf: where to put the data we read from the ROM
 753 * @off: file offset
 754 * @count: number of bytes to read
 755 *
 756 * Put @count bytes starting at @off into @buf from the ROM in the PCI
 757 * device corresponding to @kobj.
 758 */
 759static ssize_t
 760pci_read_rom(struct kobject *kobj, struct bin_attribute *bin_attr,
 761             char *buf, loff_t off, size_t count)
 762{
 763        struct pci_dev *pdev = to_pci_dev(container_of(kobj, struct device, kobj));
 764        void __iomem *rom;
 765        size_t size;
 766
 767        if (!pdev->rom_attr_enabled)
 768                return -EINVAL;
 769        
 770        rom = pci_map_rom(pdev, &size); /* size starts out as PCI window size */
 771        if (!rom || !size)
 772                return -EIO;
 773                
 774        if (off >= size)
 775                count = 0;
 776        else {
 777                if (off + count > size)
 778                        count = size - off;
 779                
 780                memcpy_fromio(buf, rom + off, count);
 781        }
 782        pci_unmap_rom(pdev, rom);
 783                
 784        return count;
 785}
 786
 787static struct bin_attribute pci_config_attr = {
 788        .attr = {
 789                .name = "config",
 790                .mode = S_IRUGO | S_IWUSR,
 791        },
 792        .size = PCI_CFG_SPACE_SIZE,
 793        .read = pci_read_config,
 794        .write = pci_write_config,
 795};
 796
 797static struct bin_attribute pcie_config_attr = {
 798        .attr = {
 799                .name = "config",
 800                .mode = S_IRUGO | S_IWUSR,
 801        },
 802        .size = PCI_CFG_SPACE_EXP_SIZE,
 803        .read = pci_read_config,
 804        .write = pci_write_config,
 805};
 806
 807int __attribute__ ((weak)) pcibios_add_platform_entries(struct pci_dev *dev)
 808{
 809        return 0;
 810}
 811
 812static int pci_create_capabilities_sysfs(struct pci_dev *dev)
 813{
 814        int retval;
 815        struct bin_attribute *attr;
 816
 817        /* If the device has VPD, try to expose it in sysfs. */
 818        if (dev->vpd) {
 819                attr = kzalloc(sizeof(*attr), GFP_ATOMIC);
 820                if (!attr)
 821                        return -ENOMEM;
 822
 823                attr->size = dev->vpd->len;
 824                attr->attr.name = "vpd";
 825                attr->attr.mode = S_IRUSR | S_IWUSR;
 826                attr->read = read_vpd_attr;
 827                attr->write = write_vpd_attr;
 828                retval = sysfs_create_bin_file(&dev->dev.kobj, attr);
 829                if (retval) {
 830                        kfree(dev->vpd->attr);
 831                        return retval;
 832                }
 833                dev->vpd->attr = attr;
 834        }
 835
 836        /* Active State Power Management */
 837        pcie_aspm_create_sysfs_dev_files(dev);
 838
 839        return 0;
 840}
 841
 842int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
 843{
 844        int retval;
 845        int rom_size = 0;
 846        struct bin_attribute *attr;
 847
 848        if (!sysfs_initialized)
 849                return -EACCES;
 850
 851        if (pdev->cfg_size < PCI_CFG_SPACE_EXP_SIZE)
 852                retval = sysfs_create_bin_file(&pdev->dev.kobj, &pci_config_attr);
 853        else
 854                retval = sysfs_create_bin_file(&pdev->dev.kobj, &pcie_config_attr);
 855        if (retval)
 856                goto err;
 857
 858        retval = pci_create_resource_files(pdev);
 859        if (retval)
 860                goto err_config_file;
 861
 862        if (pci_resource_len(pdev, PCI_ROM_RESOURCE))
 863                rom_size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
 864        else if (pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW)
 865                rom_size = 0x20000;
 866
 867        /* If the device has a ROM, try to expose it in sysfs. */
 868        if (rom_size) {
 869                attr = kzalloc(sizeof(*attr), GFP_ATOMIC);
 870                if (!attr) {
 871                        retval = -ENOMEM;
 872                        goto err_resource_files;
 873                }
 874                attr->size = rom_size;
 875                attr->attr.name = "rom";
 876                attr->attr.mode = S_IRUSR;
 877                attr->read = pci_read_rom;
 878                attr->write = pci_write_rom;
 879                retval = sysfs_create_bin_file(&pdev->dev.kobj, attr);
 880                if (retval) {
 881                        kfree(attr);
 882                        goto err_resource_files;
 883                }
 884                pdev->rom_attr = attr;
 885        }
 886
 887        /* add platform-specific attributes */
 888        retval = pcibios_add_platform_entries(pdev);
 889        if (retval)
 890                goto err_rom_file;
 891
 892        /* add sysfs entries for various capabilities */
 893        retval = pci_create_capabilities_sysfs(pdev);
 894        if (retval)
 895                goto err_rom_file;
 896
 897        return 0;
 898
 899err_rom_file:
 900        if (rom_size) {
 901                sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr);
 902                kfree(pdev->rom_attr);
 903                pdev->rom_attr = NULL;
 904        }
 905err_resource_files:
 906        pci_remove_resource_files(pdev);
 907err_config_file:
 908        if (pdev->cfg_size < PCI_CFG_SPACE_EXP_SIZE)
 909                sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr);
 910        else
 911                sysfs_remove_bin_file(&pdev->dev.kobj, &pcie_config_attr);
 912err:
 913        return retval;
 914}
 915
 916static void pci_remove_capabilities_sysfs(struct pci_dev *dev)
 917{
 918        if (dev->vpd && dev->vpd->attr) {
 919                sysfs_remove_bin_file(&dev->dev.kobj, dev->vpd->attr);
 920                kfree(dev->vpd->attr);
 921        }
 922
 923        pcie_aspm_remove_sysfs_dev_files(dev);
 924}
 925
 926/**
 927 * pci_remove_sysfs_dev_files - cleanup PCI specific sysfs files
 928 * @pdev: device whose entries we should free
 929 *
 930 * Cleanup when @pdev is removed from sysfs.
 931 */
 932void pci_remove_sysfs_dev_files(struct pci_dev *pdev)
 933{
 934        int rom_size = 0;
 935
 936        if (!sysfs_initialized)
 937                return;
 938
 939        pci_remove_capabilities_sysfs(pdev);
 940
 941        if (pdev->cfg_size < PCI_CFG_SPACE_EXP_SIZE)
 942                sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr);
 943        else
 944                sysfs_remove_bin_file(&pdev->dev.kobj, &pcie_config_attr);
 945
 946        pci_remove_resource_files(pdev);
 947
 948        if (pci_resource_len(pdev, PCI_ROM_RESOURCE))
 949                rom_size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
 950        else if (pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW)
 951                rom_size = 0x20000;
 952
 953        if (rom_size && pdev->rom_attr) {
 954                sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr);
 955                kfree(pdev->rom_attr);
 956        }
 957}
 958
 959static int __init pci_sysfs_init(void)
 960{
 961        struct pci_dev *pdev = NULL;
 962        int retval;
 963
 964        sysfs_initialized = 1;
 965        for_each_pci_dev(pdev) {
 966                retval = pci_create_sysfs_dev_files(pdev);
 967                if (retval) {
 968                        pci_dev_put(pdev);
 969                        return retval;
 970                }
 971        }
 972
 973        return 0;
 974}
 975
 976late_initcall(pci_sysfs_init);
 977
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.