aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-agn-lib.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-lib.c63
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
1441int 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 */
1477int 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}