diff options
author | David S. Miller <davem@davemloft.net> | 2008-06-10 04:54:31 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-06-10 04:54:31 -0400 |
commit | 788c0a53164c05c5ccdb1472474372b72ba74644 (patch) | |
tree | 5f274102e3dc4bcca6cb3a695aa2c8228ad5fc4f /drivers/net/wireless/iwlwifi/iwl-4965.c | |
parent | e64bda89b8fe81cce9b4a20885d2c204c2d52532 (diff) | |
parent | 78cf07472f0ede8394bacc4bc02354505080cfe1 (diff) |
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Conflicts:
drivers/net/ps3_gelic_wireless.c
drivers/net/wireless/libertas/main.c
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-4965.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-4965.c | 1019 |
1 files changed, 378 insertions, 641 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 17847f981e11..aee7014bcb94 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c | |||
@@ -44,6 +44,7 @@ | |||
44 | #include "iwl-io.h" | 44 | #include "iwl-io.h" |
45 | #include "iwl-helpers.h" | 45 | #include "iwl-helpers.h" |
46 | #include "iwl-calib.h" | 46 | #include "iwl-calib.h" |
47 | #include "iwl-sta.h" | ||
47 | 48 | ||
48 | /* module parameters */ | 49 | /* module parameters */ |
49 | static struct iwl_mod_params iwl4965_mod_params = { | 50 | static struct iwl_mod_params iwl4965_mod_params = { |
@@ -54,30 +55,6 @@ static struct iwl_mod_params iwl4965_mod_params = { | |||
54 | /* the rest are 0 by default */ | 55 | /* the rest are 0 by default */ |
55 | }; | 56 | }; |
56 | 57 | ||
57 | #ifdef CONFIG_IWL4965_HT | ||
58 | |||
59 | static const u16 default_tid_to_tx_fifo[] = { | ||
60 | IWL_TX_FIFO_AC1, | ||
61 | IWL_TX_FIFO_AC0, | ||
62 | IWL_TX_FIFO_AC0, | ||
63 | IWL_TX_FIFO_AC1, | ||
64 | IWL_TX_FIFO_AC2, | ||
65 | IWL_TX_FIFO_AC2, | ||
66 | IWL_TX_FIFO_AC3, | ||
67 | IWL_TX_FIFO_AC3, | ||
68 | IWL_TX_FIFO_NONE, | ||
69 | IWL_TX_FIFO_NONE, | ||
70 | IWL_TX_FIFO_NONE, | ||
71 | IWL_TX_FIFO_NONE, | ||
72 | IWL_TX_FIFO_NONE, | ||
73 | IWL_TX_FIFO_NONE, | ||
74 | IWL_TX_FIFO_NONE, | ||
75 | IWL_TX_FIFO_NONE, | ||
76 | IWL_TX_FIFO_AC3 | ||
77 | }; | ||
78 | |||
79 | #endif /*CONFIG_IWL4965_HT */ | ||
80 | |||
81 | /* check contents of special bootstrap uCode SRAM */ | 58 | /* check contents of special bootstrap uCode SRAM */ |
82 | static int iwl4965_verify_bsm(struct iwl_priv *priv) | 59 | static int iwl4965_verify_bsm(struct iwl_priv *priv) |
83 | { | 60 | { |
@@ -156,15 +133,18 @@ static int iwl4965_load_bsm(struct iwl_priv *priv) | |||
156 | 133 | ||
157 | IWL_DEBUG_INFO("Begin load bsm\n"); | 134 | IWL_DEBUG_INFO("Begin load bsm\n"); |
158 | 135 | ||
136 | priv->ucode_type = UCODE_RT; | ||
137 | |||
159 | /* make sure bootstrap program is no larger than BSM's SRAM size */ | 138 | /* make sure bootstrap program is no larger than BSM's SRAM size */ |
160 | if (len > IWL_MAX_BSM_SIZE) | 139 | if (len > IWL_MAX_BSM_SIZE) |
161 | return -EINVAL; | 140 | return -EINVAL; |
162 | 141 | ||
163 | /* Tell bootstrap uCode where to find the "Initialize" uCode | 142 | /* Tell bootstrap uCode where to find the "Initialize" uCode |
164 | * in host DRAM ... host DRAM physical address bits 35:4 for 4965. | 143 | * in host DRAM ... host DRAM physical address bits 35:4 for 4965. |
165 | * NOTE: iwl4965_initialize_alive_start() will replace these values, | 144 | * NOTE: iwl_init_alive_start() will replace these values, |
166 | * after the "initialize" uCode has run, to point to | 145 | * after the "initialize" uCode has run, to point to |
167 | * runtime/protocol instructions and backup data cache. */ | 146 | * runtime/protocol instructions and backup data cache. |
147 | */ | ||
168 | pinst = priv->ucode_init.p_addr >> 4; | 148 | pinst = priv->ucode_init.p_addr >> 4; |
169 | pdata = priv->ucode_init_data.p_addr >> 4; | 149 | pdata = priv->ucode_init_data.p_addr >> 4; |
170 | inst_len = priv->ucode_init.len; | 150 | inst_len = priv->ucode_init.len; |
@@ -345,8 +325,8 @@ int iwl4965_hwrate_to_plcp_idx(u32 rate_n_flags) | |||
345 | 325 | ||
346 | /* 4965 legacy rate format, search for match in table */ | 326 | /* 4965 legacy rate format, search for match in table */ |
347 | } else { | 327 | } else { |
348 | for (idx = 0; idx < ARRAY_SIZE(iwl4965_rates); idx++) | 328 | for (idx = 0; idx < ARRAY_SIZE(iwl_rates); idx++) |
349 | if (iwl4965_rates[idx].plcp == (rate_n_flags & 0xFF)) | 329 | if (iwl_rates[idx].plcp == (rate_n_flags & 0xFF)) |
350 | return idx; | 330 | return idx; |
351 | } | 331 | } |
352 | 332 | ||
@@ -357,55 +337,26 @@ int iwl4965_hwrate_to_plcp_idx(u32 rate_n_flags) | |||
357 | * translate ucode response to mac80211 tx status control values | 337 | * translate ucode response to mac80211 tx status control values |
358 | */ | 338 | */ |
359 | void iwl4965_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, | 339 | void iwl4965_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, |
360 | struct ieee80211_tx_control *control) | 340 | struct ieee80211_tx_info *control) |
361 | { | 341 | { |
362 | int rate_index; | 342 | int rate_index; |
363 | 343 | ||
364 | control->antenna_sel_tx = | 344 | control->antenna_sel_tx = |
365 | ((rate_n_flags & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS); | 345 | ((rate_n_flags & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS); |
366 | if (rate_n_flags & RATE_MCS_HT_MSK) | 346 | if (rate_n_flags & RATE_MCS_HT_MSK) |
367 | control->flags |= IEEE80211_TXCTL_OFDM_HT; | 347 | control->flags |= IEEE80211_TX_CTL_OFDM_HT; |
368 | if (rate_n_flags & RATE_MCS_GF_MSK) | 348 | if (rate_n_flags & RATE_MCS_GF_MSK) |
369 | control->flags |= IEEE80211_TXCTL_GREEN_FIELD; | 349 | control->flags |= IEEE80211_TX_CTL_GREEN_FIELD; |
370 | if (rate_n_flags & RATE_MCS_FAT_MSK) | 350 | if (rate_n_flags & RATE_MCS_FAT_MSK) |
371 | control->flags |= IEEE80211_TXCTL_40_MHZ_WIDTH; | 351 | control->flags |= IEEE80211_TX_CTL_40_MHZ_WIDTH; |
372 | if (rate_n_flags & RATE_MCS_DUP_MSK) | 352 | if (rate_n_flags & RATE_MCS_DUP_MSK) |
373 | control->flags |= IEEE80211_TXCTL_DUP_DATA; | 353 | control->flags |= IEEE80211_TX_CTL_DUP_DATA; |
374 | if (rate_n_flags & RATE_MCS_SGI_MSK) | 354 | if (rate_n_flags & RATE_MCS_SGI_MSK) |
375 | control->flags |= IEEE80211_TXCTL_SHORT_GI; | 355 | control->flags |= IEEE80211_TX_CTL_SHORT_GI; |
376 | /* since iwl4965_hwrate_to_plcp_idx is band indifferent, we always use | ||
377 | * IEEE80211_BAND_2GHZ band as it contains all the rates */ | ||
378 | rate_index = iwl4965_hwrate_to_plcp_idx(rate_n_flags); | 356 | rate_index = iwl4965_hwrate_to_plcp_idx(rate_n_flags); |
379 | if (rate_index == -1) | 357 | if (control->band == IEEE80211_BAND_5GHZ) |
380 | control->tx_rate = NULL; | 358 | rate_index -= IWL_FIRST_OFDM_RATE; |
381 | else | 359 | control->tx_rate_idx = rate_index; |
382 | control->tx_rate = | ||
383 | &priv->bands[IEEE80211_BAND_2GHZ].bitrates[rate_index]; | ||
384 | } | ||
385 | |||
386 | int iwl4965_hw_rxq_stop(struct iwl_priv *priv) | ||
387 | { | ||
388 | int rc; | ||
389 | unsigned long flags; | ||
390 | |||
391 | spin_lock_irqsave(&priv->lock, flags); | ||
392 | rc = iwl_grab_nic_access(priv); | ||
393 | if (rc) { | ||
394 | spin_unlock_irqrestore(&priv->lock, flags); | ||
395 | return rc; | ||
396 | } | ||
397 | |||
398 | /* stop Rx DMA */ | ||
399 | iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); | ||
400 | rc = iwl_poll_direct_bit(priv, FH_MEM_RSSR_RX_STATUS_REG, | ||
401 | (1 << 24), 1000); | ||
402 | if (rc < 0) | ||
403 | IWL_ERROR("Can't stop Rx DMA.\n"); | ||
404 | |||
405 | iwl_release_nic_access(priv); | ||
406 | spin_unlock_irqrestore(&priv->lock, flags); | ||
407 | |||
408 | return 0; | ||
409 | } | 360 | } |
410 | 361 | ||
411 | /* | 362 | /* |
@@ -467,25 +418,13 @@ int iwl4965_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src) | |||
467 | return ret; | 418 | return ret; |
468 | } | 419 | } |
469 | 420 | ||
470 | static int iwl4965_disable_tx_fifo(struct iwl_priv *priv) | 421 | /* |
422 | * Activate/Deactivat Tx DMA/FIFO channels according tx fifos mask | ||
423 | * must be called under priv->lock and mac access | ||
424 | */ | ||
425 | static void iwl4965_txq_set_sched(struct iwl_priv *priv, u32 mask) | ||
471 | { | 426 | { |
472 | unsigned long flags; | 427 | iwl_write_prph(priv, IWL49_SCD_TXFACT, mask); |
473 | int ret; | ||
474 | |||
475 | spin_lock_irqsave(&priv->lock, flags); | ||
476 | |||
477 | ret = iwl_grab_nic_access(priv); | ||
478 | if (unlikely(ret)) { | ||
479 | IWL_ERROR("Tx fifo reset failed"); | ||
480 | spin_unlock_irqrestore(&priv->lock, flags); | ||
481 | return ret; | ||
482 | } | ||
483 | |||
484 | iwl_write_prph(priv, IWL49_SCD_TXFACT, 0); | ||
485 | iwl_release_nic_access(priv); | ||
486 | spin_unlock_irqrestore(&priv->lock, flags); | ||
487 | |||
488 | return 0; | ||
489 | } | 428 | } |
490 | 429 | ||
491 | static int iwl4965_apm_init(struct iwl_priv *priv) | 430 | static int iwl4965_apm_init(struct iwl_priv *priv) |
@@ -495,6 +434,10 @@ static int iwl4965_apm_init(struct iwl_priv *priv) | |||
495 | iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS, | 434 | iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS, |
496 | CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER); | 435 | CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER); |
497 | 436 | ||
437 | /* disable L0s without affecting L1 :don't wait for ICH L0s bug W/A) */ | ||
438 | iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS, | ||
439 | CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX); | ||
440 | |||
498 | /* set "initialization complete" bit to move adapter | 441 | /* set "initialization complete" bit to move adapter |
499 | * D0U* --> D0A* state */ | 442 | * D0U* --> D0A* state */ |
500 | iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); | 443 | iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); |
@@ -513,11 +456,12 @@ static int iwl4965_apm_init(struct iwl_priv *priv) | |||
513 | goto out; | 456 | goto out; |
514 | 457 | ||
515 | /* enable DMA */ | 458 | /* enable DMA */ |
516 | iwl_write_prph(priv, APMG_CLK_CTRL_REG, | 459 | iwl_write_prph(priv, APMG_CLK_CTRL_REG, APMG_CLK_VAL_DMA_CLK_RQT | |
517 | APMG_CLK_VAL_DMA_CLK_RQT | APMG_CLK_VAL_BSM_CLK_RQT); | 460 | APMG_CLK_VAL_BSM_CLK_RQT); |
518 | 461 | ||
519 | udelay(20); | 462 | udelay(20); |
520 | 463 | ||
464 | /* disable L1-Active */ | ||
521 | iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG, | 465 | iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG, |
522 | APMG_PCIDEV_STT_VAL_L1_ACT_DIS); | 466 | APMG_PCIDEV_STT_VAL_L1_ACT_DIS); |
523 | 467 | ||
@@ -545,8 +489,13 @@ static void iwl4965_nic_config(struct iwl_priv *priv) | |||
545 | 489 | ||
546 | pci_read_config_byte(priv->pci_dev, PCI_LINK_CTRL, &val_link); | 490 | pci_read_config_byte(priv->pci_dev, PCI_LINK_CTRL, &val_link); |
547 | 491 | ||
548 | /* disable L1 entry -- workaround for pre-B1 */ | 492 | /* L1 is enabled by BIOS */ |
549 | pci_write_config_byte(priv->pci_dev, PCI_LINK_CTRL, val_link & ~0x02); | 493 | if ((val_link & PCI_LINK_VAL_L1_EN) == PCI_LINK_VAL_L1_EN) |
494 | /* diable L0S disabled L1A enabled */ | ||
495 | iwl_set_bit(priv, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED); | ||
496 | else | ||
497 | /* L0S enabled L1A disabled */ | ||
498 | iwl_clear_bit(priv, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED); | ||
550 | 499 | ||
551 | radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG); | 500 | radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG); |
552 | 501 | ||
@@ -568,10 +517,9 @@ static void iwl4965_nic_config(struct iwl_priv *priv) | |||
568 | spin_unlock_irqrestore(&priv->lock, flags); | 517 | spin_unlock_irqrestore(&priv->lock, flags); |
569 | } | 518 | } |
570 | 519 | ||
571 | int iwl4965_hw_nic_stop_master(struct iwl_priv *priv) | 520 | static int iwl4965_apm_stop_master(struct iwl_priv *priv) |
572 | { | 521 | { |
573 | int rc = 0; | 522 | int ret = 0; |
574 | u32 reg_val; | ||
575 | unsigned long flags; | 523 | unsigned long flags; |
576 | 524 | ||
577 | spin_lock_irqsave(&priv->lock, flags); | 525 | spin_lock_irqsave(&priv->lock, flags); |
@@ -579,64 +527,41 @@ int iwl4965_hw_nic_stop_master(struct iwl_priv *priv) | |||
579 | /* set stop master bit */ | 527 | /* set stop master bit */ |
580 | iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER); | 528 | iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER); |
581 | 529 | ||
582 | reg_val = iwl_read32(priv, CSR_GP_CNTRL); | 530 | ret = iwl_poll_bit(priv, CSR_RESET, |
583 | |||
584 | if (CSR_GP_CNTRL_REG_FLAG_MAC_POWER_SAVE == | ||
585 | (reg_val & CSR_GP_CNTRL_REG_MSK_POWER_SAVE_TYPE)) | ||
586 | IWL_DEBUG_INFO("Card in power save, master is already " | ||
587 | "stopped\n"); | ||
588 | else { | ||
589 | rc = iwl_poll_bit(priv, CSR_RESET, | ||
590 | CSR_RESET_REG_FLAG_MASTER_DISABLED, | 531 | CSR_RESET_REG_FLAG_MASTER_DISABLED, |
591 | CSR_RESET_REG_FLAG_MASTER_DISABLED, 100); | 532 | CSR_RESET_REG_FLAG_MASTER_DISABLED, 100); |
592 | if (rc < 0) { | 533 | if (ret < 0) |
593 | spin_unlock_irqrestore(&priv->lock, flags); | 534 | goto out; |
594 | return rc; | ||
595 | } | ||
596 | } | ||
597 | 535 | ||
536 | out: | ||
598 | spin_unlock_irqrestore(&priv->lock, flags); | 537 | spin_unlock_irqrestore(&priv->lock, flags); |
599 | IWL_DEBUG_INFO("stop master\n"); | 538 | IWL_DEBUG_INFO("stop master\n"); |
600 | 539 | ||
601 | return rc; | 540 | return ret; |
602 | } | 541 | } |
603 | 542 | ||
604 | /** | 543 | static void iwl4965_apm_stop(struct iwl_priv *priv) |
605 | * iwl4965_hw_txq_ctx_stop - Stop all Tx DMA channels, free Tx queue memory | ||
606 | */ | ||
607 | void iwl4965_hw_txq_ctx_stop(struct iwl_priv *priv) | ||
608 | { | 544 | { |
609 | |||
610 | int txq_id; | ||
611 | unsigned long flags; | 545 | unsigned long flags; |
612 | 546 | ||
613 | /* Stop each Tx DMA channel, and wait for it to be idle */ | 547 | iwl4965_apm_stop_master(priv); |
614 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { | ||
615 | spin_lock_irqsave(&priv->lock, flags); | ||
616 | if (iwl_grab_nic_access(priv)) { | ||
617 | spin_unlock_irqrestore(&priv->lock, flags); | ||
618 | continue; | ||
619 | } | ||
620 | 548 | ||
621 | iwl_write_direct32(priv, | 549 | spin_lock_irqsave(&priv->lock, flags); |
622 | FH_TCSR_CHNL_TX_CONFIG_REG(txq_id), 0x0); | 550 | |
623 | iwl_poll_direct_bit(priv, FH_TSSR_TX_STATUS_REG, | 551 | iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); |
624 | FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE | ||
625 | (txq_id), 200); | ||
626 | iwl_release_nic_access(priv); | ||
627 | spin_unlock_irqrestore(&priv->lock, flags); | ||
628 | } | ||
629 | 552 | ||
630 | /* Deallocate memory for all Tx queues */ | 553 | udelay(10); |
631 | iwl_hw_txq_ctx_free(priv); | 554 | |
555 | iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); | ||
556 | spin_unlock_irqrestore(&priv->lock, flags); | ||
632 | } | 557 | } |
633 | 558 | ||
634 | int iwl4965_hw_nic_reset(struct iwl_priv *priv) | 559 | static int iwl4965_apm_reset(struct iwl_priv *priv) |
635 | { | 560 | { |
636 | int rc = 0; | 561 | int ret = 0; |
637 | unsigned long flags; | 562 | unsigned long flags; |
638 | 563 | ||
639 | iwl4965_hw_nic_stop_master(priv); | 564 | iwl4965_apm_stop_master(priv); |
640 | 565 | ||
641 | spin_lock_irqsave(&priv->lock, flags); | 566 | spin_lock_irqsave(&priv->lock, flags); |
642 | 567 | ||
@@ -644,34 +569,41 @@ int iwl4965_hw_nic_reset(struct iwl_priv *priv) | |||
644 | 569 | ||
645 | udelay(10); | 570 | udelay(10); |
646 | 571 | ||
572 | /* FIXME: put here L1A -L0S w/a */ | ||
573 | |||
647 | iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); | 574 | iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); |
648 | rc = iwl_poll_bit(priv, CSR_RESET, | 575 | |
576 | ret = iwl_poll_bit(priv, CSR_RESET, | ||
649 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, | 577 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, |
650 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25); | 578 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25); |
651 | 579 | ||
580 | if (ret) | ||
581 | goto out; | ||
582 | |||
652 | udelay(10); | 583 | udelay(10); |
653 | 584 | ||
654 | rc = iwl_grab_nic_access(priv); | 585 | ret = iwl_grab_nic_access(priv); |
655 | if (!rc) { | 586 | if (ret) |
656 | iwl_write_prph(priv, APMG_CLK_EN_REG, | 587 | goto out; |
657 | APMG_CLK_VAL_DMA_CLK_RQT | | 588 | /* Enable DMA and BSM Clock */ |
658 | APMG_CLK_VAL_BSM_CLK_RQT); | 589 | iwl_write_prph(priv, APMG_CLK_EN_REG, APMG_CLK_VAL_DMA_CLK_RQT | |
590 | APMG_CLK_VAL_BSM_CLK_RQT); | ||
659 | 591 | ||
660 | udelay(10); | 592 | udelay(10); |
661 | 593 | ||
662 | iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG, | 594 | /* disable L1A */ |
663 | APMG_PCIDEV_STT_VAL_L1_ACT_DIS); | 595 | iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG, |
596 | APMG_PCIDEV_STT_VAL_L1_ACT_DIS); | ||
664 | 597 | ||
665 | iwl_release_nic_access(priv); | 598 | iwl_release_nic_access(priv); |
666 | } | ||
667 | 599 | ||
668 | clear_bit(STATUS_HCMD_ACTIVE, &priv->status); | 600 | clear_bit(STATUS_HCMD_ACTIVE, &priv->status); |
669 | wake_up_interruptible(&priv->wait_command_queue); | 601 | wake_up_interruptible(&priv->wait_command_queue); |
670 | 602 | ||
603 | out: | ||
671 | spin_unlock_irqrestore(&priv->lock, flags); | 604 | spin_unlock_irqrestore(&priv->lock, flags); |
672 | 605 | ||
673 | return rc; | 606 | return ret; |
674 | |||
675 | } | 607 | } |
676 | 608 | ||
677 | #define REG_RECALIB_PERIOD (60) | 609 | #define REG_RECALIB_PERIOD (60) |
@@ -911,16 +843,6 @@ static const u16 default_queue_to_tx_fifo[] = { | |||
911 | IWL_TX_FIFO_HCCA_2 | 843 | IWL_TX_FIFO_HCCA_2 |
912 | }; | 844 | }; |
913 | 845 | ||
914 | static inline void iwl4965_txq_ctx_activate(struct iwl_priv *priv, int txq_id) | ||
915 | { | ||
916 | set_bit(txq_id, &priv->txq_ctx_active_msk); | ||
917 | } | ||
918 | |||
919 | static inline void iwl4965_txq_ctx_deactivate(struct iwl_priv *priv, int txq_id) | ||
920 | { | ||
921 | clear_bit(txq_id, &priv->txq_ctx_active_msk); | ||
922 | } | ||
923 | |||
924 | int iwl4965_alive_notify(struct iwl_priv *priv) | 846 | int iwl4965_alive_notify(struct iwl_priv *priv) |
925 | { | 847 | { |
926 | u32 a; | 848 | u32 a; |
@@ -930,15 +852,6 @@ int iwl4965_alive_notify(struct iwl_priv *priv) | |||
930 | 852 | ||
931 | spin_lock_irqsave(&priv->lock, flags); | 853 | spin_lock_irqsave(&priv->lock, flags); |
932 | 854 | ||
933 | #ifdef CONFIG_IWL4965_RUN_TIME_CALIB | ||
934 | memset(&(priv->sensitivity_data), 0, | ||
935 | sizeof(struct iwl_sensitivity_data)); | ||
936 | memset(&(priv->chain_noise_data), 0, | ||
937 | sizeof(struct iwl_chain_noise_data)); | ||
938 | for (i = 0; i < NUM_RX_CHAINS; i++) | ||
939 | priv->chain_noise_data.delta_gain_code[i] = | ||
940 | CHAIN_NOISE_DELTA_GAIN_INIT_VAL; | ||
941 | #endif /* CONFIG_IWL4965_RUN_TIME_CALIB*/ | ||
942 | ret = iwl_grab_nic_access(priv); | 855 | ret = iwl_grab_nic_access(priv); |
943 | if (ret) { | 856 | if (ret) { |
944 | spin_unlock_irqrestore(&priv->lock, flags); | 857 | spin_unlock_irqrestore(&priv->lock, flags); |
@@ -990,24 +903,20 @@ int iwl4965_alive_notify(struct iwl_priv *priv) | |||
990 | (1 << priv->hw_params.max_txq_num) - 1); | 903 | (1 << priv->hw_params.max_txq_num) - 1); |
991 | 904 | ||
992 | /* Activate all Tx DMA/FIFO channels */ | 905 | /* Activate all Tx DMA/FIFO channels */ |
993 | iwl_write_prph(priv, IWL49_SCD_TXFACT, | 906 | priv->cfg->ops->lib->txq_set_sched(priv, IWL_MASK(0, 7)); |
994 | SCD_TXFACT_REG_TXFIFO_MASK(0, 7)); | ||
995 | 907 | ||
996 | iwl4965_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0); | 908 | iwl4965_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0); |
997 | 909 | ||
998 | /* Map each Tx/cmd queue to its corresponding fifo */ | 910 | /* Map each Tx/cmd queue to its corresponding fifo */ |
999 | for (i = 0; i < ARRAY_SIZE(default_queue_to_tx_fifo); i++) { | 911 | for (i = 0; i < ARRAY_SIZE(default_queue_to_tx_fifo); i++) { |
1000 | int ac = default_queue_to_tx_fifo[i]; | 912 | int ac = default_queue_to_tx_fifo[i]; |
1001 | iwl4965_txq_ctx_activate(priv, i); | 913 | iwl_txq_ctx_activate(priv, i); |
1002 | iwl4965_tx_queue_set_status(priv, &priv->txq[i], ac, 0); | 914 | iwl4965_tx_queue_set_status(priv, &priv->txq[i], ac, 0); |
1003 | } | 915 | } |
1004 | 916 | ||
1005 | iwl_release_nic_access(priv); | 917 | iwl_release_nic_access(priv); |
1006 | spin_unlock_irqrestore(&priv->lock, flags); | 918 | spin_unlock_irqrestore(&priv->lock, flags); |
1007 | 919 | ||
1008 | /* Ask for statistics now, the uCode will send statistics notification | ||
1009 | * periodically after association */ | ||
1010 | iwl_send_statistics_request(priv, CMD_ASYNC); | ||
1011 | return ret; | 920 | return ret; |
1012 | } | 921 | } |
1013 | 922 | ||
@@ -1053,7 +962,6 @@ int iwl4965_hw_set_hw_params(struct iwl_priv *priv) | |||
1053 | 962 | ||
1054 | priv->hw_params.max_txq_num = priv->cfg->mod_params->num_of_queues; | 963 | priv->hw_params.max_txq_num = priv->cfg->mod_params->num_of_queues; |
1055 | priv->hw_params.sw_crypto = priv->cfg->mod_params->sw_crypto; | 964 | priv->hw_params.sw_crypto = priv->cfg->mod_params->sw_crypto; |
1056 | priv->hw_params.tx_cmd_len = sizeof(struct iwl4965_tx_cmd); | ||
1057 | priv->hw_params.max_rxq_size = RX_QUEUE_SIZE; | 965 | priv->hw_params.max_rxq_size = RX_QUEUE_SIZE; |
1058 | priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG; | 966 | priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG; |
1059 | if (priv->cfg->mod_params->amsdu_size_8K) | 967 | if (priv->cfg->mod_params->amsdu_size_8K) |
@@ -1857,8 +1765,8 @@ static int iwl4965_send_rxon_assoc(struct iwl_priv *priv) | |||
1857 | { | 1765 | { |
1858 | int ret = 0; | 1766 | int ret = 0; |
1859 | struct iwl4965_rxon_assoc_cmd rxon_assoc; | 1767 | struct iwl4965_rxon_assoc_cmd rxon_assoc; |
1860 | const struct iwl4965_rxon_cmd *rxon1 = &priv->staging_rxon; | 1768 | const struct iwl_rxon_cmd *rxon1 = &priv->staging_rxon; |
1861 | const struct iwl4965_rxon_cmd *rxon2 = &priv->active_rxon; | 1769 | const struct iwl_rxon_cmd *rxon2 = &priv->active_rxon; |
1862 | 1770 | ||
1863 | if ((rxon1->flags == rxon2->flags) && | 1771 | if ((rxon1->flags == rxon2->flags) && |
1864 | (rxon1->filter_flags == rxon2->filter_flags) && | 1772 | (rxon1->filter_flags == rxon2->filter_flags) && |
@@ -1934,76 +1842,6 @@ int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel) | |||
1934 | return rc; | 1842 | return rc; |
1935 | } | 1843 | } |
1936 | 1844 | ||
1937 | #define RTS_HCCA_RETRY_LIMIT 3 | ||
1938 | #define RTS_DFAULT_RETRY_LIMIT 60 | ||
1939 | |||
1940 | void iwl4965_hw_build_tx_cmd_rate(struct iwl_priv *priv, | ||
1941 | struct iwl_cmd *cmd, | ||
1942 | struct ieee80211_tx_control *ctrl, | ||
1943 | struct ieee80211_hdr *hdr, int sta_id, | ||
1944 | int is_hcca) | ||
1945 | { | ||
1946 | struct iwl4965_tx_cmd *tx = &cmd->cmd.tx; | ||
1947 | u8 rts_retry_limit = 0; | ||
1948 | u8 data_retry_limit = 0; | ||
1949 | u16 fc = le16_to_cpu(hdr->frame_control); | ||
1950 | u8 rate_plcp; | ||
1951 | u16 rate_flags = 0; | ||
1952 | int rate_idx = min(ctrl->tx_rate->hw_value & 0xffff, IWL_RATE_COUNT - 1); | ||
1953 | |||
1954 | rate_plcp = iwl4965_rates[rate_idx].plcp; | ||
1955 | |||
1956 | rts_retry_limit = (is_hcca) ? | ||
1957 | RTS_HCCA_RETRY_LIMIT : RTS_DFAULT_RETRY_LIMIT; | ||
1958 | |||
1959 | if ((rate_idx >= IWL_FIRST_CCK_RATE) && (rate_idx <= IWL_LAST_CCK_RATE)) | ||
1960 | rate_flags |= RATE_MCS_CCK_MSK; | ||
1961 | |||
1962 | |||
1963 | if (ieee80211_is_probe_response(fc)) { | ||
1964 | data_retry_limit = 3; | ||
1965 | if (data_retry_limit < rts_retry_limit) | ||
1966 | rts_retry_limit = data_retry_limit; | ||
1967 | } else | ||
1968 | data_retry_limit = IWL_DEFAULT_TX_RETRY; | ||
1969 | |||
1970 | if (priv->data_retry_limit != -1) | ||
1971 | data_retry_limit = priv->data_retry_limit; | ||
1972 | |||
1973 | |||
1974 | if (ieee80211_is_data(fc)) { | ||
1975 | tx->initial_rate_index = 0; | ||
1976 | tx->tx_flags |= TX_CMD_FLG_STA_RATE_MSK; | ||
1977 | } else { | ||
1978 | switch (fc & IEEE80211_FCTL_STYPE) { | ||
1979 | case IEEE80211_STYPE_AUTH: | ||
1980 | case IEEE80211_STYPE_DEAUTH: | ||
1981 | case IEEE80211_STYPE_ASSOC_REQ: | ||
1982 | case IEEE80211_STYPE_REASSOC_REQ: | ||
1983 | if (tx->tx_flags & TX_CMD_FLG_RTS_MSK) { | ||
1984 | tx->tx_flags &= ~TX_CMD_FLG_RTS_MSK; | ||
1985 | tx->tx_flags |= TX_CMD_FLG_CTS_MSK; | ||
1986 | } | ||
1987 | break; | ||
1988 | default: | ||
1989 | break; | ||
1990 | } | ||
1991 | |||
1992 | /* Alternate between antenna A and B for successive frames */ | ||
1993 | if (priv->use_ant_b_for_management_frame) { | ||
1994 | priv->use_ant_b_for_management_frame = 0; | ||
1995 | rate_flags |= RATE_MCS_ANT_B_MSK; | ||
1996 | } else { | ||
1997 | priv->use_ant_b_for_management_frame = 1; | ||
1998 | rate_flags |= RATE_MCS_ANT_A_MSK; | ||
1999 | } | ||
2000 | } | ||
2001 | |||
2002 | tx->rts_retry_limit = rts_retry_limit; | ||
2003 | tx->data_retry_limit = data_retry_limit; | ||
2004 | tx->rate_n_flags = iwl4965_hw_set_rate_n_flags(rate_plcp, rate_flags); | ||
2005 | } | ||
2006 | |||
2007 | static int iwl4965_shared_mem_rx_idx(struct iwl_priv *priv) | 1845 | static int iwl4965_shared_mem_rx_idx(struct iwl_priv *priv) |
2008 | { | 1846 | { |
2009 | struct iwl4965_shared *s = priv->shared_virt; | 1847 | struct iwl4965_shared *s = priv->shared_virt; |
@@ -2016,7 +1854,7 @@ int iwl4965_hw_get_temperature(struct iwl_priv *priv) | |||
2016 | } | 1854 | } |
2017 | 1855 | ||
2018 | unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv, | 1856 | unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv, |
2019 | struct iwl4965_frame *frame, u8 rate) | 1857 | struct iwl_frame *frame, u8 rate) |
2020 | { | 1858 | { |
2021 | struct iwl4965_tx_beacon_cmd *tx_beacon_cmd; | 1859 | struct iwl4965_tx_beacon_cmd *tx_beacon_cmd; |
2022 | unsigned int frame_size; | 1860 | unsigned int frame_size; |
@@ -2029,7 +1867,7 @@ unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv, | |||
2029 | 1867 | ||
2030 | frame_size = iwl4965_fill_beacon_frame(priv, | 1868 | frame_size = iwl4965_fill_beacon_frame(priv, |
2031 | tx_beacon_cmd->frame, | 1869 | tx_beacon_cmd->frame, |
2032 | iwl4965_broadcast_addr, | 1870 | iwl_bcast_addr, |
2033 | sizeof(frame->u) - sizeof(*tx_beacon_cmd)); | 1871 | sizeof(frame->u) - sizeof(*tx_beacon_cmd)); |
2034 | 1872 | ||
2035 | BUG_ON(frame_size > MAX_MPDU_SIZE); | 1873 | BUG_ON(frame_size > MAX_MPDU_SIZE); |
@@ -2047,40 +1885,6 @@ unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv, | |||
2047 | return (sizeof(*tx_beacon_cmd) + frame_size); | 1885 | return (sizeof(*tx_beacon_cmd) + frame_size); |
2048 | } | 1886 | } |
2049 | 1887 | ||
2050 | int iwl4965_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *ptr, | ||
2051 | dma_addr_t addr, u16 len) | ||
2052 | { | ||
2053 | int index, is_odd; | ||
2054 | struct iwl_tfd_frame *tfd = ptr; | ||
2055 | u32 num_tbs = IWL_GET_BITS(*tfd, num_tbs); | ||
2056 | |||
2057 | /* Each TFD can point to a maximum 20 Tx buffers */ | ||
2058 | if ((num_tbs >= MAX_NUM_OF_TBS) || (num_tbs < 0)) { | ||
2059 | IWL_ERROR("Error can not send more than %d chunks\n", | ||
2060 | MAX_NUM_OF_TBS); | ||
2061 | return -EINVAL; | ||
2062 | } | ||
2063 | |||
2064 | index = num_tbs / 2; | ||
2065 | is_odd = num_tbs & 0x1; | ||
2066 | |||
2067 | if (!is_odd) { | ||
2068 | tfd->pa[index].tb1_addr = cpu_to_le32(addr); | ||
2069 | IWL_SET_BITS(tfd->pa[index], tb1_addr_hi, | ||
2070 | iwl_get_dma_hi_address(addr)); | ||
2071 | IWL_SET_BITS(tfd->pa[index], tb1_len, len); | ||
2072 | } else { | ||
2073 | IWL_SET_BITS(tfd->pa[index], tb2_addr_lo16, | ||
2074 | (u32) (addr & 0xffff)); | ||
2075 | IWL_SET_BITS(tfd->pa[index], tb2_addr_hi20, addr >> 16); | ||
2076 | IWL_SET_BITS(tfd->pa[index], tb2_len, len); | ||
2077 | } | ||
2078 | |||
2079 | IWL_SET_BITS(*tfd, num_tbs, num_tbs + 1); | ||
2080 | |||
2081 | return 0; | ||
2082 | } | ||
2083 | |||
2084 | static int iwl4965_alloc_shared_mem(struct iwl_priv *priv) | 1888 | static int iwl4965_alloc_shared_mem(struct iwl_priv *priv) |
2085 | { | 1889 | { |
2086 | priv->shared_virt = pci_alloc_consistent(priv->pci_dev, | 1890 | priv->shared_virt = pci_alloc_consistent(priv->pci_dev, |
@@ -2436,7 +2240,7 @@ static void iwl4965_add_radiotap(struct iwl_priv *priv, | |||
2436 | if (rate == -1) | 2240 | if (rate == -1) |
2437 | iwl4965_rt->rt_rate = 0; | 2241 | iwl4965_rt->rt_rate = 0; |
2438 | else | 2242 | else |
2439 | iwl4965_rt->rt_rate = iwl4965_rates[rate].ieee; | 2243 | iwl4965_rt->rt_rate = iwl_rates[rate].ieee; |
2440 | 2244 | ||
2441 | /* | 2245 | /* |
2442 | * "antenna number" | 2246 | * "antenna number" |
@@ -2494,6 +2298,7 @@ static int iwl4965_set_decrypted_flag(struct iwl_priv *priv, | |||
2494 | RX_RES_STATUS_BAD_KEY_TTAK) | 2298 | RX_RES_STATUS_BAD_KEY_TTAK) |
2495 | break; | 2299 | break; |
2496 | 2300 | ||
2301 | case RX_RES_STATUS_SEC_TYPE_WEP: | ||
2497 | if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) == | 2302 | if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) == |
2498 | RX_RES_STATUS_BAD_ICV_MIC) { | 2303 | RX_RES_STATUS_BAD_ICV_MIC) { |
2499 | /* bad ICV, the packet is destroyed since the | 2304 | /* bad ICV, the packet is destroyed since the |
@@ -2501,7 +2306,6 @@ static int iwl4965_set_decrypted_flag(struct iwl_priv *priv, | |||
2501 | IWL_DEBUG_RX("Packet destroyed\n"); | 2306 | IWL_DEBUG_RX("Packet destroyed\n"); |
2502 | return -1; | 2307 | return -1; |
2503 | } | 2308 | } |
2504 | case RX_RES_STATUS_SEC_TYPE_WEP: | ||
2505 | case RX_RES_STATUS_SEC_TYPE_CCMP: | 2309 | case RX_RES_STATUS_SEC_TYPE_CCMP: |
2506 | if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) == | 2310 | if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) == |
2507 | RX_RES_STATUS_DECRYPT_OK) { | 2311 | RX_RES_STATUS_DECRYPT_OK) { |
@@ -2848,7 +2652,7 @@ static void iwl4965_dbg_report_frame(struct iwl_priv *priv, | |||
2848 | if (unlikely(rate_idx == -1)) | 2652 | if (unlikely(rate_idx == -1)) |
2849 | bitrate = 0; | 2653 | bitrate = 0; |
2850 | else | 2654 | else |
2851 | bitrate = iwl4965_rates[rate_idx].ieee / 2; | 2655 | bitrate = iwl_rates[rate_idx].ieee / 2; |
2852 | 2656 | ||
2853 | /* print frame summary. | 2657 | /* print frame summary. |
2854 | * MAC addresses show just the last byte (for brevity), | 2658 | * MAC addresses show just the last byte (for brevity), |
@@ -2885,7 +2689,7 @@ static inline void iwl4965_dbg_report_frame(struct iwl_priv *priv, | |||
2885 | 2689 | ||
2886 | /* Called for REPLY_RX (legacy ABG frames), or | 2690 | /* Called for REPLY_RX (legacy ABG frames), or |
2887 | * REPLY_RX_MPDU_CMD (HT high-throughput N frames). */ | 2691 | * REPLY_RX_MPDU_CMD (HT high-throughput N frames). */ |
2888 | static void iwl4965_rx_reply_rx(struct iwl_priv *priv, | 2692 | void iwl4965_rx_reply_rx(struct iwl_priv *priv, |
2889 | struct iwl_rx_mem_buffer *rxb) | 2693 | struct iwl_rx_mem_buffer *rxb) |
2890 | { | 2694 | { |
2891 | struct ieee80211_hdr *header; | 2695 | struct ieee80211_hdr *header; |
@@ -3059,57 +2863,9 @@ static void iwl4965_rx_reply_rx(struct iwl_priv *priv, | |||
3059 | } | 2863 | } |
3060 | } | 2864 | } |
3061 | 2865 | ||
3062 | /* Cache phy data (Rx signal strength, etc) for HT frame (REPLY_RX_PHY_CMD). | ||
3063 | * This will be used later in iwl4965_rx_reply_rx() for REPLY_RX_MPDU_CMD. */ | ||
3064 | static void iwl4965_rx_reply_rx_phy(struct iwl_priv *priv, | ||
3065 | struct iwl_rx_mem_buffer *rxb) | ||
3066 | { | ||
3067 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | ||
3068 | priv->last_phy_res[0] = 1; | ||
3069 | memcpy(&priv->last_phy_res[1], &(pkt->u.raw[0]), | ||
3070 | sizeof(struct iwl4965_rx_phy_res)); | ||
3071 | } | ||
3072 | static void iwl4965_rx_missed_beacon_notif(struct iwl_priv *priv, | ||
3073 | struct iwl_rx_mem_buffer *rxb) | ||
3074 | |||
3075 | { | ||
3076 | #ifdef CONFIG_IWL4965_RUN_TIME_CALIB | ||
3077 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | ||
3078 | struct iwl4965_missed_beacon_notif *missed_beacon; | ||
3079 | |||
3080 | missed_beacon = &pkt->u.missed_beacon; | ||
3081 | if (le32_to_cpu(missed_beacon->consequtive_missed_beacons) > 5) { | ||
3082 | IWL_DEBUG_CALIB("missed bcn cnsq %d totl %d rcd %d expctd %d\n", | ||
3083 | le32_to_cpu(missed_beacon->consequtive_missed_beacons), | ||
3084 | le32_to_cpu(missed_beacon->total_missed_becons), | ||
3085 | le32_to_cpu(missed_beacon->num_recvd_beacons), | ||
3086 | le32_to_cpu(missed_beacon->num_expected_beacons)); | ||
3087 | if (!test_bit(STATUS_SCANNING, &priv->status)) | ||
3088 | iwl_init_sensitivity(priv); | ||
3089 | } | ||
3090 | #endif /*CONFIG_IWL4965_RUN_TIME_CALIB*/ | ||
3091 | } | ||
3092 | #ifdef CONFIG_IWL4965_HT | 2866 | #ifdef CONFIG_IWL4965_HT |
3093 | 2867 | ||
3094 | /** | 2868 | /** |
3095 | * iwl4965_sta_modify_enable_tid_tx - Enable Tx for this TID in station table | ||
3096 | */ | ||
3097 | static void iwl4965_sta_modify_enable_tid_tx(struct iwl_priv *priv, | ||
3098 | int sta_id, int tid) | ||
3099 | { | ||
3100 | unsigned long flags; | ||
3101 | |||
3102 | /* Remove "disable" flag, to enable Tx for this TID */ | ||
3103 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
3104 | priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_TID_DISABLE_TX; | ||
3105 | priv->stations[sta_id].sta.tid_disable_tx &= cpu_to_le16(~(1 << tid)); | ||
3106 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; | ||
3107 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
3108 | |||
3109 | iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); | ||
3110 | } | ||
3111 | |||
3112 | /** | ||
3113 | * iwl4965_tx_status_reply_compressed_ba - Update tx status from block-ack | 2869 | * iwl4965_tx_status_reply_compressed_ba - Update tx status from block-ack |
3114 | * | 2870 | * |
3115 | * Go through block-ack's bitmap of ACK'd frames, update driver's record of | 2871 | * Go through block-ack's bitmap of ACK'd frames, update driver's record of |
@@ -3126,7 +2882,7 @@ static int iwl4965_tx_status_reply_compressed_ba(struct iwl_priv *priv, | |||
3126 | u16 scd_flow = le16_to_cpu(ba_resp->scd_flow); | 2882 | u16 scd_flow = le16_to_cpu(ba_resp->scd_flow); |
3127 | u64 bitmap; | 2883 | u64 bitmap; |
3128 | int successes = 0; | 2884 | int successes = 0; |
3129 | struct ieee80211_tx_status *tx_status; | 2885 | struct ieee80211_tx_info *info; |
3130 | 2886 | ||
3131 | if (unlikely(!agg->wait_for_ba)) { | 2887 | if (unlikely(!agg->wait_for_ba)) { |
3132 | IWL_ERROR("Received BA when not expected\n"); | 2888 | IWL_ERROR("Received BA when not expected\n"); |
@@ -3164,13 +2920,13 @@ static int iwl4965_tx_status_reply_compressed_ba(struct iwl_priv *priv, | |||
3164 | agg->start_idx + i); | 2920 | agg->start_idx + i); |
3165 | } | 2921 | } |
3166 | 2922 | ||
3167 | tx_status = &priv->txq[scd_flow].txb[agg->start_idx].status; | 2923 | info = IEEE80211_SKB_CB(priv->txq[scd_flow].txb[agg->start_idx].skb[0]); |
3168 | tx_status->flags = IEEE80211_TX_STATUS_ACK; | 2924 | memset(&info->status, 0, sizeof(info->status)); |
3169 | tx_status->flags |= IEEE80211_TX_STATUS_AMPDU; | 2925 | info->flags = IEEE80211_TX_STAT_ACK; |
3170 | tx_status->ampdu_ack_map = successes; | 2926 | info->flags |= IEEE80211_TX_STAT_AMPDU; |
3171 | tx_status->ampdu_ack_len = agg->frame_count; | 2927 | info->status.ampdu_ack_map = successes; |
3172 | iwl4965_hwrate_to_tx_control(priv, agg->rate_n_flags, | 2928 | info->status.ampdu_ack_len = agg->frame_count; |
3173 | &tx_status->control); | 2929 | iwl4965_hwrate_to_tx_control(priv, agg->rate_n_flags, info); |
3174 | 2930 | ||
3175 | IWL_DEBUG_TX_REPLY("Bitmap %llx\n", (unsigned long long)bitmap); | 2931 | IWL_DEBUG_TX_REPLY("Bitmap %llx\n", (unsigned long long)bitmap); |
3176 | 2932 | ||
@@ -3195,8 +2951,8 @@ static void iwl4965_tx_queue_stop_scheduler(struct iwl_priv *priv, | |||
3195 | * txq_id must be greater than IWL_BACK_QUEUE_FIRST_ID | 2951 | * txq_id must be greater than IWL_BACK_QUEUE_FIRST_ID |
3196 | * priv->lock must be held by the caller | 2952 | * priv->lock must be held by the caller |
3197 | */ | 2953 | */ |
3198 | static int iwl4965_tx_queue_agg_disable(struct iwl_priv *priv, u16 txq_id, | 2954 | static int iwl4965_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, |
3199 | u16 ssn_idx, u8 tx_fifo) | 2955 | u16 ssn_idx, u8 tx_fifo) |
3200 | { | 2956 | { |
3201 | int ret = 0; | 2957 | int ret = 0; |
3202 | 2958 | ||
@@ -3220,7 +2976,7 @@ static int iwl4965_tx_queue_agg_disable(struct iwl_priv *priv, u16 txq_id, | |||
3220 | iwl4965_set_wr_ptrs(priv, txq_id, ssn_idx); | 2976 | iwl4965_set_wr_ptrs(priv, txq_id, ssn_idx); |
3221 | 2977 | ||
3222 | iwl_clear_bits_prph(priv, IWL49_SCD_INTERRUPT_MASK, (1 << txq_id)); | 2978 | iwl_clear_bits_prph(priv, IWL49_SCD_INTERRUPT_MASK, (1 << txq_id)); |
3223 | iwl4965_txq_ctx_deactivate(priv, txq_id); | 2979 | iwl_txq_ctx_deactivate(priv, txq_id); |
3224 | iwl4965_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 0); | 2980 | iwl4965_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 0); |
3225 | 2981 | ||
3226 | iwl_release_nic_access(priv); | 2982 | iwl_release_nic_access(priv); |
@@ -3228,49 +2984,6 @@ static int iwl4965_tx_queue_agg_disable(struct iwl_priv *priv, u16 txq_id, | |||
3228 | return 0; | 2984 | return 0; |
3229 | } | 2985 | } |
3230 | 2986 | ||
3231 | int iwl4965_check_empty_hw_queue(struct iwl_priv *priv, int sta_id, | ||
3232 | u8 tid, int txq_id) | ||
3233 | { | ||
3234 | struct iwl4965_queue *q = &priv->txq[txq_id].q; | ||
3235 | u8 *addr = priv->stations[sta_id].sta.sta.addr; | ||
3236 | struct iwl_tid_data *tid_data = &priv->stations[sta_id].tid[tid]; | ||
3237 | |||
3238 | switch (priv->stations[sta_id].tid[tid].agg.state) { | ||
3239 | case IWL_EMPTYING_HW_QUEUE_DELBA: | ||
3240 | /* We are reclaiming the last packet of the */ | ||
3241 | /* aggregated HW queue */ | ||
3242 | if (txq_id == tid_data->agg.txq_id && | ||
3243 | q->read_ptr == q->write_ptr) { | ||
3244 | u16 ssn = SEQ_TO_SN(tid_data->seq_number); | ||
3245 | int tx_fifo = default_tid_to_tx_fifo[tid]; | ||
3246 | IWL_DEBUG_HT("HW queue empty: continue DELBA flow\n"); | ||
3247 | iwl4965_tx_queue_agg_disable(priv, txq_id, | ||
3248 | ssn, tx_fifo); | ||
3249 | tid_data->agg.state = IWL_AGG_OFF; | ||
3250 | ieee80211_stop_tx_ba_cb_irqsafe(priv->hw, addr, tid); | ||
3251 | } | ||
3252 | break; | ||
3253 | case IWL_EMPTYING_HW_QUEUE_ADDBA: | ||
3254 | /* We are reclaiming the last packet of the queue */ | ||
3255 | if (tid_data->tfds_in_queue == 0) { | ||
3256 | IWL_DEBUG_HT("HW queue empty: continue ADDBA flow\n"); | ||
3257 | tid_data->agg.state = IWL_AGG_ON; | ||
3258 | ieee80211_start_tx_ba_cb_irqsafe(priv->hw, addr, tid); | ||
3259 | } | ||
3260 | break; | ||
3261 | } | ||
3262 | return 0; | ||
3263 | } | ||
3264 | |||
3265 | /** | ||
3266 | * iwl4965_queue_dec_wrap - Decrement queue index, wrap back to end if needed | ||
3267 | * @index -- current index | ||
3268 | * @n_bd -- total number of entries in queue (s/b power of 2) | ||
3269 | */ | ||
3270 | static inline int iwl4965_queue_dec_wrap(int index, int n_bd) | ||
3271 | { | ||
3272 | return (index == 0) ? n_bd - 1 : index - 1; | ||
3273 | } | ||
3274 | 2987 | ||
3275 | /** | 2988 | /** |
3276 | * iwl4965_rx_reply_compressed_ba - Handler for REPLY_COMPRESSED_BA | 2989 | * iwl4965_rx_reply_compressed_ba - Handler for REPLY_COMPRESSED_BA |
@@ -3304,7 +3017,7 @@ static void iwl4965_rx_reply_compressed_ba(struct iwl_priv *priv, | |||
3304 | agg = &priv->stations[ba_resp->sta_id].tid[ba_resp->tid].agg; | 3017 | agg = &priv->stations[ba_resp->sta_id].tid[ba_resp->tid].agg; |
3305 | 3018 | ||
3306 | /* Find index just before block-ack window */ | 3019 | /* Find index just before block-ack window */ |
3307 | index = iwl4965_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd); | 3020 | index = iwl_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd); |
3308 | 3021 | ||
3309 | /* TODO: Need to get this copy more safely - now good for debug */ | 3022 | /* TODO: Need to get this copy more safely - now good for debug */ |
3310 | 3023 | ||
@@ -3334,15 +3047,16 @@ static void iwl4965_rx_reply_compressed_ba(struct iwl_priv *priv, | |||
3334 | /* calculate mac80211 ampdu sw queue to wake */ | 3047 | /* calculate mac80211 ampdu sw queue to wake */ |
3335 | int ampdu_q = | 3048 | int ampdu_q = |
3336 | scd_flow - IWL_BACK_QUEUE_FIRST_ID + priv->hw->queues; | 3049 | scd_flow - IWL_BACK_QUEUE_FIRST_ID + priv->hw->queues; |
3337 | int freed = iwl4965_tx_queue_reclaim(priv, scd_flow, index); | 3050 | int freed = iwl_tx_queue_reclaim(priv, scd_flow, index); |
3338 | priv->stations[ba_resp->sta_id]. | 3051 | priv->stations[ba_resp->sta_id]. |
3339 | tid[ba_resp->tid].tfds_in_queue -= freed; | 3052 | tid[ba_resp->tid].tfds_in_queue -= freed; |
3340 | if (iwl4965_queue_space(&txq->q) > txq->q.low_mark && | 3053 | if (iwl_queue_space(&txq->q) > txq->q.low_mark && |
3341 | priv->mac80211_registered && | 3054 | priv->mac80211_registered && |
3342 | agg->state != IWL_EMPTYING_HW_QUEUE_DELBA) | 3055 | agg->state != IWL_EMPTYING_HW_QUEUE_DELBA) |
3343 | ieee80211_wake_queue(priv->hw, ampdu_q); | 3056 | ieee80211_wake_queue(priv->hw, ampdu_q); |
3344 | iwl4965_check_empty_hw_queue(priv, ba_resp->sta_id, | 3057 | |
3345 | ba_resp->tid, scd_flow); | 3058 | iwl_txq_check_empty(priv, ba_resp->sta_id, |
3059 | ba_resp->tid, scd_flow); | ||
3346 | } | 3060 | } |
3347 | } | 3061 | } |
3348 | 3062 | ||
@@ -3356,7 +3070,7 @@ static int iwl4965_tx_queue_set_q2ratid(struct iwl_priv *priv, u16 ra_tid, | |||
3356 | u32 tbl_dw; | 3070 | u32 tbl_dw; |
3357 | u16 scd_q2ratid; | 3071 | u16 scd_q2ratid; |
3358 | 3072 | ||
3359 | scd_q2ratid = ra_tid & IWL49_SCD_QUEUE_RA_TID_MAP_RATID_MSK; | 3073 | scd_q2ratid = ra_tid & IWL_SCD_QUEUE_RA_TID_MAP_RATID_MSK; |
3360 | 3074 | ||
3361 | tbl_dw_addr = priv->scd_base_addr + | 3075 | tbl_dw_addr = priv->scd_base_addr + |
3362 | IWL49_SCD_TRANSLATE_TBL_OFFSET_QUEUE(txq_id); | 3076 | IWL49_SCD_TRANSLATE_TBL_OFFSET_QUEUE(txq_id); |
@@ -3380,12 +3094,11 @@ static int iwl4965_tx_queue_set_q2ratid(struct iwl_priv *priv, u16 ra_tid, | |||
3380 | * NOTE: txq_id must be greater than IWL_BACK_QUEUE_FIRST_ID, | 3094 | * NOTE: txq_id must be greater than IWL_BACK_QUEUE_FIRST_ID, |
3381 | * i.e. it must be one of the higher queues used for aggregation | 3095 | * i.e. it must be one of the higher queues used for aggregation |
3382 | */ | 3096 | */ |
3383 | static int iwl4965_tx_queue_agg_enable(struct iwl_priv *priv, int txq_id, | 3097 | static int iwl4965_txq_agg_enable(struct iwl_priv *priv, int txq_id, |
3384 | int tx_fifo, int sta_id, int tid, | 3098 | int tx_fifo, int sta_id, int tid, u16 ssn_idx) |
3385 | u16 ssn_idx) | ||
3386 | { | 3099 | { |
3387 | unsigned long flags; | 3100 | unsigned long flags; |
3388 | int rc; | 3101 | int ret; |
3389 | u16 ra_tid; | 3102 | u16 ra_tid; |
3390 | 3103 | ||
3391 | if (IWL_BACK_QUEUE_FIRST_ID > txq_id) | 3104 | if (IWL_BACK_QUEUE_FIRST_ID > txq_id) |
@@ -3395,13 +3108,13 @@ static int iwl4965_tx_queue_agg_enable(struct iwl_priv *priv, int txq_id, | |||
3395 | ra_tid = BUILD_RAxTID(sta_id, tid); | 3108 | ra_tid = BUILD_RAxTID(sta_id, tid); |
3396 | 3109 | ||
3397 | /* Modify device's station table to Tx this TID */ | 3110 | /* Modify device's station table to Tx this TID */ |
3398 | iwl4965_sta_modify_enable_tid_tx(priv, sta_id, tid); | 3111 | iwl_sta_modify_enable_tid_tx(priv, sta_id, tid); |
3399 | 3112 | ||
3400 | spin_lock_irqsave(&priv->lock, flags); | 3113 | spin_lock_irqsave(&priv->lock, flags); |
3401 | rc = iwl_grab_nic_access(priv); | 3114 | ret = iwl_grab_nic_access(priv); |
3402 | if (rc) { | 3115 | if (ret) { |
3403 | spin_unlock_irqrestore(&priv->lock, flags); | 3116 | spin_unlock_irqrestore(&priv->lock, flags); |
3404 | return rc; | 3117 | return ret; |
3405 | } | 3118 | } |
3406 | 3119 | ||
3407 | /* Stop this Tx queue before configuring it */ | 3120 | /* Stop this Tx queue before configuring it */ |
@@ -3443,109 +3156,8 @@ static int iwl4965_tx_queue_agg_enable(struct iwl_priv *priv, int txq_id, | |||
3443 | 3156 | ||
3444 | #endif /* CONFIG_IWL4965_HT */ | 3157 | #endif /* CONFIG_IWL4965_HT */ |
3445 | 3158 | ||
3446 | /** | ||
3447 | * iwl4965_add_station - Initialize a station's hardware rate table | ||
3448 | * | ||
3449 | * The uCode's station table contains a table of fallback rates | ||
3450 | * for automatic fallback during transmission. | ||
3451 | * | ||
3452 | * NOTE: This sets up a default set of values. These will be replaced later | ||
3453 | * if the driver's iwl-4965-rs rate scaling algorithm is used, instead of | ||
3454 | * rc80211_simple. | ||
3455 | * | ||
3456 | * NOTE: Run REPLY_ADD_STA command to set up station table entry, before | ||
3457 | * calling this function (which runs REPLY_TX_LINK_QUALITY_CMD, | ||
3458 | * which requires station table entry to exist). | ||
3459 | */ | ||
3460 | void iwl4965_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap) | ||
3461 | { | ||
3462 | int i, r; | ||
3463 | struct iwl_link_quality_cmd link_cmd = { | ||
3464 | .reserved1 = 0, | ||
3465 | }; | ||
3466 | u16 rate_flags; | ||
3467 | |||
3468 | /* Set up the rate scaling to start at selected rate, fall back | ||
3469 | * all the way down to 1M in IEEE order, and then spin on 1M */ | ||
3470 | if (is_ap) | ||
3471 | r = IWL_RATE_54M_INDEX; | ||
3472 | else if (priv->band == IEEE80211_BAND_5GHZ) | ||
3473 | r = IWL_RATE_6M_INDEX; | ||
3474 | else | ||
3475 | r = IWL_RATE_1M_INDEX; | ||
3476 | |||
3477 | for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) { | ||
3478 | rate_flags = 0; | ||
3479 | if (r >= IWL_FIRST_CCK_RATE && r <= IWL_LAST_CCK_RATE) | ||
3480 | rate_flags |= RATE_MCS_CCK_MSK; | ||
3481 | |||
3482 | /* Use Tx antenna B only */ | ||
3483 | rate_flags |= RATE_MCS_ANT_B_MSK; /*FIXME:RS*/ | ||
3484 | |||
3485 | link_cmd.rs_table[i].rate_n_flags = | ||
3486 | iwl4965_hw_set_rate_n_flags(iwl4965_rates[r].plcp, rate_flags); | ||
3487 | r = iwl4965_get_prev_ieee_rate(r); | ||
3488 | } | ||
3489 | |||
3490 | link_cmd.general_params.single_stream_ant_msk = 2; | ||
3491 | link_cmd.general_params.dual_stream_ant_msk = 3; | ||
3492 | link_cmd.agg_params.agg_dis_start_th = 3; | ||
3493 | link_cmd.agg_params.agg_time_limit = cpu_to_le16(4000); | ||
3494 | |||
3495 | /* Update the rate scaling for control frame Tx to AP */ | ||
3496 | link_cmd.sta_id = is_ap ? IWL_AP_ID : priv->hw_params.bcast_sta_id; | ||
3497 | |||
3498 | iwl_send_cmd_pdu_async(priv, REPLY_TX_LINK_QUALITY_CMD, | ||
3499 | sizeof(link_cmd), &link_cmd, NULL); | ||
3500 | } | ||
3501 | 3159 | ||
3502 | #ifdef CONFIG_IWL4965_HT | 3160 | #ifdef CONFIG_IWL4965_HT |
3503 | |||
3504 | void iwl4965_set_ht_add_station(struct iwl_priv *priv, u8 index, | ||
3505 | struct ieee80211_ht_info *sta_ht_inf) | ||
3506 | { | ||
3507 | __le32 sta_flags; | ||
3508 | u8 mimo_ps_mode; | ||
3509 | |||
3510 | if (!sta_ht_inf || !sta_ht_inf->ht_supported) | ||
3511 | goto done; | ||
3512 | |||
3513 | mimo_ps_mode = (sta_ht_inf->cap & IEEE80211_HT_CAP_MIMO_PS) >> 2; | ||
3514 | |||
3515 | sta_flags = priv->stations[index].sta.station_flags; | ||
3516 | |||
3517 | sta_flags &= ~(STA_FLG_RTS_MIMO_PROT_MSK | STA_FLG_MIMO_DIS_MSK); | ||
3518 | |||
3519 | switch (mimo_ps_mode) { | ||
3520 | case WLAN_HT_CAP_MIMO_PS_STATIC: | ||
3521 | sta_flags |= STA_FLG_MIMO_DIS_MSK; | ||
3522 | break; | ||
3523 | case WLAN_HT_CAP_MIMO_PS_DYNAMIC: | ||
3524 | sta_flags |= STA_FLG_RTS_MIMO_PROT_MSK; | ||
3525 | break; | ||
3526 | case WLAN_HT_CAP_MIMO_PS_DISABLED: | ||
3527 | break; | ||
3528 | default: | ||
3529 | IWL_WARNING("Invalid MIMO PS mode %d", mimo_ps_mode); | ||
3530 | break; | ||
3531 | } | ||
3532 | |||
3533 | sta_flags |= cpu_to_le32( | ||
3534 | (u32)sta_ht_inf->ampdu_factor << STA_FLG_MAX_AGG_SIZE_POS); | ||
3535 | |||
3536 | sta_flags |= cpu_to_le32( | ||
3537 | (u32)sta_ht_inf->ampdu_density << STA_FLG_AGG_MPDU_DENSITY_POS); | ||
3538 | |||
3539 | if (iwl_is_fat_tx_allowed(priv, sta_ht_inf)) | ||
3540 | sta_flags |= STA_FLG_FAT_EN_MSK; | ||
3541 | else | ||
3542 | sta_flags &= ~STA_FLG_FAT_EN_MSK; | ||
3543 | |||
3544 | priv->stations[index].sta.station_flags = sta_flags; | ||
3545 | done: | ||
3546 | return; | ||
3547 | } | ||
3548 | |||
3549 | static int iwl4965_rx_agg_start(struct iwl_priv *priv, | 3161 | static int iwl4965_rx_agg_start(struct iwl_priv *priv, |
3550 | const u8 *addr, int tid, u16 ssn) | 3162 | const u8 *addr, int tid, u16 ssn) |
3551 | { | 3163 | { |
@@ -3589,137 +3201,6 @@ static int iwl4965_rx_agg_stop(struct iwl_priv *priv, | |||
3589 | CMD_ASYNC); | 3201 | CMD_ASYNC); |
3590 | } | 3202 | } |
3591 | 3203 | ||
3592 | /* | ||
3593 | * Find first available (lowest unused) Tx Queue, mark it "active". | ||
3594 | * Called only when finding queue for aggregation. | ||
3595 | * Should never return anything < 7, because they should already | ||
3596 | * be in use as EDCA AC (0-3), Command (4), HCCA (5, 6). | ||
3597 | */ | ||
3598 | static int iwl4965_txq_ctx_activate_free(struct iwl_priv *priv) | ||
3599 | { | ||
3600 | int txq_id; | ||
3601 | |||
3602 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) | ||
3603 | if (!test_and_set_bit(txq_id, &priv->txq_ctx_active_msk)) | ||
3604 | return txq_id; | ||
3605 | return -1; | ||
3606 | } | ||
3607 | |||
3608 | static int iwl4965_tx_agg_start(struct ieee80211_hw *hw, const u8 *ra, | ||
3609 | u16 tid, u16 *start_seq_num) | ||
3610 | { | ||
3611 | struct iwl_priv *priv = hw->priv; | ||
3612 | int sta_id; | ||
3613 | int tx_fifo; | ||
3614 | int txq_id; | ||
3615 | int ssn = -1; | ||
3616 | int ret = 0; | ||
3617 | unsigned long flags; | ||
3618 | struct iwl_tid_data *tid_data; | ||
3619 | DECLARE_MAC_BUF(mac); | ||
3620 | |||
3621 | if (likely(tid < ARRAY_SIZE(default_tid_to_tx_fifo))) | ||
3622 | tx_fifo = default_tid_to_tx_fifo[tid]; | ||
3623 | else | ||
3624 | return -EINVAL; | ||
3625 | |||
3626 | IWL_WARNING("%s on ra = %s tid = %d\n", | ||
3627 | __func__, print_mac(mac, ra), tid); | ||
3628 | |||
3629 | sta_id = iwl_find_station(priv, ra); | ||
3630 | if (sta_id == IWL_INVALID_STATION) | ||
3631 | return -ENXIO; | ||
3632 | |||
3633 | if (priv->stations[sta_id].tid[tid].agg.state != IWL_AGG_OFF) { | ||
3634 | IWL_ERROR("Start AGG when state is not IWL_AGG_OFF !\n"); | ||
3635 | return -ENXIO; | ||
3636 | } | ||
3637 | |||
3638 | txq_id = iwl4965_txq_ctx_activate_free(priv); | ||
3639 | if (txq_id == -1) | ||
3640 | return -ENXIO; | ||
3641 | |||
3642 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
3643 | tid_data = &priv->stations[sta_id].tid[tid]; | ||
3644 | ssn = SEQ_TO_SN(tid_data->seq_number); | ||
3645 | tid_data->agg.txq_id = txq_id; | ||
3646 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
3647 | |||
3648 | *start_seq_num = ssn; | ||
3649 | ret = iwl4965_tx_queue_agg_enable(priv, txq_id, tx_fifo, | ||
3650 | sta_id, tid, ssn); | ||
3651 | if (ret) | ||
3652 | return ret; | ||
3653 | |||
3654 | ret = 0; | ||
3655 | if (tid_data->tfds_in_queue == 0) { | ||
3656 | printk(KERN_ERR "HW queue is empty\n"); | ||
3657 | tid_data->agg.state = IWL_AGG_ON; | ||
3658 | ieee80211_start_tx_ba_cb_irqsafe(hw, ra, tid); | ||
3659 | } else { | ||
3660 | IWL_DEBUG_HT("HW queue is NOT empty: %d packets in HW queue\n", | ||
3661 | tid_data->tfds_in_queue); | ||
3662 | tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_ADDBA; | ||
3663 | } | ||
3664 | return ret; | ||
3665 | } | ||
3666 | |||
3667 | static int iwl4965_tx_agg_stop(struct ieee80211_hw *hw, const u8 *ra, u16 tid) | ||
3668 | { | ||
3669 | struct iwl_priv *priv = hw->priv; | ||
3670 | int tx_fifo_id, txq_id, sta_id, ssn = -1; | ||
3671 | struct iwl_tid_data *tid_data; | ||
3672 | int ret, write_ptr, read_ptr; | ||
3673 | unsigned long flags; | ||
3674 | DECLARE_MAC_BUF(mac); | ||
3675 | |||
3676 | if (!ra) { | ||
3677 | IWL_ERROR("ra = NULL\n"); | ||
3678 | return -EINVAL; | ||
3679 | } | ||
3680 | |||
3681 | if (likely(tid < ARRAY_SIZE(default_tid_to_tx_fifo))) | ||
3682 | tx_fifo_id = default_tid_to_tx_fifo[tid]; | ||
3683 | else | ||
3684 | return -EINVAL; | ||
3685 | |||
3686 | sta_id = iwl_find_station(priv, ra); | ||
3687 | |||
3688 | if (sta_id == IWL_INVALID_STATION) | ||
3689 | return -ENXIO; | ||
3690 | |||
3691 | if (priv->stations[sta_id].tid[tid].agg.state != IWL_AGG_ON) | ||
3692 | IWL_WARNING("Stopping AGG while state not IWL_AGG_ON\n"); | ||
3693 | |||
3694 | tid_data = &priv->stations[sta_id].tid[tid]; | ||
3695 | ssn = (tid_data->seq_number & IEEE80211_SCTL_SEQ) >> 4; | ||
3696 | txq_id = tid_data->agg.txq_id; | ||
3697 | write_ptr = priv->txq[txq_id].q.write_ptr; | ||
3698 | read_ptr = priv->txq[txq_id].q.read_ptr; | ||
3699 | |||
3700 | /* The queue is not empty */ | ||
3701 | if (write_ptr != read_ptr) { | ||
3702 | IWL_DEBUG_HT("Stopping a non empty AGG HW QUEUE\n"); | ||
3703 | priv->stations[sta_id].tid[tid].agg.state = | ||
3704 | IWL_EMPTYING_HW_QUEUE_DELBA; | ||
3705 | return 0; | ||
3706 | } | ||
3707 | |||
3708 | IWL_DEBUG_HT("HW queue is empty\n"); | ||
3709 | priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; | ||
3710 | |||
3711 | spin_lock_irqsave(&priv->lock, flags); | ||
3712 | ret = iwl4965_tx_queue_agg_disable(priv, txq_id, ssn, tx_fifo_id); | ||
3713 | spin_unlock_irqrestore(&priv->lock, flags); | ||
3714 | |||
3715 | if (ret) | ||
3716 | return ret; | ||
3717 | |||
3718 | ieee80211_stop_tx_ba_cb_irqsafe(priv->hw, ra, tid); | ||
3719 | |||
3720 | return 0; | ||
3721 | } | ||
3722 | |||
3723 | int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw, | 3204 | int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw, |
3724 | enum ieee80211_ampdu_mlme_action action, | 3205 | enum ieee80211_ampdu_mlme_action action, |
3725 | const u8 *addr, u16 tid, u16 *ssn) | 3206 | const u8 *addr, u16 tid, u16 *ssn) |
@@ -3739,10 +3220,10 @@ int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw, | |||
3739 | return iwl4965_rx_agg_stop(priv, addr, tid); | 3220 | return iwl4965_rx_agg_stop(priv, addr, tid); |
3740 | case IEEE80211_AMPDU_TX_START: | 3221 | case IEEE80211_AMPDU_TX_START: |
3741 | IWL_DEBUG_HT("start Tx\n"); | 3222 | IWL_DEBUG_HT("start Tx\n"); |
3742 | return iwl4965_tx_agg_start(hw, addr, tid, ssn); | 3223 | return iwl_tx_agg_start(priv, addr, tid, ssn); |
3743 | case IEEE80211_AMPDU_TX_STOP: | 3224 | case IEEE80211_AMPDU_TX_STOP: |
3744 | IWL_DEBUG_HT("stop Tx\n"); | 3225 | IWL_DEBUG_HT("stop Tx\n"); |
3745 | return iwl4965_tx_agg_stop(hw, addr, tid); | 3226 | return iwl_tx_agg_stop(priv, addr, tid); |
3746 | default: | 3227 | default: |
3747 | IWL_DEBUG_HT("unknown\n"); | 3228 | IWL_DEBUG_HT("unknown\n"); |
3748 | return -EINVAL; | 3229 | return -EINVAL; |
@@ -3753,6 +3234,16 @@ int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw, | |||
3753 | #endif /* CONFIG_IWL4965_HT */ | 3234 | #endif /* CONFIG_IWL4965_HT */ |
3754 | 3235 | ||
3755 | 3236 | ||
3237 | static u16 iwl4965_get_hcmd_size(u8 cmd_id, u16 len) | ||
3238 | { | ||
3239 | switch (cmd_id) { | ||
3240 | case REPLY_RXON: | ||
3241 | return (u16) sizeof(struct iwl4965_rxon_cmd); | ||
3242 | default: | ||
3243 | return len; | ||
3244 | } | ||
3245 | } | ||
3246 | |||
3756 | static u16 iwl4965_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data) | 3247 | static u16 iwl4965_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data) |
3757 | { | 3248 | { |
3758 | struct iwl4965_addsta_cmd *addsta = (struct iwl4965_addsta_cmd *)data; | 3249 | struct iwl4965_addsta_cmd *addsta = (struct iwl4965_addsta_cmd *)data; |
@@ -3770,18 +3261,258 @@ static u16 iwl4965_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data) | |||
3770 | 3261 | ||
3771 | return (u16)sizeof(struct iwl4965_addsta_cmd); | 3262 | return (u16)sizeof(struct iwl4965_addsta_cmd); |
3772 | } | 3263 | } |
3264 | |||
3265 | #ifdef CONFIG_IWL4965_HT | ||
3266 | static inline u32 iwl4965_get_scd_ssn(struct iwl4965_tx_resp *tx_resp) | ||
3267 | { | ||
3268 | __le32 *scd_ssn = (__le32 *)((u32 *)&tx_resp->status + | ||
3269 | tx_resp->frame_count); | ||
3270 | return le32_to_cpu(*scd_ssn) & MAX_SN; | ||
3271 | |||
3272 | } | ||
3273 | |||
3274 | /** | ||
3275 | * iwl4965_tx_status_reply_tx - Handle Tx rspnse for frames in aggregation queue | ||
3276 | */ | ||
3277 | static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv, | ||
3278 | struct iwl_ht_agg *agg, | ||
3279 | struct iwl4965_tx_resp_agg *tx_resp, | ||
3280 | u16 start_idx) | ||
3281 | { | ||
3282 | u16 status; | ||
3283 | struct agg_tx_status *frame_status = &tx_resp->status; | ||
3284 | struct ieee80211_tx_info *info = NULL; | ||
3285 | struct ieee80211_hdr *hdr = NULL; | ||
3286 | int i, sh; | ||
3287 | int txq_id, idx; | ||
3288 | u16 seq; | ||
3289 | |||
3290 | if (agg->wait_for_ba) | ||
3291 | IWL_DEBUG_TX_REPLY("got tx response w/o block-ack\n"); | ||
3292 | |||
3293 | agg->frame_count = tx_resp->frame_count; | ||
3294 | agg->start_idx = start_idx; | ||
3295 | agg->rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags); | ||
3296 | agg->bitmap = 0; | ||
3297 | |||
3298 | /* # frames attempted by Tx command */ | ||
3299 | if (agg->frame_count == 1) { | ||
3300 | /* Only one frame was attempted; no block-ack will arrive */ | ||
3301 | status = le16_to_cpu(frame_status[0].status); | ||
3302 | seq = le16_to_cpu(frame_status[0].sequence); | ||
3303 | idx = SEQ_TO_INDEX(seq); | ||
3304 | txq_id = SEQ_TO_QUEUE(seq); | ||
3305 | |||
3306 | /* FIXME: code repetition */ | ||
3307 | IWL_DEBUG_TX_REPLY("FrameCnt = %d, StartIdx=%d idx=%d\n", | ||
3308 | agg->frame_count, agg->start_idx, idx); | ||
3309 | |||
3310 | info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb[0]); | ||
3311 | info->status.retry_count = tx_resp->failure_frame; | ||
3312 | info->flags &= ~IEEE80211_TX_CTL_AMPDU; | ||
3313 | info->flags |= iwl_is_tx_success(status)? | ||
3314 | IEEE80211_TX_STAT_ACK : 0; | ||
3315 | iwl4965_hwrate_to_tx_control(priv, | ||
3316 | le32_to_cpu(tx_resp->rate_n_flags), | ||
3317 | info); | ||
3318 | /* FIXME: code repetition end */ | ||
3319 | |||
3320 | IWL_DEBUG_TX_REPLY("1 Frame 0x%x failure :%d\n", | ||
3321 | status & 0xff, tx_resp->failure_frame); | ||
3322 | IWL_DEBUG_TX_REPLY("Rate Info rate_n_flags=%x\n", | ||
3323 | iwl4965_hw_get_rate_n_flags(tx_resp->rate_n_flags)); | ||
3324 | |||
3325 | agg->wait_for_ba = 0; | ||
3326 | } else { | ||
3327 | /* Two or more frames were attempted; expect block-ack */ | ||
3328 | u64 bitmap = 0; | ||
3329 | int start = agg->start_idx; | ||
3330 | |||
3331 | /* Construct bit-map of pending frames within Tx window */ | ||
3332 | for (i = 0; i < agg->frame_count; i++) { | ||
3333 | u16 sc; | ||
3334 | status = le16_to_cpu(frame_status[i].status); | ||
3335 | seq = le16_to_cpu(frame_status[i].sequence); | ||
3336 | idx = SEQ_TO_INDEX(seq); | ||
3337 | txq_id = SEQ_TO_QUEUE(seq); | ||
3338 | |||
3339 | if (status & (AGG_TX_STATE_FEW_BYTES_MSK | | ||
3340 | AGG_TX_STATE_ABORT_MSK)) | ||
3341 | continue; | ||
3342 | |||
3343 | IWL_DEBUG_TX_REPLY("FrameCnt = %d, txq_id=%d idx=%d\n", | ||
3344 | agg->frame_count, txq_id, idx); | ||
3345 | |||
3346 | hdr = iwl_tx_queue_get_hdr(priv, txq_id, idx); | ||
3347 | |||
3348 | sc = le16_to_cpu(hdr->seq_ctrl); | ||
3349 | if (idx != (SEQ_TO_SN(sc) & 0xff)) { | ||
3350 | IWL_ERROR("BUG_ON idx doesn't match seq control" | ||
3351 | " idx=%d, seq_idx=%d, seq=%d\n", | ||
3352 | idx, SEQ_TO_SN(sc), | ||
3353 | hdr->seq_ctrl); | ||
3354 | return -1; | ||
3355 | } | ||
3356 | |||
3357 | IWL_DEBUG_TX_REPLY("AGG Frame i=%d idx %d seq=%d\n", | ||
3358 | i, idx, SEQ_TO_SN(sc)); | ||
3359 | |||
3360 | sh = idx - start; | ||
3361 | if (sh > 64) { | ||
3362 | sh = (start - idx) + 0xff; | ||
3363 | bitmap = bitmap << sh; | ||
3364 | sh = 0; | ||
3365 | start = idx; | ||
3366 | } else if (sh < -64) | ||
3367 | sh = 0xff - (start - idx); | ||
3368 | else if (sh < 0) { | ||
3369 | sh = start - idx; | ||
3370 | start = idx; | ||
3371 | bitmap = bitmap << sh; | ||
3372 | sh = 0; | ||
3373 | } | ||
3374 | bitmap |= (1 << sh); | ||
3375 | IWL_DEBUG_TX_REPLY("start=%d bitmap=0x%x\n", | ||
3376 | start, (u32)(bitmap & 0xFFFFFFFF)); | ||
3377 | } | ||
3378 | |||
3379 | agg->bitmap = bitmap; | ||
3380 | agg->start_idx = start; | ||
3381 | agg->rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags); | ||
3382 | IWL_DEBUG_TX_REPLY("Frames %d start_idx=%d bitmap=0x%llx\n", | ||
3383 | agg->frame_count, agg->start_idx, | ||
3384 | (unsigned long long)agg->bitmap); | ||
3385 | |||
3386 | if (bitmap) | ||
3387 | agg->wait_for_ba = 1; | ||
3388 | } | ||
3389 | return 0; | ||
3390 | } | ||
3391 | #endif | ||
3392 | |||
3393 | /** | ||
3394 | * iwl4965_rx_reply_tx - Handle standard (non-aggregation) Tx response | ||
3395 | */ | ||
3396 | static void iwl4965_rx_reply_tx(struct iwl_priv *priv, | ||
3397 | struct iwl_rx_mem_buffer *rxb) | ||
3398 | { | ||
3399 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | ||
3400 | u16 sequence = le16_to_cpu(pkt->hdr.sequence); | ||
3401 | int txq_id = SEQ_TO_QUEUE(sequence); | ||
3402 | int index = SEQ_TO_INDEX(sequence); | ||
3403 | struct iwl_tx_queue *txq = &priv->txq[txq_id]; | ||
3404 | struct ieee80211_tx_info *info; | ||
3405 | struct iwl4965_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; | ||
3406 | u32 status = le32_to_cpu(tx_resp->status); | ||
3407 | #ifdef CONFIG_IWL4965_HT | ||
3408 | int tid = MAX_TID_COUNT, sta_id = IWL_INVALID_STATION; | ||
3409 | u16 fc; | ||
3410 | struct ieee80211_hdr *hdr; | ||
3411 | u8 *qc = NULL; | ||
3412 | #endif | ||
3413 | |||
3414 | if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) { | ||
3415 | IWL_ERROR("Read index for DMA queue txq_id (%d) index %d " | ||
3416 | "is out of range [0-%d] %d %d\n", txq_id, | ||
3417 | index, txq->q.n_bd, txq->q.write_ptr, | ||
3418 | txq->q.read_ptr); | ||
3419 | return; | ||
3420 | } | ||
3421 | |||
3422 | info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb[0]); | ||
3423 | memset(&info->status, 0, sizeof(info->status)); | ||
3424 | |||
3425 | #ifdef CONFIG_IWL4965_HT | ||
3426 | hdr = iwl_tx_queue_get_hdr(priv, txq_id, index); | ||
3427 | fc = le16_to_cpu(hdr->frame_control); | ||
3428 | if (ieee80211_is_qos_data(fc)) { | ||
3429 | qc = ieee80211_get_qos_ctrl(hdr, ieee80211_get_hdrlen(fc)); | ||
3430 | tid = qc[0] & 0xf; | ||
3431 | } | ||
3432 | |||
3433 | sta_id = iwl_get_ra_sta_id(priv, hdr); | ||
3434 | if (txq->sched_retry && unlikely(sta_id == IWL_INVALID_STATION)) { | ||
3435 | IWL_ERROR("Station not known\n"); | ||
3436 | return; | ||
3437 | } | ||
3438 | |||
3439 | if (txq->sched_retry) { | ||
3440 | const u32 scd_ssn = iwl4965_get_scd_ssn(tx_resp); | ||
3441 | struct iwl_ht_agg *agg = NULL; | ||
3442 | |||
3443 | if (!qc) | ||
3444 | return; | ||
3445 | |||
3446 | agg = &priv->stations[sta_id].tid[tid].agg; | ||
3447 | |||
3448 | iwl4965_tx_status_reply_tx(priv, agg, | ||
3449 | (struct iwl4965_tx_resp_agg *)tx_resp, index); | ||
3450 | |||
3451 | if ((tx_resp->frame_count == 1) && !iwl_is_tx_success(status)) { | ||
3452 | /* TODO: send BAR */ | ||
3453 | } | ||
3454 | |||
3455 | if (txq->q.read_ptr != (scd_ssn & 0xff)) { | ||
3456 | int freed, ampdu_q; | ||
3457 | index = iwl_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd); | ||
3458 | IWL_DEBUG_TX_REPLY("Retry scheduler reclaim scd_ssn " | ||
3459 | "%d index %d\n", scd_ssn , index); | ||
3460 | freed = iwl_tx_queue_reclaim(priv, txq_id, index); | ||
3461 | priv->stations[sta_id].tid[tid].tfds_in_queue -= freed; | ||
3462 | |||
3463 | if (iwl_queue_space(&txq->q) > txq->q.low_mark && | ||
3464 | txq_id >= 0 && priv->mac80211_registered && | ||
3465 | agg->state != IWL_EMPTYING_HW_QUEUE_DELBA) { | ||
3466 | /* calculate mac80211 ampdu sw queue to wake */ | ||
3467 | ampdu_q = txq_id - IWL_BACK_QUEUE_FIRST_ID + | ||
3468 | priv->hw->queues; | ||
3469 | if (agg->state == IWL_AGG_OFF) | ||
3470 | ieee80211_wake_queue(priv->hw, txq_id); | ||
3471 | else | ||
3472 | ieee80211_wake_queue(priv->hw, ampdu_q); | ||
3473 | } | ||
3474 | iwl_txq_check_empty(priv, sta_id, tid, txq_id); | ||
3475 | } | ||
3476 | } else { | ||
3477 | #endif /* CONFIG_IWL4965_HT */ | ||
3478 | |||
3479 | info->status.retry_count = tx_resp->failure_frame; | ||
3480 | info->flags |= iwl_is_tx_success(status) ? IEEE80211_TX_STAT_ACK : 0; | ||
3481 | iwl4965_hwrate_to_tx_control(priv, le32_to_cpu(tx_resp->rate_n_flags), | ||
3482 | info); | ||
3483 | |||
3484 | IWL_DEBUG_TX("Tx queue %d Status %s (0x%08x) rate_n_flags 0x%x " | ||
3485 | "retries %d\n", txq_id, iwl_get_tx_fail_reason(status), | ||
3486 | status, le32_to_cpu(tx_resp->rate_n_flags), | ||
3487 | tx_resp->failure_frame); | ||
3488 | |||
3489 | IWL_DEBUG_TX_REPLY("Tx queue reclaim %d\n", index); | ||
3490 | #ifdef CONFIG_IWL4965_HT | ||
3491 | if (index != -1) { | ||
3492 | int freed = iwl_tx_queue_reclaim(priv, txq_id, index); | ||
3493 | if (tid != MAX_TID_COUNT) | ||
3494 | priv->stations[sta_id].tid[tid].tfds_in_queue -= freed; | ||
3495 | if (iwl_queue_space(&txq->q) > txq->q.low_mark && | ||
3496 | (txq_id >= 0) && priv->mac80211_registered) | ||
3497 | ieee80211_wake_queue(priv->hw, txq_id); | ||
3498 | if (tid != MAX_TID_COUNT) | ||
3499 | iwl_txq_check_empty(priv, sta_id, tid, txq_id); | ||
3500 | } | ||
3501 | } | ||
3502 | #endif /* CONFIG_IWL4965_HT */ | ||
3503 | |||
3504 | if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK)) | ||
3505 | IWL_ERROR("TODO: Implement Tx ABORT REQUIRED!!!\n"); | ||
3506 | } | ||
3507 | |||
3508 | |||
3773 | /* Set up 4965-specific Rx frame reply handlers */ | 3509 | /* Set up 4965-specific Rx frame reply handlers */ |
3774 | static void iwl4965_rx_handler_setup(struct iwl_priv *priv) | 3510 | static void iwl4965_rx_handler_setup(struct iwl_priv *priv) |
3775 | { | 3511 | { |
3776 | /* Legacy Rx frames */ | 3512 | /* Legacy Rx frames */ |
3777 | priv->rx_handlers[REPLY_RX] = iwl4965_rx_reply_rx; | 3513 | priv->rx_handlers[REPLY_RX] = iwl4965_rx_reply_rx; |
3778 | 3514 | /* Tx response */ | |
3779 | /* High-throughput (HT) Rx frames */ | 3515 | priv->rx_handlers[REPLY_TX] = iwl4965_rx_reply_tx; |
3780 | priv->rx_handlers[REPLY_RX_PHY_CMD] = iwl4965_rx_reply_rx_phy; | ||
3781 | priv->rx_handlers[REPLY_RX_MPDU_CMD] = iwl4965_rx_reply_rx; | ||
3782 | |||
3783 | priv->rx_handlers[MISSED_BEACONS_NOTIFICATION] = | ||
3784 | iwl4965_rx_missed_beacon_notif; | ||
3785 | 3516 | ||
3786 | #ifdef CONFIG_IWL4965_HT | 3517 | #ifdef CONFIG_IWL4965_HT |
3787 | priv->rx_handlers[REPLY_COMPRESSED_BA] = iwl4965_rx_reply_compressed_ba; | 3518 | priv->rx_handlers[REPLY_COMPRESSED_BA] = iwl4965_rx_reply_compressed_ba; |
@@ -3812,7 +3543,7 @@ static struct iwl_hcmd_ops iwl4965_hcmd = { | |||
3812 | }; | 3543 | }; |
3813 | 3544 | ||
3814 | static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = { | 3545 | static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = { |
3815 | .enqueue_hcmd = iwl4965_enqueue_hcmd, | 3546 | .get_hcmd_size = iwl4965_get_hcmd_size, |
3816 | .build_addsta_hcmd = iwl4965_build_addsta_hcmd, | 3547 | .build_addsta_hcmd = iwl4965_build_addsta_hcmd, |
3817 | #ifdef CONFIG_IWL4965_RUN_TIME_CALIB | 3548 | #ifdef CONFIG_IWL4965_RUN_TIME_CALIB |
3818 | .chain_noise_reset = iwl4965_chain_noise_reset, | 3549 | .chain_noise_reset = iwl4965_chain_noise_reset, |
@@ -3826,7 +3557,11 @@ static struct iwl_lib_ops iwl4965_lib = { | |||
3826 | .free_shared_mem = iwl4965_free_shared_mem, | 3557 | .free_shared_mem = iwl4965_free_shared_mem, |
3827 | .shared_mem_rx_idx = iwl4965_shared_mem_rx_idx, | 3558 | .shared_mem_rx_idx = iwl4965_shared_mem_rx_idx, |
3828 | .txq_update_byte_cnt_tbl = iwl4965_txq_update_byte_cnt_tbl, | 3559 | .txq_update_byte_cnt_tbl = iwl4965_txq_update_byte_cnt_tbl, |
3829 | .disable_tx_fifo = iwl4965_disable_tx_fifo, | 3560 | .txq_set_sched = iwl4965_txq_set_sched, |
3561 | #ifdef CONFIG_IWL4965_HT | ||
3562 | .txq_agg_enable = iwl4965_txq_agg_enable, | ||
3563 | .txq_agg_disable = iwl4965_txq_agg_disable, | ||
3564 | #endif | ||
3830 | .rx_handler_setup = iwl4965_rx_handler_setup, | 3565 | .rx_handler_setup = iwl4965_rx_handler_setup, |
3831 | .is_valid_rtc_data_addr = iwl4965_hw_valid_rtc_data_addr, | 3566 | .is_valid_rtc_data_addr = iwl4965_hw_valid_rtc_data_addr, |
3832 | .alive_notify = iwl4965_alive_notify, | 3567 | .alive_notify = iwl4965_alive_notify, |
@@ -3834,6 +3569,8 @@ static struct iwl_lib_ops iwl4965_lib = { | |||
3834 | .load_ucode = iwl4965_load_bsm, | 3569 | .load_ucode = iwl4965_load_bsm, |
3835 | .apm_ops = { | 3570 | .apm_ops = { |
3836 | .init = iwl4965_apm_init, | 3571 | .init = iwl4965_apm_init, |
3572 | .reset = iwl4965_apm_reset, | ||
3573 | .stop = iwl4965_apm_stop, | ||
3837 | .config = iwl4965_nic_config, | 3574 | .config = iwl4965_nic_config, |
3838 | .set_pwr_src = iwl4965_set_pwr_src, | 3575 | .set_pwr_src = iwl4965_set_pwr_src, |
3839 | }, | 3576 | }, |