aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_main.c74
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_reg.h2
2 files changed, 31 insertions, 45 deletions
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index 22d44ba2e96..8ac9bc1b944 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -76,20 +76,14 @@ static void wl1271_power_on(struct wl1271 *wl)
76 wl->set_power(true); 76 wl->set_power(true);
77} 77}
78 78
79static void wl1271_fw_status(struct wl1271 *wl, struct wl1271_fw_status *status) 79static void wl1271_fw_status(struct wl1271 *wl,
80 struct wl1271_fw_status *status)
80{ 81{
81 u32 total = 0; 82 u32 total = 0;
82 int i; 83 int i;
83 84
84 /* 85 wl1271_spi_reg_read(wl, FW_STATUS_ADDR, status,
85 * FIXME: Reading the FW status directly from the registers seems to 86 sizeof(*status), false);
86 * be the right thing to do, but it doesn't work. And in the
87 * reference driver, there is a workaround called
88 * USE_SDIO_24M_WORKAROUND, which reads the status from memory
89 * instead, so we do the same here.
90 */
91
92 wl1271_spi_mem_read(wl, STATUS_MEM_ADDRESS, status, sizeof(*status));
93 87
94 wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, " 88 wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, "
95 "drv_rx_counter = %d, tx_results_counter = %d)", 89 "drv_rx_counter = %d, tx_results_counter = %d)",
@@ -114,11 +108,10 @@ static void wl1271_fw_status(struct wl1271 *wl, struct wl1271_fw_status *status)
114 wl->time_offset = jiffies_to_usecs(jiffies) - status->fw_localtime; 108 wl->time_offset = jiffies_to_usecs(jiffies) - status->fw_localtime;
115} 109}
116 110
117#define WL1271_IRQ_MAX_LOOPS 10
118static void wl1271_irq_work(struct work_struct *work) 111static void wl1271_irq_work(struct work_struct *work)
119{ 112{
120 u32 intr, ctr = WL1271_IRQ_MAX_LOOPS;
121 int ret; 113 int ret;
114 u32 intr;
122 struct wl1271 *wl = 115 struct wl1271 *wl =
123 container_of(work, struct wl1271, irq_work); 116 container_of(work, struct wl1271, irq_work);
124 117
@@ -135,7 +128,8 @@ static void wl1271_irq_work(struct work_struct *work)
135 128
136 wl1271_reg_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL); 129 wl1271_reg_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL);
137 130
138 intr = wl1271_reg_read32(wl, ACX_REG_INTERRUPT_CLEAR); 131 wl1271_fw_status(wl, wl->fw_status);
132 intr = wl->fw_status->intr;
139 if (!intr) { 133 if (!intr) {
140 wl1271_debug(DEBUG_IRQ, "Zero interrupt received."); 134 wl1271_debug(DEBUG_IRQ, "Zero interrupt received.");
141 goto out_sleep; 135 goto out_sleep;
@@ -143,43 +137,35 @@ static void wl1271_irq_work(struct work_struct *work)
143 137
144 intr &= WL1271_INTR_MASK; 138 intr &= WL1271_INTR_MASK;
145 139
146 do { 140 if (intr & (WL1271_ACX_INTR_EVENT_A |
147 wl1271_fw_status(wl, wl->fw_status); 141 WL1271_ACX_INTR_EVENT_B)) {
148 142 wl1271_debug(DEBUG_IRQ,
149 143 "WL1271_ACX_INTR_EVENT (0x%x)", intr);
150 if (intr & (WL1271_ACX_INTR_EVENT_A | 144 if (intr & WL1271_ACX_INTR_EVENT_A)
151 WL1271_ACX_INTR_EVENT_B)) { 145 wl1271_event_handle(wl, 0);
152 wl1271_debug(DEBUG_IRQ, 146 else
153 "WL1271_ACX_INTR_EVENT (0x%x)", intr); 147 wl1271_event_handle(wl, 1);
154 if (intr & WL1271_ACX_INTR_EVENT_A) 148 }
155 wl1271_event_handle(wl, 0);
156 else
157 wl1271_event_handle(wl, 1);
158 }
159 149
160 if (intr & WL1271_ACX_INTR_INIT_COMPLETE) 150 if (intr & WL1271_ACX_INTR_INIT_COMPLETE)
161 wl1271_debug(DEBUG_IRQ, 151 wl1271_debug(DEBUG_IRQ,
162 "WL1271_ACX_INTR_INIT_COMPLETE"); 152 "WL1271_ACX_INTR_INIT_COMPLETE");
163 153
164 if (intr & WL1271_ACX_INTR_HW_AVAILABLE) 154 if (intr & WL1271_ACX_INTR_HW_AVAILABLE)
165 wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_HW_AVAILABLE"); 155 wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_HW_AVAILABLE");
166 156
167 if (intr & WL1271_ACX_INTR_DATA) { 157 if (intr & WL1271_ACX_INTR_DATA) {
168 u8 tx_res_cnt = wl->fw_status->tx_results_counter - 158 u8 tx_res_cnt = wl->fw_status->tx_results_counter -
169 wl->tx_results_count; 159 wl->tx_results_count;
170 160
171 wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA"); 161 wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA");
172 162
173 /* check for tx results */ 163 /* check for tx results */
174 if (tx_res_cnt) 164 if (tx_res_cnt)
175 wl1271_tx_complete(wl, tx_res_cnt); 165 wl1271_tx_complete(wl, tx_res_cnt);
176 166
177 wl1271_rx(wl, wl->fw_status); 167 wl1271_rx(wl, wl->fw_status);
178 } 168 }
179
180 intr = wl1271_reg_read32(wl, ACX_REG_INTERRUPT_CLEAR);
181 intr &= WL1271_INTR_MASK;
182 } while (intr && --ctr);
183 169
184out_sleep: 170out_sleep:
185 wl1271_reg_write32(wl, ACX_REG_INTERRUPT_MASK, 171 wl1271_reg_write32(wl, ACX_REG_INTERRUPT_MASK,
diff --git a/drivers/net/wireless/wl12xx/wl1271_reg.h b/drivers/net/wireless/wl12xx/wl1271_reg.h
index bd12615e4ca..6af87b5573b 100644
--- a/drivers/net/wireless/wl12xx/wl1271_reg.h
+++ b/drivers/net/wireless/wl12xx/wl1271_reg.h
@@ -34,7 +34,7 @@
34#define REGISTERS_WORK_SIZE 0x0000b000 34#define REGISTERS_WORK_SIZE 0x0000b000
35 35
36#define HW_ACCESS_ELP_CTRL_REG_ADDR 0x1FFFC 36#define HW_ACCESS_ELP_CTRL_REG_ADDR 0x1FFFC
37#define STATUS_MEM_ADDRESS 0x40400 37#define FW_STATUS_ADDR (0x14FC0 + 0xA000)
38 38
39/* ELP register commands */ 39/* ELP register commands */
40#define ELPCTRL_WAKE_UP 0x1 40#define ELPCTRL_WAKE_UP 0x1