diff options
author | Wey-Yi Guy <wey-yi.w.guy@intel.com> | 2010-11-10 12:56:50 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-11-15 13:26:59 -0500 |
commit | f81c1f48384d398dbe8f6c5b10377c7158086791 (patch) | |
tree | f5a813c7e3b66a024adb7db8359c920fb878a4db /drivers/net/wireless | |
parent | 6fe8efb2211fe61caa7b0e1c36c521670b8a10a9 (diff) |
iwlagn: enable shadow register
For 6000 series devices and up, enable automatic update MAC's register
for better power usage in PSP mode
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-6000.c | 3 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 6 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-core.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-csr.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-rx.c | 45 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-tx.c | 51 |
6 files changed, 70 insertions, 39 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 21ac2817722e..c7ff1bdf42cd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c | |||
@@ -487,6 +487,7 @@ static struct iwl_base_params iwl6000_base_params = { | |||
487 | .ucode_tracing = true, | 487 | .ucode_tracing = true, |
488 | .sensitivity_calib_by_driver = true, | 488 | .sensitivity_calib_by_driver = true, |
489 | .chain_noise_calib_by_driver = true, | 489 | .chain_noise_calib_by_driver = true, |
490 | .shadow_reg_enable = true, | ||
490 | }; | 491 | }; |
491 | 492 | ||
492 | static struct iwl_base_params iwl6050_base_params = { | 493 | static struct iwl_base_params iwl6050_base_params = { |
@@ -510,6 +511,7 @@ static struct iwl_base_params iwl6050_base_params = { | |||
510 | .ucode_tracing = true, | 511 | .ucode_tracing = true, |
511 | .sensitivity_calib_by_driver = true, | 512 | .sensitivity_calib_by_driver = true, |
512 | .chain_noise_calib_by_driver = true, | 513 | .chain_noise_calib_by_driver = true, |
514 | .shadow_reg_enable = true, | ||
513 | }; | 515 | }; |
514 | static struct iwl_base_params iwl6000_coex_base_params = { | 516 | static struct iwl_base_params iwl6000_coex_base_params = { |
515 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 517 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
@@ -532,6 +534,7 @@ static struct iwl_base_params iwl6000_coex_base_params = { | |||
532 | .ucode_tracing = true, | 534 | .ucode_tracing = true, |
533 | .sensitivity_calib_by_driver = true, | 535 | .sensitivity_calib_by_driver = true, |
534 | .chain_noise_calib_by_driver = true, | 536 | .chain_noise_calib_by_driver = true, |
537 | .shadow_reg_enable = true, | ||
535 | }; | 538 | }; |
536 | 539 | ||
537 | static struct iwl_ht_params iwl6000_ht_params = { | 540 | static struct iwl_ht_params iwl6000_ht_params = { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 019d4e7d7348..ca3530c4295a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c | |||
@@ -753,6 +753,12 @@ int iwlagn_hw_nic_init(struct iwl_priv *priv) | |||
753 | } else | 753 | } else |
754 | iwlagn_txq_ctx_reset(priv); | 754 | iwlagn_txq_ctx_reset(priv); |
755 | 755 | ||
756 | if (priv->cfg->base_params->shadow_reg_enable) { | ||
757 | /* enable shadow regs in HW */ | ||
758 | iwl_set_bit(priv, CSR_MAC_SHADOW_REG_CTRL, | ||
759 | 0x800FFFFF); | ||
760 | } | ||
761 | |||
756 | set_bit(STATUS_INIT, &priv->status); | 762 | set_bit(STATUS_INIT, &priv->status); |
757 | 763 | ||
758 | return 0; | 764 | return 0; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 6064bc412e07..ee8cf240d65d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h | |||
@@ -290,6 +290,7 @@ struct iwl_mod_params { | |||
290 | * sensitivity calibration operation | 290 | * sensitivity calibration operation |
291 | * @chain_noise_calib_by_driver: driver has the capability to perform | 291 | * @chain_noise_calib_by_driver: driver has the capability to perform |
292 | * chain noise calibration operation | 292 | * chain noise calibration operation |
293 | * @shadow_reg_enable: HW shadhow register bit | ||
293 | */ | 294 | */ |
294 | struct iwl_base_params { | 295 | struct iwl_base_params { |
295 | int eeprom_size; | 296 | int eeprom_size; |
@@ -320,6 +321,7 @@ struct iwl_base_params { | |||
320 | const bool ucode_tracing; | 321 | const bool ucode_tracing; |
321 | const bool sensitivity_calib_by_driver; | 322 | const bool sensitivity_calib_by_driver; |
322 | const bool chain_noise_calib_by_driver; | 323 | const bool chain_noise_calib_by_driver; |
324 | const bool shadow_reg_enable; | ||
323 | }; | 325 | }; |
324 | /* | 326 | /* |
325 | * @advanced_bt_coexist: support advanced bt coexist | 327 | * @advanced_bt_coexist: support advanced bt coexist |
diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h index 2aa15ab13892..b80bf7dff55b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/iwlwifi/iwl-csr.h | |||
@@ -132,6 +132,8 @@ | |||
132 | 132 | ||
133 | #define CSR_LED_REG (CSR_BASE+0x094) | 133 | #define CSR_LED_REG (CSR_BASE+0x094) |
134 | #define CSR_DRAM_INT_TBL_REG (CSR_BASE+0x0A0) | 134 | #define CSR_DRAM_INT_TBL_REG (CSR_BASE+0x0A0) |
135 | #define CSR_MAC_SHADOW_REG_CTRL (CSR_BASE+0x0A8) /* 6000 and up */ | ||
136 | |||
135 | 137 | ||
136 | /* GIO Chicken Bits (PCI Express bus link power management) */ | 138 | /* GIO Chicken Bits (PCI Express bus link power management) */ |
137 | #define CSR_GIO_CHICKEN_BITS (CSR_BASE+0x100) | 139 | #define CSR_GIO_CHICKEN_BITS (CSR_BASE+0x100) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index baca4cc0073b..87a6fd84d4d2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c | |||
@@ -134,28 +134,37 @@ void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q | |||
134 | if (q->need_update == 0) | 134 | if (q->need_update == 0) |
135 | goto exit_unlock; | 135 | goto exit_unlock; |
136 | 136 | ||
137 | /* If power-saving is in use, make sure device is awake */ | 137 | if (priv->cfg->base_params->shadow_reg_enable) { |
138 | if (test_bit(STATUS_POWER_PMI, &priv->status)) { | 138 | /* shadow register enabled */ |
139 | reg = iwl_read32(priv, CSR_UCODE_DRV_GP1); | ||
140 | |||
141 | if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { | ||
142 | IWL_DEBUG_INFO(priv, "Rx queue requesting wakeup, GP1 = 0x%x\n", | ||
143 | reg); | ||
144 | iwl_set_bit(priv, CSR_GP_CNTRL, | ||
145 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); | ||
146 | goto exit_unlock; | ||
147 | } | ||
148 | |||
149 | q->write_actual = (q->write & ~0x7); | ||
150 | iwl_write_direct32(priv, rx_wrt_ptr_reg, q->write_actual); | ||
151 | |||
152 | /* Else device is assumed to be awake */ | ||
153 | } else { | ||
154 | /* Device expects a multiple of 8 */ | 139 | /* Device expects a multiple of 8 */ |
155 | q->write_actual = (q->write & ~0x7); | 140 | q->write_actual = (q->write & ~0x7); |
156 | iwl_write32(priv, rx_wrt_ptr_reg, q->write_actual); | 141 | iwl_write32(priv, rx_wrt_ptr_reg, q->write_actual); |
157 | } | 142 | } else { |
143 | /* If power-saving is in use, make sure device is awake */ | ||
144 | if (test_bit(STATUS_POWER_PMI, &priv->status)) { | ||
145 | reg = iwl_read32(priv, CSR_UCODE_DRV_GP1); | ||
146 | |||
147 | if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { | ||
148 | IWL_DEBUG_INFO(priv, | ||
149 | "Rx queue requesting wakeup," | ||
150 | " GP1 = 0x%x\n", reg); | ||
151 | iwl_set_bit(priv, CSR_GP_CNTRL, | ||
152 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); | ||
153 | goto exit_unlock; | ||
154 | } | ||
158 | 155 | ||
156 | q->write_actual = (q->write & ~0x7); | ||
157 | iwl_write_direct32(priv, rx_wrt_ptr_reg, | ||
158 | q->write_actual); | ||
159 | |||
160 | /* Else device is assumed to be awake */ | ||
161 | } else { | ||
162 | /* Device expects a multiple of 8 */ | ||
163 | q->write_actual = (q->write & ~0x7); | ||
164 | iwl_write_direct32(priv, rx_wrt_ptr_reg, | ||
165 | q->write_actual); | ||
166 | } | ||
167 | } | ||
159 | q->need_update = 0; | 168 | q->need_update = 0; |
160 | 169 | ||
161 | exit_unlock: | 170 | exit_unlock: |
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 7261ee49f282..feaa3670c6bb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c | |||
@@ -49,30 +49,39 @@ void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq) | |||
49 | if (txq->need_update == 0) | 49 | if (txq->need_update == 0) |
50 | return; | 50 | return; |
51 | 51 | ||
52 | /* if we're trying to save power */ | 52 | if (priv->cfg->base_params->shadow_reg_enable) { |
53 | if (test_bit(STATUS_POWER_PMI, &priv->status)) { | 53 | /* shadow register enabled */ |
54 | /* wake up nic if it's powered down ... | ||
55 | * uCode will wake up, and interrupt us again, so next | ||
56 | * time we'll skip this part. */ | ||
57 | reg = iwl_read32(priv, CSR_UCODE_DRV_GP1); | ||
58 | |||
59 | if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { | ||
60 | IWL_DEBUG_INFO(priv, "Tx queue %d requesting wakeup, GP1 = 0x%x\n", | ||
61 | txq_id, reg); | ||
62 | iwl_set_bit(priv, CSR_GP_CNTRL, | ||
63 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); | ||
64 | return; | ||
65 | } | ||
66 | |||
67 | iwl_write_direct32(priv, HBUS_TARG_WRPTR, | ||
68 | txq->q.write_ptr | (txq_id << 8)); | ||
69 | |||
70 | /* else not in power-save mode, uCode will never sleep when we're | ||
71 | * trying to tx (during RFKILL, we're not trying to tx). */ | ||
72 | } else | ||
73 | iwl_write32(priv, HBUS_TARG_WRPTR, | 54 | iwl_write32(priv, HBUS_TARG_WRPTR, |
74 | txq->q.write_ptr | (txq_id << 8)); | 55 | txq->q.write_ptr | (txq_id << 8)); |
56 | } else { | ||
57 | /* if we're trying to save power */ | ||
58 | if (test_bit(STATUS_POWER_PMI, &priv->status)) { | ||
59 | /* wake up nic if it's powered down ... | ||
60 | * uCode will wake up, and interrupt us again, so next | ||
61 | * time we'll skip this part. */ | ||
62 | reg = iwl_read32(priv, CSR_UCODE_DRV_GP1); | ||
63 | |||
64 | if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { | ||
65 | IWL_DEBUG_INFO(priv, | ||
66 | "Tx queue %d requesting wakeup," | ||
67 | " GP1 = 0x%x\n", txq_id, reg); | ||
68 | iwl_set_bit(priv, CSR_GP_CNTRL, | ||
69 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); | ||
70 | return; | ||
71 | } | ||
72 | |||
73 | iwl_write_direct32(priv, HBUS_TARG_WRPTR, | ||
74 | txq->q.write_ptr | (txq_id << 8)); | ||
75 | 75 | ||
76 | /* | ||
77 | * else not in power-save mode, | ||
78 | * uCode will never sleep when we're | ||
79 | * trying to tx (during RFKILL, we're not trying to tx). | ||
80 | */ | ||
81 | } else | ||
82 | iwl_write32(priv, HBUS_TARG_WRPTR, | ||
83 | txq->q.write_ptr | (txq_id << 8)); | ||
84 | } | ||
76 | txq->need_update = 0; | 85 | txq->need_update = 0; |
77 | } | 86 | } |
78 | EXPORT_SYMBOL(iwl_txq_update_write_ptr); | 87 | EXPORT_SYMBOL(iwl_txq_update_write_ptr); |