Date:2011-07-06 23:26:18 (9 years 2 months ago)
Author:Werner Almesberger
Commit:edb55e1d9917f35ce2ec30afa47ede66fb06273b
Message:atusb: converted interrupt delivery to use tasklets

Tasklets are a lot cleaner than the atomic operations and weird logic
we had before. And the result should also be more correct ;-)

Signed-off-by: Werner Almesberger <werner@almesberger.net>
Files: drivers/spi/atusb.c (7 diffs)

Change Details

drivers/spi/atusb.c
1919#include <linux/module.h>
2020#include <linux/platform_device.h>
2121#include <linux/interrupt.h>
22#include <linux/atomic.h>
2322#include <linux/usb.h>
2423#include <linux/spi/spi.h>
2524#include <linux/spi/at86rf230.h>
...... 
4746    int slave_irq;
4847    struct urb *irq_urb;
4948    uint8_t irq_buf; /* scratch space */
50    atomic_t pending; /* pending interrupts */
51    atomic_t masked; /* masking levels */
49    struct tasklet_struct task; /* interrupt delivery tasklet */
5250    struct at86rf230_platform_data platform_data;
5351    /* copy platform_data so that we can adapt .reset_data */
5452    struct spi_device *spi;
...... 
357355/* ----- Interrupt handling ------------------------------------------------ */
358356
359357
360static void atusb_do_irq(struct atusb_local *atusb);
361
362static void atusb_irq_enable(struct atusb_local *atusb)
358static void atusb_tasklet(unsigned long data)
363359{
364    printk(KERN_INFO "atusb_irq_enable\n");
365    if (atomic_dec_return(&atusb->masked))
366        return;
367    if (!atomic_add_unless(&atusb->pending, -1, 0))
368        return;
369    /* @@@ probably racy around here.
370       need to think this through some more - wa */
371    atusb_do_irq(atusb);
372}
360    struct atusb_local *atusb = (void *) data;
373361
374static void atusb_do_irq(struct atusb_local *atusb)
375{
376    printk(KERN_INFO "atusb_do_irq\n");
377    if (atomic_inc_return(&atusb->masked) == 1)
378        generic_handle_irq(atusb->slave_irq);
379    else
380        atomic_set(&atusb->pending, 1);
381    printk(KERN_INFO "atusb_do_irq out\n");
382    atusb_irq_enable(atusb);
362    generic_handle_irq(atusb->slave_irq);
383363}
384364
385365static void atusb_irq(struct urb *urb)
...... 
389369    printk(KERN_INFO "atusb_irq (%d)\n", urb->status);
390370    usb_free_urb(urb);
391371    atusb->irq_urb = NULL;
392    atusb_do_irq(atusb);
372    tasklet_schedule(&atusb->task);
393373}
394374
395375static int atusb_arm_interrupt(struct atusb_local *atusb)
...... 
436416    struct atusb_local *atusb = irq_data_get_irq_chip_data(data);
437417
438418    printk(KERN_INFO "atusb_irq_mask\n");
439    atomic_inc(&atusb->masked);
419    tasklet_disable_nosync(&atusb->task);
440420}
441421
442422static void atusb_irq_unmask(struct irq_data *data)
...... 
444424    struct atusb_local *atusb = irq_data_get_irq_chip_data(data);
445425
446426    printk(KERN_INFO "atusb_irq_unmask\n");
447    atusb_irq_enable(atusb);
427    tasklet_enable(&atusb->task);
448428}
449429
450430static struct irq_chip atusb_irq_chip = {
...... 
607587    board_info.platform_data = &atusb->platform_data;
608588    board_info.irq = atusb->slave_irq;
609589
610    atomic_set(&atusb->masked, 0);
611    atomic_set(&atusb->pending, 0);
590    tasklet_init(&atusb->task, atusb_tasklet, (unsigned long) atusb);
612591    atusb_arm_interrupt(atusb);
613592
614593    atusb->spi = spi_new_device(master, &board_info);

Archive Download the corresponding diff file



interactive