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 | ||
---|---|---|
33 | 33 | |
34 | 34 | #include "../ieee802154/at86rf230.h" /* dirty */ |
35 | 35 | |
36 | ||
37 | #define SYNC_TIMEOUT_MS 50 /* assume interrupt has been synced after | |
38 | waiting this long */ | |
39 | ||
36 | 40 | #define VENDOR_ID 0x20b7 |
37 | 41 | #define PRODUCT_ID 0x1540 |
38 | 42 | |
... | ... | |
53 | 57 | struct spi_master *master; |
54 | 58 | int slave_irq; |
55 | 59 | 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 */ | |
57 | 63 | struct tasklet_struct task; /* interrupt delivery tasklet */ |
58 | 64 | struct timer_list timer; /* delay, for interrupt synch */ |
59 | 65 | struct at86rf230_platform_data platform_data; |
... | ... | |
85 | 91 | ATUSB_SPI_WRITE = 0x30, /* SPI group */ |
86 | 92 | ATUSB_SPI_READ1, |
87 | 93 | ATUSB_SPI_READ2, |
94 | ATUSB_SPI_WRITE2_SYNC, | |
88 | 95 | }; |
89 | 96 | |
90 | 97 | /* |
... | ... | |
112 | 119 | * host-> ATUSB_SPI_WRITE byte0 byte1 #bytes |
113 | 120 | * ->host ATUSB_SPI_READ1 byte0 - #bytes |
114 | 121 | * ->host ATUSB_SPI_READ2 byte0 byte1 #bytes |
122 | * ->host ATUSB_SPI_WRITE2_SYNC byte0 byte1 0/1 | |
115 | 123 | */ |
116 | 124 | |
117 | 125 | #define ATUSB_FROM_DEV (USB_TYPE_VENDOR | USB_DIR_IN) |
... | ... | |
165 | 173 | { |
166 | 174 | struct urb *urb = (void *) data; |
167 | 175 | |
168 | dev_vdbg(&urb->dev->dev, "atusb_timer\n"); | |
176 | dev_warn(&urb->dev->dev, "atusb_timer\n"); | |
169 | 177 | atusb_async_finish(urb); |
170 | 178 | } |
171 | 179 | |
172 | static void atusb_ctrl_cb_delayed(struct urb *urb) | |
180 | static void atusb_ctrl_cb_sync(struct urb *urb) | |
173 | 181 | { |
174 | 182 | struct atusb_local *atusb = urb->context; |
175 | 183 | |
176 | if (atusb_async_errchk(urb)) | |
184 | /* @@@ needs locking/atomic */ | |
185 | if (atusb_async_errchk(urb) || atusb->irq_sync == atusb->irq_seen) { | |
177 | 186 | 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; | |
183 | 188 | } |
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); | |
184 | 194 | } |
185 | 195 | |
186 | 196 | static void atusb_read_fb_cb(struct urb *urb) |
... | ... | |
273 | 283 | static int atusb_write(struct atusb_local *atusb, |
274 | 284 | uint8_t tx0, uint8_t tx1, const uint8_t *tx, int len) |
275 | 285 | { |
276 | usb_complete_t cb = atusb_ctrl_cb; | |
277 | ||
278 | 286 | dev_dbg(&atusb->udev->dev, |
279 | 287 | "atusb_write: tx0 = 0x%x tx1 = 0x%x\n", tx0, tx1); |
280 | 288 | |
... | ... | |
288 | 296 | */ |
289 | 297 | if (tx0 == (CMD_REG | CMD_WRITE | RG_TRX_STATE) && |
290 | 298 | (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); | |
296 | 306 | } |
297 | 307 | |
298 | 308 | static int atusb_transfer(struct spi_device *spi, struct spi_message *msg) |
... | ... | |
395 | 405 | { |
396 | 406 | struct atusb_local *atusb = urb->context; |
397 | 407 | |
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 | } | |
399 | 416 | usb_free_urb(urb); |
400 | 417 | atusb->irq_urb = NULL; |
401 | 418 | tasklet_schedule(&atusb->task); |
Branches:
ben-wpan
ben-wpan-stefan
5396a9238205f20f811ea57898980d3ca82df0b6
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9