diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-4965.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-4965.c | 339 |
1 files changed, 2 insertions, 337 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 9e6f3e33ab66..319ffe747a70 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c | |||
@@ -53,8 +53,6 @@ static struct iwl_mod_params iwl4965_mod_params = { | |||
53 | /* the rest are 0 by default */ | 53 | /* the rest are 0 by default */ |
54 | }; | 54 | }; |
55 | 55 | ||
56 | static void iwl4965_hw_card_show_info(struct iwl_priv *priv); | ||
57 | |||
58 | #ifdef CONFIG_IWL4965_HT | 56 | #ifdef CONFIG_IWL4965_HT |
59 | 57 | ||
60 | static const u16 default_tid_to_tx_fifo[] = { | 58 | static const u16 default_tid_to_tx_fifo[] = { |
@@ -372,104 +370,6 @@ int iwl4965_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src) | |||
372 | return ret; | 370 | return ret; |
373 | } | 371 | } |
374 | 372 | ||
375 | static int iwl4965_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq) | ||
376 | { | ||
377 | int ret; | ||
378 | unsigned long flags; | ||
379 | unsigned int rb_size; | ||
380 | |||
381 | spin_lock_irqsave(&priv->lock, flags); | ||
382 | ret = iwl_grab_nic_access(priv); | ||
383 | if (ret) { | ||
384 | spin_unlock_irqrestore(&priv->lock, flags); | ||
385 | return ret; | ||
386 | } | ||
387 | |||
388 | if (priv->cfg->mod_params->amsdu_size_8K) | ||
389 | rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K; | ||
390 | else | ||
391 | rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K; | ||
392 | |||
393 | /* Stop Rx DMA */ | ||
394 | iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); | ||
395 | |||
396 | /* Reset driver's Rx queue write index */ | ||
397 | iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0); | ||
398 | |||
399 | /* Tell device where to find RBD circular buffer in DRAM */ | ||
400 | iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_BASE_REG, | ||
401 | rxq->dma_addr >> 8); | ||
402 | |||
403 | /* Tell device where in DRAM to update its Rx status */ | ||
404 | iwl_write_direct32(priv, FH_RSCSR_CHNL0_STTS_WPTR_REG, | ||
405 | (priv->shared_phys + | ||
406 | offsetof(struct iwl4965_shared, rb_closed)) >> 4); | ||
407 | |||
408 | /* Enable Rx DMA, enable host interrupt, Rx buffer size 4k, 256 RBDs */ | ||
409 | iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, | ||
410 | FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL | | ||
411 | FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL | | ||
412 | rb_size | | ||
413 | /* 0x10 << 4 | */ | ||
414 | (RX_QUEUE_SIZE_LOG << | ||
415 | FH_RCSR_RX_CONFIG_RBDCB_SIZE_BITSHIFT)); | ||
416 | |||
417 | /* | ||
418 | * iwl_write32(priv,CSR_INT_COAL_REG,0); | ||
419 | */ | ||
420 | |||
421 | iwl_release_nic_access(priv); | ||
422 | spin_unlock_irqrestore(&priv->lock, flags); | ||
423 | |||
424 | return 0; | ||
425 | } | ||
426 | |||
427 | /* Tell 4965 where to find the "keep warm" buffer */ | ||
428 | static int iwl4965_kw_init(struct iwl_priv *priv) | ||
429 | { | ||
430 | unsigned long flags; | ||
431 | int rc; | ||
432 | |||
433 | spin_lock_irqsave(&priv->lock, flags); | ||
434 | rc = iwl_grab_nic_access(priv); | ||
435 | if (rc) | ||
436 | goto out; | ||
437 | |||
438 | iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, | ||
439 | priv->kw.dma_addr >> 4); | ||
440 | iwl_release_nic_access(priv); | ||
441 | out: | ||
442 | spin_unlock_irqrestore(&priv->lock, flags); | ||
443 | return rc; | ||
444 | } | ||
445 | |||
446 | static int iwl4965_kw_alloc(struct iwl_priv *priv) | ||
447 | { | ||
448 | struct pci_dev *dev = priv->pci_dev; | ||
449 | struct iwl4965_kw *kw = &priv->kw; | ||
450 | |||
451 | kw->size = IWL4965_KW_SIZE; /* TBW need set somewhere else */ | ||
452 | kw->v_addr = pci_alloc_consistent(dev, kw->size, &kw->dma_addr); | ||
453 | if (!kw->v_addr) | ||
454 | return -ENOMEM; | ||
455 | |||
456 | return 0; | ||
457 | } | ||
458 | |||
459 | /** | ||
460 | * iwl4965_kw_free - Free the "keep warm" buffer | ||
461 | */ | ||
462 | static void iwl4965_kw_free(struct iwl_priv *priv) | ||
463 | { | ||
464 | struct pci_dev *dev = priv->pci_dev; | ||
465 | struct iwl4965_kw *kw = &priv->kw; | ||
466 | |||
467 | if (kw->v_addr) { | ||
468 | pci_free_consistent(dev, kw->size, kw->v_addr, kw->dma_addr); | ||
469 | memset(kw, 0, sizeof(*kw)); | ||
470 | } | ||
471 | } | ||
472 | |||
473 | static int iwl4965_disable_tx_fifo(struct iwl_priv *priv) | 373 | static int iwl4965_disable_tx_fifo(struct iwl_priv *priv) |
474 | { | 374 | { |
475 | unsigned long flags; | 375 | unsigned long flags; |
@@ -491,65 +391,6 @@ static int iwl4965_disable_tx_fifo(struct iwl_priv *priv) | |||
491 | return 0; | 391 | return 0; |
492 | } | 392 | } |
493 | 393 | ||
494 | /** | ||
495 | * iwl4965_txq_ctx_reset - Reset TX queue context | ||
496 | * Destroys all DMA structures and initialise them again | ||
497 | * | ||
498 | * @param priv | ||
499 | * @return error code | ||
500 | */ | ||
501 | static int iwl4965_txq_ctx_reset(struct iwl_priv *priv) | ||
502 | { | ||
503 | int rc = 0; | ||
504 | int txq_id, slots_num; | ||
505 | |||
506 | iwl4965_kw_free(priv); | ||
507 | |||
508 | /* Free all tx/cmd queues and keep-warm buffer */ | ||
509 | iwl4965_hw_txq_ctx_free(priv); | ||
510 | |||
511 | /* Alloc keep-warm buffer */ | ||
512 | rc = iwl4965_kw_alloc(priv); | ||
513 | if (rc) { | ||
514 | IWL_ERROR("Keep Warm allocation failed"); | ||
515 | goto error_kw; | ||
516 | } | ||
517 | |||
518 | /* Turn off all Tx DMA fifos */ | ||
519 | rc = priv->cfg->ops->lib->disable_tx_fifo(priv); | ||
520 | if (unlikely(rc)) | ||
521 | goto error_reset; | ||
522 | |||
523 | /* Tell 4965 where to find the keep-warm buffer */ | ||
524 | rc = iwl4965_kw_init(priv); | ||
525 | if (rc) { | ||
526 | IWL_ERROR("kw_init failed\n"); | ||
527 | goto error_reset; | ||
528 | } | ||
529 | |||
530 | /* Alloc and init all (default 16) Tx queues, | ||
531 | * including the command queue (#4) */ | ||
532 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { | ||
533 | slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ? | ||
534 | TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; | ||
535 | rc = iwl4965_tx_queue_init(priv, &priv->txq[txq_id], slots_num, | ||
536 | txq_id); | ||
537 | if (rc) { | ||
538 | IWL_ERROR("Tx %d queue init failed\n", txq_id); | ||
539 | goto error; | ||
540 | } | ||
541 | } | ||
542 | |||
543 | return rc; | ||
544 | |||
545 | error: | ||
546 | iwl4965_hw_txq_ctx_free(priv); | ||
547 | error_reset: | ||
548 | iwl4965_kw_free(priv); | ||
549 | error_kw: | ||
550 | return rc; | ||
551 | } | ||
552 | |||
553 | static int iwl4965_apm_init(struct iwl_priv *priv) | 394 | static int iwl4965_apm_init(struct iwl_priv *priv) |
554 | { | 395 | { |
555 | unsigned long flags; | 396 | unsigned long flags; |
@@ -633,58 +474,6 @@ static void iwl4965_nic_config(struct iwl_priv *priv) | |||
633 | spin_unlock_irqrestore(&priv->lock, flags); | 474 | spin_unlock_irqrestore(&priv->lock, flags); |
634 | } | 475 | } |
635 | 476 | ||
636 | int iwl4965_hw_nic_init(struct iwl_priv *priv) | ||
637 | { | ||
638 | unsigned long flags; | ||
639 | struct iwl_rx_queue *rxq = &priv->rxq; | ||
640 | int ret; | ||
641 | |||
642 | /* nic_init */ | ||
643 | priv->cfg->ops->lib->apm_ops.init(priv); | ||
644 | |||
645 | spin_lock_irqsave(&priv->lock, flags); | ||
646 | iwl_write32(priv, CSR_INT_COALESCING, 512 / 32); | ||
647 | spin_unlock_irqrestore(&priv->lock, flags); | ||
648 | |||
649 | ret = priv->cfg->ops->lib->apm_ops.set_pwr_src(priv, IWL_PWR_SRC_VMAIN); | ||
650 | |||
651 | priv->cfg->ops->lib->apm_ops.config(priv); | ||
652 | |||
653 | iwl4965_hw_card_show_info(priv); | ||
654 | |||
655 | /* end nic_init */ | ||
656 | |||
657 | /* Allocate the RX queue, or reset if it is already allocated */ | ||
658 | if (!rxq->bd) { | ||
659 | ret = iwl_rx_queue_alloc(priv); | ||
660 | if (ret) { | ||
661 | IWL_ERROR("Unable to initialize Rx queue\n"); | ||
662 | return -ENOMEM; | ||
663 | } | ||
664 | } else | ||
665 | iwl_rx_queue_reset(priv, rxq); | ||
666 | |||
667 | iwl_rx_replenish(priv); | ||
668 | |||
669 | iwl4965_rx_init(priv, rxq); | ||
670 | |||
671 | spin_lock_irqsave(&priv->lock, flags); | ||
672 | |||
673 | rxq->need_update = 1; | ||
674 | iwl_rx_queue_update_write_ptr(priv, rxq); | ||
675 | |||
676 | spin_unlock_irqrestore(&priv->lock, flags); | ||
677 | |||
678 | /* Allocate and init all Tx and Command queues */ | ||
679 | ret = iwl4965_txq_ctx_reset(priv); | ||
680 | if (ret) | ||
681 | return ret; | ||
682 | |||
683 | set_bit(STATUS_INIT, &priv->status); | ||
684 | |||
685 | return 0; | ||
686 | } | ||
687 | |||
688 | int iwl4965_hw_nic_stop_master(struct iwl_priv *priv) | 477 | int iwl4965_hw_nic_stop_master(struct iwl_priv *priv) |
689 | { | 478 | { |
690 | int rc = 0; | 479 | int rc = 0; |
@@ -745,7 +534,7 @@ void iwl4965_hw_txq_ctx_stop(struct iwl_priv *priv) | |||
745 | } | 534 | } |
746 | 535 | ||
747 | /* Deallocate memory for all Tx queues */ | 536 | /* Deallocate memory for all Tx queues */ |
748 | iwl4965_hw_txq_ctx_free(priv); | 537 | iwl_hw_txq_ctx_free(priv); |
749 | } | 538 | } |
750 | 539 | ||
751 | int iwl4965_hw_nic_reset(struct iwl_priv *priv) | 540 | int iwl4965_hw_nic_reset(struct iwl_priv *priv) |
@@ -1199,82 +988,6 @@ int iwl4965_hw_set_hw_params(struct iwl_priv *priv) | |||
1199 | return 0; | 988 | return 0; |
1200 | } | 989 | } |
1201 | 990 | ||
1202 | /** | ||
1203 | * iwl4965_hw_txq_ctx_free - Free TXQ Context | ||
1204 | * | ||
1205 | * Destroy all TX DMA queues and structures | ||
1206 | */ | ||
1207 | void iwl4965_hw_txq_ctx_free(struct iwl_priv *priv) | ||
1208 | { | ||
1209 | int txq_id; | ||
1210 | |||
1211 | /* Tx queues */ | ||
1212 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) | ||
1213 | iwl4965_tx_queue_free(priv, &priv->txq[txq_id]); | ||
1214 | |||
1215 | /* Keep-warm buffer */ | ||
1216 | iwl4965_kw_free(priv); | ||
1217 | } | ||
1218 | |||
1219 | /** | ||
1220 | * iwl4965_hw_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr] | ||
1221 | * | ||
1222 | * Does NOT advance any TFD circular buffer read/write indexes | ||
1223 | * Does NOT free the TFD itself (which is within circular buffer) | ||
1224 | */ | ||
1225 | int iwl4965_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl4965_tx_queue *txq) | ||
1226 | { | ||
1227 | struct iwl4965_tfd_frame *bd_tmp = (struct iwl4965_tfd_frame *)&txq->bd[0]; | ||
1228 | struct iwl4965_tfd_frame *bd = &bd_tmp[txq->q.read_ptr]; | ||
1229 | struct pci_dev *dev = priv->pci_dev; | ||
1230 | int i; | ||
1231 | int counter = 0; | ||
1232 | int index, is_odd; | ||
1233 | |||
1234 | /* Host command buffers stay mapped in memory, nothing to clean */ | ||
1235 | if (txq->q.id == IWL_CMD_QUEUE_NUM) | ||
1236 | return 0; | ||
1237 | |||
1238 | /* Sanity check on number of chunks */ | ||
1239 | counter = IWL_GET_BITS(*bd, num_tbs); | ||
1240 | if (counter > MAX_NUM_OF_TBS) { | ||
1241 | IWL_ERROR("Too many chunks: %i\n", counter); | ||
1242 | /* @todo issue fatal error, it is quite serious situation */ | ||
1243 | return 0; | ||
1244 | } | ||
1245 | |||
1246 | /* Unmap chunks, if any. | ||
1247 | * TFD info for odd chunks is different format than for even chunks. */ | ||
1248 | for (i = 0; i < counter; i++) { | ||
1249 | index = i / 2; | ||
1250 | is_odd = i & 0x1; | ||
1251 | |||
1252 | if (is_odd) | ||
1253 | pci_unmap_single( | ||
1254 | dev, | ||
1255 | IWL_GET_BITS(bd->pa[index], tb2_addr_lo16) | | ||
1256 | (IWL_GET_BITS(bd->pa[index], | ||
1257 | tb2_addr_hi20) << 16), | ||
1258 | IWL_GET_BITS(bd->pa[index], tb2_len), | ||
1259 | PCI_DMA_TODEVICE); | ||
1260 | |||
1261 | else if (i > 0) | ||
1262 | pci_unmap_single(dev, | ||
1263 | le32_to_cpu(bd->pa[index].tb1_addr), | ||
1264 | IWL_GET_BITS(bd->pa[index], tb1_len), | ||
1265 | PCI_DMA_TODEVICE); | ||
1266 | |||
1267 | /* Free SKB, if any, for this chunk */ | ||
1268 | if (txq->txb[txq->q.read_ptr].skb[i]) { | ||
1269 | struct sk_buff *skb = txq->txb[txq->q.read_ptr].skb[i]; | ||
1270 | |||
1271 | dev_kfree_skb(skb); | ||
1272 | txq->txb[txq->q.read_ptr].skb[i] = NULL; | ||
1273 | } | ||
1274 | } | ||
1275 | return 0; | ||
1276 | } | ||
1277 | |||
1278 | /* set card power command */ | 991 | /* set card power command */ |
1279 | static int iwl4965_set_power(struct iwl_priv *priv, | 992 | static int iwl4965_set_power(struct iwl_priv *priv, |
1280 | void *cmd) | 993 | void *cmd) |
@@ -2240,46 +1953,11 @@ unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv, | |||
2240 | return (sizeof(*tx_beacon_cmd) + frame_size); | 1953 | return (sizeof(*tx_beacon_cmd) + frame_size); |
2241 | } | 1954 | } |
2242 | 1955 | ||
2243 | /* | ||
2244 | * Tell 4965 where to find circular buffer of Tx Frame Descriptors for | ||
2245 | * given Tx queue, and enable the DMA channel used for that queue. | ||
2246 | * | ||
2247 | * 4965 supports up to 16 Tx queues in DRAM, mapped to up to 8 Tx DMA | ||
2248 | * channels supported in hardware. | ||
2249 | */ | ||
2250 | int iwl4965_hw_tx_queue_init(struct iwl_priv *priv, struct iwl4965_tx_queue *txq) | ||
2251 | { | ||
2252 | int rc; | ||
2253 | unsigned long flags; | ||
2254 | int txq_id = txq->q.id; | ||
2255 | |||
2256 | spin_lock_irqsave(&priv->lock, flags); | ||
2257 | rc = iwl_grab_nic_access(priv); | ||
2258 | if (rc) { | ||
2259 | spin_unlock_irqrestore(&priv->lock, flags); | ||
2260 | return rc; | ||
2261 | } | ||
2262 | |||
2263 | /* Circular buffer (TFD queue in DRAM) physical base address */ | ||
2264 | iwl_write_direct32(priv, FH_MEM_CBBC_QUEUE(txq_id), | ||
2265 | txq->q.dma_addr >> 8); | ||
2266 | |||
2267 | /* Enable DMA channel, using same id as for TFD queue */ | ||
2268 | iwl_write_direct32( | ||
2269 | priv, FH_TCSR_CHNL_TX_CONFIG_REG(txq_id), | ||
2270 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | | ||
2271 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL); | ||
2272 | iwl_release_nic_access(priv); | ||
2273 | spin_unlock_irqrestore(&priv->lock, flags); | ||
2274 | |||
2275 | return 0; | ||
2276 | } | ||
2277 | |||
2278 | int iwl4965_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *ptr, | 1956 | int iwl4965_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *ptr, |
2279 | dma_addr_t addr, u16 len) | 1957 | dma_addr_t addr, u16 len) |
2280 | { | 1958 | { |
2281 | int index, is_odd; | 1959 | int index, is_odd; |
2282 | struct iwl4965_tfd_frame *tfd = ptr; | 1960 | struct iwl_tfd_frame *tfd = ptr; |
2283 | u32 num_tbs = IWL_GET_BITS(*tfd, num_tbs); | 1961 | u32 num_tbs = IWL_GET_BITS(*tfd, num_tbs); |
2284 | 1962 | ||
2285 | /* Each TFD can point to a maximum 20 Tx buffers */ | 1963 | /* Each TFD can point to a maximum 20 Tx buffers */ |
@@ -2309,18 +1987,6 @@ int iwl4965_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *ptr, | |||
2309 | return 0; | 1987 | return 0; |
2310 | } | 1988 | } |
2311 | 1989 | ||
2312 | static void iwl4965_hw_card_show_info(struct iwl_priv *priv) | ||
2313 | { | ||
2314 | u16 hw_version = iwl_eeprom_query16(priv, EEPROM_4965_BOARD_REVISION); | ||
2315 | |||
2316 | IWL_DEBUG_INFO("4965ABGN HW Version %u.%u.%u\n", | ||
2317 | ((hw_version >> 8) & 0x0F), | ||
2318 | ((hw_version >> 8) >> 4), (hw_version & 0x00FF)); | ||
2319 | |||
2320 | IWL_DEBUG_INFO("4965ABGN PBA Number %.16s\n", | ||
2321 | &priv->eeprom[EEPROM_4965_BOARD_PBA]); | ||
2322 | } | ||
2323 | |||
2324 | static int iwl4965_alloc_shared_mem(struct iwl_priv *priv) | 1990 | static int iwl4965_alloc_shared_mem(struct iwl_priv *priv) |
2325 | { | 1991 | { |
2326 | priv->shared_virt = pci_alloc_consistent(priv->pci_dev, | 1992 | priv->shared_virt = pci_alloc_consistent(priv->pci_dev, |
@@ -4054,7 +3720,6 @@ static struct iwl_lib_ops iwl4965_lib = { | |||
4054 | .alloc_shared_mem = iwl4965_alloc_shared_mem, | 3720 | .alloc_shared_mem = iwl4965_alloc_shared_mem, |
4055 | .free_shared_mem = iwl4965_free_shared_mem, | 3721 | .free_shared_mem = iwl4965_free_shared_mem, |
4056 | .txq_update_byte_cnt_tbl = iwl4965_txq_update_byte_cnt_tbl, | 3722 | .txq_update_byte_cnt_tbl = iwl4965_txq_update_byte_cnt_tbl, |
4057 | .hw_nic_init = iwl4965_hw_nic_init, | ||
4058 | .disable_tx_fifo = iwl4965_disable_tx_fifo, | 3723 | .disable_tx_fifo = iwl4965_disable_tx_fifo, |
4059 | .rx_handler_setup = iwl4965_rx_handler_setup, | 3724 | .rx_handler_setup = iwl4965_rx_handler_setup, |
4060 | .is_valid_rtc_data_addr = iwl4965_hw_valid_rtc_data_addr, | 3725 | .is_valid_rtc_data_addr = iwl4965_hw_valid_rtc_data_addr, |