diff options
| author | Ben Hutchings <bhutchings@solarflare.com> | 2008-09-01 07:49:37 -0400 |
|---|---|---|
| committer | Jeff Garzik <jgarzik@redhat.com> | 2008-09-24 18:54:37 -0400 |
| commit | 6bc5d3a9334401d788e1adf8b71add211265bc8b (patch) | |
| tree | 250f3de17f38b778ac8a109229c5b3687ab8d15d /drivers/net/sfc | |
| parent | 92ade881b2fcfc2744d3de43d172d3ec8e13afd7 (diff) | |
sfc: Make queue flushes more reliable
Increase the potential retry count for RX flushes from 5 to 100.
Stop polling the RX_DESC_PTR_TBL to infer that a flush might have
happened. Instead absolutely rely on the flush events, unless bug 7803
applies (Falcon rev A only).
To keep things quick, request flushes for every TX and RX queue up
front, and match up the events to requests.
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers/net/sfc')
| -rw-r--r-- | drivers/net/sfc/efx.c | 15 | ||||
| -rw-r--r-- | drivers/net/sfc/falcon.c | 247 | ||||
| -rw-r--r-- | drivers/net/sfc/falcon.h | 1 | ||||
| -rw-r--r-- | drivers/net/sfc/net_driver.h | 4 |
4 files changed, 141 insertions, 126 deletions
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index f65e313c2be..06ea71c7e34 100644 --- a/drivers/net/sfc/efx.c +++ b/drivers/net/sfc/efx.c | |||
| @@ -445,10 +445,17 @@ static void efx_fini_channels(struct efx_nic *efx) | |||
| 445 | struct efx_channel *channel; | 445 | struct efx_channel *channel; |
| 446 | struct efx_tx_queue *tx_queue; | 446 | struct efx_tx_queue *tx_queue; |
| 447 | struct efx_rx_queue *rx_queue; | 447 | struct efx_rx_queue *rx_queue; |
| 448 | int rc; | ||
| 448 | 449 | ||
| 449 | EFX_ASSERT_RESET_SERIALISED(efx); | 450 | EFX_ASSERT_RESET_SERIALISED(efx); |
| 450 | BUG_ON(efx->port_enabled); | 451 | BUG_ON(efx->port_enabled); |
| 451 | 452 | ||
| 453 | rc = falcon_flush_queues(efx); | ||
| 454 | if (rc) | ||
| 455 | EFX_ERR(efx, "failed to flush queues\n"); | ||
| 456 | else | ||
| 457 | EFX_LOG(efx, "successfully flushed all queues\n"); | ||
| 458 | |||
| 452 | efx_for_each_channel(channel, efx) { | 459 | efx_for_each_channel(channel, efx) { |
| 453 | EFX_LOG(channel->efx, "shut down chan %d\n", channel->channel); | 460 | EFX_LOG(channel->efx, "shut down chan %d\n", channel->channel); |
| 454 | 461 | ||
| @@ -456,13 +463,6 @@ static void efx_fini_channels(struct efx_nic *efx) | |||
| 456 | efx_fini_rx_queue(rx_queue); | 463 | efx_fini_rx_queue(rx_queue); |
| 457 | efx_for_each_channel_tx_queue(tx_queue, channel) | 464 | efx_for_each_channel_tx_queue(tx_queue, channel) |
| 458 | efx_fini_tx_queue(tx_queue); | 465 | efx_fini_tx_queue(tx_queue); |
| 459 | } | ||
| 460 | |||
| 461 | /* Do the event queues last so that we can handle flush events | ||
| 462 | * for all DMA queues. */ | ||
| 463 | efx_for_each_channel(channel, efx) { | ||
| 464 | EFX_LOG(channel->efx, "shut down evq %d\n", channel->channel); | ||
| 465 | |||
| 466 | efx_fini_eventq(channel); | 466 | efx_fini_eventq(channel); |
| 467 | } | 467 | } |
| 468 | } | 468 | } |
| @@ -1092,7 +1092,6 @@ static void efx_stop_all(struct efx_nic *efx) | |||
| 1092 | 1092 | ||
| 1093 | /* Isolate the MAC from the TX and RX engines, so that queue | 1093 | /* Isolate the MAC from the TX and RX engines, so that queue |
| 1094 | * flushes will complete in a timely fashion. */ | 1094 | * flushes will complete in a timely fashion. */ |
| 1095 | falcon_deconfigure_mac_wrapper(efx); | ||
| 1096 | falcon_drain_tx_fifo(efx); | 1095 | falcon_drain_tx_fifo(efx); |
| 1097 | 1096 | ||
| 1098 | /* Stop the kernel transmit interface late, so the watchdog | 1097 | /* Stop the kernel transmit interface late, so the watchdog |
diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c index ad192f82c5e..70c681ecdab 100644 --- a/drivers/net/sfc/falcon.c +++ b/drivers/net/sfc/falcon.c | |||
| @@ -108,10 +108,10 @@ MODULE_PARM_DESC(rx_xon_thresh_bytes, "RX fifo XON threshold"); | |||
| 108 | /* Max number of internal errors. After this resets will not be performed */ | 108 | /* Max number of internal errors. After this resets will not be performed */ |
| 109 | #define FALCON_MAX_INT_ERRORS 4 | 109 | #define FALCON_MAX_INT_ERRORS 4 |
| 110 | 110 | ||
| 111 | /* Maximum period that we wait for flush events. If the flush event | 111 | /* We poll for events every FLUSH_INTERVAL ms, and check FLUSH_POLL_COUNT times |
| 112 | * doesn't arrive in this period of time then we check if the queue | 112 | */ |
| 113 | * was disabled anyway. */ | 113 | #define FALCON_FLUSH_INTERVAL 10 |
| 114 | #define FALCON_FLUSH_TIMEOUT 10 /* 10ms */ | 114 | #define FALCON_FLUSH_POLL_COUNT 100 |
| 115 | 115 | ||
| 116 | /************************************************************************** | 116 | /************************************************************************** |
| 117 | * | 117 | * |
| @@ -452,6 +452,8 @@ void falcon_init_tx(struct efx_tx_queue *tx_queue) | |||
| 452 | efx_oword_t tx_desc_ptr; | 452 | efx_oword_t tx_desc_ptr; |
| 453 | struct efx_nic *efx = tx_queue->efx; | 453 | struct efx_nic *efx = tx_queue->efx; |
| 454 | 454 | ||
| 455 | tx_queue->flushed = false; | ||
| 456 | |||
| 455 | /* Pin TX descriptor ring */ | 457 | /* Pin TX descriptor ring */ |
| 456 | falcon_init_special_buffer(efx, &tx_queue->txd); | 458 | falcon_init_special_buffer(efx, &tx_queue->txd); |
| 457 | 459 | ||
| @@ -492,60 +494,16 @@ void falcon_init_tx(struct efx_tx_queue *tx_queue) | |||
| 492 | } | 494 | } |
| 493 | } | 495 | } |
| 494 | 496 | ||
| 495 | static int falcon_flush_tx_queue(struct efx_tx_queue *tx_queue) | 497 | static void falcon_flush_tx_queue(struct efx_tx_queue *tx_queue) |
| 496 | { | 498 | { |
| 497 | struct efx_nic *efx = tx_queue->efx; | 499 | struct efx_nic *efx = tx_queue->efx; |
| 498 | struct efx_channel *channel = &efx->channel[0]; | ||
| 499 | efx_oword_t tx_flush_descq; | 500 | efx_oword_t tx_flush_descq; |
| 500 | unsigned int read_ptr, i; | ||
| 501 | 501 | ||
| 502 | /* Post a flush command */ | 502 | /* Post a flush command */ |
| 503 | EFX_POPULATE_OWORD_2(tx_flush_descq, | 503 | EFX_POPULATE_OWORD_2(tx_flush_descq, |
| 504 | TX_FLUSH_DESCQ_CMD, 1, | 504 | TX_FLUSH_DESCQ_CMD, 1, |
| 505 | TX_FLUSH_DESCQ, tx_queue->queue); | 505 | TX_FLUSH_DESCQ, tx_queue->queue); |
| 506 | falcon_write(efx, &tx_flush_descq, TX_FLUSH_DESCQ_REG_KER); | 506 | falcon_write(efx, &tx_flush_descq, TX_FLUSH_DESCQ_REG_KER); |
| 507 | msleep(FALCON_FLUSH_TIMEOUT); | ||
| 508 | |||
| 509 | if (EFX_WORKAROUND_7803(efx)) | ||
| 510 | return 0; | ||
| 511 | |||
| 512 | /* Look for a flush completed event */ | ||
| 513 | read_ptr = channel->eventq_read_ptr; | ||
| 514 | for (i = 0; i < FALCON_EVQ_SIZE; ++i) { | ||
| 515 | efx_qword_t *event = falcon_event(channel, read_ptr); | ||
| 516 | int ev_code, ev_sub_code, ev_queue; | ||
| 517 | if (!falcon_event_present(event)) | ||
| 518 | break; | ||
| 519 | |||
| 520 | ev_code = EFX_QWORD_FIELD(*event, EV_CODE); | ||
| 521 | ev_sub_code = EFX_QWORD_FIELD(*event, DRIVER_EV_SUB_CODE); | ||
| 522 | ev_queue = EFX_QWORD_FIELD(*event, DRIVER_EV_TX_DESCQ_ID); | ||
| 523 | if ((ev_sub_code == TX_DESCQ_FLS_DONE_EV_DECODE) && | ||
| 524 | (ev_queue == tx_queue->queue)) { | ||
| 525 | EFX_LOG(efx, "tx queue %d flush command succesful\n", | ||
| 526 | tx_queue->queue); | ||
| 527 | return 0; | ||
| 528 | } | ||
| 529 | |||
| 530 | read_ptr = (read_ptr + 1) & FALCON_EVQ_MASK; | ||
| 531 | } | ||
| 532 | |||
| 533 | if (EFX_WORKAROUND_11557(efx)) { | ||
| 534 | efx_oword_t reg; | ||
| 535 | bool enabled; | ||
| 536 | |||
| 537 | falcon_read_table(efx, ®, efx->type->txd_ptr_tbl_base, | ||
| 538 | tx_queue->queue); | ||
| 539 | enabled = EFX_OWORD_FIELD(reg, TX_DESCQ_EN); | ||
| 540 | if (!enabled) { | ||
| 541 | EFX_LOG(efx, "tx queue %d disabled without a " | ||
| 542 | "flush event seen\n", tx_queue->queue); | ||
| 543 | return 0; | ||
| 544 | } | ||
| 545 | } | ||
| 546 | |||
| 547 | EFX_ERR(efx, "tx queue %d flush command timed out\n", tx_queue->queue); | ||
| 548 | return -ETIMEDOUT; | ||
| 549 | } | 507 | } |
| 550 | 508 | ||
| 551 | void falcon_fini_tx(struct efx_tx_queue *tx_queue) | 509 | void falcon_fini_tx(struct efx_tx_queue *tx_queue) |
| @@ -553,9 +511,8 @@ void falcon_fini_tx(struct efx_tx_queue *tx_queue) | |||
| 553 | struct efx_nic *efx = tx_queue->efx; | 511 | struct efx_nic *efx = tx_queue->efx; |
| 554 | efx_oword_t tx_desc_ptr; | 512 | efx_oword_t tx_desc_ptr; |
| 555 | 513 | ||
| 556 | /* Stop the hardware using the queue */ | 514 | /* The queue should have been flushed */ |
| 557 | if (falcon_flush_tx_queue(tx_queue)) | 515 | WARN_ON(!tx_queue->flushed); |
| 558 | EFX_ERR(efx, "failed to flush tx queue %d\n", tx_queue->queue); | ||
| 559 | 516 | ||
| 560 | /* Remove TX descriptor ring from card */ | 517 | /* Remove TX descriptor ring from card */ |
| 561 | EFX_ZERO_OWORD(tx_desc_ptr); | 518 | EFX_ZERO_OWORD(tx_desc_ptr); |
| @@ -643,6 +600,8 @@ void falcon_init_rx(struct efx_rx_queue *rx_queue) | |||
| 643 | rx_queue->queue, rx_queue->rxd.index, | 600 | rx_queue->queue, rx_queue->rxd.index, |
| 644 | rx_queue->rxd.index + rx_queue->rxd.entries - 1); | 601 | rx_queue->rxd.index + rx_queue->rxd.entries - 1); |
| 645 | 602 | ||
| 603 | rx_queue->flushed = false; | ||
| 604 | |||
| 646 | /* Pin RX descriptor ring */ | 605 | /* Pin RX descriptor ring */ |
| 647 | falcon_init_special_buffer(efx, &rx_queue->rxd); | 606 | falcon_init_special_buffer(efx, &rx_queue->rxd); |
| 648 | 607 | ||
| @@ -663,11 +622,9 @@ void falcon_init_rx(struct efx_rx_queue *rx_queue) | |||
| 663 | rx_queue->queue); | 622 | rx_queue->queue); |
| 664 | } | 623 | } |
| 665 | 624 | ||
| 666 | static int falcon_flush_rx_queue(struct efx_rx_queue *rx_queue) | 625 | static void falcon_flush_rx_queue(struct efx_rx_queue *rx_queue) |
| 667 | { | 626 | { |
| 668 | struct efx_nic *efx = rx_queue->efx; | 627 | struct efx_nic *efx = rx_queue->efx; |
| 669 | struct efx_channel *channel = &efx->channel[0]; | ||
| 670 | unsigned int read_ptr, i; | ||
| 671 | efx_oword_t rx_flush_descq; | 628 | efx_oword_t rx_flush_descq; |
| 672 | 629 | ||
| 673 | /* Post a flush command */ | 630 | /* Post a flush command */ |
| @@ -675,76 +632,15 @@ static int falcon_flush_rx_queue(struct efx_rx_queue *rx_queue) | |||
| 675 | RX_FLUSH_DESCQ_CMD, 1, | 632 | RX_FLUSH_DESCQ_CMD, 1, |
| 676 | RX_FLUSH_DESCQ, rx_queue->queue); | 633 | RX_FLUSH_DESCQ, rx_queue->queue); |
| 677 | falcon_write(efx, &rx_flush_descq, RX_FLUSH_DESCQ_REG_KER); | 634 | falcon_write(efx, &rx_flush_descq, RX_FLUSH_DESCQ_REG_KER); |
| 678 | msleep(FALCON_FLUSH_TIMEOUT); | ||
| 679 | |||
| 680 | if (EFX_WORKAROUND_7803(efx)) | ||
| 681 | return 0; | ||
| 682 | |||
| 683 | /* Look for a flush completed event */ | ||
| 684 | read_ptr = channel->eventq_read_ptr; | ||
| 685 | for (i = 0; i < FALCON_EVQ_SIZE; ++i) { | ||
| 686 | efx_qword_t *event = falcon_event(channel, read_ptr); | ||
| 687 | int ev_code, ev_sub_code, ev_queue; | ||
| 688 | bool ev_failed; | ||
| 689 | if (!falcon_event_present(event)) | ||
| 690 | break; | ||
| 691 | |||
| 692 | ev_code = EFX_QWORD_FIELD(*event, EV_CODE); | ||
| 693 | ev_sub_code = EFX_QWORD_FIELD(*event, DRIVER_EV_SUB_CODE); | ||
| 694 | ev_queue = EFX_QWORD_FIELD(*event, DRIVER_EV_RX_DESCQ_ID); | ||
| 695 | ev_failed = EFX_QWORD_FIELD(*event, DRIVER_EV_RX_FLUSH_FAIL); | ||
| 696 | |||
| 697 | if ((ev_sub_code == RX_DESCQ_FLS_DONE_EV_DECODE) && | ||
| 698 | (ev_queue == rx_queue->queue)) { | ||
| 699 | if (ev_failed) { | ||
| 700 | EFX_INFO(efx, "rx queue %d flush command " | ||
| 701 | "failed\n", rx_queue->queue); | ||
| 702 | return -EAGAIN; | ||
| 703 | } else { | ||
| 704 | EFX_LOG(efx, "rx queue %d flush command " | ||
| 705 | "succesful\n", rx_queue->queue); | ||
| 706 | return 0; | ||
| 707 | } | ||
| 708 | } | ||
| 709 | |||
| 710 | read_ptr = (read_ptr + 1) & FALCON_EVQ_MASK; | ||
| 711 | } | ||
| 712 | |||
| 713 | if (EFX_WORKAROUND_11557(efx)) { | ||
| 714 | efx_oword_t reg; | ||
| 715 | bool enabled; | ||
| 716 | |||
| 717 | falcon_read_table(efx, ®, efx->type->rxd_ptr_tbl_base, | ||
| 718 | rx_queue->queue); | ||
| 719 | enabled = EFX_OWORD_FIELD(reg, RX_DESCQ_EN); | ||
| 720 | if (!enabled) { | ||
| 721 | EFX_LOG(efx, "rx queue %d disabled without a " | ||
| 722 | "flush event seen\n", rx_queue->queue); | ||
| 723 | return 0; | ||
| 724 | } | ||
| 725 | } | ||
| 726 | |||
| 727 | EFX_ERR(efx, "rx queue %d flush command timed out\n", rx_queue->queue); | ||
| 728 | return -ETIMEDOUT; | ||
| 729 | } | 635 | } |
| 730 | 636 | ||
| 731 | void falcon_fini_rx(struct efx_rx_queue *rx_queue) | 637 | void falcon_fini_rx(struct efx_rx_queue *rx_queue) |
| 732 | { | 638 | { |
| 733 | efx_oword_t rx_desc_ptr; | 639 | efx_oword_t rx_desc_ptr; |
| 734 | struct efx_nic *efx = rx_queue->efx; | 640 | struct efx_nic *efx = rx_queue->efx; |
| 735 | int i, rc; | ||
| 736 | 641 | ||
| 737 | /* Try and flush the rx queue. This may need to be repeated */ | 642 | /* The queue should already have been flushed */ |
| 738 | for (i = 0; i < 5; i++) { | 643 | WARN_ON(!rx_queue->flushed); |
| 739 | rc = falcon_flush_rx_queue(rx_queue); | ||
| 740 | if (rc == -EAGAIN) | ||
| 741 | continue; | ||
| 742 | break; | ||
| 743 | } | ||
| 744 | if (rc) { | ||
| 745 | EFX_ERR(efx, "failed to flush rx queue %d\n", rx_queue->queue); | ||
| 746 | efx_schedule_reset(efx, RESET_TYPE_INVISIBLE); | ||
| 747 | } | ||
| 748 | 644 | ||
| 749 | /* Remove RX descriptor ring from card */ | 645 | /* Remove RX descriptor ring from card */ |
| 750 | EFX_ZERO_OWORD(rx_desc_ptr); | 646 | EFX_ZERO_OWORD(rx_desc_ptr); |
| @@ -1255,6 +1151,121 @@ void falcon_generate_test_event(struct efx_channel *channel, unsigned int magic) | |||
| 1255 | falcon_generate_event(channel, &test_event); | 1151 | falcon_generate_event(channel, &test_event); |
| 1256 | } | 1152 | } |
| 1257 | 1153 | ||
| 1154 | /************************************************************************** | ||
| 1155 | * | ||
| 1156 | * Flush handling | ||
| 1157 | * | ||
| 1158 | **************************************************************************/ | ||
| 1159 | |||
| 1160 | |||
| 1161 | static void falcon_poll_flush_events(struct efx_nic *efx) | ||
| 1162 | { | ||
| 1163 | struct efx_channel *channel = &efx->channel[0]; | ||
| 1164 | struct efx_tx_queue *tx_queue; | ||
| 1165 | struct efx_rx_queue *rx_queue; | ||
| 1166 | unsigned int read_ptr, i; | ||
| 1167 | |||
| 1168 | read_ptr = channel->eventq_read_ptr; | ||
| 1169 | for (i = 0; i < FALCON_EVQ_SIZE; ++i) { | ||
| 1170 | efx_qword_t *event = falcon_event(channel, read_ptr); | ||
| 1171 | int ev_code, ev_sub_code, ev_queue; | ||
| 1172 | bool ev_failed; | ||
| 1173 | if (!falcon_event_present(event)) | ||
| 1174 | break; | ||
| 1175 | |||
| 1176 | ev_code = EFX_QWORD_FIELD(*event, EV_CODE); | ||
| 1177 | if (ev_code != DRIVER_EV_DECODE) | ||
| 1178 | continue; | ||
| 1179 | |||
| 1180 | ev_sub_code = EFX_QWORD_FIELD(*event, DRIVER_EV_SUB_CODE); | ||
| 1181 | switch (ev_sub_code) { | ||
| 1182 | case TX_DESCQ_FLS_DONE_EV_DECODE: | ||
| 1183 | ev_queue = EFX_QWORD_FIELD(*event, | ||
| 1184 | DRIVER_EV_TX_DESCQ_ID); | ||
| 1185 | if (ev_queue < EFX_TX_QUEUE_COUNT) { | ||
| 1186 | tx_queue = efx->tx_queue + ev_queue; | ||
| 1187 | tx_queue->flushed = true; | ||
| 1188 | } | ||
| 1189 | break; | ||
| 1190 | case RX_DESCQ_FLS_DONE_EV_DECODE: | ||
| 1191 | ev_queue = EFX_QWORD_FIELD(*event, | ||
| 1192 | DRIVER_EV_RX_DESCQ_ID); | ||
| 1193 | ev_failed = EFX_QWORD_FIELD(*event, | ||
| 1194 | DRIVER_EV_RX_FLUSH_FAIL); | ||
| 1195 | if (ev_queue < efx->n_rx_queues) { | ||
| 1196 | rx_queue = efx->rx_queue + ev_queue; | ||
| 1197 | |||
| 1198 | /* retry the rx flush */ | ||
| 1199 | if (ev_failed) | ||
| 1200 | falcon_flush_rx_queue(rx_queue); | ||
| 1201 | else | ||
| 1202 | rx_queue->flushed = true; | ||
| 1203 | } | ||
| 1204 | break; | ||
| 1205 | } | ||
| 1206 | |||
| 1207 | read_ptr = (read_ptr + 1) & FALCON_EVQ_MASK; | ||
| 1208 | } | ||
| 1209 | } | ||
| 1210 | |||
| 1211 | /* Handle tx and rx flushes at the same time, since they run in | ||
| 1212 | * parallel in the hardware and there's no reason for us to | ||
| 1213 | * serialise them */ | ||
| 1214 | int falcon_flush_queues(struct efx_nic *efx) | ||
| 1215 | { | ||
| 1216 | struct efx_rx_queue *rx_queue; | ||
| 1217 | struct efx_tx_queue *tx_queue; | ||
| 1218 | int i; | ||
| 1219 | bool outstanding; | ||
| 1220 | |||
| 1221 | /* Issue flush requests */ | ||
| 1222 | efx_for_each_tx_queue(tx_queue, efx) { | ||
| 1223 | tx_queue->flushed = false; | ||
| 1224 | falcon_flush_tx_queue(tx_queue); | ||
| 1225 | } | ||
| 1226 | efx_for_each_rx_queue(rx_queue, efx) { | ||
| 1227 | rx_queue->flushed = false; | ||
| 1228 | falcon_flush_rx_queue(rx_queue); | ||
| 1229 | } | ||
| 1230 | |||
| 1231 | /* Poll the evq looking for flush completions. Since we're not pushing | ||
| 1232 | * any more rx or tx descriptors at this point, we're in no danger of | ||
| 1233 | * overflowing the evq whilst we wait */ | ||
| 1234 | for (i = 0; i < FALCON_FLUSH_POLL_COUNT; ++i) { | ||
| 1235 | msleep(FALCON_FLUSH_INTERVAL); | ||
| 1236 | falcon_poll_flush_events(efx); | ||
| 1237 | |||
| 1238 | /* Check if every queue has been succesfully flushed */ | ||
| 1239 | outstanding = false; | ||
| 1240 | efx_for_each_tx_queue(tx_queue, efx) | ||
| 1241 | outstanding |= !tx_queue->flushed; | ||
| 1242 | efx_for_each_rx_queue(rx_queue, efx) | ||
| 1243 | outstanding |= !rx_queue->flushed; | ||
| 1244 | if (!outstanding) | ||
| 1245 | return 0; | ||
| 1246 | } | ||
| 1247 | |||
| 1248 | /* Mark the queues as all flushed. We're going to return failure | ||
| 1249 | * leading to a reset, or fake up success anyway. "flushed" now | ||
| 1250 | * indicates that we tried to flush. */ | ||
| 1251 | efx_for_each_tx_queue(tx_queue, efx) { | ||
| 1252 | if (!tx_queue->flushed) | ||
| 1253 | EFX_ERR(efx, "tx queue %d flush command timed out\n", | ||
| 1254 | tx_queue->queue); | ||
| 1255 | tx_queue->flushed = true; | ||
| 1256 | } | ||
| 1257 | efx_for_each_rx_queue(rx_queue, efx) { | ||
| 1258 | if (!rx_queue->flushed) | ||
| 1259 | EFX_ERR(efx, "rx queue %d flush command timed out\n", | ||
| 1260 | rx_queue->queue); | ||
| 1261 | rx_queue->flushed = true; | ||
| 1262 | } | ||
| 1263 | |||
| 1264 | if (EFX_WORKAROUND_7803(efx)) | ||
| 1265 | return 0; | ||
| 1266 | |||
| 1267 | return -ETIMEDOUT; | ||
| 1268 | } | ||
| 1258 | 1269 | ||
| 1259 | /************************************************************************** | 1270 | /************************************************************************** |
| 1260 | * | 1271 | * |
diff --git a/drivers/net/sfc/falcon.h b/drivers/net/sfc/falcon.h index 30d61e48ac6..be025ba7a6c 100644 --- a/drivers/net/sfc/falcon.h +++ b/drivers/net/sfc/falcon.h | |||
| @@ -86,6 +86,7 @@ extern void falcon_fini_interrupt(struct efx_nic *efx); | |||
| 86 | extern int falcon_probe_nic(struct efx_nic *efx); | 86 | extern int falcon_probe_nic(struct efx_nic *efx); |
| 87 | extern int falcon_probe_resources(struct efx_nic *efx); | 87 | extern int falcon_probe_resources(struct efx_nic *efx); |
| 88 | extern int falcon_init_nic(struct efx_nic *efx); | 88 | extern int falcon_init_nic(struct efx_nic *efx); |
| 89 | extern int falcon_flush_queues(struct efx_nic *efx); | ||
| 89 | extern int falcon_reset_hw(struct efx_nic *efx, enum reset_type method); | 90 | extern int falcon_reset_hw(struct efx_nic *efx, enum reset_type method); |
| 90 | extern void falcon_remove_resources(struct efx_nic *efx); | 91 | extern void falcon_remove_resources(struct efx_nic *efx); |
| 91 | extern void falcon_remove_nic(struct efx_nic *efx); | 92 | extern void falcon_remove_nic(struct efx_nic *efx); |
diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h index be3d2ba3b74..868ad1e703f 100644 --- a/drivers/net/sfc/net_driver.h +++ b/drivers/net/sfc/net_driver.h | |||
| @@ -160,6 +160,7 @@ struct efx_tx_buffer { | |||
| 160 | * @channel: The associated channel | 160 | * @channel: The associated channel |
| 161 | * @buffer: The software buffer ring | 161 | * @buffer: The software buffer ring |
| 162 | * @txd: The hardware descriptor ring | 162 | * @txd: The hardware descriptor ring |
| 163 | * @flushed: Used when handling queue flushing | ||
| 163 | * @read_count: Current read pointer. | 164 | * @read_count: Current read pointer. |
| 164 | * This is the number of buffers that have been removed from both rings. | 165 | * This is the number of buffers that have been removed from both rings. |
| 165 | * @stopped: Stopped count. | 166 | * @stopped: Stopped count. |
| @@ -192,6 +193,7 @@ struct efx_tx_queue { | |||
| 192 | struct efx_nic *nic; | 193 | struct efx_nic *nic; |
| 193 | struct efx_tx_buffer *buffer; | 194 | struct efx_tx_buffer *buffer; |
| 194 | struct efx_special_buffer txd; | 195 | struct efx_special_buffer txd; |
| 196 | bool flushed; | ||
| 195 | 197 | ||
| 196 | /* Members used mainly on the completion path */ | 198 | /* Members used mainly on the completion path */ |
| 197 | unsigned int read_count ____cacheline_aligned_in_smp; | 199 | unsigned int read_count ____cacheline_aligned_in_smp; |
| @@ -260,6 +262,7 @@ struct efx_rx_buffer { | |||
| 260 | * the remaining space in the allocation. | 262 | * the remaining space in the allocation. |
| 261 | * @buf_dma_addr: Page's DMA address. | 263 | * @buf_dma_addr: Page's DMA address. |
| 262 | * @buf_data: Page's host address. | 264 | * @buf_data: Page's host address. |
| 265 | * @flushed: Use when handling queue flushing | ||
| 263 | */ | 266 | */ |
| 264 | struct efx_rx_queue { | 267 | struct efx_rx_queue { |
| 265 | struct efx_nic *efx; | 268 | struct efx_nic *efx; |
| @@ -285,6 +288,7 @@ struct efx_rx_queue { | |||
| 285 | struct page *buf_page; | 288 | struct page *buf_page; |
| 286 | dma_addr_t buf_dma_addr; | 289 | dma_addr_t buf_dma_addr; |
| 287 | char *buf_data; | 290 | char *buf_data; |
| 291 | bool flushed; | ||
| 288 | }; | 292 | }; |
| 289 | 293 | ||
| 290 | /** | 294 | /** |
