diff options
author | John W. Linville <linville@tuxdriver.com> | 2012-09-24 14:37:36 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-09-24 14:37:36 -0400 |
commit | e5a876250d05d9708895da3d5408bdf67f1180f3 (patch) | |
tree | 92f2c844912ebd4d91741980a2cd56544c2906d7 /drivers | |
parent | 9b4e9e756541fd5d1223b323ed5a8a8545dd11cd (diff) | |
parent | 83f84d7bd49f9e4deea0a77a76c9882673ee1f3c (diff) |
Merge branch 'for-john' of git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/iwlwifi/dvm/ucode.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-drv.c | 26 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-fw.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/pcie/drv.c | 13 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/pcie/internal.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/pcie/rx.c | 75 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/pcie/trans.c | 84 |
7 files changed, 117 insertions, 90 deletions
diff --git a/drivers/net/wireless/iwlwifi/dvm/ucode.c b/drivers/net/wireless/iwlwifi/dvm/ucode.c index 6d8d6dd7943f..2cb1efbc5ed1 100644 --- a/drivers/net/wireless/iwlwifi/dvm/ucode.c +++ b/drivers/net/wireless/iwlwifi/dvm/ucode.c | |||
@@ -295,7 +295,7 @@ static int iwl_alive_notify(struct iwl_priv *priv) | |||
295 | static int iwl_verify_sec_sparse(struct iwl_priv *priv, | 295 | static int iwl_verify_sec_sparse(struct iwl_priv *priv, |
296 | const struct fw_desc *fw_desc) | 296 | const struct fw_desc *fw_desc) |
297 | { | 297 | { |
298 | __le32 *image = (__le32 *)fw_desc->v_addr; | 298 | __le32 *image = (__le32 *)fw_desc->data; |
299 | u32 len = fw_desc->len; | 299 | u32 len = fw_desc->len; |
300 | u32 val; | 300 | u32 val; |
301 | u32 i; | 301 | u32 i; |
@@ -319,7 +319,7 @@ static int iwl_verify_sec_sparse(struct iwl_priv *priv, | |||
319 | static void iwl_print_mismatch_sec(struct iwl_priv *priv, | 319 | static void iwl_print_mismatch_sec(struct iwl_priv *priv, |
320 | const struct fw_desc *fw_desc) | 320 | const struct fw_desc *fw_desc) |
321 | { | 321 | { |
322 | __le32 *image = (__le32 *)fw_desc->v_addr; | 322 | __le32 *image = (__le32 *)fw_desc->data; |
323 | u32 len = fw_desc->len; | 323 | u32 len = fw_desc->len; |
324 | u32 val; | 324 | u32 val; |
325 | u32 offs; | 325 | u32 offs; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c index 48d6d44c16d0..198634b75ed0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/iwlwifi/iwl-drv.c | |||
@@ -64,6 +64,7 @@ | |||
64 | #include <linux/dma-mapping.h> | 64 | #include <linux/dma-mapping.h> |
65 | #include <linux/firmware.h> | 65 | #include <linux/firmware.h> |
66 | #include <linux/module.h> | 66 | #include <linux/module.h> |
67 | #include <linux/vmalloc.h> | ||
67 | 68 | ||
68 | #include "iwl-drv.h" | 69 | #include "iwl-drv.h" |
69 | #include "iwl-debug.h" | 70 | #include "iwl-debug.h" |
@@ -164,10 +165,8 @@ struct fw_sec { | |||
164 | 165 | ||
165 | static void iwl_free_fw_desc(struct iwl_drv *drv, struct fw_desc *desc) | 166 | static void iwl_free_fw_desc(struct iwl_drv *drv, struct fw_desc *desc) |
166 | { | 167 | { |
167 | if (desc->v_addr) | 168 | vfree(desc->data); |
168 | dma_free_coherent(drv->trans->dev, desc->len, | 169 | desc->data = NULL; |
169 | desc->v_addr, desc->p_addr); | ||
170 | desc->v_addr = NULL; | ||
171 | desc->len = 0; | 170 | desc->len = 0; |
172 | } | 171 | } |
173 | 172 | ||
@@ -186,21 +185,24 @@ static void iwl_dealloc_ucode(struct iwl_drv *drv) | |||
186 | } | 185 | } |
187 | 186 | ||
188 | static int iwl_alloc_fw_desc(struct iwl_drv *drv, struct fw_desc *desc, | 187 | static int iwl_alloc_fw_desc(struct iwl_drv *drv, struct fw_desc *desc, |
189 | struct fw_sec *sec) | 188 | struct fw_sec *sec) |
190 | { | 189 | { |
191 | if (!sec || !sec->size) { | 190 | void *data; |
192 | desc->v_addr = NULL; | 191 | |
192 | desc->data = NULL; | ||
193 | |||
194 | if (!sec || !sec->size) | ||
193 | return -EINVAL; | 195 | return -EINVAL; |
194 | } | ||
195 | 196 | ||
196 | desc->v_addr = dma_alloc_coherent(drv->trans->dev, sec->size, | 197 | data = vmalloc(sec->size); |
197 | &desc->p_addr, GFP_KERNEL); | 198 | if (!data) |
198 | if (!desc->v_addr) | ||
199 | return -ENOMEM; | 199 | return -ENOMEM; |
200 | 200 | ||
201 | desc->len = sec->size; | 201 | desc->len = sec->size; |
202 | desc->offset = sec->offset; | 202 | desc->offset = sec->offset; |
203 | memcpy(desc->v_addr, sec->data, sec->size); | 203 | memcpy(data, sec->data, desc->len); |
204 | desc->data = data; | ||
205 | |||
204 | return 0; | 206 | return 0; |
205 | } | 207 | } |
206 | 208 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw.h b/drivers/net/wireless/iwlwifi/iwl-fw.h index 2153e4cc5572..d1a86b66bc51 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fw.h +++ b/drivers/net/wireless/iwlwifi/iwl-fw.h | |||
@@ -124,8 +124,7 @@ struct iwl_ucode_capabilities { | |||
124 | 124 | ||
125 | /* one for each uCode image (inst/data, init/runtime/wowlan) */ | 125 | /* one for each uCode image (inst/data, init/runtime/wowlan) */ |
126 | struct fw_desc { | 126 | struct fw_desc { |
127 | dma_addr_t p_addr; /* hardware address */ | 127 | const void *data; /* vmalloc'ed data */ |
128 | void *v_addr; /* software address */ | ||
129 | u32 len; /* size in bytes */ | 128 | u32 len; /* size in bytes */ |
130 | u32 offset; /* offset in the device */ | 129 | u32 offset; /* offset in the device */ |
131 | }; | 130 | }; |
diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c index 89bfb43f4946..2a4675396707 100644 --- a/drivers/net/wireless/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/iwlwifi/pcie/drv.c | |||
@@ -263,8 +263,6 @@ MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids); | |||
263 | /* PCI registers */ | 263 | /* PCI registers */ |
264 | #define PCI_CFG_RETRY_TIMEOUT 0x041 | 264 | #define PCI_CFG_RETRY_TIMEOUT 0x041 |
265 | 265 | ||
266 | #ifndef CONFIG_IWLWIFI_IDI | ||
267 | |||
268 | static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | 266 | static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) |
269 | { | 267 | { |
270 | const struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data); | 268 | const struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data); |
@@ -307,8 +305,6 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev) | |||
307 | pci_set_drvdata(pdev, NULL); | 305 | pci_set_drvdata(pdev, NULL); |
308 | } | 306 | } |
309 | 307 | ||
310 | #endif /* CONFIG_IWLWIFI_IDI */ | ||
311 | |||
312 | #ifdef CONFIG_PM_SLEEP | 308 | #ifdef CONFIG_PM_SLEEP |
313 | 309 | ||
314 | static int iwl_pci_suspend(struct device *device) | 310 | static int iwl_pci_suspend(struct device *device) |
@@ -353,15 +349,6 @@ static SIMPLE_DEV_PM_OPS(iwl_dev_pm_ops, iwl_pci_suspend, iwl_pci_resume); | |||
353 | 349 | ||
354 | #endif | 350 | #endif |
355 | 351 | ||
356 | #ifdef CONFIG_IWLWIFI_IDI | ||
357 | /* | ||
358 | * Defined externally in iwl-idi.c | ||
359 | */ | ||
360 | int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent); | ||
361 | void __devexit iwl_pci_remove(struct pci_dev *pdev); | ||
362 | |||
363 | #endif /* CONFIG_IWLWIFI_IDI */ | ||
364 | |||
365 | static struct pci_driver iwl_pci_driver = { | 352 | static struct pci_driver iwl_pci_driver = { |
366 | .name = DRV_NAME, | 353 | .name = DRV_NAME, |
367 | .id_table = iwl_hw_card_ids, | 354 | .id_table = iwl_hw_card_ids, |
diff --git a/drivers/net/wireless/iwlwifi/pcie/internal.h b/drivers/net/wireless/iwlwifi/pcie/internal.h index 71c79943e633..401178f44a3b 100644 --- a/drivers/net/wireless/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/iwlwifi/pcie/internal.h | |||
@@ -311,7 +311,7 @@ void iwl_trans_pcie_free(struct iwl_trans *trans); | |||
311 | ******************************************************/ | 311 | ******************************************************/ |
312 | void iwl_bg_rx_replenish(struct work_struct *data); | 312 | void iwl_bg_rx_replenish(struct work_struct *data); |
313 | void iwl_irq_tasklet(struct iwl_trans *trans); | 313 | void iwl_irq_tasklet(struct iwl_trans *trans); |
314 | void iwlagn_rx_replenish(struct iwl_trans *trans); | 314 | void iwl_rx_replenish(struct iwl_trans *trans); |
315 | void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans, | 315 | void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans, |
316 | struct iwl_rx_queue *q); | 316 | struct iwl_rx_queue *q); |
317 | 317 | ||
diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c index 498372008810..17c8e5d82681 100644 --- a/drivers/net/wireless/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/iwlwifi/pcie/rx.c | |||
@@ -35,10 +35,6 @@ | |||
35 | #include "internal.h" | 35 | #include "internal.h" |
36 | #include "iwl-op-mode.h" | 36 | #include "iwl-op-mode.h" |
37 | 37 | ||
38 | #ifdef CONFIG_IWLWIFI_IDI | ||
39 | #include "iwl-amfh.h" | ||
40 | #endif | ||
41 | |||
42 | /****************************************************************************** | 38 | /****************************************************************************** |
43 | * | 39 | * |
44 | * RX path functions | 40 | * RX path functions |
@@ -181,15 +177,15 @@ void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans, | |||
181 | } | 177 | } |
182 | 178 | ||
183 | /** | 179 | /** |
184 | * iwlagn_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr | 180 | * iwl_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr |
185 | */ | 181 | */ |
186 | static inline __le32 iwlagn_dma_addr2rbd_ptr(dma_addr_t dma_addr) | 182 | static inline __le32 iwl_dma_addr2rbd_ptr(dma_addr_t dma_addr) |
187 | { | 183 | { |
188 | return cpu_to_le32((u32)(dma_addr >> 8)); | 184 | return cpu_to_le32((u32)(dma_addr >> 8)); |
189 | } | 185 | } |
190 | 186 | ||
191 | /** | 187 | /** |
192 | * iwlagn_rx_queue_restock - refill RX queue from pre-allocated pool | 188 | * iwl_rx_queue_restock - refill RX queue from pre-allocated pool |
193 | * | 189 | * |
194 | * If there are slots in the RX queue that need to be restocked, | 190 | * If there are slots in the RX queue that need to be restocked, |
195 | * and we have free pre-allocated buffers, fill the ranks as much | 191 | * and we have free pre-allocated buffers, fill the ranks as much |
@@ -199,7 +195,7 @@ static inline __le32 iwlagn_dma_addr2rbd_ptr(dma_addr_t dma_addr) | |||
199 | * also updates the memory address in the firmware to reference the new | 195 | * also updates the memory address in the firmware to reference the new |
200 | * target buffer. | 196 | * target buffer. |
201 | */ | 197 | */ |
202 | static void iwlagn_rx_queue_restock(struct iwl_trans *trans) | 198 | static void iwl_rx_queue_restock(struct iwl_trans *trans) |
203 | { | 199 | { |
204 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 200 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
205 | struct iwl_rx_queue *rxq = &trans_pcie->rxq; | 201 | struct iwl_rx_queue *rxq = &trans_pcie->rxq; |
@@ -207,6 +203,17 @@ static void iwlagn_rx_queue_restock(struct iwl_trans *trans) | |||
207 | struct iwl_rx_mem_buffer *rxb; | 203 | struct iwl_rx_mem_buffer *rxb; |
208 | unsigned long flags; | 204 | unsigned long flags; |
209 | 205 | ||
206 | /* | ||
207 | * If the device isn't enabled - not need to try to add buffers... | ||
208 | * This can happen when we stop the device and still have an interrupt | ||
209 | * pending. We stop the APM before we sync the interrupts / tasklets | ||
210 | * because we have to (see comment there). On the other hand, since | ||
211 | * the APM is stopped, we cannot access the HW (in particular not prph). | ||
212 | * So don't try to restock if the APM has been already stopped. | ||
213 | */ | ||
214 | if (!test_bit(STATUS_DEVICE_ENABLED, &trans_pcie->status)) | ||
215 | return; | ||
216 | |||
210 | spin_lock_irqsave(&rxq->lock, flags); | 217 | spin_lock_irqsave(&rxq->lock, flags); |
211 | while ((iwl_rx_queue_space(rxq) > 0) && (rxq->free_count)) { | 218 | while ((iwl_rx_queue_space(rxq) > 0) && (rxq->free_count)) { |
212 | /* The overwritten rxb must be a used one */ | 219 | /* The overwritten rxb must be a used one */ |
@@ -219,7 +226,7 @@ static void iwlagn_rx_queue_restock(struct iwl_trans *trans) | |||
219 | list_del(element); | 226 | list_del(element); |
220 | 227 | ||
221 | /* Point to Rx buffer via next RBD in circular buffer */ | 228 | /* Point to Rx buffer via next RBD in circular buffer */ |
222 | rxq->bd[rxq->write] = iwlagn_dma_addr2rbd_ptr(rxb->page_dma); | 229 | rxq->bd[rxq->write] = iwl_dma_addr2rbd_ptr(rxb->page_dma); |
223 | rxq->queue[rxq->write] = rxb; | 230 | rxq->queue[rxq->write] = rxb; |
224 | rxq->write = (rxq->write + 1) & RX_QUEUE_MASK; | 231 | rxq->write = (rxq->write + 1) & RX_QUEUE_MASK; |
225 | rxq->free_count--; | 232 | rxq->free_count--; |
@@ -230,7 +237,6 @@ static void iwlagn_rx_queue_restock(struct iwl_trans *trans) | |||
230 | if (rxq->free_count <= RX_LOW_WATERMARK) | 237 | if (rxq->free_count <= RX_LOW_WATERMARK) |
231 | schedule_work(&trans_pcie->rx_replenish); | 238 | schedule_work(&trans_pcie->rx_replenish); |
232 | 239 | ||
233 | |||
234 | /* If we've added more space for the firmware to place data, tell it. | 240 | /* If we've added more space for the firmware to place data, tell it. |
235 | * Increment device's write pointer in multiples of 8. */ | 241 | * Increment device's write pointer in multiples of 8. */ |
236 | if (rxq->write_actual != (rxq->write & ~0x7)) { | 242 | if (rxq->write_actual != (rxq->write & ~0x7)) { |
@@ -241,15 +247,16 @@ static void iwlagn_rx_queue_restock(struct iwl_trans *trans) | |||
241 | } | 247 | } |
242 | } | 248 | } |
243 | 249 | ||
244 | /** | 250 | /* |
245 | * iwlagn_rx_replenish - Move all used packet from rx_used to rx_free | 251 | * iwl_rx_allocate - allocate a page for each used RBD |
246 | * | ||
247 | * When moving to rx_free an SKB is allocated for the slot. | ||
248 | * | 252 | * |
249 | * Also restock the Rx queue via iwl_rx_queue_restock. | 253 | * A used RBD is an Rx buffer that has been given to the stack. To use it again |
250 | * This is called as a scheduled work item (except for during initialization) | 254 | * a page must be allocated and the RBD must point to the page. This function |
255 | * doesn't change the HW pointer but handles the list of pages that is used by | ||
256 | * iwl_rx_queue_restock. The latter function will update the HW to use the newly | ||
257 | * allocated buffers. | ||
251 | */ | 258 | */ |
252 | static void iwlagn_rx_allocate(struct iwl_trans *trans, gfp_t priority) | 259 | static void iwl_rx_allocate(struct iwl_trans *trans, gfp_t priority) |
253 | { | 260 | { |
254 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 261 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
255 | struct iwl_rx_queue *rxq = &trans_pcie->rxq; | 262 | struct iwl_rx_queue *rxq = &trans_pcie->rxq; |
@@ -328,23 +335,31 @@ static void iwlagn_rx_allocate(struct iwl_trans *trans, gfp_t priority) | |||
328 | } | 335 | } |
329 | } | 336 | } |
330 | 337 | ||
331 | void iwlagn_rx_replenish(struct iwl_trans *trans) | 338 | /* |
339 | * iwl_rx_replenish - Move all used buffers from rx_used to rx_free | ||
340 | * | ||
341 | * When moving to rx_free an page is allocated for the slot. | ||
342 | * | ||
343 | * Also restock the Rx queue via iwl_rx_queue_restock. | ||
344 | * This is called as a scheduled work item (except for during initialization) | ||
345 | */ | ||
346 | void iwl_rx_replenish(struct iwl_trans *trans) | ||
332 | { | 347 | { |
333 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 348 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
334 | unsigned long flags; | 349 | unsigned long flags; |
335 | 350 | ||
336 | iwlagn_rx_allocate(trans, GFP_KERNEL); | 351 | iwl_rx_allocate(trans, GFP_KERNEL); |
337 | 352 | ||
338 | spin_lock_irqsave(&trans_pcie->irq_lock, flags); | 353 | spin_lock_irqsave(&trans_pcie->irq_lock, flags); |
339 | iwlagn_rx_queue_restock(trans); | 354 | iwl_rx_queue_restock(trans); |
340 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); | 355 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); |
341 | } | 356 | } |
342 | 357 | ||
343 | static void iwlagn_rx_replenish_now(struct iwl_trans *trans) | 358 | static void iwl_rx_replenish_now(struct iwl_trans *trans) |
344 | { | 359 | { |
345 | iwlagn_rx_allocate(trans, GFP_ATOMIC); | 360 | iwl_rx_allocate(trans, GFP_ATOMIC); |
346 | 361 | ||
347 | iwlagn_rx_queue_restock(trans); | 362 | iwl_rx_queue_restock(trans); |
348 | } | 363 | } |
349 | 364 | ||
350 | void iwl_bg_rx_replenish(struct work_struct *data) | 365 | void iwl_bg_rx_replenish(struct work_struct *data) |
@@ -352,7 +367,7 @@ void iwl_bg_rx_replenish(struct work_struct *data) | |||
352 | struct iwl_trans_pcie *trans_pcie = | 367 | struct iwl_trans_pcie *trans_pcie = |
353 | container_of(data, struct iwl_trans_pcie, rx_replenish); | 368 | container_of(data, struct iwl_trans_pcie, rx_replenish); |
354 | 369 | ||
355 | iwlagn_rx_replenish(trans_pcie->trans); | 370 | iwl_rx_replenish(trans_pcie->trans); |
356 | } | 371 | } |
357 | 372 | ||
358 | static void iwl_rx_handle_rxbuf(struct iwl_trans *trans, | 373 | static void iwl_rx_handle_rxbuf(struct iwl_trans *trans, |
@@ -530,7 +545,7 @@ static void iwl_rx_handle(struct iwl_trans *trans) | |||
530 | count++; | 545 | count++; |
531 | if (count >= 8) { | 546 | if (count >= 8) { |
532 | rxq->read = i; | 547 | rxq->read = i; |
533 | iwlagn_rx_replenish_now(trans); | 548 | iwl_rx_replenish_now(trans); |
534 | count = 0; | 549 | count = 0; |
535 | } | 550 | } |
536 | } | 551 | } |
@@ -539,9 +554,9 @@ static void iwl_rx_handle(struct iwl_trans *trans) | |||
539 | /* Backtrack one entry */ | 554 | /* Backtrack one entry */ |
540 | rxq->read = i; | 555 | rxq->read = i; |
541 | if (fill_rx) | 556 | if (fill_rx) |
542 | iwlagn_rx_replenish_now(trans); | 557 | iwl_rx_replenish_now(trans); |
543 | else | 558 | else |
544 | iwlagn_rx_queue_restock(trans); | 559 | iwl_rx_queue_restock(trans); |
545 | } | 560 | } |
546 | 561 | ||
547 | /** | 562 | /** |
@@ -723,11 +738,9 @@ void iwl_irq_tasklet(struct iwl_trans *trans) | |||
723 | /* Disable periodic interrupt; we use it as just a one-shot. */ | 738 | /* Disable periodic interrupt; we use it as just a one-shot. */ |
724 | iwl_write8(trans, CSR_INT_PERIODIC_REG, | 739 | iwl_write8(trans, CSR_INT_PERIODIC_REG, |
725 | CSR_INT_PERIODIC_DIS); | 740 | CSR_INT_PERIODIC_DIS); |
726 | #ifdef CONFIG_IWLWIFI_IDI | 741 | |
727 | iwl_amfh_rx_handler(); | ||
728 | #else | ||
729 | iwl_rx_handle(trans); | 742 | iwl_rx_handle(trans); |
730 | #endif | 743 | |
731 | /* | 744 | /* |
732 | * Enable periodic interrupt in 8 msec only if we received | 745 | * Enable periodic interrupt in 8 msec only if we received |
733 | * real RX interrupt (instead of just periodic int), to catch | 746 | * real RX interrupt (instead of just periodic int), to catch |
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c index 848851177e7e..d0c0fe7edc2f 100644 --- a/drivers/net/wireless/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/iwlwifi/pcie/trans.c | |||
@@ -216,7 +216,7 @@ static int iwl_rx_init(struct iwl_trans *trans) | |||
216 | rxq->free_count = 0; | 216 | rxq->free_count = 0; |
217 | spin_unlock_irqrestore(&rxq->lock, flags); | 217 | spin_unlock_irqrestore(&rxq->lock, flags); |
218 | 218 | ||
219 | iwlagn_rx_replenish(trans); | 219 | iwl_rx_replenish(trans); |
220 | 220 | ||
221 | iwl_trans_rx_hw_init(trans, rxq); | 221 | iwl_trans_rx_hw_init(trans, rxq); |
222 | 222 | ||
@@ -855,10 +855,8 @@ static int iwl_nic_init(struct iwl_trans *trans) | |||
855 | 855 | ||
856 | iwl_op_mode_nic_config(trans->op_mode); | 856 | iwl_op_mode_nic_config(trans->op_mode); |
857 | 857 | ||
858 | #ifndef CONFIG_IWLWIFI_IDI | ||
859 | /* Allocate the RX queue, or reset if it is already allocated */ | 858 | /* Allocate the RX queue, or reset if it is already allocated */ |
860 | iwl_rx_init(trans); | 859 | iwl_rx_init(trans); |
861 | #endif | ||
862 | 860 | ||
863 | /* Allocate or reset and init all Tx and Command queues */ | 861 | /* Allocate or reset and init all Tx and Command queues */ |
864 | if (iwl_tx_init(trans)) | 862 | if (iwl_tx_init(trans)) |
@@ -925,13 +923,10 @@ static int iwl_prepare_card_hw(struct iwl_trans *trans) | |||
925 | /* | 923 | /* |
926 | * ucode | 924 | * ucode |
927 | */ | 925 | */ |
928 | static int iwl_load_section(struct iwl_trans *trans, u8 section_num, | 926 | static int iwl_load_firmware_chunk(struct iwl_trans *trans, u32 dst_addr, |
929 | const struct fw_desc *section) | 927 | dma_addr_t phy_addr, u32 byte_cnt) |
930 | { | 928 | { |
931 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 929 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
932 | dma_addr_t phy_addr = section->p_addr; | ||
933 | u32 byte_cnt = section->len; | ||
934 | u32 dst_addr = section->offset; | ||
935 | int ret; | 930 | int ret; |
936 | 931 | ||
937 | trans_pcie->ucode_write_complete = false; | 932 | trans_pcie->ucode_write_complete = false; |
@@ -945,8 +940,8 @@ static int iwl_load_section(struct iwl_trans *trans, u8 section_num, | |||
945 | dst_addr); | 940 | dst_addr); |
946 | 941 | ||
947 | iwl_write_direct32(trans, | 942 | iwl_write_direct32(trans, |
948 | FH_TFDIB_CTRL0_REG(FH_SRVC_CHNL), | 943 | FH_TFDIB_CTRL0_REG(FH_SRVC_CHNL), |
949 | phy_addr & FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK); | 944 | phy_addr & FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK); |
950 | 945 | ||
951 | iwl_write_direct32(trans, | 946 | iwl_write_direct32(trans, |
952 | FH_TFDIB_CTRL1_REG(FH_SRVC_CHNL), | 947 | FH_TFDIB_CTRL1_REG(FH_SRVC_CHNL), |
@@ -965,33 +960,64 @@ static int iwl_load_section(struct iwl_trans *trans, u8 section_num, | |||
965 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE | | 960 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE | |
966 | FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD); | 961 | FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD); |
967 | 962 | ||
968 | IWL_DEBUG_FW(trans, "[%d] uCode section being loaded...\n", | ||
969 | section_num); | ||
970 | ret = wait_event_timeout(trans_pcie->ucode_write_waitq, | 963 | ret = wait_event_timeout(trans_pcie->ucode_write_waitq, |
971 | trans_pcie->ucode_write_complete, 5 * HZ); | 964 | trans_pcie->ucode_write_complete, 5 * HZ); |
972 | if (!ret) { | 965 | if (!ret) { |
973 | IWL_ERR(trans, "Could not load the [%d] uCode section\n", | 966 | IWL_ERR(trans, "Failed to load firmware chunk!\n"); |
974 | section_num); | ||
975 | return -ETIMEDOUT; | 967 | return -ETIMEDOUT; |
976 | } | 968 | } |
977 | 969 | ||
978 | return 0; | 970 | return 0; |
979 | } | 971 | } |
980 | 972 | ||
981 | static int iwl_load_given_ucode(struct iwl_trans *trans, | 973 | static int iwl_load_section(struct iwl_trans *trans, u8 section_num, |
982 | const struct fw_img *image) | 974 | const struct fw_desc *section) |
983 | { | 975 | { |
976 | u8 *v_addr; | ||
977 | dma_addr_t p_addr; | ||
978 | u32 offset; | ||
984 | int ret = 0; | 979 | int ret = 0; |
985 | int i; | ||
986 | 980 | ||
987 | for (i = 0; i < IWL_UCODE_SECTION_MAX; i++) { | 981 | IWL_DEBUG_FW(trans, "[%d] uCode section being loaded...\n", |
988 | if (!image->sec[i].p_addr) | 982 | section_num); |
989 | break; | ||
990 | 983 | ||
991 | ret = iwl_load_section(trans, i, &image->sec[i]); | 984 | v_addr = dma_alloc_coherent(trans->dev, PAGE_SIZE, &p_addr, GFP_KERNEL); |
992 | if (ret) | 985 | if (!v_addr) |
993 | return ret; | 986 | return -ENOMEM; |
987 | |||
988 | for (offset = 0; offset < section->len; offset += PAGE_SIZE) { | ||
989 | u32 copy_size; | ||
990 | |||
991 | copy_size = min_t(u32, PAGE_SIZE, section->len - offset); | ||
992 | |||
993 | memcpy(v_addr, (u8 *)section->data + offset, copy_size); | ||
994 | ret = iwl_load_firmware_chunk(trans, section->offset + offset, | ||
995 | p_addr, copy_size); | ||
996 | if (ret) { | ||
997 | IWL_ERR(trans, | ||
998 | "Could not load the [%d] uCode section\n", | ||
999 | section_num); | ||
1000 | break; | ||
994 | } | 1001 | } |
1002 | } | ||
1003 | |||
1004 | dma_free_coherent(trans->dev, PAGE_SIZE, v_addr, p_addr); | ||
1005 | return ret; | ||
1006 | } | ||
1007 | |||
1008 | static int iwl_load_given_ucode(struct iwl_trans *trans, | ||
1009 | const struct fw_img *image) | ||
1010 | { | ||
1011 | int i, ret = 0; | ||
1012 | |||
1013 | for (i = 0; i < IWL_UCODE_SECTION_MAX; i++) { | ||
1014 | if (!image->sec[i].data) | ||
1015 | break; | ||
1016 | |||
1017 | ret = iwl_load_section(trans, i, &image->sec[i]); | ||
1018 | if (ret) | ||
1019 | return ret; | ||
1020 | } | ||
995 | 1021 | ||
996 | /* Remove all resets to allow NIC to operate */ | 1022 | /* Remove all resets to allow NIC to operate */ |
997 | iwl_write32(trans, CSR_RESET, 0); | 1023 | iwl_write32(trans, CSR_RESET, 0); |
@@ -1184,9 +1210,8 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) | |||
1184 | */ | 1210 | */ |
1185 | if (test_bit(STATUS_DEVICE_ENABLED, &trans_pcie->status)) { | 1211 | if (test_bit(STATUS_DEVICE_ENABLED, &trans_pcie->status)) { |
1186 | iwl_trans_tx_stop(trans); | 1212 | iwl_trans_tx_stop(trans); |
1187 | #ifndef CONFIG_IWLWIFI_IDI | ||
1188 | iwl_trans_rx_stop(trans); | 1213 | iwl_trans_rx_stop(trans); |
1189 | #endif | 1214 | |
1190 | /* Power-down device's busmaster DMA clocks */ | 1215 | /* Power-down device's busmaster DMA clocks */ |
1191 | iwl_write_prph(trans, APMG_CLK_DIS_REG, | 1216 | iwl_write_prph(trans, APMG_CLK_DIS_REG, |
1192 | APMG_CLK_VAL_DMA_CLK_RQT); | 1217 | APMG_CLK_VAL_DMA_CLK_RQT); |
@@ -1456,14 +1481,16 @@ static void iwl_trans_pcie_stop_hw(struct iwl_trans *trans, | |||
1456 | bool hw_rfkill; | 1481 | bool hw_rfkill; |
1457 | unsigned long flags; | 1482 | unsigned long flags; |
1458 | 1483 | ||
1484 | spin_lock_irqsave(&trans_pcie->irq_lock, flags); | ||
1485 | iwl_disable_interrupts(trans); | ||
1486 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); | ||
1487 | |||
1459 | iwl_apm_stop(trans); | 1488 | iwl_apm_stop(trans); |
1460 | 1489 | ||
1461 | spin_lock_irqsave(&trans_pcie->irq_lock, flags); | 1490 | spin_lock_irqsave(&trans_pcie->irq_lock, flags); |
1462 | iwl_disable_interrupts(trans); | 1491 | iwl_disable_interrupts(trans); |
1463 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); | 1492 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); |
1464 | 1493 | ||
1465 | iwl_write32(trans, CSR_INT, 0xFFFFFFFF); | ||
1466 | |||
1467 | if (!op_mode_leaving) { | 1494 | if (!op_mode_leaving) { |
1468 | /* | 1495 | /* |
1469 | * Even if we stop the HW, we still want the RF kill | 1496 | * Even if we stop the HW, we still want the RF kill |
@@ -1551,9 +1578,8 @@ void iwl_trans_pcie_free(struct iwl_trans *trans) | |||
1551 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 1578 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
1552 | 1579 | ||
1553 | iwl_trans_pcie_tx_free(trans); | 1580 | iwl_trans_pcie_tx_free(trans); |
1554 | #ifndef CONFIG_IWLWIFI_IDI | ||
1555 | iwl_trans_pcie_rx_free(trans); | 1581 | iwl_trans_pcie_rx_free(trans); |
1556 | #endif | 1582 | |
1557 | if (trans_pcie->irq_requested == true) { | 1583 | if (trans_pcie->irq_requested == true) { |
1558 | free_irq(trans_pcie->irq, trans); | 1584 | free_irq(trans_pcie->irq, trans); |
1559 | iwl_free_isr_ict(trans); | 1585 | iwl_free_isr_ict(trans); |