The delay of the .poll function in the driver code has not taken effect?

44 Views Asked by At

I added a GPIO driver to the kernel code of Linux v3.10, and added a .poll function to the driver code. I don't know why I added 8ms to the poll() function of test code, but I noticed that the delay (poll_wait(file, &WaitQueue, wait);) did not take effect when dmesg was printed. I don't know why? Also, may I ask if it is appropriate to add a mutex in the interrupt callback function?

#driver code:

#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/of_gpio.h>
#include <linux/gpio.h>
#include <linux/sys_config.h>
#include <linux/major.h>
#include <linux/seq_file.h>
#include <linux/device.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/poll.h>
#include <linux/wait.h>
#include <linux/mutex.h>

static int MajorDevNum = 0;
static struct class *SpiioClass;
static int SpiioGpio;
static int IrqOccurred = 0;
static wait_queue_head_t WaitQueue;
struct mutex RWLock;

static ssize_t spiio_drv_read(struct file *file, char __user *buf, size_t size, loff_t *offset)
{
        int value = 0;
        char userValue = value ? 1:0;
        // wake_event_interruptible(wq, IrqOccrred);
        userValue = gpio_get_value(SpiioGpio) ? 1 : 0;
        printk("read value is %d\n", userValue);
        if (copy_to_user(buf, &userValue, sizeof(char) != 0)) {
                printk("failed to copy to user\n");
                return  -1;
        } else {
                return sizeof(char);
        }
}

static ssize_t spiio_drv_write(struct file *file, const char __user *buf, size_t size, loff_t *offset)
{
   return -1;
}

static int spiio_drv_open(struct inode *node, struct file *file)
{
    printk("this is open\n");
    return 0;
}

static int spiio_drv_close(struct inode *node, struct file *file)
{
    return 0;
}

static long spiio_drv_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
        return 0;
}

static unsigned int spiio_drv_poll(struct file *file, struct poll_table_struct *wait)
{
    printk("this is poll.\n");
    poll_wait(file, &WaitQueue, wait);
    if (IrqOccurred) {
        mutex_lock(&RWLock);
        IrqOccurred = 0;  // need lock
        mutex_unlock(&RWLock);
        printk(" an irq occurred. return %d\n", POLLIN);
        return POLLIN;
    }
    printk("no irq occurred, IrqOccurred = %d\n", IrqOccurred);
    return 0;
}

static irqreturn_t spiio_irq_handler(int irq, void *dev_id)
{
        // pr_info("spiio irq ocurred on IRQ %d\n", irq);
        wake_up_interruptible(&WaitQueue);
        mutex_lock(&RWLock);
        IrqOccurred = 1;
        mutex_unlock(&RWLock);
        return IRQ_HANDLED;
}

static struct file_operations spiio_drv = {
    .owner = THIS_MODULE,
    .open = spiio_drv_open,
    .read = spiio_drv_read,
    .write = spiio_drv_write,
    .release = spiio_drv_close,
    .unlocked_ioctl = spiio_drv_ioctl,
    .poll = spiio_drv_poll,
};

int spiio_probe(struct platform_device *pdev)
{
    struct device_node *nd = pdev->dev.of_node;
    struct gpio_config config;
    printk("gpio count:%d\n", of_gpio_named_count(nd, "spiio_gpio"));
    SpiioGpio = of_get_named_gpio_flags(nd, "spiio_gpio", 0, (enum of_gpio_flags *)&config);
    if (!gpio_is_valid(SpiioGpio))
        printk("gpio isn't valid\n");
    if (gpio_request(SpiioGpio, pdev->name) < 0)
        printk("gpio request faispiio %d\n", SpiioGpio);
    if (gpio_direction_input(SpiioGpio) < 0)
        printk("gpio_direction_input failed %d\n", SpiioGpio);
    init_waitqueue_head(&WaitQueue);

    // if (request_irq(gpio_to_irq(SpiioGpio), spiio_irq_handler, IRQF_TRIGGER_HIGH, "spiio_irq", NULL) < 0)
    if (request_irq(gpio_to_irq(SpiioGpio), spiio_irq_handler, IRQF_TRIGGER_RISING, "spiio_irq", NULL) < 0)
        printk("requst_irq failed\n");

    MajorDevNum = register_chrdev(0, "spiio", &spiio_drv); /* /dev/spiio */
    if (MajorDevNum < 0)
        printk("failed to get major device number\n");

    SpiioClass = class_create(THIS_MODULE, "spiio_class");
    if (IS_ERR(SpiioClass)) {
        printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
        unregister_chrdev(MajorDevNum, "spiio");
        gpio_free(SpiioGpio);
        return PTR_ERR(SpiioClass);
    }
    device_create(SpiioClass, NULL, MKDEV(MajorDevNum, 0), NULL, "spiio%d", 0); /* /dev/100ask_spiio0 */
    mutex_init(&RWLock);
    printk("gpio is ok, registered GPIO: %d\n", SpiioGpio);
    return 0;
}

int spiio_remove(struct platform_device *pdev)
{
    free_irq(gpio_to_irq(SpiioGpio), NULL);
    device_destroy(SpiioClass, MKDEV(MajorDevNum, 0));
    class_destroy(SpiioClass);
    unregister_chrdev(MajorDevNum, "spiio");
    gpio_free(SpiioGpio);
    mutex_destroy(&RWLock);
    printk("gpio remove ...\n");
    return 0;
}

struct of_device_id ids[] = {
    { .compatible = "dobot, spiio" },
    {},
};

static struct platform_driver chip_demo_gpio_driver = {
    .probe = spiio_probe,
    .remove = spiio_remove,
    .driver = {
        .name = "spiio",
        .of_match_table = ids,
    },
};

static int __init spiio_init(void)
{
    int err;
    err = platform_driver_register(&chip_demo_gpio_driver);
    return err;
}

test code:

#include "spidev.h"
#include <poll.h>
#include <time.h>    

int SpiDevFd = 0;

struct _SPI_Settings spi_settings;

int ReadData(int fd)
{
    int ret = 0;
    int ret2 = 0;
    char buffer[2] = {0};
    short revents;
    struct pollfd pfd;
    int timeout_ms = 8;

        pfd.fd = fd;
        pfd.events = POLLIN;
    
        uint8_t tx[256] = {0};
    for (int i = 0; i <= 255; i++)
    {
        tx[i] = i;
    }
    uint8_t rx[ARRAY_SIZE(tx)] = {
         0,
    };

    while (1) {
        memset(buffer, 0, sizeof(buffer));
        ret = poll(&pfd, 1, timeout_ms);
        revents = pfd.revents;
        if (ret) {
            TransferSpi(SpiDevFd, &spi_settings, tx, sizeof(tx), rx);
            hex_dump(rx, ARRAY_SIZE(rx), 32, "RX");
        } else {
            printf("ret = %d\n", ret);
            exit(-1);
        }
    }
    return 0;
}

int main() {
    // int fd = open("/sys/class/gpio_sw/gpio_pin_1/data", O_RDONLY);
   //  int fd = open("/sys/class/gpio_sw/PH1/data", O_RDONLY);
    int fd = open("/dev/spiio0", O_RDONLY);
    if (fd < 0) {
        perror("Failed to open GPIO value file\n");
        return 1;
    }
    
    spi_settings.mode = 0;
    spi_settings.bits = 8;
    spi_settings.speed = 20*1000*1000;
    spi_settings.delay = 0;
    SpiDevFd = OpenSpiDev("/dev/spidev2.0", &spi_settings);
    if (SpiDevFd < 0) {
                perror("Failed to spi dev file\n");
                return 1;
        }

    int ret = ReadData(fd);    

    close(fd);
    return 0;
}

The part of dmesg:

[ 3458.628570] gpio count:1
[ 3458.629278] gpio is ok, registered GPIO: 225
[ 3461.818972] this is open
[ 3461.819640] this is poll.
[ 3461.819679]  an irq occurred. return 1
[ 3461.820758] this is poll.
[ 3461.820777] no irq occurred, IrqOccurred = 0
[ 3461.822363] this is poll.
[ 3461.822373]  an irq occurred. return 1
[ 3461.823260] this is poll.
[ 3461.823273] no irq occurred, IrqOccurred = 0
[ 3461.831337] this is poll.
[ 3461.831356] no irq occurred, IrqOccurred = 0
0

There are 0 best solutions below