diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn.c | 12 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-dev.h | 13 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-helpers.h | 21 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h | 45 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c | 333 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-trans.c | 50 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-trans.h | 13 |
7 files changed, 255 insertions, 232 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 660abede935c..ca6bb7b1c96d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -3627,7 +3627,6 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops, | |||
3627 | 3627 | ||
3628 | IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n"); | 3628 | IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n"); |
3629 | priv->cfg = cfg; | 3629 | priv->cfg = cfg; |
3630 | priv->inta_mask = CSR_INI_SET_MASK; | ||
3631 | 3630 | ||
3632 | /* is antenna coupling more than 35dB ? */ | 3631 | /* is antenna coupling more than 35dB ? */ |
3633 | priv->bt_ant_couple_ok = | 3632 | priv->bt_ant_couple_ok = |
@@ -3771,8 +3770,6 @@ out: | |||
3771 | 3770 | ||
3772 | void __devexit iwl_remove(struct iwl_priv * priv) | 3771 | void __devexit iwl_remove(struct iwl_priv * priv) |
3773 | { | 3772 | { |
3774 | unsigned long flags; | ||
3775 | |||
3776 | wait_for_completion(&priv->firmware_loading_complete); | 3773 | wait_for_completion(&priv->firmware_loading_complete); |
3777 | 3774 | ||
3778 | IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n"); | 3775 | IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n"); |
@@ -3801,13 +3798,8 @@ void __devexit iwl_remove(struct iwl_priv * priv) | |||
3801 | iwl_tt_exit(priv); | 3798 | iwl_tt_exit(priv); |
3802 | 3799 | ||
3803 | /* make sure we flush any pending irq or | 3800 | /* make sure we flush any pending irq or |
3804 | * tasklet for the driver | 3801 | * tasklet for the driver */ |
3805 | */ | 3802 | iwl_trans_disable_sync_irq(trans(priv)); |
3806 | spin_lock_irqsave(&priv->shrd->lock, flags); | ||
3807 | iwl_disable_interrupts(priv); | ||
3808 | spin_unlock_irqrestore(&priv->shrd->lock, flags); | ||
3809 | |||
3810 | iwl_trans_sync_irq(trans(priv)); | ||
3811 | 3803 | ||
3812 | iwl_dealloc_ucode(priv); | 3804 | iwl_dealloc_ucode(priv); |
3813 | 3805 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 8a8fc74eebca..40a01c0e4f30 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h | |||
@@ -1259,6 +1259,7 @@ struct iwl_priv { | |||
1259 | struct traffic_stats rx_stats; | 1259 | struct traffic_stats rx_stats; |
1260 | 1260 | ||
1261 | /* counts interrupts */ | 1261 | /* counts interrupts */ |
1262 | /* TODO: move to the transport layer */ | ||
1262 | struct isr_statistics isr_stats; | 1263 | struct isr_statistics isr_stats; |
1263 | 1264 | ||
1264 | struct iwl_power_mgr power_data; | 1265 | struct iwl_power_mgr power_data; |
@@ -1315,14 +1316,6 @@ struct iwl_priv { | |||
1315 | } accum_stats, delta_stats, max_delta_stats; | 1316 | } accum_stats, delta_stats, max_delta_stats; |
1316 | #endif | 1317 | #endif |
1317 | 1318 | ||
1318 | /* INT ICT Table */ | ||
1319 | __le32 *ict_tbl; | ||
1320 | void *ict_tbl_vir; | ||
1321 | dma_addr_t ict_tbl_dma; | ||
1322 | dma_addr_t aligned_ict_tbl_dma; | ||
1323 | int ict_index; | ||
1324 | u32 inta; | ||
1325 | bool use_ict; | ||
1326 | /* | 1319 | /* |
1327 | * reporting the number of tids has AGG on. 0 means | 1320 | * reporting the number of tids has AGG on. 0 means |
1328 | * no AGGREGATION | 1321 | * no AGGREGATION |
@@ -1379,8 +1372,6 @@ struct iwl_priv { | |||
1379 | struct iwl_rxon_context *cur_rssi_ctx; | 1372 | struct iwl_rxon_context *cur_rssi_ctx; |
1380 | bool bt_is_sco; | 1373 | bool bt_is_sco; |
1381 | 1374 | ||
1382 | u32 inta_mask; | ||
1383 | |||
1384 | struct work_struct restart; | 1375 | struct work_struct restart; |
1385 | struct work_struct scan_completed; | 1376 | struct work_struct scan_completed; |
1386 | struct work_struct abort_scan; | 1377 | struct work_struct abort_scan; |
@@ -1398,8 +1389,6 @@ struct iwl_priv { | |||
1398 | struct work_struct bt_full_concurrency; | 1389 | struct work_struct bt_full_concurrency; |
1399 | struct work_struct bt_runtime_config; | 1390 | struct work_struct bt_runtime_config; |
1400 | 1391 | ||
1401 | struct tasklet_struct irq_tasklet; | ||
1402 | |||
1403 | struct delayed_work scan_check; | 1392 | struct delayed_work scan_check; |
1404 | 1393 | ||
1405 | /* TX Power */ | 1394 | /* TX Power */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h index d053ed7ef794..09ed7af19889 100644 --- a/drivers/net/wireless/iwlwifi/iwl-helpers.h +++ b/drivers/net/wireless/iwlwifi/iwl-helpers.h | |||
@@ -132,33 +132,12 @@ static inline void iwl_wake_any_queue(struct iwl_priv *priv, | |||
132 | 132 | ||
133 | #define ieee80211_wake_queue DO_NOT_USE_ieee80211_wake_queue | 133 | #define ieee80211_wake_queue DO_NOT_USE_ieee80211_wake_queue |
134 | 134 | ||
135 | static inline void iwl_disable_interrupts(struct iwl_priv *priv) | ||
136 | { | ||
137 | clear_bit(STATUS_INT_ENABLED, &priv->shrd->status); | ||
138 | |||
139 | /* disable interrupts from uCode/NIC to host */ | ||
140 | iwl_write32(priv, CSR_INT_MASK, 0x00000000); | ||
141 | |||
142 | /* acknowledge/clear/reset any interrupts still pending | ||
143 | * from uCode or flow handler (Rx/Tx DMA) */ | ||
144 | iwl_write32(priv, CSR_INT, 0xffffffff); | ||
145 | iwl_write32(priv, CSR_FH_INT_STATUS, 0xffffffff); | ||
146 | IWL_DEBUG_ISR(priv, "Disabled interrupts\n"); | ||
147 | } | ||
148 | |||
149 | static inline void iwl_enable_rfkill_int(struct iwl_priv *priv) | 135 | static inline void iwl_enable_rfkill_int(struct iwl_priv *priv) |
150 | { | 136 | { |
151 | IWL_DEBUG_ISR(priv, "Enabling rfkill interrupt\n"); | 137 | IWL_DEBUG_ISR(priv, "Enabling rfkill interrupt\n"); |
152 | iwl_write32(priv, CSR_INT_MASK, CSR_INT_BIT_RF_KILL); | 138 | iwl_write32(priv, CSR_INT_MASK, CSR_INT_BIT_RF_KILL); |
153 | } | 139 | } |
154 | 140 | ||
155 | static inline void iwl_enable_interrupts(struct iwl_priv *priv) | ||
156 | { | ||
157 | IWL_DEBUG_ISR(priv, "Enabling interrupts\n"); | ||
158 | set_bit(STATUS_INT_ENABLED, &priv->shrd->status); | ||
159 | iwl_write32(priv, CSR_INT_MASK, priv->inta_mask); | ||
160 | } | ||
161 | |||
162 | /** | 141 | /** |
163 | * iwl_beacon_time_mask_low - mask of lower 32 bit of beacon time | 142 | * iwl_beacon_time_mask_low - mask of lower 32 bit of beacon time |
164 | * @priv -- pointer to iwl_priv data structure | 143 | * @priv -- pointer to iwl_priv data structure |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h index 1d80515c1dbf..7e2f954c95f2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h | |||
@@ -78,6 +78,18 @@ struct iwl_trans_pcie { | |||
78 | struct iwl_rx_queue rxq; | 78 | struct iwl_rx_queue rxq; |
79 | struct work_struct rx_replenish; | 79 | struct work_struct rx_replenish; |
80 | struct iwl_trans *trans; | 80 | struct iwl_trans *trans; |
81 | |||
82 | /* INT ICT Table */ | ||
83 | __le32 *ict_tbl; | ||
84 | void *ict_tbl_vir; | ||
85 | dma_addr_t ict_tbl_dma; | ||
86 | dma_addr_t aligned_ict_tbl_dma; | ||
87 | int ict_index; | ||
88 | u32 inta; | ||
89 | bool use_ict; | ||
90 | struct tasklet_struct irq_tasklet; | ||
91 | |||
92 | u32 inta_mask; | ||
81 | }; | 93 | }; |
82 | 94 | ||
83 | #define IWL_TRANS_GET_PCIE_TRANS(_iwl_trans) \ | 95 | #define IWL_TRANS_GET_PCIE_TRANS(_iwl_trans) \ |
@@ -87,7 +99,7 @@ struct iwl_trans_pcie { | |||
87 | * RX | 99 | * RX |
88 | ******************************************************/ | 100 | ******************************************************/ |
89 | void iwl_bg_rx_replenish(struct work_struct *data); | 101 | void iwl_bg_rx_replenish(struct work_struct *data); |
90 | void iwl_irq_tasklet(struct iwl_priv *priv); | 102 | void iwl_irq_tasklet(struct iwl_trans *trans); |
91 | void iwlagn_rx_replenish(struct iwl_trans *trans); | 103 | void iwlagn_rx_replenish(struct iwl_trans *trans); |
92 | void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans, | 104 | void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans, |
93 | struct iwl_rx_queue *q); | 105 | struct iwl_rx_queue *q); |
@@ -96,12 +108,11 @@ void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans, | |||
96 | * ICT | 108 | * ICT |
97 | ******************************************************/ | 109 | ******************************************************/ |
98 | int iwl_reset_ict(struct iwl_priv *priv); | 110 | int iwl_reset_ict(struct iwl_priv *priv); |
99 | void iwl_disable_ict(struct iwl_priv *priv); | 111 | void iwl_disable_ict(struct iwl_trans *trans); |
100 | int iwl_alloc_isr_ict(struct iwl_priv *priv); | 112 | int iwl_alloc_isr_ict(struct iwl_trans *trans); |
101 | void iwl_free_isr_ict(struct iwl_priv *priv); | 113 | void iwl_free_isr_ict(struct iwl_trans *trans); |
102 | irqreturn_t iwl_isr_ict(int irq, void *data); | 114 | irqreturn_t iwl_isr_ict(int irq, void *data); |
103 | 115 | ||
104 | |||
105 | /***************************************************** | 116 | /***************************************************** |
106 | * TX / HCMD | 117 | * TX / HCMD |
107 | ******************************************************/ | 118 | ******************************************************/ |
@@ -130,4 +141,28 @@ void iwl_trans_tx_queue_set_status(struct iwl_priv *priv, | |||
130 | void iwl_trans_pcie_txq_agg_setup(struct iwl_priv *priv, int sta_id, int tid, | 141 | void iwl_trans_pcie_txq_agg_setup(struct iwl_priv *priv, int sta_id, int tid, |
131 | int frame_limit); | 142 | int frame_limit); |
132 | 143 | ||
144 | static inline void iwl_disable_interrupts(struct iwl_trans *trans) | ||
145 | { | ||
146 | clear_bit(STATUS_INT_ENABLED, &trans->shrd->status); | ||
147 | |||
148 | /* disable interrupts from uCode/NIC to host */ | ||
149 | iwl_write32(priv(trans), CSR_INT_MASK, 0x00000000); | ||
150 | |||
151 | /* acknowledge/clear/reset any interrupts still pending | ||
152 | * from uCode or flow handler (Rx/Tx DMA) */ | ||
153 | iwl_write32(priv(trans), CSR_INT, 0xffffffff); | ||
154 | iwl_write32(priv(trans), CSR_FH_INT_STATUS, 0xffffffff); | ||
155 | IWL_DEBUG_ISR(trans, "Disabled interrupts\n"); | ||
156 | } | ||
157 | |||
158 | static inline void iwl_enable_interrupts(struct iwl_trans *trans) | ||
159 | { | ||
160 | struct iwl_trans_pcie *trans_pcie = | ||
161 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
162 | |||
163 | IWL_DEBUG_ISR(trans, "Enabling interrupts\n"); | ||
164 | set_bit(STATUS_INT_ENABLED, &trans->shrd->status); | ||
165 | iwl_write32(priv(trans), CSR_INT_MASK, trans_pcie->inta_mask); | ||
166 | } | ||
167 | |||
133 | #endif /* __iwl_trans_int_pcie_h__ */ | 168 | #endif /* __iwl_trans_int_pcie_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c index fb06acf83fc6..15e2645c2fb3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c | |||
@@ -497,7 +497,7 @@ static void iwl_rx_handle(struct iwl_trans *trans) | |||
497 | } | 497 | } |
498 | 498 | ||
499 | /* tasklet for iwlagn interrupt */ | 499 | /* tasklet for iwlagn interrupt */ |
500 | void iwl_irq_tasklet(struct iwl_priv *priv) | 500 | void iwl_irq_tasklet(struct iwl_trans *trans) |
501 | { | 501 | { |
502 | u32 inta = 0; | 502 | u32 inta = 0; |
503 | u32 handled = 0; | 503 | u32 handled = 0; |
@@ -507,7 +507,10 @@ void iwl_irq_tasklet(struct iwl_priv *priv) | |||
507 | u32 inta_mask; | 507 | u32 inta_mask; |
508 | #endif | 508 | #endif |
509 | 509 | ||
510 | spin_lock_irqsave(&priv->shrd->lock, flags); | 510 | struct iwl_trans_pcie *trans_pcie = |
511 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
512 | |||
513 | spin_lock_irqsave(&trans->shrd->lock, flags); | ||
511 | 514 | ||
512 | /* Ack/clear/reset pending uCode interrupts. | 515 | /* Ack/clear/reset pending uCode interrupts. |
513 | * Note: Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS, | 516 | * Note: Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS, |
@@ -520,33 +523,34 @@ void iwl_irq_tasklet(struct iwl_priv *priv) | |||
520 | * hardware bugs here by ACKing all the possible interrupts so that | 523 | * hardware bugs here by ACKing all the possible interrupts so that |
521 | * interrupt coalescing can still be achieved. | 524 | * interrupt coalescing can still be achieved. |
522 | */ | 525 | */ |
523 | iwl_write32(priv, CSR_INT, priv->inta | ~priv->inta_mask); | 526 | iwl_write32(priv(trans), CSR_INT, |
527 | trans_pcie->inta | ~trans_pcie->inta_mask); | ||
524 | 528 | ||
525 | inta = priv->inta; | 529 | inta = trans_pcie->inta; |
526 | 530 | ||
527 | #ifdef CONFIG_IWLWIFI_DEBUG | 531 | #ifdef CONFIG_IWLWIFI_DEBUG |
528 | if (iwl_get_debug_level(priv->shrd) & IWL_DL_ISR) { | 532 | if (iwl_get_debug_level(trans->shrd) & IWL_DL_ISR) { |
529 | /* just for debug */ | 533 | /* just for debug */ |
530 | inta_mask = iwl_read32(priv, CSR_INT_MASK); | 534 | inta_mask = iwl_read32(priv(trans), CSR_INT_MASK); |
531 | IWL_DEBUG_ISR(priv, "inta 0x%08x, enabled 0x%08x\n ", | 535 | IWL_DEBUG_ISR(trans, "inta 0x%08x, enabled 0x%08x\n ", |
532 | inta, inta_mask); | 536 | inta, inta_mask); |
533 | } | 537 | } |
534 | #endif | 538 | #endif |
535 | 539 | ||
536 | spin_unlock_irqrestore(&priv->shrd->lock, flags); | 540 | spin_unlock_irqrestore(&trans->shrd->lock, flags); |
537 | 541 | ||
538 | /* saved interrupt in inta variable now we can reset priv->inta */ | 542 | /* saved interrupt in inta variable now we can reset trans_pcie->inta */ |
539 | priv->inta = 0; | 543 | trans_pcie->inta = 0; |
540 | 544 | ||
541 | /* Now service all interrupt bits discovered above. */ | 545 | /* Now service all interrupt bits discovered above. */ |
542 | if (inta & CSR_INT_BIT_HW_ERR) { | 546 | if (inta & CSR_INT_BIT_HW_ERR) { |
543 | IWL_ERR(priv, "Hardware error detected. Restarting.\n"); | 547 | IWL_ERR(trans, "Hardware error detected. Restarting.\n"); |
544 | 548 | ||
545 | /* Tell the device to stop sending interrupts */ | 549 | /* Tell the device to stop sending interrupts */ |
546 | iwl_disable_interrupts(priv); | 550 | iwl_disable_interrupts(trans); |
547 | 551 | ||
548 | priv->isr_stats.hw++; | 552 | priv(trans)->isr_stats.hw++; |
549 | iwl_irq_handle_error(priv); | 553 | iwl_irq_handle_error(priv(trans)); |
550 | 554 | ||
551 | handled |= CSR_INT_BIT_HW_ERR; | 555 | handled |= CSR_INT_BIT_HW_ERR; |
552 | 556 | ||
@@ -554,18 +558,18 @@ void iwl_irq_tasklet(struct iwl_priv *priv) | |||
554 | } | 558 | } |
555 | 559 | ||
556 | #ifdef CONFIG_IWLWIFI_DEBUG | 560 | #ifdef CONFIG_IWLWIFI_DEBUG |
557 | if (iwl_get_debug_level(priv->shrd) & (IWL_DL_ISR)) { | 561 | if (iwl_get_debug_level(trans->shrd) & (IWL_DL_ISR)) { |
558 | /* NIC fires this, but we don't use it, redundant with WAKEUP */ | 562 | /* NIC fires this, but we don't use it, redundant with WAKEUP */ |
559 | if (inta & CSR_INT_BIT_SCD) { | 563 | if (inta & CSR_INT_BIT_SCD) { |
560 | IWL_DEBUG_ISR(priv, "Scheduler finished to transmit " | 564 | IWL_DEBUG_ISR(trans, "Scheduler finished to transmit " |
561 | "the frame/frames.\n"); | 565 | "the frame/frames.\n"); |
562 | priv->isr_stats.sch++; | 566 | priv(trans)->isr_stats.sch++; |
563 | } | 567 | } |
564 | 568 | ||
565 | /* Alive notification via Rx interrupt will do the real work */ | 569 | /* Alive notification via Rx interrupt will do the real work */ |
566 | if (inta & CSR_INT_BIT_ALIVE) { | 570 | if (inta & CSR_INT_BIT_ALIVE) { |
567 | IWL_DEBUG_ISR(priv, "Alive interrupt\n"); | 571 | IWL_DEBUG_ISR(trans, "Alive interrupt\n"); |
568 | priv->isr_stats.alive++; | 572 | priv(trans)->isr_stats.alive++; |
569 | } | 573 | } |
570 | } | 574 | } |
571 | #endif | 575 | #endif |
@@ -575,27 +579,29 @@ void iwl_irq_tasklet(struct iwl_priv *priv) | |||
575 | /* HW RF KILL switch toggled */ | 579 | /* HW RF KILL switch toggled */ |
576 | if (inta & CSR_INT_BIT_RF_KILL) { | 580 | if (inta & CSR_INT_BIT_RF_KILL) { |
577 | int hw_rf_kill = 0; | 581 | int hw_rf_kill = 0; |
578 | if (!(iwl_read32(priv, CSR_GP_CNTRL) & | 582 | if (!(iwl_read32(priv(trans), CSR_GP_CNTRL) & |
579 | CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)) | 583 | CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)) |
580 | hw_rf_kill = 1; | 584 | hw_rf_kill = 1; |
581 | 585 | ||
582 | IWL_WARN(priv, "RF_KILL bit toggled to %s.\n", | 586 | IWL_WARN(trans, "RF_KILL bit toggled to %s.\n", |
583 | hw_rf_kill ? "disable radio" : "enable radio"); | 587 | hw_rf_kill ? "disable radio" : "enable radio"); |
584 | 588 | ||
585 | priv->isr_stats.rfkill++; | 589 | priv(trans)->isr_stats.rfkill++; |
586 | 590 | ||
587 | /* driver only loads ucode once setting the interface up. | 591 | /* driver only loads ucode once setting the interface up. |
588 | * the driver allows loading the ucode even if the radio | 592 | * the driver allows loading the ucode even if the radio |
589 | * is killed. Hence update the killswitch state here. The | 593 | * is killed. Hence update the killswitch state here. The |
590 | * rfkill handler will care about restarting if needed. | 594 | * rfkill handler will care about restarting if needed. |
591 | */ | 595 | */ |
592 | if (!test_bit(STATUS_ALIVE, &priv->shrd->status)) { | 596 | if (!test_bit(STATUS_ALIVE, &trans->shrd->status)) { |
593 | if (hw_rf_kill) | 597 | if (hw_rf_kill) |
594 | set_bit(STATUS_RF_KILL_HW, &priv->shrd->status); | 598 | set_bit(STATUS_RF_KILL_HW, |
599 | &trans->shrd->status); | ||
595 | else | 600 | else |
596 | clear_bit(STATUS_RF_KILL_HW, | 601 | clear_bit(STATUS_RF_KILL_HW, |
597 | &priv->shrd->status); | 602 | &trans->shrd->status); |
598 | wiphy_rfkill_set_hw_state(priv->hw->wiphy, hw_rf_kill); | 603 | wiphy_rfkill_set_hw_state(priv(trans)->hw->wiphy, |
604 | hw_rf_kill); | ||
599 | } | 605 | } |
600 | 606 | ||
601 | handled |= CSR_INT_BIT_RF_KILL; | 607 | handled |= CSR_INT_BIT_RF_KILL; |
@@ -603,30 +609,29 @@ void iwl_irq_tasklet(struct iwl_priv *priv) | |||
603 | 609 | ||
604 | /* Chip got too hot and stopped itself */ | 610 | /* Chip got too hot and stopped itself */ |
605 | if (inta & CSR_INT_BIT_CT_KILL) { | 611 | if (inta & CSR_INT_BIT_CT_KILL) { |
606 | IWL_ERR(priv, "Microcode CT kill error detected.\n"); | 612 | IWL_ERR(trans, "Microcode CT kill error detected.\n"); |
607 | priv->isr_stats.ctkill++; | 613 | priv(trans)->isr_stats.ctkill++; |
608 | handled |= CSR_INT_BIT_CT_KILL; | 614 | handled |= CSR_INT_BIT_CT_KILL; |
609 | } | 615 | } |
610 | 616 | ||
611 | /* Error detected by uCode */ | 617 | /* Error detected by uCode */ |
612 | if (inta & CSR_INT_BIT_SW_ERR) { | 618 | if (inta & CSR_INT_BIT_SW_ERR) { |
613 | IWL_ERR(priv, "Microcode SW error detected. " | 619 | IWL_ERR(trans, "Microcode SW error detected. " |
614 | " Restarting 0x%X.\n", inta); | 620 | " Restarting 0x%X.\n", inta); |
615 | priv->isr_stats.sw++; | 621 | priv(trans)->isr_stats.sw++; |
616 | iwl_irq_handle_error(priv); | 622 | iwl_irq_handle_error(priv(trans)); |
617 | handled |= CSR_INT_BIT_SW_ERR; | 623 | handled |= CSR_INT_BIT_SW_ERR; |
618 | } | 624 | } |
619 | 625 | ||
620 | /* uCode wakes up after power-down sleep */ | 626 | /* uCode wakes up after power-down sleep */ |
621 | if (inta & CSR_INT_BIT_WAKEUP) { | 627 | if (inta & CSR_INT_BIT_WAKEUP) { |
622 | struct iwl_trans_pcie *trans_pcie = | 628 | IWL_DEBUG_ISR(trans, "Wakeup interrupt\n"); |
623 | IWL_TRANS_GET_PCIE_TRANS(trans(priv)); | 629 | iwl_rx_queue_update_write_ptr(trans, &trans_pcie->rxq); |
624 | IWL_DEBUG_ISR(priv, "Wakeup interrupt\n"); | 630 | for (i = 0; i < hw_params(trans).max_txq_num; i++) |
625 | iwl_rx_queue_update_write_ptr(trans(priv), &trans_pcie->rxq); | 631 | iwl_txq_update_write_ptr(priv(trans), |
626 | for (i = 0; i < hw_params(priv).max_txq_num; i++) | 632 | &priv(trans)->txq[i]); |
627 | iwl_txq_update_write_ptr(priv, &priv->txq[i]); | ||
628 | 633 | ||
629 | priv->isr_stats.wakeup++; | 634 | priv(trans)->isr_stats.wakeup++; |
630 | 635 | ||
631 | handled |= CSR_INT_BIT_WAKEUP; | 636 | handled |= CSR_INT_BIT_WAKEUP; |
632 | } | 637 | } |
@@ -636,15 +641,16 @@ void iwl_irq_tasklet(struct iwl_priv *priv) | |||
636 | * notifications from uCode come through here*/ | 641 | * notifications from uCode come through here*/ |
637 | if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX | | 642 | if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX | |
638 | CSR_INT_BIT_RX_PERIODIC)) { | 643 | CSR_INT_BIT_RX_PERIODIC)) { |
639 | IWL_DEBUG_ISR(priv, "Rx interrupt\n"); | 644 | IWL_DEBUG_ISR(trans, "Rx interrupt\n"); |
640 | if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) { | 645 | if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) { |
641 | handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX); | 646 | handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX); |
642 | iwl_write32(priv, CSR_FH_INT_STATUS, | 647 | iwl_write32(priv(trans), CSR_FH_INT_STATUS, |
643 | CSR_FH_INT_RX_MASK); | 648 | CSR_FH_INT_RX_MASK); |
644 | } | 649 | } |
645 | if (inta & CSR_INT_BIT_RX_PERIODIC) { | 650 | if (inta & CSR_INT_BIT_RX_PERIODIC) { |
646 | handled |= CSR_INT_BIT_RX_PERIODIC; | 651 | handled |= CSR_INT_BIT_RX_PERIODIC; |
647 | iwl_write32(priv, CSR_INT, CSR_INT_BIT_RX_PERIODIC); | 652 | iwl_write32(priv(trans), |
653 | CSR_INT, CSR_INT_BIT_RX_PERIODIC); | ||
648 | } | 654 | } |
649 | /* Sending RX interrupt require many steps to be done in the | 655 | /* Sending RX interrupt require many steps to be done in the |
650 | * the device: | 656 | * the device: |
@@ -658,9 +664,9 @@ void iwl_irq_tasklet(struct iwl_priv *priv) | |||
658 | */ | 664 | */ |
659 | 665 | ||
660 | /* Disable periodic interrupt; we use it as just a one-shot. */ | 666 | /* Disable periodic interrupt; we use it as just a one-shot. */ |
661 | iwl_write8(priv, CSR_INT_PERIODIC_REG, | 667 | iwl_write8(priv(trans), CSR_INT_PERIODIC_REG, |
662 | CSR_INT_PERIODIC_DIS); | 668 | CSR_INT_PERIODIC_DIS); |
663 | iwl_rx_handle(trans(priv)); | 669 | iwl_rx_handle(trans); |
664 | 670 | ||
665 | /* | 671 | /* |
666 | * Enable periodic interrupt in 8 msec only if we received | 672 | * Enable periodic interrupt in 8 msec only if we received |
@@ -670,40 +676,40 @@ void iwl_irq_tasklet(struct iwl_priv *priv) | |||
670 | * to extend the periodic interrupt; one-shot is enough. | 676 | * to extend the periodic interrupt; one-shot is enough. |
671 | */ | 677 | */ |
672 | if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) | 678 | if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) |
673 | iwl_write8(priv, CSR_INT_PERIODIC_REG, | 679 | iwl_write8(priv(trans), CSR_INT_PERIODIC_REG, |
674 | CSR_INT_PERIODIC_ENA); | 680 | CSR_INT_PERIODIC_ENA); |
675 | 681 | ||
676 | priv->isr_stats.rx++; | 682 | priv(trans)->isr_stats.rx++; |
677 | } | 683 | } |
678 | 684 | ||
679 | /* This "Tx" DMA channel is used only for loading uCode */ | 685 | /* This "Tx" DMA channel is used only for loading uCode */ |
680 | if (inta & CSR_INT_BIT_FH_TX) { | 686 | if (inta & CSR_INT_BIT_FH_TX) { |
681 | iwl_write32(priv, CSR_FH_INT_STATUS, CSR_FH_INT_TX_MASK); | 687 | iwl_write32(priv(trans), CSR_FH_INT_STATUS, CSR_FH_INT_TX_MASK); |
682 | IWL_DEBUG_ISR(priv, "uCode load interrupt\n"); | 688 | IWL_DEBUG_ISR(trans, "uCode load interrupt\n"); |
683 | priv->isr_stats.tx++; | 689 | priv(trans)->isr_stats.tx++; |
684 | handled |= CSR_INT_BIT_FH_TX; | 690 | handled |= CSR_INT_BIT_FH_TX; |
685 | /* Wake up uCode load routine, now that load is complete */ | 691 | /* Wake up uCode load routine, now that load is complete */ |
686 | priv->ucode_write_complete = 1; | 692 | priv(trans)->ucode_write_complete = 1; |
687 | wake_up_interruptible(&priv->wait_command_queue); | 693 | wake_up_interruptible(&priv(trans)->wait_command_queue); |
688 | } | 694 | } |
689 | 695 | ||
690 | if (inta & ~handled) { | 696 | if (inta & ~handled) { |
691 | IWL_ERR(priv, "Unhandled INTA bits 0x%08x\n", inta & ~handled); | 697 | IWL_ERR(trans, "Unhandled INTA bits 0x%08x\n", inta & ~handled); |
692 | priv->isr_stats.unhandled++; | 698 | priv(trans)->isr_stats.unhandled++; |
693 | } | 699 | } |
694 | 700 | ||
695 | if (inta & ~(priv->inta_mask)) { | 701 | if (inta & ~(trans_pcie->inta_mask)) { |
696 | IWL_WARN(priv, "Disabled INTA bits 0x%08x were pending\n", | 702 | IWL_WARN(trans, "Disabled INTA bits 0x%08x were pending\n", |
697 | inta & ~priv->inta_mask); | 703 | inta & ~trans_pcie->inta_mask); |
698 | } | 704 | } |
699 | 705 | ||
700 | /* Re-enable all interrupts */ | 706 | /* Re-enable all interrupts */ |
701 | /* only Re-enable if disabled by irq */ | 707 | /* only Re-enable if disabled by irq */ |
702 | if (test_bit(STATUS_INT_ENABLED, &priv->shrd->status)) | 708 | if (test_bit(STATUS_INT_ENABLED, &trans->shrd->status)) |
703 | iwl_enable_interrupts(priv); | 709 | iwl_enable_interrupts(trans); |
704 | /* Re-enable RF_KILL if it occurred */ | 710 | /* Re-enable RF_KILL if it occurred */ |
705 | else if (handled & CSR_INT_BIT_RF_KILL) | 711 | else if (handled & CSR_INT_BIT_RF_KILL) |
706 | iwl_enable_rfkill_int(priv); | 712 | iwl_enable_rfkill_int(priv(trans)); |
707 | } | 713 | } |
708 | 714 | ||
709 | /****************************************************************************** | 715 | /****************************************************************************** |
@@ -714,18 +720,21 @@ void iwl_irq_tasklet(struct iwl_priv *priv) | |||
714 | #define ICT_COUNT (PAGE_SIZE/sizeof(u32)) | 720 | #define ICT_COUNT (PAGE_SIZE/sizeof(u32)) |
715 | 721 | ||
716 | /* Free dram table */ | 722 | /* Free dram table */ |
717 | void iwl_free_isr_ict(struct iwl_priv *priv) | 723 | void iwl_free_isr_ict(struct iwl_trans *trans) |
718 | { | 724 | { |
719 | if (priv->ict_tbl_vir) { | 725 | struct iwl_trans_pcie *trans_pcie = |
720 | dma_free_coherent(priv->bus->dev, | 726 | IWL_TRANS_GET_PCIE_TRANS(trans); |
727 | |||
728 | if (trans_pcie->ict_tbl_vir) { | ||
729 | dma_free_coherent(bus(trans)->dev, | ||
721 | (sizeof(u32) * ICT_COUNT) + PAGE_SIZE, | 730 | (sizeof(u32) * ICT_COUNT) + PAGE_SIZE, |
722 | priv->ict_tbl_vir, | 731 | trans_pcie->ict_tbl_vir, |
723 | priv->ict_tbl_dma); | 732 | trans_pcie->ict_tbl_dma); |
724 | priv->ict_tbl_vir = NULL; | 733 | trans_pcie->ict_tbl_vir = NULL; |
725 | memset(&priv->ict_tbl_dma, 0, | 734 | memset(&trans_pcie->ict_tbl_dma, 0, |
726 | sizeof(priv->ict_tbl_dma)); | 735 | sizeof(trans_pcie->ict_tbl_dma)); |
727 | memset(&priv->aligned_ict_tbl_dma, 0, | 736 | memset(&trans_pcie->aligned_ict_tbl_dma, 0, |
728 | sizeof(priv->aligned_ict_tbl_dma)); | 737 | sizeof(trans_pcie->aligned_ict_tbl_dma)); |
729 | } | 738 | } |
730 | } | 739 | } |
731 | 740 | ||
@@ -733,43 +742,45 @@ void iwl_free_isr_ict(struct iwl_priv *priv) | |||
733 | /* allocate dram shared table it is a PAGE_SIZE aligned | 742 | /* allocate dram shared table it is a PAGE_SIZE aligned |
734 | * also reset all data related to ICT table interrupt. | 743 | * also reset all data related to ICT table interrupt. |
735 | */ | 744 | */ |
736 | int iwl_alloc_isr_ict(struct iwl_priv *priv) | 745 | int iwl_alloc_isr_ict(struct iwl_trans *trans) |
737 | { | 746 | { |
747 | struct iwl_trans_pcie *trans_pcie = | ||
748 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
738 | 749 | ||
739 | /* allocate shrared data table */ | 750 | /* allocate shrared data table */ |
740 | priv->ict_tbl_vir = | 751 | trans_pcie->ict_tbl_vir = |
741 | dma_alloc_coherent(priv->bus->dev, | 752 | dma_alloc_coherent(bus(trans)->dev, |
742 | (sizeof(u32) * ICT_COUNT) + PAGE_SIZE, | 753 | (sizeof(u32) * ICT_COUNT) + PAGE_SIZE, |
743 | &priv->ict_tbl_dma, GFP_KERNEL); | 754 | &trans_pcie->ict_tbl_dma, GFP_KERNEL); |
744 | if (!priv->ict_tbl_vir) | 755 | if (!trans_pcie->ict_tbl_vir) |
745 | return -ENOMEM; | 756 | return -ENOMEM; |
746 | 757 | ||
747 | /* align table to PAGE_SIZE boundary */ | 758 | /* align table to PAGE_SIZE boundary */ |
748 | priv->aligned_ict_tbl_dma = | 759 | trans_pcie->aligned_ict_tbl_dma = |
749 | ALIGN(priv->ict_tbl_dma, PAGE_SIZE); | 760 | ALIGN(trans_pcie->ict_tbl_dma, PAGE_SIZE); |
750 | 761 | ||
751 | IWL_DEBUG_ISR(priv, "ict dma addr %Lx dma aligned %Lx diff %d\n", | 762 | IWL_DEBUG_ISR(trans, "ict dma addr %Lx dma aligned %Lx diff %d\n", |
752 | (unsigned long long)priv->ict_tbl_dma, | 763 | (unsigned long long)trans_pcie->ict_tbl_dma, |
753 | (unsigned long long)priv->aligned_ict_tbl_dma, | 764 | (unsigned long long)trans_pcie->aligned_ict_tbl_dma, |
754 | (int)(priv->aligned_ict_tbl_dma - | 765 | (int)(trans_pcie->aligned_ict_tbl_dma - |
755 | priv->ict_tbl_dma)); | 766 | trans_pcie->ict_tbl_dma)); |
756 | 767 | ||
757 | priv->ict_tbl = priv->ict_tbl_vir + | 768 | trans_pcie->ict_tbl = trans_pcie->ict_tbl_vir + |
758 | (priv->aligned_ict_tbl_dma - | 769 | (trans_pcie->aligned_ict_tbl_dma - |
759 | priv->ict_tbl_dma); | 770 | trans_pcie->ict_tbl_dma); |
760 | 771 | ||
761 | IWL_DEBUG_ISR(priv, "ict vir addr %p vir aligned %p diff %d\n", | 772 | IWL_DEBUG_ISR(trans, "ict vir addr %p vir aligned %p diff %d\n", |
762 | priv->ict_tbl, priv->ict_tbl_vir, | 773 | trans_pcie->ict_tbl, trans_pcie->ict_tbl_vir, |
763 | (int)(priv->aligned_ict_tbl_dma - | 774 | (int)(trans_pcie->aligned_ict_tbl_dma - |
764 | priv->ict_tbl_dma)); | 775 | trans_pcie->ict_tbl_dma)); |
765 | 776 | ||
766 | /* reset table and index to all 0 */ | 777 | /* reset table and index to all 0 */ |
767 | memset(priv->ict_tbl_vir, 0, | 778 | memset(trans_pcie->ict_tbl_vir, 0, |
768 | (sizeof(u32) * ICT_COUNT) + PAGE_SIZE); | 779 | (sizeof(u32) * ICT_COUNT) + PAGE_SIZE); |
769 | priv->ict_index = 0; | 780 | trans_pcie->ict_index = 0; |
770 | 781 | ||
771 | /* add periodic RX interrupt */ | 782 | /* add periodic RX interrupt */ |
772 | priv->inta_mask |= CSR_INT_BIT_RX_PERIODIC; | 783 | trans_pcie->inta_mask |= CSR_INT_BIT_RX_PERIODIC; |
773 | return 0; | 784 | return 0; |
774 | } | 785 | } |
775 | 786 | ||
@@ -780,110 +791,120 @@ int iwl_reset_ict(struct iwl_priv *priv) | |||
780 | { | 791 | { |
781 | u32 val; | 792 | u32 val; |
782 | unsigned long flags; | 793 | unsigned long flags; |
794 | struct iwl_trans *trans = trans(priv); | ||
795 | struct iwl_trans_pcie *trans_pcie = | ||
796 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
783 | 797 | ||
784 | if (!priv->ict_tbl_vir) | 798 | if (!trans_pcie->ict_tbl_vir) |
785 | return 0; | 799 | return 0; |
786 | 800 | ||
787 | spin_lock_irqsave(&priv->shrd->lock, flags); | 801 | spin_lock_irqsave(&trans->shrd->lock, flags); |
788 | iwl_disable_interrupts(priv); | 802 | iwl_disable_interrupts(trans); |
789 | 803 | ||
790 | memset(&priv->ict_tbl[0], 0, sizeof(u32) * ICT_COUNT); | 804 | memset(&trans_pcie->ict_tbl[0], 0, sizeof(u32) * ICT_COUNT); |
791 | 805 | ||
792 | val = priv->aligned_ict_tbl_dma >> PAGE_SHIFT; | 806 | val = trans_pcie->aligned_ict_tbl_dma >> PAGE_SHIFT; |
793 | 807 | ||
794 | val |= CSR_DRAM_INT_TBL_ENABLE; | 808 | val |= CSR_DRAM_INT_TBL_ENABLE; |
795 | val |= CSR_DRAM_INIT_TBL_WRAP_CHECK; | 809 | val |= CSR_DRAM_INIT_TBL_WRAP_CHECK; |
796 | 810 | ||
797 | IWL_DEBUG_ISR(priv, "CSR_DRAM_INT_TBL_REG =0x%X " | 811 | IWL_DEBUG_ISR(trans, "CSR_DRAM_INT_TBL_REG =0x%X " |
798 | "aligned dma address %Lx\n", | 812 | "aligned dma address %Lx\n", |
799 | val, | 813 | val, |
800 | (unsigned long long)priv->aligned_ict_tbl_dma); | 814 | (unsigned long long)trans_pcie->aligned_ict_tbl_dma); |
801 | 815 | ||
802 | iwl_write32(priv, CSR_DRAM_INT_TBL_REG, val); | 816 | iwl_write32(priv(trans), CSR_DRAM_INT_TBL_REG, val); |
803 | priv->use_ict = true; | 817 | trans_pcie->use_ict = true; |
804 | priv->ict_index = 0; | 818 | trans_pcie->ict_index = 0; |
805 | iwl_write32(priv, CSR_INT, priv->inta_mask); | 819 | iwl_write32(priv(trans), CSR_INT, trans_pcie->inta_mask); |
806 | iwl_enable_interrupts(priv); | 820 | iwl_enable_interrupts(trans); |
807 | spin_unlock_irqrestore(&priv->shrd->lock, flags); | 821 | spin_unlock_irqrestore(&trans->shrd->lock, flags); |
808 | 822 | ||
809 | return 0; | 823 | return 0; |
810 | } | 824 | } |
811 | 825 | ||
812 | /* Device is going down disable ict interrupt usage */ | 826 | /* Device is going down disable ict interrupt usage */ |
813 | void iwl_disable_ict(struct iwl_priv *priv) | 827 | void iwl_disable_ict(struct iwl_trans *trans) |
814 | { | 828 | { |
829 | struct iwl_trans_pcie *trans_pcie = | ||
830 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
831 | |||
815 | unsigned long flags; | 832 | unsigned long flags; |
816 | 833 | ||
817 | spin_lock_irqsave(&priv->shrd->lock, flags); | 834 | spin_lock_irqsave(&trans->shrd->lock, flags); |
818 | priv->use_ict = false; | 835 | trans_pcie->use_ict = false; |
819 | spin_unlock_irqrestore(&priv->shrd->lock, flags); | 836 | spin_unlock_irqrestore(&trans->shrd->lock, flags); |
820 | } | 837 | } |
821 | 838 | ||
822 | static irqreturn_t iwl_isr(int irq, void *data) | 839 | static irqreturn_t iwl_isr(int irq, void *data) |
823 | { | 840 | { |
824 | struct iwl_priv *priv = data; | 841 | struct iwl_trans *trans = data; |
842 | struct iwl_trans_pcie *trans_pcie; | ||
825 | u32 inta, inta_mask; | 843 | u32 inta, inta_mask; |
826 | unsigned long flags; | 844 | unsigned long flags; |
827 | #ifdef CONFIG_IWLWIFI_DEBUG | 845 | #ifdef CONFIG_IWLWIFI_DEBUG |
828 | u32 inta_fh; | 846 | u32 inta_fh; |
829 | #endif | 847 | #endif |
830 | if (!priv) | 848 | if (!trans) |
831 | return IRQ_NONE; | 849 | return IRQ_NONE; |
832 | 850 | ||
833 | spin_lock_irqsave(&priv->shrd->lock, flags); | 851 | trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
852 | |||
853 | spin_lock_irqsave(&trans->shrd->lock, flags); | ||
834 | 854 | ||
835 | /* Disable (but don't clear!) interrupts here to avoid | 855 | /* Disable (but don't clear!) interrupts here to avoid |
836 | * back-to-back ISRs and sporadic interrupts from our NIC. | 856 | * back-to-back ISRs and sporadic interrupts from our NIC. |
837 | * If we have something to service, the tasklet will re-enable ints. | 857 | * If we have something to service, the tasklet will re-enable ints. |
838 | * If we *don't* have something, we'll re-enable before leaving here. */ | 858 | * If we *don't* have something, we'll re-enable before leaving here. */ |
839 | inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */ | 859 | inta_mask = iwl_read32(priv(trans), CSR_INT_MASK); /* just for debug */ |
840 | iwl_write32(priv, CSR_INT_MASK, 0x00000000); | 860 | iwl_write32(priv(trans), CSR_INT_MASK, 0x00000000); |
841 | 861 | ||
842 | /* Discover which interrupts are active/pending */ | 862 | /* Discover which interrupts are active/pending */ |
843 | inta = iwl_read32(priv, CSR_INT); | 863 | inta = iwl_read32(priv(trans), CSR_INT); |
844 | 864 | ||
845 | /* Ignore interrupt if there's nothing in NIC to service. | 865 | /* Ignore interrupt if there's nothing in NIC to service. |
846 | * This may be due to IRQ shared with another device, | 866 | * This may be due to IRQ shared with another device, |
847 | * or due to sporadic interrupts thrown from our NIC. */ | 867 | * or due to sporadic interrupts thrown from our NIC. */ |
848 | if (!inta) { | 868 | if (!inta) { |
849 | IWL_DEBUG_ISR(priv, "Ignore interrupt, inta == 0\n"); | 869 | IWL_DEBUG_ISR(trans, "Ignore interrupt, inta == 0\n"); |
850 | goto none; | 870 | goto none; |
851 | } | 871 | } |
852 | 872 | ||
853 | if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) { | 873 | if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) { |
854 | /* Hardware disappeared. It might have already raised | 874 | /* Hardware disappeared. It might have already raised |
855 | * an interrupt */ | 875 | * an interrupt */ |
856 | IWL_WARN(priv, "HARDWARE GONE?? INTA == 0x%08x\n", inta); | 876 | IWL_WARN(trans, "HARDWARE GONE?? INTA == 0x%08x\n", inta); |
857 | goto unplugged; | 877 | goto unplugged; |
858 | } | 878 | } |
859 | 879 | ||
860 | #ifdef CONFIG_IWLWIFI_DEBUG | 880 | #ifdef CONFIG_IWLWIFI_DEBUG |
861 | if (iwl_get_debug_level(priv->shrd) & (IWL_DL_ISR)) { | 881 | if (iwl_get_debug_level(trans->shrd) & (IWL_DL_ISR)) { |
862 | inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS); | 882 | inta_fh = iwl_read32(priv(trans), CSR_FH_INT_STATUS); |
863 | IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x, " | 883 | IWL_DEBUG_ISR(trans, "ISR inta 0x%08x, enabled 0x%08x, " |
864 | "fh 0x%08x\n", inta, inta_mask, inta_fh); | 884 | "fh 0x%08x\n", inta, inta_mask, inta_fh); |
865 | } | 885 | } |
866 | #endif | 886 | #endif |
867 | 887 | ||
868 | priv->inta |= inta; | 888 | trans_pcie->inta |= inta; |
869 | /* iwl_irq_tasklet() will service interrupts and re-enable them */ | 889 | /* iwl_irq_tasklet() will service interrupts and re-enable them */ |
870 | if (likely(inta)) | 890 | if (likely(inta)) |
871 | tasklet_schedule(&priv->irq_tasklet); | 891 | tasklet_schedule(&trans_pcie->irq_tasklet); |
872 | else if (test_bit(STATUS_INT_ENABLED, &priv->shrd->status) && | 892 | else if (test_bit(STATUS_INT_ENABLED, &trans->shrd->status) && |
873 | !priv->inta) | 893 | !trans_pcie->inta) |
874 | iwl_enable_interrupts(priv); | 894 | iwl_enable_interrupts(trans); |
875 | 895 | ||
876 | unplugged: | 896 | unplugged: |
877 | spin_unlock_irqrestore(&priv->shrd->lock, flags); | 897 | spin_unlock_irqrestore(&trans->shrd->lock, flags); |
878 | return IRQ_HANDLED; | 898 | return IRQ_HANDLED; |
879 | 899 | ||
880 | none: | 900 | none: |
881 | /* re-enable interrupts here since we don't have anything to service. */ | 901 | /* re-enable interrupts here since we don't have anything to service. */ |
882 | /* only Re-enable if disabled by irq and no schedules tasklet. */ | 902 | /* only Re-enable if disabled by irq and no schedules tasklet. */ |
883 | if (test_bit(STATUS_INT_ENABLED, &priv->shrd->status) && !priv->inta) | 903 | if (test_bit(STATUS_INT_ENABLED, &trans->shrd->status) && |
884 | iwl_enable_interrupts(priv); | 904 | !trans_pcie->inta) |
905 | iwl_enable_interrupts(trans); | ||
885 | 906 | ||
886 | spin_unlock_irqrestore(&priv->shrd->lock, flags); | 907 | spin_unlock_irqrestore(&trans->shrd->lock, flags); |
887 | return IRQ_NONE; | 908 | return IRQ_NONE; |
888 | } | 909 | } |
889 | 910 | ||
@@ -897,50 +918,53 @@ static irqreturn_t iwl_isr(int irq, void *data) | |||
897 | */ | 918 | */ |
898 | irqreturn_t iwl_isr_ict(int irq, void *data) | 919 | irqreturn_t iwl_isr_ict(int irq, void *data) |
899 | { | 920 | { |
900 | struct iwl_priv *priv = data; | 921 | struct iwl_trans *trans = data; |
922 | struct iwl_trans_pcie *trans_pcie; | ||
901 | u32 inta, inta_mask; | 923 | u32 inta, inta_mask; |
902 | u32 val = 0; | 924 | u32 val = 0; |
903 | unsigned long flags; | 925 | unsigned long flags; |
904 | 926 | ||
905 | if (!priv) | 927 | if (!trans) |
906 | return IRQ_NONE; | 928 | return IRQ_NONE; |
907 | 929 | ||
930 | trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
931 | |||
908 | /* dram interrupt table not set yet, | 932 | /* dram interrupt table not set yet, |
909 | * use legacy interrupt. | 933 | * use legacy interrupt. |
910 | */ | 934 | */ |
911 | if (!priv->use_ict) | 935 | if (!trans_pcie->use_ict) |
912 | return iwl_isr(irq, data); | 936 | return iwl_isr(irq, data); |
913 | 937 | ||
914 | spin_lock_irqsave(&priv->shrd->lock, flags); | 938 | spin_lock_irqsave(&trans->shrd->lock, flags); |
915 | 939 | ||
916 | /* Disable (but don't clear!) interrupts here to avoid | 940 | /* Disable (but don't clear!) interrupts here to avoid |
917 | * back-to-back ISRs and sporadic interrupts from our NIC. | 941 | * back-to-back ISRs and sporadic interrupts from our NIC. |
918 | * If we have something to service, the tasklet will re-enable ints. | 942 | * If we have something to service, the tasklet will re-enable ints. |
919 | * If we *don't* have something, we'll re-enable before leaving here. | 943 | * If we *don't* have something, we'll re-enable before leaving here. |
920 | */ | 944 | */ |
921 | inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */ | 945 | inta_mask = iwl_read32(priv(trans), CSR_INT_MASK); /* just for debug */ |
922 | iwl_write32(priv, CSR_INT_MASK, 0x00000000); | 946 | iwl_write32(priv(trans), CSR_INT_MASK, 0x00000000); |
923 | 947 | ||
924 | 948 | ||
925 | /* Ignore interrupt if there's nothing in NIC to service. | 949 | /* Ignore interrupt if there's nothing in NIC to service. |
926 | * This may be due to IRQ shared with another device, | 950 | * This may be due to IRQ shared with another device, |
927 | * or due to sporadic interrupts thrown from our NIC. */ | 951 | * or due to sporadic interrupts thrown from our NIC. */ |
928 | if (!priv->ict_tbl[priv->ict_index]) { | 952 | if (!trans_pcie->ict_tbl[trans_pcie->ict_index]) { |
929 | IWL_DEBUG_ISR(priv, "Ignore interrupt, inta == 0\n"); | 953 | IWL_DEBUG_ISR(trans, "Ignore interrupt, inta == 0\n"); |
930 | goto none; | 954 | goto none; |
931 | } | 955 | } |
932 | 956 | ||
933 | /* read all entries that not 0 start with ict_index */ | 957 | /* read all entries that not 0 start with ict_index */ |
934 | while (priv->ict_tbl[priv->ict_index]) { | 958 | while (trans_pcie->ict_tbl[trans_pcie->ict_index]) { |
935 | 959 | ||
936 | val |= le32_to_cpu(priv->ict_tbl[priv->ict_index]); | 960 | val |= le32_to_cpu(trans_pcie->ict_tbl[trans_pcie->ict_index]); |
937 | IWL_DEBUG_ISR(priv, "ICT index %d value 0x%08X\n", | 961 | IWL_DEBUG_ISR(trans, "ICT index %d value 0x%08X\n", |
938 | priv->ict_index, | 962 | trans_pcie->ict_index, |
939 | le32_to_cpu( | 963 | le32_to_cpu( |
940 | priv->ict_tbl[priv->ict_index])); | 964 | trans_pcie->ict_tbl[trans_pcie->ict_index])); |
941 | priv->ict_tbl[priv->ict_index] = 0; | 965 | trans_pcie->ict_tbl[trans_pcie->ict_index] = 0; |
942 | priv->ict_index = iwl_queue_inc_wrap(priv->ict_index, | 966 | trans_pcie->ict_index = |
943 | ICT_COUNT); | 967 | iwl_queue_inc_wrap(trans_pcie->ict_index, ICT_COUNT); |
944 | 968 | ||
945 | } | 969 | } |
946 | 970 | ||
@@ -959,34 +983,35 @@ irqreturn_t iwl_isr_ict(int irq, void *data) | |||
959 | val |= 0x8000; | 983 | val |= 0x8000; |
960 | 984 | ||
961 | inta = (0xff & val) | ((0xff00 & val) << 16); | 985 | inta = (0xff & val) | ((0xff00 & val) << 16); |
962 | IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x ict 0x%08x\n", | 986 | IWL_DEBUG_ISR(trans, "ISR inta 0x%08x, enabled 0x%08x ict 0x%08x\n", |
963 | inta, inta_mask, val); | 987 | inta, inta_mask, val); |
964 | 988 | ||
965 | inta &= priv->inta_mask; | 989 | inta &= trans_pcie->inta_mask; |
966 | priv->inta |= inta; | 990 | trans_pcie->inta |= inta; |
967 | 991 | ||
968 | /* iwl_irq_tasklet() will service interrupts and re-enable them */ | 992 | /* iwl_irq_tasklet() will service interrupts and re-enable them */ |
969 | if (likely(inta)) | 993 | if (likely(inta)) |
970 | tasklet_schedule(&priv->irq_tasklet); | 994 | tasklet_schedule(&trans_pcie->irq_tasklet); |
971 | else if (test_bit(STATUS_INT_ENABLED, &priv->shrd->status) && | 995 | else if (test_bit(STATUS_INT_ENABLED, &trans->shrd->status) && |
972 | !priv->inta) { | 996 | !trans_pcie->inta) { |
973 | /* Allow interrupt if was disabled by this handler and | 997 | /* Allow interrupt if was disabled by this handler and |
974 | * no tasklet was schedules, We should not enable interrupt, | 998 | * no tasklet was schedules, We should not enable interrupt, |
975 | * tasklet will enable it. | 999 | * tasklet will enable it. |
976 | */ | 1000 | */ |
977 | iwl_enable_interrupts(priv); | 1001 | iwl_enable_interrupts(trans); |
978 | } | 1002 | } |
979 | 1003 | ||
980 | spin_unlock_irqrestore(&priv->shrd->lock, flags); | 1004 | spin_unlock_irqrestore(&trans->shrd->lock, flags); |
981 | return IRQ_HANDLED; | 1005 | return IRQ_HANDLED; |
982 | 1006 | ||
983 | none: | 1007 | none: |
984 | /* re-enable interrupts here since we don't have anything to service. | 1008 | /* re-enable interrupts here since we don't have anything to service. |
985 | * only Re-enable if disabled by irq. | 1009 | * only Re-enable if disabled by irq. |
986 | */ | 1010 | */ |
987 | if (test_bit(STATUS_INT_ENABLED, &priv->shrd->status) && !priv->inta) | 1011 | if (test_bit(STATUS_INT_ENABLED, &trans->shrd->status) && |
988 | iwl_enable_interrupts(priv); | 1012 | !trans_pcie->inta) |
1013 | iwl_enable_interrupts(trans); | ||
989 | 1014 | ||
990 | spin_unlock_irqrestore(&priv->shrd->lock, flags); | 1015 | spin_unlock_irqrestore(&trans->shrd->lock, flags); |
991 | return IRQ_NONE; | 1016 | return IRQ_NONE; |
992 | } | 1017 | } |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index 621b9a822090..687a09226e6d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c | |||
@@ -711,7 +711,7 @@ static int iwl_trans_pcie_start_device(struct iwl_priv *priv) | |||
711 | 711 | ||
712 | if (iwl_is_rfkill(priv)) { | 712 | if (iwl_is_rfkill(priv)) { |
713 | wiphy_rfkill_set_hw_state(priv->hw->wiphy, true); | 713 | wiphy_rfkill_set_hw_state(priv->hw->wiphy, true); |
714 | iwl_enable_interrupts(priv); | 714 | iwl_enable_interrupts(trans(priv)); |
715 | return -ERFKILL; | 715 | return -ERFKILL; |
716 | } | 716 | } |
717 | 717 | ||
@@ -730,7 +730,7 @@ static int iwl_trans_pcie_start_device(struct iwl_priv *priv) | |||
730 | 730 | ||
731 | /* clear (again), then enable host interrupts */ | 731 | /* clear (again), then enable host interrupts */ |
732 | iwl_write32(priv, CSR_INT, 0xFFFFFFFF); | 732 | iwl_write32(priv, CSR_INT, 0xFFFFFFFF); |
733 | iwl_enable_interrupts(priv); | 733 | iwl_enable_interrupts(trans(priv)); |
734 | 734 | ||
735 | /* really make sure rfkill handshake bits are cleared */ | 735 | /* really make sure rfkill handshake bits are cleared */ |
736 | iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); | 736 | iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); |
@@ -931,19 +931,14 @@ static int iwl_trans_tx_stop(struct iwl_priv *priv) | |||
931 | 931 | ||
932 | static void iwl_trans_pcie_stop_device(struct iwl_priv *priv) | 932 | static void iwl_trans_pcie_stop_device(struct iwl_priv *priv) |
933 | { | 933 | { |
934 | unsigned long flags; | ||
935 | |||
936 | /* stop and reset the on-board processor */ | 934 | /* stop and reset the on-board processor */ |
937 | iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); | 935 | iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); |
938 | 936 | ||
939 | /* tell the device to stop sending interrupts */ | 937 | /* tell the device to stop sending interrupts */ |
940 | spin_lock_irqsave(&priv->shrd->lock, flags); | 938 | iwl_trans_disable_sync_irq(trans(priv)); |
941 | iwl_disable_interrupts(priv); | ||
942 | spin_unlock_irqrestore(&priv->shrd->lock, flags); | ||
943 | iwl_trans_sync_irq(trans(priv)); | ||
944 | 939 | ||
945 | /* device going down, Stop using ICT table */ | 940 | /* device going down, Stop using ICT table */ |
946 | iwl_disable_ict(priv); | 941 | iwl_disable_ict(trans(priv)); |
947 | 942 | ||
948 | /* | 943 | /* |
949 | * If a HW restart happens during firmware loading, | 944 | * If a HW restart happens during firmware loading, |
@@ -1132,19 +1127,20 @@ static int iwl_trans_pcie_request_irq(struct iwl_trans *trans) | |||
1132 | { | 1127 | { |
1133 | struct iwl_trans_pcie *trans_pcie = | 1128 | struct iwl_trans_pcie *trans_pcie = |
1134 | IWL_TRANS_GET_PCIE_TRANS(trans); | 1129 | IWL_TRANS_GET_PCIE_TRANS(trans); |
1135 | struct iwl_priv *priv = priv(trans); | ||
1136 | int err; | 1130 | int err; |
1137 | 1131 | ||
1138 | tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) | 1132 | trans_pcie->inta_mask = CSR_INI_SET_MASK; |
1139 | iwl_irq_tasklet, (unsigned long)priv); | 1133 | |
1134 | tasklet_init(&trans_pcie->irq_tasklet, (void (*)(unsigned long)) | ||
1135 | iwl_irq_tasklet, (unsigned long)trans); | ||
1140 | 1136 | ||
1141 | iwl_alloc_isr_ict(priv); | 1137 | iwl_alloc_isr_ict(trans); |
1142 | 1138 | ||
1143 | err = request_irq(bus(trans)->irq, iwl_isr_ict, IRQF_SHARED, | 1139 | err = request_irq(bus(trans)->irq, iwl_isr_ict, IRQF_SHARED, |
1144 | DRV_NAME, priv); | 1140 | DRV_NAME, trans); |
1145 | if (err) { | 1141 | if (err) { |
1146 | IWL_ERR(priv, "Error allocating IRQ %d\n", priv->bus->irq); | 1142 | IWL_ERR(trans, "Error allocating IRQ %d\n", bus(trans)->irq); |
1147 | iwl_free_isr_ict(priv); | 1143 | iwl_free_isr_ict(trans); |
1148 | return err; | 1144 | return err; |
1149 | } | 1145 | } |
1150 | 1146 | ||
@@ -1152,17 +1148,25 @@ static int iwl_trans_pcie_request_irq(struct iwl_trans *trans) | |||
1152 | return 0; | 1148 | return 0; |
1153 | } | 1149 | } |
1154 | 1150 | ||
1155 | static void iwl_trans_pcie_sync_irq(struct iwl_priv *priv) | 1151 | static void iwl_trans_pcie_disable_sync_irq(struct iwl_trans *trans) |
1156 | { | 1152 | { |
1153 | unsigned long flags; | ||
1154 | struct iwl_trans_pcie *trans_pcie = | ||
1155 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
1156 | |||
1157 | spin_lock_irqsave(&trans->shrd->lock, flags); | ||
1158 | iwl_disable_interrupts(trans); | ||
1159 | spin_unlock_irqrestore(&trans->shrd->lock, flags); | ||
1160 | |||
1157 | /* wait to make sure we flush pending tasklet*/ | 1161 | /* wait to make sure we flush pending tasklet*/ |
1158 | synchronize_irq(priv->bus->irq); | 1162 | synchronize_irq(bus(trans)->irq); |
1159 | tasklet_kill(&priv->irq_tasklet); | 1163 | tasklet_kill(&trans_pcie->irq_tasklet); |
1160 | } | 1164 | } |
1161 | 1165 | ||
1162 | static void iwl_trans_pcie_free(struct iwl_priv *priv) | 1166 | static void iwl_trans_pcie_free(struct iwl_priv *priv) |
1163 | { | 1167 | { |
1164 | free_irq(priv->bus->irq, priv); | 1168 | free_irq(priv->bus->irq, trans(priv)); |
1165 | iwl_free_isr_ict(priv); | 1169 | iwl_free_isr_ict(trans(priv)); |
1166 | kfree(trans(priv)); | 1170 | kfree(trans(priv)); |
1167 | trans(priv) = NULL; | 1171 | trans(priv) = NULL; |
1168 | } | 1172 | } |
@@ -1191,7 +1195,7 @@ static int iwl_trans_pcie_resume(struct iwl_trans *trans) | |||
1191 | { | 1195 | { |
1192 | bool hw_rfkill = false; | 1196 | bool hw_rfkill = false; |
1193 | 1197 | ||
1194 | iwl_enable_interrupts(priv(trans)); | 1198 | iwl_enable_interrupts(trans); |
1195 | 1199 | ||
1196 | if (!(iwl_read32(priv(trans), CSR_GP_CNTRL) & | 1200 | if (!(iwl_read32(priv(trans), CSR_GP_CNTRL) & |
1197 | CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)) | 1201 | CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)) |
@@ -1500,7 +1504,7 @@ const struct iwl_trans_ops trans_ops_pcie = { | |||
1500 | 1504 | ||
1501 | .kick_nic = iwl_trans_pcie_kick_nic, | 1505 | .kick_nic = iwl_trans_pcie_kick_nic, |
1502 | 1506 | ||
1503 | .sync_irq = iwl_trans_pcie_sync_irq, | 1507 | .disable_sync_irq = iwl_trans_pcie_disable_sync_irq, |
1504 | .free = iwl_trans_pcie_free, | 1508 | .free = iwl_trans_pcie_free, |
1505 | 1509 | ||
1506 | .dbgfs_register = iwl_trans_pcie_dbgfs_register, | 1510 | .dbgfs_register = iwl_trans_pcie_dbgfs_register, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index c12763c1a3a8..b4c7166a70e3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h | |||
@@ -94,10 +94,9 @@ struct iwl_shared; | |||
94 | * ready and a successful ADDBA response has been received. | 94 | * ready and a successful ADDBA response has been received. |
95 | * @txq_agg_disable: de-configure a Tx queue to send AMPDUs | 95 | * @txq_agg_disable: de-configure a Tx queue to send AMPDUs |
96 | * @kick_nic: remove the RESET from the embedded CPU and let it run | 96 | * @kick_nic: remove the RESET from the embedded CPU and let it run |
97 | * @sync_irq: the upper layer will typically disable interrupt and call this | 97 | * @disable_sync_irq: Disable and sync: after this handler returns, it is |
98 | * handler. After this handler returns, it is guaranteed that all | 98 | * guaranteed that all the ISR / tasklet etc... have finished running |
99 | * the ISR / tasklet etc... have finished running and the transport | 99 | * and the transport layer shall not pass any Rx. |
100 | * layer shall not pass any Rx. | ||
101 | * @free: release all the ressource for the transport layer itself such as | 100 | * @free: release all the ressource for the transport layer itself such as |
102 | * irq, tasklet etc... | 101 | * irq, tasklet etc... |
103 | * @dbgfs_register: add the dbgfs files under this directory. Files will be | 102 | * @dbgfs_register: add the dbgfs files under this directory. Files will be |
@@ -132,7 +131,7 @@ struct iwl_trans_ops { | |||
132 | 131 | ||
133 | void (*kick_nic)(struct iwl_priv *priv); | 132 | void (*kick_nic)(struct iwl_priv *priv); |
134 | 133 | ||
135 | void (*sync_irq)(struct iwl_priv *priv); | 134 | void (*disable_sync_irq)(struct iwl_trans *trans); |
136 | void (*free)(struct iwl_priv *priv); | 135 | void (*free)(struct iwl_priv *priv); |
137 | 136 | ||
138 | int (*dbgfs_register)(struct iwl_trans *trans, struct dentry* dir); | 137 | int (*dbgfs_register)(struct iwl_trans *trans, struct dentry* dir); |
@@ -232,9 +231,9 @@ static inline void iwl_trans_kick_nic(struct iwl_trans *trans) | |||
232 | trans->ops->kick_nic(priv(trans)); | 231 | trans->ops->kick_nic(priv(trans)); |
233 | } | 232 | } |
234 | 233 | ||
235 | static inline void iwl_trans_sync_irq(struct iwl_trans *trans) | 234 | static inline void iwl_trans_disable_sync_irq(struct iwl_trans *trans) |
236 | { | 235 | { |
237 | trans->ops->sync_irq(priv(trans)); | 236 | trans->ops->disable_sync_irq(trans); |
238 | } | 237 | } |
239 | 238 | ||
240 | static inline void iwl_trans_free(struct iwl_trans *trans) | 239 | static inline void iwl_trans_free(struct iwl_trans *trans) |