aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi
diff options
context:
space:
mode:
authorMohamed Abbas <mohamed.abbas@intel.com>2009-05-22 14:01:52 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-05-22 14:06:09 -0400
commit40cefda9ce11c44a2531d07af812900aa5f3ce9d (patch)
tree08b4108aa0c9678bb76450212e0806234134731e /drivers/net/wireless/iwlwifi
parent4752c93c30441f98f7ed723001b1a5e3e5619829 (diff)
iwlcore: Add support for periodic RX interrupt
Periodic RX interrupt needed with ICT interrupt to prevent RX race. Sending RX interrupt require many steps to be done in the the device: 1- write interrupt to current index in ICT table. 2- dma RX frame. 3- update RX shared data to indicate last write index. 4- send interrupt. This could lead to RX race, driver could receive RX interrupt but the shared data changes does not reflect that. this could lead to RX race, RX periodic will solve this race Signed-off-by: Mohamed Abbas <mohamed.abbas@intel.com> Signed-off-by: Reinette Chatre <reinette.chatre@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c40
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c8
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-csr.h5
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c5
5 files changed, 46 insertions, 13 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index be1058bdc4c5..889574d852b8 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -1107,9 +1107,9 @@ static void iwl_irq_tasklet_legacy(struct iwl_priv *priv)
1107 priv->isr_stats.unhandled++; 1107 priv->isr_stats.unhandled++;
1108 } 1108 }
1109 1109
1110 if (inta & ~CSR_INI_SET_MASK) { 1110 if (inta & ~(priv->inta_mask)) {
1111 IWL_WARN(priv, "Disabled INTA bits 0x%08x were pending\n", 1111 IWL_WARN(priv, "Disabled INTA bits 0x%08x were pending\n",
1112 inta & ~CSR_INI_SET_MASK); 1112 inta & ~priv->inta_mask);
1113 IWL_WARN(priv, " with FH_INT = 0x%08x\n", inta_fh); 1113 IWL_WARN(priv, " with FH_INT = 0x%08x\n", inta_fh);
1114 } 1114 }
1115 1115
@@ -1260,12 +1260,37 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
1260 /* All uCode command responses, including Tx command responses, 1260 /* All uCode command responses, including Tx command responses,
1261 * Rx "responses" (frame-received notification), and other 1261 * Rx "responses" (frame-received notification), and other
1262 * notifications from uCode come through here*/ 1262 * notifications from uCode come through here*/
1263 if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) { 1263 if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX |
1264 CSR_INT_BIT_RX_PERIODIC)) {
1264 IWL_DEBUG_ISR(priv, "Rx interrupt\n"); 1265 IWL_DEBUG_ISR(priv, "Rx interrupt\n");
1265 iwl_write32(priv, CSR_FH_INT_STATUS, CSR49_FH_INT_RX_MASK); 1266 if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) {
1267 handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX);
1268 iwl_write32(priv, CSR_FH_INT_STATUS,
1269 CSR49_FH_INT_RX_MASK);
1270 }
1271 if (inta & CSR_INT_BIT_RX_PERIODIC) {
1272 handled |= CSR_INT_BIT_RX_PERIODIC;
1273 iwl_write32(priv, CSR_INT, CSR_INT_BIT_RX_PERIODIC);
1274 }
1275 /* Sending RX interrupt require many steps to be done in the
1276 * the device:
1277 * 1- write interrupt to current index in ICT table.
1278 * 2- dma RX frame.
1279 * 3- update RX shared data to indicate last write index.
1280 * 4- send interrupt.
1281 * This could lead to RX race, driver could receive RX interrupt
1282 * but the shared data changes does not reflect this.
1283 * this could lead to RX race, RX periodic will solve this race
1284 */
1285 iwl_write32(priv, CSR_INT_PERIODIC_REG,
1286 CSR_INT_PERIODIC_DIS);
1266 iwl_rx_handle(priv); 1287 iwl_rx_handle(priv);
1288 /* Only set RX periodic if real RX is received. */
1289 if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX))
1290 iwl_write32(priv, CSR_INT_PERIODIC_REG,
1291 CSR_INT_PERIODIC_ENA);
1292
1267 priv->isr_stats.rx++; 1293 priv->isr_stats.rx++;
1268 handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX);
1269 } 1294 }
1270 1295
1271 if (inta & CSR_INT_BIT_FH_TX) { 1296 if (inta & CSR_INT_BIT_FH_TX) {
@@ -1283,9 +1308,9 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
1283 priv->isr_stats.unhandled++; 1308 priv->isr_stats.unhandled++;
1284 } 1309 }
1285 1310
1286 if (inta & ~CSR_INI_SET_MASK) { 1311 if (inta & ~(priv->inta_mask)) {
1287 IWL_WARN(priv, "Disabled INTA bits 0x%08x were pending\n", 1312 IWL_WARN(priv, "Disabled INTA bits 0x%08x were pending\n",
1288 inta & ~CSR_INI_SET_MASK); 1313 inta & ~priv->inta_mask);
1289 } 1314 }
1290 1315
1291 1316
@@ -2808,6 +2833,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
2808 IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n"); 2833 IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n");
2809 priv->cfg = cfg; 2834 priv->cfg = cfg;
2810 priv->pci_dev = pdev; 2835 priv->pci_dev = pdev;
2836 priv->inta_mask = CSR_INI_SET_MASK;
2811 2837
2812#ifdef CONFIG_IWLWIFI_DEBUG 2838#ifdef CONFIG_IWLWIFI_DEBUG
2813 priv->debug_level = priv->cfg->mod_params->debug; 2839 priv->debug_level = priv->cfg->mod_params->debug;
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 12f018392a44..e93ddb74457e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -1500,7 +1500,7 @@ void iwl_enable_interrupts(struct iwl_priv *priv)
1500{ 1500{
1501 IWL_DEBUG_ISR(priv, "Enabling interrupts\n"); 1501 IWL_DEBUG_ISR(priv, "Enabling interrupts\n");
1502 set_bit(STATUS_INT_ENABLED, &priv->status); 1502 set_bit(STATUS_INT_ENABLED, &priv->status);
1503 iwl_write32(priv, CSR_INT_MASK, CSR_INI_SET_MASK); 1503 iwl_write32(priv, CSR_INT_MASK, priv->inta_mask);
1504} 1504}
1505EXPORT_SYMBOL(iwl_enable_interrupts); 1505EXPORT_SYMBOL(iwl_enable_interrupts);
1506 1506
@@ -1554,6 +1554,8 @@ int iwl_alloc_isr_ict(struct iwl_priv *priv)
1554 memset(priv->ict_tbl_vir,0, (sizeof(u32) * ICT_COUNT) + PAGE_SIZE); 1554 memset(priv->ict_tbl_vir,0, (sizeof(u32) * ICT_COUNT) + PAGE_SIZE);
1555 priv->ict_index = 0; 1555 priv->ict_index = 0;
1556 1556
1557 /* add periodic RX interrupt */
1558 priv->inta_mask |= CSR_INT_BIT_RX_PERIODIC;
1557 return 0; 1559 return 0;
1558} 1560}
1559EXPORT_SYMBOL(iwl_alloc_isr_ict); 1561EXPORT_SYMBOL(iwl_alloc_isr_ict);
@@ -1586,7 +1588,7 @@ int iwl_reset_ict(struct iwl_priv *priv)
1586 iwl_write32(priv, CSR_DRAM_INT_TBL_REG, val); 1588 iwl_write32(priv, CSR_DRAM_INT_TBL_REG, val);
1587 priv->use_ict = true; 1589 priv->use_ict = true;
1588 priv->ict_index = 0; 1590 priv->ict_index = 0;
1589 iwl_write32(priv, CSR_INT, CSR_INI_SET_MASK); 1591 iwl_write32(priv, CSR_INT, priv->inta_mask);
1590 iwl_enable_interrupts(priv); 1592 iwl_enable_interrupts(priv);
1591 spin_unlock_irqrestore(&priv->lock, flags); 1593 spin_unlock_irqrestore(&priv->lock, flags);
1592 1594
@@ -1668,7 +1670,7 @@ irqreturn_t iwl_isr_ict(int irq, void *data)
1668 IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x ict 0x%08x\n", 1670 IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x ict 0x%08x\n",
1669 inta, inta_mask, val); 1671 inta, inta_mask, val);
1670 1672
1671 inta &= CSR_INI_SET_MASK; 1673 inta &= priv->inta_mask;
1672 priv->inta |= inta; 1674 priv->inta |= inta;
1673 1675
1674 /* iwl_irq_tasklet() will service interrupts and re-enable them */ 1676 /* iwl_irq_tasklet() will service interrupts and re-enable them */
diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h
index 34c123ea1d3e..e2fafb828684 100644
--- a/drivers/net/wireless/iwlwifi/iwl-csr.h
+++ b/drivers/net/wireless/iwlwifi/iwl-csr.h
@@ -100,6 +100,7 @@
100#define CSR_DRAM_INT_TBL_REG (CSR_BASE+0x0A0) 100#define CSR_DRAM_INT_TBL_REG (CSR_BASE+0x0A0)
101#define CSR_GIO_CHICKEN_BITS (CSR_BASE+0x100) 101#define CSR_GIO_CHICKEN_BITS (CSR_BASE+0x100)
102 102
103#define CSR_INT_PERIODIC_REG (CSR_BASE+0x005)
103/* Analog phase-lock-loop configuration */ 104/* Analog phase-lock-loop configuration */
104#define CSR_ANA_PLL_CFG (CSR_BASE+0x20c) 105#define CSR_ANA_PLL_CFG (CSR_BASE+0x20c)
105/* 106/*
@@ -129,12 +130,14 @@
129#define CSR_HW_IF_CONFIG_REG_BIT_ME_OWN (0x02000000) 130#define CSR_HW_IF_CONFIG_REG_BIT_ME_OWN (0x02000000)
130#define CSR_HW_IF_CONFIG_REG_BIT_WAKE_ME (0x08000000) 131#define CSR_HW_IF_CONFIG_REG_BIT_WAKE_ME (0x08000000)
131 132
133#define CSR_INT_PERIODIC_DIS (0x00)
134#define CSR_INT_PERIODIC_ENA (0xFF)
132 135
133/* interrupt flags in INTA, set by uCode or hardware (e.g. dma), 136/* interrupt flags in INTA, set by uCode or hardware (e.g. dma),
134 * acknowledged (reset) by host writing "1" to flagged bits. */ 137 * acknowledged (reset) by host writing "1" to flagged bits. */
135#define CSR_INT_BIT_FH_RX (1 << 31) /* Rx DMA, cmd responses, FH_INT[17:16] */ 138#define CSR_INT_BIT_FH_RX (1 << 31) /* Rx DMA, cmd responses, FH_INT[17:16] */
136#define CSR_INT_BIT_HW_ERR (1 << 29) /* DMA hardware error FH_INT[31] */ 139#define CSR_INT_BIT_HW_ERR (1 << 29) /* DMA hardware error FH_INT[31] */
137#define CSR_INT_BIT_DNLD (1 << 28) /* uCode Download */ 140#define CSR_INT_BIT_RX_PERIODIC (1 << 28) /* Rx periodic */
138#define CSR_INT_BIT_FH_TX (1 << 27) /* Tx DMA FH_INT[1:0] */ 141#define CSR_INT_BIT_FH_TX (1 << 27) /* Tx DMA FH_INT[1:0] */
139#define CSR_INT_BIT_SCD (1 << 26) /* TXQ pointer advanced */ 142#define CSR_INT_BIT_SCD (1 << 26) /* TXQ pointer advanced */
140#define CSR_INT_BIT_SW_ERR (1 << 25) /* uCode error */ 143#define CSR_INT_BIT_SW_ERR (1 << 25) /* uCode error */
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 770cd1b062ff..f9a3fd6a023a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -1058,6 +1058,7 @@ struct iwl_priv {
1058 u32 inta; 1058 u32 inta;
1059 bool use_ict; 1059 bool use_ict;
1060 1060
1061 u32 inta_mask;
1061 /* Current association information needed to configure the 1062 /* Current association information needed to configure the
1062 * hardware */ 1063 * hardware */
1063 u16 assoc_id; 1064 u16 assoc_id;
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 639893d7808b..c434f493daf5 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -1944,9 +1944,9 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)
1944 priv->isr_stats.unhandled++; 1944 priv->isr_stats.unhandled++;
1945 } 1945 }
1946 1946
1947 if (inta & ~CSR_INI_SET_MASK) { 1947 if (inta & ~priv->inta_mask) {
1948 IWL_WARN(priv, "Disabled INTA bits 0x%08x were pending\n", 1948 IWL_WARN(priv, "Disabled INTA bits 0x%08x were pending\n",
1949 inta & ~CSR_INI_SET_MASK); 1949 inta & ~priv->inta_mask);
1950 IWL_WARN(priv, " with FH_INT = 0x%08x\n", inta_fh); 1950 IWL_WARN(priv, " with FH_INT = 0x%08x\n", inta_fh);
1951 } 1951 }
1952 1952
@@ -4184,6 +4184,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
4184 IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n"); 4184 IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n");
4185 priv->cfg = cfg; 4185 priv->cfg = cfg;
4186 priv->pci_dev = pdev; 4186 priv->pci_dev = pdev;
4187 priv->inta_mask = CSR_INI_SET_MASK;
4187 4188
4188#ifdef CONFIG_IWLWIFI_DEBUG 4189#ifdef CONFIG_IWLWIFI_DEBUG
4189 priv->debug_level = iwl3945_mod_params.debug; 4190 priv->debug_level = iwl3945_mod_params.debug;