lkml.org 
[lkml]   [2004]   [Dec]   [21]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    SubjectRe: [PATCH] add legacy resources to sysfs
    Date
    On Tuesday, December 21, 2004 1:46 pm, Greg KH wrote:
    > You are passing the wrong things around :)
    >
    > A struct pci_bus is a struct class_device, not a struct device. I think
    > you need to rethink your goal of putting the files into the pci device
    > directory, or just put the files into the proper /sys/class/pci_bus/*
    > directory as your code assumes is happening.

    Something like this then? I added bin file support to class.c and use that
    instead from probe.c. I also fixed the container_of stuff in pci-sysfs.c.

    Thanks,
    Jesse
    ===== arch/ia64/pci/pci.c 1.59 vs edited =====
    --- 1.59/arch/ia64/pci/pci.c 2004-11-05 11:55:25 -08:00
    +++ edited/arch/ia64/pci/pci.c 2004-12-21 13:45:17 -08:00
    @@ -6,6 +6,7 @@
    * Copyright (C) 2002 Hewlett-Packard Co
    * David Mosberger-Tang <davidm@hpl.hp.com>
    * Bjorn Helgaas <bjorn_helgaas@hp.com>
    + * Copyright (C) 2004 Silicon Graphics, Inc.
    *
    * Note: Above list of copyright holders is incomplete...
    */
    @@ -518,7 +519,7 @@
    * Leave vm_pgoff as-is, the PCI space address is the physical
    * address on this platform.
    */
    - vma->vm_flags |= (VM_SHM | VM_LOCKED | VM_IO);
    + vma->vm_flags |= (VM_SHM | VM_RESERVED | VM_IO);

    if (write_combine)
    vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
    @@ -530,6 +531,121 @@
    return -EAGAIN;

    return 0;
    +}
    +
    +/**
    + * pci_mmap_legacy_page_range - map legacy memory space to userland
    + * @bus: bus whose legacy space we're mapping
    + * @vma: vma passed in by mmap
    + *
    + * Map legacy memory space for this device back to userspace using a machine
    + * vector to get the base address.
    + */
    +int
    +pci_mmap_legacy_page_range(struct pci_bus *bus, struct vm_area_struct *vma)
    +{
    + char *addr;
    +
    + addr = pci_get_legacy_mem(bus);
    + if (IS_ERR(addr))
    + return PTR_ERR(addr);
    +
    + vma->vm_pgoff += (unsigned long)addr >> PAGE_SHIFT;
    +
    + /*
    + * Leave vm_pgoff as-is, the PCI space address is the physical
    + * address on this platform.
    + */
    + vma->vm_flags |= (VM_SHM | VM_RESERVED | VM_IO);
    +
    + if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
    + vma->vm_end - vma->vm_start, vma->vm_page_prot))
    + return -EAGAIN;
    +
    + return 0;
    +}
    +
    +/**
    + * ia64_pci_get_legacy_mem - generic legacy mem routine
    + * @bus: bus to get legacy memory base address for
    + *
    + * Find the base of legacy memory for @bus. This is typically the first
    + * megabyte of bus address space for @bus or is simply 0 on platforms whose
    + * chipsets support legacy I/O and memory routing. Returns the base address
    + * or an error pointer if an error occurred.
    + *
    + * This is the ia64 generic version of this routine. Other platforms
    + * are free to override it with a machine vector.
    + */
    +char *ia64_pci_get_legacy_mem(struct pci_bus *bus)
    +{
    + return (char *)__IA64_UNCACHED_OFFSET;
    +}
    +
    +/**
    + * ia64_pci_legacy_read - read from legacy I/O space
    + * @bus: bus to read
    + * @port: legacy port value
    + * @val: caller allocated storage for returned value
    + * @size: number of bytes to read
    + *
    + * Simply reads @size bytes from @port and puts the result in @val.
    + *
    + * Again, this (and the write routine) are generic versions that can be
    + * overridden by the platform. This is necessary on platforms that don't
    + * support legacy I/O routing or that hard fail on legacy I/O timeouts.
    + */
    +int ia64_pci_legacy_read(struct pci_bus *bus, u16 port, u32 *val, u8 size)
    +{
    + int ret = size;
    +
    + switch (size) {
    + case 1:
    + *val = inb(port);
    + break;
    + case 2:
    + *val = inw(port);
    + break;
    + case 4:
    + *val = inl(port);
    + break;
    + default:
    + ret = -EINVAL;
    + break;
    + }
    +
    + return ret;
    +}
    +
    +/**
    + * ia64_pci_legacy_write - perform a legacy I/O write
    + * @bus: bus pointer
    + * @port: port to write
    + * @val: value to write
    + * @size: number of bytes to write from @val
    + *
    + * Simply writes @size bytes of @val to @port.
    + */
    +int ia64_pci_legacy_write(struct pci_dev *bus, u16 port, u32 val, u8 size)
    +{
    + int ret = 0;
    +
    + switch (size) {
    + case 1:
    + outb(val, port);
    + break;
    + case 2:
    + outw(val, port);
    + break;
    + case 4:
    + outl(val, port);
    + break;
    + default:
    + ret = -EINVAL;
    + break;
    + }
    +
    + return ret;
    }

    /**
    ===== arch/ia64/sn/pci/pci_dma.c 1.2 vs edited =====
    --- 1.2/arch/ia64/sn/pci/pci_dma.c 2004-10-20 12:00:10 -07:00
    +++ edited/arch/ia64/sn/pci/pci_dma.c 2004-12-21 13:40:54 -08:00
    @@ -475,3 +475,75 @@
    EXPORT_SYMBOL(sn_pci_free_consistent);
    EXPORT_SYMBOL(sn_pci_dma_supported);
    EXPORT_SYMBOL(sn_dma_mapping_error);
    +
    +char *sn_pci_get_legacy_mem(struct pci_bus *bus)
    +{
    + if (!SN_PCIBUS_BUSSOFT(bus))
    + return ERR_PTR(-ENODEV);
    +
    + return (char *)(SN_PCIBUS_BUSSOFT(bus)->bs_legacy_mem | __IA64_UNCACHED_OFFSET);
    +}
    +
    +int sn_pci_legacy_read(struct pci_bus *bus, u16 port, u32 *val, u8 size)
    +{
    + int ret = size;
    + unsigned long addr;
    +
    + if (!SN_PCIBUS_BUSSOFT(bus)) {
    + ret = -ENODEV;
    + goto out;
    + }
    +
    + addr = SN_PCIBUS_BUSSOFT(bus)->bs_legacy_io | __IA64_UNCACHED_OFFSET;
    + addr += port;
    +
    + ret = ia64_sn_probe_mem(addr, (long)size, (void *)val);
    +
    + /* Read timed out, return -1 to emulate soft fail */
    + if (ret == 1)
    + *val = -1;
    +
    + /* Invalid argument */
    + if (ret == 2)
    + ret = -EINVAL;
    +
    + out:
    + return ret;
    +}
    +
    +int sn_pci_legacy_write(struct pci_bus *bus, u16 port, u32 val, u8 size)
    +{
    + int ret = 0;
    + unsigned long paddr;
    + unsigned long *addr;
    +
    + if (!SN_PCIBUS_BUSSOFT(bus)) {
    + ret = -ENODEV;
    + goto out;
    + }
    +
    + /* Put the phys addr in uncached space */
    + paddr = SN_PCIBUS_BUSSOFT(bus)->bs_legacy_io | __IA64_UNCACHED_OFFSET;
    + paddr += port;
    + addr = (unsigned long *)paddr;
    +
    + switch (size) {
    + case 1:
    + *(volatile u8 *)(addr) = (u8)(val);
    + ret = 1;
    + break;
    + case 2:
    + *(volatile u16 *)(addr) = (u16)(val);
    + ret = 2;
    + break;
    + case 4:
    + *(volatile u32 *)(addr) = (u32)(val);
    + ret = 4;
    + break;
    + default:
    + ret = -EINVAL;
    + break;
    + }
    + out:
    + return ret;
    +}
    ===== drivers/base/class.c 1.56 vs edited =====
    --- 1.56/drivers/base/class.c 2004-11-12 03:45:39 -08:00
    +++ edited/drivers/base/class.c 2004-12-21 13:59:00 -08:00
    @@ -179,6 +179,22 @@
    sysfs_remove_file(&class_dev->kobj, &attr->attr);
    }

    +int class_device_create_bin_file(struct class_device *class_dev,
    + struct bin_attribute *attr)
    +{
    + int error = -EINVAL;
    + if (class_dev)
    + error = sysfs_create_bin_file(&class_dev->kobj, attr);
    + return error;
    +}
    +
    +void class_device_remove_bin_file(struct class_device *class_dev,
    + struct bin_attribute *attr)
    +{
    + if (class_dev)
    + sysfs_remove_bin_file(&class_dev->kobj, attr);
    +}
    +
    static int class_device_dev_link(struct class_device * class_dev)
    {
    if (class_dev->dev)
    ===== drivers/pci/pci-sysfs.c 1.14 vs edited =====
    --- 1.14/drivers/pci/pci-sysfs.c 2004-12-21 11:28:57 -08:00
    +++ edited/drivers/pci/pci-sysfs.c 2004-12-21 14:03:35 -08:00
    @@ -179,6 +179,76 @@
    return count;
    }

    +#ifdef HAVE_PCI_LEGACY
    +/**
    + * pci_read_legacy_io - read byte(s) from legacy I/O port space
    + * @kobj: kobject corresponding to file to read from
    + * @buf: buffer to store results
    + * @off: offset into legacy I/O port space
    + * @count: number of bytes to read
    + *
    + * Reads 1, 2, or 4 bytes from legacy I/O port space using an arch specific
    + * callback routine (pci_legacy_read).
    + */
    +ssize_t
    +pci_read_legacy_io(struct kobject *kobj, char *buf, loff_t off, size_t count)
    +{
    + struct pci_bus *bus = to_pci_bus(container_of(kobj,
    + struct class_device,
    + kobj));
    +
    + /* Only support 1, 2 or 4 byte accesses */
    + if (count != 1 && count != 2 && count != 4)
    + return -EINVAL;
    +
    + return pci_legacy_read(bus, off, (u32 *)buf, count);
    +}
    +
    +/**
    + * pci_write_legacy_io - write byte(s) to legacy I/O port space
    + * @kobj: kobject corresponding to file to read from
    + * @buf: buffer containing value to be written
    + * @off: offset into legacy I/O port space
    + * @count: number of bytes to write
    + *
    + * Writes 1, 2, or 4 bytes from legacy I/O port space using an arch specific
    + * callback routine (pci_legacy_write).
    + */
    +ssize_t
    +pci_write_legacy_io(struct kobject *kobj, char *buf, loff_t off, size_t count)
    +{
    + struct pci_bus *bus = to_pci_bus(container_of(kobj,
    + struct class_device,
    + kobj));
    + /* Only support 1, 2 or 4 byte accesses */
    + if (count != 1 && count != 2 && count != 4)
    + return -EINVAL;
    +
    + return pci_legacy_write(bus, off, *(u32 *)buf, count);
    +}
    +
    +/**
    + * pci_mmap_legacy_mem - map legacy PCI memory into user memory space
    + * @kobj: kobject corresponding to device to be mapped
    + * @attr: struct bin_attribute for this file
    + * @vma: struct vm_area_struct passed to mmap
    + *
    + * Uses an arch specific callback, pci_mmap_legacy_page_range, to mmap
    + * legacy memory space (first meg of bus space) into application virtual
    + * memory space.
    + */
    +int
    +pci_mmap_legacy_mem(struct kobject *kobj, struct bin_attribute *attr,
    + struct vm_area_struct *vma)
    +{
    + struct pci_bus *bus = to_pci_bus(container_of(kobj,
    + struct class_device,
    + kobj));
    +
    + return pci_mmap_legacy_page_range(bus, vma);
    +}
    +#endif /* HAVE_PCI_LEGACY */
    +
    #ifdef HAVE_PCI_MMAP
    /**
    * pci_mmap_resource - map a PCI resource into user memory space
    ===== drivers/pci/probe.c 1.72 vs edited =====
    --- 1.72/drivers/pci/probe.c 2004-11-11 12:53:33 -08:00
    +++ edited/drivers/pci/probe.c 2004-12-21 13:58:10 -08:00
    @@ -764,6 +764,42 @@
    return max;
    }

    +#ifdef HAVE_PCI_LEGACY
    +/**
    + * pci_create_legacy_files - create legacy I/O port and memory files
    + * @b: bus to create files under
    + *
    + * Some platforms allow access to legacy I/O port and ISA memory space on
    + * a per-bus basis. This routine creates the files and ties them into
    + * their associated read, write and mmap files from pci-sysfs.c
    + */
    +static void pci_create_legacy_files(struct pci_bus *b)
    +{
    + b->legacy_io = kmalloc(sizeof(struct bin_attribute) * 2,
    + GFP_ATOMIC);
    + if (b->legacy_io) {
    + b->legacy_io->attr.name = "legacy_io";
    + b->legacy_io->size = 0xffff;
    + b->legacy_io->attr.mode = S_IRUSR | S_IWUSR;
    + b->legacy_io->attr.owner = THIS_MODULE;
    + b->legacy_io->read = pci_read_legacy_io;
    + b->legacy_io->write = pci_write_legacy_io;
    + class_device_create_bin_file(&b->class_dev, b->legacy_io);
    +
    + /* Allocated above after the legacy_io struct */
    + b->legacy_mem = b->legacy_io + 1;
    + b->legacy_mem->attr.name = "legacy_mem";
    + b->legacy_mem->size = 1024*1024;
    + b->legacy_mem->attr.mode = S_IRUSR | S_IWUSR;
    + b->legacy_mem->attr.owner = THIS_MODULE;
    + b->legacy_mem->mmap = pci_mmap_legacy_mem;
    + class_device_create_bin_file(&b->class_dev, b->legacy_mem);
    + }
    +}
    +#else /* !HAVE_PCI_LEGACY */
    +static inline void pci_create_legacy_files(struct pci_bus *bus) { return; }
    +#endif /* HAVE_PCI_LEGACY */
    +
    struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent, int bus, struct pci_ops *ops, void *sysdata)
    {
    int error;
    @@ -807,6 +843,9 @@
    error = class_device_create_file(&b->class_dev, &class_device_attr_cpuaffinity);
    if (error)
    goto class_dev_create_file_err;
    +
    + /* Create legacy_io and legacy_mem files for this bus */
    + pci_create_legacy_files(b);

    error = sysfs_create_link(&b->class_dev.kobj, &b->bridge->kobj, "bridge");
    if (error)
    ===== include/asm-ia64/machvec.h 1.29 vs edited =====
    --- 1.29/include/asm-ia64/machvec.h 2004-10-25 13:06:49 -07:00
    +++ edited/include/asm-ia64/machvec.h 2004-12-21 13:40:18 -08:00
    @@ -20,6 +20,7 @@
    struct irq_desc;
    struct page;
    struct mm_struct;
    +struct pci_bus;

    typedef void ia64_mv_setup_t (char **);
    typedef void ia64_mv_cpu_init_t (void);
    @@ -31,6 +32,11 @@
    typedef struct irq_desc *ia64_mv_irq_desc (unsigned int);
    typedef u8 ia64_mv_irq_to_vector (unsigned int);
    typedef unsigned int ia64_mv_local_vector_to_irq (u8);
    +typedef char *ia64_mv_pci_get_legacy_mem_t (struct pci_bus *);
    +typedef int ia64_mv_pci_legacy_read_t (struct pci_bus *, u16 port, u32 *val,
    + u8 size);
    +typedef int ia64_mv_pci_legacy_write_t (struct pci_bus *, u16 port, u32 val,
    + u8 size);

    /* DMA-mapping interface: */
    typedef void ia64_mv_dma_init (void);
    @@ -125,6 +131,9 @@
    # define platform_irq_desc ia64_mv.irq_desc
    # define platform_irq_to_vector ia64_mv.irq_to_vector
    # define platform_local_vector_to_irq ia64_mv.local_vector_to_irq
    +# define platform_pci_get_legacy_mem ia64_mv.pci_get_legacy_mem
    +# define platform_pci_legacy_read ia64_mv.pci_legacy_read
    +# define platform_pci_legacy_write ia64_mv.pci_legacy_write
    # define platform_inb ia64_mv.inb
    # define platform_inw ia64_mv.inw
    # define platform_inl ia64_mv.inl
    @@ -172,6 +181,9 @@
    ia64_mv_irq_desc *irq_desc;
    ia64_mv_irq_to_vector *irq_to_vector;
    ia64_mv_local_vector_to_irq *local_vector_to_irq;
    + ia64_mv_pci_get_legacy_mem_t *pci_get_legacy_mem;
    + ia64_mv_pci_legacy_read_t *pci_legacy_read;
    + ia64_mv_pci_legacy_write_t *pci_legacy_write;
    ia64_mv_inb_t *inb;
    ia64_mv_inw_t *inw;
    ia64_mv_inl_t *inl;
    @@ -215,6 +227,9 @@
    platform_irq_desc, \
    platform_irq_to_vector, \
    platform_local_vector_to_irq, \
    + platform_pci_get_legacy_mem, \
    + platform_pci_legacy_read, \
    + platform_pci_legacy_write, \
    platform_inb, \
    platform_inw, \
    platform_inl, \
    @@ -329,6 +344,15 @@
    #endif
    #ifndef platform_local_vector_to_irq
    # define platform_local_vector_to_irq __ia64_local_vector_to_irq
    +#endif
    +#ifndef platform_pci_get_legacy_mem
    +# define platform_pci_get_legacy_mem ia64_pci_get_legacy_mem
    +#endif
    +#ifndef platform_pci_legacy_read
    +# define platform_pci_legacy_read ia64_pci_legacy_read
    +#endif
    +#ifndef platform_pci_legacy_write
    +# define platform_pci_legacy_write ia64_pci_legacy_write
    #endif
    #ifndef platform_inb
    # define platform_inb __ia64_inb
    ===== include/asm-ia64/machvec_init.h 1.8 vs edited =====
    --- 1.8/include/asm-ia64/machvec_init.h 2004-10-25 13:06:49 -07:00
    +++ edited/include/asm-ia64/machvec_init.h 2004-12-21 12:32:37 -08:00
    @@ -5,6 +5,9 @@
    extern ia64_mv_irq_desc __ia64_irq_desc;
    extern ia64_mv_irq_to_vector __ia64_irq_to_vector;
    extern ia64_mv_local_vector_to_irq __ia64_local_vector_to_irq;
    +extern ia64_mv_pci_get_legacy_mem_t ia64_pci_get_legacy_mem;
    +extern ia64_mv_pci_legacy_read_t ia64_pci_legacy_read;
    +extern ia64_mv_pci_legacy_write_t ia64_pci_legacy_write;

    extern ia64_mv_inb_t __ia64_inb;
    extern ia64_mv_inw_t __ia64_inw;
    ===== include/asm-ia64/machvec_sn2.h 1.16 vs edited =====
    --- 1.16/include/asm-ia64/machvec_sn2.h 2004-10-25 13:06:49 -07:00
    +++ edited/include/asm-ia64/machvec_sn2.h 2004-12-21 12:32:37 -08:00
    @@ -43,6 +43,9 @@
    extern ia64_mv_irq_desc sn_irq_desc;
    extern ia64_mv_irq_to_vector sn_irq_to_vector;
    extern ia64_mv_local_vector_to_irq sn_local_vector_to_irq;
    +extern ia64_mv_pci_get_legacy_mem_t sn_pci_get_legacy_mem;
    +extern ia64_mv_pci_legacy_read_t sn_pci_legacy_read;
    +extern ia64_mv_pci_legacy_write_t sn_pci_legacy_write;
    extern ia64_mv_inb_t __sn_inb;
    extern ia64_mv_inw_t __sn_inw;
    extern ia64_mv_inl_t __sn_inl;
    @@ -105,6 +108,9 @@
    #define platform_irq_desc sn_irq_desc
    #define platform_irq_to_vector sn_irq_to_vector
    #define platform_local_vector_to_irq sn_local_vector_to_irq
    +#define platform_pci_get_legacy_mem sn_pci_get_legacy_mem
    +#define platform_pci_legacy_read sn_pci_legacy_read
    +#define platform_pci_legacy_write sn_pci_legacy_write
    #define platform_dma_init machvec_noop
    #define platform_dma_alloc_coherent sn_dma_alloc_coherent
    #define platform_dma_free_coherent sn_dma_free_coherent
    ===== include/asm-ia64/pci.h 1.27 vs edited =====
    --- 1.27/include/asm-ia64/pci.h 2004-11-03 13:36:55 -08:00
    +++ edited/include/asm-ia64/pci.h 2004-12-21 12:32:38 -08:00
    @@ -85,6 +85,20 @@
    #define HAVE_PCI_MMAP
    extern int pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma,
    enum pci_mmap_state mmap_state, int write_combine);
    +#define HAVE_PCI_LEGACY
    +extern int pci_mmap_legacy_page_range(struct pci_bus *bus,
    + struct vm_area_struct *vma);
    +extern ssize_t pci_read_legacy_io(struct kobject *kobj, char *buf, loff_t off,
    + size_t count);
    +extern ssize_t pci_write_legacy_io(struct kobject *kobj, char *buf, loff_t off,
    + size_t count);
    +extern int pci_mmap_legacy_mem(struct kobject *kobj,
    + struct bin_attribute *attr,
    + struct vm_area_struct *vma);
    +
    +#define pci_get_legacy_mem platform_pci_get_legacy_mem
    +#define pci_legacy_read platform_pci_legacy_read
    +#define pci_legacy_write platform_pci_legacy_write

    struct pci_window {
    struct resource resource;
    ===== include/asm-ia64/sn/sn_sal.h 1.17 vs edited =====
    --- 1.17/include/asm-ia64/sn/sn_sal.h 2004-11-03 13:41:17 -08:00
    +++ edited/include/asm-ia64/sn/sn_sal.h 2004-12-21 12:32:38 -08:00
    @@ -474,6 +474,52 @@
    return isrv.v0;
    }

    +/**
    + * ia64_sn_probe_mem - read from memory safely
    + * @addr: address to probe
    + * @size: number bytes to read (1,2,4,8)
    + * @data_ptr: address to store value read by probe (-1 returned if probe fails)
    + *
    + * Call into the SAL to do a memory read. If the read generates a machine
    + * check, this routine will recover gracefully and return -1 to the caller.
    + * @addr is usually a kernel virtual address in uncached space (i.e. the
    + * address starts with 0xc), but if called in physical mode, @addr should
    + * be a physical address.
    + *
    + * Return values:
    + * 0 - probe successful
    + * 1 - probe failed (generated MCA)
    + * 2 - Bad arg
    + * <0 - PAL error
    + */
    +static inline u64
    +ia64_sn_probe_mem(long addr, long size, void *data_ptr)
    +{
    + struct ia64_sal_retval isrv;
    +
    + SAL_CALL(isrv, SN_SAL_PROBE, addr, size, 0, 0, 0, 0, 0);
    +
    + if (data_ptr) {
    + switch (size) {
    + case 1:
    + *((u8*)data_ptr) = (u8)isrv.v0;
    + break;
    + case 2:
    + *((u16*)data_ptr) = (u16)isrv.v0;
    + break;
    + case 4:
    + *((u32*)data_ptr) = (u32)isrv.v0;
    + break;
    + case 8:
    + *((u64*)data_ptr) = (u64)isrv.v0;
    + break;
    + default:
    + isrv.status = 2;
    + }
    + }
    + return isrv.status;
    +}
    +
    /*
    * Retrieve the system serial number as an ASCII string.
    */
    ===== include/linux/pci.h 1.143 vs edited =====
    --- 1.143/include/linux/pci.h 2004-12-21 11:21:50 -08:00
    +++ edited/include/linux/pci.h 2004-12-21 12:32:38 -08:00
    @@ -594,6 +594,8 @@
    unsigned short pad2;
    struct device *bridge;
    struct class_device class_dev;
    + struct bin_attribute *legacy_io; /* legacy I/O for this bus */
    + struct bin_attribute *legacy_mem; /* legacy mem */
    };

    #define pci_bus_b(n) list_entry(n, struct pci_bus, node)
    \
     
     \ /
      Last update: 2005-03-22 14:08    [W:0.062 / U:91.652 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site