aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-agn.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-agn.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c190
1 files changed, 185 insertions, 5 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 4e41038a92c1..fa24b019c62c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -937,7 +937,7 @@ static inline void iwl_synchronize_irq(struct iwl_priv *priv)
937 tasklet_kill(&priv->irq_tasklet); 937 tasklet_kill(&priv->irq_tasklet);
938} 938}
939 939
940static void iwl_irq_tasklet(struct iwl_priv *priv) 940static void iwl_irq_tasklet_legacy(struct iwl_priv *priv)
941{ 941{
942 u32 inta, handled = 0; 942 u32 inta, handled = 0;
943 u32 inta_fh; 943 u32 inta_fh;
@@ -1121,6 +1121,174 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
1121 spin_unlock_irqrestore(&priv->lock, flags); 1121 spin_unlock_irqrestore(&priv->lock, flags);
1122} 1122}
1123 1123
1124/* tasklet for iwlagn interrupt */
1125static void iwl_irq_tasklet(struct iwl_priv *priv)
1126{
1127 u32 inta = 0;
1128 u32 handled = 0;
1129 unsigned long flags;
1130#ifdef CONFIG_IWLWIFI_DEBUG
1131 u32 inta_mask;
1132#endif
1133
1134 spin_lock_irqsave(&priv->lock, flags);
1135
1136 /* Ack/clear/reset pending uCode interrupts.
1137 * Note: Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS,
1138 */
1139 iwl_write32(priv, CSR_INT, priv->inta);
1140
1141 inta = priv->inta;
1142
1143#ifdef CONFIG_IWLWIFI_DEBUG
1144 if (priv->debug_level & IWL_DL_ISR) {
1145 /* just for debug */
1146 inta_mask = iwl_read32(priv, CSR_INT_MASK);
1147 IWL_DEBUG_ISR(priv, "inta 0x%08x, enabled 0x%08x\n ",
1148 inta, inta_mask);
1149 }
1150#endif
1151 /* saved interrupt in inta variable now we can reset priv->inta */
1152 priv->inta = 0;
1153
1154 /* Now service all interrupt bits discovered above. */
1155 if (inta & CSR_INT_BIT_HW_ERR) {
1156 IWL_ERR(priv, "Microcode HW error detected. Restarting.\n");
1157
1158 /* Tell the device to stop sending interrupts */
1159 iwl_disable_interrupts(priv);
1160
1161 priv->isr_stats.hw++;
1162 iwl_irq_handle_error(priv);
1163
1164 handled |= CSR_INT_BIT_HW_ERR;
1165
1166 spin_unlock_irqrestore(&priv->lock, flags);
1167
1168 return;
1169 }
1170
1171#ifdef CONFIG_IWLWIFI_DEBUG
1172 if (priv->debug_level & (IWL_DL_ISR)) {
1173 /* NIC fires this, but we don't use it, redundant with WAKEUP */
1174 if (inta & CSR_INT_BIT_SCD) {
1175 IWL_DEBUG_ISR(priv, "Scheduler finished to transmit "
1176 "the frame/frames.\n");
1177 priv->isr_stats.sch++;
1178 }
1179
1180 /* Alive notification via Rx interrupt will do the real work */
1181 if (inta & CSR_INT_BIT_ALIVE) {
1182 IWL_DEBUG_ISR(priv, "Alive interrupt\n");
1183 priv->isr_stats.alive++;
1184 }
1185 }
1186#endif
1187 /* Safely ignore these bits for debug checks below */
1188 inta &= ~(CSR_INT_BIT_SCD | CSR_INT_BIT_ALIVE);
1189
1190 /* HW RF KILL switch toggled */
1191 if (inta & CSR_INT_BIT_RF_KILL) {
1192 int hw_rf_kill = 0;
1193 if (!(iwl_read32(priv, CSR_GP_CNTRL) &
1194 CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW))
1195 hw_rf_kill = 1;
1196
1197 IWL_DEBUG_RF_KILL(priv, "RF_KILL bit toggled to %s.\n",
1198 hw_rf_kill ? "disable radio" : "enable radio");
1199
1200 priv->isr_stats.rfkill++;
1201
1202 /* driver only loads ucode once setting the interface up.
1203 * the driver allows loading the ucode even if the radio
1204 * is killed. Hence update the killswitch state here. The
1205 * rfkill handler will care about restarting if needed.
1206 */
1207 if (!test_bit(STATUS_ALIVE, &priv->status)) {
1208 if (hw_rf_kill)
1209 set_bit(STATUS_RF_KILL_HW, &priv->status);
1210 else
1211 clear_bit(STATUS_RF_KILL_HW, &priv->status);
1212 queue_work(priv->workqueue, &priv->rf_kill);
1213 }
1214
1215 handled |= CSR_INT_BIT_RF_KILL;
1216 }
1217
1218 /* Chip got too hot and stopped itself */
1219 if (inta & CSR_INT_BIT_CT_KILL) {
1220 IWL_ERR(priv, "Microcode CT kill error detected.\n");
1221 priv->isr_stats.ctkill++;
1222 handled |= CSR_INT_BIT_CT_KILL;
1223 }
1224
1225 /* Error detected by uCode */
1226 if (inta & CSR_INT_BIT_SW_ERR) {
1227 IWL_ERR(priv, "Microcode SW error detected. "
1228 " Restarting 0x%X.\n", inta);
1229 priv->isr_stats.sw++;
1230 priv->isr_stats.sw_err = inta;
1231 iwl_irq_handle_error(priv);
1232 handled |= CSR_INT_BIT_SW_ERR;
1233 }
1234
1235 /* uCode wakes up after power-down sleep */
1236 if (inta & CSR_INT_BIT_WAKEUP) {
1237 IWL_DEBUG_ISR(priv, "Wakeup interrupt\n");
1238 iwl_rx_queue_update_write_ptr(priv, &priv->rxq);
1239 iwl_txq_update_write_ptr(priv, &priv->txq[0]);
1240 iwl_txq_update_write_ptr(priv, &priv->txq[1]);
1241 iwl_txq_update_write_ptr(priv, &priv->txq[2]);
1242 iwl_txq_update_write_ptr(priv, &priv->txq[3]);
1243 iwl_txq_update_write_ptr(priv, &priv->txq[4]);
1244 iwl_txq_update_write_ptr(priv, &priv->txq[5]);
1245
1246 priv->isr_stats.wakeup++;
1247
1248 handled |= CSR_INT_BIT_WAKEUP;
1249 }
1250
1251 /* All uCode command responses, including Tx command responses,
1252 * Rx "responses" (frame-received notification), and other
1253 * notifications from uCode come through here*/
1254 if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) {
1255 IWL_DEBUG_ISR(priv, "Rx interrupt\n");
1256 iwl_write32(priv, CSR_FH_INT_STATUS, CSR49_FH_INT_RX_MASK);
1257 iwl_rx_handle(priv);
1258 priv->isr_stats.rx++;
1259 handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX);
1260 }
1261
1262 if (inta & CSR_INT_BIT_FH_TX) {
1263 iwl_write32(priv, CSR_FH_INT_STATUS, CSR49_FH_INT_TX_MASK);
1264 IWL_DEBUG_ISR(priv, "Tx interrupt\n");
1265 priv->isr_stats.tx++;
1266 handled |= CSR_INT_BIT_FH_TX;
1267 /* FH finished to write, send event */
1268 priv->ucode_write_complete = 1;
1269 wake_up_interruptible(&priv->wait_command_queue);
1270 }
1271
1272 if (inta & ~handled) {
1273 IWL_ERR(priv, "Unhandled INTA bits 0x%08x\n", inta & ~handled);
1274 priv->isr_stats.unhandled++;
1275 }
1276
1277 if (inta & ~CSR_INI_SET_MASK) {
1278 IWL_WARN(priv, "Disabled INTA bits 0x%08x were pending\n",
1279 inta & ~CSR_INI_SET_MASK);
1280 }
1281
1282
1283 /* Re-enable all interrupts */
1284 /* only Re-enable if diabled by irq */
1285 if (test_bit(STATUS_INT_ENABLED, &priv->status))
1286 iwl_enable_interrupts(priv);
1287
1288 spin_unlock_irqrestore(&priv->lock, flags);
1289
1290}
1291
1124 1292
1125/****************************************************************************** 1293/******************************************************************************
1126 * 1294 *
@@ -1550,6 +1718,8 @@ static void __iwl_down(struct iwl_priv *priv)
1550 test_bit(STATUS_EXIT_PENDING, &priv->status) << 1718 test_bit(STATUS_EXIT_PENDING, &priv->status) <<
1551 STATUS_EXIT_PENDING; 1719 STATUS_EXIT_PENDING;
1552 1720
1721 /* device going down, Stop using ICT table */
1722 iwl_disable_ict(priv);
1553 spin_lock_irqsave(&priv->lock, flags); 1723 spin_lock_irqsave(&priv->lock, flags);
1554 iwl_clear_bit(priv, CSR_GP_CNTRL, 1724 iwl_clear_bit(priv, CSR_GP_CNTRL,
1555 CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); 1725 CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
@@ -1633,6 +1803,8 @@ static int __iwl_up(struct iwl_priv *priv)
1633 1803
1634 /* clear (again), then enable host interrupts */ 1804 /* clear (again), then enable host interrupts */
1635 iwl_write32(priv, CSR_INT, 0xFFFFFFFF); 1805 iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
1806 /* enable dram interrupt */
1807 iwl_reset_ict(priv);
1636 iwl_enable_interrupts(priv); 1808 iwl_enable_interrupts(priv);
1637 1809
1638 /* really make sure rfkill handshake bits are cleared */ 1810 /* really make sure rfkill handshake bits are cleared */
@@ -2533,8 +2705,12 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
2533 priv->statistics_periodic.data = (unsigned long)priv; 2705 priv->statistics_periodic.data = (unsigned long)priv;
2534 priv->statistics_periodic.function = iwl_bg_statistics_periodic; 2706 priv->statistics_periodic.function = iwl_bg_statistics_periodic;
2535 2707
2536 tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) 2708 if (!priv->cfg->use_isr_legacy)
2537 iwl_irq_tasklet, (unsigned long)priv); 2709 tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
2710 iwl_irq_tasklet, (unsigned long)priv);
2711 else
2712 tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
2713 iwl_irq_tasklet_legacy, (unsigned long)priv);
2538} 2714}
2539 2715
2540static void iwl_cancel_deferred_work(struct iwl_priv *priv) 2716static void iwl_cancel_deferred_work(struct iwl_priv *priv)
@@ -2735,8 +2911,9 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
2735 2911
2736 pci_enable_msi(priv->pci_dev); 2912 pci_enable_msi(priv->pci_dev);
2737 2913
2738 err = request_irq(priv->pci_dev->irq, iwl_isr, IRQF_SHARED, 2914 iwl_alloc_isr_ict(priv);
2739 DRV_NAME, priv); 2915 err = request_irq(priv->pci_dev->irq, priv->cfg->ops->lib->isr,
2916 IRQF_SHARED, DRV_NAME, priv);
2740 if (err) { 2917 if (err) {
2741 IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq); 2918 IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq);
2742 goto out_disable_msi; 2919 goto out_disable_msi;
@@ -2793,6 +2970,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
2793 sysfs_remove_group(&pdev->dev.kobj, &iwl_attribute_group); 2970 sysfs_remove_group(&pdev->dev.kobj, &iwl_attribute_group);
2794 out_free_irq: 2971 out_free_irq:
2795 free_irq(priv->pci_dev->irq, priv); 2972 free_irq(priv->pci_dev->irq, priv);
2973 iwl_free_isr_ict(priv);
2796 out_disable_msi: 2974 out_disable_msi:
2797 pci_disable_msi(priv->pci_dev); 2975 pci_disable_msi(priv->pci_dev);
2798 iwl_uninit_drv(priv); 2976 iwl_uninit_drv(priv);
@@ -2874,6 +3052,8 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)
2874 3052
2875 iwl_uninit_drv(priv); 3053 iwl_uninit_drv(priv);
2876 3054
3055 iwl_free_isr_ict(priv);
3056
2877 if (priv->ibss_beacon) 3057 if (priv->ibss_beacon)
2878 dev_kfree_skb(priv->ibss_beacon); 3058 dev_kfree_skb(priv->ibss_beacon);
2879 3059