Search code examples
linuxdriverdevicepci

Access/Set filp->private_data member in probe() function


General:
I am developing a PCIE(PCI Express) linux device driver with the open()/close()/read()/write() methods being implemented and the probe() function for the PCIE part.

Current situation:
Within the probe() function I have access to the dev pointer driver_pcie_probe(struct pci_dev *dev, const struct pci_device_id *id) and through it I can do stuff like:

int my_pcie_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
    int err = 0;
    int *bar0 = NULL;
    int x = 0;
    int i = 0;

    // Before any device resources can be accessed, the device needs to be enabled.
    err = pci_enable_device(dev);
    if(err < 0) {
        printk(KERN_ALERT "Unable to enable PCIe device!\n");
        return err;
    }

    // Request all BARs to this device.
    err = pci_request_regions(dev, MY_DRIVER_NAME);
    if(err) {
        printk(KERN_ALERT "Unable to request memory regions (BARs) from PCIe device!\n");
        return err;
    }

    // !!! TESTING !!!
    bar0 = pci_iomap(dev, 0, 0);
    for(i = 0; i < 16; i++) {
        x = ioread32(bar0 + i);
        printk(KERN_ALERT "cycle: %d bar0: 0x%p, x = 0x%016x\n", i, bar0, x);
    }

    for(i = 0; i < 16; i++) {
        iowrite32(i, bar0 + i);
    }
    // !!! TESTING !!!

    return err;
}

within the probe() function which works perfect.

What I want to do:
...is transfer the iowrite/ioreads into the character devices read/write methods.

ssize_t char_device_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
    ssize_t ret = 0;
    struct my_device *my_dev;
    int device_buf[16];
    int i = 0;

    my_dev = filp->private_data;

    if (down_interruptible(&my_dev->sem)) {
        return -ERESTARTSYS;
    }

    for(i = 0; i < 16; i++) {
        device_buf[i] = ioread32(my_dev->BAR0 + i);
    }

    if (copy_to_user(buf, device_buf, count)) {
        return -EFAULT;
    }
    *f_pos += count;
    ret = count;

    up(&my_dev->sem);

    return ret;
}

Problem:
I need access to the pci_dev struct *dev within the character devices read/write method in order to do an ioread/iowrite.

What I know:
There is filp->private_data within the read/write methods of the character device, so I thought about having my_own_device_struct which I set the filp->private_data to. This way it's available within open/close/read/write of the character device.

What I thoughts works, but I can't figure out how:
I thought I can set the filp->private_data->... within the probe() function of the PCIE driver. This way the *dev (or at least the a bar0 which is a member of my_own_device_struct is available for the open/close/read/write methods of the character device, but unfortunately this doesn't work and dev_set_drvdata() doesn't seem to do the job either.

Anyone can help me on this?


Solution

  • The only way I found so far is using a struct my_own_device with a struct pci_dev as member being initialized during the probe() function. It's just a static variable within my device driver module accessible from every function.

    Since I have only one PCIe device that I am communicating with this might just be sufficient.