diff options
author | Kristian Høgsberg <krh@redhat.com> | 2007-01-26 00:38:49 -0500 |
---|---|---|
committer | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2007-03-09 16:02:49 -0500 |
commit | 0edeefd99fd31f74432aba5860f6ebcbde874dbf (patch) | |
tree | 45b6411584a198947c7d37a7c78bbf85346ac927 | |
parent | 931c4834c8d1e1bf0dcc256b89449a01711f970d (diff) |
firewire: Make sure we wait for DMA to stop before we reprogram it.
Signed-off-by: Kristian Høgsberg <krh@redhat.com>
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
-rw-r--r-- | drivers/firewire/fw-ohci.c | 21 |
1 files changed, 16 insertions, 5 deletions
diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c index 58bc85dd7917..29285f209dcf 100644 --- a/drivers/firewire/fw-ohci.c +++ b/drivers/firewire/fw-ohci.c | |||
@@ -170,6 +170,8 @@ static inline struct fw_ohci *fw_ohci(struct fw_card *card) | |||
170 | #define OHCI1394_PCI_HCI_Control 0x40 | 170 | #define OHCI1394_PCI_HCI_Control 0x40 |
171 | #define SELF_ID_BUF_SIZE 0x800 | 171 | #define SELF_ID_BUF_SIZE 0x800 |
172 | 172 | ||
173 | #define MAX_STOP_CONTEXT_LOOPS 1000 | ||
174 | |||
173 | static char ohci_driver_name[] = KBUILD_MODNAME; | 175 | static char ohci_driver_name[] = KBUILD_MODNAME; |
174 | 176 | ||
175 | static inline void reg_write(const struct fw_ohci *ohci, int offset, u32 data) | 177 | static inline void reg_write(const struct fw_ohci *ohci, int offset, u32 data) |
@@ -224,6 +226,13 @@ static void ar_context_tasklet(unsigned long data) | |||
224 | struct fw_ohci *ohci = ctx->ohci; | 226 | struct fw_ohci *ohci = ctx->ohci; |
225 | struct fw_packet p; | 227 | struct fw_packet p; |
226 | u32 status, length, tcode; | 228 | u32 status, length, tcode; |
229 | int i; | ||
230 | |||
231 | /* FIXME: We stop and restart the ar context here, what if we | ||
232 | * stop while a receive is in progress? Maybe we could just | ||
233 | * loop the context back to itself and use it in buffer fill | ||
234 | * mode as intended... */ | ||
235 | reg_write(ctx->ohci, ctx->control_clear, CONTEXT_RUN); | ||
227 | 236 | ||
228 | /* FIXME: What to do about evt_* errors? */ | 237 | /* FIXME: What to do about evt_* errors? */ |
229 | length = le16_to_cpu(ctx->descriptor.req_count) - | 238 | length = le16_to_cpu(ctx->descriptor.req_count) - |
@@ -287,12 +296,14 @@ static void ar_context_tasklet(unsigned long data) | |||
287 | dma_sync_single_for_device(ohci->card.device, ctx->descriptor_bus, | 296 | dma_sync_single_for_device(ohci->card.device, ctx->descriptor_bus, |
288 | sizeof ctx->descriptor_bus, DMA_TO_DEVICE); | 297 | sizeof ctx->descriptor_bus, DMA_TO_DEVICE); |
289 | 298 | ||
290 | /* FIXME: We stop and restart the ar context here, what if we | 299 | /* Make sure the active bit is 0 before we reprogram the DMA. */ |
291 | * stop while a receive is in progress? Maybe we could just | 300 | for (i = 0; i < MAX_STOP_CONTEXT_LOOPS; i++) |
292 | * loop the context back to itself and use it in buffer fill | 301 | if (!(reg_read(ctx->ohci, |
293 | * mode as intended... */ | 302 | ctx->control_clear) & CONTEXT_ACTIVE)) |
303 | break; | ||
304 | if (i == MAX_STOP_CONTEXT_LOOPS) | ||
305 | fw_error("Failed to stop ar context\n"); | ||
294 | 306 | ||
295 | reg_write(ctx->ohci, ctx->control_clear, CONTEXT_RUN); | ||
296 | ar_context_run(ctx); | 307 | ar_context_run(ctx); |
297 | } | 308 | } |
298 | 309 | ||