Date:2011-07-07 21:56:07 (12 years 8 months ago)
Author:Werner Almesberger
Commit:b2d71a931b84b937520b79a4d422cb3de5e1ec87
Message:atusb: changed interrupt synchronization from fixed delay to SPI_WRITE2_SYNC

The fixed 10 ms delay was an unnecessary waste of time. The new
mechanism synchronized interrupts by matching the interrupt's
serial number (sent on EP 1) with the serial returned by the new
request ATUSB_SPI_WRITE2_SYNC.

If we don't have a match, a 50 ms timeout will kick in. This will
save us in situations where EP 1 has a problem or also in case a
new interrupt arrives before the ATUSB_SPI_WRITE2_SYNC response.

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

Change Details

drivers/spi/atusb.c
3333
3434#include "../ieee802154/at86rf230.h" /* dirty */
3535
36
37#define SYNC_TIMEOUT_MS 50 /* assume interrupt has been synced after
38                   waiting this long */
39
3640#define VENDOR_ID 0x20b7
3741#define PRODUCT_ID 0x1540
3842
...... 
5357    struct spi_master *master;
5458    int slave_irq;
5559    struct urb *irq_urb;
56    uint8_t irq_buf; /* scratch space */
60    uint8_t irq_buf; /* receive irq serial here*/
61    uint8_t irq_seen; /* last irq serial from bulk */
62    uint8_t irq_sync; /* last irq serial from WRITE2_SYNC */
5763    struct tasklet_struct task; /* interrupt delivery tasklet */
5864    struct timer_list timer; /* delay, for interrupt synch */
5965    struct at86rf230_platform_data platform_data;
...... 
8591    ATUSB_SPI_WRITE = 0x30, /* SPI group */
8692    ATUSB_SPI_READ1,
8793    ATUSB_SPI_READ2,
94    ATUSB_SPI_WRITE2_SYNC,
8895};
8996
9097/*
...... 
112119 * host-> ATUSB_SPI_WRITE byte0 byte1 #bytes
113120 * ->host ATUSB_SPI_READ1 byte0 - #bytes
114121 * ->host ATUSB_SPI_READ2 byte0 byte1 #bytes
122 * ->host ATUSB_SPI_WRITE2_SYNC byte0 byte1 0/1
115123 */
116124
117125#define ATUSB_FROM_DEV (USB_TYPE_VENDOR | USB_DIR_IN)
...... 
165173{
166174    struct urb *urb = (void *) data;
167175
168    dev_vdbg(&urb->dev->dev, "atusb_timer\n");
176    dev_warn(&urb->dev->dev, "atusb_timer\n");
169177    atusb_async_finish(urb);
170178}
171179
172static void atusb_ctrl_cb_delayed(struct urb *urb)
180static void atusb_ctrl_cb_sync(struct urb *urb)
173181{
174182    struct atusb_local *atusb = urb->context;
175183
176    if (atusb_async_errchk(urb))
184    /* @@@ needs locking/atomic */
185    if (atusb_async_errchk(urb) || atusb->irq_sync == atusb->irq_seen) {
177186        atusb_async_finish(urb);
178    else {
179        BUG_ON(timer_pending(&atusb->timer));
180        atusb->timer.expires = jiffies+msecs_to_jiffies(10);
181        atusb->timer.data = (unsigned long) urb;
182        add_timer(&atusb->timer);
187        return;
183188    }
189
190    BUG_ON(timer_pending(&atusb->timer));
191    atusb->timer.expires = jiffies+msecs_to_jiffies(SYNC_TIMEOUT_MS);
192    atusb->timer.data = (unsigned long) urb;
193    add_timer(&atusb->timer);
184194}
185195
186196static void atusb_read_fb_cb(struct urb *urb)
...... 
273283static int atusb_write(struct atusb_local *atusb,
274284    uint8_t tx0, uint8_t tx1, const uint8_t *tx, int len)
275285{
276    usb_complete_t cb = atusb_ctrl_cb;
277
278286    dev_dbg(&atusb->udev->dev,
279287        "atusb_write: tx0 = 0x%x tx1 = 0x%x\n", tx0, tx1);
280288
...... 
288296     */
289297    if (tx0 == (CMD_REG | CMD_WRITE | RG_TRX_STATE) &&
290298        (tx1 & 0x1f) == STATE_FORCE_TX_ON)
291        cb = atusb_ctrl_cb_delayed;
292
293    return submit_control_msg(atusb,
294        ATUSB_SPI_WRITE, ATUSB_TO_DEV, tx0, tx1,
295        (uint8_t *) tx, len, cb, atusb);
299        return submit_control_msg(atusb,
300            ATUSB_SPI_WRITE2_SYNC, ATUSB_FROM_DEV, tx0, tx1,
301             &atusb->irq_sync, 1, atusb_ctrl_cb_sync, atusb);
302    else
303        return submit_control_msg(atusb,
304            ATUSB_SPI_WRITE, ATUSB_TO_DEV, tx0, tx1,
305            (uint8_t *) tx, len, atusb_ctrl_cb, atusb);
296306}
297307
298308static int atusb_transfer(struct spi_device *spi, struct spi_message *msg)
...... 
395405{
396406    struct atusb_local *atusb = urb->context;
397407
398    dev_dbg(&urb->dev->dev, "atusb_irq (%d)\n", urb->status);
408    dev_dbg(&urb->dev->dev, "atusb_irq (%d), seen %d sync %d\n",
409        urb->status, atusb->irq_buf, atusb->irq_sync);
410    if (!urb->status) {
411        atusb->irq_seen = atusb->irq_buf;
412        if (atusb->irq_sync == atusb->irq_seen &&
413            try_to_del_timer_sync(&atusb->timer) == 1)
414            atusb_async_finish((struct urb *) atusb->timer.data);
415    }
399416    usb_free_urb(urb);
400417    atusb->irq_urb = NULL;
401418    tasklet_schedule(&atusb->task);

Archive Download the corresponding diff file



interactive