diff options
| -rw-r--r-- | drivers/firewire/ohci.c | 46 |
1 files changed, 39 insertions, 7 deletions
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index 5e5d5d3d43d..3372cd187c2 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c | |||
| @@ -125,6 +125,7 @@ struct context { | |||
| 125 | struct fw_ohci *ohci; | 125 | struct fw_ohci *ohci; |
| 126 | u32 regs; | 126 | u32 regs; |
| 127 | int total_allocation; | 127 | int total_allocation; |
| 128 | bool flushing; | ||
| 128 | 129 | ||
| 129 | /* | 130 | /* |
| 130 | * List of page-sized buffers for storing DMA descriptors. | 131 | * List of page-sized buffers for storing DMA descriptors. |
| @@ -1356,6 +1357,17 @@ static int at_context_queue_packet(struct context *ctx, | |||
| 1356 | return 0; | 1357 | return 0; |
| 1357 | } | 1358 | } |
| 1358 | 1359 | ||
| 1360 | static void at_context_flush(struct context *ctx) | ||
| 1361 | { | ||
| 1362 | tasklet_disable(&ctx->tasklet); | ||
| 1363 | |||
| 1364 | ctx->flushing = true; | ||
| 1365 | context_tasklet((unsigned long)ctx); | ||
| 1366 | ctx->flushing = false; | ||
| 1367 | |||
| 1368 | tasklet_enable(&ctx->tasklet); | ||
| 1369 | } | ||
| 1370 | |||
| 1359 | static int handle_at_packet(struct context *context, | 1371 | static int handle_at_packet(struct context *context, |
| 1360 | struct descriptor *d, | 1372 | struct descriptor *d, |
| 1361 | struct descriptor *last) | 1373 | struct descriptor *last) |
| @@ -1365,7 +1377,7 @@ static int handle_at_packet(struct context *context, | |||
| 1365 | struct fw_ohci *ohci = context->ohci; | 1377 | struct fw_ohci *ohci = context->ohci; |
| 1366 | int evt; | 1378 | int evt; |
| 1367 | 1379 | ||
| 1368 | if (last->transfer_status == 0) | 1380 | if (last->transfer_status == 0 && !context->flushing) |
| 1369 | /* This descriptor isn't done yet, stop iteration. */ | 1381 | /* This descriptor isn't done yet, stop iteration. */ |
| 1370 | return 0; | 1382 | return 0; |
| 1371 | 1383 | ||
| @@ -1399,11 +1411,15 @@ static int handle_at_packet(struct context *context, | |||
| 1399 | break; | 1411 | break; |
| 1400 | 1412 | ||
| 1401 | case OHCI1394_evt_missing_ack: | 1413 | case OHCI1394_evt_missing_ack: |
| 1402 | /* | 1414 | if (context->flushing) |
| 1403 | * Using a valid (current) generation count, but the | 1415 | packet->ack = RCODE_GENERATION; |
| 1404 | * node is not on the bus or not sending acks. | 1416 | else { |
| 1405 | */ | 1417 | /* |
| 1406 | packet->ack = RCODE_NO_ACK; | 1418 | * Using a valid (current) generation count, but the |
| 1419 | * node is not on the bus or not sending acks. | ||
| 1420 | */ | ||
| 1421 | packet->ack = RCODE_NO_ACK; | ||
| 1422 | } | ||
| 1407 | break; | 1423 | break; |
| 1408 | 1424 | ||
| 1409 | case ACK_COMPLETE + 0x10: | 1425 | case ACK_COMPLETE + 0x10: |
| @@ -1416,6 +1432,13 @@ static int handle_at_packet(struct context *context, | |||
| 1416 | packet->ack = evt - 0x10; | 1432 | packet->ack = evt - 0x10; |
| 1417 | break; | 1433 | break; |
| 1418 | 1434 | ||
| 1435 | case OHCI1394_evt_no_status: | ||
| 1436 | if (context->flushing) { | ||
| 1437 | packet->ack = RCODE_GENERATION; | ||
| 1438 | break; | ||
| 1439 | } | ||
| 1440 | /* fall through */ | ||
| 1441 | |||
| 1419 | default: | 1442 | default: |
| 1420 | packet->ack = RCODE_SEND_ERROR; | 1443 | packet->ack = RCODE_SEND_ERROR; |
| 1421 | break; | 1444 | break; |
| @@ -1721,9 +1744,18 @@ static void bus_reset_tasklet(unsigned long data) | |||
| 1721 | /* FIXME: Document how the locking works. */ | 1744 | /* FIXME: Document how the locking works. */ |
| 1722 | spin_lock_irqsave(&ohci->lock, flags); | 1745 | spin_lock_irqsave(&ohci->lock, flags); |
| 1723 | 1746 | ||
| 1724 | ohci->generation = generation; | 1747 | ohci->generation = -1; /* prevent AT packet queueing */ |
| 1725 | context_stop(&ohci->at_request_ctx); | 1748 | context_stop(&ohci->at_request_ctx); |
| 1726 | context_stop(&ohci->at_response_ctx); | 1749 | context_stop(&ohci->at_response_ctx); |
| 1750 | |||
| 1751 | spin_unlock_irqrestore(&ohci->lock, flags); | ||
| 1752 | |||
| 1753 | at_context_flush(&ohci->at_request_ctx); | ||
| 1754 | at_context_flush(&ohci->at_response_ctx); | ||
| 1755 | |||
| 1756 | spin_lock_irqsave(&ohci->lock, flags); | ||
| 1757 | |||
| 1758 | ohci->generation = generation; | ||
| 1727 | reg_write(ohci, OHCI1394_IntEventClear, OHCI1394_busReset); | 1759 | reg_write(ohci, OHCI1394_IntEventClear, OHCI1394_busReset); |
| 1728 | 1760 | ||
| 1729 | if (ohci->quirks & QUIRK_RESET_PACKET) | 1761 | if (ohci->quirks & QUIRK_RESET_PACKET) |
