aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/internal.h29
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/trans.c35
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/tx.c71
3 files changed, 82 insertions, 53 deletions
diff --git a/drivers/net/wireless/iwlwifi/pcie/internal.h b/drivers/net/wireless/iwlwifi/pcie/internal.h
index 9dfee7ed2e3e..809052442e91 100644
--- a/drivers/net/wireless/iwlwifi/pcie/internal.h
+++ b/drivers/net/wireless/iwlwifi/pcie/internal.h
@@ -262,6 +262,7 @@ iwl_pcie_get_scratchbuf_dma(struct iwl_txq *txq, int idx)
262 * @rx_page_order: page order for receive buffer size 262 * @rx_page_order: page order for receive buffer size
263 * @wd_timeout: queue watchdog timeout (jiffies) 263 * @wd_timeout: queue watchdog timeout (jiffies)
264 * @reg_lock: protect hw register access 264 * @reg_lock: protect hw register access
265 * @cmd_in_flight: true when we have a host command in flight
265 */ 266 */
266struct iwl_trans_pcie { 267struct iwl_trans_pcie {
267 struct iwl_rxq rxq; 268 struct iwl_rxq rxq;
@@ -310,6 +311,7 @@ struct iwl_trans_pcie {
310 311
311 /*protect hw register */ 312 /*protect hw register */
312 spinlock_t reg_lock; 313 spinlock_t reg_lock;
314 bool cmd_in_flight;
313}; 315};
314 316
315#define IWL_TRANS_GET_PCIE_TRANS(_iwl_trans) \ 317#define IWL_TRANS_GET_PCIE_TRANS(_iwl_trans) \
@@ -459,4 +461,31 @@ static inline bool iwl_is_rfkill_set(struct iwl_trans *trans)
459 CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW); 461 CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW);
460} 462}
461 463
464static inline void __iwl_trans_pcie_set_bits_mask(struct iwl_trans *trans,
465 u32 reg, u32 mask, u32 value)
466{
467 u32 v;
468
469#ifdef CONFIG_IWLWIFI_DEBUG
470 WARN_ON_ONCE(value & ~mask);
471#endif
472
473 v = iwl_read32(trans, reg);
474 v &= ~mask;
475 v |= value;
476 iwl_write32(trans, reg, v);
477}
478
479static inline void __iwl_trans_pcie_clear_bit(struct iwl_trans *trans,
480 u32 reg, u32 mask)
481{
482 __iwl_trans_pcie_set_bits_mask(trans, reg, mask, 0);
483}
484
485static inline void __iwl_trans_pcie_set_bit(struct iwl_trans *trans,
486 u32 reg, u32 mask)
487{
488 __iwl_trans_pcie_set_bits_mask(trans, reg, mask, mask);
489}
490
462#endif /* __iwl_trans_int_pcie_h__ */ 491#endif /* __iwl_trans_int_pcie_h__ */
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c
index 9a07cf3062ea..d9ccb4edc602 100644
--- a/drivers/net/wireless/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/iwlwifi/pcie/trans.c
@@ -75,33 +75,6 @@
75#include "iwl-agn-hw.h" 75#include "iwl-agn-hw.h"
76#include "internal.h" 76#include "internal.h"
77 77
78static void __iwl_trans_pcie_set_bits_mask(struct iwl_trans *trans,
79 u32 reg, u32 mask, u32 value)
80{
81 u32 v;
82
83#ifdef CONFIG_IWLWIFI_DEBUG
84 WARN_ON_ONCE(value & ~mask);
85#endif
86
87 v = iwl_read32(trans, reg);
88 v &= ~mask;
89 v |= value;
90 iwl_write32(trans, reg, v);
91}
92
93static inline void __iwl_trans_pcie_clear_bit(struct iwl_trans *trans,
94 u32 reg, u32 mask)
95{
96 __iwl_trans_pcie_set_bits_mask(trans, reg, mask, 0);
97}
98
99static inline void __iwl_trans_pcie_set_bit(struct iwl_trans *trans,
100 u32 reg, u32 mask)
101{
102 __iwl_trans_pcie_set_bits_mask(trans, reg, mask, mask);
103}
104
105static void iwl_pcie_set_pwr(struct iwl_trans *trans, bool vaux) 78static void iwl_pcie_set_pwr(struct iwl_trans *trans, bool vaux)
106{ 79{
107 if (vaux && pci_pme_capable(to_pci_dev(trans->dev), PCI_D3cold)) 80 if (vaux && pci_pme_capable(to_pci_dev(trans->dev), PCI_D3cold))
@@ -929,6 +902,9 @@ static bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans, bool silent,
929 902
930 spin_lock_irqsave(&trans_pcie->reg_lock, *flags); 903 spin_lock_irqsave(&trans_pcie->reg_lock, *flags);
931 904
905 if (trans_pcie->cmd_in_flight)
906 goto out;
907
932 /* this bit wakes up the NIC */ 908 /* this bit wakes up the NIC */
933 __iwl_trans_pcie_set_bit(trans, CSR_GP_CNTRL, 909 __iwl_trans_pcie_set_bit(trans, CSR_GP_CNTRL,
934 CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); 910 CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
@@ -968,6 +944,7 @@ static bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans, bool silent,
968 } 944 }
969 } 945 }
970 946
947out:
971 /* 948 /*
972 * Fool sparse by faking we release the lock - sparse will 949 * Fool sparse by faking we release the lock - sparse will
973 * track nic_access anyway. 950 * track nic_access anyway.
@@ -989,6 +966,9 @@ static void iwl_trans_pcie_release_nic_access(struct iwl_trans *trans,
989 */ 966 */
990 __acquire(&trans_pcie->reg_lock); 967 __acquire(&trans_pcie->reg_lock);
991 968
969 if (trans_pcie->cmd_in_flight)
970 goto out;
971
992 __iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL, 972 __iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL,
993 CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); 973 CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
994 /* 974 /*
@@ -998,6 +978,7 @@ static void iwl_trans_pcie_release_nic_access(struct iwl_trans *trans,
998 * scheduled on different CPUs (after we drop reg_lock). 978 * scheduled on different CPUs (after we drop reg_lock).
999 */ 979 */
1000 mmiowb(); 980 mmiowb();
981out:
1001 spin_unlock_irqrestore(&trans_pcie->reg_lock, *flags); 982 spin_unlock_irqrestore(&trans_pcie->reg_lock, *flags);
1002} 983}
1003 984
diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c
index b49a185355e4..2417af9ad2c6 100644
--- a/drivers/net/wireless/iwlwifi/pcie/tx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/tx.c
@@ -1001,6 +1001,7 @@ static void iwl_pcie_cmdq_reclaim(struct iwl_trans *trans, int txq_id, int idx)
1001 struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 1001 struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
1002 struct iwl_txq *txq = &trans_pcie->txq[txq_id]; 1002 struct iwl_txq *txq = &trans_pcie->txq[txq_id];
1003 struct iwl_queue *q = &txq->q; 1003 struct iwl_queue *q = &txq->q;
1004 unsigned long flags;
1004 int nfreed = 0; 1005 int nfreed = 0;
1005 1006
1006 lockdep_assert_held(&txq->lock); 1007 lockdep_assert_held(&txq->lock);
@@ -1023,6 +1024,16 @@ static void iwl_pcie_cmdq_reclaim(struct iwl_trans *trans, int txq_id, int idx)
1023 } 1024 }
1024 } 1025 }
1025 1026
1027 if (q->read_ptr == q->write_ptr) {
1028 spin_lock_irqsave(&trans_pcie->reg_lock, flags);
1029 WARN_ON(!trans_pcie->cmd_in_flight);
1030 trans_pcie->cmd_in_flight = false;
1031 __iwl_trans_pcie_clear_bit(trans,
1032 CSR_GP_CNTRL,
1033 CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
1034 spin_unlock_irqrestore(&trans_pcie->reg_lock, flags);
1035 }
1036
1026 iwl_pcie_txq_progress(trans_pcie, txq); 1037 iwl_pcie_txq_progress(trans_pcie, txq);
1027} 1038}
1028 1039
@@ -1174,12 +1185,13 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
1174 struct iwl_queue *q = &txq->q; 1185 struct iwl_queue *q = &txq->q;
1175 struct iwl_device_cmd *out_cmd; 1186 struct iwl_device_cmd *out_cmd;
1176 struct iwl_cmd_meta *out_meta; 1187 struct iwl_cmd_meta *out_meta;
1188 unsigned long flags;
1177 void *dup_buf = NULL; 1189 void *dup_buf = NULL;
1178 dma_addr_t phys_addr; 1190 dma_addr_t phys_addr;
1179 int idx; 1191 int idx;
1180 u16 copy_size, cmd_size, scratch_size; 1192 u16 copy_size, cmd_size, scratch_size;
1181 bool had_nocopy = false; 1193 bool had_nocopy = false;
1182 int i; 1194 int i, ret;
1183 u32 cmd_pos; 1195 u32 cmd_pos;
1184 const u8 *cmddata[IWL_MAX_CMD_TBS_PER_TFD]; 1196 const u8 *cmddata[IWL_MAX_CMD_TBS_PER_TFD];
1185 u16 cmdlen[IWL_MAX_CMD_TBS_PER_TFD]; 1197 u16 cmdlen[IWL_MAX_CMD_TBS_PER_TFD];
@@ -1377,10 +1389,38 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
1377 if (q->read_ptr == q->write_ptr && trans_pcie->wd_timeout) 1389 if (q->read_ptr == q->write_ptr && trans_pcie->wd_timeout)
1378 mod_timer(&txq->stuck_timer, jiffies + trans_pcie->wd_timeout); 1390 mod_timer(&txq->stuck_timer, jiffies + trans_pcie->wd_timeout);
1379 1391
1392 spin_lock_irqsave(&trans_pcie->reg_lock, flags);
1393
1394 /*
1395 * wake up the NIC to make sure that the firmware will see the host
1396 * command - we will let the NIC sleep once all the host commands
1397 * returned.
1398 */
1399 if (!trans_pcie->cmd_in_flight) {
1400 trans_pcie->cmd_in_flight = true;
1401 __iwl_trans_pcie_set_bit(trans, CSR_GP_CNTRL,
1402 CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
1403 ret = iwl_poll_bit(trans, CSR_GP_CNTRL,
1404 CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN,
1405 (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY |
1406 CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP),
1407 15000);
1408 if (ret < 0) {
1409 __iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL,
1410 CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
1411 spin_unlock_irqrestore(&trans_pcie->reg_lock, flags);
1412 trans_pcie->cmd_in_flight = false;
1413 idx = -EIO;
1414 goto out;
1415 }
1416 }
1417
1380 /* Increment and update queue's write index */ 1418 /* Increment and update queue's write index */
1381 q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); 1419 q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
1382 iwl_pcie_txq_inc_wr_ptr(trans, txq); 1420 iwl_pcie_txq_inc_wr_ptr(trans, txq);
1383 1421
1422 spin_unlock_irqrestore(&trans_pcie->reg_lock, flags);
1423
1384 out: 1424 out:
1385 spin_unlock_bh(&txq->lock); 1425 spin_unlock_bh(&txq->lock);
1386 free_dup_buf: 1426 free_dup_buf:
@@ -1462,7 +1502,6 @@ void iwl_pcie_hcmd_complete(struct iwl_trans *trans,
1462} 1502}
1463 1503
1464#define HOST_COMPLETE_TIMEOUT (2 * HZ) 1504#define HOST_COMPLETE_TIMEOUT (2 * HZ)
1465#define COMMAND_POKE_TIMEOUT (HZ / 10)
1466 1505
1467static int iwl_pcie_send_hcmd_async(struct iwl_trans *trans, 1506static int iwl_pcie_send_hcmd_async(struct iwl_trans *trans,
1468 struct iwl_host_cmd *cmd) 1507 struct iwl_host_cmd *cmd)
@@ -1490,7 +1529,6 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans,
1490 struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 1529 struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
1491 int cmd_idx; 1530 int cmd_idx;
1492 int ret; 1531 int ret;
1493 int timeout = HOST_COMPLETE_TIMEOUT;
1494 1532
1495 IWL_DEBUG_INFO(trans, "Attempting to send sync command %s\n", 1533 IWL_DEBUG_INFO(trans, "Attempting to send sync command %s\n",
1496 get_cmd_string(trans_pcie, cmd->id)); 1534 get_cmd_string(trans_pcie, cmd->id));
@@ -1514,29 +1552,10 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans,
1514 return ret; 1552 return ret;
1515 } 1553 }
1516 1554
1517 while (timeout > 0) { 1555 ret = wait_event_timeout(trans_pcie->wait_command_queue,
1518 unsigned long flags; 1556 !test_bit(STATUS_SYNC_HCMD_ACTIVE,
1519 1557 &trans->status),
1520 timeout -= COMMAND_POKE_TIMEOUT; 1558 HOST_COMPLETE_TIMEOUT);
1521 ret = wait_event_timeout(trans_pcie->wait_command_queue,
1522 !test_bit(STATUS_SYNC_HCMD_ACTIVE,
1523 &trans->status),
1524 COMMAND_POKE_TIMEOUT);
1525 if (ret)
1526 break;
1527 /* poke the device - it may have lost the command */
1528 if (iwl_trans_grab_nic_access(trans, true, &flags)) {
1529 iwl_trans_release_nic_access(trans, &flags);
1530 IWL_DEBUG_INFO(trans,
1531 "Tried to wake NIC for command %s\n",
1532 get_cmd_string(trans_pcie, cmd->id));
1533 } else {
1534 IWL_ERR(trans, "Failed to poke NIC for command %s\n",
1535 get_cmd_string(trans_pcie, cmd->id));
1536 break;
1537 }
1538 }
1539
1540 if (!ret) { 1559 if (!ret) {
1541 struct iwl_txq *txq = &trans_pcie->txq[trans_pcie->cmd_queue]; 1560 struct iwl_txq *txq = &trans_pcie->txq[trans_pcie->cmd_queue];
1542 struct iwl_queue *q = &txq->q; 1561 struct iwl_queue *q = &txq->q;