diff options
author | Clemens Ladisch <clemens@ladisch.de> | 2010-12-24 08:40:15 -0500 |
---|---|---|
committer | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2011-01-03 16:34:48 -0500 |
commit | 82b662dc41027527675740de15344d1b4e34958e (patch) | |
tree | e9e38e035e426c40b5f52f48da7928872fe61f5c /drivers/firewire | |
parent | c16714704bb35165e5b85d927873dcc643772648 (diff) |
firewire: ohci: flush AT contexts after bus reset for OHCI 1.2
The OHCI 1.2 (draft) specification, clause 7.2.3.3, allows and
recommends that, after a bus reset, the controller does not flush all
the packets in the AT queues. Therefore, the driver has to do this
itself.
Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Diffstat (limited to 'drivers/firewire')
-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 5e5d5d3d43d1..3372cd187c25 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) |