diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-agn-lib.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 5f1e7d802cb..95666e565c7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c | |||
@@ -1435,3 +1435,66 @@ void iwl_free_tfds_in_queue(struct iwl_priv *priv, | |||
1435 | priv->stations[sta_id].tid[tid].tfds_in_queue = 0; | 1435 | priv->stations[sta_id].tid[tid].tfds_in_queue = 0; |
1436 | } | 1436 | } |
1437 | } | 1437 | } |
1438 | |||
1439 | #define IWL_FLUSH_WAIT_MS 2000 | ||
1440 | |||
1441 | int iwlagn_wait_tx_queue_empty(struct iwl_priv *priv) | ||
1442 | { | ||
1443 | struct iwl_tx_queue *txq; | ||
1444 | struct iwl_queue *q; | ||
1445 | int cnt; | ||
1446 | unsigned long now = jiffies; | ||
1447 | int ret = 0; | ||
1448 | |||
1449 | /* waiting for all the tx frames complete might take a while */ | ||
1450 | for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) { | ||
1451 | if (cnt == IWL_CMD_QUEUE_NUM) | ||
1452 | continue; | ||
1453 | txq = &priv->txq[cnt]; | ||
1454 | q = &txq->q; | ||
1455 | while (q->read_ptr != q->write_ptr && !time_after(jiffies, | ||
1456 | now + msecs_to_jiffies(IWL_FLUSH_WAIT_MS))) | ||
1457 | msleep(1); | ||
1458 | |||
1459 | if (q->read_ptr != q->write_ptr) { | ||
1460 | IWL_ERR(priv, "fail to flush all tx fifo queues\n"); | ||
1461 | ret = -ETIMEDOUT; | ||
1462 | break; | ||
1463 | } | ||
1464 | } | ||
1465 | return ret; | ||
1466 | } | ||
1467 | |||
1468 | #define IWL_TX_QUEUE_MSK 0xfffff | ||
1469 | |||
1470 | /** | ||
1471 | * iwlagn_txfifo_flush: send REPLY_TXFIFO_FLUSH command to uCode | ||
1472 | * | ||
1473 | * pre-requirements: | ||
1474 | * 1. acquire mutex before calling | ||
1475 | * 2. make sure rf is on and not in exit state | ||
1476 | */ | ||
1477 | int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control) | ||
1478 | { | ||
1479 | struct iwl_txfifo_flush_cmd flush_cmd; | ||
1480 | struct iwl_host_cmd cmd = { | ||
1481 | .id = REPLY_TXFIFO_FLUSH, | ||
1482 | .len = sizeof(struct iwl_txfifo_flush_cmd), | ||
1483 | .flags = CMD_SYNC, | ||
1484 | .data = &flush_cmd, | ||
1485 | }; | ||
1486 | |||
1487 | might_sleep(); | ||
1488 | |||
1489 | memset(&flush_cmd, 0, sizeof(flush_cmd)); | ||
1490 | flush_cmd.fifo_control = IWL_TX_FIFO_VO_MSK | IWL_TX_FIFO_VI_MSK | | ||
1491 | IWL_TX_FIFO_BE_MSK | IWL_TX_FIFO_BK_MSK; | ||
1492 | if (priv->cfg->sku & IWL_SKU_N) | ||
1493 | flush_cmd.fifo_control |= IWL_AGG_TX_QUEUE_MSK; | ||
1494 | |||
1495 | IWL_DEBUG_INFO(priv, "fifo queue control: 0X%x\n", | ||
1496 | flush_cmd.fifo_control); | ||
1497 | flush_cmd.flush_control = cpu_to_le16(flush_control); | ||
1498 | |||
1499 | return iwl_send_cmd(priv, &cmd); | ||
1500 | } | ||