aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2012-02-05 16:55:11 -0500
committerWey-Yi Guy <wey-yi.w.guy@intel.com>2012-02-17 13:11:52 -0500
commit7b11488fbbbe06ada39a396dec16532db8c933e6 (patch)
treea826ecf0ced428dffaf06cf3a0d4a0ae3e38ecc0 /drivers/net
parent1ee158d83853a9f5c1465be56d56ff56e6698e92 (diff)
iwlwifi: give PCIe its own lock
Instead of using a global lock, the PCIe transport can use an own lock for its IRQ. This will make it possible to not disable IRQs for the shared lock. The lock is currently used throughout the code but this can be improved even further by splitting up the locking for the queues. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Reviewed-by: Wey-Yi W Guy <wey-yi.w.guy@intel.com>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c29
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans-pcie.c37
4 files changed, 40 insertions, 31 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h
index 561865f29d56..8c30fea8c2b3 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h
+++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h
@@ -230,6 +230,7 @@ struct iwl_trans_pcie {
230 struct tasklet_struct irq_tasklet; 230 struct tasklet_struct irq_tasklet;
231 struct isr_statistics isr_stats; 231 struct isr_statistics isr_stats;
232 232
233 spinlock_t irq_lock;
233 u32 inta_mask; 234 u32 inta_mask;
234 u32 scd_base_addr; 235 u32 scd_base_addr;
235 struct iwl_dma_ptr scd_bc_tbls; 236 struct iwl_dma_ptr scd_bc_tbls;
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c
index 1b11cfec5da6..e06342656cea 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c
@@ -331,13 +331,14 @@ static void iwlagn_rx_allocate(struct iwl_trans *trans, gfp_t priority)
331 331
332void iwlagn_rx_replenish(struct iwl_trans *trans) 332void iwlagn_rx_replenish(struct iwl_trans *trans)
333{ 333{
334 struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
334 unsigned long flags; 335 unsigned long flags;
335 336
336 iwlagn_rx_allocate(trans, GFP_KERNEL); 337 iwlagn_rx_allocate(trans, GFP_KERNEL);
337 338
338 spin_lock_irqsave(&trans->shrd->lock, flags); 339 spin_lock_irqsave(&trans_pcie->irq_lock, flags);
339 iwlagn_rx_queue_restock(trans); 340 iwlagn_rx_queue_restock(trans);
340 spin_unlock_irqrestore(&trans->shrd->lock, flags); 341 spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
341} 342}
342 343
343static void iwlagn_rx_replenish_now(struct iwl_trans *trans) 344static void iwlagn_rx_replenish_now(struct iwl_trans *trans)
@@ -943,7 +944,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
943 struct isr_statistics *isr_stats = &trans_pcie->isr_stats; 944 struct isr_statistics *isr_stats = &trans_pcie->isr_stats;
944 945
945 946
946 spin_lock_irqsave(&trans->shrd->lock, flags); 947 spin_lock_irqsave(&trans_pcie->irq_lock, flags);
947 948
948 /* Ack/clear/reset pending uCode interrupts. 949 /* Ack/clear/reset pending uCode interrupts.
949 * Note: Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS, 950 * Note: Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS,
@@ -973,7 +974,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
973 /* saved interrupt in inta variable now we can reset trans_pcie->inta */ 974 /* saved interrupt in inta variable now we can reset trans_pcie->inta */
974 trans_pcie->inta = 0; 975 trans_pcie->inta = 0;
975 976
976 spin_unlock_irqrestore(&trans->shrd->lock, flags); 977 spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
977 978
978 /* Now service all interrupt bits discovered above. */ 979 /* Now service all interrupt bits discovered above. */
979 if (inta & CSR_INT_BIT_HW_ERR) { 980 if (inta & CSR_INT_BIT_HW_ERR) {
@@ -1226,7 +1227,7 @@ void iwl_reset_ict(struct iwl_trans *trans)
1226 if (!trans_pcie->ict_tbl) 1227 if (!trans_pcie->ict_tbl)
1227 return; 1228 return;
1228 1229
1229 spin_lock_irqsave(&trans->shrd->lock, flags); 1230 spin_lock_irqsave(&trans_pcie->irq_lock, flags);
1230 iwl_disable_interrupts(trans); 1231 iwl_disable_interrupts(trans);
1231 1232
1232 memset(trans_pcie->ict_tbl, 0, ICT_SIZE); 1233 memset(trans_pcie->ict_tbl, 0, ICT_SIZE);
@@ -1243,7 +1244,7 @@ void iwl_reset_ict(struct iwl_trans *trans)
1243 trans_pcie->ict_index = 0; 1244 trans_pcie->ict_index = 0;
1244 iwl_write32(trans, CSR_INT, trans_pcie->inta_mask); 1245 iwl_write32(trans, CSR_INT, trans_pcie->inta_mask);
1245 iwl_enable_interrupts(trans); 1246 iwl_enable_interrupts(trans);
1246 spin_unlock_irqrestore(&trans->shrd->lock, flags); 1247 spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
1247} 1248}
1248 1249
1249/* Device is going down disable ict interrupt usage */ 1250/* Device is going down disable ict interrupt usage */
@@ -1254,9 +1255,9 @@ void iwl_disable_ict(struct iwl_trans *trans)
1254 1255
1255 unsigned long flags; 1256 unsigned long flags;
1256 1257
1257 spin_lock_irqsave(&trans->shrd->lock, flags); 1258 spin_lock_irqsave(&trans_pcie->irq_lock, flags);
1258 trans_pcie->use_ict = false; 1259 trans_pcie->use_ict = false;
1259 spin_unlock_irqrestore(&trans->shrd->lock, flags); 1260 spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
1260} 1261}
1261 1262
1262static irqreturn_t iwl_isr(int irq, void *data) 1263static irqreturn_t iwl_isr(int irq, void *data)
@@ -1275,7 +1276,7 @@ static irqreturn_t iwl_isr(int irq, void *data)
1275 1276
1276 trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 1277 trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
1277 1278
1278 spin_lock_irqsave(&trans->shrd->lock, flags); 1279 spin_lock_irqsave(&trans_pcie->irq_lock, flags);
1279 1280
1280 /* Disable (but don't clear!) interrupts here to avoid 1281 /* Disable (but don't clear!) interrupts here to avoid
1281 * back-to-back ISRs and sporadic interrupts from our NIC. 1282 * back-to-back ISRs and sporadic interrupts from our NIC.
@@ -1319,7 +1320,7 @@ static irqreturn_t iwl_isr(int irq, void *data)
1319 iwl_enable_interrupts(trans); 1320 iwl_enable_interrupts(trans);
1320 1321
1321 unplugged: 1322 unplugged:
1322 spin_unlock_irqrestore(&trans->shrd->lock, flags); 1323 spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
1323 return IRQ_HANDLED; 1324 return IRQ_HANDLED;
1324 1325
1325 none: 1326 none:
@@ -1329,7 +1330,7 @@ static irqreturn_t iwl_isr(int irq, void *data)
1329 !trans_pcie->inta) 1330 !trans_pcie->inta)
1330 iwl_enable_interrupts(trans); 1331 iwl_enable_interrupts(trans);
1331 1332
1332 spin_unlock_irqrestore(&trans->shrd->lock, flags); 1333 spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
1333 return IRQ_NONE; 1334 return IRQ_NONE;
1334} 1335}
1335 1336
@@ -1363,7 +1364,7 @@ irqreturn_t iwl_isr_ict(int irq, void *data)
1363 1364
1364 trace_iwlwifi_dev_irq(priv(trans)); 1365 trace_iwlwifi_dev_irq(priv(trans));
1365 1366
1366 spin_lock_irqsave(&trans->shrd->lock, flags); 1367 spin_lock_irqsave(&trans_pcie->irq_lock, flags);
1367 1368
1368 /* Disable (but don't clear!) interrupts here to avoid 1369 /* Disable (but don't clear!) interrupts here to avoid
1369 * back-to-back ISRs and sporadic interrupts from our NIC. 1370 * back-to-back ISRs and sporadic interrupts from our NIC.
@@ -1434,7 +1435,7 @@ irqreturn_t iwl_isr_ict(int irq, void *data)
1434 iwl_enable_interrupts(trans); 1435 iwl_enable_interrupts(trans);
1435 } 1436 }
1436 1437
1437 spin_unlock_irqrestore(&trans->shrd->lock, flags); 1438 spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
1438 return IRQ_HANDLED; 1439 return IRQ_HANDLED;
1439 1440
1440 none: 1441 none:
@@ -1445,6 +1446,6 @@ irqreturn_t iwl_isr_ict(int irq, void *data)
1445 !trans_pcie->inta) 1446 !trans_pcie->inta)
1446 iwl_enable_interrupts(trans); 1447 iwl_enable_interrupts(trans);
1447 1448
1448 spin_unlock_irqrestore(&trans->shrd->lock, flags); 1449 spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
1449 return IRQ_NONE; 1450 return IRQ_NONE;
1450} 1451}
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c
index 08e0a7da48a9..a3cebd76dc0c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c
@@ -492,7 +492,7 @@ void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans,
492 492
493 ra_tid = BUILD_RAxTID(sta_id, tid); 493 ra_tid = BUILD_RAxTID(sta_id, tid);
494 494
495 spin_lock_irqsave(&trans->shrd->lock, flags); 495 spin_lock_irqsave(&trans_pcie->irq_lock, flags);
496 496
497 /* Stop this Tx queue before configuring it */ 497 /* Stop this Tx queue before configuring it */
498 iwlagn_tx_queue_stop_scheduler(trans, txq_id); 498 iwlagn_tx_queue_stop_scheduler(trans, txq_id);
@@ -532,7 +532,7 @@ void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans,
532 trans_pcie->txq[txq_id].sta_id = sta_id; 532 trans_pcie->txq[txq_id].sta_id = sta_id;
533 trans_pcie->txq[txq_id].tid = tid; 533 trans_pcie->txq[txq_id].tid = tid;
534 534
535 spin_unlock_irqrestore(&trans->shrd->lock, flags); 535 spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
536} 536}
537 537
538/* 538/*
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
index e8d1dbfa1aea..176063c4f781 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
+++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
@@ -219,10 +219,10 @@ static int iwl_rx_init(struct iwl_trans *trans)
219 219
220 iwl_trans_rx_hw_init(trans, rxq); 220 iwl_trans_rx_hw_init(trans, rxq);
221 221
222 spin_lock_irqsave(&trans->shrd->lock, flags); 222 spin_lock_irqsave(&trans_pcie->irq_lock, flags);
223 rxq->need_update = 1; 223 rxq->need_update = 1;
224 iwl_rx_queue_update_write_ptr(trans, rxq); 224 iwl_rx_queue_update_write_ptr(trans, rxq);
225 spin_unlock_irqrestore(&trans->shrd->lock, flags); 225 spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
226 226
227 return 0; 227 return 0;
228} 228}
@@ -585,7 +585,7 @@ static int iwl_tx_init(struct iwl_trans *trans)
585 alloc = true; 585 alloc = true;
586 } 586 }
587 587
588 spin_lock_irqsave(&trans->shrd->lock, flags); 588 spin_lock_irqsave(&trans_pcie->irq_lock, flags);
589 589
590 /* Turn off all Tx DMA fifos */ 590 /* Turn off all Tx DMA fifos */
591 iwl_write_prph(trans, SCD_TXFACT, 0); 591 iwl_write_prph(trans, SCD_TXFACT, 0);
@@ -594,7 +594,7 @@ static int iwl_tx_init(struct iwl_trans *trans)
594 iwl_write_direct32(trans, FH_KW_MEM_ADDR_REG, 594 iwl_write_direct32(trans, FH_KW_MEM_ADDR_REG,
595 trans_pcie->kw.dma >> 4); 595 trans_pcie->kw.dma >> 4);
596 596
597 spin_unlock_irqrestore(&trans->shrd->lock, flags); 597 spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
598 598
599 /* Alloc and init all Tx queues, including the command queue (#4/#9) */ 599 /* Alloc and init all Tx queues, including the command queue (#4/#9) */
600 for (txq_id = 0; txq_id < hw_params(trans).max_txq_num; txq_id++) { 600 for (txq_id = 0; txq_id < hw_params(trans).max_txq_num; txq_id++) {
@@ -803,17 +803,18 @@ static void iwl_apm_stop(struct iwl_trans *trans)
803 803
804static int iwl_nic_init(struct iwl_trans *trans) 804static int iwl_nic_init(struct iwl_trans *trans)
805{ 805{
806 struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
806 unsigned long flags; 807 unsigned long flags;
807 808
808 /* nic_init */ 809 /* nic_init */
809 spin_lock_irqsave(&trans->shrd->lock, flags); 810 spin_lock_irqsave(&trans_pcie->irq_lock, flags);
810 iwl_apm_init(trans); 811 iwl_apm_init(trans);
811 812
812 /* Set interrupt coalescing calibration timer to default (512 usecs) */ 813 /* Set interrupt coalescing calibration timer to default (512 usecs) */
813 iwl_write8(trans, CSR_INT_COALESCING, 814 iwl_write8(trans, CSR_INT_COALESCING,
814 IWL_HOST_INT_CALIB_TIMEOUT_DEF); 815 IWL_HOST_INT_CALIB_TIMEOUT_DEF);
815 816
816 spin_unlock_irqrestore(&trans->shrd->lock, flags); 817 spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
817 818
818 iwl_set_pwr_vmain(trans); 819 iwl_set_pwr_vmain(trans);
819 820
@@ -1078,10 +1079,15 @@ static int iwl_trans_pcie_start_fw(struct iwl_trans *trans, struct fw_img *fw)
1078 1079
1079/* 1080/*
1080 * Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask 1081 * Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask
1081 * must be called under priv->shrd->lock and mac access 1082 * must be called under the irq lock and with MAC access
1082 */ 1083 */
1083static void iwl_trans_txq_set_sched(struct iwl_trans *trans, u32 mask) 1084static void iwl_trans_txq_set_sched(struct iwl_trans *trans, u32 mask)
1084{ 1085{
1086 struct iwl_trans_pcie __maybe_unused *trans_pcie =
1087 IWL_TRANS_GET_PCIE_TRANS(trans);
1088
1089 lockdep_assert_held(&trans_pcie->irq_lock);
1090
1085 iwl_write_prph(trans, SCD_TXFACT, mask); 1091 iwl_write_prph(trans, SCD_TXFACT, mask);
1086} 1092}
1087 1093
@@ -1095,7 +1101,7 @@ static void iwl_tx_start(struct iwl_trans *trans)
1095 int i, chan; 1101 int i, chan;
1096 u32 reg_val; 1102 u32 reg_val;
1097 1103
1098 spin_lock_irqsave(&trans->shrd->lock, flags); 1104 spin_lock_irqsave(&trans_pcie->irq_lock, flags);
1099 1105
1100 trans_pcie->scd_base_addr = 1106 trans_pcie->scd_base_addr =
1101 iwl_read_prph(trans, SCD_SRAM_BASE_ADDR); 1107 iwl_read_prph(trans, SCD_SRAM_BASE_ADDR);
@@ -1191,7 +1197,7 @@ static void iwl_tx_start(struct iwl_trans *trans)
1191 fifo, 0); 1197 fifo, 0);
1192 } 1198 }
1193 1199
1194 spin_unlock_irqrestore(&trans->shrd->lock, flags); 1200 spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
1195 1201
1196 /* Enable L1-Active */ 1202 /* Enable L1-Active */
1197 iwl_clear_bits_prph(trans, APMG_PCIDEV_STT_REG, 1203 iwl_clear_bits_prph(trans, APMG_PCIDEV_STT_REG,
@@ -1214,7 +1220,7 @@ static int iwl_trans_tx_stop(struct iwl_trans *trans)
1214 struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 1220 struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
1215 1221
1216 /* Turn off all Tx DMA fifos */ 1222 /* Turn off all Tx DMA fifos */
1217 spin_lock_irqsave(&trans->shrd->lock, flags); 1223 spin_lock_irqsave(&trans_pcie->irq_lock, flags);
1218 1224
1219 iwl_trans_txq_set_sched(trans, 0); 1225 iwl_trans_txq_set_sched(trans, 0);
1220 1226
@@ -1230,7 +1236,7 @@ static int iwl_trans_tx_stop(struct iwl_trans *trans)
1230 iwl_read_direct32(trans, 1236 iwl_read_direct32(trans,
1231 FH_TSSR_TX_STATUS_REG)); 1237 FH_TSSR_TX_STATUS_REG));
1232 } 1238 }
1233 spin_unlock_irqrestore(&trans->shrd->lock, flags); 1239 spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
1234 1240
1235 if (!trans_pcie->txq) { 1241 if (!trans_pcie->txq) {
1236 IWL_WARN(trans, "Stopping tx queues that aren't allocated..."); 1242 IWL_WARN(trans, "Stopping tx queues that aren't allocated...");
@@ -1250,9 +1256,9 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
1250 struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 1256 struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
1251 1257
1252 /* tell the device to stop sending interrupts */ 1258 /* tell the device to stop sending interrupts */
1253 spin_lock_irqsave(&trans->shrd->lock, flags); 1259 spin_lock_irqsave(&trans_pcie->irq_lock, flags);
1254 iwl_disable_interrupts(trans); 1260 iwl_disable_interrupts(trans);
1255 spin_unlock_irqrestore(&trans->shrd->lock, flags); 1261 spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
1256 1262
1257 /* device going down, Stop using ICT table */ 1263 /* device going down, Stop using ICT table */
1258 iwl_disable_ict(trans); 1264 iwl_disable_ict(trans);
@@ -1285,9 +1291,9 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
1285 /* Upon stop, the APM issues an interrupt if HW RF kill is set. 1291 /* Upon stop, the APM issues an interrupt if HW RF kill is set.
1286 * Clean again the interrupt here 1292 * Clean again the interrupt here
1287 */ 1293 */
1288 spin_lock_irqsave(&trans->shrd->lock, flags); 1294 spin_lock_irqsave(&trans_pcie->irq_lock, flags);
1289 iwl_disable_interrupts(trans); 1295 iwl_disable_interrupts(trans);
1290 spin_unlock_irqrestore(&trans->shrd->lock, flags); 1296 spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
1291 1297
1292 /* wait to make sure we flush pending tasklet*/ 1298 /* wait to make sure we flush pending tasklet*/
1293 synchronize_irq(trans->irq); 1299 synchronize_irq(trans->irq);
@@ -2261,6 +2267,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct iwl_shared *shrd,
2261 trans->shrd = shrd; 2267 trans->shrd = shrd;
2262 trans_pcie->trans = trans; 2268 trans_pcie->trans = trans;
2263 spin_lock_init(&trans->hcmd_lock); 2269 spin_lock_init(&trans->hcmd_lock);
2270 spin_lock_init(&trans_pcie->irq_lock);
2264 2271
2265 /* W/A - seems to solve weird behavior. We need to remove this if we 2272 /* W/A - seems to solve weird behavior. We need to remove this if we
2266 * don't want to stay in L1 all the time. This wastes a lot of power */ 2273 * don't want to stay in L1 all the time. This wastes a lot of power */