Quantcast
Channel: Active questions tagged kernel - Stack Overflow
Viewing all articles
Browse latest Browse all 6502

Can I use sysfs_notify() for several attributes on same kobj simultaneously?

$
0
0

Can I use sysfs_notify() from several attributes on the same kobj simultaneously?

I'm trying to make a linux device driver for notify interrupt comes from HW to userspace.Yes I know there are other several methods for this(uio, mmap and etc) but my legacy driver used sysfs so I trying to use sysfs_notify() from interrupt handler.

My driver has to handle some of interrupt sources more than two so I made one of sysfs class and some attributes to notify interrupt via attirutes with sysfs_notify().The interrupts will be occurred 30 times in a second and there are multiple interrupt sources.

I've found there are attributes after insmod foo.ko in sysfs like /sys/devices/platform/foo_device/intr0 and /sys/devices/platform/foo_device/intr1.

My problem comes from here. If I enabled only one interrupt and one of ISR call sysfs_notify() then it works well but if I enabled more than two interrups then kernel stucks on spin_lock or some conditions and doesn't give any reactions even if I type the keyboard, ping to the targer and so on.

My source code looks like this

static struct foo_attr foo_notify_0;static struct foo_attr foo_notify_1;static struct attribute *foo_attrs[] = {&foo_notify_0.attr.attr,&foo_notify_1.attr.attr,    NULL};ATTRIBUTE_GROUPS(foo);static ssize_t foo_sysfs_push_intr_0(struct device *dev, struct device_attribute *attr,         const char *buf, size_t len){    // USER_DEFINE function    struct foo_attr *foo = container_of(attr, struct foo_attr, attr);    sscanf(buf, "%d", &foo->value);    sysfs_notify(&dev->kobj, NULL, "foo_notify_0");    return len;}static ssize_t foo_sysfs_push_intr_1(struct device *dev, struct device_attribute *attr,         const char *buf, size_t len){    // USER_DEFINE function    struct foo_attr *foo = container_of(attr, struct foo_attr, attr);    static int count = 0;    if(count++%30==0) printk("1 %p\n", &dev->kobj);    sscanf(buf, "%d", &foo->value);    sysfs_notify(&dev->kobj, NULL, "foo_notify_1");    return len;}static struct foo_attr foo_notify_0 = {    .attr = __ATTR(intr0, 0644, foo_sysfs_show, foo_sysfs_push_intr_0),    .value = 0,};static struct foo_attr foo_notify_1 = {    .attr = __ATTR(intr1, 0644, foo_sysfs_show, foo_sysfs_push_intr_1),    .value = 0,};static struct platform_device foo_device = {    .name = "nextchip,foo",    .id   = PLATFORM_DEVID_NONE,    .dev.groups = foo_groups,};static irqreturn_t foo_isr_intp_0(int irq, void *priv){    struct device *dev = &foo_device.dev;    struct device_attribute *attr = &foo_notify_0.attr;    struct foo_attr *foo = container_of(attr, struct foo_attr, attr);    int ch = 0;    //DEBUG_TRACE;    // interrupt pending clear    writel(1<<ch, foo_res->base + 0x140);    foo_sysfs_push_intr_0(dev, attr, "1", 1);    return IRQ_HANDLED;}static irqreturn_t foo_isr_intp_1(int irq, void *priv){    struct device *dev = &foo_device.dev;    struct device_attribute *attr = &foo_notify_1.attr;    struct foo_attr *foo = container_of(attr, struct foo_attr, attr);    int ch = 1;    //DEBUG_TRACE;    // interrupt pending clear    writel(1<<ch, foo_res->base + 0x140);    foo_sysfs_push_intr_1(dev, attr, "1", 1);    return IRQ_HANDLED;}static int foo_probe(struct platform_device *pdev){    ...    foo_res->irq[0] = platform_get_irq_byname(pdev, "foo_vsip");    foo_res->irq[1] = platform_get_irq_byname(pdev, "foo_vsin");    ret = devm_request_irq(&pdev->dev, foo_res->irq[0], foo_isr_intp_0, IRQF_TRIGGER_RISING, "foo_vsip", NULL);    ret = devm_request_irq(&pdev->dev, foo_res->irq[1], foo_isr_intp_1, IRQF_TRIGGER_RISING, "foo_vsin", NULL);    ...}

Viewing all articles
Browse latest Browse all 6502

Trending Articles