* [PATCH 01/36] iwlwifi: Support for uCode without init and bsm section [not found] <1196305816-23023-1-git-send-email-yi.zhu@intel.com> @ 2007-11-29 3:09 ` Zhu Yi 2007-11-29 3:09 ` [PATCH 02/36] iwlwifi: continue namespace changes - fix CONFIG variables Zhu Yi 0 siblings, 1 reply; 36+ messages in thread From: Zhu Yi @ 2007-11-29 3:09 UTC (permalink / raw) To: linville; +Cc: linux-wireless, Tomas Winkler, Gregory Greenman, Zhu Yi From: Tomas Winkler <tomas.winkler@intel.com> This patch enables loading fw w/o init and bsm section. It also provides general cleanup of the rutine. Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Signed-off-by: Gregory Greenman <gregory.greenman@intel.com> Signed-off-by: Zhu Yi <yi.zhu@intel.com> --- drivers/net/wireless/iwlwifi/iwl3945-base.c | 120 ++++++++++++-------------- drivers/net/wireless/iwlwifi/iwl4965-base.c | 122 ++++++++++++-------------- 2 files changed, 112 insertions(+), 130 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 96420d5..f93cd1d 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -5761,6 +5761,12 @@ static void iwl3945_nic_start(struct iwl3945_priv *priv) iwl3945_write32(priv, CSR_RESET, 0); } +static int iwl3945_alloc_fw_desc(struct pci_dev *pci_dev, struct fw_desc *desc) +{ + desc->v_addr = pci_alloc_consistent(pci_dev, desc->len, &desc->p_addr); + return (desc->v_addr != NULL) ? 0 : -ENOMEM; +} + /** * iwl3945_read_ucode - Read uCode images from disk file. * @@ -5769,7 +5775,7 @@ static void iwl3945_nic_start(struct iwl3945_priv *priv) static int iwl3945_read_ucode(struct iwl3945_priv *priv) { struct iwl3945_ucode *ucode; - int rc = 0; + int ret = 0; const struct firmware *ucode_raw; /* firmware file name contains uCode/driver compatibility version */ const char *name = "iwlwifi-3945" IWL3945_UCODE_API ".ucode"; @@ -5779,9 +5785,10 @@ static int iwl3945_read_ucode(struct iwl3945_priv *priv) /* Ask kernel firmware_class module to get the boot firmware off disk. * request_firmware() is synchronous, file is in memory on return. */ - rc = request_firmware(&ucode_raw, name, &priv->pci_dev->dev); - if (rc < 0) { - IWL_ERROR("%s firmware file req failed: Reason %d\n", name, rc); + ret = request_firmware(&ucode_raw, name, &priv->pci_dev->dev); + if (ret < 0) { + IWL_ERROR("%s firmware file req failed: Reason %d\n", + name, ret); goto error; } @@ -5791,7 +5798,7 @@ static int iwl3945_read_ucode(struct iwl3945_priv *priv) /* Make sure that we got at least our header! */ if (ucode_raw->size < sizeof(*ucode)) { IWL_ERROR("File size way too small!\n"); - rc = -EINVAL; + ret = -EINVAL; goto err_release; } @@ -5819,43 +5826,40 @@ static int iwl3945_read_ucode(struct iwl3945_priv *priv) IWL_DEBUG_INFO("uCode file size %d too small\n", (int)ucode_raw->size); - rc = -EINVAL; + ret = -EINVAL; goto err_release; } /* Verify that uCode images will fit in card's SRAM */ if (inst_size > IWL_MAX_INST_SIZE) { - IWL_DEBUG_INFO("uCode instr len %d too large to fit in card\n", - (int)inst_size); - rc = -EINVAL; + IWL_DEBUG_INFO("uCode instr len %d too large to fit in\n", + inst_size); + ret = -EINVAL; goto err_release; } if (data_size > IWL_MAX_DATA_SIZE) { - IWL_DEBUG_INFO("uCode data len %d too large to fit in card\n", - (int)data_size); - rc = -EINVAL; + IWL_DEBUG_INFO("uCode data len %d too large to fit in\n", + data_size); + ret = -EINVAL; goto err_release; } if (init_size > IWL_MAX_INST_SIZE) { - IWL_DEBUG_INFO - ("uCode init instr len %d too large to fit in card\n", - (int)init_size); - rc = -EINVAL; + IWL_DEBUG_INFO("uCode init instr len %d too large to fit in\n", + init_size); + ret = -EINVAL; goto err_release; } if (init_data_size > IWL_MAX_DATA_SIZE) { - IWL_DEBUG_INFO - ("uCode init data len %d too large to fit in card\n", - (int)init_data_size); - rc = -EINVAL; + IWL_DEBUG_INFO("uCode init data len %d too large to fit in\n", + init_data_size); + ret = -EINVAL; goto err_release; } if (boot_size > IWL_MAX_BSM_SIZE) { - IWL_DEBUG_INFO - ("uCode boot instr len %d too large to fit in bsm\n", - (int)boot_size); - rc = -EINVAL; + IWL_DEBUG_INFO("uCode boot instr len %d too large to fit in\n", + boot_size); + ret = -EINVAL; goto err_release; } @@ -5865,56 +5869,45 @@ static int iwl3945_read_ucode(struct iwl3945_priv *priv) * 1) unmodified from disk * 2) backup cache for save/restore during power-downs */ priv->ucode_code.len = inst_size; - priv->ucode_code.v_addr = - pci_alloc_consistent(priv->pci_dev, - priv->ucode_code.len, - &(priv->ucode_code.p_addr)); + iwl3945_alloc_fw_desc(priv->pci_dev, &priv->ucode_code); priv->ucode_data.len = data_size; - priv->ucode_data.v_addr = - pci_alloc_consistent(priv->pci_dev, - priv->ucode_data.len, - &(priv->ucode_data.p_addr)); + iwl3945_alloc_fw_desc(priv->pci_dev, &priv->ucode_data); priv->ucode_data_backup.len = data_size; - priv->ucode_data_backup.v_addr = - pci_alloc_consistent(priv->pci_dev, - priv->ucode_data_backup.len, - &(priv->ucode_data_backup.p_addr)); + iwl3945_alloc_fw_desc(priv->pci_dev, &priv->ucode_data_backup); + if (!priv->ucode_code.v_addr || !priv->ucode_data.v_addr || + !priv->ucode_data_backup.v_addr) + goto err_pci_alloc; /* Initialization instructions and data */ - priv->ucode_init.len = init_size; - priv->ucode_init.v_addr = - pci_alloc_consistent(priv->pci_dev, - priv->ucode_init.len, - &(priv->ucode_init.p_addr)); - - priv->ucode_init_data.len = init_data_size; - priv->ucode_init_data.v_addr = - pci_alloc_consistent(priv->pci_dev, - priv->ucode_init_data.len, - &(priv->ucode_init_data.p_addr)); + if (init_size && init_data_size) { + priv->ucode_init.len = init_size; + iwl3945_alloc_fw_desc(priv->pci_dev, &priv->ucode_init); + + priv->ucode_init_data.len = init_data_size; + iwl3945_alloc_fw_desc(priv->pci_dev, &priv->ucode_init_data); + + if (!priv->ucode_init.v_addr || !priv->ucode_init_data.v_addr) + goto err_pci_alloc; + } /* Bootstrap (instructions only, no data) */ - priv->ucode_boot.len = boot_size; - priv->ucode_boot.v_addr = - pci_alloc_consistent(priv->pci_dev, - priv->ucode_boot.len, - &(priv->ucode_boot.p_addr)); + if (boot_size) { + priv->ucode_boot.len = boot_size; + iwl3945_alloc_fw_desc(priv->pci_dev, &priv->ucode_boot); - if (!priv->ucode_code.v_addr || !priv->ucode_data.v_addr || - !priv->ucode_init.v_addr || !priv->ucode_init_data.v_addr || - !priv->ucode_boot.v_addr || !priv->ucode_data_backup.v_addr) - goto err_pci_alloc; + if (!priv->ucode_boot.v_addr) + goto err_pci_alloc; + } /* Copy images into buffers for card's bus-master reads ... */ /* Runtime instructions (first block of data in file) */ src = &ucode->data[0]; len = priv->ucode_code.len; - IWL_DEBUG_INFO("Copying (but not loading) uCode instr len %d\n", - (int)len); + IWL_DEBUG_INFO("Copying (but not loading) uCode instr len %Zd\n", len); memcpy(priv->ucode_code.v_addr, src, len); IWL_DEBUG_INFO("uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n", priv->ucode_code.v_addr, (u32)priv->ucode_code.p_addr); @@ -5923,8 +5916,7 @@ static int iwl3945_read_ucode(struct iwl3945_priv *priv) * NOTE: Copy into backup buffer will be done in iwl3945_up() */ src = &ucode->data[inst_size]; len = priv->ucode_data.len; - IWL_DEBUG_INFO("Copying (but not loading) uCode data len %d\n", - (int)len); + IWL_DEBUG_INFO("Copying (but not loading) uCode data len %Zd\n", len); memcpy(priv->ucode_data.v_addr, src, len); memcpy(priv->ucode_data_backup.v_addr, src, len); @@ -5932,8 +5924,8 @@ static int iwl3945_read_ucode(struct iwl3945_priv *priv) if (init_size) { src = &ucode->data[inst_size + data_size]; len = priv->ucode_init.len; - IWL_DEBUG_INFO("Copying (but not loading) init instr len %d\n", - (int)len); + IWL_DEBUG_INFO("Copying (but not loading) init instr len %Zd\n", + len); memcpy(priv->ucode_init.v_addr, src, len); } @@ -5959,14 +5951,14 @@ static int iwl3945_read_ucode(struct iwl3945_priv *priv) err_pci_alloc: IWL_ERROR("failed to allocate pci memory\n"); - rc = -ENOMEM; + ret = -ENOMEM; iwl3945_dealloc_ucode_pci(priv); err_release: release_firmware(ucode_raw); error: - return rc; + return ret; } diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index df011ea..04aadfb 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -6140,6 +6140,12 @@ static void iwl4965_nic_start(struct iwl4965_priv *priv) iwl4965_write32(priv, CSR_RESET, 0); } +static int iwl4965_alloc_fw_desc(struct pci_dev *pci_dev, struct fw_desc *desc) +{ + desc->v_addr = pci_alloc_consistent(pci_dev, desc->len, &desc->p_addr); + return (desc->v_addr != NULL) ? 0 : -ENOMEM; +} + /** * iwl4965_read_ucode - Read uCode images from disk file. * @@ -6148,7 +6154,7 @@ static void iwl4965_nic_start(struct iwl4965_priv *priv) static int iwl4965_read_ucode(struct iwl4965_priv *priv) { struct iwl4965_ucode *ucode; - int rc = 0; + int ret; const struct firmware *ucode_raw; const char *name = "iwlwifi-4965" IWL4965_UCODE_API ".ucode"; u8 *src; @@ -6157,9 +6163,10 @@ static int iwl4965_read_ucode(struct iwl4965_priv *priv) /* Ask kernel firmware_class module to get the boot firmware off disk. * request_firmware() is synchronous, file is in memory on return. */ - rc = request_firmware(&ucode_raw, name, &priv->pci_dev->dev); - if (rc < 0) { - IWL_ERROR("%s firmware file req failed: Reason %d\n", name, rc); + ret = request_firmware(&ucode_raw, name, &priv->pci_dev->dev); + if (ret < 0) { + IWL_ERROR("%s firmware file req failed: Reason %d\n", + name, ret); goto error; } @@ -6169,7 +6176,7 @@ static int iwl4965_read_ucode(struct iwl4965_priv *priv) /* Make sure that we got at least our header! */ if (ucode_raw->size < sizeof(*ucode)) { IWL_ERROR("File size way too small!\n"); - rc = -EINVAL; + ret = -EINVAL; goto err_release; } @@ -6202,43 +6209,43 @@ static int iwl4965_read_ucode(struct iwl4965_priv *priv) IWL_DEBUG_INFO("uCode file size %d too small\n", (int)ucode_raw->size); - rc = -EINVAL; + ret = -EINVAL; goto err_release; } /* Verify that uCode images will fit in card's SRAM */ if (inst_size > IWL_MAX_INST_SIZE) { - IWL_DEBUG_INFO("uCode instr len %d too large to fit in card\n", - (int)inst_size); - rc = -EINVAL; + IWL_DEBUG_INFO("uCode instr len %d too large to fit in\n", + inst_size); + ret = -EINVAL; goto err_release; } if (data_size > IWL_MAX_DATA_SIZE) { - IWL_DEBUG_INFO("uCode data len %d too large to fit in card\n", - (int)data_size); - rc = -EINVAL; + IWL_DEBUG_INFO("uCode data len %d too large to fit in\n", + data_size); + ret = -EINVAL; goto err_release; } if (init_size > IWL_MAX_INST_SIZE) { IWL_DEBUG_INFO - ("uCode init instr len %d too large to fit in card\n", - (int)init_size); - rc = -EINVAL; + ("uCode init instr len %d too large to fit in\n", + init_size); + ret = -EINVAL; goto err_release; } if (init_data_size > IWL_MAX_DATA_SIZE) { IWL_DEBUG_INFO - ("uCode init data len %d too large to fit in card\n", - (int)init_data_size); - rc = -EINVAL; + ("uCode init data len %d too large to fit in\n", + init_data_size); + ret = -EINVAL; goto err_release; } if (boot_size > IWL_MAX_BSM_SIZE) { IWL_DEBUG_INFO - ("uCode boot instr len %d too large to fit in bsm\n", - (int)boot_size); - rc = -EINVAL; + ("uCode boot instr len %d too large to fit in\n", + boot_size); + ret = -EINVAL; goto err_release; } @@ -6248,56 +6255,41 @@ static int iwl4965_read_ucode(struct iwl4965_priv *priv) * 1) unmodified from disk * 2) backup cache for save/restore during power-downs */ priv->ucode_code.len = inst_size; - priv->ucode_code.v_addr = - pci_alloc_consistent(priv->pci_dev, - priv->ucode_code.len, - &(priv->ucode_code.p_addr)); + iwl4965_alloc_fw_desc(priv->pci_dev, &priv->ucode_code); priv->ucode_data.len = data_size; - priv->ucode_data.v_addr = - pci_alloc_consistent(priv->pci_dev, - priv->ucode_data.len, - &(priv->ucode_data.p_addr)); + iwl4965_alloc_fw_desc(priv->pci_dev, &priv->ucode_data); priv->ucode_data_backup.len = data_size; - priv->ucode_data_backup.v_addr = - pci_alloc_consistent(priv->pci_dev, - priv->ucode_data_backup.len, - &(priv->ucode_data_backup.p_addr)); - + iwl4965_alloc_fw_desc(priv->pci_dev, &priv->ucode_data_backup); /* Initialization instructions and data */ - priv->ucode_init.len = init_size; - priv->ucode_init.v_addr = - pci_alloc_consistent(priv->pci_dev, - priv->ucode_init.len, - &(priv->ucode_init.p_addr)); - - priv->ucode_init_data.len = init_data_size; - priv->ucode_init_data.v_addr = - pci_alloc_consistent(priv->pci_dev, - priv->ucode_init_data.len, - &(priv->ucode_init_data.p_addr)); + if (init_size && init_data_size) { + priv->ucode_init.len = init_size; + iwl4965_alloc_fw_desc(priv->pci_dev, &priv->ucode_init); + + priv->ucode_init_data.len = init_data_size; + iwl4965_alloc_fw_desc(priv->pci_dev, &priv->ucode_init_data); + + if (!priv->ucode_init.v_addr || !priv->ucode_init_data.v_addr) + goto err_pci_alloc; + } /* Bootstrap (instructions only, no data) */ - priv->ucode_boot.len = boot_size; - priv->ucode_boot.v_addr = - pci_alloc_consistent(priv->pci_dev, - priv->ucode_boot.len, - &(priv->ucode_boot.p_addr)); + if (boot_size) { + priv->ucode_boot.len = boot_size; + iwl4965_alloc_fw_desc(priv->pci_dev, &priv->ucode_boot); - if (!priv->ucode_code.v_addr || !priv->ucode_data.v_addr || - !priv->ucode_init.v_addr || !priv->ucode_init_data.v_addr || - !priv->ucode_boot.v_addr || !priv->ucode_data_backup.v_addr) - goto err_pci_alloc; + if (!priv->ucode_boot.v_addr) + goto err_pci_alloc; + } /* Copy images into buffers for card's bus-master reads ... */ /* Runtime instructions (first block of data in file) */ src = &ucode->data[0]; len = priv->ucode_code.len; - IWL_DEBUG_INFO("Copying (but not loading) uCode instr len %d\n", - (int)len); + IWL_DEBUG_INFO("Copying (but not loading) uCode instr len %Zd\n", len); memcpy(priv->ucode_code.v_addr, src, len); IWL_DEBUG_INFO("uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n", priv->ucode_code.v_addr, (u32)priv->ucode_code.p_addr); @@ -6306,8 +6298,7 @@ static int iwl4965_read_ucode(struct iwl4965_priv *priv) * NOTE: Copy into backup buffer will be done in iwl4965_up() */ src = &ucode->data[inst_size]; len = priv->ucode_data.len; - IWL_DEBUG_INFO("Copying (but not loading) uCode data len %d\n", - (int)len); + IWL_DEBUG_INFO("Copying (but not loading) uCode data len %Zd\n", len); memcpy(priv->ucode_data.v_addr, src, len); memcpy(priv->ucode_data_backup.v_addr, src, len); @@ -6315,8 +6306,8 @@ static int iwl4965_read_ucode(struct iwl4965_priv *priv) if (init_size) { src = &ucode->data[inst_size + data_size]; len = priv->ucode_init.len; - IWL_DEBUG_INFO("Copying (but not loading) init instr len %d\n", - (int)len); + IWL_DEBUG_INFO("Copying (but not loading) init instr len %Zd\n", + len); memcpy(priv->ucode_init.v_addr, src, len); } @@ -6324,16 +6315,15 @@ static int iwl4965_read_ucode(struct iwl4965_priv *priv) if (init_data_size) { src = &ucode->data[inst_size + data_size + init_size]; len = priv->ucode_init_data.len; - IWL_DEBUG_INFO("Copying (but not loading) init data len %d\n", - (int)len); + IWL_DEBUG_INFO("Copying (but not loading) init data len %Zd\n", + len); memcpy(priv->ucode_init_data.v_addr, src, len); } /* Bootstrap instructions (5th block) */ src = &ucode->data[inst_size + data_size + init_size + init_data_size]; len = priv->ucode_boot.len; - IWL_DEBUG_INFO("Copying (but not loading) boot instr len %d\n", - (int)len); + IWL_DEBUG_INFO("Copying (but not loading) boot instr len %Zd\n", len); memcpy(priv->ucode_boot.v_addr, src, len); /* We have our copies now, allow OS release its copies */ @@ -6342,14 +6332,14 @@ static int iwl4965_read_ucode(struct iwl4965_priv *priv) err_pci_alloc: IWL_ERROR("failed to allocate pci memory\n"); - rc = -ENOMEM; + ret = -ENOMEM; iwl4965_dealloc_ucode_pci(priv); err_release: release_firmware(ucode_raw); error: - return rc; + return ret; } -- 1.5.3.6 ^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 02/36] iwlwifi: continue namespace changes - fix CONFIG variables 2007-11-29 3:09 ` [PATCH 01/36] iwlwifi: Support for uCode without init and bsm section Zhu Yi @ 2007-11-29 3:09 ` Zhu Yi 2007-11-29 3:09 ` [PATCH 03/36] iwl3945: re-align 3945 event log data Zhu Yi 0 siblings, 1 reply; 36+ messages in thread From: Zhu Yi @ 2007-11-29 3:09 UTC (permalink / raw) To: linville; +Cc: linux-wireless, Reinette Chatre From: Reinette Chatre <reinette.chatre@intel.com> - Remove HT code from iwl-3945.h - it is not needed here as 3945 does not support HT. The code ended up here during the header file split. - Modify a few places where the CONFIG variables were named incorrectly: all changes are to comments only. Signed-off-by: Reinette Chatre <reinette.chatre@intel.com> --- drivers/net/wireless/iwlwifi/iwl-3945.h | 25 ------------------------- drivers/net/wireless/iwlwifi/iwl-4965.c | 2 +- drivers/net/wireless/iwlwifi/iwl3945-base.c | 2 +- drivers/net/wireless/iwlwifi/iwl4965-base.c | 2 +- 4 files changed, 3 insertions(+), 28 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index e5b345d..02040ef 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -445,31 +445,6 @@ union iwl3945_ht_rate_supp { }; }; -#ifdef CONFIG_IWL3945_HT -#define CFG_HT_RX_AMPDU_FACTOR_DEF (0x3) -#define HT_IE_MAX_AMSDU_SIZE_4K (0) -#define CFG_HT_MPDU_DENSITY_2USEC (0x5) -#define CFG_HT_MPDU_DENSITY_DEF CFG_HT_MPDU_DENSITY_2USEC - -struct sta_ht_info { - u8 is_ht; - u16 rx_mimo_ps_mode; - u16 tx_mimo_ps_mode; - u16 control_channel; - u8 max_amsdu_size; - u8 ampdu_factor; - u8 mpdu_density; - u8 operating_mode; - u8 supported_chan_width; - u8 extension_chan_offset; - u8 is_green_field; - u8 sgf; - u8 supp_rates[16]; - u8 tx_chan_width; - u8 chan_width_cap; -}; -#endif /*CONFIG_IWL3945_HT */ - #ifdef CONFIG_IWL3945_QOS union iwl3945_qos_capabity { diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 9b8560d..5dee8e5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -4667,7 +4667,7 @@ void iwl4965_hw_setup_deferred_work(struct iwl4965_priv *priv) #ifdef CONFIG_IWL4965_HT #ifdef CONFIG_IWL4965_HT_AGG INIT_WORK(&priv->agg_work, iwl4965_bg_agg_work); -#endif /* CONFIG_IWL4965_AGG */ +#endif /* CONFIG_IWL4965_HT_AGG */ #endif /* CONFIG_IWL4965_HT */ init_timer(&priv->statistics_periodic); priv->statistics_periodic.data = (unsigned long)priv; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index f93cd1d..7012aed 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -7347,7 +7347,7 @@ static int iwl3945_mac_conf_tx(struct ieee80211_hw *hw, int queue, #ifdef CONFIG_IWL3945_QOS unsigned long flags; int q; -#endif /* CONFIG_IWL_QOS */ +#endif /* CONFIG_IWL3945_QOS */ IWL_DEBUG_MAC80211("enter\n"); diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 04aadfb..6dd6c7d 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -7781,7 +7781,7 @@ static int iwl4965_mac_conf_tx(struct ieee80211_hw *hw, int queue, #ifdef CONFIG_IWL4965_QOS unsigned long flags; int q; -#endif /* CONFIG_IWL_QOS */ +#endif /* CONFIG_IWL4965_QOS */ IWL_DEBUG_MAC80211("enter\n"); -- 1.5.3.6 ^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 03/36] iwl3945: re-align 3945 event log data 2007-11-29 3:09 ` [PATCH 02/36] iwlwifi: continue namespace changes - fix CONFIG variables Zhu Yi @ 2007-11-29 3:09 ` Zhu Yi 2007-11-29 3:09 ` [PATCH 04/36] iwl4965: add comments to rate scaling code Zhu Yi 0 siblings, 1 reply; 36+ messages in thread From: Zhu Yi @ 2007-11-29 3:09 UTC (permalink / raw) To: linville; +Cc: linux-wireless, Ben Cahill, Zhu Yi From: Ben Cahill <ben.m.cahill@intel.com> Re-align 3945 event log data. Signed-off-by: Ben Cahill <ben.m.cahill@intel.com> Signed-off-by: Zhu Yi <yi.zhu@intel.com> --- drivers/net/wireless/iwlwifi/iwl3945-base.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 7012aed..496ca14 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -4490,7 +4490,7 @@ static void iwl3945_dump_nic_error_log(struct iwl3945_priv *priv) } -#define EVENT_START_OFFSET (4 * sizeof(u32)) +#define EVENT_START_OFFSET (6 * sizeof(u32)) /** * iwl3945_print_event_log - Dump error event log to syslog -- 1.5.3.6 ^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 04/36] iwl4965: add comments to rate scaling code 2007-11-29 3:09 ` [PATCH 03/36] iwl3945: re-align 3945 event log data Zhu Yi @ 2007-11-29 3:09 ` Zhu Yi 2007-11-29 3:09 ` [PATCH 05/36] iwlwifi: add comments to EEPROM stuff Zhu Yi 0 siblings, 1 reply; 36+ messages in thread From: Zhu Yi @ 2007-11-29 3:09 UTC (permalink / raw) To: linville; +Cc: linux-wireless, Ben Cahill, Zhu Yi From: Ben Cahill <ben.m.cahill@intel.com> Add comments to rate scaling code. Signed-off-by: Ben Cahill <ben.m.cahill@intel.com> Signed-off-by: Zhu Yi <yi.zhu@intel.com> --- drivers/net/wireless/iwlwifi/iwl-4965-rs.c | 467 +++++++++++++++++++++++---- drivers/net/wireless/iwlwifi/iwl-4965-rs.h | 45 ++- drivers/net/wireless/iwlwifi/iwl-4965.h | 2 +- drivers/net/wireless/iwlwifi/iwl4965-base.c | 3 + 4 files changed, 442 insertions(+), 75 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c index 4b6aa96..eb918a7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c @@ -47,13 +47,12 @@ #define IWL_NUMBER_TRY 1 #define IWL_HT_NUMBER_TRY 3 -#define IWL_RATE_MAX_WINDOW 62 -#define IWL_RATE_HIGH_TH 10880 -#define IWL_RATE_MIN_FAILURE_TH 6 -#define IWL_RATE_MIN_SUCCESS_TH 8 -#define IWL_RATE_DECREASE_TH 1920 -#define IWL_RATE_INCREASE_TH 8960 -#define IWL_RATE_SCALE_FLUSH_INTVL (2*HZ) /*2 seconds */ +#define IWL_RATE_MAX_WINDOW 62 /* # tx in history window */ +#define IWL_RATE_MIN_FAILURE_TH 6 /* min failures to calc tpt */ +#define IWL_RATE_MIN_SUCCESS_TH 8 /* min successes to calc tpt */ + +/* max time to accum history 2 seconds */ +#define IWL_RATE_SCALE_FLUSH_INTVL (2*HZ) static u8 rs_ht_to_legacy[] = { IWL_RATE_6M_INDEX, IWL_RATE_6M_INDEX, @@ -69,54 +68,74 @@ struct iwl4965_rate { u32 rate_n_flags; } __attribute__ ((packed)); +/** + * struct iwl4965_rate_scale_data -- tx success history for one rate + */ struct iwl4965_rate_scale_data { - u64 data; - s32 success_counter; - s32 success_ratio; - s32 counter; - s32 average_tpt; + u64 data; /* bitmap of successful frames */ + s32 success_counter; /* number of frames successful */ + s32 success_ratio; /* per-cent * 128 */ + s32 counter; /* number of frames attempted */ + s32 average_tpt; /* success ratio * expected throughput */ unsigned long stamp; }; +/** + * struct iwl4965_scale_tbl_info -- tx params and success history for all rates + * + * There are two of these in struct iwl_rate_scale_priv, + * one for "active", and one for "search". + */ struct iwl4965_scale_tbl_info { enum iwl4965_table_type lq_type; enum iwl4965_antenna_type antenna_type; - u8 is_SGI; - u8 is_fat; - u8 is_dup; - u8 action; - s32 *expected_tpt; - struct iwl4965_rate current_rate; - struct iwl4965_rate_scale_data win[IWL_RATE_COUNT]; + u8 is_SGI; /* 1 = short guard interval */ + u8 is_fat; /* 1 = 40 MHz channel width */ + u8 is_dup; /* 1 = duplicated data streams */ + u8 action; /* change modulation; IWL_[LEGACY/SISO/MIMO]_SWITCH_* */ + s32 *expected_tpt; /* throughput metrics; expected_tpt_G, etc. */ + struct iwl4965_rate current_rate; /* rate_n_flags, uCode API format */ + struct iwl4965_rate_scale_data win[IWL_RATE_COUNT]; /* rate histories */ }; +/** + * struct iwl_rate_scale_priv -- driver's rate scaling private structure + * + * Pointer to this gets passed back and forth between driver and mac80211. + */ struct iwl4965_rate_scale_priv { - u8 active_tbl; - u8 enable_counter; - u8 stay_in_tbl; - u8 search_better_tbl; + u8 active_tbl; /* index of active table, range 0-1 */ + u8 enable_counter; /* indicates HT mode */ + u8 stay_in_tbl; /* 1: disallow, 0: allow search for new mode */ + u8 search_better_tbl; /* 1: currently trying alternate mode */ s32 last_tpt; + + /* The following determine when to search for a new mode */ u32 table_count_limit; - u32 max_failure_limit; - u32 max_success_limit; + u32 max_failure_limit; /* # failed frames before new search */ + u32 max_success_limit; /* # successful frames before new search */ u32 table_count; - u32 total_failed; - u32 total_success; - u32 flush_timer; - u8 action_counter; + u32 total_failed; /* total failed frames, any/all rates */ + u32 total_success; /* total successful frames, any/all rates */ + u32 flush_timer; /* time staying in mode before new search */ + + u8 action_counter; /* # mode-switch actions tried */ u8 antenna; u8 valid_antenna; u8 is_green; u8 is_dup; u8 phymode; u8 ibss_sta_added; + + /* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */ u32 supp_rates; u16 active_rate; u16 active_siso_rate; u16 active_mimo_rate; u16 active_rate_basic; + struct iwl4965_link_quality_cmd lq; - struct iwl4965_scale_tbl_info lq_info[LQ_SIZE]; + struct iwl4965_scale_tbl_info lq_info[LQ_SIZE]; /* "active", "search" */ #ifdef CONFIG_MAC80211_DEBUGFS struct dentry *rs_sta_dbgfs_scale_table_file; struct dentry *rs_sta_dbgfs_stats_table_file; @@ -142,6 +161,12 @@ static void rs_dbgfs_set_mcs(struct iwl4965_rate_scale_priv *rs_priv, struct iwl4965_rate *mcs, int index) {} #endif + +/* + * Expected throughput metrics for following rates: + * 1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 60 MBits + * "G" is the only table that supports CCK (the first 4 rates). + */ static s32 expected_tpt_A[IWL_RATE_COUNT] = { 0, 0, 0, 0, 40, 57, 72, 98, 121, 154, 177, 186, 186 }; @@ -244,6 +269,13 @@ static void rs_rate_scale_clear_window(struct iwl4965_rate_scale_data *window) window->stamp = 0; } +/** + * rs_collect_tx_data - Update the success/failure sliding window + * + * We keep a sliding window of the last 62 packets transmitted + * at this rate. window->data contains the bitmask of successful + * packets. + */ static int rs_collect_tx_data(struct iwl4965_rate_scale_data *windows, int scale_index, s32 tpt, u32 status) { @@ -255,10 +287,18 @@ static int rs_collect_tx_data(struct iwl4965_rate_scale_data *windows, if (scale_index < 0 || scale_index >= IWL_RATE_COUNT) return -EINVAL; + /* Select data for current tx bit rate */ window = &(windows[scale_index]); + /* + * Keep track of only the latest 62 tx frame attempts in this rate's + * history window; anything older isn't really relevant any more. + * If we have filled up the sliding window, drop the oldest attempt; + * if the oldest attempt (highest bit in bitmap) shows "success", + * subtract "1" from the success counter (this is the main reason + * we keep these bitmaps!). + */ if (window->counter >= win_size) { - window->counter = win_size - 1; mask = 1; mask = (mask << (win_size - 1)); @@ -268,7 +308,11 @@ static int rs_collect_tx_data(struct iwl4965_rate_scale_data *windows, } } + /* Increment frames-attempted counter */ window->counter = window->counter + 1; + + /* Shift bitmap by one frame (throw away oldest history), + * OR in "1", and increment "success" if this frame was successful. */ mask = window->data; window->data = (mask << 1); if (status != 0) { @@ -276,6 +320,7 @@ static int rs_collect_tx_data(struct iwl4965_rate_scale_data *windows, window->data |= 0x1; } + /* Calculate current success ratio, avoid divide-by-0! */ if (window->counter > 0) window->success_ratio = 128 * (100 * window->success_counter) / window->counter; @@ -284,17 +329,22 @@ static int rs_collect_tx_data(struct iwl4965_rate_scale_data *windows, fail_count = window->counter - window->success_counter; + /* Calculate average throughput, if we have enough history. */ if ((fail_count >= IWL_RATE_MIN_FAILURE_TH) || (window->success_counter >= IWL_RATE_MIN_SUCCESS_TH)) window->average_tpt = (window->success_ratio * tpt + 64) / 128; else window->average_tpt = IWL_INVALID_VALUE; + /* Tag this window as having been updated */ window->stamp = jiffies; return 0; } +/* + * Fill uCode API rate_n_flags field, based on "search" or "active" table. + */ static void rs_mcs_from_tbl(struct iwl4965_rate *mcs_rate, struct iwl4965_scale_tbl_info *tbl, int index, u8 use_green) @@ -349,6 +399,10 @@ static void rs_mcs_from_tbl(struct iwl4965_rate *mcs_rate, } } +/* + * Interpret uCode API's rate_n_flags format, + * fill "search" or "active" tx mode table. + */ static int rs_get_tbl_info_from_mcs(const struct iwl4965_rate *mcs_rate, int phymode, struct iwl4965_scale_tbl_info *tbl, int *rate_idx) @@ -362,11 +416,12 @@ static int rs_get_tbl_info_from_mcs(const struct iwl4965_rate *mcs_rate, *rate_idx = -1; return -EINVAL; } - tbl->is_SGI = 0; + tbl->is_SGI = 0; /* default legacy setup */ tbl->is_fat = 0; tbl->is_dup = 0; - tbl->antenna_type = ANT_BOTH; + tbl->antenna_type = ANT_BOTH; /* default MIMO setup */ + /* legacy rate format */ if (!(mcs_rate->rate_n_flags & RATE_MCS_HT_MSK)) { ant_msk = (mcs_rate->rate_n_flags & RATE_MCS_ANT_AB_MSK); @@ -386,6 +441,7 @@ static int rs_get_tbl_info_from_mcs(const struct iwl4965_rate *mcs_rate, } *rate_idx = index; + /* HT rate format, SISO (might be 20 MHz legacy or 40 MHz fat width) */ } else if (iwl4965_rate_get_rate(mcs_rate->rate_n_flags) <= IWL_RATE_SISO_60M_PLCP) { tbl->lq_type = LQ_SISO; @@ -410,6 +466,8 @@ static int rs_get_tbl_info_from_mcs(const struct iwl4965_rate *mcs_rate, tbl->is_dup = 1; *rate_idx = index; + + /* HT rate format, MIMO (might be 20 MHz legacy or 40 MHz fat width) */ } else { tbl->lq_type = LQ_MIMO; if (mcs_rate->rate_n_flags & RATE_MCS_SGI_MSK) @@ -564,8 +622,9 @@ static void rs_get_lower_rate(struct iwl4965_rate_scale_priv *lq_data, rs_get_supported_rates(lq_data, NULL, tbl->lq_type, &rate_mask); - /* mask with station rate restriction */ + /* Mask with station rate restriction */ if (is_legacy(tbl->lq_type)) { + /* supp_rates has no CCK bits in A mode */ if (lq_data->phymode == (u8) MODE_IEEE80211A) rate_mask = (u16)(rate_mask & (lq_data->supp_rates << IWL_FIRST_OFDM_RATE)); @@ -573,7 +632,7 @@ static void rs_get_lower_rate(struct iwl4965_rate_scale_priv *lq_data, rate_mask = (u16)(rate_mask & lq_data->supp_rates); } - /* if we did switched from HT to legacy check current rate */ + /* If we switched from HT to legacy, check current rate */ if (switch_to_legacy && (rate_mask & (1 << scale_index))) { rs_mcs_from_tbl(mcs_rate, tbl, scale_index, is_green); return; @@ -588,6 +647,9 @@ static void rs_get_lower_rate(struct iwl4965_rate_scale_priv *lq_data, rs_mcs_from_tbl(mcs_rate, tbl, scale_index, is_green); } +/* + * mac80211 sends us Tx status + */ static void rs_tx_status(void *priv_rate, struct net_device *dev, struct sk_buff *skb, @@ -641,11 +703,14 @@ static void rs_tx_status(void *priv_rate, table = &lq->lq; active_index = lq->active_tbl; + /* Get mac80211 antenna info */ lq->antenna = (lq->valid_antenna & local->hw.conf.antenna_sel_tx); if (!lq->antenna) lq->antenna = lq->valid_antenna; + /* Ignore mac80211 antenna info for now */ lq->antenna = lq->valid_antenna; + curr_tbl = &(lq->lq_info[active_index]); search_tbl = &(lq->lq_info[(1 - active_index)]); window = (struct iwl4965_rate_scale_data *) @@ -664,6 +729,14 @@ static void rs_tx_status(void *priv_rate, return; } + /* + * Ignore this Tx frame response if its initial rate doesn't match + * that of latest Link Quality command. There may be stragglers + * from a previous Link Quality command, but we're no longer interested + * in those; they're either from the "active" mode while we're trying + * to check "search" mode, or a prior "search" mode after we've moved + * to a new "search" mode (which might become the new "active" mode). + */ if (retries && (tx_mcs.rate_n_flags != le32_to_cpu(table->rs_table[0].rate_n_flags))) { @@ -674,12 +747,17 @@ static void rs_tx_status(void *priv_rate, return; } + /* Update frame history window with "failure" for each Tx retry. */ while (retries) { + /* Look up the rate and other info used for each tx attempt. + * Each tx attempt steps one entry deeper in the rate table. */ tx_mcs.rate_n_flags = le32_to_cpu(table->rs_table[index].rate_n_flags); rs_get_tbl_info_from_mcs(&tx_mcs, priv->phymode, &tbl_type, &rs_index); + /* If type matches "search" table, + * add failure to "search" history */ if ((tbl_type.lq_type == search_tbl->lq_type) && (tbl_type.antenna_type == search_tbl->antenna_type) && (tbl_type.is_SGI == search_tbl->is_SGI)) { @@ -687,8 +765,10 @@ static void rs_tx_status(void *priv_rate, tpt = search_tbl->expected_tpt[rs_index]; else tpt = 0; - rs_collect_tx_data(search_win, - rs_index, tpt, 0); + rs_collect_tx_data(search_win, rs_index, tpt, 0); + + /* Else if type matches "current/active" table, + * add failure to "current/active" history */ } else if ((tbl_type.lq_type == curr_tbl->lq_type) && (tbl_type.antenna_type == curr_tbl->antenna_type) && (tbl_type.is_SGI == curr_tbl->is_SGI)) { @@ -698,6 +778,9 @@ static void rs_tx_status(void *priv_rate, tpt = 0; rs_collect_tx_data(window, rs_index, tpt, 0); } + + /* If not searching for a new mode, increment failed counter + * ... this helps determine when to start searching again */ if (lq->stay_in_tbl) lq->total_failed++; --retries; @@ -705,6 +788,11 @@ static void rs_tx_status(void *priv_rate, } + /* + * Find (by rate) the history window to update with final Tx attempt; + * if Tx was successful first try, use original rate, + * else look up the rate that was, finally, successful. + */ if (!tx_resp->retry_count) tx_mcs.rate_n_flags = tx_resp->control.tx_rate; else @@ -714,11 +802,14 @@ static void rs_tx_status(void *priv_rate, rs_get_tbl_info_from_mcs(&tx_mcs, priv->phymode, &tbl_type, &rs_index); + /* Update frame history window with "success" if Tx got ACKed ... */ if (tx_resp->flags & IEEE80211_TX_STATUS_ACK) status = 1; else status = 0; + /* If type matches "search" table, + * add final tx status to "search" history */ if ((tbl_type.lq_type == search_tbl->lq_type) && (tbl_type.antenna_type == search_tbl->antenna_type) && (tbl_type.is_SGI == search_tbl->is_SGI)) { @@ -728,6 +819,9 @@ static void rs_tx_status(void *priv_rate, tpt = 0; rs_collect_tx_data(search_win, rs_index, tpt, status); + + /* Else if type matches "current/active" table, + * add final tx status to "current/active" history */ } else if ((tbl_type.lq_type == curr_tbl->lq_type) && (tbl_type.antenna_type == curr_tbl->antenna_type) && (tbl_type.is_SGI == curr_tbl->is_SGI)) { @@ -738,6 +832,8 @@ static void rs_tx_status(void *priv_rate, rs_collect_tx_data(window, rs_index, tpt, status); } + /* If not searching for new mode, increment success/failed counter + * ... these help determine when to start searching again */ if (lq->stay_in_tbl) { if (status) lq->total_success++; @@ -745,6 +841,7 @@ static void rs_tx_status(void *priv_rate, lq->total_failed++; } + /* See if there's a better rate or modulation mode to try. */ rs_rate_scale_perform(priv, dev, hdr, sta); sta_info_put(sta); return; @@ -774,11 +871,19 @@ static u8 rs_is_other_ant_connected(u8 valid_antenna, return 0; } +/* + * Begin a period of staying with a selected modulation mode. + * Set "stay_in_tbl" flag to prevent any mode switches. + * Set frame tx success limits according to legacy vs. high-throughput, + * and reset overall (spanning all rates) tx success history statistics. + * These control how long we stay using same modulation mode before + * searching for a new mode. + */ static void rs_set_stay_in_table(u8 is_legacy, struct iwl4965_rate_scale_priv *lq_data) { IWL_DEBUG_HT("we are staying in the same table\n"); - lq_data->stay_in_tbl = 1; + lq_data->stay_in_tbl = 1; /* only place this gets set */ if (is_legacy) { lq_data->table_count_limit = IWL_LEGACY_TABLE_COUNT; lq_data->max_failure_limit = IWL_LEGACY_FAILURE_LIMIT; @@ -793,6 +898,9 @@ static void rs_set_stay_in_table(u8 is_legacy, lq_data->total_success = 0; } +/* + * Find correct throughput table for given mode of modulation + */ static void rs_get_expected_tpt_table(struct iwl4965_rate_scale_priv *lq_data, struct iwl4965_scale_tbl_info *tbl) { @@ -827,17 +935,33 @@ static void rs_get_expected_tpt_table(struct iwl4965_rate_scale_priv *lq_data, } #ifdef CONFIG_IWL4965_HT +/* + * Find starting rate for new "search" high-throughput mode of modulation. + * Goal is to find lowest expected rate (under perfect conditions) that is + * above the current measured throughput of "active" mode, to give new mode + * a fair chance to prove itself without too many challenges. + * + * This gets called when transitioning to more aggressive modulation + * (i.e. legacy to SISO or MIMO, or SISO to MIMO), as well as less aggressive + * (i.e. MIMO to SISO). When moving to MIMO, bit rate will typically need + * to decrease to match "active" throughput. When moving from MIMO to SISO, + * bit rate will typically need to increase, but not if performance was bad. + */ static s32 rs_get_best_rate(struct iwl4965_priv *priv, struct iwl4965_rate_scale_priv *lq_data, - struct iwl4965_scale_tbl_info *tbl, + struct iwl4965_scale_tbl_info *tbl, /* "search" */ u16 rate_mask, s8 index, s8 rate) { + /* "active" values */ struct iwl4965_scale_tbl_info *active_tbl = &(lq_data->lq_info[lq_data->active_tbl]); - s32 new_rate, high, low, start_hi; s32 active_sr = active_tbl->win[index].success_ratio; - s32 *tpt_tbl = tbl->expected_tpt; s32 active_tpt = active_tbl->expected_tpt[index]; + + /* expected "search" throughput */ + s32 *tpt_tbl = tbl->expected_tpt; + + s32 new_rate, high, low, start_hi; u16 high_low; new_rate = high = low = start_hi = IWL_RATE_INVALID; @@ -848,6 +972,21 @@ static s32 rs_get_best_rate(struct iwl4965_priv *priv, low = high_low & 0xff; high = (high_low >> 8) & 0xff; + /* + * Lower the "search" bit rate, to give new "search" mode + * approximately the same throughput as "active" if: + * + * 1) "Active" mode has been working modestly well (but not + * great), and expected "search" throughput (under perfect + * conditions) at candidate rate is above the actual + * measured "active" throughput (but less than expected + * "active" throughput under perfect conditions). + * OR + * 2) "Active" mode has been working perfectly or very well + * and expected "search" throughput (under perfect + * conditions) at candidate rate is above expected + * "active" throughput (under perfect conditions). + */ if ((((100 * tpt_tbl[rate]) > lq_data->last_tpt) && ((active_sr > IWL_RATE_DECREASE_TH) && (active_sr <= IWL_RATE_HIGH_TH) && @@ -855,21 +994,38 @@ static s32 rs_get_best_rate(struct iwl4965_priv *priv, ((active_sr >= IWL_RATE_SCALE_SWITCH) && (tpt_tbl[rate] > active_tpt))) { + /* (2nd or later pass) + * If we've already tried to raise the rate, and are + * now trying to lower it, use the higher rate. */ if (start_hi != IWL_RATE_INVALID) { new_rate = start_hi; break; } + new_rate = rate; + + /* Loop again with lower rate */ if (low != IWL_RATE_INVALID) rate = low; + + /* Lower rate not available, use the original */ else break; + + /* Else try to raise the "search" rate to match "active" */ } else { + /* (2nd or later pass) + * If we've already tried to lower the rate, and are + * now trying to raise it, use the lower rate. */ if (new_rate != IWL_RATE_INVALID) break; + + /* Loop again with higher rate */ else if (high != IWL_RATE_INVALID) { start_hi = high; rate = high; + + /* Higher rate not available, use the original */ } else { new_rate = rate; break; @@ -886,6 +1042,9 @@ static inline u8 rs_is_both_ant_supp(u8 valid_antenna) return (rs_is_ant_connected(valid_antenna, ANT_BOTH)); } +/* + * Set up search table for MIMO + */ static int rs_switch_to_mimo(struct iwl4965_priv *priv, struct iwl4965_rate_scale_priv *lq_data, struct iwl4965_scale_tbl_info *tbl, int index) @@ -906,6 +1065,7 @@ static int rs_switch_to_mimo(struct iwl4965_priv *priv, if (priv->current_assoc_ht.tx_mimo_ps_mode == IWL_MIMO_PS_STATIC) return -1; + /* Need both Tx chains/antennas to support MIMO */ if (!rs_is_both_ant_supp(lq_data->antenna)) return -1; @@ -943,6 +1103,9 @@ static int rs_switch_to_mimo(struct iwl4965_priv *priv, #endif /*CONFIG_IWL4965_HT */ } +/* + * Set up search table for SISO + */ static int rs_switch_to_siso(struct iwl4965_priv *priv, struct iwl4965_rate_scale_priv *lq_data, struct iwl4965_scale_tbl_info *tbl, int index) @@ -999,6 +1162,9 @@ static int rs_switch_to_siso(struct iwl4965_priv *priv, #endif /*CONFIG_IWL4965_HT */ } +/* + * Try to switch to new modulation mode from legacy + */ static int rs_move_legacy_other(struct iwl4965_priv *priv, struct iwl4965_rate_scale_priv *lq_data, int index) @@ -1020,12 +1186,17 @@ static int rs_move_legacy_other(struct iwl4965_priv *priv, search_tbl->lq_type = LQ_NONE; lq_data->action_counter++; + + /* Don't change antenna if success has been great */ if (window->success_ratio >= IWL_RS_GOOD_RATIO) break; + + /* Don't change antenna if other one is not connected */ if (!rs_is_other_ant_connected(lq_data->antenna, tbl->antenna_type)) break; + /* Set up search table to try other antenna */ memcpy(search_tbl, tbl, sz); rs_toggle_antenna(&(search_tbl->current_rate), @@ -1036,6 +1207,8 @@ static int rs_move_legacy_other(struct iwl4965_priv *priv, case IWL_LEGACY_SWITCH_SISO: IWL_DEBUG_HT("LQ: Legacy switch to SISO\n"); + + /* Set up search table to try SISO */ memcpy(search_tbl, tbl, sz); search_tbl->lq_type = LQ_SISO; search_tbl->is_SGI = 0; @@ -1051,6 +1224,8 @@ static int rs_move_legacy_other(struct iwl4965_priv *priv, break; case IWL_LEGACY_SWITCH_MIMO: IWL_DEBUG_HT("LQ: Legacy switch MIMO\n"); + + /* Set up search table to try MIMO */ memcpy(search_tbl, tbl, sz); search_tbl->lq_type = LQ_MIMO; search_tbl->is_SGI = 0; @@ -1083,6 +1258,9 @@ static int rs_move_legacy_other(struct iwl4965_priv *priv, } +/* + * Try to switch to new modulation mode from SISO + */ static int rs_move_siso_to_other(struct iwl4965_priv *priv, struct iwl4965_rate_scale_priv *lq_data, int index) @@ -1173,6 +1351,9 @@ static int rs_move_siso_to_other(struct iwl4965_priv *priv, return 0; } +/* + * Try to switch to new modulation mode from MIMO + */ static int rs_move_mimo_to_other(struct iwl4965_priv *priv, struct iwl4965_rate_scale_priv *lq_data, int index) @@ -1193,6 +1374,8 @@ static int rs_move_mimo_to_other(struct iwl4965_priv *priv, case IWL_MIMO_SWITCH_ANTENNA_A: case IWL_MIMO_SWITCH_ANTENNA_B: IWL_DEBUG_HT("LQ: MIMO SWITCH TO SISO\n"); + + /* Set up new search table for SISO */ memcpy(search_tbl, tbl, sz); search_tbl->lq_type = LQ_SISO; search_tbl->is_SGI = 0; @@ -1212,6 +1395,8 @@ static int rs_move_mimo_to_other(struct iwl4965_priv *priv, case IWL_MIMO_SWITCH_GI: IWL_DEBUG_HT("LQ: MIMO SWITCH TO GI\n"); + + /* Set up new search table for MIMO */ memcpy(search_tbl, tbl, sz); search_tbl->lq_type = LQ_MIMO; search_tbl->antenna_type = ANT_BOTH; @@ -1221,6 +1406,13 @@ static int rs_move_mimo_to_other(struct iwl4965_priv *priv, else search_tbl->is_SGI = 1; lq_data->search_better_tbl = 1; + + /* + * If active table already uses the fastest possible + * modulation (dual stream with short guard interval), + * and it's working well, there's no need to look + * for a better type of modulation! + */ if ((tbl->lq_type == LQ_MIMO) && (tbl->is_SGI)) { s32 tpt = lq_data->last_tpt / 100; @@ -1253,6 +1445,13 @@ static int rs_move_mimo_to_other(struct iwl4965_priv *priv, } +/* + * Check whether we should continue using same modulation mode, or + * begin search for a new mode, based on: + * 1) # tx successes or failures while using this mode + * 2) # times calling this function + * 3) elapsed time in this mode (not used, for now) + */ static void rs_stay_in_table(struct iwl4965_rate_scale_priv *lq_data) { struct iwl4965_scale_tbl_info *tbl; @@ -1264,15 +1463,27 @@ static void rs_stay_in_table(struct iwl4965_rate_scale_priv *lq_data) tbl = &(lq_data->lq_info[active_tbl]); + /* If we've been disallowing search, see if we should now allow it */ if (lq_data->stay_in_tbl) { + /* Elapsed time using current modulation mode */ if (lq_data->flush_timer) flush_interval_passed = time_after(jiffies, (unsigned long)(lq_data->flush_timer + IWL_RATE_SCALE_FLUSH_INTVL)); + /* For now, disable the elapsed time criterion */ flush_interval_passed = 0; + + /* + * Check if we should allow search for new modulation mode. + * If many frames have failed or succeeded, or we've used + * this same modulation for a long time, allow search, and + * reset history stats that keep track of whether we should + * allow a new search. Also (below) reset all bitmaps and + * stats in active history. + */ if ((lq_data->total_failed > lq_data->max_failure_limit) || (lq_data->total_success > lq_data->max_success_limit) || ((!lq_data->search_better_tbl) && (lq_data->flush_timer) @@ -1281,10 +1492,19 @@ static void rs_stay_in_table(struct iwl4965_rate_scale_priv *lq_data) lq_data->total_failed, lq_data->total_success, flush_interval_passed); - lq_data->stay_in_tbl = 0; + + /* Allow search for new mode */ + lq_data->stay_in_tbl = 0; /* only place reset */ lq_data->total_failed = 0; lq_data->total_success = 0; lq_data->flush_timer = 0; + + /* + * Else if we've used this modulation mode enough repetitions + * (regardless of elapsed time or success/failure), reset + * history bitmaps and rate-specific stats for all rates in + * active table. + */ } else { lq_data->table_count++; if (lq_data->table_count >= @@ -1298,6 +1518,9 @@ static void rs_stay_in_table(struct iwl4965_rate_scale_priv *lq_data) } } + /* If transitioning to allow "search", reset all history + * bitmaps and stats in active table (this will become the new + * "search" table). */ if (!lq_data->stay_in_tbl) { for (i = 0; i < IWL_RATE_COUNT; i++) rs_rate_scale_clear_window(&(tbl->win[i])); @@ -1305,6 +1528,9 @@ static void rs_stay_in_table(struct iwl4965_rate_scale_priv *lq_data) } } +/* + * Do rate scaling and search for new modulation mode. + */ static void rs_rate_scale_perform(struct iwl4965_priv *priv, struct net_device *dev, struct ieee80211_hdr *hdr, @@ -1350,6 +1576,11 @@ static void rs_rate_scale_perform(struct iwl4965_priv *priv, } lq_data = (struct iwl4965_rate_scale_priv *)sta->rate_ctrl_priv; + /* + * Select rate-scale / modulation-mode table to work with in + * the rest of this function: "search" if searching for better + * modulation mode, or "active" if doing rate scaling within a mode. + */ if (!lq_data->search_better_tbl) active_tbl = lq_data->active_tbl; else @@ -1358,11 +1589,13 @@ static void rs_rate_scale_perform(struct iwl4965_priv *priv, tbl = &(lq_data->lq_info[active_tbl]); is_green = lq_data->is_green; + /* current tx rate */ index = sta->last_txrate; IWL_DEBUG_RATE("Rate scale index %d for type %d\n", index, tbl->lq_type); + /* rates available for this association, and for modulation mode */ rs_get_supported_rates(lq_data, hdr, tbl->lq_type, &rate_mask); @@ -1371,6 +1604,7 @@ static void rs_rate_scale_perform(struct iwl4965_priv *priv, /* mask with station rate restriction */ if (is_legacy(tbl->lq_type)) { if (lq_data->phymode == (u8) MODE_IEEE80211A) + /* supp_rates has no CCK bits in A mode */ rate_scale_index_msk = (u16) (rate_mask & (lq_data->supp_rates << IWL_FIRST_OFDM_RATE)); else @@ -1383,11 +1617,13 @@ static void rs_rate_scale_perform(struct iwl4965_priv *priv, if (!rate_scale_index_msk) rate_scale_index_msk = rate_mask; + /* If current rate is no longer supported on current association, + * or user changed preferences for rates, find a new supported rate. */ if (index < 0 || !((1 << index) & rate_scale_index_msk)) { index = IWL_INVALID_VALUE; update_lq = 1; - /* get the lowest available rate */ + /* get the highest available rate */ for (i = 0; i <= IWL_RATE_COUNT; i++) { if ((1 << i) & rate_scale_index_msk) index = i; @@ -1399,11 +1635,19 @@ static void rs_rate_scale_perform(struct iwl4965_priv *priv, } } + /* Get expected throughput table and history window for current rate */ if (!tbl->expected_tpt) rs_get_expected_tpt_table(lq_data, tbl); window = &(tbl->win[index]); + /* + * If there is not enough history to calculate actual average + * throughput, keep analyzing results of more tx frames, without + * changing rate or mode (bypass most of the rest of this function). + * Set up new rate table in uCode only if old rate is not supported + * in current association (use new rate found above). + */ fail_count = window->counter - window->success_counter; if (((fail_count < IWL_RATE_MIN_FAILURE_TH) && (window->success_counter < IWL_RATE_MIN_SUCCESS_TH)) @@ -1411,8 +1655,15 @@ static void rs_rate_scale_perform(struct iwl4965_priv *priv, IWL_DEBUG_RATE("LQ: still below TH succ %d total %d " "for index %d\n", window->success_counter, window->counter, index); + + /* Can't calculate this yet; not enough history */ window->average_tpt = IWL_INVALID_VALUE; + + /* Should we stay with this modulation mode, + * or search for a new one? */ rs_stay_in_table(lq_data); + + /* Set up new rate table in uCode, if needed */ if (update_lq) { rs_mcs_from_tbl(&mcs_rate, tbl, index, is_green); rs_fill_link_cmd(lq_data, &mcs_rate, &lq_data->lq); @@ -1420,13 +1671,19 @@ static void rs_rate_scale_perform(struct iwl4965_priv *priv, } goto out; + /* Else we have enough samples; calculate estimate of + * actual average throughput */ } else window->average_tpt = ((window->success_ratio * tbl->expected_tpt[index] + 64) / 128); + /* If we are searching for better modulation mode, check success. */ if (lq_data->search_better_tbl) { int success_limit = IWL_RATE_SCALE_SWITCH; + /* If good success, continue using the "search" mode; + * no need to send new link quality command, since we're + * continuing to use the setup that we've been trying. */ if ((window->success_ratio > success_limit) || (window->average_tpt > lq_data->last_tpt)) { if (!is_legacy(tbl->lq_type)) { @@ -1438,55 +1695,78 @@ static void rs_rate_scale_perform(struct iwl4965_priv *priv, lq_data->last_tpt); lq_data->enable_counter = 1; } + /* Swap tables; "search" becomes "active" */ lq_data->active_tbl = active_tbl; current_tpt = window->average_tpt; + + /* Else poor success; go back to mode in "active" table */ } else { + /* Nullify "search" table */ tbl->lq_type = LQ_NONE; + + /* Revert to "active" table */ active_tbl = lq_data->active_tbl; tbl = &(lq_data->lq_info[active_tbl]); + /* Revert to "active" rate and throughput info */ index = iwl4965_rate_index_from_plcp( tbl->current_rate.rate_n_flags); + current_tpt = lq_data->last_tpt; + /* Need to set up a new rate table in uCode */ update_lq = 1; - current_tpt = lq_data->last_tpt; IWL_DEBUG_HT("XXY GO BACK TO OLD TABLE\n"); } + + /* Either way, we've made a decision; modulation mode + * search is done, allow rate adjustment next time. */ lq_data->search_better_tbl = 0; - done_search = 1; + done_search = 1; /* Don't switch modes below! */ goto lq_update; } + /* (Else) not in search of better modulation mode, try for better + * starting rate, while staying in this mode. */ high_low = rs_get_adjacent_rate(index, rate_scale_index_msk, tbl->lq_type); low = high_low & 0xff; high = (high_low >> 8) & 0xff; + /* Collect measured throughputs for current and adjacent rates */ current_tpt = window->average_tpt; - if (low != IWL_RATE_INVALID) low_tpt = tbl->win[low].average_tpt; - if (high != IWL_RATE_INVALID) high_tpt = tbl->win[high].average_tpt; - + /* Assume rate increase */ scale_action = 1; + /* Too many failures, decrease rate */ if ((window->success_ratio <= IWL_RATE_DECREASE_TH) || (current_tpt == 0)) { IWL_DEBUG_RATE("decrease rate because of low success_ratio\n"); scale_action = -1; + + /* No throughput measured yet for adjacent rates; try increase. */ } else if ((low_tpt == IWL_INVALID_VALUE) && (high_tpt == IWL_INVALID_VALUE)) scale_action = 1; + + /* Both adjacent throughputs are measured, but neither one has better + * throughput; we're using the best rate, don't change it! */ else if ((low_tpt != IWL_INVALID_VALUE) && (high_tpt != IWL_INVALID_VALUE) && (low_tpt < current_tpt) && (high_tpt < current_tpt)) scale_action = 0; + + /* At least one adjacent rate's throughput is measured, + * and may have better performance. */ else { + /* Higher adjacent rate's throughput is measured */ if (high_tpt != IWL_INVALID_VALUE) { + /* Higher rate has better throughput */ if (high_tpt > current_tpt) scale_action = 1; else { @@ -1494,7 +1774,10 @@ static void rs_rate_scale_perform(struct iwl4965_priv *priv, ("decrease rate because of high tpt\n"); scale_action = -1; } + + /* Lower adjacent rate's throughput is measured */ } else if (low_tpt != IWL_INVALID_VALUE) { + /* Lower rate has better throughput */ if (low_tpt > current_tpt) { IWL_DEBUG_RATE ("decrease rate because of low tpt\n"); @@ -1504,23 +1787,30 @@ static void rs_rate_scale_perform(struct iwl4965_priv *priv, } } + /* Sanity check; asked for decrease, but success rate or throughput + * has been good at old rate. Don't change it. */ if (scale_action == -1) { if ((low != IWL_RATE_INVALID) && ((window->success_ratio > IWL_RATE_HIGH_TH) || (current_tpt > (100 * tbl->expected_tpt[low])))) scale_action = 0; + + /* Sanity check; asked for increase, but success rate has not been great + * even at old rate, higher rate will be worse. Don't change it. */ } else if ((scale_action == 1) && (window->success_ratio < IWL_RATE_INCREASE_TH)) scale_action = 0; switch (scale_action) { case -1: + /* Decrease starting rate, update uCode's rate table */ if (low != IWL_RATE_INVALID) { update_lq = 1; index = low; } break; case 1: + /* Increase starting rate, update uCode's rate table */ if (high != IWL_RATE_INVALID) { update_lq = 1; index = high; @@ -1528,6 +1818,7 @@ static void rs_rate_scale_perform(struct iwl4965_priv *priv, break; case 0: + /* No change */ default: break; } @@ -1537,16 +1828,28 @@ static void rs_rate_scale_perform(struct iwl4965_priv *priv, index, scale_action, low, high, tbl->lq_type); lq_update: + /* Replace uCode's rate table for the destination station. */ if (update_lq) { rs_mcs_from_tbl(&mcs_rate, tbl, index, is_green); rs_fill_link_cmd(lq_data, &mcs_rate, &lq_data->lq); rs_send_lq_cmd(priv, &lq_data->lq, CMD_ASYNC); } + + /* Should we stay with this modulation mode, or search for a new one? */ rs_stay_in_table(lq_data); + /* + * Search for new modulation mode if we're: + * 1) Not changing rates right now + * 2) Not just finishing up a search + * 3) Allowing a new search + */ if (!update_lq && !done_search && !lq_data->stay_in_tbl) { + /* Save current throughput to compare with "search" throughput*/ lq_data->last_tpt = current_tpt; + /* Select a new "search" modulation mode to try. + * If one is found, set up the new "search" table. */ if (is_legacy(tbl->lq_type)) rs_move_legacy_other(priv, lq_data, index); else if (is_siso(tbl->lq_type)) @@ -1554,11 +1857,14 @@ static void rs_rate_scale_perform(struct iwl4965_priv *priv, else rs_move_mimo_to_other(priv, lq_data, index); + /* If new "search" mode was selected, set up in uCode table */ if (lq_data->search_better_tbl) { + /* Access the "search" table, clear its history. */ tbl = &(lq_data->lq_info[(1 - lq_data->active_tbl)]); for (i = 0; i < IWL_RATE_COUNT; i++) rs_rate_scale_clear_window(&(tbl->win[i])); + /* Use new "search" start rate */ index = iwl4965_rate_index_from_plcp( tbl->current_rate.rate_n_flags); @@ -1568,8 +1874,13 @@ static void rs_rate_scale_perform(struct iwl4965_priv *priv, &lq_data->lq); rs_send_lq_cmd(priv, &lq_data->lq, CMD_ASYNC); } - tbl1 = &(lq_data->lq_info[lq_data->active_tbl]); + /* If the "active" (non-search) mode was legacy, + * and we've tried switching antennas, + * but we haven't been able to try HT modes (not available), + * stay with best antenna legacy modulation for a while + * before next round of mode comparisons. */ + tbl1 = &(lq_data->lq_info[lq_data->active_tbl]); if (is_legacy(tbl1->lq_type) && #ifdef CONFIG_IWL4965_HT !priv->current_assoc_ht.is_ht && @@ -1580,9 +1891,13 @@ static void rs_rate_scale_perform(struct iwl4965_priv *priv, rs_set_stay_in_table(1, lq_data); } + /* If we're in an HT mode, and all 3 mode switch actions + * have been tried and compared, stay in this best modulation + * mode for a while before next round of mode comparisons. */ if (lq_data->enable_counter && (lq_data->action_counter >= IWL_ACTION_LIMIT)) { #ifdef CONFIG_IWL4965_HT_AGG + /* If appropriate, set up aggregation! */ if ((lq_data->last_tpt > TID_AGG_TPT_THREHOLD) && (priv->lq_mngr.agg_ctrl.auto_agg)) { priv->lq_mngr.agg_ctrl.tid_retry = @@ -1593,6 +1908,14 @@ static void rs_rate_scale_perform(struct iwl4965_priv *priv, lq_data->action_counter = 0; rs_set_stay_in_table(0, lq_data); } + + /* + * Else, don't search for a new modulation mode. + * Put new timestamp in stay-in-modulation-mode flush timer if: + * 1) Not changing rates right now + * 2) Not just finishing up a search + * 3) flush timer is empty + */ } else { if ((!update_lq) && (!done_search) && (!lq_data->flush_timer)) lq_data->flush_timer = jiffies; @@ -1815,15 +2138,14 @@ static void rs_rate_init(void *priv_rate, void *priv_sta, priv->assoc_station_added = 1; } + /* Find highest tx rate supported by hardware and destination station */ for (i = 0; i < mode->num_rates; i++) { if ((sta->supp_rates & BIT(i)) && (mode->rates[i].flags & IEEE80211_RATE_SUPPORTED)) sta->txrate = i; } sta->last_txrate = sta->txrate; - /* For MODE_IEEE80211A mode cck rate are at end - * rate table - */ + /* For MODE_IEEE80211A, cck rates are at end of rate table */ if (local->hw.conf.phymode == MODE_IEEE80211A) sta->last_txrate += IWL_FIRST_OFDM_RATE; @@ -1836,11 +2158,16 @@ static void rs_rate_init(void *priv_rate, void *priv_sta, crl->active_rate_basic = priv->active_rate_basic; crl->phymode = priv->phymode; #ifdef CONFIG_IWL4965_HT + /* + * active_siso_rate mask includes 9 MBits (bit 5), and CCK (bits 0-3), + * supp_rates[] does not; shift to convert format, force 9 MBits off. + */ crl->active_siso_rate = (priv->current_assoc_ht.supp_rates[0] << 1); crl->active_siso_rate |= (priv->current_assoc_ht.supp_rates[0] & 0x1); crl->active_siso_rate &= ~((u16)0x2); crl->active_siso_rate = crl->active_siso_rate << IWL_FIRST_OFDM_RATE; + /* Same here */ crl->active_mimo_rate = (priv->current_assoc_ht.supp_rates[1] << 1); crl->active_mimo_rate |= (priv->current_assoc_ht.supp_rates[1] & 0x1); crl->active_mimo_rate &= ~((u16)0x2); @@ -1870,11 +2197,14 @@ static void rs_fill_link_cmd(struct iwl4965_rate_scale_priv *lq_data, struct iwl4965_rate new_rate; struct iwl4965_scale_tbl_info tbl_type = { 0 }; + /* Override starting rate (index 0) if needed for debug purposes */ rs_dbgfs_set_mcs(lq_data, tx_mcs, index); + /* Interpret rate_n_flags */ rs_get_tbl_info_from_mcs(tx_mcs, lq_data->phymode, &tbl_type, &rate_idx); + /* How many times should we repeat the initial rate? */ if (is_legacy(tbl_type.lq_type)) { ant_toggle_count = 1; repeat_rate = IWL_NUMBER_TRY; @@ -1883,19 +2213,27 @@ static void rs_fill_link_cmd(struct iwl4965_rate_scale_priv *lq_data, lq_cmd->general_params.mimo_delimiter = is_mimo(tbl_type.lq_type) ? 1 : 0; + + /* Fill 1st table entry (index 0) */ lq_cmd->rs_table[index].rate_n_flags = cpu_to_le32(tx_mcs->rate_n_flags); new_rate.rate_n_flags = tx_mcs->rate_n_flags; if (is_mimo(tbl_type.lq_type) || (tbl_type.antenna_type == ANT_MAIN)) - lq_cmd->general_params.single_stream_ant_msk = 1; + lq_cmd->general_params.single_stream_ant_msk + = LINK_QUAL_ANT_A_MSK; else - lq_cmd->general_params.single_stream_ant_msk = 2; + lq_cmd->general_params.single_stream_ant_msk + = LINK_QUAL_ANT_B_MSK; index++; repeat_rate--; + /* Fill rest of rate table */ while (index < LINK_QUAL_MAX_RETRY_NUM) { + /* Repeat initial/next rate. + * For legacy IWL_NUMBER_TRY == 1, this loop will not execute. + * For HT IWL_HT_NUMBER_TRY == 3, this executes twice. */ while (repeat_rate > 0 && (index < LINK_QUAL_MAX_RETRY_NUM)) { if (is_legacy(tbl_type.lq_type)) { if (ant_toggle_count < @@ -1907,7 +2245,10 @@ static void rs_fill_link_cmd(struct iwl4965_rate_scale_priv *lq_data, } } + /* Override next rate if needed for debug purposes */ rs_dbgfs_set_mcs(lq_data, &new_rate, index); + + /* Fill next table entry */ lq_cmd->rs_table[index].rate_n_flags = cpu_to_le32(new_rate.rate_n_flags); repeat_rate--; @@ -1917,12 +2258,17 @@ static void rs_fill_link_cmd(struct iwl4965_rate_scale_priv *lq_data, rs_get_tbl_info_from_mcs(&new_rate, lq_data->phymode, &tbl_type, &rate_idx); + /* Indicate to uCode which entries might be MIMO. + * If initial rate was MIMO, this will finally end up + * as (IWL_HT_NUMBER_TRY * 2), after 2nd pass, otherwise 0. */ if (is_mimo(tbl_type.lq_type)) lq_cmd->general_params.mimo_delimiter = index; + /* Get next rate */ rs_get_lower_rate(lq_data, &tbl_type, rate_idx, use_ht_possible, &new_rate); + /* How many times should we repeat the next rate? */ if (is_legacy(tbl_type.lq_type)) { if (ant_toggle_count < NUM_TRY_BEFORE_ANTENNA_TOGGLE) ant_toggle_count++; @@ -1934,9 +2280,14 @@ static void rs_fill_link_cmd(struct iwl4965_rate_scale_priv *lq_data, } else repeat_rate = IWL_HT_NUMBER_TRY; + /* Don't allow HT rates after next pass. + * rs_get_lower_rate() will change type to LQ_A or LQ_G. */ use_ht_possible = 0; + /* Override next rate if needed for debug purposes */ rs_dbgfs_set_mcs(lq_data, &new_rate, index); + + /* Fill next table entry */ lq_cmd->rs_table[index].rate_n_flags = cpu_to_le32(new_rate.rate_n_flags); @@ -2032,9 +2383,9 @@ static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file, else rs_priv->dbg_fixed.rate_n_flags = 0; - rs_priv->active_rate = 0x0FFF; - rs_priv->active_siso_rate = 0x1FD0; - rs_priv->active_mimo_rate = 0x1FD0; + rs_priv->active_rate = 0x0FFF; /* 1 - 54 MBits, includes CCK */ + rs_priv->active_siso_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */ + rs_priv->active_mimo_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */ IWL_DEBUG_RATE("sta_id %d rate 0x%X\n", rs_priv->lq.sta_id, rs_priv->dbg_fixed.rate_n_flags); @@ -2235,7 +2586,7 @@ int iwl4965_fill_rs_info(struct ieee80211_hw *hw, char *buf, u8 sta_id) /* Display the average rate of all samples taken. * - * NOTE: We multiple # of samples by 2 since the IEEE measurement + * NOTE: We multiply # of samples by 2 since the IEEE measurement * added from iwl4965_rates is actually 2X the rate */ if (samples) count += sprintf(&buf[count], diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.h b/drivers/net/wireless/iwlwifi/iwl-4965-rs.h index 4259099..86f62d8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-rs.h @@ -30,10 +30,10 @@ #include "iwl-4965.h" struct iwl4965_rate_info { - u8 plcp; - u8 plcp_siso; - u8 plcp_mimo; - u8 ieee; + u8 plcp; /* uCode API: IWL_RATE_6M_PLCP, etc. */ + u8 plcp_siso; /* uCode API: IWL_RATE_SISO_6M_PLCP, etc. */ + u8 plcp_mimo; /* uCode API: IWL_RATE_MIMO_6M_PLCP, etc. */ + u8 ieee; /* MAC header: IWL_RATE_6M_IEEE, etc. */ u8 prev_ieee; /* previous rate in IEEE speeds */ u8 next_ieee; /* next rate in IEEE speeds */ u8 prev_rs; /* previous rate used in rs algo */ @@ -42,6 +42,7 @@ struct iwl4965_rate_info { u8 next_rs_tgg; /* next rate used in TGG rs algo */ }; +/* For driver (not uCode API) */ enum { IWL_RATE_1M_INDEX = 0, IWL_RATE_2M_INDEX, @@ -83,6 +84,7 @@ enum { #define IWL_RATE_5M_MASK (1<<IWL_RATE_5M_INDEX) #define IWL_RATE_11M_MASK (1<<IWL_RATE_11M_INDEX) +/* 4965 uCode API values for legacy bit rates, both OFDM and CCK */ enum { IWL_RATE_6M_PLCP = 13, IWL_RATE_9M_PLCP = 15, @@ -99,7 +101,7 @@ enum { IWL_RATE_11M_PLCP = 110, }; -/* OFDM HT rate plcp */ +/* 4965 uCode API values for OFDM high-throughput (HT) bit rates */ enum { IWL_RATE_SISO_6M_PLCP = 0, IWL_RATE_SISO_12M_PLCP = 1, @@ -121,6 +123,7 @@ enum { IWL_RATE_MIMO_INVM_PLCP = IWL_RATE_SISO_INVM_PLCP, }; +/* MAC header values for bit rates */ enum { IWL_RATE_6M_IEEE = 12, IWL_RATE_9M_IEEE = 18, @@ -170,13 +173,8 @@ enum { #define IWL_MIN_RSSI_VAL -100 #define IWL_MAX_RSSI_VAL 0 -#define IWL_LEGACY_SWITCH_ANTENNA 0 -#define IWL_LEGACY_SWITCH_SISO 1 -#define IWL_LEGACY_SWITCH_MIMO 2 - -#define IWL_RS_GOOD_RATIO 12800 - -#define IWL_ACTION_LIMIT 3 +/* These values specify how many Tx frame attempts before + * searching for a new modulation mode */ #define IWL_LEGACY_FAILURE_LIMIT 160 #define IWL_LEGACY_SUCCESS_LIMIT 480 #define IWL_LEGACY_TABLE_COUNT 160 @@ -185,29 +183,44 @@ enum { #define IWL_NONE_LEGACY_SUCCESS_LIMIT 4500 #define IWL_NONE_LEGACY_TABLE_COUNT 1500 -#define IWL_RATE_SCALE_SWITCH (10880) +/* Success ratio (ACKed / attempted tx frames) values (perfect is 128 * 100) */ +#define IWL_RS_GOOD_RATIO 12800 /* 100% */ +#define IWL_RATE_SCALE_SWITCH 10880 /* 85% */ +#define IWL_RATE_HIGH_TH 10880 /* 85% */ +#define IWL_RATE_INCREASE_TH 8960 /* 70% */ +#define IWL_RATE_DECREASE_TH 1920 /* 15% */ +/* possible actions when in legacy mode */ +#define IWL_LEGACY_SWITCH_ANTENNA 0 +#define IWL_LEGACY_SWITCH_SISO 1 +#define IWL_LEGACY_SWITCH_MIMO 2 + +/* possible actions when in siso mode */ #define IWL_SISO_SWITCH_ANTENNA 0 #define IWL_SISO_SWITCH_MIMO 1 #define IWL_SISO_SWITCH_GI 2 +/* possible actions when in mimo mode */ #define IWL_MIMO_SWITCH_ANTENNA_A 0 #define IWL_MIMO_SWITCH_ANTENNA_B 1 #define IWL_MIMO_SWITCH_GI 2 -#define LQ_SIZE 2 +#define IWL_ACTION_LIMIT 3 /* # possible actions */ + +#define LQ_SIZE 2 /* 2 mode tables: "Active" and "Search" */ extern const struct iwl4965_rate_info iwl4965_rates[IWL_RATE_COUNT]; enum iwl4965_table_type { LQ_NONE, - LQ_G, + LQ_G, /* legacy types */ LQ_A, - LQ_SISO, + LQ_SISO, /* high-throughput types */ LQ_MIMO, LQ_MAX, }; +/* 4965 has 2 antennas/chains for Tx (but 3 for Rx) */ enum iwl4965_antenna_type { ANT_NONE, ANT_MAIN, diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index 5944b4b..d0abbb3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h @@ -489,7 +489,7 @@ struct sta_ht_info { u8 supported_chan_width; u8 extension_chan_offset; u8 is_green_field; - u8 sgf; + u8 sgf; /* HT_SHORT_GI_* short guard interval */ u8 supp_rates[16]; u8 tx_chan_width; u8 chan_width_cap; diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 6dd6c7d..a41839e 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -1488,6 +1488,7 @@ int iwl4965_rate_index_from_plcp(int plcp) { int i = 0; + /* 4965 HT rate format */ if (plcp & RATE_MCS_HT_MSK) { i = (plcp & 0xff); @@ -1501,6 +1502,8 @@ int iwl4965_rate_index_from_plcp(int plcp) if ((i >= IWL_FIRST_OFDM_RATE) && (i <= IWL_LAST_OFDM_RATE)) return i; + + /* 4965 legacy rate format, search for match in table */ } else { for (i = 0; i < ARRAY_SIZE(iwl4965_rates); i++) if (iwl4965_rates[i].plcp == (plcp &0xFF)) -- 1.5.3.6 ^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 05/36] iwlwifi: add comments to EEPROM stuff 2007-11-29 3:09 ` [PATCH 04/36] iwl4965: add comments to rate scaling code Zhu Yi @ 2007-11-29 3:09 ` Zhu Yi 2007-11-29 3:09 ` [PATCH 06/36] iwl-4965-hw.h: clean up unused eeprom structures and definitions Zhu Yi 0 siblings, 1 reply; 36+ messages in thread From: Zhu Yi @ 2007-11-29 3:09 UTC (permalink / raw) To: linville; +Cc: linux-wireless, Ben Cahill, Zhu Yi From: Ben Cahill <ben.m.cahill@intel.com> Add comments to EEPROM stuff. Signed-off-by: Ben Cahill <ben.m.cahill@intel.com> Signed-off-by: Zhu Yi <yi.zhu@intel.com> --- drivers/net/wireless/iwlwifi/iwl-3945-hw.h | 94 +++++++++++-- drivers/net/wireless/iwlwifi/iwl-3945.c | 9 ++ drivers/net/wireless/iwlwifi/iwl-4965-hw.h | 209 +++++++++++++++++++++++++--- drivers/net/wireless/iwlwifi/iwl-4965.c | 9 ++ 4 files changed, 285 insertions(+), 36 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h index 402e347..243a225 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h @@ -85,24 +85,48 @@ #define IWL_RSSI_OFFSET 95 /* - * This file defines EEPROM related constants, enums, and inline functions. - * + * EEPROM related constants, enums, and structures. */ +/* + * EEPROM access time values: + * + * Driver initiates EEPROM read by writing byte address << 1 to CSR_EEPROM_REG, + * then clearing (with subsequent read/modify/write) CSR_EEPROM_REG bit + * CSR_EEPROM_REG_BIT_CMD (0x2). + * Driver then polls CSR_EEPROM_REG for CSR_EEPROM_REG_READ_VALID_MSK (0x1). + * When polling, wait 10 uSec between polling loops, up to a maximum 5000 uSec. + * Driver reads 16-bit value from bits 31-16 of CSR_EEPROM_REG. + */ #define IWL_EEPROM_ACCESS_TIMEOUT 5000 /* uSec */ #define IWL_EEPROM_ACCESS_DELAY 10 /* uSec */ + /* EEPROM field values */ #define ANTENNA_SWITCH_NORMAL 0 #define ANTENNA_SWITCH_INVERSE 1 +/* + * Regulatory channel usage flags in EEPROM struct iwl_eeprom_channel.flags. + * + * IBSS and/or AP operation is allowed *only* on those channels with + * (VALID && IBSS && ACTIVE && !RADAR). This restriction is in place because + * RADAR detection is not supported by the 3945 driver, but is a + * requirement for establishing a new network for legal operation on channels + * requiring RADAR detection or restricting ACTIVE scanning. + * + * NOTE: "WIDE" flag indicates that 20 MHz channel is supported; + * 3945 does not support FAT 40 MHz-wide channels. + * + * NOTE: Using a channel inappropriately will result in a uCode error! + */ enum { EEPROM_CHANNEL_VALID = (1 << 0), /* usable for this SKU/geo */ - EEPROM_CHANNEL_IBSS = (1 << 1), /* usable as an IBSS channel */ + EEPROM_CHANNEL_IBSS = (1 << 1), /* usable as an IBSS channel */ /* Bit 2 Reserved */ EEPROM_CHANNEL_ACTIVE = (1 << 3), /* active scanning allowed */ EEPROM_CHANNEL_RADAR = (1 << 4), /* radar detection required */ - EEPROM_CHANNEL_WIDE = (1 << 5), - EEPROM_CHANNEL_NARROW = (1 << 6), + EEPROM_CHANNEL_WIDE = (1 << 5), /* 20 MHz channel okay */ + EEPROM_CHANNEL_NARROW = (1 << 6), /* 10 MHz channel, not used */ EEPROM_CHANNEL_DFS = (1 << 7), /* dynamic freq selection candidate */ }; @@ -147,6 +171,7 @@ struct iwl3945_eeprom_channel { * long packets in normal operation to provide feedback as to proper output * level. * Data copied from EEPROM. + * DO NOT ALTER THIS STRUCTURE!!! */ struct iwl3945_eeprom_txpower_sample { u8 gain_index; /* index into power (gain) setup table ... */ @@ -163,11 +188,11 @@ struct iwl3945_eeprom_txpower_sample { * DO NOT ALTER THIS STRUCTURE!!! */ struct iwl3945_eeprom_txpower_group { - struct iwl3945_eeprom_txpower_sample samples[5]; /* 5 power levels */ + struct iwl3945_eeprom_txpower_sample samples[5]; /* 5 power levels */ s32 a, b, c, d, e; /* coefficients for voltage->power * formula (signed) */ s32 Fa, Fb, Fc, Fd, Fe; /* these modify coeffs based on - * frequency (signed) */ + * frequency (signed) */ s8 saturation_power; /* highest power possible by h/w in this * band */ u8 group_channel; /* "representative" channel # in this band */ @@ -189,6 +214,9 @@ struct iwl3945_eeprom_temperature_corr { u32 Te; } __attribute__ ((packed)); +/* + * EEPROM map + */ struct iwl3945_eeprom { u8 reserved0[16]; #define EEPROM_DEVICE_ID (2*0x08) /* 2 bytes */ @@ -229,29 +257,67 @@ struct iwl3945_eeprom { u8 reserved6[42]; #define EEPROM_REGULATORY_SKU_ID (2*0x60) /* 4 bytes */ u8 sku_id[4]; /* abs.ofs: 192 */ + +/* + * Per-channel regulatory data. + * + * Each channel that *might* be supported by 3945 or 4965 has a fixed location + * in EEPROM containing EEPROM_CHANNEL_* usage flags (LSB) and max regulatory + * txpower (MSB). + * + * Entries immediately below are for 20 MHz channel width. FAT (40 MHz) + * channels (only for 4965, not supported by 3945) appear later in the EEPROM. + * + * 2.4 GHz channels 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 + */ #define EEPROM_REGULATORY_BAND_1 (2*0x62) /* 2 bytes */ u16 band_1_count; /* abs.ofs: 196 */ #define EEPROM_REGULATORY_BAND_1_CHANNELS (2*0x63) /* 28 bytes */ - struct iwl3945_eeprom_channel band_1_channels[14]; /* abs.ofs: 196 */ + struct iwl3945_eeprom_channel band_1_channels[14]; /* abs.ofs: 196 */ + +/* + * 4.9 GHz channels 183, 184, 185, 187, 188, 189, 192, 196, + * 5.0 GHz channels 7, 8, 11, 12, 16 + * (4915-5080MHz) (none of these is ever supported) + */ #define EEPROM_REGULATORY_BAND_2 (2*0x71) /* 2 bytes */ u16 band_2_count; /* abs.ofs: 226 */ #define EEPROM_REGULATORY_BAND_2_CHANNELS (2*0x72) /* 26 bytes */ - struct iwl3945_eeprom_channel band_2_channels[13]; /* abs.ofs: 228 */ + struct iwl3945_eeprom_channel band_2_channels[13]; /* abs.ofs: 228 */ + +/* + * 5.2 GHz channels 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64 + * (5170-5320MHz) + */ #define EEPROM_REGULATORY_BAND_3 (2*0x7F) /* 2 bytes */ u16 band_3_count; /* abs.ofs: 254 */ #define EEPROM_REGULATORY_BAND_3_CHANNELS (2*0x80) /* 24 bytes */ - struct iwl3945_eeprom_channel band_3_channels[12]; /* abs.ofs: 256 */ + struct iwl3945_eeprom_channel band_3_channels[12]; /* abs.ofs: 256 */ + +/* + * 5.5 GHz channels 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140 + * (5500-5700MHz) + */ #define EEPROM_REGULATORY_BAND_4 (2*0x8C) /* 2 bytes */ u16 band_4_count; /* abs.ofs: 280 */ #define EEPROM_REGULATORY_BAND_4_CHANNELS (2*0x8D) /* 22 bytes */ - struct iwl3945_eeprom_channel band_4_channels[11]; /* abs.ofs: 282 */ + struct iwl3945_eeprom_channel band_4_channels[11]; /* abs.ofs: 282 */ + +/* + * 5.7 GHz channels 145, 149, 153, 157, 161, 165 + * (5725-5825MHz) + */ #define EEPROM_REGULATORY_BAND_5 (2*0x98) /* 2 bytes */ u16 band_5_count; /* abs.ofs: 304 */ #define EEPROM_REGULATORY_BAND_5_CHANNELS (2*0x99) /* 12 bytes */ - struct iwl3945_eeprom_channel band_5_channels[6]; /* abs.ofs: 306 */ + struct iwl3945_eeprom_channel band_5_channels[6]; /* abs.ofs: 306 */ u8 reserved9[194]; + +/* + * 3945 Txpower calibration data. + */ #define EEPROM_TXPOWER_CALIB_GROUP0 0x200 #define EEPROM_TXPOWER_CALIB_GROUP1 0x240 #define EEPROM_TXPOWER_CALIB_GROUP2 0x280 @@ -261,12 +327,14 @@ struct iwl3945_eeprom { struct iwl3945_eeprom_txpower_group groups[IWL_NUM_TX_CALIB_GROUPS]; /* abs.ofs: 512 */ #define EEPROM_CALIB_TEMPERATURE_CORRECT 0x340 - struct iwl3945_eeprom_temperature_corr corrections; /* abs.ofs: 832 */ + struct iwl3945_eeprom_temperature_corr corrections; /* abs.ofs: 832 */ u8 reserved16[172]; /* fill out to full 1024 byte block */ } __attribute__ ((packed)); #define IWL_EEPROM_IMAGE_SIZE 1024 +/* End of EEPROM */ + #include "iwl-3945-commands.h" diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 953a9be..51b9030 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -2202,6 +2202,7 @@ int iwl3945_init_hw_rate_table(struct iwl3945_priv *priv) &rate_cmd); } +/* Called when initializing driver */ int iwl3945_hw_set_hw_setting(struct iwl3945_priv *priv) { memset((void *)&priv->hw_setting, 0, @@ -2284,6 +2285,14 @@ struct pci_device_id iwl3945_hw_card_ids[] = { {0} }; +/* + * Clear the OWNER_MSK, to establish driver (instead of uCode running on + * embedded controller) as EEPROM reader; each read is a series of pulses + * to/from the EEPROM chip, not a single event, so even reads could conflict + * if they weren't arbitrated by some ownership mechanism. Here, the driver + * simply claims ownership, which should be safe when this function is called + * (i.e. before loading uCode!). + */ inline int iwl3945_eeprom_acquire_semaphore(struct iwl3945_priv *priv) { _iwl3945_clear_bit(priv, CSR_EEPROM_GP, CSR_EEPROM_GP_IF_OWNER_MSK); diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h index 1800490..1c44459 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h @@ -85,24 +85,50 @@ #define IWL_RSSI_OFFSET 44 /* - * This file defines EEPROM related constants, enums, and inline functions. - * + * EEPROM related constants, enums, and structures. */ +/* + * EEPROM access time values: + * + * Driver initiates EEPROM read by writing byte address << 1 to CSR_EEPROM_REG, + * then clearing (with subsequent read/modify/write) CSR_EEPROM_REG bit + * CSR_EEPROM_REG_BIT_CMD (0x2). + * Driver then polls CSR_EEPROM_REG for CSR_EEPROM_REG_READ_VALID_MSK (0x1). + * When polling, wait 10 uSec between polling loops, up to a maximum 5000 uSec. + * Driver reads 16-bit value from bits 31-16 of CSR_EEPROM_REG. + */ #define IWL_EEPROM_ACCESS_TIMEOUT 5000 /* uSec */ #define IWL_EEPROM_ACCESS_DELAY 10 /* uSec */ + /* EEPROM field values */ #define ANTENNA_SWITCH_NORMAL 0 #define ANTENNA_SWITCH_INVERSE 1 +/* + * Regulatory channel usage flags in EEPROM struct iwl4965_eeprom_channel.flags. + * + * IBSS and/or AP operation is allowed *only* on those channels with + * (VALID && IBSS && ACTIVE && !RADAR). This restriction is in place because + * RADAR detection is not supported by the 4965 driver, but is a + * requirement for establishing a new network for legal operation on channels + * requiring RADAR detection or restricting ACTIVE scanning. + * + * NOTE: "WIDE" flag does not indicate anything about "FAT" 40 MHz channels. + * It only indicates that 20 MHz channel use is supported; FAT channel + * usage is indicated by a separate set of regulatory flags for each + * FAT channel pair. + * + * NOTE: Using a channel inappropriately will result in a uCode error! + */ enum { EEPROM_CHANNEL_VALID = (1 << 0), /* usable for this SKU/geo */ - EEPROM_CHANNEL_IBSS = (1 << 1), /* usable as an IBSS channel */ + EEPROM_CHANNEL_IBSS = (1 << 1), /* usable as an IBSS channel */ /* Bit 2 Reserved */ EEPROM_CHANNEL_ACTIVE = (1 << 3), /* active scanning allowed */ EEPROM_CHANNEL_RADAR = (1 << 4), /* radar detection required */ - EEPROM_CHANNEL_WIDE = (1 << 5), - EEPROM_CHANNEL_NARROW = (1 << 6), + EEPROM_CHANNEL_WIDE = (1 << 5), /* 20 MHz channel okay */ + EEPROM_CHANNEL_NARROW = (1 << 6), /* 10 MHz channel, not used */ EEPROM_CHANNEL_DFS = (1 << 7), /* dynamic freq selection candidate */ }; @@ -136,9 +162,10 @@ enum { #define EEPROM_SKU_CAP_HW_RF_KILL_ENABLE (1 << 1) #define EEPROM_SKU_CAP_OP_MODE_MRC (1 << 7) -/* *regulatory* channel data from eeprom, one for each channel */ +/* *regulatory* channel data format in eeprom, one for each channel. + * There are separate entries for FAT (40 MHz) vs. normal (20 MHz) channels. */ struct iwl4965_eeprom_channel { - u8 flags; /* flags copied from EEPROM */ + u8 flags; /* EEPROM_CHANNEL_* flags copied from EEPROM */ s8 max_power_avg; /* max power (dBm) on this chnl, limit 31 */ } __attribute__ ((packed)); @@ -193,44 +220,112 @@ struct iwl4965_eeprom_temperature_corr { u32 Te; } __attribute__ ((packed)); +/* 4965 has two radio transmitters (and 3 radio receivers) */ #define EEPROM_TX_POWER_TX_CHAINS (2) + +/* 4965 has room for up to 8 sets of txpower calibration data */ #define EEPROM_TX_POWER_BANDS (8) + +/* 4965 factory calibration measures txpower gain settings for + * each of 3 target output levels */ #define EEPROM_TX_POWER_MEASUREMENTS (3) + #define EEPROM_TX_POWER_VERSION (2) + +/* 4965 driver does not work with txpower calibration version < 5. + * Look for this in calib_version member of struct iwl4965_eeprom. */ #define EEPROM_TX_POWER_VERSION_NEW (5) + +/* + * 4965 factory calibration data for one txpower level, on one channel, + * measured on one of the 2 tx chains (radio transmitter and associated + * antenna). EEPROM contains: + * + * 1) Temperature (degrees Celsius) of device when measurement was made. + * + * 2) Gain table index used to achieve the target measurement power. + * This refers to the "well-known" gain tables (see iwl-4965-hw.h). + * + * 3) Actual measured output power, in half-dBm ("34" = 17 dBm). + * + * 4) RF power amplifier detector level measurement (not used). + */ struct iwl4965_eeprom_calib_measure { - u8 temperature; - u8 gain_idx; - u8 actual_pow; - s8 pa_det; + u8 temperature; /* Device temperature (Celsius) */ + u8 gain_idx; /* Index into gain table */ + u8 actual_pow; /* Measured RF output power, half-dBm */ + s8 pa_det; /* Power amp detector level (not used) */ } __attribute__ ((packed)); + +/* + * 4965 measurement set for one channel. EEPROM contains: + * + * 1) Channel number measured + * + * 2) Measurements for each of 3 power levels for each of 2 radio transmitters + * (a.k.a. "tx chains") (6 measurements altogether) + */ struct iwl4965_eeprom_calib_ch_info { u8 ch_num; struct iwl4965_eeprom_calib_measure measurements[EEPROM_TX_POWER_TX_CHAINS] [EEPROM_TX_POWER_MEASUREMENTS]; } __attribute__ ((packed)); +/* + * 4965 txpower subband info. + * + * For each frequency subband, EEPROM contains the following: + * + * 1) First and last channels within range of the subband. "0" values + * indicate that this sample set is not being used. + * + * 2) Sample measurement sets for 2 channels close to the range endpoints. + */ struct iwl4965_eeprom_calib_subband_info { - u8 ch_from; - u8 ch_to; + u8 ch_from; /* channel number of lowest channel in subband */ + u8 ch_to; /* channel number of highest channel in subband */ struct iwl4965_eeprom_calib_ch_info ch1; struct iwl4965_eeprom_calib_ch_info ch2; } __attribute__ ((packed)); + +/* + * 4965 txpower calibration info. EEPROM contains: + * + * 1) Factory-measured saturation power levels (maximum levels at which + * tx power amplifier can output a signal without too much distortion). + * There is one level for 2.4 GHz band and one for 5 GHz band. These + * values apply to all channels within each of the bands. + * + * 2) Factory-measured power supply voltage level. This is assumed to be + * constant (i.e. same value applies to all channels/bands) while the + * factory measurements are being made. + * + * 3) Up to 8 sets of factory-measured txpower calibration values. + * These are for different frequency ranges, since txpower gain + * characteristics of the analog radio circuitry vary with frequency. + * + * Not all sets need to be filled with data; + * struct iwl4965_eeprom_calib_subband_info contains range of channels + * (0 if unused) for each set of data. + */ struct iwl4965_eeprom_calib_info { - u8 saturation_power24; - u8 saturation_power52; + u8 saturation_power24; /* half-dBm (e.g. "34" = 17 dBm) */ + u8 saturation_power52; /* half-dBm */ s16 voltage; /* signed */ struct iwl4965_eeprom_calib_subband_info band_info[EEPROM_TX_POWER_BANDS]; } __attribute__ ((packed)); +/* + * 4965 EEPROM map + */ struct iwl4965_eeprom { u8 reserved0[16]; #define EEPROM_DEVICE_ID (2*0x08) /* 2 bytes */ - u16 device_id; /* abs.ofs: 16 */ + u16 device_id; /* abs.ofs: 16 */ u8 reserved1[2]; #define EEPROM_PMC (2*0x0A) /* 2 bytes */ u16 pmc; /* abs.ofs: 20 */ @@ -273,40 +368,107 @@ struct iwl4965_eeprom { u8 reserved8[10]; #define EEPROM_REGULATORY_SKU_ID (2*0x60) /* 4 bytes */ u8 sku_id[4]; /* abs.ofs: 192 */ + +/* + * Per-channel regulatory data. + * + * Each channel that *might* be supported by 3945 or 4965 has a fixed location + * in EEPROM containing EEPROM_CHANNEL_* usage flags (LSB) and max regulatory + * txpower (MSB). + * + * Entries immediately below are for 20 MHz channel width. FAT (40 MHz) + * channels (only for 4965, not supported by 3945) appear later in the EEPROM. + * + * 2.4 GHz channels 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 + */ #define EEPROM_REGULATORY_BAND_1 (2*0x62) /* 2 bytes */ u16 band_1_count; /* abs.ofs: 196 */ #define EEPROM_REGULATORY_BAND_1_CHANNELS (2*0x63) /* 28 bytes */ - struct iwl4965_eeprom_channel band_1_channels[14]; /* abs.ofs: 196 */ + struct iwl4965_eeprom_channel band_1_channels[14]; /* abs.ofs: 196 */ + +/* + * 4.9 GHz channels 183, 184, 185, 187, 188, 189, 192, 196, + * 5.0 GHz channels 7, 8, 11, 12, 16 + * (4915-5080MHz) (none of these is ever supported) + */ #define EEPROM_REGULATORY_BAND_2 (2*0x71) /* 2 bytes */ u16 band_2_count; /* abs.ofs: 226 */ #define EEPROM_REGULATORY_BAND_2_CHANNELS (2*0x72) /* 26 bytes */ - struct iwl4965_eeprom_channel band_2_channels[13]; /* abs.ofs: 228 */ + struct iwl4965_eeprom_channel band_2_channels[13]; /* abs.ofs: 228 */ + +/* + * 5.2 GHz channels 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64 + * (5170-5320MHz) + */ #define EEPROM_REGULATORY_BAND_3 (2*0x7F) /* 2 bytes */ u16 band_3_count; /* abs.ofs: 254 */ #define EEPROM_REGULATORY_BAND_3_CHANNELS (2*0x80) /* 24 bytes */ - struct iwl4965_eeprom_channel band_3_channels[12]; /* abs.ofs: 256 */ + struct iwl4965_eeprom_channel band_3_channels[12]; /* abs.ofs: 256 */ + +/* + * 5.5 GHz channels 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140 + * (5500-5700MHz) + */ #define EEPROM_REGULATORY_BAND_4 (2*0x8C) /* 2 bytes */ u16 band_4_count; /* abs.ofs: 280 */ #define EEPROM_REGULATORY_BAND_4_CHANNELS (2*0x8D) /* 22 bytes */ - struct iwl4965_eeprom_channel band_4_channels[11]; /* abs.ofs: 282 */ + struct iwl4965_eeprom_channel band_4_channels[11]; /* abs.ofs: 282 */ + +/* + * 5.7 GHz channels 145, 149, 153, 157, 161, 165 + * (5725-5825MHz) + */ #define EEPROM_REGULATORY_BAND_5 (2*0x98) /* 2 bytes */ u16 band_5_count; /* abs.ofs: 304 */ #define EEPROM_REGULATORY_BAND_5_CHANNELS (2*0x99) /* 12 bytes */ - struct iwl4965_eeprom_channel band_5_channels[6]; /* abs.ofs: 306 */ + struct iwl4965_eeprom_channel band_5_channels[6]; /* abs.ofs: 306 */ u8 reserved10[2]; + + +/* + * 2.4 GHz FAT channels 1 (5), 2 (6), 3 (7), 4 (8), 5 (9), 6 (10), 7 (11) + * + * The channel listed is the center of the lower 20 MHz half of the channel. + * The overall center frequency is actually 2 channels (10 MHz) above that, + * and the upper half of each FAT channel is centered 4 channels (20 MHz) away + * from the lower half; e.g. the upper half of FAT channel 1 is channel 5, + * and the overall FAT channel width centers on channel 3. + * + * NOTE: The RXON command uses 20 MHz channel numbers to specify the + * control channel to which to tune. RXON also specifies whether the + * control channel is the upper or lower half of a FAT channel. + * + * NOTE: 4965 does not support FAT channels on 2.4 GHz. + */ #define EEPROM_REGULATORY_BAND_24_FAT_CHANNELS (2*0xA0) /* 14 bytes */ - struct iwl4965_eeprom_channel band_24_channels[7]; /* abs.ofs: 320 */ + struct iwl4965_eeprom_channel band_24_channels[7]; /* abs.ofs: 320 */ u8 reserved11[2]; + +/* + * 5.2 GHz FAT channels 36 (40), 44 (48), 52 (56), 60 (64), + * 100 (104), 108 (112), 116 (120), 124 (128), 132 (136), 149 (153), 157 (161) + */ #define EEPROM_REGULATORY_BAND_52_FAT_CHANNELS (2*0xA8) /* 22 bytes */ - struct iwl4965_eeprom_channel band_52_channels[11]; /* abs.ofs: 336 */ + struct iwl4965_eeprom_channel band_52_channels[11]; /* abs.ofs: 336 */ u8 reserved12[6]; + +/* + * 4965 driver requires txpower calibration format version 5 or greater. + * Driver does not work with txpower calibration version < 5. + * This value is simply a 16-bit number, no major/minor versions here. + */ #define EEPROM_CALIB_VERSION_OFFSET (2*0xB6) /* 2 bytes */ u16 calib_version; /* abs.ofs: 364 */ u8 reserved13[2]; + #define EEPROM_SATURATION_POWER_OFFSET (2*0xB8) /* 2 bytes */ u16 satruation_power; /* abs.ofs: 368 */ u8 reserved14[94]; + +/* + * 4965 Txpower calibration data. + */ #define EEPROM_IWL_CALIB_TXPOWER_OFFSET (2*0xE8) /* 48 bytes */ struct iwl4965_eeprom_calib_info calib_info; /* abs.ofs: 464 */ @@ -317,6 +479,7 @@ struct iwl4965_eeprom { #define IWL_EEPROM_IMAGE_SIZE 1024 +/* End of EEPROM */ #include "iwl-4965-commands.h" diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 5dee8e5..7d95de9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -4687,14 +4687,23 @@ struct pci_device_id iwl4965_hw_card_ids[] = { {0} }; +/* + * The device's EEPROM semaphore prevents conflicts between driver and uCode + * when accessing the EEPROM; each access is a series of pulses to/from the + * EEPROM chip, not a single event, so even reads could conflict if they + * weren't arbitrated by the semaphore. + */ int iwl4965_eeprom_acquire_semaphore(struct iwl4965_priv *priv) { u16 count; int rc; for (count = 0; count < EEPROM_SEM_RETRY_LIMIT; count++) { + /* Request semaphore */ iwl4965_set_bit(priv, CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); + + /* See if we got it */ rc = iwl4965_poll_bit(priv, CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, -- 1.5.3.6 ^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 06/36] iwl-4965-hw.h: clean up unused eeprom structures and definitions 2007-11-29 3:09 ` [PATCH 05/36] iwlwifi: add comments to EEPROM stuff Zhu Yi @ 2007-11-29 3:09 ` Zhu Yi 2007-11-29 3:09 ` [PATCH 07/36] iwlwifi: clean up and clarify some comments after 3945/4965 split Zhu Yi 0 siblings, 1 reply; 36+ messages in thread From: Zhu Yi @ 2007-11-29 3:09 UTC (permalink / raw) To: linville; +Cc: linux-wireless, Ben Cahill, Zhu Yi From: Ben Cahill <ben.m.cahill@intel.com> Clean up unused eeprom structures and definitions in iwl-4965-hw.h. Signed-off-by: Ben Cahill <ben.m.cahill@intel.com> Signed-off-by: Zhu Yi <yi.zhu@intel.com> --- drivers/net/wireless/iwlwifi/iwl-4965-hw.h | 58 +--------------------------- 1 files changed, 1 insertions(+), 57 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h index 1c44459..e106ec1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h @@ -169,57 +169,6 @@ struct iwl4965_eeprom_channel { s8 max_power_avg; /* max power (dBm) on this chnl, limit 31 */ } __attribute__ ((packed)); -/* - * Mapping of a Tx power level, at factory calibration temperature, - * to a radio/DSP gain table index. - * One for each of 5 "sample" power levels in each band. - * v_det is measured at the factory, using the 3945's built-in power amplifier - * (PA) output voltage detector. This same detector is used during Tx of - * long packets in normal operation to provide feedback as to proper output - * level. - * Data copied from EEPROM. - */ -struct iwl4965_eeprom_txpower_sample { - u8 gain_index; /* index into power (gain) setup table ... */ - s8 power; /* ... for this pwr level for this chnl group */ - u16 v_det; /* PA output voltage */ -} __attribute__ ((packed)); - -/* - * Mappings of Tx power levels -> nominal radio/DSP gain table indexes. - * One for each channel group (a.k.a. "band") (1 for BG, 4 for A). - * Tx power setup code interpolates between the 5 "sample" power levels - * to determine the nominal setup for a requested power level. - * Data copied from EEPROM. - * DO NOT ALTER THIS STRUCTURE!!! - */ -struct iwl4965_eeprom_txpower_group { - struct iwl4965_eeprom_txpower_sample samples[5]; /* 5 power levels */ - s32 a, b, c, d, e; /* coefficients for voltage->power - * formula (signed) */ - s32 Fa, Fb, Fc, Fd, Fe; /* these modify coeffs based on - * frequency (signed) */ - s8 saturation_power; /* highest power possible by h/w in this - * band */ - u8 group_channel; /* "representative" channel # in this band */ - s16 temperature; /* h/w temperature at factory calib this band - * (signed) */ -} __attribute__ ((packed)); - -/* - * Temperature-based Tx-power compensation data, not band-specific. - * These coefficients are use to modify a/b/c/d/e coeffs based on - * difference between current temperature and factory calib temperature. - * Data copied from EEPROM. - */ -struct iwl4965_eeprom_temperature_corr { - u32 Ta; - u32 Tb; - u32 Tc; - u32 Td; - u32 Te; -} __attribute__ ((packed)); - /* 4965 has two radio transmitters (and 3 radio receivers) */ #define EEPROM_TX_POWER_TX_CHAINS (2) @@ -230,8 +179,6 @@ struct iwl4965_eeprom_temperature_corr { * each of 3 target output levels */ #define EEPROM_TX_POWER_MEASUREMENTS (3) -#define EEPROM_TX_POWER_VERSION (2) - /* 4965 driver does not work with txpower calibration version < 5. * Look for this in calib_version member of struct iwl4965_eeprom. */ #define EEPROM_TX_POWER_VERSION_NEW (5) @@ -461,10 +408,7 @@ struct iwl4965_eeprom { #define EEPROM_CALIB_VERSION_OFFSET (2*0xB6) /* 2 bytes */ u16 calib_version; /* abs.ofs: 364 */ u8 reserved13[2]; - -#define EEPROM_SATURATION_POWER_OFFSET (2*0xB8) /* 2 bytes */ - u16 satruation_power; /* abs.ofs: 368 */ - u8 reserved14[94]; + u8 reserved14[96]; /* abs.ofs: 368 */ /* * 4965 Txpower calibration data. -- 1.5.3.6 ^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 07/36] iwlwifi: clean up and clarify some comments after 3945/4965 split 2007-11-29 3:09 ` [PATCH 06/36] iwl-4965-hw.h: clean up unused eeprom structures and definitions Zhu Yi @ 2007-11-29 3:09 ` Zhu Yi 2007-11-29 3:09 ` [PATCH 08/36] iwlwifi: Move is_legacy() macro family from iwl-4965-hw.h to iwl-4965-rs.h Zhu Yi 0 siblings, 1 reply; 36+ messages in thread From: Zhu Yi @ 2007-11-29 3:09 UTC (permalink / raw) To: linville; +Cc: linux-wireless, Ben Cahill, Zhu Yi From: Ben Cahill <ben.m.cahill@intel.com> Clean up and clarify some comments after 3945/4965 split. Signed-off-by: Ben Cahill <ben.m.cahill@intel.com> Signed-off-by: Zhu Yi <yi.zhu@intel.com> --- drivers/net/wireless/iwlwifi/iwl-3945-rs.h | 11 ++- drivers/net/wireless/iwlwifi/iwl-4965-rs.h | 5 +- drivers/net/wireless/iwlwifi/iwl3945-base.c | 126 ++++++++------------- drivers/net/wireless/iwlwifi/iwl4965-base.c | 163 ++++++++++++--------------- 4 files changed, 132 insertions(+), 173 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.h b/drivers/net/wireless/iwlwifi/iwl-3945-rs.h index 075f7de..e21a5ba 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.h @@ -28,8 +28,8 @@ #define __iwl_3945_rs_h__ struct iwl3945_rate_info { - u8 plcp; - u8 ieee; + u8 plcp; /* uCode API: IWL_RATE_6M_PLCP, etc. */ + u8 ieee; /* MAC header: IWL_RATE_6M_IEEE, etc. */ u8 prev_ieee; /* previous rate in IEEE speeds */ u8 next_ieee; /* next rate in IEEE speeds */ u8 prev_rs; /* previous rate used in rs algo */ @@ -38,9 +38,12 @@ struct iwl3945_rate_info { u8 next_rs_tgg; /* next rate used in TGG rs algo */ u8 table_rs_index; /* index in rate scale table cmd */ u8 prev_table_rs; /* prev in rate table cmd */ - }; +/* + * These serve as indexes into + * struct iwl3945_rate_info iwl3945_rates[IWL_RATE_COUNT]; + */ enum { IWL_RATE_1M_INDEX = 0, IWL_RATE_2M_INDEX, @@ -96,6 +99,7 @@ enum { #define IWL_RATE_5M_MASK (1<<IWL_RATE_5M_INDEX) #define IWL_RATE_11M_MASK (1<<IWL_RATE_11M_INDEX) +/* 3945 uCode API values for (legacy) bit rates, both OFDM and CCK */ enum { IWL_RATE_6M_PLCP = 13, IWL_RATE_9M_PLCP = 15, @@ -111,6 +115,7 @@ enum { IWL_RATE_11M_PLCP = 110, }; +/* MAC header values for bit rates */ enum { IWL_RATE_6M_IEEE = 12, IWL_RATE_9M_IEEE = 18, diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.h b/drivers/net/wireless/iwlwifi/iwl-4965-rs.h index 86f62d8..0c9552b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-rs.h @@ -42,7 +42,10 @@ struct iwl4965_rate_info { u8 next_rs_tgg; /* next rate used in TGG rs algo */ }; -/* For driver (not uCode API) */ +/* + * These serve as indexes into + * struct iwl4965_rate_info iwl4965_rates[IWL_RATE_COUNT]; + */ enum { IWL_RATE_1M_INDEX = 0, IWL_RATE_2M_INDEX, diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 496ca14..c0b6ac3 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -27,16 +27,6 @@ * *****************************************************************************/ -/* - * NOTE: This file (iwl-base.c) is used to build to multiple hardware targets - * by defining IWL to either 3945 or 4965. The Makefile used when building - * the base targets will create base-3945.o and base-4965.o - * - * The eventual goal is to move as many of the #if IWL / #endif blocks out of - * this file and into the hardware specific implementation files (iwl-XXXX.c) - * and leave only the common (non #ifdef sprinkled) code in this file - */ - #include <linux/kernel.h> #include <linux/module.h> #include <linux/version.h> @@ -75,9 +65,9 @@ static int iwl3945_tx_queue_update_write_ptr(struct iwl3945_priv *priv, /* module parameters */ static int iwl3945_param_disable_hw_scan; static int iwl3945_param_debug; -static int iwl3945_param_disable; /* def: enable radio */ -static int iwl3945_param_antenna; /* def: 0 = both antennas (use diversity) */ -int iwl3945_param_hwcrypto; /* def: using software encryption */ +static int iwl3945_param_disable; /* def: enable radio */ +static int iwl3945_param_antenna; /* def: 0 = both antennas (use diversity) */ +int iwl3945_param_hwcrypto; /* def: using software encryption */ static int iwl3945_param_qos_enable = 1; int iwl3945_param_queues_num = IWL_MAX_NUM_QUEUES; @@ -396,11 +386,7 @@ void iwl3945_tx_queue_free(struct iwl3945_priv *priv, struct iwl3945_tx_queue *t const u8 iwl3945_broadcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; /*************** STATION TABLE MANAGEMENT **** - * - * NOTE: This needs to be overhauled to better synchronize between - * how the iwl-4965.c is using iwl3945_hw_find_station vs. iwl-3945.c - * - * mac80211 should also be examined to determine if sta_info is duplicating + * mac80211 should be examined to determine if sta_info is duplicating * the functionality provided here */ @@ -956,12 +942,12 @@ static int iwl3945_check_rxon_cmd(struct iwl3945_rxon_cmd *rxon) } /** - * iwl3945_full_rxon_required - determine if RXON_ASSOC can be used in RXON commit + * iwl3945_full_rxon_required - check if full RXON (vs RXON_ASSOC) cmd is needed * @priv: staging_rxon is compared to active_rxon * - * If the RXON structure is changing sufficient to require a new - * tune or to clear and reset the RXON_FILTER_ASSOC_MSK then return 1 - * to indicate a new tune is required. + * If the RXON structure is changing enough to require a new tune, + * or is clearing the RXON_FILTER_ASSOC_MSK, then return 1 to indicate that + * a new tune (full RXON command, rather than RXON_ASSOC cmd) is required. */ static int iwl3945_full_rxon_required(struct iwl3945_priv *priv) { @@ -1235,7 +1221,7 @@ static int iwl3945_card_state_sync_callback(struct iwl3945_priv *priv, /* * CARD_STATE_CMD * - * Use: Sets the internal card state to enable, disable, or halt + * Use: Sets the device's internal card state to enable, disable, or halt * * When in the 'enable' state the card operates as normal. * When in the 'disable' state, the card enters into a low power mode. @@ -1589,14 +1575,9 @@ int iwl3945_eeprom_init(struct iwl3945_priv *priv) /** * iwl3945_report_frame - dump frame to syslog during debug sessions * - * hack this function to show different aspects of received frames, + * You may hack this function to show different aspects of received frames, * including selective frame dumps. * group100 parameter selects whether to show 1 out of 100 good frames. - * - * TODO: ieee80211_hdr stuff is common to 3945 and 4965, so frame type - * info output is okay, but some of this stuff (e.g. iwl3945_rx_frame_stats) - * is 3945-specific and gives bad output for 4965. Need to split the - * functionality, keep common stuff here. */ void iwl3945_report_frame(struct iwl3945_priv *priv, struct iwl3945_rx_packet *pkt, @@ -3771,13 +3752,10 @@ static void iwl3945_setup_rx_handlers(struct iwl3945_priv *priv) iwl3945_rx_pm_debug_statistics_notif; priv->rx_handlers[BEACON_NOTIFICATION] = iwl3945_rx_beacon_notif; - /* NOTE: iwl3945_rx_statistics is different based on whether - * the build is for the 3945 or the 4965. See the - * corresponding implementation in iwl-XXXX.c - * - * The same handler is used for both the REPLY to a - * discrete statistics request from the host as well as - * for the periodic statistics notification from the uCode + /* + * The same handler is used for both the REPLY to a discrete + * statistics request from the host as well as for the periodic + * statistics notifications (after received beacons) from the uCode. */ priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl3945_hw_rx_statistics; priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl3945_hw_rx_statistics; @@ -3791,7 +3769,7 @@ static void iwl3945_setup_rx_handlers(struct iwl3945_priv *priv) priv->rx_handlers[CARD_STATE_NOTIFICATION] = iwl3945_rx_card_state_notif; priv->rx_handlers[REPLY_TX] = iwl3945_rx_reply_tx; - /* Setup hardware specific Rx handlers */ + /* Set up hardware specific Rx handlers */ iwl3945_hw_rx_handler_setup(priv); } @@ -3863,10 +3841,10 @@ static void iwl3945_tx_cmd_complete(struct iwl3945_priv *priv, * The queue is empty (no good data) if WRITE = READ - 1, and is full if * WRITE = READ. * - * During initialization the host sets up the READ queue position to the first + * During initialization, the host sets up the READ queue position to the first * INDEX position, and WRITE to the last (READ - 1 wrapped) * - * When the firmware places a packet in a buffer it will advance the READ index + * When the firmware places a packet in a buffer, it will advance the READ index * and fire the RX interrupt. The driver can then query the READ index and * process as many packets as possible, moving the WRITE index forward as it * resets the Rx queue buffers with new memory. @@ -3888,16 +3866,16 @@ static void iwl3945_tx_cmd_complete(struct iwl3945_priv *priv, * * Driver sequence: * - * iwl3945_rx_queue_alloc() Allocates rx_free - * iwl3945_rx_replenish() Replenishes rx_free list from rx_used, and calls + * iwl3945_rx_queue_alloc() Allocates rx_free + * iwl3945_rx_replenish() Replenishes rx_free list from rx_used, and calls * iwl3945_rx_queue_restock - * iwl3945_rx_queue_restock() Moves available buffers from rx_free into Rx + * iwl3945_rx_queue_restock() Moves available buffers from rx_free into Rx * queue, updates firmware pointers, and updates * the WRITE index. If insufficient rx_free buffers * are available, schedules iwl3945_rx_replenish * * -- enable interrupts -- - * ISR - iwl3945_rx() Detach iwl3945_rx_mem_buffers from pool up to the + * ISR - iwl3945_rx() Detach iwl3945_rx_mem_buffers from pool up to the * READ INDEX, detaching the SKB from the pool. * Moves the packet buffer from queue to rx_used. * Calls iwl3945_rx_queue_restock to refill any empty @@ -3923,12 +3901,6 @@ static int iwl3945_rx_queue_space(const struct iwl3945_rx_queue *q) /** * iwl3945_rx_queue_update_write_ptr - Update the write pointer for the RX queue - * - * NOTE: This function has 3945 and 4965 specific code sections - * but is declared in base due to the majority of the - * implementation being the same (only a numeric constant is - * different) - * */ int iwl3945_rx_queue_update_write_ptr(struct iwl3945_priv *priv, struct iwl3945_rx_queue *q) { @@ -3969,9 +3941,7 @@ int iwl3945_rx_queue_update_write_ptr(struct iwl3945_priv *priv, struct iwl3945_ } /** - * iwl3945_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer pointer. - * - * NOTE: This function has 3945 and 4965 specific code paths in it. + * iwl3945_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr */ static inline __le32 iwl3945_dma_addr2rbd_ptr(struct iwl3945_priv *priv, dma_addr_t dma_addr) @@ -3982,9 +3952,9 @@ static inline __le32 iwl3945_dma_addr2rbd_ptr(struct iwl3945_priv *priv, /** * iwl3945_rx_queue_restock - refill RX queue from pre-allocated pool * - * If there are slots in the RX queue that need to be restocked, + * If there are slots in the RX queue that need to be restocked, * and we have free pre-allocated buffers, fill the ranks as much - * as we can pulling from rx_free. + * as we can, pulling from rx_free. * * This moves the 'write' index forward to catch up with 'processed', and * also updates the memory address in the firmware to reference the new @@ -4076,7 +4046,7 @@ void iwl3945_rx_replenish(void *data) } /* Assumes that the skb field of the buffers in 'pool' is kept accurate. - * If an SKB has been detached, the POOL needs to have it's SKB set to NULL + * If an SKB has been detached, the POOL needs to have its SKB set to NULL * This free routine walks the list of POOL entries and if SKB is set to * non NULL it is unmapped and freed */ @@ -4228,7 +4198,7 @@ int iwl3945_calc_sig_qual(int rssi_dbm, int noise_dbm) } /** - * iwl3945_rx_handle - Main entry function for receiving responses from the uCode + * iwl3945_rx_handle - Main entry function for receiving responses from uCode * * Uses the priv->rx_handlers callback function array to invoke * the appropriate handlers, including command responses, @@ -4253,7 +4223,7 @@ static void iwl3945_rx_handle(struct iwl3945_priv *priv) while (i != r) { rxb = rxq->queue[i]; - /* If an RXB doesn't have a queue slot associated with it + /* If an RXB doesn't have a Rx queue slot associated with it, * then a bug has been introduced in the queue refilling * routines -- catch it here */ BUG_ON(rxb == NULL); @@ -4292,8 +4262,8 @@ static void iwl3945_rx_handle(struct iwl3945_priv *priv) } if (reclaim) { - /* Invoke any callbacks, transfer the skb to caller, - * and fire off the (possibly) blocking iwl3945_send_cmd() + /* Invoke any callbacks, transfer the skb to caller, and + * fire off the (possibly) blocking iwl3945_send_cmd() * as we reclaim the driver command queue */ if (rxb && rxb->skb) iwl3945_tx_cmd_complete(priv, rxb); @@ -4667,7 +4637,8 @@ static void iwl3945_irq_tasklet(struct iwl3945_priv *priv) #ifdef CONFIG_IWL3945_DEBUG if (iwl3945_debug_level & IWL_DL_ISR) { - inta_mask = iwl3945_read32(priv, CSR_INT_MASK); /* just for debug */ + /* just for debug */ + inta_mask = iwl3945_read32(priv, CSR_INT_MASK); IWL_DEBUG_ISR("inta 0x%08x, enabled 0x%08x, fh 0x%08x\n", inta, inta_mask, inta_fh); } @@ -4895,11 +4866,11 @@ static const u8 iwl3945_eeprom_band_1[14] = { }; /* 5.2 GHz bands */ -static const u8 iwl3945_eeprom_band_2[] = { +static const u8 iwl3945_eeprom_band_2[] = { /* 4915-5080MHz */ 183, 184, 185, 187, 188, 189, 192, 196, 7, 8, 11, 12, 16 }; -static const u8 iwl3945_eeprom_band_3[] = { /* 5205-5320MHz */ +static const u8 iwl3945_eeprom_band_3[] = { /* 5170-5320MHz */ 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64 }; @@ -4923,7 +4894,7 @@ static void iwl3945_init_band_reference(const struct iwl3945_priv *priv, int ban *eeprom_ch_info = priv->eeprom.band_1_channels; *eeprom_ch_index = iwl3945_eeprom_band_1; break; - case 2: /* 5.2GHz band */ + case 2: /* 4.9GHz band */ *eeprom_ch_count = ARRAY_SIZE(iwl3945_eeprom_band_2); *eeprom_ch_info = priv->eeprom.band_2_channels; *eeprom_ch_index = iwl3945_eeprom_band_2; @@ -4933,12 +4904,12 @@ static void iwl3945_init_band_reference(const struct iwl3945_priv *priv, int ban *eeprom_ch_info = priv->eeprom.band_3_channels; *eeprom_ch_index = iwl3945_eeprom_band_3; break; - case 4: /* 5.2GHz band */ + case 4: /* 5.5GHz band */ *eeprom_ch_count = ARRAY_SIZE(iwl3945_eeprom_band_4); *eeprom_ch_info = priv->eeprom.band_4_channels; *eeprom_ch_index = iwl3945_eeprom_band_4; break; - case 5: /* 5.2GHz band */ + case 5: /* 5.7GHz band */ *eeprom_ch_count = ARRAY_SIZE(iwl3945_eeprom_band_5); *eeprom_ch_info = priv->eeprom.band_5_channels; *eeprom_ch_index = iwl3945_eeprom_band_5; @@ -5201,7 +5172,7 @@ static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv, int phymode, scan_ch->active_dwell = cpu_to_le16(active_dwell); scan_ch->passive_dwell = cpu_to_le16(passive_dwell); - /* Set power levels to defaults */ + /* Set txpower levels to defaults */ scan_ch->tpc.dsp_atten = 110; /* scan_pwr_info->tpc.dsp_atten; */ @@ -5211,8 +5182,8 @@ static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv, int phymode, else { scan_ch->tpc.tx_gain = ((1 << 5) | (5 << 3)); /* NOTE: if we were doing 6Mb OFDM for scans we'd use - * power level - scan_ch->tpc.tx_gain = ((1<<5) | (2 << 3)) | 3; + * power level: + * scan_ch->tpc.tx_gain = ((1<<5) | (2 << 3)) | 3; */ } @@ -5596,8 +5567,9 @@ static int iwl3945_verify_ucode(struct iwl3945_priv *priv) IWL_ERROR("NO VALID UCODE IMAGE IN INSTRUCTION SRAM!!\n"); - /* Show first several data entries in instruction SRAM. - * Selection of bootstrap image is arbitrary. */ + /* Since nothing seems to match, show first several data entries in + * instruction SRAM, so maybe visual inspection will give a clue. + * Selection of bootstrap image (vs. other images) is arbitrary. */ image = (__le32 *)priv->ucode_boot.v_addr; len = priv->ucode_boot.len; rc = iwl3945_verify_inst_full(priv, image, len); @@ -5689,7 +5661,7 @@ static int iwl3945_load_bsm(struct iwl3945_priv *priv) return -EINVAL; /* Tell bootstrap uCode where to find the "Initialize" uCode - * in host DRAM ... bits 31:0 for 3945, bits 35:4 for 4965. + * in host DRAM ... host DRAM physical address bits 31:0 for 3945. * NOTE: iwl3945_initialize_alive_start() will replace these values, * after the "initialize" uCode has run, to point to * runtime/protocol instructions and backup data cache. */ @@ -6014,12 +5986,8 @@ static int iwl3945_set_ucode_ptrs(struct iwl3945_priv *priv) * * Called after REPLY_ALIVE notification received from "initialize" uCode. * - * The 4965 "initialize" ALIVE reply contains calibration data for: - * Voltage, temperature, and MIMO tx gain correction, now stored in priv - * (3945 does not contain this data). - * * Tell "initialize" uCode to go ahead and load the runtime uCode. -*/ + */ static void iwl3945_init_alive_start(struct iwl3945_priv *priv) { /* Check alive response for "valid" sign from uCode */ @@ -6114,7 +6082,7 @@ static void iwl3945_alive_start(struct iwl3945_priv *priv) } else set_bit(STATUS_RF_KILL_HW, &priv->status); - /* After the ALIVE response, we can process host commands */ + /* After the ALIVE response, we can send commands to 3945 uCode */ set_bit(STATUS_ALIVE, &priv->status); /* Clear out the uCode error bit if it is set */ @@ -6170,7 +6138,7 @@ static void iwl3945_alive_start(struct iwl3945_priv *priv) memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN); } - /* Configure BT coexistence */ + /* Configure Bluetooth device coexistence support */ iwl3945_send_bt_config(priv); /* Configure the adapter for unassociated operation */ @@ -6353,7 +6321,7 @@ static int __iwl3945_up(struct iwl3945_priv *priv) /* start card; "initialize" will load runtime ucode */ iwl3945_nic_start(priv); - /* MAC Address location in EEPROM same for 3945/4965 */ + /* MAC Address location in EEPROM is same for 3945/4965 */ get_eeprom_mac(priv, priv->mac_addr); IWL_DEBUG_INFO("MAC address: %s\n", print_mac(mac, priv->mac_addr)); diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index a41839e..f2a3ecd 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -27,16 +27,6 @@ * *****************************************************************************/ -/* - * NOTE: This file (iwl-base.c) is used to build to multiple hardware targets - * by defining IWL to either 3945 or 4965. The Makefile used when building - * the base targets will create base-3945.o and base-4965.o - * - * The eventual goal is to move as many of the #if IWL / #endif blocks out of - * this file and into the hardware specific implementation files (iwl-XXXX.c) - * and leave only the common (non #ifdef sprinkled) code in this file - */ - #include <linux/kernel.h> #include <linux/module.h> #include <linux/version.h> @@ -75,9 +65,9 @@ static int iwl4965_tx_queue_update_write_ptr(struct iwl4965_priv *priv, /* module parameters */ static int iwl4965_param_disable_hw_scan; static int iwl4965_param_debug; -static int iwl4965_param_disable; /* def: enable radio */ -static int iwl4965_param_antenna; /* def: 0 = both antennas (use diversity) */ -int iwl4965_param_hwcrypto; /* def: using software encryption */ +static int iwl4965_param_disable; /* def: enable radio */ +static int iwl4965_param_antenna; /* def: 0 = both antennas (use diversity) */ +int iwl4965_param_hwcrypto; /* def: using software encryption */ static int iwl4965_param_qos_enable = 1; int iwl4965_param_queues_num = IWL_MAX_NUM_QUEUES; @@ -395,11 +385,7 @@ void iwl4965_tx_queue_free(struct iwl4965_priv *priv, struct iwl4965_tx_queue *t const u8 iwl4965_broadcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; /*************** STATION TABLE MANAGEMENT **** - * - * NOTE: This needs to be overhauled to better synchronize between - * how the iwl-4965.c is using iwl4965_hw_find_station vs. iwl-3945.c - * - * mac80211 should also be examined to determine if sta_info is duplicating + * mac80211 should be examined to determine if sta_info is duplicating * the functionality provided here */ @@ -482,8 +468,8 @@ u8 iwl4965_add_station_flags(struct iwl4965_priv *priv, const u8 *addr, int is_a } - /* These two conditions has the same outcome but keep them separate - since they have different meaning */ + /* These two conditions have the same outcome, but keep them separate + since they have different meanings */ if (unlikely(index == IWL_INVALID_STATION)) { spin_unlock_irqrestore(&priv->sta_lock, flags_spin); return index; @@ -843,8 +829,8 @@ int iwl4965_send_statistics_request(struct iwl4965_priv *priv) * iwl4965_rxon_add_station - add station into station table. * * there is only one AP station with id= IWL_AP_ID - * NOTE: mutex must be held before calling the this fnction -*/ + * NOTE: mutex must be held before calling this fnction + */ static int iwl4965_rxon_add_station(struct iwl4965_priv *priv, const u8 *addr, int is_ap) { @@ -866,7 +852,8 @@ static int iwl4965_rxon_add_station(struct iwl4965_priv *priv, * NOTE: Does not commit to the hardware; it sets appropriate bit fields * in the staging RXON flag structure based on the phymode */ -static int iwl4965_set_rxon_channel(struct iwl4965_priv *priv, u8 phymode, u16 channel) +static int iwl4965_set_rxon_channel(struct iwl4965_priv *priv, u8 phymode, + u16 channel) { if (!iwl4965_get_channel_info(priv, phymode, channel)) { IWL_DEBUG_INFO("Could not set channel to %d [%d]\n", @@ -965,12 +952,12 @@ static int iwl4965_check_rxon_cmd(struct iwl4965_rxon_cmd *rxon) } /** - * iwl4965_full_rxon_required - determine if RXON_ASSOC can be used in RXON commit + * iwl4965_full_rxon_required - check if full RXON (vs RXON_ASSOC) cmd is needed * @priv: staging_rxon is compared to active_rxon * - * If the RXON structure is changing sufficient to require a new - * tune or to clear and reset the RXON_FILTER_ASSOC_MSK then return 1 - * to indicate a new tune is required. + * If the RXON structure is changing enough to require a new tune, + * or is clearing the RXON_FILTER_ASSOC_MSK, then return 1 to indicate that + * a new tune (full RXON command, rather than RXON_ASSOC cmd) is required. */ static int iwl4965_full_rxon_required(struct iwl4965_priv *priv) { @@ -1267,7 +1254,7 @@ static int iwl4965_card_state_sync_callback(struct iwl4965_priv *priv, /* * CARD_STATE_CMD * - * Use: Sets the internal card state to enable, disable, or halt + * Use: Sets the device's internal card state to enable, disable, or halt * * When in the 'enable' state the card operates as normal. * When in the 'disable' state, the card enters into a low power mode. @@ -1643,14 +1630,12 @@ done: /** * iwl4965_report_frame - dump frame to syslog during debug sessions * - * hack this function to show different aspects of received frames, + * You may hack this function to show different aspects of received frames, * including selective frame dumps. * group100 parameter selects whether to show 1 out of 100 good frames. * - * TODO: ieee80211_hdr stuff is common to 3945 and 4965, so frame type - * info output is okay, but some of this stuff (e.g. iwl4965_rx_frame_stats) - * is 3945-specific and gives bad output for 4965. Need to split the - * functionality, keep common stuff here. + * TODO: This was originally written for 3945, need to audit for + * proper operation with 4965. */ void iwl4965_report_frame(struct iwl4965_priv *priv, struct iwl4965_rx_packet *pkt, @@ -2742,7 +2727,8 @@ static void iwl4965_build_tx_cmd_basic(struct iwl4965_priv *priv, cmd->cmd.tx.next_frame_len = 0; } -static int iwl4965_get_sta_id(struct iwl4965_priv *priv, struct ieee80211_hdr *hdr) +static int iwl4965_get_sta_id(struct iwl4965_priv *priv, + struct ieee80211_hdr *hdr) { int sta_id; u16 fc = le16_to_cpu(hdr->frame_control); @@ -4100,13 +4086,10 @@ static void iwl4965_setup_rx_handlers(struct iwl4965_priv *priv) iwl4965_rx_pm_debug_statistics_notif; priv->rx_handlers[BEACON_NOTIFICATION] = iwl4965_rx_beacon_notif; - /* NOTE: iwl4965_rx_statistics is different based on whether - * the build is for the 3945 or the 4965. See the - * corresponding implementation in iwl-XXXX.c - * - * The same handler is used for both the REPLY to a - * discrete statistics request from the host as well as - * for the periodic statistics notification from the uCode + /* + * The same handler is used for both the REPLY to a discrete + * statistics request from the host as well as for the periodic + * statistics notifications (after received beacons) from the uCode. */ priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl4965_hw_rx_statistics; priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl4965_hw_rx_statistics; @@ -4120,7 +4103,7 @@ static void iwl4965_setup_rx_handlers(struct iwl4965_priv *priv) priv->rx_handlers[CARD_STATE_NOTIFICATION] = iwl4965_rx_card_state_notif; priv->rx_handlers[REPLY_TX] = iwl4965_rx_reply_tx; - /* Setup hardware specific Rx handlers */ + /* Set up hardware specific Rx handlers */ iwl4965_hw_rx_handler_setup(priv); } @@ -4174,9 +4157,11 @@ static void iwl4965_tx_cmd_complete(struct iwl4965_priv *priv, /* * Rx theory of operation * - * The host allocates 32 DMA target addresses and passes the host address - * to the firmware at register IWL_RFDS_TABLE_LOWER + N * RFD_SIZE where N is - * 0 to 31 + * Driver allocates a circular buffer of Receive Buffer Descriptors (RBDs), + * each of which point to Receive Buffers to be filled by 4965. These get + * used not only for Rx frames, but for any command response or notification + * from the 4965. The driver and 4965 manage the Rx buffers by means + * of indexes into the circular buffer. * * Rx Queue Indexes * The host/firmware share two index registers for managing the Rx buffers. @@ -4192,10 +4177,10 @@ static void iwl4965_tx_cmd_complete(struct iwl4965_priv *priv, * The queue is empty (no good data) if WRITE = READ - 1, and is full if * WRITE = READ. * - * During initialization the host sets up the READ queue position to the first + * During initialization, the host sets up the READ queue position to the first * INDEX position, and WRITE to the last (READ - 1 wrapped) * - * When the firmware places a packet in a buffer it will advance the READ index + * When the firmware places a packet in a buffer, it will advance the READ index * and fire the RX interrupt. The driver can then query the READ index and * process as many packets as possible, moving the WRITE index forward as it * resets the Rx queue buffers with new memory. @@ -4217,16 +4202,16 @@ static void iwl4965_tx_cmd_complete(struct iwl4965_priv *priv, * * Driver sequence: * - * iwl4965_rx_queue_alloc() Allocates rx_free - * iwl4965_rx_replenish() Replenishes rx_free list from rx_used, and calls + * iwl4965_rx_queue_alloc() Allocates rx_free + * iwl4965_rx_replenish() Replenishes rx_free list from rx_used, and calls * iwl4965_rx_queue_restock - * iwl4965_rx_queue_restock() Moves available buffers from rx_free into Rx + * iwl4965_rx_queue_restock() Moves available buffers from rx_free into Rx * queue, updates firmware pointers, and updates * the WRITE index. If insufficient rx_free buffers * are available, schedules iwl4965_rx_replenish * * -- enable interrupts -- - * ISR - iwl4965_rx() Detach iwl4965_rx_mem_buffers from pool up to the + * ISR - iwl4965_rx() Detach iwl4965_rx_mem_buffers from pool up to the * READ INDEX, detaching the SKB from the pool. * Moves the packet buffer from queue to rx_used. * Calls iwl4965_rx_queue_restock to refill any empty @@ -4252,12 +4237,6 @@ static int iwl4965_rx_queue_space(const struct iwl4965_rx_queue *q) /** * iwl4965_rx_queue_update_write_ptr - Update the write pointer for the RX queue - * - * NOTE: This function has 3945 and 4965 specific code sections - * but is declared in base due to the majority of the - * implementation being the same (only a numeric constant is - * different) - * */ int iwl4965_rx_queue_update_write_ptr(struct iwl4965_priv *priv, struct iwl4965_rx_queue *q) { @@ -4298,9 +4277,7 @@ int iwl4965_rx_queue_update_write_ptr(struct iwl4965_priv *priv, struct iwl4965_ } /** - * iwl4965_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer pointer. - * - * NOTE: This function has 3945 and 4965 specific code paths in it. + * iwl4965_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr */ static inline __le32 iwl4965_dma_addr2rbd_ptr(struct iwl4965_priv *priv, dma_addr_t dma_addr) @@ -4312,9 +4289,9 @@ static inline __le32 iwl4965_dma_addr2rbd_ptr(struct iwl4965_priv *priv, /** * iwl4965_rx_queue_restock - refill RX queue from pre-allocated pool * - * If there are slots in the RX queue that need to be restocked, + * If there are slots in the RX queue that need to be restocked, * and we have free pre-allocated buffers, fill the ranks as much - * as we can pulling from rx_free. + * as we can, pulling from rx_free. * * This moves the 'write' index forward to catch up with 'processed', and * also updates the memory address in the firmware to reference the new @@ -4406,7 +4383,7 @@ void iwl4965_rx_replenish(void *data) } /* Assumes that the skb field of the buffers in 'pool' is kept accurate. - * If an SKB has been detached, the POOL needs to have it's SKB set to NULL + * If an SKB has been detached, the POOL needs to have its SKB set to NULL * This free routine walks the list of POOL entries and if SKB is set to * non NULL it is unmapped and freed */ @@ -4558,7 +4535,7 @@ int iwl4965_calc_sig_qual(int rssi_dbm, int noise_dbm) } /** - * iwl4965_rx_handle - Main entry function for receiving responses from the uCode + * iwl4965_rx_handle - Main entry function for receiving responses from uCode * * Uses the priv->rx_handlers callback function array to invoke * the appropriate handlers, including command responses, @@ -4583,7 +4560,7 @@ static void iwl4965_rx_handle(struct iwl4965_priv *priv) while (i != r) { rxb = rxq->queue[i]; - /* If an RXB doesn't have a queue slot associated with it + /* If an RXB doesn't have a Rx queue slot associated with it, * then a bug has been introduced in the queue refilling * routines -- catch it here */ BUG_ON(rxb == NULL); @@ -4625,8 +4602,8 @@ static void iwl4965_rx_handle(struct iwl4965_priv *priv) } if (reclaim) { - /* Invoke any callbacks, transfer the skb to caller, - * and fire off the (possibly) blocking iwl4965_send_cmd() + /* Invoke any callbacks, transfer the skb to caller, and + * fire off the (possibly) blocking iwl4965_send_cmd() * as we reclaim the driver command queue */ if (rxb && rxb->skb) iwl4965_tx_cmd_complete(priv, rxb); @@ -4992,7 +4969,8 @@ static void iwl4965_irq_tasklet(struct iwl4965_priv *priv) #ifdef CONFIG_IWL4965_DEBUG if (iwl4965_debug_level & IWL_DL_ISR) { - inta_mask = iwl4965_read32(priv, CSR_INT_MASK); /* just for debug */ + /* just for debug */ + inta_mask = iwl4965_read32(priv, CSR_INT_MASK); IWL_DEBUG_ISR("inta 0x%08x, enabled 0x%08x, fh 0x%08x\n", inta, inta_mask, inta_fh); } @@ -5037,7 +5015,7 @@ static void iwl4965_irq_tasklet(struct iwl4965_priv *priv) /* Safely ignore these bits for debug checks below */ inta &= ~(CSR_INT_BIT_MAC_CLK_ACTV | CSR_INT_BIT_ALIVE); - /* HW RF KILL switch toggled (4965 only) */ + /* HW RF KILL switch toggled */ if (inta & CSR_INT_BIT_RF_KILL) { int hw_rf_kill = 0; if (!(iwl4965_read32(priv, CSR_GP_CNTRL) & @@ -5058,7 +5036,7 @@ static void iwl4965_irq_tasklet(struct iwl4965_priv *priv) handled |= CSR_INT_BIT_RF_KILL; } - /* Chip got too hot and stopped itself (4965 only) */ + /* Chip got too hot and stopped itself */ if (inta & CSR_INT_BIT_CT_KILL) { IWL_ERROR("Microcode CT kill error detected.\n"); handled |= CSR_INT_BIT_CT_KILL; @@ -5213,11 +5191,11 @@ static const u8 iwl4965_eeprom_band_1[14] = { }; /* 5.2 GHz bands */ -static const u8 iwl4965_eeprom_band_2[] = { +static const u8 iwl4965_eeprom_band_2[] = { /* 4915-5080MHz */ 183, 184, 185, 187, 188, 189, 192, 196, 7, 8, 11, 12, 16 }; -static const u8 iwl4965_eeprom_band_3[] = { /* 5205-5320MHz */ +static const u8 iwl4965_eeprom_band_3[] = { /* 5170-5320MHz */ 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64 }; @@ -5237,7 +5215,8 @@ static u8 iwl4965_eeprom_band_7[] = { /* 5.2 FAT channel */ 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157 }; -static void iwl4965_init_band_reference(const struct iwl4965_priv *priv, int band, +static void iwl4965_init_band_reference(const struct iwl4965_priv *priv, + int band, int *eeprom_ch_count, const struct iwl4965_eeprom_channel **eeprom_ch_info, @@ -5249,7 +5228,7 @@ static void iwl4965_init_band_reference(const struct iwl4965_priv *priv, int ban *eeprom_ch_info = priv->eeprom.band_1_channels; *eeprom_ch_index = iwl4965_eeprom_band_1; break; - case 2: /* 5.2GHz band */ + case 2: /* 4.9GHz band */ *eeprom_ch_count = ARRAY_SIZE(iwl4965_eeprom_band_2); *eeprom_ch_info = priv->eeprom.band_2_channels; *eeprom_ch_index = iwl4965_eeprom_band_2; @@ -5259,22 +5238,22 @@ static void iwl4965_init_band_reference(const struct iwl4965_priv *priv, int ban *eeprom_ch_info = priv->eeprom.band_3_channels; *eeprom_ch_index = iwl4965_eeprom_band_3; break; - case 4: /* 5.2GHz band */ + case 4: /* 5.5GHz band */ *eeprom_ch_count = ARRAY_SIZE(iwl4965_eeprom_band_4); *eeprom_ch_info = priv->eeprom.band_4_channels; *eeprom_ch_index = iwl4965_eeprom_band_4; break; - case 5: /* 5.2GHz band */ + case 5: /* 5.7GHz band */ *eeprom_ch_count = ARRAY_SIZE(iwl4965_eeprom_band_5); *eeprom_ch_info = priv->eeprom.band_5_channels; *eeprom_ch_index = iwl4965_eeprom_band_5; break; - case 6: + case 6: /* 2.4GHz FAT channels */ *eeprom_ch_count = ARRAY_SIZE(iwl4965_eeprom_band_6); *eeprom_ch_info = priv->eeprom.band_24_channels; *eeprom_ch_index = iwl4965_eeprom_band_6; break; - case 7: + case 7: /* 5 GHz FAT channels */ *eeprom_ch_count = ARRAY_SIZE(iwl4965_eeprom_band_7); *eeprom_ch_info = priv->eeprom.band_52_channels; *eeprom_ch_index = iwl4965_eeprom_band_7; @@ -5543,7 +5522,8 @@ static int iwl4965_get_channels_for_scan(struct iwl4965_priv *priv, int phymode, scan_ch->channel = channels[i].chan; - ch_info = iwl4965_get_channel_info(priv, phymode, scan_ch->channel); + ch_info = iwl4965_get_channel_info(priv, phymode, + scan_ch->channel); if (!is_channel_valid(ch_info)) { IWL_DEBUG_SCAN("Channel %d is INVALID for this SKU.\n", scan_ch->channel); @@ -5565,7 +5545,7 @@ static int iwl4965_get_channels_for_scan(struct iwl4965_priv *priv, int phymode, scan_ch->active_dwell = cpu_to_le16(active_dwell); scan_ch->passive_dwell = cpu_to_le16(passive_dwell); - /* Set power levels to defaults */ + /* Set txpower levels to defaults */ scan_ch->tpc.dsp_atten = 110; /* scan_pwr_info->tpc.dsp_atten; */ @@ -5575,8 +5555,8 @@ static int iwl4965_get_channels_for_scan(struct iwl4965_priv *priv, int phymode, else { scan_ch->tpc.tx_gain = ((1 << 5) | (5 << 3)); /* NOTE: if we were doing 6Mb OFDM for scans we'd use - * power level - scan_ch->tpc.tx_gain = ((1<<5) | (2 << 3)) | 3; + * power level: + * scan_ch->tpc.tx_gain = ((1<<5) | (2 << 3)) | 3; */ } @@ -5853,7 +5833,8 @@ static void iwl4965_dealloc_ucode_pci(struct iwl4965_priv *priv) * iwl4965_verify_inst_full - verify runtime uCode image in card vs. host, * looking at all data. */ -static int iwl4965_verify_inst_full(struct iwl4965_priv *priv, __le32 * image, u32 len) +static int iwl4965_verify_inst_full(struct iwl4965_priv *priv, __le32 * image, + u32 len) { u32 val; u32 save_len = len; @@ -5978,8 +5959,9 @@ static int iwl4965_verify_ucode(struct iwl4965_priv *priv) IWL_ERROR("NO VALID UCODE IMAGE IN INSTRUCTION SRAM!!\n"); - /* Show first several data entries in instruction SRAM. - * Selection of bootstrap image is arbitrary. */ + /* Since nothing seems to match, show first several data entries in + * instruction SRAM, so maybe visual inspection will give a clue. + * Selection of bootstrap image (vs. other images) is arbitrary. */ image = (__le32 *)priv->ucode_boot.v_addr; len = priv->ucode_boot.len; rc = iwl4965_verify_inst_full(priv, image, len); @@ -6071,7 +6053,7 @@ static int iwl4965_load_bsm(struct iwl4965_priv *priv) return -EINVAL; /* Tell bootstrap uCode where to find the "Initialize" uCode - * in host DRAM ... bits 31:0 for 3945, bits 35:4 for 4965. + * in host DRAM ... host DRAM physical address bits 35:4 for 4965. * NOTE: iwl4965_initialize_alive_start() will replace these values, * after the "initialize" uCode has run, to point to * runtime/protocol instructions and backup data cache. */ @@ -6481,7 +6463,7 @@ static void iwl4965_alive_start(struct iwl4965_priv *priv) goto restart; } - /* After the ALIVE response, we can process host commands */ + /* After the ALIVE response, we can send host commands to 4965 uCode */ set_bit(STATUS_ALIVE, &priv->status); /* Clear out the uCode error bit if it is set */ @@ -6537,7 +6519,7 @@ static void iwl4965_alive_start(struct iwl4965_priv *priv) memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN); } - /* Configure BT coexistence */ + /* Configure Bluetooth device coexistence support */ iwl4965_send_bt_config(priv); /* Configure the adapter for unassociated operation */ @@ -6619,7 +6601,8 @@ static void __iwl4965_down(struct iwl4965_priv *priv) STATUS_FW_ERROR; spin_lock_irqsave(&priv->lock, flags); - iwl4965_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); + iwl4965_clear_bit(priv, CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); spin_unlock_irqrestore(&priv->lock, flags); iwl4965_hw_txq_ctx_stop(priv); @@ -6732,7 +6715,7 @@ static int __iwl4965_up(struct iwl4965_priv *priv) /* start card; "initialize" will load runtime ucode */ iwl4965_nic_start(priv); - /* MAC Address location in EEPROM same for 3945/4965 */ + /* MAC Address location in EEPROM is same for 3945/4965 */ get_eeprom_mac(priv, priv->mac_addr); IWL_DEBUG_INFO("MAC address: %s\n", print_mac(mac, priv->mac_addr)); -- 1.5.3.6 ^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 08/36] iwlwifi: Move is_legacy() macro family from iwl-4965-hw.h to iwl-4965-rs.h 2007-11-29 3:09 ` [PATCH 07/36] iwlwifi: clean up and clarify some comments after 3945/4965 split Zhu Yi @ 2007-11-29 3:09 ` Zhu Yi 2007-11-29 3:09 ` [PATCH 09/36] iwlwifi: Add comments to some driver data structures Zhu Yi 0 siblings, 1 reply; 36+ messages in thread From: Zhu Yi @ 2007-11-29 3:09 UTC (permalink / raw) To: linville; +Cc: linux-wireless, Ben Cahill, Zhu Yi From: Ben Cahill <ben.m.cahill@intel.com> Move is_legacy() macro family from iwl-4965-hw.h to iwl-4965-rs.h These macros are for driver's rate scaling implementation, and are not related to hardware or uCode API values (moved from iwl-4965-hw.h). Signed-off-by: Ben Cahill <ben.m.cahill@intel.com> Signed-off-by: Zhu Yi <yi.zhu@intel.com> --- drivers/net/wireless/iwlwifi/iwl-4965-hw.h | 7 ------- drivers/net/wireless/iwlwifi/iwl-4965-rs.h | 7 +++++++ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h index e106ec1..93e2dff 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h @@ -1036,13 +1036,6 @@ union iwl4965_tx_power_dual_stream { #define R_MCS_36M_DUAL_MSK 0x400 #define R_MCS_48M_DUAL_MSK 0x800 -#define is_legacy(tbl) (((tbl) == LQ_G) || ((tbl) == LQ_A)) -#define is_siso(tbl) (((tbl) == LQ_SISO)) -#define is_mimo(tbl) (((tbl) == LQ_MIMO)) -#define is_Ht(tbl) (is_siso(tbl) || is_mimo(tbl)) -#define is_a_band(tbl) (((tbl) == LQ_A)) -#define is_g_and(tbl) (((tbl) == LQ_G)) - /* Flow Handler Definitions */ /**********************/ diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.h b/drivers/net/wireless/iwlwifi/iwl-4965-rs.h index 0c9552b..31e21e2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-rs.h @@ -223,6 +223,13 @@ enum iwl4965_table_type { LQ_MAX, }; +#define is_legacy(tbl) (((tbl) == LQ_G) || ((tbl) == LQ_A)) +#define is_siso(tbl) (((tbl) == LQ_SISO)) +#define is_mimo(tbl) (((tbl) == LQ_MIMO)) +#define is_Ht(tbl) (is_siso(tbl) || is_mimo(tbl)) +#define is_a_band(tbl) (((tbl) == LQ_A)) +#define is_g_and(tbl) (((tbl) == LQ_G)) + /* 4965 has 2 antennas/chains for Tx (but 3 for Rx) */ enum iwl4965_antenna_type { ANT_NONE, -- 1.5.3.6 ^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 09/36] iwlwifi: Add comments to some driver data structures 2007-11-29 3:09 ` [PATCH 08/36] iwlwifi: Move is_legacy() macro family from iwl-4965-hw.h to iwl-4965-rs.h Zhu Yi @ 2007-11-29 3:09 ` Zhu Yi 2007-11-29 3:09 ` [PATCH 10/36] iwlwifi: Document 4965 rate_n_flags bits Zhu Yi 0 siblings, 1 reply; 36+ messages in thread From: Zhu Yi @ 2007-11-29 3:09 UTC (permalink / raw) To: linville; +Cc: linux-wireless, Ben Cahill, Zhu Yi From: Ben Cahill <ben.m.cahill@intel.com> Add comments to some driver data structures Remove unused "sched_retry" member from struct iwl3945_tx_queue Signed-off-by: Ben Cahill <ben.m.cahill@intel.com> Signed-off-by: Zhu Yi <yi.zhu@intel.com> --- drivers/net/wireless/iwlwifi/iwl-3945.h | 35 ++++++++++++++++-- drivers/net/wireless/iwlwifi/iwl-4965.h | 58 +++++++++++++++++++++++++++---- 2 files changed, 82 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 02040ef..607a1ed 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -130,6 +130,7 @@ struct iwl3945_queue { #define MAX_NUM_OF_TBS (20) +/* One for each TFD */ struct iwl3945_tx_info { struct ieee80211_tx_status status; struct sk_buff *skb[MAX_NUM_OF_TBS]; @@ -137,10 +138,15 @@ struct iwl3945_tx_info { /** * struct iwl3945_tx_queue - Tx Queue for DMA - * @need_update: need to update read/write index - * @shed_retry: queue is HT AGG enabled + * @q: generic Rx/Tx queue descriptor + * @bd: base of circular buffer of TFDs + * @cmd: array of command/Tx buffers + * @dma_addr_cmd: physical address of cmd/tx buffer array + * @txb: array of per-TFD driver data + * @need_update: indicates need to update read/write index * - * Queue consists of circular buffer of BD's and required locking structures. + * A Tx queue consists of circular buffer of BDs (a.k.a. TFDs, transmit frame + * descriptors) and required locking structures. */ struct iwl3945_tx_queue { struct iwl3945_queue q; @@ -149,7 +155,6 @@ struct iwl3945_tx_queue { dma_addr_t dma_addr_cmd; struct iwl3945_tx_info *txb; int need_update; - int sched_retry; int active; }; @@ -325,6 +330,13 @@ struct iwl3945_cmd_meta { } __attribute__ ((packed)); +/** + * struct iwl3945_cmd + * + * For allocation of the command and tx queues, this establishes the overall + * size of the largest command we send to uCode, except for a scan command + * (which is relatively huge; space is allocated separately). + */ struct iwl3945_cmd { struct iwl3945_cmd_meta meta; struct iwl3945_cmd_header hdr; @@ -522,6 +534,19 @@ struct iwl3945_ibss_seq { struct list_head list; }; +/** + * struct iwl4965_driver_hw_info + * @max_txq_num: Max # Tx queues supported + * @ac_queue_count: # Tx queues for EDCA Access Categories (AC) + * @tx_cmd_len: Size of Tx command (but not including frame itself) + * @max_rxq_size: Max # Rx frames in Rx queue (must be power-of-2) + * @rx_buffer_size: + * @max_rxq_log: Log-base-2 of max_rxq_size + * @max_stations: + * @bcast_sta_id: + * @shared_virt: Pointer to driver/uCode shared Tx Byte Counts and Rx status + * @shared_phys: Physical Pointer to Tx Byte Counts and Rx status + */ struct iwl3945_driver_hw_info { u16 max_txq_num; u16 ac_queue_count; @@ -857,6 +882,8 @@ struct iwl3945_priv { u16 last_seq_num; u16 last_frag_num; unsigned long last_packet_time; + + /* Hash table for finding stations in IBSS network */ struct list_head ibss_mac_hash[IWL_IBSS_MAC_HASH_SIZE]; /* eeprom */ diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index d0abbb3..3000148 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h @@ -129,6 +129,7 @@ struct iwl4965_queue { #define MAX_NUM_OF_TBS (20) +/* One for each TFD */ struct iwl4965_tx_info { struct ieee80211_tx_status status; struct sk_buff *skb[MAX_NUM_OF_TBS]; @@ -136,10 +137,16 @@ struct iwl4965_tx_info { /** * struct iwl4965_tx_queue - Tx Queue for DMA - * @need_update: need to update read/write index - * @shed_retry: queue is HT AGG enabled + * @q: generic Rx/Tx queue descriptor + * @bd: base of circular buffer of TFDs + * @cmd: array of command/Tx buffers + * @dma_addr_cmd: physical address of cmd/tx buffer array + * @txb: array of per-TFD driver data + * @need_update: indicates need to update read/write index + * @sched_retry: indicates queue is high-throughput aggregation (HT AGG) enabled * - * Queue consists of circular buffer of BD's and required locking structures. + * A Tx queue consists of circular buffer of BDs (a.k.a. TFDs, transmit frame + * descriptors) and required locking structures. */ struct iwl4965_tx_queue { struct iwl4965_queue q; @@ -332,9 +339,16 @@ struct iwl4965_cmd_meta { } __attribute__ ((packed)); +/** + * struct iwl4965_cmd + * + * For allocation of the command and tx queues, this establishes the overall + * size of the largest command we send to uCode, except for a scan command + * (which is relatively huge; space is allocated separately). + */ struct iwl4965_cmd { - struct iwl4965_cmd_meta meta; - struct iwl4965_cmd_header hdr; + struct iwl4965_cmd_meta meta; /* driver data */ + struct iwl4965_cmd_header hdr; /* uCode API */ union { struct iwl4965_addsta_cmd addsta; struct iwl4965_led_cmd led; @@ -436,6 +450,20 @@ struct iwl4965_rx_queue { #ifdef CONFIG_IWL4965_HT #ifdef CONFIG_IWL4965_HT_AGG +/** + * struct iwl4965_ht_agg -- aggregation status while waiting for block-ack + * @txq_id: Tx queue used for Tx attempt + * @frame_count: # frames attempted by Tx command + * @wait_for_ba: Expect block-ack before next Tx reply + * @start_idx: Index of 1st Transmit Frame Descriptor (TFD) in Tx window + * @bitmap0: Low order bitmap, one bit for each frame pending ACK in Tx window + * @bitmap1: High order, one bit for each frame pending ACK in Tx window + * @rate_n_flags: Rate at which Tx was attempted + * + * If REPLY_TX indicates that aggregation was attempted, driver must wait + * for block ack (REPLY_COMPRESSED_BA). This struct stores tx reply info + * until block ack arrives. + */ struct iwl4965_ht_agg { u16 txq_id; u16 frame_count; @@ -566,6 +594,19 @@ struct iwl4965_ibss_seq { struct list_head list; }; +/** + * struct iwl4965_driver_hw_info + * @max_txq_num: Max # Tx queues supported + * @ac_queue_count: # Tx queues for EDCA Access Categories (AC) + * @tx_cmd_len: Size of Tx command (but not including frame itself) + * @max_rxq_size: Max # Rx frames in Rx queue (must be power-of-2) + * @rx_buffer_size: + * @max_rxq_log: Log-base-2 of max_rxq_size + * @max_stations: + * @bcast_sta_id: + * @shared_virt: Pointer to driver/uCode shared Tx Byte Counts and Rx status + * @shared_phys: Physical Pointer to Tx Byte Counts and Rx status + */ struct iwl4965_driver_hw_info { u16 max_txq_num; u16 ac_queue_count; @@ -1149,10 +1190,11 @@ struct iwl4965_priv { u8 call_post_assoc_from_beacon; u8 assoc_station_added; u8 use_ant_b_for_management_frame; /* Tx antenna selection */ - /* HT variables */ + + /* High Throughput (HT) variables */ u8 is_dup; u8 is_ht_enabled; - u8 channel_width; /* 0=20MHZ, 1=40MHZ */ + u8 channel_width; /* 0=20MHZ, 1=40MHZ supported */ u8 current_channel_width; u8 valid_antenna; /* Bit mask of antennas actually connected */ #ifdef CONFIG_IWL4965_SENSITIVITY @@ -1229,6 +1271,8 @@ struct iwl4965_priv { u16 last_seq_num; u16 last_frag_num; unsigned long last_packet_time; + + /* Hash table for finding stations in IBSS network */ struct list_head ibss_mac_hash[IWL_IBSS_MAC_HASH_SIZE]; /* eeprom */ -- 1.5.3.6 ^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 10/36] iwlwifi: Document 4965 rate_n_flags bits 2007-11-29 3:09 ` [PATCH 09/36] iwlwifi: Add comments to some driver data structures Zhu Yi @ 2007-11-29 3:09 ` Zhu Yi 2007-11-29 3:09 ` [PATCH 11/36] iwlwifi: Document Rx calibration Zhu Yi 0 siblings, 1 reply; 36+ messages in thread From: Zhu Yi @ 2007-11-29 3:09 UTC (permalink / raw) To: linville; +Cc: linux-wireless, Ben Cahill, Zhu Yi From: Ben Cahill <ben.m.cahill@intel.com> Document 4965 rate_n_flags bits Signed-off-by: Ben Cahill <ben.m.cahill@intel.com> Signed-off-by: Zhu Yi <yi.zhu@intel.com> --- drivers/net/wireless/iwlwifi/iwl-4965-commands.h | 98 +++++++++++++++++++--- drivers/net/wireless/iwlwifi/iwl-4965.h | 30 ++----- 2 files changed, 92 insertions(+), 36 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-commands.h b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h index 2703c52..00d4ab7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h @@ -141,7 +141,8 @@ enum { /****************************************************************************** * (0) - * Header + * Commonly used structures and definitions: + * Command header, rate_n_flags * *****************************************************************************/ @@ -167,6 +168,89 @@ struct iwl4965_cmd_header { u8 data[0]; } __attribute__ ((packed)); +/** + * 4965 rate_n_flags bit fields + * + * rate_n_flags format is used in following 4965 commands: + * REPLY_4965_RX (response only) + * REPLY_TX (both command and response) + * REPLY_TX_LINK_QUALITY_CMD + * + * High-throughput (HT) rate format for bits 7:0 (bit 8 must be "1"): + * 2-0: 0) 6 Mbps + * 1) 12 Mbps + * 2) 18 Mbps + * 3) 24 Mbps + * 4) 36 Mbps + * 5) 48 Mbps + * 6) 54 Mbps + * 7) 60 Mbps + * + * 3: 0) Single stream (SISO) + * 1) Dual stream (MIMO) + * + * 5: Value of 0x20 in bits 7:0 indicates 6 Mbps FAT duplicate data + * + * Legacy OFDM rate format for bits 7:0 (bit 8 must be "0", bit 9 "0"): + * 3-0: 0xD) 6 Mbps + * 0xF) 9 Mbps + * 0x5) 12 Mbps + * 0x7) 18 Mbps + * 0x9) 24 Mbps + * 0xB) 36 Mbps + * 0x1) 48 Mbps + * 0x3) 54 Mbps + * + * Legacy CCK rate format for bits 7:0 (bit 8 must be "0", bit 9 "1"): + * 3-0: 10) 1 Mbps + * 20) 2 Mbps + * 55) 5.5 Mbps + * 110) 11 Mbps + */ +#define RATE_MCS_CODE_MSK 0x7 +#define RATE_MCS_MIMO_POS 3 +#define RATE_MCS_MIMO_MSK 0x8 +#define RATE_MCS_HT_DUP_POS 5 +#define RATE_MCS_HT_DUP_MSK 0x20 + +/* (1) HT format, (0) legacy format in bits 7:0 */ +#define RATE_MCS_FLAGS_POS 8 +#define RATE_MCS_HT_POS 8 +#define RATE_MCS_HT_MSK 0x100 + +/* (1) CCK, (0) OFDM. HT (bit 8) must be "0" for this bit to be valid */ +#define RATE_MCS_CCK_POS 9 +#define RATE_MCS_CCK_MSK 0x200 + +/* (1) Use Green Field preamble */ +#define RATE_MCS_GF_POS 10 +#define RATE_MCS_GF_MSK 0x400 + +/* (1) Use 40Mhz FAT channel width, (0) use 20 MHz legacy channel width */ +#define RATE_MCS_FAT_POS 11 +#define RATE_MCS_FAT_MSK 0x800 + +/* (1) Duplicate data on both 20MHz channels. FAT (bit 11) must be set. */ +#define RATE_MCS_DUP_POS 12 +#define RATE_MCS_DUP_MSK 0x1000 + +/* (1) Short guard interval (0.4 usec), (0) normal GI (0.8 usec) */ +#define RATE_MCS_SGI_POS 13 +#define RATE_MCS_SGI_MSK 0x2000 + +/** + * rate_n_flags Tx antenna masks (4965 has 2 transmitters): + * bit14:15 01 B inactive, A active + * 10 B active, A inactive + * 11 Both active + */ +#define RATE_MCS_ANT_A_POS 14 +#define RATE_MCS_ANT_B_POS 15 +#define RATE_MCS_ANT_A_MSK 0x4000 +#define RATE_MCS_ANT_B_MSK 0x8000 +#define RATE_MCS_ANT_AB_MSK 0xc000 + + /****************************************************************************** * (0a) * Alive and Error Commands & Responses: @@ -452,18 +536,6 @@ struct iwl4965_qosparam_cmd { #define STA_MODIFY_DELBA_TID_MSK 0x10 #define BUILD_RAxTID(sta_id, tid) (((sta_id) << 4) + (tid)) -/* - * Antenna masks: - * bit14:15 01 B inactive, A active - * 10 B active, A inactive - * 11 Both active - */ -#define RATE_MCS_ANT_A_POS 14 -#define RATE_MCS_ANT_B_POS 15 -#define RATE_MCS_ANT_A_MSK 0x4000 -#define RATE_MCS_ANT_B_MSK 0x8000 -#define RATE_MCS_ANT_AB_MSK 0xc000 - struct iwl4965_keyinfo { __le16 key_flags; u8 tkip_rx_tsc_byte2; /* TSC[2] for key mix ph1 detection */ diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index 3000148..af34974 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h @@ -883,6 +883,11 @@ struct iwl4965_traffic_load { }; #ifdef CONFIG_IWL4965_HT_AGG +/** + * struct iwl4965_agg_control + * @requested_ba: bit map of tids requesting aggregation/block-ack + * @granted_ba: bit map of tids granted aggregation/block-ack + */ struct iwl4965_agg_control { unsigned long next_retry; u32 wait_for_agg_status; @@ -1054,29 +1059,8 @@ struct iwl4965_chain_noise_data { u8 radio_write; }; -/* IWL4965 */ -#define RATE_MCS_CODE_MSK 0x7 -#define RATE_MCS_MIMO_POS 3 -#define RATE_MCS_MIMO_MSK 0x8 -#define RATE_MCS_HT_DUP_POS 5 -#define RATE_MCS_HT_DUP_MSK 0x20 -#define RATE_MCS_FLAGS_POS 8 -#define RATE_MCS_HT_POS 8 -#define RATE_MCS_HT_MSK 0x100 -#define RATE_MCS_CCK_POS 9 -#define RATE_MCS_CCK_MSK 0x200 -#define RATE_MCS_GF_POS 10 -#define RATE_MCS_GF_MSK 0x400 - -#define RATE_MCS_FAT_POS 11 -#define RATE_MCS_FAT_MSK 0x800 -#define RATE_MCS_DUP_POS 12 -#define RATE_MCS_DUP_MSK 0x1000 -#define RATE_MCS_SGI_POS 13 -#define RATE_MCS_SGI_MSK 0x2000 - -#define EEPROM_SEM_TIMEOUT 10 -#define EEPROM_SEM_RETRY_LIMIT 1000 +#define EEPROM_SEM_TIMEOUT 10 /* milliseconds */ +#define EEPROM_SEM_RETRY_LIMIT 1000 /* number of attempts (not time) */ #ifdef CONFIG_IWL4965_SPECTRUM_MEASUREMENT -- 1.5.3.6 ^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 11/36] iwlwifi: Document Rx calibration 2007-11-29 3:09 ` [PATCH 10/36] iwlwifi: Document 4965 rate_n_flags bits Zhu Yi @ 2007-11-29 3:09 ` Zhu Yi [not found] ` <1196305816-23023-13-git-send-email-yi.zhu@intel.com> 0 siblings, 1 reply; 36+ messages in thread From: Zhu Yi @ 2007-11-29 3:09 UTC (permalink / raw) To: linville; +Cc: linux-wireless, Ben Cahill, Zhu Yi From: Ben Cahill <ben.m.cahill@intel.com> Document Rx calibration Signed-off-by: Ben Cahill <ben.m.cahill@intel.com> Signed-off-by: Zhu Yi <yi.zhu@intel.com> --- drivers/net/wireless/iwlwifi/iwl-4965-commands.h | 267 +++++++++++++++++++++- drivers/net/wireless/iwlwifi/iwl-4965.c | 1 + drivers/net/wireless/iwlwifi/iwl-4965.h | 18 -- 3 files changed, 261 insertions(+), 25 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-commands.h b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h index 00d4ab7..575a065 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h @@ -1573,25 +1573,278 @@ struct iwl4965_missed_beacon_notif { __le32 num_recvd_beacons; } __attribute__ ((packed)); + /****************************************************************************** * (11) * Rx Calibration Commands: * + * With the uCode used for open source drivers, most Tx calibration (except + * for Tx Power) and most Rx calibration is done by uCode during the + * "initialize" phase of uCode boot. Driver must calibrate only: + * + * 1) Tx power (depends on temperature), described elsewhere + * 2) Receiver gain balance (optimize MIMO, and detect disconnected antennas) + * 3) Receiver sensitivity (to optimize signal detection) + * *****************************************************************************/ -#define PHY_CALIBRATE_DIFF_GAIN_CMD (7) -#define HD_TABLE_SIZE (11) +/** + * SENSITIVITY_CMD = 0xa8 (command, has simple generic response) + * + * This command sets up the Rx signal detector for a sensitivity level that + * is high enough to lock onto all signals within the associated network, + * but low enough to ignore signals that are below a certain threshold, so as + * not to have too many "false alarms". False alarms are signals that the + * Rx DSP tries to lock onto, but then discards after determining that they + * are noise. + * + * The optimum number of false alarms is between 5 and 50 per 200 TUs + * (200 * 1024 uSecs, i.e. 204.8 milliseconds) of actual Rx time (i.e. + * time listening, not transmitting). Driver must adjust sensitivity so that + * the ratio of actual false alarms to actual Rx time falls within this range. + * + * While associated, uCode delivers STATISTICS_NOTIFICATIONs after each + * received beacon. These provide information to the driver to analyze the + * sensitivity. Don't analyze statistics that come in from scanning, or any + * other non-associated-network source. Pertinent statistics include: + * + * From "general" statistics (struct statistics_rx_non_phy): + * + * (beacon_energy_[abc] & 0x0FF00) >> 8 (unsigned, higher value is lower level) + * Measure of energy of desired signal. Used for establishing a level + * below which the device does not detect signals. + * + * (beacon_silence_rssi_[abc] & 0x0FF00) >> 8 (unsigned, units in dB) + * Measure of background noise in silent period after beacon. + * + * channel_load + * uSecs of actual Rx time during beacon period (varies according to + * how much time was spent transmitting). + * + * From "cck" and "ofdm" statistics (struct statistics_rx_phy), separately: + * + * false_alarm_cnt + * Signal locks abandoned early (before phy-level header). + * + * plcp_err + * Signal locks abandoned late (during phy-level header). + * + * NOTE: Both false_alarm_cnt and plcp_err increment monotonically from + * beacon to beacon, i.e. each value is an accumulation of all errors + * before and including the latest beacon. Values will wrap around to 0 + * after counting up to 2^32 - 1. Driver must differentiate vs. + * previous beacon's values to determine # false alarms in the current + * beacon period. + * + * Total number of false alarms = false_alarms + plcp_errs + * + * For OFDM, adjust the following table entries in struct iwl_sensitivity_cmd + * (notice that the start points for OFDM are at or close to settings for + * maximum sensitivity): + * + * START / MIN / MAX + * HD_AUTO_CORR32_X1_TH_ADD_MIN_INDEX 90 / 85 / 120 + * HD_AUTO_CORR32_X1_TH_ADD_MIN_MRC_INDEX 170 / 170 / 210 + * HD_AUTO_CORR32_X4_TH_ADD_MIN_INDEX 105 / 105 / 140 + * HD_AUTO_CORR32_X4_TH_ADD_MIN_MRC_INDEX 220 / 220 / 270 + * + * If actual rate of OFDM false alarms (+ plcp_errors) is too high + * (greater than 50 for each 204.8 msecs listening), reduce sensitivity + * by *adding* 1 to all 4 of the table entries above, up to the max for + * each entry. Conversely, if false alarm rate is too low (less than 5 + * for each 204.8 msecs listening), *subtract* 1 from each entry to + * increase sensitivity. + * + * For CCK sensitivity, keep track of the following: + * + * 1). 20-beacon history of maximum background noise, indicated by + * (beacon_silence_rssi_[abc] & 0x0FF00), units in dB, across the + * 3 receivers. For any given beacon, the "silence reference" is + * the maximum of last 60 samples (20 beacons * 3 receivers). + * + * 2). 10-beacon history of strongest signal level, as indicated + * by (beacon_energy_[abc] & 0x0FF00) >> 8, across the 3 receivers, + * i.e. the strength of the signal through the best receiver at the + * moment. These measurements are "upside down", with lower values + * for stronger signals, so max energy will be *minimum* value. + * + * Then for any given beacon, the driver must determine the *weakest* + * of the strongest signals; this is the minimum level that needs to be + * successfully detected, when using the best receiver at the moment. + * "Max cck energy" is the maximum (higher value means lower energy!) + * of the last 10 minima. Once this is determined, driver must add + * a little margin by adding "6" to it. + * + * 3). Number of consecutive beacon periods with too few false alarms. + * Reset this to 0 at the first beacon period that falls within the + * "good" range (5 to 50 false alarms per 204.8 milliseconds rx). + * + * Then, adjust the following CCK table entries in struct iwl_sensitivity_cmd + * (notice that the start points for CCK are at maximum sensitivity): + * + * START / MIN / MAX + * HD_AUTO_CORR40_X4_TH_ADD_MIN_INDEX 125 / 125 / 200 + * HD_AUTO_CORR40_X4_TH_ADD_MIN_MRC_INDEX 200 / 200 / 400 + * HD_MIN_ENERGY_CCK_DET_INDEX 100 / 0 / 100 + * + * If actual rate of CCK false alarms (+ plcp_errors) is too high + * (greater than 50 for each 204.8 msecs listening), method for reducing + * sensitivity is: + * + * 1) *Add* 3 to value in HD_AUTO_CORR40_X4_TH_ADD_MIN_MRC_INDEX, + * up to max 400. + * + * 2) If current value in HD_AUTO_CORR40_X4_TH_ADD_MIN_INDEX is < 160, + * sensitivity has been reduced a significant amount; bring it up to + * a moderate 161. Otherwise, *add* 3, up to max 200. + * + * 3) a) If current value in HD_AUTO_CORR40_X4_TH_ADD_MIN_INDEX is > 160, + * sensitivity has been reduced only a moderate or small amount; + * *subtract* 2 from value in HD_MIN_ENERGY_CCK_DET_INDEX, + * down to min 0. Otherwise (if gain has been significantly reduced), + * don't change the HD_MIN_ENERGY_CCK_DET_INDEX value. + * + * b) Save a snapshot of the "silence reference". + * + * If actual rate of CCK false alarms (+ plcp_errors) is too low + * (less than 5 for each 204.8 msecs listening), method for increasing + * sensitivity is used only if: + * + * 1a) Previous beacon did not have too many false alarms + * 1b) AND difference between previous "silence reference" and current + * "silence reference" (prev - current) is 2 or more, + * OR 2) 100 or more consecutive beacon periods have had rate of + * less than 5 false alarms per 204.8 milliseconds rx time. + * + * Method for increasing sensitivity: + * + * 1) *Subtract* 3 from value in HD_AUTO_CORR40_X4_TH_ADD_MIN_INDEX, + * down to min 125. + * + * 2) *Subtract* 3 from value in HD_AUTO_CORR40_X4_TH_ADD_MIN_MRC_INDEX, + * down to min 200. + * + * 3) *Add* 2 to value in HD_MIN_ENERGY_CCK_DET_INDEX, up to max 100. + * + * If actual rate of CCK false alarms (+ plcp_errors) is within good range + * (between 5 and 50 for each 204.8 msecs listening): + * + * 1) Save a snapshot of the silence reference. + * + * 2) If previous beacon had too many CCK false alarms (+ plcp_errors), + * give some extra margin to energy threshold by *subtracting* 8 + * from value in HD_MIN_ENERGY_CCK_DET_INDEX. + * + * For all cases (too few, too many, good range), make sure that the CCK + * detection threshold (energy) is below the energy level for robust + * detection over the past 10 beacon periods, the "Max cck energy". + * Lower values mean higher energy; this means making sure that the value + * in HD_MIN_ENERGY_CCK_DET_INDEX is at or *above* "Max cck energy". + * + * Driver should set the following entries to fixed values: + * + * HD_MIN_ENERGY_OFDM_DET_INDEX 100 + * HD_BARKER_CORR_TH_ADD_MIN_INDEX 190 + * HD_BARKER_CORR_TH_ADD_MIN_MRC_INDEX 390 + * HD_OFDM_ENERGY_TH_IN_INDEX 62 + */ + +/* + * Table entries in SENSITIVITY_CMD (struct iwl4965_sensitivity_cmd) + */ +#define HD_TABLE_SIZE (11) /* number of entries */ +#define HD_MIN_ENERGY_CCK_DET_INDEX (0) /* table indexes */ +#define HD_MIN_ENERGY_OFDM_DET_INDEX (1) +#define HD_AUTO_CORR32_X1_TH_ADD_MIN_INDEX (2) +#define HD_AUTO_CORR32_X1_TH_ADD_MIN_MRC_INDEX (3) +#define HD_AUTO_CORR40_X4_TH_ADD_MIN_MRC_INDEX (4) +#define HD_AUTO_CORR32_X4_TH_ADD_MIN_INDEX (5) +#define HD_AUTO_CORR32_X4_TH_ADD_MIN_MRC_INDEX (6) +#define HD_BARKER_CORR_TH_ADD_MIN_INDEX (7) +#define HD_BARKER_CORR_TH_ADD_MIN_MRC_INDEX (8) +#define HD_AUTO_CORR40_X4_TH_ADD_MIN_INDEX (9) +#define HD_OFDM_ENERGY_TH_IN_INDEX (10) + +/* Control field in struct iwl4965_sensitivity_cmd */ +#define SENSITIVITY_CMD_CONTROL_DEFAULT_TABLE __constant_cpu_to_le16(0) +#define SENSITIVITY_CMD_CONTROL_WORK_TABLE __constant_cpu_to_le16(1) +/** + * struct iwl4965_sensitivity_cmd + * @control: (1) updates working table, (0) updates default table + * @table: energy threshold values, use HD_* as index into table + * + * Always use "1" in "control" to update uCode's working table and DSP. + */ struct iwl4965_sensitivity_cmd { - __le16 control; - __le16 table[HD_TABLE_SIZE]; + __le16 control; /* always use "1" */ + __le16 table[HD_TABLE_SIZE]; /* use HD_* as index */ } __attribute__ ((packed)); + +/** + * REPLY_PHY_CALIBRATION_CMD = 0xb0 (command, has simple generic response) + * + * This command sets the relative gains of 4965's 3 radio receiver chains. + * + * After the first association, driver should accumulate signal and noise + * statistics from the STATISTICS_NOTIFICATIONs that follow the first 20 + * beacons from the associated network (don't collect statistics that come + * in from scanning, or any other non-network source). + * + * DISCONNECTED ANTENNA: + * + * Driver should determine which antennas are actually connected, by comparing + * average beacon signal levels for the 3 Rx chains. Accumulate (add) the + * following values over 20 beacons, one accumulator for each of the chains + * a/b/c, from struct statistics_rx_non_phy: + * + * beacon_rssi_[abc] & 0x0FF (unsigned, units in dB) + * + * Find the strongest signal from among a/b/c. Compare the other two to the + * strongest. If any signal is more than 15 dB (times 20, unless you + * divide the accumulated values by 20) below the strongest, the driver + * considers that antenna to be disconnected, and should not try to use that + * antenna/chain for Rx or Tx. If both A and B seem to be disconnected, + * driver should declare the stronger one as connected, and attempt to use it + * (A and B are the only 2 Tx chains!). + * + * + * RX BALANCE: + * + * Driver should balance the 3 receivers (but just the ones that are connected + * to antennas, see above) for gain, by comparing the average signal levels + * detected during the silence after each beacon (background noise). + * Accumulate (add) the following values over 20 beacons, one accumulator for + * each of the chains a/b/c, from struct statistics_rx_non_phy: + * + * beacon_silence_rssi_[abc] & 0x0FF (unsigned, units in dB) + * + * Find the weakest background noise level from among a/b/c. This Rx chain + * will be the reference, with 0 gain adjustment. Attenuate other channels by + * finding noise difference: + * + * (accum_noise[i] - accum_noise[reference]) / 30 + * + * The "30" adjusts the dB in the 20 accumulated samples to units of 1.5 dB. + * For use in diff_gain_[abc] fields of struct iwl_calibration_cmd, the + * driver should limit the difference results to a range of 0-3 (0-4.5 dB), + * and set bit 2 to indicate "reduce gain". The value for the reference + * (weakest) chain should be "0". + * + * diff_gain_[abc] bit fields: + * 2: (1) reduce gain, (0) increase gain + * 1-0: amount of gain, units of 1.5 dB + */ + +/* "Differential Gain" opcode used in REPLY_PHY_CALIBRATION_CMD. */ +#define PHY_CALIBRATE_DIFF_GAIN_CMD (7) + struct iwl4965_calibration_cmd { - u8 opCode; - u8 flags; + u8 opCode; /* PHY_CALIBRATE_DIFF_GAIN_CMD (7) */ + u8 flags; /* not used */ __le16 reserved; - s8 diff_gain_a; + s8 diff_gain_a; /* see above */ s8 diff_gain_b; s8 diff_gain_c; u8 reserved1; diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 7d95de9..d44166a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -1068,6 +1068,7 @@ static int iwl4965_sensitivity_write(struct iwl4965_priv *priv, u8 flags) data->auto_corr_cck, data->auto_corr_cck_mrc, data->nrg_th_cck); + /* Update uCode's "work" table, and copy it to DSP */ cmd.control = SENSITIVITY_CMD_CONTROL_WORK_TABLE; if (flags & CMD_ASYNC) diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index af34974..321767f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h @@ -924,22 +924,6 @@ struct iwl4965_lq_mngr { #define CAL_NUM_OF_BEACONS 20 #define MAXIMUM_ALLOWED_PATHLOSS 15 -/* Param table within SENSITIVITY_CMD */ -#define HD_MIN_ENERGY_CCK_DET_INDEX (0) -#define HD_MIN_ENERGY_OFDM_DET_INDEX (1) -#define HD_AUTO_CORR32_X1_TH_ADD_MIN_INDEX (2) -#define HD_AUTO_CORR32_X1_TH_ADD_MIN_MRC_INDEX (3) -#define HD_AUTO_CORR40_X4_TH_ADD_MIN_MRC_INDEX (4) -#define HD_AUTO_CORR32_X4_TH_ADD_MIN_INDEX (5) -#define HD_AUTO_CORR32_X4_TH_ADD_MIN_MRC_INDEX (6) -#define HD_BARKER_CORR_TH_ADD_MIN_INDEX (7) -#define HD_BARKER_CORR_TH_ADD_MIN_MRC_INDEX (8) -#define HD_AUTO_CORR40_X4_TH_ADD_MIN_INDEX (9) -#define HD_OFDM_ENERGY_TH_IN_INDEX (10) - -#define SENSITIVITY_CMD_CONTROL_DEFAULT_TABLE __constant_cpu_to_le16(0) -#define SENSITIVITY_CMD_CONTROL_WORK_TABLE __constant_cpu_to_le16(1) - #define CHAIN_NOISE_MAX_DELTA_GAIN_CODE 3 #define MAX_FA_OFDM 50 @@ -967,8 +951,6 @@ struct iwl4965_lq_mngr { #define AUTO_CORR_STEP_CCK 3 #define AUTO_CORR_MAX_TH_CCK 160 -#define NRG_ALG 0 -#define AUTO_CORR_ALG 1 #define NRG_DIFF 2 #define NRG_STEP_CCK 2 #define NRG_MARGIN 8 -- 1.5.3.6 ^ permalink raw reply related [flat|nested] 36+ messages in thread
[parent not found: <1196305816-23023-13-git-send-email-yi.zhu@intel.com>]
* [PATCH 13/36] iwlwifi: clean up some unused definitions in iwl-4965.h and iwl-3945.h [not found] ` <1196305816-23023-13-git-send-email-yi.zhu@intel.com> @ 2007-11-29 3:09 ` Zhu Yi 2007-11-29 3:09 ` [PATCH 14/36] iwlwifi: add comments, mostly on Tx queues Zhu Yi 2007-11-29 3:16 ` [PATCH 12/36] iwlwifi: Partially clean-up, add comments to iwl-*-hw.h Zhu Yi 1 sibling, 1 reply; 36+ messages in thread From: Zhu Yi @ 2007-11-29 3:09 UTC (permalink / raw) To: linville; +Cc: linux-wireless, Ben Cahill, Zhu Yi From: Ben Cahill <ben.m.cahill@intel.com> Clean up some unused definitions in iwl-4965.h and iwl-3945.h Move STA_FLG_ definitions to iwl-4965-commands.h Signed-off-by: Ben Cahill <ben.m.cahill@intel.com> Signed-off-by: Zhu Yi <yi.zhu@intel.com> --- drivers/net/wireless/iwlwifi/iwl-3945.h | 21 ----------------- drivers/net/wireless/iwlwifi/iwl-4965-commands.h | 8 ++++++ drivers/net/wireless/iwlwifi/iwl-4965.h | 26 ---------------------- 3 files changed, 8 insertions(+), 47 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 607a1ed..2f3a8b4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -191,14 +191,6 @@ struct iwl3945_scan_power_info { s8 requested_power; /* scan pwr (dBm) requested for chnl/rate */ }; -/* Channel unlock period is 15 seconds. If no beacon or probe response - * has been received within 15 seconds on a locked channel then the channel - * remains locked. */ -#define TX_UNLOCK_PERIOD 15 - -/* CSA lock period is 15 seconds. If a CSA has been received on a channel in - * the last 15 seconds, the channel is locked */ -#define CSA_LOCK_PERIOD 15 /* * One for each channel, holds all channel setup data * Some of the fields (e.g. eeprom and flags/max_power_avg) are redundant @@ -560,19 +552,6 @@ struct iwl3945_driver_hw_info { dma_addr_t shared_phys; }; - -#define STA_FLG_RTS_MIMO_PROT_MSK __constant_cpu_to_le32(1 << 17) -#define STA_FLG_AGG_MPDU_8US_MSK __constant_cpu_to_le32(1 << 18) -#define STA_FLG_MAX_AGG_SIZE_POS (19) -#define STA_FLG_MAX_AGG_SIZE_MSK __constant_cpu_to_le32(3 << 19) -#define STA_FLG_FAT_EN_MSK __constant_cpu_to_le32(1 << 21) -#define STA_FLG_MIMO_DIS_MSK __constant_cpu_to_le32(1 << 22) -#define STA_FLG_AGG_MPDU_DENSITY_POS (23) -#define STA_FLG_AGG_MPDU_DENSITY_MSK __constant_cpu_to_le32(7 << 23) -#define HT_SHORT_GI_20MHZ_ONLY (1 << 0) -#define HT_SHORT_GI_40MHZ_ONLY (1 << 1) - - #define IWL_RX_HDR(x) ((struct iwl3945_rx_frame_hdr *)(\ x->u.rx_frame.stats.payload + \ x->u.rx_frame.stats.phy_count)) diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-commands.h b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h index 575a065..bd55709 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h @@ -515,6 +515,14 @@ struct iwl4965_qosparam_cmd { #define IWL_INVALID_STATION 255 #define STA_FLG_PWR_SAVE_MSK __constant_cpu_to_le32(1<<8); +#define STA_FLG_RTS_MIMO_PROT_MSK __constant_cpu_to_le32(1 << 17) +#define STA_FLG_AGG_MPDU_8US_MSK __constant_cpu_to_le32(1 << 18) +#define STA_FLG_MAX_AGG_SIZE_POS (19) +#define STA_FLG_MAX_AGG_SIZE_MSK __constant_cpu_to_le32(3 << 19) +#define STA_FLG_FAT_EN_MSK __constant_cpu_to_le32(1 << 21) +#define STA_FLG_MIMO_DIS_MSK __constant_cpu_to_le32(1 << 22) +#define STA_FLG_AGG_MPDU_DENSITY_POS (23) +#define STA_FLG_AGG_MPDU_DENSITY_MSK __constant_cpu_to_le32(7 << 23) #define STA_CONTROL_MODIFY_MSK 0x01 diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index 321767f..9438c63 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h @@ -192,14 +192,6 @@ struct iwl4965_scan_power_info { s8 requested_power; /* scan pwr (dBm) requested for chnl/rate */ }; -/* Channel unlock period is 15 seconds. If no beacon or probe response - * has been received within 15 seconds on a locked channel then the channel - * remains locked. */ -#define TX_UNLOCK_PERIOD 15 - -/* CSA lock period is 15 seconds. If a CSA has been received on a channel in - * the last 15 seconds, the channel is locked */ -#define CSA_LOCK_PERIOD 15 /* * One for each channel, holds all channel setup data * Some of the fields (e.g. eeprom and flags/max_power_avg) are redundant @@ -620,15 +612,6 @@ struct iwl4965_driver_hw_info { dma_addr_t shared_phys; }; - -#define STA_FLG_RTS_MIMO_PROT_MSK __constant_cpu_to_le32(1 << 17) -#define STA_FLG_AGG_MPDU_8US_MSK __constant_cpu_to_le32(1 << 18) -#define STA_FLG_MAX_AGG_SIZE_POS (19) -#define STA_FLG_MAX_AGG_SIZE_MSK __constant_cpu_to_le32(3 << 19) -#define STA_FLG_FAT_EN_MSK __constant_cpu_to_le32(1 << 21) -#define STA_FLG_MIMO_DIS_MSK __constant_cpu_to_le32(1 << 22) -#define STA_FLG_AGG_MPDU_DENSITY_POS (23) -#define STA_FLG_AGG_MPDU_DENSITY_MSK __constant_cpu_to_le32(7 << 23) #define HT_SHORT_GI_20MHZ_ONLY (1 << 0) #define HT_SHORT_GI_40MHZ_ONLY (1 << 1) @@ -860,17 +843,8 @@ struct iwl4965_kw { #define NRG_NUM_PREV_STAT_L 20 #define NUM_RX_CHAINS (3) -#define TX_POWER_IWL_ILLEGAL_VDET -100000 #define TX_POWER_IWL_ILLEGAL_VOLTAGE -10000 -#define TX_POWER_IWL_CLOSED_LOOP_MIN_POWER 18 -#define TX_POWER_IWL_CLOSED_LOOP_MAX_POWER 34 -#define TX_POWER_IWL_VDET_SLOPE_BELOW_NOMINAL 17 -#define TX_POWER_IWL_VDET_SLOPE_ABOVE_NOMINAL 20 -#define TX_POWER_IWL_NOMINAL_POWER 26 -#define TX_POWER_IWL_CLOSED_LOOP_ITERATION_LIMIT 1 #define TX_POWER_IWL_VOLTAGE_CODES_PER_03V 7 -#define TX_POWER_IWL_DEGREES_PER_VDET_CODE 11 -#define IWL_TX_POWER_MAX_NUM_PA_MEASUREMENTS 1 #define IWL_TX_POWER_CCK_COMPENSATION_B_STEP (9) #define IWL_TX_POWER_CCK_COMPENSATION_C_STEP (5) -- 1.5.3.6 ^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 14/36] iwlwifi: add comments, mostly on Tx queues 2007-11-29 3:09 ` [PATCH 13/36] iwlwifi: clean up some unused definitions in iwl-4965.h and iwl-3945.h Zhu Yi @ 2007-11-29 3:09 ` Zhu Yi [not found] ` <1196305816-23023-16-git-send-email-yi.zhu@intel.com> 0 siblings, 1 reply; 36+ messages in thread From: Zhu Yi @ 2007-11-29 3:09 UTC (permalink / raw) To: linville; +Cc: linux-wireless, Cahill, Ben M, Zhu Yi From: Cahill, Ben M <ben.m.cahill@intel.com> Add comments, mostly on Tx queues Signed-off-by: Cahill, Ben M <ben.m.cahill@intel.com> Signed-off-by: Zhu Yi <yi.zhu@intel.com> --- drivers/net/wireless/iwlwifi/iwl-4965.c | 252 +++++++++++++++++++++++---- drivers/net/wireless/iwlwifi/iwl4965-base.c | 18 ++- 2 files changed, 231 insertions(+), 39 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index d44166a..40c795e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -144,7 +144,7 @@ int iwl4965_hw_rxq_stop(struct iwl4965_priv *priv) return rc; } - /* stop HW */ + /* stop Rx DMA */ iwl4965_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); rc = iwl4965_poll_direct_bit(priv, FH_MEM_RSSR_RX_STATUS_REG, (1 << 24), 1000); @@ -234,17 +234,22 @@ static int iwl4965_rx_init(struct iwl4965_priv *priv, struct iwl4965_rx_queue *r return rc; } - /* stop HW */ + /* Stop Rx DMA */ iwl4965_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); + /* Reset driver's Rx queue write index */ iwl4965_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0); + + /* Tell device where to find RBD circular buffer in DRAM */ iwl4965_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_BASE_REG, rxq->dma_addr >> 8); + /* Tell device where in DRAM to update its Rx status */ iwl4965_write_direct32(priv, FH_RSCSR_CHNL0_STTS_WPTR_REG, (priv->hw_setting.shared_phys + offsetof(struct iwl4965_shared, val0)) >> 4); + /* Enable Rx DMA, enable host interrupt, Rx buffer size 4k, 256 RBDs */ iwl4965_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL | FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL | @@ -263,6 +268,7 @@ static int iwl4965_rx_init(struct iwl4965_priv *priv, struct iwl4965_rx_queue *r return 0; } +/* Tell 4965 where to find the "keep warm" buffer */ static int iwl4965_kw_init(struct iwl4965_priv *priv) { unsigned long flags; @@ -297,6 +303,11 @@ static int iwl4965_kw_alloc(struct iwl4965_priv *priv) #define CHECK_AND_PRINT(x) ((eeprom_ch->flags & EEPROM_CHANNEL_##x) \ ? # x " " : "") +/** + * iwl4965_set_fat_chan_info - Copy fat channel info into driver's priv. + * + * Does not set up a command, or touch hardware. + */ int iwl4965_set_fat_chan_info(struct iwl4965_priv *priv, int phymode, u16 channel, const struct iwl4965_eeprom_channel *eeprom_ch, u8 fat_extension_channel) @@ -337,6 +348,9 @@ int iwl4965_set_fat_chan_info(struct iwl4965_priv *priv, int phymode, u16 channe return 0; } +/** + * iwl4965_kw_free - Free the "keep warm" buffer + */ static void iwl4965_kw_free(struct iwl4965_priv *priv) { struct pci_dev *dev = priv->pci_dev; @@ -363,9 +377,10 @@ static int iwl4965_txq_ctx_reset(struct iwl4965_priv *priv) iwl4965_kw_free(priv); + /* Free all tx/cmd queues and keep-warm buffer */ iwl4965_hw_txq_ctx_free(priv); - /* Tx CMD queue */ + /* Alloc keep-warm buffer */ rc = iwl4965_kw_alloc(priv); if (rc) { IWL_ERROR("Keep Warm allocation failed"); @@ -381,17 +396,20 @@ static int iwl4965_txq_ctx_reset(struct iwl4965_priv *priv) goto error_reset; } + /* Turn off all Tx DMA channels */ iwl4965_write_prph(priv, KDR_SCD_TXFACT, 0); iwl4965_release_nic_access(priv); spin_unlock_irqrestore(&priv->lock, flags); + /* Tell 4965 where to find the keep-warm buffer */ rc = iwl4965_kw_init(priv); if (rc) { IWL_ERROR("kw_init failed\n"); goto error_reset; } - /* Tx queue(s) */ + /* Alloc and init all (default 16) Tx queues, + * including the command queue (#4) */ for (txq_id = 0; txq_id < priv->hw_setting.max_txq_num; txq_id++) { slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ? TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; @@ -545,6 +563,8 @@ int iwl4965_hw_nic_init(struct iwl4965_priv *priv) iwl4965_rx_queue_update_write_ptr(priv, rxq); spin_unlock_irqrestore(&priv->lock, flags); + + /* Allocate and init all Tx and Command queues */ rc = iwl4965_txq_ctx_reset(priv); if (rc) return rc; @@ -593,13 +613,16 @@ int iwl4965_hw_nic_stop_master(struct iwl4965_priv *priv) return rc; } +/** + * iwl4965_hw_txq_ctx_stop - Stop all Tx DMA channels, free Tx queue memory + */ void iwl4965_hw_txq_ctx_stop(struct iwl4965_priv *priv) { int txq_id; unsigned long flags; - /* reset TFD queues */ + /* Stop each Tx DMA channel, and wait for it to be idle */ for (txq_id = 0; txq_id < priv->hw_setting.max_txq_num; txq_id++) { spin_lock_irqsave(&priv->lock, flags); if (iwl4965_grab_nic_access(priv)) { @@ -617,6 +640,7 @@ void iwl4965_hw_txq_ctx_stop(struct iwl4965_priv *priv) spin_unlock_irqrestore(&priv->lock, flags); } + /* Deallocate memory for all Tx queues */ iwl4965_hw_txq_ctx_free(priv); } @@ -1586,16 +1610,23 @@ static void iwl4965_set_wr_ptrs(struct iwl4965_priv *priv, int txq_id, u32 index iwl4965_write_prph(priv, KDR_SCD_QUEUE_RDPTR(txq_id), index); } -/* - * Acquire priv->lock before calling this function ! +/** + * iwl4965_tx_queue_set_status - (optionally) start Tx/Cmd queue + * @tx_fifo_id: Tx DMA/FIFO channel (range 0-7) that the queue will feed + * @scd_retry: (1) Indicates queue will be used in aggregation mode + * + * NOTE: Acquire priv->lock before calling this function ! */ static void iwl4965_tx_queue_set_status(struct iwl4965_priv *priv, struct iwl4965_tx_queue *txq, int tx_fifo_id, int scd_retry) { int txq_id = txq->q.id; + + /* Find out whether to activate Tx queue */ int active = test_bit(txq_id, &priv->txq_ctx_active_msk)?1:0; + /* Set up and activate */ iwl4965_write_prph(priv, KDR_SCD_QUEUE_STATUS_BITS(txq_id), (active << SCD_QUEUE_STTS_REG_POS_ACTIVE) | (tx_fifo_id << SCD_QUEUE_STTS_REG_POS_TXF) | @@ -1606,7 +1637,7 @@ static void iwl4965_tx_queue_set_status(struct iwl4965_priv *priv, txq->sched_retry = scd_retry; IWL_DEBUG_INFO("%s %s Queue %d on AC %d\n", - active ? "Activete" : "Deactivate", + active ? "Activate" : "Deactivate", scd_retry ? "BA" : "AC", txq_id, tx_fifo_id); } @@ -1654,6 +1685,7 @@ int iwl4965_alive_notify(struct iwl4965_priv *priv) return rc; } + /* Clear 4965's internal Tx Scheduler data base */ priv->scd_base_addr = iwl4965_read_prph(priv, KDR_SCD_SRAM_BASE_ADDR); a = priv->scd_base_addr + SCD_CONTEXT_DATA_OFFSET; for (; a < priv->scd_base_addr + SCD_TX_STTS_BITMAP_OFFSET; a += 4) @@ -1663,20 +1695,29 @@ int iwl4965_alive_notify(struct iwl4965_priv *priv) for (; a < sizeof(u16) * priv->hw_setting.max_txq_num; a += 4) iwl4965_write_targ_mem(priv, a, 0); + /* Tel 4965 where to find Tx byte count tables */ iwl4965_write_prph(priv, KDR_SCD_DRAM_BASE_ADDR, (priv->hw_setting.shared_phys + offsetof(struct iwl4965_shared, queues_byte_cnt_tbls)) >> 10); + + /* Disable chain mode for all queues */ iwl4965_write_prph(priv, KDR_SCD_QUEUECHAIN_SEL, 0); - /* initiate the queues */ + /* Initialize each Tx queue (including the command queue) */ for (i = 0; i < priv->hw_setting.max_txq_num; i++) { + + /* TFD circular buffer read/write indexes */ iwl4965_write_prph(priv, KDR_SCD_QUEUE_RDPTR(i), 0); iwl4965_write_direct32(priv, HBUS_TARG_WRPTR, 0 | (i << 8)); + + /* Max Tx Window size for Scheduler-ACK mode */ iwl4965_write_targ_mem(priv, priv->scd_base_addr + SCD_CONTEXT_QUEUE_OFFSET(i), (SCD_WIN_SIZE << SCD_QUEUE_CTX_REG1_WIN_SIZE_POS) & SCD_QUEUE_CTX_REG1_WIN_SIZE_MSK); + + /* Frame limit */ iwl4965_write_targ_mem(priv, priv->scd_base_addr + SCD_CONTEXT_QUEUE_OFFSET(i) + sizeof(u32), @@ -1688,11 +1729,13 @@ int iwl4965_alive_notify(struct iwl4965_priv *priv) iwl4965_write_prph(priv, KDR_SCD_INTERRUPT_MASK, (1 << priv->hw_setting.max_txq_num) - 1); + /* Activate all Tx DMA/FIFO channels */ iwl4965_write_prph(priv, KDR_SCD_TXFACT, SCD_TXFACT_REG_TXFIFO_MASK(0, 7)); iwl4965_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0); - /* map qos queues to fifos one-to-one */ + + /* Map each Tx/cmd queue to its corresponding fifo */ for (i = 0; i < ARRAY_SIZE(default_queue_to_tx_fifo); i++) { int ac = default_queue_to_tx_fifo[i]; iwl4965_txq_ctx_activate(priv, i); @@ -1705,8 +1748,14 @@ int iwl4965_alive_notify(struct iwl4965_priv *priv) return 0; } +/** + * iwl4965_hw_set_hw_setting + * + * Called when initializing driver + */ int iwl4965_hw_set_hw_setting(struct iwl4965_priv *priv) { + /* Allocate area for Tx byte count tables and Rx queue status */ priv->hw_setting.shared_virt = pci_alloc_consistent(priv->pci_dev, sizeof(struct iwl4965_shared), @@ -1741,13 +1790,15 @@ void iwl4965_hw_txq_ctx_free(struct iwl4965_priv *priv) for (txq_id = 0; txq_id < priv->hw_setting.max_txq_num; txq_id++) iwl4965_tx_queue_free(priv, &priv->txq[txq_id]); + /* Keep-warm buffer */ iwl4965_kw_free(priv); } /** - * iwl4965_hw_txq_free_tfd - Free one TFD, those at index [txq->q.read_ptr] + * iwl4965_hw_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr] * - * Does NOT advance any indexes + * Does NOT advance any TFD circular buffer read/write indexes + * Does NOT free the TFD itself (which is within circular buffer) */ int iwl4965_hw_txq_free_tfd(struct iwl4965_priv *priv, struct iwl4965_tx_queue *txq) { @@ -1758,12 +1809,11 @@ int iwl4965_hw_txq_free_tfd(struct iwl4965_priv *priv, struct iwl4965_tx_queue * int counter = 0; int index, is_odd; - /* classify bd */ + /* Host command buffers stay mapped in memory, nothing to clean */ if (txq->q.id == IWL_CMD_QUEUE_NUM) - /* nothing to cleanup after for host commands */ return 0; - /* sanity check */ + /* Sanity check on number of chunks */ counter = IWL_GET_BITS(*bd, num_tbs); if (counter > MAX_NUM_OF_TBS) { IWL_ERROR("Too many chunks: %i\n", counter); @@ -1771,8 +1821,8 @@ int iwl4965_hw_txq_free_tfd(struct iwl4965_priv *priv, struct iwl4965_tx_queue * return 0; } - /* unmap chunks if any */ - + /* Unmap chunks, if any. + * TFD info for odd chunks is different format than for even chunks. */ for (i = 0; i < counter; i++) { index = i / 2; is_odd = i & 0x1; @@ -1792,6 +1842,7 @@ int iwl4965_hw_txq_free_tfd(struct iwl4965_priv *priv, struct iwl4965_tx_queue * IWL_GET_BITS(bd->pa[index], tb1_len), PCI_DMA_TODEVICE); + /* Free SKB, if any, for this chunk */ if (txq->txb[txq->q.read_ptr].skb[i]) { struct sk_buff *skb = txq->txb[txq->q.read_ptr].skb[i]; @@ -1826,6 +1877,17 @@ static s32 iwl4965_math_div_round(s32 num, s32 denom, s32 *res) return 1; } +/** + * iwl4965_get_voltage_compensation - Power supply voltage comp for txpower + * + * Determines power supply voltage compensation for txpower calculations. + * Returns number of 1/2-dB steps to subtract from gain table index, + * to compensate for difference between power supply voltage during + * factory measurements, vs. current power supply voltage. + * + * Voltage indication is higher for lower voltage. + * Lower voltage requires more gain (lower gain table index). + */ static s32 iwl4965_get_voltage_compensation(s32 eeprom_voltage, s32 current_voltage) { @@ -1913,6 +1975,14 @@ static s32 iwl4965_interpolate_value(s32 x, s32 x1, s32 y1, s32 x2, s32 y2) } } +/** + * iwl4965_interpolate_chan - Interpolate factory measurements for one channel + * + * Interpolates factory measurements from the two sample channels within a + * sub-band, to apply to channel of interest. Interpolation is proportional to + * differences in channel frequencies, which is proportional to differences + * in channel number. + */ static int iwl4965_interpolate_chan(struct iwl4965_priv *priv, u32 channel, struct iwl4965_eeprom_calib_ch_info *chan_info) { @@ -2681,6 +2751,13 @@ unsigned int iwl4965_hw_get_beacon_cmd(struct iwl4965_priv *priv, return (sizeof(*tx_beacon_cmd) + frame_size); } +/* + * Tell 4965 where to find circular buffer of Tx Frame Descriptors for + * given Tx queue, and enable the DMA channel used for that queue. + * + * 4965 supports up to 16 Tx queues in DRAM, mapped to up to 8 Tx DMA + * channels supported in hardware. + */ int iwl4965_hw_tx_queue_init(struct iwl4965_priv *priv, struct iwl4965_tx_queue *txq) { int rc; @@ -2694,8 +2771,11 @@ int iwl4965_hw_tx_queue_init(struct iwl4965_priv *priv, struct iwl4965_tx_queue return rc; } + /* Circular buffer (TFD queue in DRAM) physical base address */ iwl4965_write_direct32(priv, FH_MEM_CBBC_QUEUE(txq_id), txq->q.dma_addr >> 8); + + /* Enable DMA channel, using same id as for TFD queue */ iwl4965_write_direct32( priv, IWL_FH_TCSR_CHNL_TX_CONFIG_REG(txq_id), IWL_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | @@ -2718,6 +2798,7 @@ int iwl4965_hw_txq_attach_buf_to_tfd(struct iwl4965_priv *priv, void *ptr, struct iwl4965_tfd_frame *tfd = ptr; u32 num_tbs = IWL_GET_BITS(*tfd, num_tbs); + /* Each TFD can point to a maximum 20 Tx buffers */ if ((num_tbs >= MAX_NUM_OF_TBS) || (num_tbs < 0)) { IWL_ERROR("Error can not send more than %d chunks\n", MAX_NUM_OF_TBS); @@ -2759,6 +2840,9 @@ static void iwl4965_hw_card_show_info(struct iwl4965_priv *priv) #define IWL_TX_CRC_SIZE 4 #define IWL_TX_DELIMITER_SIZE 4 +/** + * iwl4965_tx_queue_update_wr_ptr - Set up entry in Tx byte-count array + */ int iwl4965_tx_queue_update_wr_ptr(struct iwl4965_priv *priv, struct iwl4965_tx_queue *txq, u16 byte_cnt) { @@ -2771,9 +2855,11 @@ int iwl4965_tx_queue_update_wr_ptr(struct iwl4965_priv *priv, len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE; + /* Set up byte count within first 256 entries */ IWL_SET_BITS16(shared_data->queues_byte_cnt_tbls[txq_id]. tfd_offset[txq->q.write_ptr], byte_cnt, len); + /* If within first 64 entries, duplicate at end */ if (txq->q.write_ptr < IWL4965_MAX_WIN_SIZE) IWL_SET_BITS16(shared_data->queues_byte_cnt_tbls[txq_id]. tfd_offset[IWL4965_QUEUE_SIZE + txq->q.write_ptr], @@ -2782,8 +2868,12 @@ int iwl4965_tx_queue_update_wr_ptr(struct iwl4965_priv *priv, return 0; } -/* Set up Rx receiver/antenna/chain usage in "staging" RXON image. - * This should not be used for scan command ... it puts data in wrong place. */ +/** + * iwl4965_set_rxon_chain - Set up Rx chain usage in "staging" RXON image + * + * Selects how many and which Rx receivers/antennas/chains to use. + * This should not be used for scan command ... it puts data in wrong place. + */ void iwl4965_set_rxon_chain(struct iwl4965_priv *priv) { u8 is_single = is_single_stream(priv); @@ -2931,6 +3021,9 @@ enum HT_STATUS { BA_STATUS_ACTIVE, }; +/** + * iwl4964_tl_ba_avail - Find out if an unused aggregation queue is available + */ static u8 iwl4964_tl_ba_avail(struct iwl4965_priv *priv) { int i; @@ -2939,6 +3032,8 @@ static u8 iwl4964_tl_ba_avail(struct iwl4965_priv *priv) u16 msk; lq = (struct iwl4965_lq_mngr *)&(priv->lq_mngr); + + /* Find out how many agg queues are in use */ for (i = 0; i < TID_MAX_LOAD_COUNT ; i++) { msk = 1 << i; if ((lq->agg_ctrl.granted_ba & msk) || @@ -3080,6 +3175,9 @@ void iwl4965_turn_off_agg(struct iwl4965_priv *priv, u8 tid) } } +/** + * iwl4965_ba_status - Update driver's link quality mgr with tid's HT status + */ static void iwl4965_ba_status(struct iwl4965_priv *priv, u8 tid, enum HT_STATUS status) { @@ -3301,11 +3399,12 @@ int iwl4965_get_temperature(const struct iwl4965_priv *priv) } /* - * Temperature is only 23 bits so sign extend out to 32 + * Temperature is only 23 bits, so sign extend out to 32. * * NOTE If we haven't received a statistics notification yet * with an updated temperature, use R4 provided to us in the - * ALIVE response. */ + * "initialize" ALIVE response. + */ if (!test_bit(STATUS_TEMPERATURE, &priv->status)) vt = sign_extend(R4, 23); else @@ -4001,6 +4100,11 @@ static void iwl4965_rx_missed_beacon_notif(struct iwl4965_priv *priv, #ifdef CONFIG_IWL4965_HT #ifdef CONFIG_IWL4965_HT_AGG +/** + * iwl4965_set_tx_status - Update driver's record of one Tx frame's status + * + * This will get sent to mac80211. + */ static void iwl4965_set_tx_status(struct iwl4965_priv *priv, int txq_id, int idx, u32 status, u32 retry_count, u32 rate) { @@ -4013,11 +4117,15 @@ static void iwl4965_set_tx_status(struct iwl4965_priv *priv, int txq_id, int idx } +/** + * iwl4965_sta_modify_enable_tid_tx - Enable Tx for this TID in station table + */ static void iwl4965_sta_modify_enable_tid_tx(struct iwl4965_priv *priv, int sta_id, int tid) { unsigned long flags; + /* Remove "disable" flag, to enable Tx for this TID */ spin_lock_irqsave(&priv->sta_lock, flags); priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_TID_DISABLE_TX; priv->stations[sta_id].sta.tid_disable_tx &= cpu_to_le16(~(1 << tid)); @@ -4028,6 +4136,12 @@ static void iwl4965_sta_modify_enable_tid_tx(struct iwl4965_priv *priv, } +/** + * iwl4965_tx_status_reply_compressed_ba - Update tx status from block-ack + * + * Go through block-ack's bitmap of ACK'd frames, update driver's record of + * ACK vs. not. This gets sent to mac80211, then to rate scaling algo. + */ static int iwl4965_tx_status_reply_compressed_ba(struct iwl4965_priv *priv, struct iwl4965_ht_agg *agg, struct iwl4965_compressed_ba_resp* @@ -4044,13 +4158,17 @@ static int iwl4965_tx_status_reply_compressed_ba(struct iwl4965_priv *priv, IWL_ERROR("Received BA when not expected\n"); return -EINVAL; } + + /* Mark that the expected block-ack response arrived */ agg->wait_for_ba = 0; IWL_DEBUG_TX_REPLY("BA %d %d\n", agg->start_idx, ba_resp->ba_seq_ctl); + + /* Calculate shift to align block-ack bits with our Tx window bits */ sh = agg->start_idx - SEQ_TO_INDEX(ba_seq_ctl>>4); if (sh < 0) /* tbw something is wrong with indices */ sh += 0x100; - /* don't use 64 bits for now */ + /* don't use 64-bit values for now */ bitmap0 = resp_bitmap0 >> sh; bitmap1 = resp_bitmap1 >> sh; bitmap0 |= (resp_bitmap1 & ((1<<sh)|((1<<sh)-1))) << (32 - sh); @@ -4061,10 +4179,12 @@ static int iwl4965_tx_status_reply_compressed_ba(struct iwl4965_priv *priv, } /* check for success or failure according to the - * transmitted bitmap and back bitmap */ + * transmitted bitmap and block-ack bitmap */ bitmap0 &= agg->bitmap0; bitmap1 &= agg->bitmap1; + /* For each frame attempted in aggregation, + * update driver's record of tx frame's status. */ for (i = 0; i < agg->frame_count ; i++) { int idx = (agg->start_idx + i) & 0xff; ack = bitmap0 & (1 << i); @@ -4080,11 +4200,22 @@ static int iwl4965_tx_status_reply_compressed_ba(struct iwl4965_priv *priv, return 0; } +/** + * iwl4965_queue_dec_wrap - Decrement queue index, wrap back to end if needed + * @index -- current index + * @n_bd -- total number of entries in queue (s/b power of 2) + */ static inline int iwl4965_queue_dec_wrap(int index, int n_bd) { return (index == 0) ? n_bd - 1 : index - 1; } +/** + * iwl4965_rx_reply_compressed_ba - Handler for REPLY_COMPRESSED_BA + * + * Handles block-acknowledge notification from device, which reports success + * of frames sent via aggregation. + */ static void iwl4965_rx_reply_compressed_ba(struct iwl4965_priv *priv, struct iwl4965_rx_mem_buffer *rxb) { @@ -4093,7 +4224,12 @@ static void iwl4965_rx_reply_compressed_ba(struct iwl4965_priv *priv, int index; struct iwl4965_tx_queue *txq = NULL; struct iwl4965_ht_agg *agg; + + /* "flow" corresponds to Tx queue */ u16 ba_resp_scd_flow = le16_to_cpu(ba_resp->scd_flow); + + /* "ssn" is start of block-ack Tx window, corresponds to index + * (in Tx queue's circular buffer) of first TFD/frame in window */ u16 ba_resp_scd_ssn = le16_to_cpu(ba_resp->scd_ssn); if (ba_resp_scd_flow >= ARRAY_SIZE(priv->txq)) { @@ -4103,6 +4239,8 @@ static void iwl4965_rx_reply_compressed_ba(struct iwl4965_priv *priv, txq = &priv->txq[ba_resp_scd_flow]; agg = &priv->stations[ba_resp->sta_id].tid[ba_resp->tid].agg; + + /* Find index just before block-ack window */ index = iwl4965_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd); /* TODO: Need to get this copy more safely - now good for debug */ @@ -4128,22 +4266,35 @@ static void iwl4965_rx_reply_compressed_ba(struct iwl4965_priv *priv, agg->bitmap0); } */ + + /* Update driver's record of ACK vs. not for each frame in window */ iwl4965_tx_status_reply_compressed_ba(priv, agg, ba_resp); - /* releases all the TFDs until the SSN */ + + /* Release all TFDs before the SSN, i.e. all TFDs in front of + * block-ack window (we assume that they've been successfully + * transmitted ... if not, it's too late anyway). */ if (txq->q.read_ptr != (ba_resp_scd_ssn & 0xff)) iwl4965_tx_queue_reclaim(priv, ba_resp_scd_flow, index); } +/** + * iwl4965_tx_queue_stop_scheduler - Stop queue, but keep configuration + */ static void iwl4965_tx_queue_stop_scheduler(struct iwl4965_priv *priv, u16 txq_id) { + /* Simply stop the queue, but don't change any configuration; + * the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */ iwl4965_write_prph(priv, KDR_SCD_QUEUE_STATUS_BITS(txq_id), (0 << SCD_QUEUE_STTS_REG_POS_ACTIVE)| (1 << SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN)); } +/** + * iwl4965_tx_queue_set_q2ratid - Map unique receiver/tid combination to a queue + */ static int iwl4965_tx_queue_set_q2ratid(struct iwl4965_priv *priv, u16 ra_tid, u16 txq_id) { @@ -4169,7 +4320,10 @@ static int iwl4965_tx_queue_set_q2ratid(struct iwl4965_priv *priv, u16 ra_tid, } /** - * txq_id must be greater than IWL_BACK_QUEUE_FIRST_ID + * iwl4965_tx_queue_agg_enable - Set up & enable aggregation for selected queue + * + * NOTE: txq_id must be greater than IWL_BACK_QUEUE_FIRST_ID, + * i.e. it must be one of the higher queues used for aggregation */ static int iwl4965_tx_queue_agg_enable(struct iwl4965_priv *priv, int txq_id, int tx_fifo, int sta_id, int tid, @@ -4185,6 +4339,7 @@ static int iwl4965_tx_queue_agg_enable(struct iwl4965_priv *priv, int txq_id, ra_tid = BUILD_RAxTID(sta_id, tid); + /* Modify device's station table to Tx this TID */ iwl4965_sta_modify_enable_tid_tx(priv, sta_id, tid); spin_lock_irqsave(&priv->lock, flags); @@ -4194,19 +4349,22 @@ static int iwl4965_tx_queue_agg_enable(struct iwl4965_priv *priv, int txq_id, return rc; } + /* Stop this Tx queue before configuring it */ iwl4965_tx_queue_stop_scheduler(priv, txq_id); + /* Map receiver-address / traffic-ID to this queue */ iwl4965_tx_queue_set_q2ratid(priv, ra_tid, txq_id); - + /* Set this queue as a chain-building queue */ iwl4965_set_bits_prph(priv, KDR_SCD_QUEUECHAIN_SEL, (1<<txq_id)); + /* Place first TFD at index corresponding to start sequence number. + * Assumes that ssn_idx is valid (!= 0xFFF) */ priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff); priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff); - - /* supposes that ssn_idx is valid (!= 0xFFF) */ iwl4965_set_wr_ptrs(priv, txq_id, ssn_idx); + /* Set up Tx window size and frame limit for this queue */ iwl4965_write_targ_mem(priv, priv->scd_base_addr + SCD_CONTEXT_QUEUE_OFFSET(txq_id), (SCD_WIN_SIZE << SCD_QUEUE_CTX_REG1_WIN_SIZE_POS) & @@ -4219,6 +4377,7 @@ static int iwl4965_tx_queue_agg_enable(struct iwl4965_priv *priv, int txq_id, iwl4965_set_bits_prph(priv, KDR_SCD_INTERRUPT_MASK, (1 << txq_id)); + /* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */ iwl4965_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 1); iwl4965_release_nic_access(priv); @@ -4274,14 +4433,16 @@ static int iwl4965_tx_queue_agg_disable(struct iwl4965_priv *priv, u16 txq_id, /** * iwl4965_add_station - Initialize a station's hardware rate table * - * The uCode contains a table of fallback rates and retries per rate + * The uCode's station table contains a table of fallback rates * for automatic fallback during transmission. * - * NOTE: This initializes the table for a single retry per data rate - * which is not optimal. Setting up an intelligent retry per rate - * requires feedback from transmission, which isn't exposed through - * rc80211_simple which is what this driver is currently using. + * NOTE: This sets up a default set of values. These will be replaced later + * if the driver's iwl-4965-rs rate scaling algorithm is used, instead of + * rc80211_simple. * + * NOTE: Run REPLY_ADD_STA command to set up station table entry, before + * calling this function (which runs REPLY_TX_LINK_QUALITY_CMD, + * which requires station table entry to exist). */ void iwl4965_add_station(struct iwl4965_priv *priv, const u8 *addr, int is_ap) { @@ -4291,8 +4452,8 @@ void iwl4965_add_station(struct iwl4965_priv *priv, const u8 *addr, int is_ap) }; u16 rate_flags; - /* Set up the rate scaling to start at 54M and fallback - * all the way to 1M in IEEE order and then spin on IEEE */ + /* Set up the rate scaling to start at selected rate, fall back + * all the way down to 1M in IEEE order, and then spin on 1M */ if (is_ap) r = IWL_RATE_54M_INDEX; else if (priv->phymode == MODE_IEEE80211A) @@ -4305,8 +4466,10 @@ void iwl4965_add_station(struct iwl4965_priv *priv, const u8 *addr, int is_ap) if (r >= IWL_FIRST_CCK_RATE && r <= IWL_LAST_CCK_RATE) rate_flags |= RATE_MCS_CCK_MSK; + /* Use Tx antenna B only */ rate_flags |= RATE_MCS_ANT_B_MSK; rate_flags &= ~RATE_MCS_ANT_A_MSK; + link_cmd.rs_table[i].rate_n_flags = iwl4965_hw_set_rate_n_flags(iwl4965_rates[r].plcp, rate_flags); r = iwl4965_get_prev_ieee_rate(r); @@ -4374,6 +4537,7 @@ void iwl4965_set_rxon_ht(struct iwl4965_priv *priv, struct sta_ht_info *ht_info) if (!ht_info->is_ht) return; + /* Set up channel bandwidth: 20 MHz only, or 20/40 mixed if fat ok */ if (iwl4965_is_fat_tx_allowed(priv, ht_info)) rxon->flags |= RXON_FLG_CHANNEL_MODE_MIXED_MSK; else @@ -4388,7 +4552,7 @@ void iwl4965_set_rxon_ht(struct iwl4965_priv *priv, struct sta_ht_info *ht_info) return; } - /* Note: control channel is oposit to extension channel */ + /* Note: control channel is opposite of extension channel */ switch (ht_info->extension_chan_offset) { case IWL_EXT_CHANNEL_OFFSET_ABOVE: rxon->flags &= ~(RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK); @@ -4514,6 +4678,12 @@ static const u16 default_tid_to_tx_fifo[] = { IWL_TX_FIFO_AC3 }; +/* + * Find first available (lowest unused) Tx Queue, mark it "active". + * Called only when finding queue for aggregation. + * Should never return anything < 7, because they should already + * be in use as EDCA AC (0-3), Command (4), HCCA (5, 6). + */ static int iwl4965_txq_ctx_activate_free(struct iwl4965_priv *priv) { int txq_id; @@ -4537,6 +4707,7 @@ int iwl4965_mac_ht_tx_agg_start(struct ieee80211_hw *hw, u8 *da, u16 tid, struct iwl4965_tid_data *tid_data; DECLARE_MAC_BUF(mac); + /* Determine Tx DMA/FIFO channel for this Traffic ID */ if (likely(tid < ARRAY_SIZE(default_tid_to_tx_fifo))) tx_fifo = default_tid_to_tx_fifo[tid]; else @@ -4545,22 +4716,31 @@ int iwl4965_mac_ht_tx_agg_start(struct ieee80211_hw *hw, u8 *da, u16 tid, IWL_WARNING("iwl-AGG iwl4965_mac_ht_tx_agg_start on da=%s" " tid=%d\n", print_mac(mac, da), tid); + /* Get index into station table */ sta_id = iwl4965_hw_find_station(priv, da); if (sta_id == IWL_INVALID_STATION) return -ENXIO; + /* Find available Tx queue for aggregation */ txq_id = iwl4965_txq_ctx_activate_free(priv); if (txq_id == -1) return -ENXIO; spin_lock_irqsave(&priv->sta_lock, flags); tid_data = &priv->stations[sta_id].tid[tid]; + + /* Get starting sequence number for 1st frame in block ack window. + * We'll use least signif byte as 1st frame's index into Tx queue. */ ssn = SEQ_TO_SN(tid_data->seq_number); tid_data->agg.txq_id = txq_id; spin_unlock_irqrestore(&priv->sta_lock, flags); *start_seq_num = ssn; + + /* Update driver's link quality manager */ iwl4965_ba_status(priv, tid, BA_STATUS_ACTIVE); + + /* Set up and enable aggregation for selected Tx queue and FIFO */ return iwl4965_tx_queue_agg_enable(priv, txq_id, tx_fifo, sta_id, tid, ssn); } diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index f2a3ecd..a840d5d 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -305,6 +305,9 @@ static int iwl4965_tx_queue_alloc(struct iwl4965_priv *priv, return -ENOMEM; } +/** + * iwl4965_tx_queue_init - Allocate and initialize one tx/cmd queue + */ int iwl4965_tx_queue_init(struct iwl4965_priv *priv, struct iwl4965_tx_queue *txq, int slots_num, u32 txq_id) { @@ -312,9 +315,14 @@ int iwl4965_tx_queue_init(struct iwl4965_priv *priv, int len; int rc = 0; - /* allocate command space + one big command for scan since scan - * command is very huge the system will not have two scan at the - * same time */ + /* + * Alloc buffer array for commands (Tx or other types of commands). + * For the command queue (#4), allocate command space + one big + * command for scan, since scan command is very huge; the system will + * not have two scans at the same time, so only one is needed. + * For normal Tx queues (all other queues), no super-size command + * space is needed. + */ len = sizeof(struct iwl4965_cmd) * slots_num; if (txq_id == IWL_CMD_QUEUE_NUM) len += IWL_MAX_SCAN_SIZE; @@ -322,6 +330,7 @@ int iwl4965_tx_queue_init(struct iwl4965_priv *priv, if (!txq->cmd) return -ENOMEM; + /* Alloc driver data array and TFD circular buffer */ rc = iwl4965_tx_queue_alloc(priv, txq, txq_id); if (rc) { pci_free_consistent(dev, len, txq->cmd, txq->dma_addr_cmd); @@ -333,8 +342,11 @@ int iwl4965_tx_queue_init(struct iwl4965_priv *priv, /* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise * iwl4965_queue_inc_wrap and iwl4965_queue_dec_wrap are broken. */ BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1)); + + /* Initialize queue's high/low-water marks, and head/tail indexes */ iwl4965_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id); + /* Tell device where to find queue */ iwl4965_hw_tx_queue_init(priv, txq); return 0; -- 1.5.3.6 ^ permalink raw reply related [flat|nested] 36+ messages in thread
[parent not found: <1196305816-23023-16-git-send-email-yi.zhu@intel.com>]
* [PATCH 16/36] iwlwifi: fix possibly NULL dereference in iwl_set_rate() [not found] ` <1196305816-23023-16-git-send-email-yi.zhu@intel.com> @ 2007-11-29 3:09 ` Zhu Yi 2007-11-29 3:09 ` [PATCH 17/36] iwlwifi: Clean up unused definitions in iwl-3945-hw.h Zhu Yi 2007-11-29 3:17 ` [PATCH 15/36] iwlwifi: add comments to iwl*-base.c Zhu Yi 1 sibling, 1 reply; 36+ messages in thread From: Zhu Yi @ 2007-11-29 3:09 UTC (permalink / raw) To: linville; +Cc: linux-wireless, Saleem Abdulrasool, Zhu Yi From: Saleem Abdulrasool <compnerd@compnerd.org> Signed-off-by: Saleem Abdulrasool <compnerd@compnerd.org> Signed-off-by: Zhu Yi <yi.zhu@intel.com> --- drivers/net/wireless/iwlwifi/iwl3945-base.c | 4 ++++ drivers/net/wireless/iwlwifi/iwl4965-base.c | 4 ++++ 2 files changed, 8 insertions(+), 0 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index a742309..a892e26 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -2984,6 +2984,10 @@ static void iwl3945_set_rate(struct iwl3945_priv *priv) int i; hw = iwl3945_get_hw_mode(priv, priv->phymode); + if (!hw) { + IWL_ERROR("Failed to set rate: unable to get hw mode\n"); + return; + } priv->active_rate = 0; priv->active_rate_basic = 0; diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 01ba374..f813669 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -3092,6 +3092,10 @@ static void iwl4965_set_rate(struct iwl4965_priv *priv) int i; hw = iwl4965_get_hw_mode(priv, priv->phymode); + if (!hw) { + IWL_ERROR("Failed to set rate: unable to get hw mode\n"); + return; + } priv->active_rate = 0; priv->active_rate_basic = 0; -- 1.5.3.6 ^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 17/36] iwlwifi: Clean up unused definitions in iwl-3945-hw.h 2007-11-29 3:09 ` [PATCH 16/36] iwlwifi: fix possibly NULL dereference in iwl_set_rate() Zhu Yi @ 2007-11-29 3:09 ` Zhu Yi 2007-11-29 3:09 ` [PATCH 18/36] iwlwifi: clean up unused definitions in iwl-4965-hw.h Zhu Yi 0 siblings, 1 reply; 36+ messages in thread From: Zhu Yi @ 2007-11-29 3:09 UTC (permalink / raw) To: linville; +Cc: linux-wireless, Ben Cahill, Zhu Yi From: Ben Cahill <ben.m.cahill@intel.com> Clean up unused definitions in iwl-3945-hw.h Signed-off-by: Ben Cahill <ben.m.cahill@intel.com> Signed-off-by: Zhu Yi <yi.zhu@intel.com> --- drivers/net/wireless/iwlwifi/iwl-3945-hw.h | 130 +--------------------------- 1 files changed, 1 insertions(+), 129 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h index 9526129..ea4bdd8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h @@ -102,10 +102,6 @@ #define IWL_EEPROM_ACCESS_TIMEOUT 5000 /* uSec */ #define IWL_EEPROM_ACCESS_DELAY 10 /* uSec */ -/* EEPROM field values */ -#define ANTENNA_SWITCH_NORMAL 0 -#define ANTENNA_SWITCH_INVERSE 1 - /* * Regulatory channel usage flags in EEPROM struct iwl_eeprom_channel.flags. * @@ -127,31 +123,10 @@ enum { EEPROM_CHANNEL_ACTIVE = (1 << 3), /* active scanning allowed */ EEPROM_CHANNEL_RADAR = (1 << 4), /* radar detection required */ EEPROM_CHANNEL_WIDE = (1 << 5), /* 20 MHz channel okay */ - EEPROM_CHANNEL_NARROW = (1 << 6), /* 10 MHz channel, not used */ + EEPROM_CHANNEL_NARROW = (1 << 6), /* 10 MHz channel (not used) */ EEPROM_CHANNEL_DFS = (1 << 7), /* dynamic freq selection candidate */ }; -/* EEPROM field lengths */ -#define EEPROM_BOARD_PBA_NUMBER_LENGTH 11 - -/* EEPROM field lengths */ -#define EEPROM_BOARD_PBA_NUMBER_LENGTH 11 -#define EEPROM_REGULATORY_SKU_ID_LENGTH 4 -#define EEPROM_REGULATORY_BAND1_CHANNELS_LENGTH 14 -#define EEPROM_REGULATORY_BAND2_CHANNELS_LENGTH 13 -#define EEPROM_REGULATORY_BAND3_CHANNELS_LENGTH 12 -#define EEPROM_REGULATORY_BAND4_CHANNELS_LENGTH 11 -#define EEPROM_REGULATORY_BAND5_CHANNELS_LENGTH 6 - -#define EEPROM_REGULATORY_CHANNELS_LENGTH ( \ - EEPROM_REGULATORY_BAND1_CHANNELS_LENGTH + \ - EEPROM_REGULATORY_BAND2_CHANNELS_LENGTH + \ - EEPROM_REGULATORY_BAND3_CHANNELS_LENGTH + \ - EEPROM_REGULATORY_BAND4_CHANNELS_LENGTH + \ - EEPROM_REGULATORY_BAND5_CHANNELS_LENGTH) - -#define EEPROM_REGULATORY_NUMBER_OF_BANDS 5 - /* SKU Capabilities */ #define EEPROM_SKU_CAP_SW_RF_KILL_ENABLE (1 << 0) #define EEPROM_SKU_CAP_HW_RF_KILL_ENABLE (1 << 1) @@ -646,15 +621,7 @@ struct iwl3945_eeprom { /* spectrum and channel data structures */ #define IWL_NUM_SCAN_RATES (2) -#define IWL_SCAN_FLAG_24GHZ (1<<0) -#define IWL_SCAN_FLAG_52GHZ (1<<1) -#define IWL_SCAN_FLAG_ACTIVE (1<<2) -#define IWL_SCAN_FLAG_DIRECT (1<<3) - -#define IWL_MAX_CMD_SIZE 1024 - #define IWL_DEFAULT_TX_RETRY 15 -#define IWL_MAX_TX_RETRY 16 /*********************************************/ @@ -665,101 +632,6 @@ struct iwl3945_eeprom { #define RX_QUEUE_MASK 255 #define RX_QUEUE_SIZE_LOG 8 -/* QoS definitions */ - -#define CW_MIN_OFDM 15 -#define CW_MAX_OFDM 1023 -#define CW_MIN_CCK 31 -#define CW_MAX_CCK 1023 - -#define QOS_TX0_CW_MIN_OFDM CW_MIN_OFDM -#define QOS_TX1_CW_MIN_OFDM CW_MIN_OFDM -#define QOS_TX2_CW_MIN_OFDM ((CW_MIN_OFDM + 1) / 2 - 1) -#define QOS_TX3_CW_MIN_OFDM ((CW_MIN_OFDM + 1) / 4 - 1) - -#define QOS_TX0_CW_MIN_CCK CW_MIN_CCK -#define QOS_TX1_CW_MIN_CCK CW_MIN_CCK -#define QOS_TX2_CW_MIN_CCK ((CW_MIN_CCK + 1) / 2 - 1) -#define QOS_TX3_CW_MIN_CCK ((CW_MIN_CCK + 1) / 4 - 1) - -#define QOS_TX0_CW_MAX_OFDM CW_MAX_OFDM -#define QOS_TX1_CW_MAX_OFDM CW_MAX_OFDM -#define QOS_TX2_CW_MAX_OFDM CW_MIN_OFDM -#define QOS_TX3_CW_MAX_OFDM ((CW_MIN_OFDM + 1) / 2 - 1) - -#define QOS_TX0_CW_MAX_CCK CW_MAX_CCK -#define QOS_TX1_CW_MAX_CCK CW_MAX_CCK -#define QOS_TX2_CW_MAX_CCK CW_MIN_CCK -#define QOS_TX3_CW_MAX_CCK ((CW_MIN_CCK + 1) / 2 - 1) - -#define QOS_TX0_AIFS 3 -#define QOS_TX1_AIFS 7 -#define QOS_TX2_AIFS 2 -#define QOS_TX3_AIFS 2 - -#define QOS_TX0_ACM 0 -#define QOS_TX1_ACM 0 -#define QOS_TX2_ACM 0 -#define QOS_TX3_ACM 0 - -#define QOS_TX0_TXOP_LIMIT_CCK 0 -#define QOS_TX1_TXOP_LIMIT_CCK 0 -#define QOS_TX2_TXOP_LIMIT_CCK 6016 -#define QOS_TX3_TXOP_LIMIT_CCK 3264 - -#define QOS_TX0_TXOP_LIMIT_OFDM 0 -#define QOS_TX1_TXOP_LIMIT_OFDM 0 -#define QOS_TX2_TXOP_LIMIT_OFDM 3008 -#define QOS_TX3_TXOP_LIMIT_OFDM 1504 - -#define DEF_TX0_CW_MIN_OFDM CW_MIN_OFDM -#define DEF_TX1_CW_MIN_OFDM CW_MIN_OFDM -#define DEF_TX2_CW_MIN_OFDM CW_MIN_OFDM -#define DEF_TX3_CW_MIN_OFDM CW_MIN_OFDM - -#define DEF_TX0_CW_MIN_CCK CW_MIN_CCK -#define DEF_TX1_CW_MIN_CCK CW_MIN_CCK -#define DEF_TX2_CW_MIN_CCK CW_MIN_CCK -#define DEF_TX3_CW_MIN_CCK CW_MIN_CCK - -#define DEF_TX0_CW_MAX_OFDM CW_MAX_OFDM -#define DEF_TX1_CW_MAX_OFDM CW_MAX_OFDM -#define DEF_TX2_CW_MAX_OFDM CW_MAX_OFDM -#define DEF_TX3_CW_MAX_OFDM CW_MAX_OFDM - -#define DEF_TX0_CW_MAX_CCK CW_MAX_CCK -#define DEF_TX1_CW_MAX_CCK CW_MAX_CCK -#define DEF_TX2_CW_MAX_CCK CW_MAX_CCK -#define DEF_TX3_CW_MAX_CCK CW_MAX_CCK - -#define DEF_TX0_AIFS (2) -#define DEF_TX1_AIFS (2) -#define DEF_TX2_AIFS (2) -#define DEF_TX3_AIFS (2) - -#define DEF_TX0_ACM 0 -#define DEF_TX1_ACM 0 -#define DEF_TX2_ACM 0 -#define DEF_TX3_ACM 0 - -#define DEF_TX0_TXOP_LIMIT_CCK 0 -#define DEF_TX1_TXOP_LIMIT_CCK 0 -#define DEF_TX2_TXOP_LIMIT_CCK 0 -#define DEF_TX3_TXOP_LIMIT_CCK 0 - -#define DEF_TX0_TXOP_LIMIT_OFDM 0 -#define DEF_TX1_TXOP_LIMIT_OFDM 0 -#define DEF_TX2_TXOP_LIMIT_OFDM 0 -#define DEF_TX3_TXOP_LIMIT_OFDM 0 - -#define QOS_QOS_SETS 3 -#define QOS_PARAM_SET_ACTIVE 0 -#define QOS_PARAM_SET_DEF_CCK 1 -#define QOS_PARAM_SET_DEF_OFDM 2 - -#define CTRL_QOS_NO_ACK (0x0020) -#define DCT_FLAG_EXT_QOS_ENABLED (0x10) - #define U32_PAD(n) ((4-(n))&0x3) /* -- 1.5.3.6 ^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 18/36] iwlwifi: clean up unused definitions in iwl-4965-hw.h 2007-11-29 3:09 ` [PATCH 17/36] iwlwifi: Clean up unused definitions in iwl-3945-hw.h Zhu Yi @ 2007-11-29 3:09 ` Zhu Yi 2007-11-29 3:09 ` [PATCH 19/36] iwlwifi: move uCode API definitions to iwl-4965-commands.h Zhu Yi 0 siblings, 1 reply; 36+ messages in thread From: Zhu Yi @ 2007-11-29 3:09 UTC (permalink / raw) To: linville; +Cc: linux-wireless, Ben Cahill, Zhu Yi From: Ben Cahill <ben.m.cahill@intel.com> Clean up unused definitions in iwl-4965-hw.h Signed-off-by: Ben Cahill <ben.m.cahill@intel.com> Signed-off-by: Zhu Yi <yi.zhu@intel.com> --- drivers/net/wireless/iwlwifi/iwl-4965-hw.h | 395 +--------------------------- 1 files changed, 3 insertions(+), 392 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h index 2f0da4d..4b61b89 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h @@ -106,10 +106,6 @@ #define IWL_EEPROM_ACCESS_TIMEOUT 5000 /* uSec */ #define IWL_EEPROM_ACCESS_DELAY 10 /* uSec */ -/* EEPROM field values */ -#define ANTENNA_SWITCH_NORMAL 0 -#define ANTENNA_SWITCH_INVERSE 1 - /* * Regulatory channel usage flags in EEPROM struct iwl4965_eeprom_channel.flags. * @@ -133,39 +129,13 @@ enum { EEPROM_CHANNEL_ACTIVE = (1 << 3), /* active scanning allowed */ EEPROM_CHANNEL_RADAR = (1 << 4), /* radar detection required */ EEPROM_CHANNEL_WIDE = (1 << 5), /* 20 MHz channel okay */ - EEPROM_CHANNEL_NARROW = (1 << 6), /* 10 MHz channel, not used */ + EEPROM_CHANNEL_NARROW = (1 << 6), /* 10 MHz channel (not used) */ EEPROM_CHANNEL_DFS = (1 << 7), /* dynamic freq selection candidate */ }; -/* EEPROM field lengths */ -#define EEPROM_BOARD_PBA_NUMBER_LENGTH 11 - -/* EEPROM field lengths */ -#define EEPROM_BOARD_PBA_NUMBER_LENGTH 11 -#define EEPROM_REGULATORY_SKU_ID_LENGTH 4 -#define EEPROM_REGULATORY_BAND1_CHANNELS_LENGTH 14 -#define EEPROM_REGULATORY_BAND2_CHANNELS_LENGTH 13 -#define EEPROM_REGULATORY_BAND3_CHANNELS_LENGTH 12 -#define EEPROM_REGULATORY_BAND4_CHANNELS_LENGTH 11 -#define EEPROM_REGULATORY_BAND5_CHANNELS_LENGTH 6 - -#define EEPROM_REGULATORY_BAND_24_FAT_CHANNELS_LENGTH 7 -#define EEPROM_REGULATORY_BAND_52_FAT_CHANNELS_LENGTH 11 -#define EEPROM_REGULATORY_CHANNELS_LENGTH ( \ - EEPROM_REGULATORY_BAND1_CHANNELS_LENGTH + \ - EEPROM_REGULATORY_BAND2_CHANNELS_LENGTH + \ - EEPROM_REGULATORY_BAND3_CHANNELS_LENGTH + \ - EEPROM_REGULATORY_BAND4_CHANNELS_LENGTH + \ - EEPROM_REGULATORY_BAND5_CHANNELS_LENGTH + \ - EEPROM_REGULATORY_BAND_24_FAT_CHANNELS_LENGTH + \ - EEPROM_REGULATORY_BAND_52_FAT_CHANNELS_LENGTH) - -#define EEPROM_REGULATORY_NUMBER_OF_BANDS 5 - /* SKU Capabilities */ #define EEPROM_SKU_CAP_SW_RF_KILL_ENABLE (1 << 0) #define EEPROM_SKU_CAP_HW_RF_KILL_ENABLE (1 << 1) -#define EEPROM_SKU_CAP_OP_MODE_MRC (1 << 7) /* *regulatory* channel data format in eeprom, one for each channel. * There are separate entries for FAT (40 MHz) vs. normal (20 MHz) channels. */ @@ -479,13 +449,6 @@ struct iwl4965_eeprom { */ #define CSR_HW_REV_WA_REG (CSR_BASE+0x22C) -/* HW I/F configuration */ -#define CSR_HW_IF_CONFIG_REG_BIT_ALMAGOR_MB (0x00000100) -#define CSR_HW_IF_CONFIG_REG_BIT_ALMAGOR_MM (0x00000200) -#define CSR_HW_IF_CONFIG_REG_BIT_SKU_MRC (0x00000400) -#define CSR_HW_IF_CONFIG_REG_BIT_BOARD_TYPE (0x00000800) -#define CSR_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_A (0x00000000) -#define CSR_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_B (0x00001000) #define CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM (0x00200000) /* interrupt flags in INTA, set by uCode or hardware (e.g. dma), @@ -514,20 +477,16 @@ struct iwl4965_eeprom { /* interrupt flags in FH (flow handler) (PCI busmaster DMA) */ #define CSR_FH_INT_BIT_ERR (1<<31) /* Error */ #define CSR_FH_INT_BIT_HI_PRIOR (1<<30) /* High priority Rx, bypass coalescing */ -#define CSR_FH_INT_BIT_RX_CHNL2 (1<<18) /* Rx channel 2 (3945 only) */ #define CSR_FH_INT_BIT_RX_CHNL1 (1<<17) /* Rx channel 1 */ #define CSR_FH_INT_BIT_RX_CHNL0 (1<<16) /* Rx channel 0 */ -#define CSR_FH_INT_BIT_TX_CHNL6 (1<<6) /* Tx channel 6 (3945 only) */ #define CSR_FH_INT_BIT_TX_CHNL1 (1<<1) /* Tx channel 1 */ #define CSR_FH_INT_BIT_TX_CHNL0 (1<<0) /* Tx channel 0 */ #define CSR_FH_INT_RX_MASK (CSR_FH_INT_BIT_HI_PRIOR | \ - CSR_FH_INT_BIT_RX_CHNL2 | \ CSR_FH_INT_BIT_RX_CHNL1 | \ CSR_FH_INT_BIT_RX_CHNL0) -#define CSR_FH_INT_TX_MASK (CSR_FH_INT_BIT_TX_CHNL6 | \ - CSR_FH_INT_BIT_TX_CHNL1 | \ +#define CSR_FH_INT_TX_MASK (CSR_FH_INT_BIT_TX_CHNL1 | \ CSR_FH_INT_BIT_TX_CHNL0 ) @@ -619,30 +578,6 @@ struct iwl4965_eeprom { /*=== FH (data Flow Handler) ===*/ #define FH_BASE (0x800) -#define FH_CBCC_TABLE (FH_BASE+0x140) -#define FH_TFDB_TABLE (FH_BASE+0x180) -#define FH_RCSR_TABLE (FH_BASE+0x400) -#define FH_RSSR_TABLE (FH_BASE+0x4c0) -#define FH_TCSR_TABLE (FH_BASE+0x500) -#define FH_TSSR_TABLE (FH_BASE+0x680) - -/* TFDB (Transmit Frame Buffer Descriptor) */ -#define FH_TFDB(_channel, buf) \ - (FH_TFDB_TABLE+((_channel)*2+(buf))*0x28) -#define ALM_FH_TFDB_CHNL_BUF_CTRL_REG(_channel) \ - (FH_TFDB_TABLE + 0x50 * _channel) -/* CBCC _channel is [0,2] */ -#define FH_CBCC(_channel) (FH_CBCC_TABLE+(_channel)*0x8) -#define FH_CBCC_CTRL(_channel) (FH_CBCC(_channel)+0x00) -#define FH_CBCC_BASE(_channel) (FH_CBCC(_channel)+0x04) - -/* RCSR _channel is [0,2] */ -#define FH_RCSR(_channel) (FH_RCSR_TABLE+(_channel)*0x40) -#define FH_RCSR_CONFIG(_channel) (FH_RCSR(_channel)+0x00) -#define FH_RCSR_RBD_BASE(_channel) (FH_RCSR(_channel)+0x04) -#define FH_RCSR_WPTR(_channel) (FH_RCSR(_channel)+0x20) -#define FH_RCSR_RPTR_ADDR(_channel) (FH_RCSR(_channel)+0x24) - #define FH_RSCSR_CHNL0_WPTR (FH_RSCSR_CHNL0_RBDCB_WPTR_REG) /* RSSR */ @@ -663,202 +598,19 @@ struct iwl4965_eeprom { #define RTC_INST_LOWER_BOUND (0x000000) #define RTC_DATA_LOWER_BOUND (0x800000) - -/* DBM */ - -#define ALM_FH_SRVC_CHNL (6) - -#define ALM_FH_RCSR_RX_CONFIG_REG_POS_RBDC_SIZE (20) -#define ALM_FH_RCSR_RX_CONFIG_REG_POS_IRQ_RBTH (4) - -#define ALM_FH_RCSR_RX_CONFIG_REG_BIT_WR_STTS_EN (0x08000000) - -#define ALM_FH_RCSR_RX_CONFIG_REG_VAL_DMA_CHNL_EN_ENABLE (0x80000000) - -#define ALM_FH_RCSR_RX_CONFIG_REG_VAL_RDRBD_EN_ENABLE (0x20000000) - -#define ALM_FH_RCSR_RX_CONFIG_REG_VAL_MAX_FRAG_SIZE_128 (0x01000000) - -#define ALM_FH_RCSR_RX_CONFIG_REG_VAL_IRQ_DEST_INT_HOST (0x00001000) - -#define ALM_FH_RCSR_RX_CONFIG_REG_VAL_MSG_MODE_FH (0x00000000) - -#define ALM_FH_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_TXF (0x00000000) -#define ALM_FH_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_DRIVER (0x00000001) - -#define ALM_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE_VAL (0x00000000) -#define ALM_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL (0x00000008) - -#define ALM_FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_IFTFD (0x00200000) - -#define ALM_FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_NOINT (0x00000000) - -#define ALM_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE (0x00000000) -#define ALM_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE (0x80000000) - -#define ALM_FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID (0x00004000) - -#define ALM_FH_TCSR_CHNL_TX_BUF_STS_REG_BIT_TFDB_WPTR (0x00000001) - -#define ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TXPD_ON (0xFF000000) -#define ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_TXPD_ON (0x00FF0000) - -#define ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_MAX_FRAG_SIZE_128B (0x00000400) - -#define ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TFD_ON (0x00000100) -#define ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_CBB_ON (0x00000080) - -#define ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RSP_WAIT_TH (0x00000020) -#define ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_RSP_WAIT_TH (0x00000005) - -#define ALM_TB_MAX_BYTES_COUNT (0xFFF0) - -#define ALM_FH_TSSR_TX_STATUS_REG_BIT_BUFS_EMPTY(_channel) \ - ((1LU << _channel) << 24) -#define ALM_FH_TSSR_TX_STATUS_REG_BIT_NO_PEND_REQ(_channel) \ - ((1LU << _channel) << 16) - -#define ALM_FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(_channel) \ - (ALM_FH_TSSR_TX_STATUS_REG_BIT_BUFS_EMPTY(_channel) | \ - ALM_FH_TSSR_TX_STATUS_REG_BIT_NO_PEND_REQ(_channel)) -#define PCI_CFG_REV_ID_BIT_BASIC_SKU (0x40) /* bit 6 */ -#define PCI_CFG_REV_ID_BIT_RTP (0x80) /* bit 7 */ - #define HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED (0x00000004) -#define TFD_QUEUE_MIN 0 -#define TFD_QUEUE_MAX 6 #define TFD_QUEUE_SIZE_MAX (256) /* spectrum and channel data structures */ #define IWL_NUM_SCAN_RATES (2) -#define IWL_SCAN_FLAG_24GHZ (1<<0) -#define IWL_SCAN_FLAG_52GHZ (1<<1) -#define IWL_SCAN_FLAG_ACTIVE (1<<2) -#define IWL_SCAN_FLAG_DIRECT (1<<3) - -#define IWL_MAX_CMD_SIZE 1024 - #define IWL_DEFAULT_TX_RETRY 15 -#define IWL_MAX_TX_RETRY 16 - -/*********************************************/ - -#define RFD_SIZE 4 -#define NUM_TFD_CHUNKS 4 #define RX_QUEUE_SIZE 256 #define RX_QUEUE_MASK 255 #define RX_QUEUE_SIZE_LOG 8 -/* QoS definitions */ - -#define CW_MIN_OFDM 15 -#define CW_MAX_OFDM 1023 -#define CW_MIN_CCK 31 -#define CW_MAX_CCK 1023 - -#define QOS_TX0_CW_MIN_OFDM CW_MIN_OFDM -#define QOS_TX1_CW_MIN_OFDM CW_MIN_OFDM -#define QOS_TX2_CW_MIN_OFDM ((CW_MIN_OFDM + 1) / 2 - 1) -#define QOS_TX3_CW_MIN_OFDM ((CW_MIN_OFDM + 1) / 4 - 1) - -#define QOS_TX0_CW_MIN_CCK CW_MIN_CCK -#define QOS_TX1_CW_MIN_CCK CW_MIN_CCK -#define QOS_TX2_CW_MIN_CCK ((CW_MIN_CCK + 1) / 2 - 1) -#define QOS_TX3_CW_MIN_CCK ((CW_MIN_CCK + 1) / 4 - 1) - -#define QOS_TX0_CW_MAX_OFDM CW_MAX_OFDM -#define QOS_TX1_CW_MAX_OFDM CW_MAX_OFDM -#define QOS_TX2_CW_MAX_OFDM CW_MIN_OFDM -#define QOS_TX3_CW_MAX_OFDM ((CW_MIN_OFDM + 1) / 2 - 1) - -#define QOS_TX0_CW_MAX_CCK CW_MAX_CCK -#define QOS_TX1_CW_MAX_CCK CW_MAX_CCK -#define QOS_TX2_CW_MAX_CCK CW_MIN_CCK -#define QOS_TX3_CW_MAX_CCK ((CW_MIN_CCK + 1) / 2 - 1) - -#define QOS_TX0_AIFS 3 -#define QOS_TX1_AIFS 7 -#define QOS_TX2_AIFS 2 -#define QOS_TX3_AIFS 2 - -#define QOS_TX0_ACM 0 -#define QOS_TX1_ACM 0 -#define QOS_TX2_ACM 0 -#define QOS_TX3_ACM 0 - -#define QOS_TX0_TXOP_LIMIT_CCK 0 -#define QOS_TX1_TXOP_LIMIT_CCK 0 -#define QOS_TX2_TXOP_LIMIT_CCK 6016 -#define QOS_TX3_TXOP_LIMIT_CCK 3264 - -#define QOS_TX0_TXOP_LIMIT_OFDM 0 -#define QOS_TX1_TXOP_LIMIT_OFDM 0 -#define QOS_TX2_TXOP_LIMIT_OFDM 3008 -#define QOS_TX3_TXOP_LIMIT_OFDM 1504 - -#define DEF_TX0_CW_MIN_OFDM CW_MIN_OFDM -#define DEF_TX1_CW_MIN_OFDM CW_MIN_OFDM -#define DEF_TX2_CW_MIN_OFDM CW_MIN_OFDM -#define DEF_TX3_CW_MIN_OFDM CW_MIN_OFDM - -#define DEF_TX0_CW_MIN_CCK CW_MIN_CCK -#define DEF_TX1_CW_MIN_CCK CW_MIN_CCK -#define DEF_TX2_CW_MIN_CCK CW_MIN_CCK -#define DEF_TX3_CW_MIN_CCK CW_MIN_CCK - -#define DEF_TX0_CW_MAX_OFDM CW_MAX_OFDM -#define DEF_TX1_CW_MAX_OFDM CW_MAX_OFDM -#define DEF_TX2_CW_MAX_OFDM CW_MAX_OFDM -#define DEF_TX3_CW_MAX_OFDM CW_MAX_OFDM - -#define DEF_TX0_CW_MAX_CCK CW_MAX_CCK -#define DEF_TX1_CW_MAX_CCK CW_MAX_CCK -#define DEF_TX2_CW_MAX_CCK CW_MAX_CCK -#define DEF_TX3_CW_MAX_CCK CW_MAX_CCK - -#define DEF_TX0_AIFS (2) -#define DEF_TX1_AIFS (2) -#define DEF_TX2_AIFS (2) -#define DEF_TX3_AIFS (2) - -#define DEF_TX0_ACM 0 -#define DEF_TX1_ACM 0 -#define DEF_TX2_ACM 0 -#define DEF_TX3_ACM 0 - -#define DEF_TX0_TXOP_LIMIT_CCK 0 -#define DEF_TX1_TXOP_LIMIT_CCK 0 -#define DEF_TX2_TXOP_LIMIT_CCK 0 -#define DEF_TX3_TXOP_LIMIT_CCK 0 - -#define DEF_TX0_TXOP_LIMIT_OFDM 0 -#define DEF_TX1_TXOP_LIMIT_OFDM 0 -#define DEF_TX2_TXOP_LIMIT_OFDM 0 -#define DEF_TX3_TXOP_LIMIT_OFDM 0 - -#define QOS_QOS_SETS 3 -#define QOS_PARAM_SET_ACTIVE 0 -#define QOS_PARAM_SET_DEF_CCK 1 -#define QOS_PARAM_SET_DEF_OFDM 2 - -#define CTRL_QOS_NO_ACK (0x0020) -#define DCT_FLAG_EXT_QOS_ENABLED (0x10) - -#define U32_PAD(n) ((4-(n))&0x3) - -/* - * Generic queue structure - * - * Contains common data for Rx and Tx queues - */ -#define TFD_CTL_COUNT_SET(n) (n<<24) -#define TFD_CTL_COUNT_GET(ctl) ((ctl>>24) & 7) -#define TFD_CTL_PAD_SET(n) (n<<28) -#define TFD_CTL_PAD_GET(ctl) (ctl>>28) - #define TFD_TX_CMD_SLOTS 256 #define TFD_CMD_SLOTS 32 @@ -917,28 +669,13 @@ enum { (((t) < IWL_TX_POWER_TEMPERATURE_MIN) || \ ((t) > IWL_TX_POWER_TEMPERATURE_MAX)) -#define IWL_TX_POWER_ILLEGAL_TEMPERATURE (300) - -#define IWL_TX_POWER_TEMPERATURE_DIFFERENCE (2) - #define IWL_TX_POWER_MIMO_REGULATORY_COMPENSATION (6) #define IWL_TX_POWER_TARGET_POWER_MIN (0) /* 0 dBm = 1 milliwatt */ #define IWL_TX_POWER_TARGET_POWER_MAX (16) /* 16 dBm */ -/* timeout equivalent to 3 minutes */ -#define IWL_TX_POWER_TIMELIMIT_NOCALIB 1800000000 - -#define IWL_TX_POWER_CCK_COMPENSATION (9) - #define MIN_TX_GAIN_INDEX (0) #define MIN_TX_GAIN_INDEX_52GHZ_EXT (-9) -#define MAX_TX_GAIN_INDEX_52GHZ (98) -#define MIN_TX_GAIN_52GHZ (98) -#define MAX_TX_GAIN_INDEX_24GHZ (98) -#define MIN_TX_GAIN_24GHZ (98) -#define MAX_TX_GAIN (0) -#define MAX_TX_GAIN_52GHZ_EXT (-9) #define IWL_TX_POWER_DEFAULT_REGULATORY_24 (34) #define IWL_TX_POWER_DEFAULT_REGULATORY_52 (34) @@ -949,48 +686,6 @@ enum { #define IWL_TX_POWER_SATURATION_MIN (20) #define IWL_TX_POWER_SATURATION_MAX (50) -/* dv *0.4 = dt; so that 5 degrees temperature diff equals - * 12.5 in voltage diff */ -#define IWL_TX_TEMPERATURE_UPDATE_LIMIT 9 - -#define IWL_INVALID_CHANNEL (0xffffffff) -#define IWL_TX_POWER_REGITRY_BIT (2) - -#define MIN_IWL_TX_POWER_CALIB_DUR (100) -#define IWL_CCK_FROM_OFDM_POWER_DIFF (-5) -#define IWL_CCK_FROM_OFDM_INDEX_DIFF (9) - -/* Number of entries in the gain table */ -#define POWER_GAIN_NUM_ENTRIES 78 -#define TX_POW_MAX_SESSION_NUM 5 -/* timeout equivalent to 3 minutes */ -#define TX_IWL_TIMELIMIT_NOCALIB 1800000000 - -/* Kedron TX_CALIB_STATES */ -#define IWL_TX_CALIB_STATE_SEND_TX 0x00000001 -#define IWL_TX_CALIB_WAIT_TX_RESPONSE 0x00000002 -#define IWL_TX_CALIB_ENABLED 0x00000004 -#define IWL_TX_CALIB_XVT_ON 0x00000008 -#define IWL_TX_CALIB_TEMPERATURE_CORRECT 0x00000010 -#define IWL_TX_CALIB_WORKING_WITH_XVT 0x00000020 -#define IWL_TX_CALIB_XVT_PERIODICAL 0x00000040 - -#define NUM_IWL_TX_CALIB_SETTINS 5 /* Number of tx correction groups */ - -#define IWL_MIN_POWER_IN_VP_TABLE 1 /* 0.5dBm multiplied by 2 */ -#define IWL_MAX_POWER_IN_VP_TABLE 40 /* 20dBm - multiplied by 2 (because - * entries are for each 0.5dBm) */ -#define IWL_STEP_IN_VP_TABLE 1 /* 0.5dB - multiplied by 2 */ -#define IWL_NUM_POINTS_IN_VPTABLE \ - (1 + IWL_MAX_POWER_IN_VP_TABLE - IWL_MIN_POWER_IN_VP_TABLE) - -#define MIN_TX_GAIN_INDEX (0) -#define MAX_TX_GAIN_INDEX_52GHZ (98) -#define MIN_TX_GAIN_52GHZ (98) -#define MAX_TX_GAIN_INDEX_24GHZ (98) -#define MIN_TX_GAIN_24GHZ (98) -#define MAX_TX_GAIN (0) - /* First and last channels of all groups */ #define CALIB_IWL_TX_ATTEN_GR1_FCH 34 #define CALIB_IWL_TX_ATTEN_GR1_LCH 43 @@ -1003,7 +698,6 @@ enum { #define CALIB_IWL_TX_ATTEN_GR5_FCH 1 #define CALIB_IWL_TX_ATTEN_GR5_LCH 20 - union iwl4965_tx_power_dual_stream { struct { u8 radio_tx_gain[2]; @@ -1043,23 +737,6 @@ union iwl4965_tx_power_dual_stream { #define RXON_RX_CHAIN_MIMO_FORCE_POS (14) -#define MCS_DUP_6M_PLCP 0x20 - -/* OFDM HT rate masks */ -/* ***************************************** */ -#define R_MCS_6M_MSK 0x1 -#define R_MCS_12M_MSK 0x2 -#define R_MCS_18M_MSK 0x4 -#define R_MCS_24M_MSK 0x8 -#define R_MCS_36M_MSK 0x10 -#define R_MCS_48M_MSK 0x20 -#define R_MCS_54M_MSK 0x40 -#define R_MCS_60M_MSK 0x80 -#define R_MCS_12M_DUAL_MSK 0x100 -#define R_MCS_24M_DUAL_MSK 0x200 -#define R_MCS_36M_DUAL_MSK 0x400 -#define R_MCS_48M_DUAL_MSK 0x800 - /* Flow Handler Definitions */ /**********************/ @@ -1107,7 +784,6 @@ union iwl4965_tx_power_dual_stream { #define IWL_FH_TCSR_LOWER_BOUND (IWL_FH_REGS_LOWER_BOUND + 0xD00) #define IWL_FH_TCSR_UPPER_BOUND (IWL_FH_REGS_LOWER_BOUND + 0xE60) -#define IWL_FH_TCSR_CHNL_NUM (7) #define IWL_FH_TCSR_CHNL_TX_CONFIG_REG(_chnl) \ (IWL_FH_TCSR_LOWER_BOUND + 0x20 * _chnl) @@ -1116,23 +792,8 @@ union iwl4965_tx_power_dual_stream { #define IWL_FH_TSSR_LOWER_BOUND (IWL_FH_REGS_LOWER_BOUND + 0xEA0) #define IWL_FH_TSSR_UPPER_BOUND (IWL_FH_REGS_LOWER_BOUND + 0xEC0) -#define IWL_FH_TSSR_TX_MSG_CONFIG_REG (IWL_FH_TSSR_LOWER_BOUND + 0x008) #define IWL_FH_TSSR_TX_STATUS_REG (IWL_FH_TSSR_LOWER_BOUND + 0x010) -#define IWL_FH_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TXPD_ON (0xFF000000) -#define IWL_FH_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_TXPD_ON (0x00FF0000) - -#define IWL_FH_TSSR_TX_MSG_CONFIG_REG_VAL_MAX_FRAG_SIZE_64B (0x00000000) -#define IWL_FH_TSSR_TX_MSG_CONFIG_REG_VAL_MAX_FRAG_SIZE_128B (0x00000400) -#define IWL_FH_TSSR_TX_MSG_CONFIG_REG_VAL_MAX_FRAG_SIZE_256B (0x00000800) -#define IWL_FH_TSSR_TX_MSG_CONFIG_REG_VAL_MAX_FRAG_SIZE_512B (0x00000C00) - -#define IWL_FH_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TFD_ON (0x00000100) -#define IWL_FH_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_CBB_ON (0x00000080) - -#define IWL_FH_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RSP_WAIT_TH (0x00000020) -#define IWL_FH_TSSR_TX_MSG_CONFIG_REG_VAL_RSP_WAIT_TH (0x00000005) - #define IWL_FH_TSSR_TX_STATUS_REG_BIT_BUFS_EMPTY(_chnl) \ ((1 << (_chnl)) << 24) #define IWL_FH_TSSR_TX_STATUS_REG_BIT_NO_PEND_REQ(_chnl) \ @@ -1142,60 +803,21 @@ union iwl4965_tx_power_dual_stream { (IWL_FH_TSSR_TX_STATUS_REG_BIT_BUFS_EMPTY(_chnl) | \ IWL_FH_TSSR_TX_STATUS_REG_BIT_NO_PEND_REQ(_chnl)) -/* TCSR: tx_config register values */ -#define IWL_FH_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_TXF (0x00000000) -#define IWL_FH_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_DRIVER (0x00000001) -#define IWL_FH_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_ARC (0x00000002) - -#define IWL_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE_VAL (0x00000000) #define IWL_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL (0x00000008) -#define IWL_FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_NOINT (0x00000000) -#define IWL_FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD (0x00100000) -#define IWL_FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_IFTFD (0x00200000) - -#define IWL_FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_NOINT (0x00000000) -#define IWL_FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_ENDTFD (0x00400000) -#define IWL_FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_IFTFD (0x00800000) - -#define IWL_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE (0x00000000) -#define IWL_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE_EOF (0x40000000) #define IWL_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE (0x80000000) -#define IWL_FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_EMPTY (0x00000000) -#define IWL_FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_WAIT (0x00002000) -#define IWL_FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID (0x00000003) - -#define IWL_FH_TCSR_CHNL_TX_BUF_STS_REG_BIT_TFDB_WPTR (0x00000001) - -#define IWL_FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM (20) -#define IWL_FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_IDX (12) - /* RCSR: channel 0 rx_config register defines */ -#define FH_RCSR_CHNL0_RX_CONFIG_DMA_CHNL_EN_MASK (0xC0000000) /* bits 30-31 */ -#define FH_RCSR_CHNL0_RX_CONFIG_RBDBC_SIZE_MASK (0x00F00000) /* bits 20-23 */ -#define FH_RCSR_CHNL0_RX_CONFIG_RB_SIZE_MASK (0x00030000) /* bits 16-17 */ -#define FH_RCSR_CHNL0_RX_CONFIG_SINGLE_FRAME_MASK (0x00008000) /* bit 15 */ -#define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_MASK (0x00001000) /* bit 12 */ -#define FH_RCSR_CHNL0_RX_CONFIG_RB_TIMEOUT_MASK (0x00000FF0) /* bit 4-11 */ #define FH_RCSR_RX_CONFIG_RBDCB_SIZE_BITSHIFT (20) -#define FH_RCSR_RX_CONFIG_RB_SIZE_BITSHIFT (16) -/* RCSR: rx_config register values */ -#define FH_RCSR_RX_CONFIG_CHNL_EN_PAUSE_VAL (0x00000000) -#define FH_RCSR_RX_CONFIG_CHNL_EN_PAUSE_EOF_VAL (0x40000000) #define FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL (0x80000000) #define IWL_FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K (0x00000000) /* RCSR channel 0 config register values */ -#define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_NO_INT_VAL (0x00000000) #define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL (0x00001000) -/* RSCSR: defs used in normal mode */ -#define FH_RSCSR_CHNL0_RBDCB_WPTR_MASK (0x00000FFF) /* bits 0-11 */ - #define SCD_WIN_SIZE 64 #define SCD_FRAME_LIMIT 64 @@ -1210,12 +832,6 @@ union iwl4965_tx_power_dual_stream { #define SCD_TXFACT_REG_TXFIFO_MASK(lo, hi) \ ((1<<(hi))|((1<<(hi))-(1<<(lo)))) - -#define SCD_MODE_REG_BIT_SEARCH_MODE (1<<0) -#define SCD_MODE_REG_BIT_SBYP_MODE (1<<1) - -#define SCD_TXFIFO_POS_TID (0) -#define SCD_TXFIFO_POS_RA (4) #define SCD_QUEUE_STTS_REG_POS_ACTIVE (0) #define SCD_QUEUE_STTS_REG_POS_TXF (1) #define SCD_QUEUE_STTS_REG_POS_WSL (5) @@ -1223,14 +839,9 @@ union iwl4965_tx_power_dual_stream { #define SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN (10) #define SCD_QUEUE_STTS_REG_MSK (0x0007FC00) -#define SCD_QUEUE_RA_TID_MAP_RATID_MSK (0x01FF) - #define SCD_QUEUE_CTX_REG1_WIN_SIZE_POS (0) #define SCD_QUEUE_CTX_REG1_WIN_SIZE_MSK (0x0000007F) -#define SCD_QUEUE_CTX_REG1_CREDIT_POS (8) -#define SCD_QUEUE_CTX_REG1_CREDIT_MSK (0x00FFFF00) -#define SCD_QUEUE_CTX_REG1_SUPER_CREDIT_POS (24) -#define SCD_QUEUE_CTX_REG1_SUPER_CREDIT_MSK (0xFF000000) + #define SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS (16) #define SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK (0x007F0000) -- 1.5.3.6 ^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 19/36] iwlwifi: move uCode API definitions to iwl-4965-commands.h 2007-11-29 3:09 ` [PATCH 18/36] iwlwifi: clean up unused definitions in iwl-4965-hw.h Zhu Yi @ 2007-11-29 3:09 ` Zhu Yi 2007-11-29 3:10 ` [PATCH 20/36] iwlwifi: move HT_IE_EXT_CHANNEL_* driver definitions to iwl-4965.h Zhu Yi 0 siblings, 1 reply; 36+ messages in thread From: Zhu Yi @ 2007-11-29 3:09 UTC (permalink / raw) To: linville; +Cc: linux-wireless, Ben Cahill, Zhu Yi From: Ben Cahill <ben.m.cahill@intel.com> Move uCode API definitions to iwl-4965-commands.h Signed-off-by: Ben Cahill <ben.m.cahill@intel.com> Signed-off-by: Zhu Yi <yi.zhu@intel.com> --- drivers/net/wireless/iwlwifi/iwl-4965-commands.h | 39 ++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-4965-hw.h | 37 -------------------- 2 files changed, 39 insertions(+), 37 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-commands.h b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h index bd55709..49582b9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h @@ -335,6 +335,21 @@ enum { RXON_DEV_TYPE_SNIFFER = 6, }; + +#define RXON_RX_CHAIN_DRIVER_FORCE_MSK __constant_cpu_to_le16(0x1<<0) +#define RXON_RX_CHAIN_VALID_MSK __constant_cpu_to_le16(0x7<<1) +#define RXON_RX_CHAIN_VALID_POS (1) +#define RXON_RX_CHAIN_FORCE_SEL_MSK __constant_cpu_to_le16(0x7<<4) +#define RXON_RX_CHAIN_FORCE_SEL_POS (4) +#define RXON_RX_CHAIN_FORCE_MIMO_SEL_MSK __constant_cpu_to_le16(0x7<<7) +#define RXON_RX_CHAIN_FORCE_MIMO_SEL_POS (7) +#define RXON_RX_CHAIN_CNT_MSK __constant_cpu_to_le16(0x3<<10) +#define RXON_RX_CHAIN_CNT_POS (10) +#define RXON_RX_CHAIN_MIMO_CNT_MSK __constant_cpu_to_le16(0x3<<12) +#define RXON_RX_CHAIN_MIMO_CNT_POS (12) +#define RXON_RX_CHAIN_MIMO_FORCE_MSK __constant_cpu_to_le16(0x1<<14) +#define RXON_RX_CHAIN_MIMO_FORCE_POS (14) + /* rx_config flags */ /* band & modulation selection */ #define RXON_FLG_BAND_24G_MSK __constant_cpu_to_le32(1 << 0) @@ -358,6 +373,21 @@ enum { * (according to ON_AIR deassertion) */ #define RXON_FLG_TSF2HOST_MSK __constant_cpu_to_le32(1 << 15) + +/* HT flags */ +#define RXON_FLG_CTRL_CHANNEL_LOC_POS (22) +#define RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK __constant_cpu_to_le32(0x1<<22) + +#define RXON_FLG_HT_OPERATING_MODE_POS (23) + +#define RXON_FLG_HT_PROT_MSK __constant_cpu_to_le32(0x1<<23) +#define RXON_FLG_FAT_PROT_MSK __constant_cpu_to_le32(0x2<<23) + +#define RXON_FLG_CHANNEL_MODE_POS (25) +#define RXON_FLG_CHANNEL_MODE_MSK __constant_cpu_to_le32(0x3<<25) +#define RXON_FLG_CHANNEL_MODE_PURE_40_MSK __constant_cpu_to_le32(0x1<<25) +#define RXON_FLG_CHANNEL_MODE_MIXED_MSK __constant_cpu_to_le32(0x2<<25) + /* rx_config filter flags */ /* accept all data frames */ #define RXON_FILTER_PROMISC_MSK __constant_cpu_to_le32(1 << 0) @@ -431,6 +461,15 @@ struct iwl4965_tx_power { #define POWER_TABLE_NUM_ENTRIES 33 #define POWER_TABLE_NUM_HT_OFDM_ENTRIES 32 #define POWER_TABLE_CCK_ENTRY 32 + +union iwl4965_tx_power_dual_stream { + struct { + u8 radio_tx_gain[2]; + u8 dsp_predis_atten[2]; + } s; + u32 dw; +}; + struct tx_power_dual_stream { __le32 dw; } __attribute__ ((packed)); diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h index 4b61b89..c5fa086 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h @@ -698,45 +698,8 @@ enum { #define CALIB_IWL_TX_ATTEN_GR5_FCH 1 #define CALIB_IWL_TX_ATTEN_GR5_LCH 20 -union iwl4965_tx_power_dual_stream { - struct { - u8 radio_tx_gain[2]; - u8 dsp_predis_atten[2]; - } s; - u32 dw; -}; - /********************* END TXPOWER *****************************************/ -/* HT flags */ -#define RXON_FLG_CTRL_CHANNEL_LOC_POS (22) -#define RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK __constant_cpu_to_le32(0x1<<22) - -#define RXON_FLG_HT_OPERATING_MODE_POS (23) - -#define RXON_FLG_HT_PROT_MSK __constant_cpu_to_le32(0x1<<23) -#define RXON_FLG_FAT_PROT_MSK __constant_cpu_to_le32(0x2<<23) - -#define RXON_FLG_CHANNEL_MODE_POS (25) -#define RXON_FLG_CHANNEL_MODE_MSK __constant_cpu_to_le32(0x3<<25) -#define RXON_FLG_CHANNEL_MODE_PURE_40_MSK __constant_cpu_to_le32(0x1<<25) -#define RXON_FLG_CHANNEL_MODE_MIXED_MSK __constant_cpu_to_le32(0x2<<25) - -#define RXON_RX_CHAIN_DRIVER_FORCE_MSK __constant_cpu_to_le16(0x1<<0) -#define RXON_RX_CHAIN_VALID_MSK __constant_cpu_to_le16(0x7<<1) -#define RXON_RX_CHAIN_VALID_POS (1) -#define RXON_RX_CHAIN_FORCE_SEL_MSK __constant_cpu_to_le16(0x7<<4) -#define RXON_RX_CHAIN_FORCE_SEL_POS (4) -#define RXON_RX_CHAIN_FORCE_MIMO_SEL_MSK __constant_cpu_to_le16(0x7<<7) -#define RXON_RX_CHAIN_FORCE_MIMO_SEL_POS (7) -#define RXON_RX_CHAIN_CNT_MSK __constant_cpu_to_le16(0x3<<10) -#define RXON_RX_CHAIN_CNT_POS (10) -#define RXON_RX_CHAIN_MIMO_CNT_MSK __constant_cpu_to_le16(0x3<<12) -#define RXON_RX_CHAIN_MIMO_CNT_POS (12) -#define RXON_RX_CHAIN_MIMO_FORCE_MSK __constant_cpu_to_le16(0x1<<14) -#define RXON_RX_CHAIN_MIMO_FORCE_POS (14) - - /* Flow Handler Definitions */ /**********************/ -- 1.5.3.6 ^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 20/36] iwlwifi: move HT_IE_EXT_CHANNEL_* driver definitions to iwl-4965.h 2007-11-29 3:09 ` [PATCH 19/36] iwlwifi: move uCode API definitions to iwl-4965-commands.h Zhu Yi @ 2007-11-29 3:10 ` Zhu Yi 2007-11-29 3:10 ` [PATCH 21/36] iwlwifi: document temperature calculation Zhu Yi 0 siblings, 1 reply; 36+ messages in thread From: Zhu Yi @ 2007-11-29 3:10 UTC (permalink / raw) To: linville; +Cc: linux-wireless, Ben Cahill, Zhu Yi From: Ben Cahill <ben.m.cahill@intel.com> Move HT_IE_EXT_CHANNEL_* driver definitions to iwl-4965.h Add comments to guide .h file usage (hw/api/driver definitions) Minor comment cleanup Signed-off-by: Ben Cahill <ben.m.cahill@intel.com> Signed-off-by: Zhu Yi <yi.zhu@intel.com> --- drivers/net/wireless/iwlwifi/iwl-3945-commands.h | 5 +++ drivers/net/wireless/iwlwifi/iwl-3945-hw.h | 32 ++++++++++---------- drivers/net/wireless/iwlwifi/iwl-3945.h | 5 +++ drivers/net/wireless/iwlwifi/iwl-4965-commands.h | 5 +++ drivers/net/wireless/iwlwifi/iwl-4965-hw.h | 35 ++++++++++----------- drivers/net/wireless/iwlwifi/iwl-4965.h | 25 ++++++++++++--- 6 files changed, 68 insertions(+), 39 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-commands.h b/drivers/net/wireless/iwlwifi/iwl-3945-commands.h index dc7498d..794db78 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-commands.h @@ -60,6 +60,11 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *****************************************************************************/ +/* + * Please use this file (iwl-3945-commands.h) only for uCode API definitions. + * Please use iwl-3945-hw.h for hardware-related definitions. + * Please use iwl-3945.h for driver implementation definitions. + */ #ifndef __iwl_3945_commands_h__ #define __iwl_3945_commands_h__ diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h index ea4bdd8..42da5be 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h @@ -60,6 +60,11 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *****************************************************************************/ +/* + * Please use this file (iwl-3945-hw.h) only for hardware-related definitions. + * Please use iwl-3945-commands.h for uCode API definitions. + * Please use iwl-3945.h for driver implementation definitions. + */ #ifndef __iwl_3945_hw__ #define __iwl_3945_hw__ @@ -73,9 +78,7 @@ /* Tx rates */ #define IWL_CCK_RATES 4 #define IWL_OFDM_RATES 8 - #define IWL_HT_RATES 0 - #define IWL_MAX_RATES (IWL_CCK_RATES+IWL_OFDM_RATES+IWL_HT_RATES) /* Time constants */ @@ -545,11 +548,6 @@ struct iwl3945_eeprom { #define FH_TSSR_CBB_BASE (FH_TSSR_TABLE+0x000) #define FH_TSSR_MSG_CONFIG (FH_TSSR_TABLE+0x008) #define FH_TSSR_TX_STATUS (FH_TSSR_TABLE+0x010) -/* 18 - reserved */ - -/* card static random access memory (SRAM) for processor data and instructs */ -#define RTC_INST_LOWER_BOUND (0x000000) -#define RTC_DATA_LOWER_BOUND (0x800000) /* DBM */ @@ -618,7 +616,6 @@ struct iwl3945_eeprom { #define TFD_QUEUE_MAX 6 #define TFD_QUEUE_SIZE_MAX (256) -/* spectrum and channel data structures */ #define IWL_NUM_SCAN_RATES (2) #define IWL_DEFAULT_TX_RETRY 15 @@ -634,11 +631,6 @@ struct iwl3945_eeprom { #define U32_PAD(n) ((4-(n))&0x3) -/* - * Generic queue structure - * - * Contains common data for Rx and Tx queues - */ #define TFD_CTL_COUNT_SET(n) (n<<24) #define TFD_CTL_COUNT_GET(ctl) ((ctl>>24) & 7) #define TFD_CTL_PAD_SET(n) (n<<28) @@ -656,18 +648,26 @@ struct iwl3945_eeprom { #define RX_FREE_BUFFERS 64 #define RX_LOW_WATERMARK 8 - +/* Size of one Rx buffer in host DRAM */ #define IWL_RX_BUF_SIZE 3000 -/* card static random access memory (SRAM) for processor data and instructs */ + +/* Sizes and addresses for instruction and data memory (SRAM) in + * 3945's embedded processor. Driver access is via HBUS_TARG_MEM_* regs. */ +#define RTC_INST_LOWER_BOUND (0x000000) #define ALM_RTC_INST_UPPER_BOUND (0x014000) + +#define RTC_DATA_LOWER_BOUND (0x800000) #define ALM_RTC_DATA_UPPER_BOUND (0x808000) #define ALM_RTC_INST_SIZE (ALM_RTC_INST_UPPER_BOUND - RTC_INST_LOWER_BOUND) #define ALM_RTC_DATA_SIZE (ALM_RTC_DATA_UPPER_BOUND - RTC_DATA_LOWER_BOUND) -#define IWL_MAX_BSM_SIZE ALM_RTC_INST_SIZE #define IWL_MAX_INST_SIZE ALM_RTC_INST_SIZE #define IWL_MAX_DATA_SIZE ALM_RTC_DATA_SIZE + +/* Size of uCode instruction memory in bootstrap state machine */ +#define IWL_MAX_BSM_SIZE ALM_RTC_INST_SIZE + #define IWL_MAX_NUM_QUEUES 8 static inline int iwl3945_hw_valid_rtc_data_addr(u32 addr) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 2f3a8b4..75cef3e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -23,6 +23,11 @@ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 * *****************************************************************************/ +/* + * Please use this file (iwl-3945.h) for driver implementation definitions. + * Please use iwl-3945-commands.h for uCode API definitions. + * Please use iwl-3945-hw.h for hardware-related definitions. + */ #ifndef __iwl_3945_h__ #define __iwl_3945_h__ diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-commands.h b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h index 49582b9..9910939 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h @@ -60,6 +60,11 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *****************************************************************************/ +/* + * Please use this file (iwl-4965-commands.h) only for uCode API definitions. + * Please use iwl-4965-hw.h for hardware-related definitions. + * Please use iwl-4965.h for driver implementation definitions. + */ #ifndef __iwl4965_commands_h__ #define __iwl4965_commands_h__ diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h index c5fa086..6f91c02 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h @@ -60,6 +60,11 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *****************************************************************************/ +/* + * Please use this file (iwl-4965-hw.h) only for hardware-related definitions. + * Use iwl-4965-commands.h for uCode API definitions. + * Use iwl-4965.h for driver implementation definitions. + */ #ifndef __iwl_4965_hw_h__ #define __iwl_4965_hw_h__ @@ -77,9 +82,7 @@ /* Tx rates */ #define IWL_CCK_RATES 4 #define IWL_OFDM_RATES 8 - #define IWL_HT_RATES 16 - #define IWL_MAX_RATES (IWL_CCK_RATES+IWL_OFDM_RATES+IWL_HT_RATES) /* Time constants */ @@ -449,8 +452,6 @@ struct iwl4965_eeprom { */ #define CSR_HW_REV_WA_REG (CSR_BASE+0x22C) -#define CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM (0x00200000) - /* interrupt flags in INTA, set by uCode or hardware (e.g. dma), * acknowledged (reset) by host writing "1" to flagged bits. */ #define CSR_INT_BIT_FH_RX (1<<31) /* Rx DMA, cmd responses, FH_INT[17:16] */ @@ -592,17 +593,12 @@ struct iwl4965_eeprom { #define FH_TSSR_CBB_BASE (FH_TSSR_TABLE+0x000) #define FH_TSSR_MSG_CONFIG (FH_TSSR_TABLE+0x008) #define FH_TSSR_TX_STATUS (FH_TSSR_TABLE+0x010) -/* 18 - reserved */ -/* card static random access memory (SRAM) for processor data and instructs */ -#define RTC_INST_LOWER_BOUND (0x000000) -#define RTC_DATA_LOWER_BOUND (0x800000) #define HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED (0x00000004) #define TFD_QUEUE_SIZE_MAX (256) -/* spectrum and channel data structures */ #define IWL_NUM_SCAN_RATES (2) #define IWL_DEFAULT_TX_RETRY 15 @@ -623,17 +619,26 @@ struct iwl4965_eeprom { #define RX_FREE_BUFFERS 64 #define RX_LOW_WATERMARK 8 - +/* Size of one Rx buffer in host DRAM */ #define IWL_RX_BUF_SIZE (4 * 1024) -#define IWL_MAX_BSM_SIZE BSM_SRAM_SIZE + +/* Sizes and addresses for instruction and data memory (SRAM) in + * 4965's embedded processor. Driver access is via HBUS_TARG_MEM_* regs. */ +#define RTC_INST_LOWER_BOUND (0x000000) #define KDR_RTC_INST_UPPER_BOUND (0x018000) + +#define RTC_DATA_LOWER_BOUND (0x800000) #define KDR_RTC_DATA_UPPER_BOUND (0x80A000) + #define KDR_RTC_INST_SIZE (KDR_RTC_INST_UPPER_BOUND - RTC_INST_LOWER_BOUND) #define KDR_RTC_DATA_SIZE (KDR_RTC_DATA_UPPER_BOUND - RTC_DATA_LOWER_BOUND) #define IWL_MAX_INST_SIZE KDR_RTC_INST_SIZE #define IWL_MAX_DATA_SIZE KDR_RTC_DATA_SIZE +/* Size of uCode instruction memory in bootstrap state machine */ +#define IWL_MAX_BSM_SIZE BSM_SRAM_SIZE + static inline int iwl4965_hw_valid_rtc_data_addr(u32 addr) { return (addr >= RTC_DATA_LOWER_BOUND) && @@ -641,13 +646,6 @@ static inline int iwl4965_hw_valid_rtc_data_addr(u32 addr) } /********************* START TXPOWER *****************************************/ -enum { - HT_IE_EXT_CHANNEL_NONE = 0, - HT_IE_EXT_CHANNEL_ABOVE, - HT_IE_EXT_CHANNEL_INVALID, - HT_IE_EXT_CHANNEL_BELOW, - HT_IE_EXT_CHANNEL_MAX -}; enum { CALIB_CH_GROUP_1 = 0, @@ -812,6 +810,7 @@ enum { #define CSR_HW_IF_CONFIG_REG_MSK_BOARD_VER (0x00000C00) #define CSR_HW_IF_CONFIG_REG_BIT_MAC_SI (0x00000100) #define CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI (0x00000200) +#define CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM (0x00200000) static inline u8 iwl4965_hw_get_rate(__le32 rate_n_flags) { diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index 9438c63..4a1ec94 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h @@ -23,6 +23,12 @@ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 * *****************************************************************************/ +/* + * Please use this file (iwl-4965.h) for driver implementation definitions. + * Please use iwl-4965-commands.h for uCode API definitions. + * Please use iwl-4965-hw.h for hardware-related definitions. + */ + #ifndef __iwl_4965_h__ #define __iwl_4965_h__ @@ -192,6 +198,15 @@ struct iwl4965_scan_power_info { s8 requested_power; /* scan pwr (dBm) requested for chnl/rate */ }; +/* For fat_extension_channel */ +enum { + HT_IE_EXT_CHANNEL_NONE = 0, + HT_IE_EXT_CHANNEL_ABOVE, + HT_IE_EXT_CHANNEL_INVALID, + HT_IE_EXT_CHANNEL_BELOW, + HT_IE_EXT_CHANNEL_MAX +}; + /* * One for each channel, holds all channel setup data * Some of the fields (e.g. eeprom and flags/max_power_avg) are redundant @@ -202,14 +217,14 @@ struct iwl4965_scan_power_info { struct iwl4965_channel_info { struct iwl4965_channel_tgd_info tgd; struct iwl4965_channel_tgh_info tgh; - struct iwl4965_eeprom_channel eeprom; /* EEPROM regulatory limit */ - struct iwl4965_eeprom_channel fat_eeprom; /* EEPROM regulatory limit for - * FAT channel */ + struct iwl4965_eeprom_channel eeprom; /* EEPROM regulatory limit */ + struct iwl4965_eeprom_channel fat_eeprom; /* EEPROM regulatory limit for + * FAT channel */ u8 channel; /* channel number */ u8 flags; /* flags copied from EEPROM */ s8 max_power_avg; /* (dBm) regul. eeprom, normal Tx, any rate */ - s8 curr_txpow; /* (dBm) regulatory/spectrum/user (not h/w) */ + s8 curr_txpow; /* (dBm) regulatory/spectrum/user (not h/w) limit */ s8 min_power; /* always 0 */ s8 scan_power; /* (dBm) regul. eeprom, direct scans, any rate */ @@ -228,7 +243,7 @@ struct iwl4965_channel_info { s8 fat_min_power; /* always 0 */ s8 fat_scan_power; /* (dBm) eeprom, direct scans, any rate */ u8 fat_flags; /* flags copied from EEPROM */ - u8 fat_extension_channel; + u8 fat_extension_channel; /* HT_IE_EXT_CHANNEL_* */ /* Radio/DSP gain settings for each scan rate, for directed scans. */ struct iwl4965_scan_power_info scan_pwr_info[IWL_NUM_SCAN_RATES]; -- 1.5.3.6 ^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 21/36] iwlwifi: document temperature calculation 2007-11-29 3:10 ` [PATCH 20/36] iwlwifi: move HT_IE_EXT_CHANNEL_* driver definitions to iwl-4965.h Zhu Yi @ 2007-11-29 3:10 ` Zhu Yi 2007-11-29 3:10 ` [PATCH 22/36] iwlwifi: document txpower calculations Zhu Yi 0 siblings, 1 reply; 36+ messages in thread From: Zhu Yi @ 2007-11-29 3:10 UTC (permalink / raw) To: linville; +Cc: linux-wireless, Ben Cahill, Zhu Yi From: Ben Cahill <ben.m.cahill@intel.com> Document temperature calculation Signed-off-by: Ben Cahill <ben.m.cahill@intel.com> Signed-off-by: Zhu Yi <yi.zhu@intel.com> --- drivers/net/wireless/iwlwifi/iwl-4965-hw.h | 57 ++++++++++++++++++++++----- 1 files changed, 46 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h index 6f91c02..d47179e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h @@ -645,21 +645,43 @@ static inline int iwl4965_hw_valid_rtc_data_addr(u32 addr) (addr < KDR_RTC_DATA_UPPER_BOUND); } -/********************* START TXPOWER *****************************************/ - -enum { - CALIB_CH_GROUP_1 = 0, - CALIB_CH_GROUP_2 = 1, - CALIB_CH_GROUP_3 = 2, - CALIB_CH_GROUP_4 = 3, - CALIB_CH_GROUP_5 = 4, - CALIB_CH_GROUP_MAX -}; +/********************* START TEMPERATURE *************************************/ -/* Temperature calibration offset is 3% 0C in Kelvin */ +/* + * 4965 temperature calculation. + * + * The driver must calculate the device temperature before calculating + * a txpower setting (amplifier gain is temperature dependent). The + * calculation uses 4 measurements, 3 of which (R1, R2, R3) are calibration + * values used for the life of the driver, and one of which (R4) is the + * real-time temperature indicator. + * + * uCode provides all 4 values to the driver via the "initialize alive" + * notification (see struct iwl4965_init_alive_resp). After the runtime uCode + * image loads, uCode updates the R4 value via statistics notifications + * (see STATISTICS_NOTIFICATION), which occur after each received beacon + * when associated, or can be requested via REPLY_STATISTICS_CMD. + * + * NOTE: uCode provides the R4 value as a 23-bit signed value. Driver + * must sign-extend to 32 bits before applying formula below. + * + * Formula: + * + * degrees Kelvin = ((97 * 259 * (R4 - R2) / (R3 - R1)) / 100) + 8 + * + * NOTE: The basic formula is 259 * (R4-R2) / (R3-R1). The 97/100 is + * an additional correction, which should be centered around 0 degrees + * Celsius (273 degrees Kelvin). The 8 (3 percent of 273) compensates for + * centering the 97/100 correction around 0 degrees K. + * + * Add 273 to Kelvin value to find degrees Celsius, for comparing current + * temperature with factory-measured temperatures when calculating txpower + * settings. + */ #define TEMPERATURE_CALIB_KELVIN_OFFSET 8 #define TEMPERATURE_CALIB_A_VAL 259 +/* Limit range of calculated temperature to be between these Kelvin values */ #define IWL_TX_POWER_TEMPERATURE_MIN (263) #define IWL_TX_POWER_TEMPERATURE_MAX (410) @@ -667,6 +689,19 @@ enum { (((t) < IWL_TX_POWER_TEMPERATURE_MIN) || \ ((t) > IWL_TX_POWER_TEMPERATURE_MAX)) +/********************* END TEMPERATURE ***************************************/ + +/********************* START TXPOWER *****************************************/ + +enum { + CALIB_CH_GROUP_1 = 0, + CALIB_CH_GROUP_2 = 1, + CALIB_CH_GROUP_3 = 2, + CALIB_CH_GROUP_4 = 3, + CALIB_CH_GROUP_5 = 4, + CALIB_CH_GROUP_MAX +}; + #define IWL_TX_POWER_MIMO_REGULATORY_COMPENSATION (6) #define IWL_TX_POWER_TARGET_POWER_MIN (0) /* 0 dBm = 1 milliwatt */ -- 1.5.3.6 ^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 22/36] iwlwifi: document txpower calculations 2007-11-29 3:10 ` [PATCH 21/36] iwlwifi: document temperature calculation Zhu Yi @ 2007-11-29 3:10 ` Zhu Yi 2007-11-29 3:10 ` [PATCH 23/36] iwlwifi: document keep-warm buffer Zhu Yi 0 siblings, 1 reply; 36+ messages in thread From: Zhu Yi @ 2007-11-29 3:10 UTC (permalink / raw) To: linville; +Cc: linux-wireless, Ben Cahill, Zhu Yi From: Ben Cahill <ben.m.cahill@intel.com> Document txpower calculations Signed-off-by: Ben Cahill <ben.m.cahill@intel.com> Signed-off-by: Zhu Yi <yi.zhu@intel.com> --- drivers/net/wireless/iwlwifi/iwl-4965-hw.h | 575 +++++++++++++++++++++++++++- drivers/net/wireless/iwlwifi/iwl-4965.h | 3 - 2 files changed, 562 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h index d47179e..40666f8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h @@ -647,7 +647,7 @@ static inline int iwl4965_hw_valid_rtc_data_addr(u32 addr) /********************* START TEMPERATURE *************************************/ -/* +/** * 4965 temperature calculation. * * The driver must calculate the device temperature before calculating @@ -693,44 +693,593 @@ static inline int iwl4965_hw_valid_rtc_data_addr(u32 addr) /********************* START TXPOWER *****************************************/ -enum { - CALIB_CH_GROUP_1 = 0, - CALIB_CH_GROUP_2 = 1, - CALIB_CH_GROUP_3 = 2, - CALIB_CH_GROUP_4 = 3, - CALIB_CH_GROUP_5 = 4, - CALIB_CH_GROUP_MAX -}; +/** + * 4965 txpower calculations rely on information from three sources: + * + * 1) EEPROM + * 2) "initialize" alive notification + * 3) statistics notifications + * + * EEPROM data consists of: + * + * 1) Regulatory information (max txpower and channel usage flags) is provided + * separately for each channel that can possibly supported by 4965. + * 40 MHz wide (.11n fat) channels are listed separately from 20 MHz + * (legacy) channels. + * + * See struct iwl4965_eeprom_channel for format, and struct iwl4965_eeprom + * for locations in EEPROM. + * + * 2) Factory txpower calibration information is provided separately for + * sub-bands of contiguous channels. 2.4GHz has just one sub-band, + * but 5 GHz has several sub-bands. + * + * In addition, per-band (2.4 and 5 Ghz) saturation txpowers are provided. + * + * See struct iwl4965_eeprom_calib_info (and the tree of structures + * contained within it) for format, and struct iwl4965_eeprom for + * locations in EEPROM. + * + * "Initialization alive" notification (see struct iwl4965_init_alive_resp) + * consists of: + * + * 1) Temperature calculation parameters. + * + * 2) Power supply voltage measurement. + * + * 3) Tx gain compensation to balance 2 transmitters for MIMO use. + * + * Statistics notifications deliver: + * + * 1) Current values for temperature param R4. + */ -#define IWL_TX_POWER_MIMO_REGULATORY_COMPENSATION (6) +/** + * To calculate a txpower setting for a given desired target txpower, channel, + * modulation bit rate, and transmitter chain (4965 has 2 transmitters to + * support MIMO and transmit diversity), driver must do the following: + * + * 1) Compare desired txpower vs. (EEPROM) regulatory limit for this channel. + * Do not exceed regulatory limit; reduce target txpower if necessary. + * + * If setting up txpowers for MIMO rates (rate indexes 8-15, 24-31), + * 2 transmitters will be used simultaneously; driver must reduce the + * regulatory limit by 3 dB (half-power) for each transmitter, so the + * combined total output of the 2 transmitters is within regulatory limits. + * + * + * 2) Compare target txpower vs. (EEPROM) saturation txpower *reduced by + * backoff for this bit rate*. Do not exceed (saturation - backoff[rate]); + * reduce target txpower if necessary. + * + * Backoff values below are in 1/2 dB units (equivalent to steps in + * txpower gain tables): + * + * OFDM 6 - 36 MBit: 10 steps (5 dB) + * OFDM 48 MBit: 15 steps (7.5 dB) + * OFDM 54 MBit: 17 steps (8.5 dB) + * OFDM 60 MBit: 20 steps (10 dB) + * CCK all rates: 10 steps (5 dB) + * + * Backoff values apply to saturation txpower on a per-transmitter basis; + * when using MIMO (2 transmitters), each transmitter uses the same + * saturation level provided in EEPROM, and the same backoff values; + * no reduction (such as with regulatory txpower limits) is required. + * + * Saturation and Backoff values apply equally to 20 Mhz (legacy) channel + * widths and 40 Mhz (.11n fat) channel widths; there is no separate + * factory measurement for fat channels. + * + * The result of this step is the final target txpower. The rest of + * the steps figure out the proper settings for the device to achieve + * that target txpower. + * + * + * 3) Determine (EEPROM) calibration subband for the target channel, by + * comparing against first and last channels in each subband + * (see struct iwl4965_eeprom_calib_subband_info). + * + * + * 4) Linearly interpolate (EEPROM) factory calibration measurement sets, + * referencing the 2 factory-measured (sample) channels within the subband. + * + * Interpolation is based on difference between target channel's frequency + * and the sample channels' frequencies. Since channel numbers are based + * on frequency (5 MHz between each channel number), this is equivalent + * to interpolating based on channel number differences. + * + * Note that the sample channels may or may not be the channels at the + * edges of the subband. The target channel may be "outside" of the + * span of the sampled channels. + * + * Driver may choose the pair (for 2 Tx chains) of measurements (see + * struct iwl4965_eeprom_calib_ch_info) for which the actual measured + * txpower comes closest to the desired txpower. Usually, though, + * the middle set of measurements is closest to the regulatory limits, + * and is therefore a good choice for all txpower calculations (this + * assumes that high accuracy is needed for maximizing legal txpower, + * while lower txpower configurations do not need as much accuracy). + * + * Driver should interpolate both members of the chosen measurement pair, + * i.e. for both Tx chains (radio transmitters), unless the driver knows + * that only one of the chains will be used (e.g. only one tx antenna + * connected, but this should be unusual). The rate scaling algorithm + * switches antennas to find best performance, so both Tx chains will + * be used (although only one at a time) even for non-MIMO transmissions. + * + * Driver should interpolate factory values for temperature, gain table + * index, and actual power. The power amplifier detector values are + * not used by the driver. + * + * Sanity check: If the target channel happens to be one of the sample + * channels, the results should agree with the sample channel's + * measurements! + * + * + * 5) Find difference between desired txpower and (interpolated) + * factory-measured txpower. Using (interpolated) factory gain table index + * (shown elsewhere) as a starting point, adjust this index lower to + * increase txpower, or higher to decrease txpower, until the target + * txpower is reached. Each step in the gain table is 1/2 dB. + * + * For example, if factory measured txpower is 16 dBm, and target txpower + * is 13 dBm, add 6 steps to the factory gain index to reduce txpower + * by 3 dB. + * + * + * 6) Find difference between current device temperature and (interpolated) + * factory-measured temperature for sub-band. Factory values are in + * degrees Celsius. To calculate current temperature, see comments for + * "4965 temperature calculation". + * + * If current temperature is higher than factory temperature, driver must + * increase gain (lower gain table index), and vice versa. + * + * Temperature affects gain differently for different channels: + * + * 2.4 GHz all channels: 3.5 degrees per half-dB step + * 5 GHz channels 34-43: 4.5 degrees per half-dB step + * 5 GHz channels >= 44: 4.0 degrees per half-dB step + * + * NOTE: Temperature can increase rapidly when transmitting, especially + * with heavy traffic at high txpowers. Driver should update + * temperature calculations often under these conditions to + * maintain strong txpower in the face of rising temperature. + * + * + * 7) Find difference between current power supply voltage indicator + * (from "initialize alive") and factory-measured power supply voltage + * indicator (EEPROM). + * + * If the current voltage is higher (indicator is lower) than factory + * voltage, gain should be reduced (gain table index increased) by: + * + * (eeprom - current) / 7 + * + * If the current voltage is lower (indicator is higher) than factory + * voltage, gain should be increased (gain table index decreased) by: + * + * 2 * (current - eeprom) / 7 + * + * If number of index steps in either direction turns out to be > 2, + * something is wrong ... just use 0. + * + * NOTE: Voltage compensation is independent of band/channel. + * + * NOTE: "Initialize" uCode measures current voltage, which is assumed + * to be constant after this initial measurement. Voltage + * compensation for txpower (number of steps in gain table) + * may be calculated once and used until the next uCode bootload. + * + * + * 8) If setting up txpowers for MIMO rates (rate indexes 8-15, 24-31), + * adjust txpower for each transmitter chain, so txpower is balanced + * between the two chains. There are 5 pairs of tx_atten[group][chain] + * values in "initialize alive", one pair for each of 5 channel ranges: + * + * Group 0: 5 GHz channel 34-43 + * Group 1: 5 GHz channel 44-70 + * Group 2: 5 GHz channel 71-124 + * Group 3: 5 GHz channel 125-200 + * Group 4: 2.4 GHz all channels + * + * Add the tx_atten[group][chain] value to the index for the target chain. + * The values are signed, but are in pairs of 0 and a non-negative number, + * so as to reduce gain (if necessary) of the "hotter" channel. This + * avoids any need to double-check for regulatory compliance after + * this step. + * + * + * 9) If setting up for a CCK rate, lower the gain by adding a CCK compensation + * value to the index: + * + * Hardware rev B: 9 steps (4.5 dB) + * Hardware rev C: 5 steps (2.5 dB) + * + * Hardware rev for 4965 can be determined by reading CSR_HW_REV_WA_REG, + * bits [3:2], 1 = B, 2 = C. + * + * NOTE: This compensation is in addition to any saturation backoff that + * might have been applied in an earlier step. + * + * + * 10) Select the gain table, based on band (2.4 vs 5 GHz). + * + * Limit the adjusted index to stay within the table! + * + * + * 11) Read gain table entries for DSP and radio gain, place into appropriate + * location(s) in command (struct iwl4965_txpowertable_cmd). + */ +/* Limit range of txpower output target to be between these values */ #define IWL_TX_POWER_TARGET_POWER_MIN (0) /* 0 dBm = 1 milliwatt */ #define IWL_TX_POWER_TARGET_POWER_MAX (16) /* 16 dBm */ -#define MIN_TX_GAIN_INDEX (0) -#define MIN_TX_GAIN_INDEX_52GHZ_EXT (-9) +/** + * When MIMO is used (2 transmitters operating simultaneously), driver should + * limit each transmitter to deliver a max of 3 dB below the regulatory limit + * for the device. That is, use half power for each transmitter, so total + * txpower is within regulatory limits. + * + * The value "6" represents number of steps in gain table to reduce power 3 dB. + * Each step is 1/2 dB. + */ +#define IWL_TX_POWER_MIMO_REGULATORY_COMPENSATION (6) + +/** + * CCK gain compensation. + * + * When calculating txpowers for CCK, after making sure that the target power + * is within regulatory and saturation limits, driver must additionally + * back off gain by adding these values to the gain table index. + * + * Hardware rev for 4965 can be determined by reading CSR_HW_REV_WA_REG, + * bits [3:2], 1 = B, 2 = C. + */ +#define IWL_TX_POWER_CCK_COMPENSATION_B_STEP (9) +#define IWL_TX_POWER_CCK_COMPENSATION_C_STEP (5) + +/* + * 4965 power supply voltage compensation for txpower + */ +#define TX_POWER_IWL_VOLTAGE_CODES_PER_03V (7) + +/** + * Gain tables. + * + * The following tables contain pair of values for setting txpower, i.e. + * gain settings for the output of the device's digital signal processor (DSP), + * and for the analog gain structure of the transmitter. + * + * Each entry in the gain tables represents a step of 1/2 dB. Note that these + * are *relative* steps, not indications of absolute output power. Output + * power varies with temperature, voltage, and channel frequency, and also + * requires consideration of average power (to satisfy regulatory constraints), + * and peak power (to avoid distortion of the output signal). + * + * Each entry contains two values: + * 1) DSP gain (or sometimes called DSP attenuation). This is a fine-grained + * linear value that multiplies the output of the digital signal processor, + * before being sent to the analog radio. + * 2) Radio gain. This sets the analog gain of the radio Tx path. + * It is a coarser setting, and behaves in a logarithmic (dB) fashion. + * + * EEPROM contains factory calibration data for txpower. This maps actual + * measured txpower levels to gain settings in the "well known" tables + * below ("well-known" means here that both factory calibration *and* the + * driver work with the same table). + * + * There are separate tables for 2.4 GHz and 5 GHz bands. The 5 GHz table + * has an extension (into negative indexes), in case the driver needs to + * boost power setting for high device temperatures (higher than would be + * present during factory calibration). A 5 Ghz EEPROM index of "40" + * corresponds to the 49th entry in the table used by the driver. + */ +#define MIN_TX_GAIN_INDEX (0) /* highest gain, lowest idx, 2.4 */ +#define MIN_TX_GAIN_INDEX_52GHZ_EXT (-9) /* highest gain, lowest idx, 5 */ + +/** + * 2.4 GHz gain table + * + * Index Dsp gain Radio gain + * 0 110 0x3f (highest gain) + * 1 104 0x3f + * 2 98 0x3f + * 3 110 0x3e + * 4 104 0x3e + * 5 98 0x3e + * 6 110 0x3d + * 7 104 0x3d + * 8 98 0x3d + * 9 110 0x3c + * 10 104 0x3c + * 11 98 0x3c + * 12 110 0x3b + * 13 104 0x3b + * 14 98 0x3b + * 15 110 0x3a + * 16 104 0x3a + * 17 98 0x3a + * 18 110 0x39 + * 19 104 0x39 + * 20 98 0x39 + * 21 110 0x38 + * 22 104 0x38 + * 23 98 0x38 + * 24 110 0x37 + * 25 104 0x37 + * 26 98 0x37 + * 27 110 0x36 + * 28 104 0x36 + * 29 98 0x36 + * 30 110 0x35 + * 31 104 0x35 + * 32 98 0x35 + * 33 110 0x34 + * 34 104 0x34 + * 35 98 0x34 + * 36 110 0x33 + * 37 104 0x33 + * 38 98 0x33 + * 39 110 0x32 + * 40 104 0x32 + * 41 98 0x32 + * 42 110 0x31 + * 43 104 0x31 + * 44 98 0x31 + * 45 110 0x30 + * 46 104 0x30 + * 47 98 0x30 + * 48 110 0x6 + * 49 104 0x6 + * 50 98 0x6 + * 51 110 0x5 + * 52 104 0x5 + * 53 98 0x5 + * 54 110 0x4 + * 55 104 0x4 + * 56 98 0x4 + * 57 110 0x3 + * 58 104 0x3 + * 59 98 0x3 + * 60 110 0x2 + * 61 104 0x2 + * 62 98 0x2 + * 63 110 0x1 + * 64 104 0x1 + * 65 98 0x1 + * 66 110 0x0 + * 67 104 0x0 + * 68 98 0x0 + * 69 97 0 + * 70 96 0 + * 71 95 0 + * 72 94 0 + * 73 93 0 + * 74 92 0 + * 75 91 0 + * 76 90 0 + * 77 89 0 + * 78 88 0 + * 79 87 0 + * 80 86 0 + * 81 85 0 + * 82 84 0 + * 83 83 0 + * 84 82 0 + * 85 81 0 + * 86 80 0 + * 87 79 0 + * 88 78 0 + * 89 77 0 + * 90 76 0 + * 91 75 0 + * 92 74 0 + * 93 73 0 + * 94 72 0 + * 95 71 0 + * 96 70 0 + * 97 69 0 + * 98 68 0 + */ + +/** + * 5 GHz gain table + * + * Index Dsp gain Radio gain + * -9 123 0x3F (highest gain) + * -8 117 0x3F + * -7 110 0x3F + * -6 104 0x3F + * -5 98 0x3F + * -4 110 0x3E + * -3 104 0x3E + * -2 98 0x3E + * -1 110 0x3D + * 0 104 0x3D + * 1 98 0x3D + * 2 110 0x3C + * 3 104 0x3C + * 4 98 0x3C + * 5 110 0x3B + * 6 104 0x3B + * 7 98 0x3B + * 8 110 0x3A + * 9 104 0x3A + * 10 98 0x3A + * 11 110 0x39 + * 12 104 0x39 + * 13 98 0x39 + * 14 110 0x38 + * 15 104 0x38 + * 16 98 0x38 + * 17 110 0x37 + * 18 104 0x37 + * 19 98 0x37 + * 20 110 0x36 + * 21 104 0x36 + * 22 98 0x36 + * 23 110 0x35 + * 24 104 0x35 + * 25 98 0x35 + * 26 110 0x34 + * 27 104 0x34 + * 28 98 0x34 + * 29 110 0x33 + * 30 104 0x33 + * 31 98 0x33 + * 32 110 0x32 + * 33 104 0x32 + * 34 98 0x32 + * 35 110 0x31 + * 36 104 0x31 + * 37 98 0x31 + * 38 110 0x30 + * 39 104 0x30 + * 40 98 0x30 + * 41 110 0x25 + * 42 104 0x25 + * 43 98 0x25 + * 44 110 0x24 + * 45 104 0x24 + * 46 98 0x24 + * 47 110 0x23 + * 48 104 0x23 + * 49 98 0x23 + * 50 110 0x22 + * 51 104 0x18 + * 52 98 0x18 + * 53 110 0x17 + * 54 104 0x17 + * 55 98 0x17 + * 56 110 0x16 + * 57 104 0x16 + * 58 98 0x16 + * 59 110 0x15 + * 60 104 0x15 + * 61 98 0x15 + * 62 110 0x14 + * 63 104 0x14 + * 64 98 0x14 + * 65 110 0x13 + * 66 104 0x13 + * 67 98 0x13 + * 68 110 0x12 + * 69 104 0x08 + * 70 98 0x08 + * 71 110 0x07 + * 72 104 0x07 + * 73 98 0x07 + * 74 110 0x06 + * 75 104 0x06 + * 76 98 0x06 + * 77 110 0x05 + * 78 104 0x05 + * 79 98 0x05 + * 80 110 0x04 + * 81 104 0x04 + * 82 98 0x04 + * 83 110 0x03 + * 84 104 0x03 + * 85 98 0x03 + * 86 110 0x02 + * 87 104 0x02 + * 88 98 0x02 + * 89 110 0x01 + * 90 104 0x01 + * 91 98 0x01 + * 92 110 0x00 + * 93 104 0x00 + * 94 98 0x00 + * 95 93 0x00 + * 96 88 0x00 + * 97 83 0x00 + * 98 78 0x00 + */ + +/** + * Sanity checks and default values for EEPROM regulatory levels. + * If EEPROM values fall outside MIN/MAX range, use default values. + * + * Regulatory limits refer to the maximum average txpower allowed by + * regulatory agencies in the geographies in which the device is meant + * to be operated. These limits are SKU-specific (i.e. geography-specific), + * and channel-specific; each channel has an individual regulatory limit + * listed in the EEPROM. + * + * Units are in half-dBm (i.e. "34" means 17 dBm). + */ #define IWL_TX_POWER_DEFAULT_REGULATORY_24 (34) #define IWL_TX_POWER_DEFAULT_REGULATORY_52 (34) #define IWL_TX_POWER_REGULATORY_MIN (0) #define IWL_TX_POWER_REGULATORY_MAX (34) + +/** + * Sanity checks and default values for EEPROM saturation levels. + * If EEPROM values fall outside MIN/MAX range, use default values. + * + * Saturation is the highest level that the output power amplifier can produce + * without significant clipping distortion. This is a "peak" power level. + * Different types of modulation (i.e. various "rates", and OFDM vs. CCK) + * require differing amounts of backoff, relative to their average power output, + * in order to avoid clipping distortion. + * + * Driver must make sure that it is violating neither the saturation limit, + * nor the regulatory limit, when calculating Tx power settings for various + * rates. + * + * Units are in half-dBm (i.e. "38" means 19 dBm). + */ #define IWL_TX_POWER_DEFAULT_SATURATION_24 (38) #define IWL_TX_POWER_DEFAULT_SATURATION_52 (38) #define IWL_TX_POWER_SATURATION_MIN (20) #define IWL_TX_POWER_SATURATION_MAX (50) -/* First and last channels of all groups */ +/** + * Channel groups used for Tx Attenuation calibration (MIMO tx channel balance) + * and thermal Txpower calibration. + * + * When calculating txpower, driver must compensate for current device + * temperature; higher temperature requires higher gain. Driver must calculate + * current temperature (see "4965 temperature calculation"), then compare vs. + * factory calibration temperature in EEPROM; if current temperature is higher + * than factory temperature, driver must *increase* gain by proportions shown + * in table below. If current temperature is lower than factory, driver must + * *decrease* gain. + * + * Different frequency ranges require different compensation, as shown below. + */ +/* Group 0, 5.2 GHz ch 34-43: 4.5 degrees per 1/2 dB. */ #define CALIB_IWL_TX_ATTEN_GR1_FCH 34 #define CALIB_IWL_TX_ATTEN_GR1_LCH 43 + +/* Group 1, 5.3 GHz ch 44-70: 4.0 degrees per 1/2 dB. */ #define CALIB_IWL_TX_ATTEN_GR2_FCH 44 #define CALIB_IWL_TX_ATTEN_GR2_LCH 70 + +/* Group 2, 5.5 GHz ch 71-124: 4.0 degrees per 1/2 dB. */ #define CALIB_IWL_TX_ATTEN_GR3_FCH 71 #define CALIB_IWL_TX_ATTEN_GR3_LCH 124 + +/* Group 3, 5.7 GHz ch 125-200: 4.0 degrees per 1/2 dB. */ #define CALIB_IWL_TX_ATTEN_GR4_FCH 125 #define CALIB_IWL_TX_ATTEN_GR4_LCH 200 + +/* Group 4, 2.4 GHz all channels: 3.5 degrees per 1/2 dB. */ #define CALIB_IWL_TX_ATTEN_GR5_FCH 1 #define CALIB_IWL_TX_ATTEN_GR5_LCH 20 +enum { + CALIB_CH_GROUP_1 = 0, + CALIB_CH_GROUP_2 = 1, + CALIB_CH_GROUP_3 = 2, + CALIB_CH_GROUP_4 = 3, + CALIB_CH_GROUP_5 = 4, + CALIB_CH_GROUP_MAX +}; + /********************* END TXPOWER *****************************************/ /* Flow Handler Definitions */ diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index 4a1ec94..2930c10 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h @@ -859,9 +859,6 @@ struct iwl4965_kw { #define NUM_RX_CHAINS (3) #define TX_POWER_IWL_ILLEGAL_VOLTAGE -10000 -#define TX_POWER_IWL_VOLTAGE_CODES_PER_03V 7 -#define IWL_TX_POWER_CCK_COMPENSATION_B_STEP (9) -#define IWL_TX_POWER_CCK_COMPENSATION_C_STEP (5) struct iwl4965_traffic_load { unsigned long time_stamp; -- 1.5.3.6 ^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 23/36] iwlwifi: document keep-warm buffer 2007-11-29 3:10 ` [PATCH 22/36] iwlwifi: document txpower calculations Zhu Yi @ 2007-11-29 3:10 ` Zhu Yi 2007-11-29 3:10 ` [PATCH 24/36] iwlwifi: document Rx registers Zhu Yi 0 siblings, 1 reply; 36+ messages in thread From: Zhu Yi @ 2007-11-29 3:10 UTC (permalink / raw) To: linville; +Cc: linux-wireless, Ben Cahill, Zhu Yi From: Ben Cahill <ben.m.cahill@intel.com> Document keep-warm buffer Consolidate flow handler address definitions Signed-off-by: Ben Cahill <ben.m.cahill@intel.com> Signed-off-by: Zhu Yi <yi.zhu@intel.com> --- drivers/net/wireless/iwlwifi/iwl-4965-hw.h | 39 ++++++++++++++++++++-------- 1 files changed, 28 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h index 40666f8..3c78e2d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h @@ -1282,20 +1282,37 @@ enum { /********************* END TXPOWER *****************************************/ +/****************************/ /* Flow Handler Definitions */ +/****************************/ -/**********************/ -/* Addresses */ -/**********************/ - +/* + * This I/O area is directly read/writable by driver (e.g. Linux uses writel()) + * Addresses are offsets from device's PCI hardware base address. + */ #define FH_MEM_LOWER_BOUND (0x1000) #define FH_MEM_UPPER_BOUND (0x1EF0) -#define IWL_FH_REGS_LOWER_BOUND (0x1000) -#define IWL_FH_REGS_UPPER_BOUND (0x2000) - +/** + * Keep-Warm (KW) buffer base address. + * + * Driver must allocate a 4KByte buffer that is used by 4965 for keeping the + * host DRAM powered on (via dummy accesses to DRAM) to maintain low-latency + * DRAM access when 4965 is Txing or Rxing. The dummy accesses prevent host + * from going into a power-savings mode that would cause higher DRAM latency, + * and possible data over/under-runs, before all Tx/Rx is complete. + * + * Driver loads IWL_FH_KW_MEM_ADDR_REG with the physical address (bits 35:4) + * of the buffer, which must be 4K aligned. Once this is set up, the 4965 + * automatically invokes keep-warm accesses when normal accesses might not + * be sufficient to maintain fast DRAM response. + * + * Bit fields: + * 31-0: Keep-warm buffer physical base address [35:4], must be 4K aligned + */ #define IWL_FH_KW_MEM_ADDR_REG (FH_MEM_LOWER_BOUND + 0x97C) + /* CBBC Area - Circular buffers base address cache pointers table */ #define FH_MEM_CBBC_LOWER_BOUND (FH_MEM_LOWER_BOUND + 0x9D0) #define FH_MEM_CBBC_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0xA10) @@ -1326,16 +1343,16 @@ enum { #define FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV (FH_MEM_RSSR_LOWER_BOUND + 0x008) /* TCSR */ -#define IWL_FH_TCSR_LOWER_BOUND (IWL_FH_REGS_LOWER_BOUND + 0xD00) -#define IWL_FH_TCSR_UPPER_BOUND (IWL_FH_REGS_LOWER_BOUND + 0xE60) +#define IWL_FH_TCSR_LOWER_BOUND (FH_MEM_LOWER_BOUND + 0xD00) +#define IWL_FH_TCSR_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0xE60) #define IWL_FH_TCSR_CHNL_TX_CONFIG_REG(_chnl) \ (IWL_FH_TCSR_LOWER_BOUND + 0x20 * _chnl) /* TSSR Area - Tx shared status registers */ /* TSSR */ -#define IWL_FH_TSSR_LOWER_BOUND (IWL_FH_REGS_LOWER_BOUND + 0xEA0) -#define IWL_FH_TSSR_UPPER_BOUND (IWL_FH_REGS_LOWER_BOUND + 0xEC0) +#define IWL_FH_TSSR_LOWER_BOUND (FH_MEM_LOWER_BOUND + 0xEA0) +#define IWL_FH_TSSR_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0xEC0) #define IWL_FH_TSSR_TX_STATUS_REG (IWL_FH_TSSR_LOWER_BOUND + 0x010) -- 1.5.3.6 ^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 24/36] iwlwifi: document Rx registers 2007-11-29 3:10 ` [PATCH 23/36] iwlwifi: document keep-warm buffer Zhu Yi @ 2007-11-29 3:10 ` Zhu Yi 2007-11-29 3:10 ` [PATCH 25/36] iwlwifi: document Tx registers Zhu Yi 0 siblings, 1 reply; 36+ messages in thread From: Zhu Yi @ 2007-11-29 3:10 UTC (permalink / raw) To: linville; +Cc: linux-wireless, Ben Cahill, Zhu Yi From: Ben Cahill <ben.m.cahill@intel.com> Document Rx registers Document Tx circular buffer base registers Signed-off-by: Ben Cahill <ben.m.cahill@intel.com> Signed-off-by: Zhu Yi <yi.zhu@intel.com> --- drivers/net/wireless/iwlwifi/iwl-4965-hw.h | 181 +++++++++++++++++++++++++--- 1 files changed, 164 insertions(+), 17 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h index 3c78e2d..dfd2852 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h @@ -1286,7 +1286,7 @@ enum { /* Flow Handler Definitions */ /****************************/ -/* +/** * This I/O area is directly read/writable by driver (e.g. Linux uses writel()) * Addresses are offsets from device's PCI hardware base address. */ @@ -1313,35 +1313,193 @@ enum { #define IWL_FH_KW_MEM_ADDR_REG (FH_MEM_LOWER_BOUND + 0x97C) -/* CBBC Area - Circular buffers base address cache pointers table */ +/** + * TFD Circular Buffers Base (CBBC) addresses + * + * 4965 has 16 base pointer registers, one for each of 16 host-DRAM-resident + * circular buffers (CBs/queues) containing Transmit Frame Descriptors (TFDs) + * (see struct iwl_tfd_frame). These 16 pointer registers are offset by 0x04 + * bytes from one another. Each TFD circular buffer in DRAM must be 256-byte + * aligned (address bits 0-7 must be 0). + * + * Bit fields in each pointer register: + * 27-0: TFD CB physical base address [35:8], must be 256-byte aligned + */ #define FH_MEM_CBBC_LOWER_BOUND (FH_MEM_LOWER_BOUND + 0x9D0) #define FH_MEM_CBBC_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0xA10) -/* queues 0 - 15 */ + +/* Find TFD CB base pointer for given queue (range 0-15). */ #define FH_MEM_CBBC_QUEUE(x) (FH_MEM_CBBC_LOWER_BOUND + (x) * 0x4) -/* RSCSR Area */ + +/** + * Rx SRAM Control and Status Registers (RSCSR) + * + * These registers provide handshake between driver and 4965 for the Rx queue + * (this queue handles *all* command responses, notifications, Rx data, etc. + * sent from 4965 uCode to host driver). Unlike Tx, there is only one Rx + * queue, and only one Rx DMA/FIFO channel. Also unlike Tx, which can + * concatenate up to 20 DRAM buffers to form a Tx frame, each Receive Buffer + * Descriptor (RBD) points to only one Rx Buffer (RB); there is a 1:1 + * mapping between RBDs and RBs. + * + * Driver must allocate host DRAM memory for the following, and set the + * physical address of each into 4965 registers: + * + * 1) Receive Buffer Descriptor (RBD) circular buffer (CB), typically with 256 + * entries (although any power of 2, up to 4096, is selectable by driver). + * Each entry (1 dword) points to a receive buffer (RB) of consistent size + * (typically 4K, although 8K or 16K are also selectable by driver). + * Driver sets up RB size and number of RBDs in the CB via Rx config + * register FH_MEM_RCSR_CHNL0_CONFIG_REG. + * + * Bit fields within one RBD: + * 27-0: Receive Buffer physical address bits [35:8], 256-byte aligned + * + * Driver sets physical address [35:8] of base of RBD circular buffer + * into FH_RSCSR_CHNL0_RBDCB_BASE_REG [27:0]. + * + * 2) Rx status buffer, 8 bytes, in which 4965 indicates which Rx Buffers + * (RBs) have been filled, via a "write pointer", actually the index of + * the RB's corresponding RBD within the circular buffer. Driver sets + * physical address [35:4] into FH_RSCSR_CHNL0_STTS_WPTR_REG [31:0]. + * + * Bit fields in lower dword of Rx status buffer (upper dword not used + * by driver; see struct iwl4965_shared, val0): + * 31-12: Not used by driver + * 11- 0: Index of last filled Rx buffer descriptor + * (4965 writes, driver reads this value) + * + * As the driver prepares Receive Buffers (RBs) for 4965 to fill, driver must + * enter pointers to these RBs into contiguous RBD circular buffer entries, + * and update the 4965's "write" index register, FH_RSCSR_CHNL0_RBDCB_WPTR_REG. + * + * This "write" index corresponds to the *next* RBD that the driver will make + * available, i.e. one RBD past the tail of the ready-to-fill RBDs within + * the circular buffer. This value should initially be 0 (before preparing any + * RBs), should be 8 after preparing the first 8 RBs (for example), and must + * wrap back to 0 at the end of the circular buffer (but don't wrap before + * "read" index has advanced past 1! See below). + * NOTE: 4965 EXPECTS THE WRITE INDEX TO BE INCREMENTED IN MULTIPLES OF 8. + * + * As the 4965 fills RBs (referenced from contiguous RBDs within the circular + * buffer), it updates the Rx status buffer in host DRAM, 2) described above, + * to tell the driver the index of the latest filled RBD. The driver must + * read this "read" index from DRAM after receiving an Rx interrupt from 4965. + * + * The driver must also internally keep track of a third index, which is the + * next RBD to process. When receiving an Rx interrupt, driver should process + * all filled but unprocessed RBs up to, but not including, the RB + * corresponding to the "read" index. For example, if "read" index becomes "1", + * driver may process the RB pointed to by RBD 0. Depending on volume of + * traffic, there may be many RBs to process. + * + * If read index == write index, 4965 thinks there is no room to put new data. + * Due to this, the maximum number of filled RBs is 255, instead of 256. To + * be safe, make sure that there is a gap of at least 2 RBDs between "write" + * and "read" indexes; that is, make sure that there are no more than 254 + * buffers waiting to be filled. + */ #define FH_MEM_RSCSR_LOWER_BOUND (FH_MEM_LOWER_BOUND + 0xBC0) #define FH_MEM_RSCSR_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0xC00) #define FH_MEM_RSCSR_CHNL0 (FH_MEM_RSCSR_LOWER_BOUND) +/** + * Physical base address of 8-byte Rx Status buffer. + * Bit fields: + * 31-0: Rx status buffer physical base address [35:4], must 16-byte aligned. + */ #define FH_RSCSR_CHNL0_STTS_WPTR_REG (FH_MEM_RSCSR_CHNL0) + +/** + * Physical base address of Rx Buffer Descriptor Circular Buffer. + * Bit fields: + * 27-0: RBD CD physical base address [35:8], must be 256-byte aligned. + */ #define FH_RSCSR_CHNL0_RBDCB_BASE_REG (FH_MEM_RSCSR_CHNL0 + 0x004) + +/** + * Rx write pointer (index, really!). + * Bit fields: + * 11-0: Index of driver's most recent prepared-to-be-filled RBD, + 1. + * NOTE: For 256-entry circular buffer, use only bits [7:0]. + */ #define FH_RSCSR_CHNL0_RBDCB_WPTR_REG (FH_MEM_RSCSR_CHNL0 + 0x008) -/* RCSR Area - Registers address map */ + +/** + * Rx Config/Status Registers (RCSR) + * Rx Config Reg for channel 0 (only channel used) + * + * Driver must initialize FH_MEM_RCSR_CHNL0_CONFIG_REG as follows for + * normal operation (see bit fields). + * + * Clearing FH_MEM_RCSR_CHNL0_CONFIG_REG to 0 turns off Rx DMA. + * Driver should poll FH_MEM_RSSR_RX_STATUS_REG for + * FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE (bit 24) before continuing. + * + * Bit fields: + * 31-30: Rx DMA channel enable: '00' off/pause, '01' pause at end of frame, + * '10' operate normally + * 29-24: reserved + * 23-20: # RBDs in circular buffer = 2^value; use "8" for 256 RBDs (normal), + * min "5" for 32 RBDs, max "12" for 4096 RBDs. + * 19-18: reserved + * 17-16: size of each receive buffer; '00' 4K (normal), '01' 8K, + * '10' 12K, '11' 16K. + * 15-14: reserved + * 13-12: IRQ destination; '00' none, '01' host driver (normal operation) + * 11- 4: timeout for closing Rx buffer and interrupting host (units 32 usec) + * typical value 0x10 (about 1/2 msec) + * 3- 0: reserved + */ #define FH_MEM_RCSR_LOWER_BOUND (FH_MEM_LOWER_BOUND + 0xC00) #define FH_MEM_RCSR_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0xCC0) #define FH_MEM_RCSR_CHNL0 (FH_MEM_RCSR_LOWER_BOUND) #define FH_MEM_RCSR_CHNL0_CONFIG_REG (FH_MEM_RCSR_CHNL0) -/* RSSR Area - Rx shared ctrl & status registers */ +#define FH_RCSR_CHNL0_RX_CONFIG_RB_TIMEOUT_MASK (0x00000FF0) /* bit 4-11 */ +#define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_MASK (0x00001000) /* bit 12 */ +#define FH_RCSR_CHNL0_RX_CONFIG_SINGLE_FRAME_MASK (0x00008000) /* bit 15 */ +#define FH_RCSR_CHNL0_RX_CONFIG_RB_SIZE_MASK (0x00030000) /* bits 16-17 */ +#define FH_RCSR_CHNL0_RX_CONFIG_RBDBC_SIZE_MASK (0x00F00000) /* bits 20-23 */ +#define FH_RCSR_CHNL0_RX_CONFIG_DMA_CHNL_EN_MASK (0xC0000000) /* bits 30-31 */ + +#define FH_RCSR_RX_CONFIG_RBDCB_SIZE_BITSHIFT (20) +#define FH_RCSR_RX_CONFIG_RB_SIZE_BITSHIFT (16) + +#define FH_RCSR_RX_CONFIG_CHNL_EN_PAUSE_VAL (0x00000000) +#define FH_RCSR_RX_CONFIG_CHNL_EN_PAUSE_EOF_VAL (0x40000000) +#define FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL (0x80000000) + +#define IWL_FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K (0x00000000) + +#define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_NO_INT_VAL (0x00000000) +#define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL (0x00001000) + + +/** + * Rx Shared Status Registers (RSSR) + * + * After stopping Rx DMA channel (writing 0 to FH_MEM_RCSR_CHNL0_CONFIG_REG), + * driver must poll FH_MEM_RSSR_RX_STATUS_REG until Rx channel is idle. + * + * Bit fields: + * 24: 1 = Channel 0 is idle + * + * FH_MEM_RSSR_SHARED_CTRL_REG and FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV contain + * default values that should not be altered by the driver. + */ #define FH_MEM_RSSR_LOWER_BOUND (FH_MEM_LOWER_BOUND + 0xC40) #define FH_MEM_RSSR_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0xD00) + #define FH_MEM_RSSR_SHARED_CTRL_REG (FH_MEM_RSSR_LOWER_BOUND) #define FH_MEM_RSSR_RX_STATUS_REG (FH_MEM_RSSR_LOWER_BOUND + 0x004) #define FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV (FH_MEM_RSSR_LOWER_BOUND + 0x008) +#define FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE (0x01000000) + /* TCSR */ #define IWL_FH_TCSR_LOWER_BOUND (FH_MEM_LOWER_BOUND + 0xD00) #define IWL_FH_TCSR_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0xE60) @@ -1369,17 +1527,6 @@ enum { #define IWL_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE (0x80000000) -/* RCSR: channel 0 rx_config register defines */ - -#define FH_RCSR_RX_CONFIG_RBDCB_SIZE_BITSHIFT (20) - -#define FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL (0x80000000) - -#define IWL_FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K (0x00000000) - -/* RCSR channel 0 config register values */ -#define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL (0x00001000) - #define SCD_WIN_SIZE 64 #define SCD_FRAME_LIMIT 64 -- 1.5.3.6 ^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 25/36] iwlwifi: document Tx registers 2007-11-29 3:10 ` [PATCH 24/36] iwlwifi: document Rx registers Zhu Yi @ 2007-11-29 3:10 ` Zhu Yi 2007-11-29 3:10 ` [PATCH 26/36] iwlwifi: document shared Tx structures Zhu Yi 0 siblings, 1 reply; 36+ messages in thread From: Zhu Yi @ 2007-11-29 3:10 UTC (permalink / raw) To: linville; +Cc: linux-wireless, Ben Cahill, Zhu Yi From: Ben Cahill <ben.m.cahill@intel.com> Document Tx registers Clean up unused definitions Signed-off-by: Ben Cahill <ben.m.cahill@intel.com> Signed-off-by: Zhu Yi <yi.zhu@intel.com> --- drivers/net/wireless/iwlwifi/iwl-3945-hw.h | 2 - drivers/net/wireless/iwlwifi/iwl-4965-hw.h | 72 ++++++++++++++++++---------- 2 files changed, 46 insertions(+), 28 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h index 42da5be..f754d4a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h @@ -610,8 +610,6 @@ struct iwl3945_eeprom { #define PCI_CFG_REV_ID_BIT_BASIC_SKU (0x40) /* bit 6 */ #define PCI_CFG_REV_ID_BIT_RTP (0x80) /* bit 7 */ -#define HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED (0x00000004) - #define TFD_QUEUE_MIN 0 #define TFD_QUEUE_MAX 6 #define TFD_QUEUE_SIZE_MAX (256) diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h index dfd2852..d8a01b1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h @@ -567,7 +567,8 @@ struct iwl4965_eeprom { /* * Per-Tx-queue write pointer (index, really!) (3945 and 4965). - * Indicates index to next TFD that driver will fill (1 past latest filled). + * Driver sets this to indicate index to next TFD that driver will fill + * (1 past latest filled). * Bit usage: * 0-7: queue write index (0-255) * 11-8: queue selector (0-15) @@ -576,25 +577,6 @@ struct iwl4965_eeprom { #define HBUS_TARG_MBX_C (HBUS_BASE+0x030) -/*=== FH (data Flow Handler) ===*/ -#define FH_BASE (0x800) - -#define FH_RSCSR_CHNL0_WPTR (FH_RSCSR_CHNL0_RBDCB_WPTR_REG) - -/* RSSR */ -#define FH_RSSR_CTRL (FH_RSSR_TABLE+0x000) -#define FH_RSSR_STATUS (FH_RSSR_TABLE+0x004) -/* TCSR */ -#define FH_TCSR(_channel) (FH_TCSR_TABLE+(_channel)*0x20) -#define FH_TCSR_CONFIG(_channel) (FH_TCSR(_channel)+0x00) -#define FH_TCSR_CREDIT(_channel) (FH_TCSR(_channel)+0x04) -#define FH_TCSR_BUFF_STTS(_channel) (FH_TCSR(_channel)+0x08) -/* TSSR */ -#define FH_TSSR_CBB_BASE (FH_TSSR_TABLE+0x000) -#define FH_TSSR_MSG_CONFIG (FH_TSSR_TABLE+0x008) -#define FH_TSSR_TX_STATUS (FH_TSSR_TABLE+0x010) - - #define HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED (0x00000004) #define TFD_QUEUE_SIZE_MAX (256) @@ -1425,6 +1407,7 @@ enum { * NOTE: For 256-entry circular buffer, use only bits [7:0]. */ #define FH_RSCSR_CHNL0_RBDCB_WPTR_REG (FH_MEM_RSCSR_CHNL0 + 0x008) +#define FH_RSCSR_CHNL0_WPTR (FH_RSCSR_CHNL0_RBDCB_WPTR_REG) /** @@ -1500,15 +1483,55 @@ enum { #define FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE (0x01000000) -/* TCSR */ + +/** + * Transmit DMA Channel Control/Status Registers (TCSR) + * + * 4965 has one configuration register for each of 8 Tx DMA/FIFO channels + * supported in hardware (don't confuse these with the 16 Tx queues in DRAM, + * which feed the DMA/FIFO channels); config regs are separated by 0x20 bytes. + * + * To use a Tx DMA channel, driver must initialize its + * IWL_FH_TCSR_CHNL_TX_CONFIG_REG(chnl) with: + * + * IWL_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | + * IWL_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL + * + * All other bits should be 0. + * + * Bit fields: + * 31-30: Tx DMA channel enable: '00' off/pause, '01' pause at end of frame, + * '10' operate normally + * 29- 4: Reserved, set to "0" + * 3: Enable internal DMA requests (1, normal operation), disable (0) + * 2- 0: Reserved, set to "0" + */ #define IWL_FH_TCSR_LOWER_BOUND (FH_MEM_LOWER_BOUND + 0xD00) #define IWL_FH_TCSR_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0xE60) +/* Find Control/Status reg for given Tx DMA/FIFO channel */ #define IWL_FH_TCSR_CHNL_TX_CONFIG_REG(_chnl) \ (IWL_FH_TCSR_LOWER_BOUND + 0x20 * _chnl) -/* TSSR Area - Tx shared status registers */ -/* TSSR */ +#define IWL_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE_VAL (0x00000000) +#define IWL_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL (0x00000008) + +#define IWL_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE (0x00000000) +#define IWL_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE_EOF (0x40000000) +#define IWL_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE (0x80000000) + +/** + * Tx Shared Status Registers (TSSR) + * + * After stopping Tx DMA channel (writing 0 to + * IWL_FH_TCSR_CHNL_TX_CONFIG_REG(chnl)), driver must poll + * IWL_FH_TSSR_TX_STATUS_REG until selected Tx channel is idle + * (channel's buffers empty | no pending requests). + * + * Bit fields: + * 31-24: 1 = Channel buffers empty (channel 7:0) + * 23-16: 1 = No pending requests (channel 7:0) + */ #define IWL_FH_TSSR_LOWER_BOUND (FH_MEM_LOWER_BOUND + 0xEA0) #define IWL_FH_TSSR_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0xEC0) @@ -1523,9 +1546,6 @@ enum { (IWL_FH_TSSR_TX_STATUS_REG_BIT_BUFS_EMPTY(_chnl) | \ IWL_FH_TSSR_TX_STATUS_REG_BIT_NO_PEND_REQ(_chnl)) -#define IWL_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL (0x00000008) - -#define IWL_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE (0x80000000) #define SCD_WIN_SIZE 64 #define SCD_FRAME_LIMIT 64 -- 1.5.3.6 ^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 26/36] iwlwifi: document shared Tx structures 2007-11-29 3:10 ` [PATCH 25/36] iwlwifi: document Tx registers Zhu Yi @ 2007-11-29 3:10 ` Zhu Yi 2007-11-29 3:10 ` [PATCH 27/36] iwlwifi: document 4965 Tx scheduler Zhu Yi 0 siblings, 1 reply; 36+ messages in thread From: Zhu Yi @ 2007-11-29 3:10 UTC (permalink / raw) To: linville; +Cc: linux-wireless, Ben Cahill, Zhu Yi From: Ben Cahill <ben.m.cahill@intel.com> Document shared Tx structures Signed-off-by: Ben Cahill <ben.m.cahill@intel.com> Signed-off-by: Zhu Yi <yi.zhu@intel.com> --- drivers/net/wireless/iwlwifi/iwl-4965-hw.h | 147 +++++++++++++++++++++++++--- 1 files changed, 135 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h index d8a01b1..ecfc6f5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h @@ -452,6 +452,13 @@ struct iwl4965_eeprom { */ #define CSR_HW_REV_WA_REG (CSR_BASE+0x22C) +/* Hardware interface configuration bits */ +#define CSR_HW_IF_CONFIG_REG_BIT_KEDRON_R (0x00000010) +#define CSR_HW_IF_CONFIG_REG_MSK_BOARD_VER (0x00000C00) +#define CSR_HW_IF_CONFIG_REG_BIT_MAC_SI (0x00000100) +#define CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI (0x00000200) +#define CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM (0x00200000) + /* interrupt flags in INTA, set by uCode or hardware (e.g. dma), * acknowledged (reset) by host writing "1" to flagged bits. */ #define CSR_INT_BIT_FH_RX (1<<31) /* Rx DMA, cmd responses, FH_INT[17:16] */ @@ -1574,12 +1581,6 @@ enum { #define SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS (16) #define SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK (0x007F0000) -#define CSR_HW_IF_CONFIG_REG_BIT_KEDRON_R (0x00000010) -#define CSR_HW_IF_CONFIG_REG_MSK_BOARD_VER (0x00000C00) -#define CSR_HW_IF_CONFIG_REG_BIT_MAC_SI (0x00000100) -#define CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI (0x00000200) -#define CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM (0x00200000) - static inline u8 iwl4965_hw_get_rate(__le32 rate_n_flags) { return le32_to_cpu(rate_n_flags) & 0xFF; @@ -1593,6 +1594,53 @@ static inline __le32 iwl4965_hw_set_rate_n_flags(u8 rate, u16 flags) return cpu_to_le32(flags|(u16)rate); } + +/** + * Tx/Rx Queues + * + * Most communication between driver and 4965 is via queues of data buffers. + * For example, all commands that the driver issues to device's embedded + * controller (uCode) are via the command queue (one of the Tx queues). All + * uCode command responses/replies/notifications, including Rx frames, are + * conveyed from uCode to driver via the Rx queue. + * + * Most support for these queues, including handshake support, resides in + * structures in host DRAM, shared between the driver and the device. When + * allocating this memory, the driver must make sure that data written by + * the host CPU updates DRAM immediately (and does not get "stuck" in CPU's + * cache memory), so DRAM and cache are consistent, and the device can + * immediately see changes made by the driver. + * + * 4965 supports up to 16 DRAM-based Tx queues, and services these queues via + * up to 7 DMA channels (FIFOs). Each Tx queue is supported by a circular array + * in DRAM containing 256 Transmit Frame Descriptors (TFDs). + */ +#define IWL4965_MAX_WIN_SIZE 64 +#define IWL4965_QUEUE_SIZE 256 +#define IWL4965_NUM_FIFOS 7 +#define IWL_MAX_NUM_QUEUES 16 + + +/** + * struct iwl4965_tfd_frame_data + * + * Describes up to 2 buffers containing (contiguous) portions of a Tx frame. + * Each buffer must be on dword boundary. + * Up to 10 iwl_tfd_frame_data structures, describing up to 20 buffers, + * may be filled within a TFD (iwl_tfd_frame). + * + * Bit fields in tb1_addr: + * 31- 0: Tx buffer 1 address bits [31:0] + * + * Bit fields in val1: + * 31-16: Tx buffer 2 address bits [15:0] + * 15- 4: Tx buffer 1 length (bytes) + * 3- 0: Tx buffer 1 address bits [32:32] + * + * Bit fields in val2: + * 31-20: Tx buffer 2 length (bytes) + * 19- 0: Tx buffer 2 address bits [35:16] + */ struct iwl4965_tfd_frame_data { __le32 tb1_addr; @@ -1621,6 +1669,35 @@ struct iwl4965_tfd_frame_data { #define IWL_tb2_len_SYM val2 } __attribute__ ((packed)); + +/** + * struct iwl4965_tfd_frame + * + * Transmit Frame Descriptor (TFD) + * + * 4965 supports up to 16 Tx queues resident in host DRAM. + * Each Tx queue uses a circular buffer of 256 TFDs stored in host DRAM. + * Both driver and device share these circular buffers, each of which must be + * contiguous 256 TFDs x 128 bytes-per-TFD = 32 KBytes for 4965. + * + * Driver must indicate the physical address of the base of each + * circular buffer via the 4965's FH_MEM_CBBC_QUEUE registers. + * + * Each TFD contains pointer/size information for up to 20 data buffers + * in host DRAM. These buffers collectively contain the (one) frame described + * by the TFD. Each buffer must be a single contiguous block of memory within + * itself, but buffers may be scattered in host DRAM. Each buffer has max size + * of (4K - 4). The 4965 concatenates all of a TFD's buffers into a single + * Tx frame, up to 8 KBytes in size. + * + * Bit fields in the control dword (val0): + * 31-30: # dwords (0-3) of padding required at end of frame for 16-byte bound + * 29: reserved + * 28-24: # Transmit Buffer Descriptors in TFD + * 23- 0: reserved + * + * A maximum of 255 (not 256!) TFDs may be on a queue waiting for Tx. + */ struct iwl4965_tfd_frame { __le32 val0; /* __le32 rsvd1:24; */ @@ -1634,11 +1711,16 @@ struct iwl4965_tfd_frame { __le32 reserved; } __attribute__ ((packed)); -#define IWL4965_MAX_WIN_SIZE 64 -#define IWL4965_QUEUE_SIZE 256 -#define IWL4965_NUM_FIFOS 7 -#define IWL_MAX_NUM_QUEUES 16 +/** + * struct iwl4965_queue_byte_cnt_entry + * + * Byte Count Table Entry + * + * Bit fields: + * 15-12: reserved + * 11- 0: total to-be-transmitted byte count of frame (does not include command) + */ struct iwl4965_queue_byte_cnt_entry { __le16 val; /* __le16 byte_cnt:12; */ @@ -1648,6 +1730,25 @@ struct iwl4965_queue_byte_cnt_entry { /* __le16 rsvd:4; */ } __attribute__ ((packed)); + +/** + * struct iwl4965_sched_queue_byte_cnt_tbl + * + * Byte Count table + * + * Each Tx queue uses a byte-count table containing 320 entries: + * one 16-bit entry for each of 256 TFDs, plus an additional 64 entries that + * duplicate the first 64 entries (to avoid wrap-around within a Tx window; + * max Tx window is 64 TFDs). + * + * When driver sets up a new TFD, it must also enter the total byte count + * of the frame to be transmitted into the corresponding entry in the byte + * count table for the chosen Tx queue. If the TFD index is 0-63, the driver + * must duplicate the byte count entry in corresponding index 256-319. + * + * "dont_care" padding puts each byte count table on a 1024-byte boundary; + * 4965 assumes tables are separated by 1024 bytes. + */ struct iwl4965_sched_queue_byte_cnt_tbl { struct iwl4965_queue_byte_cnt_entry tfd_offset[IWL4965_QUEUE_SIZE + IWL4965_MAX_WIN_SIZE]; @@ -1656,8 +1757,30 @@ struct iwl4965_sched_queue_byte_cnt_tbl { sizeof(__le16)]; } __attribute__ ((packed)); -/* Base physical address of iwl4965_shared is provided to KDR_SCD_DRAM_BASE_ADDR - * and &iwl4965_shared.val0 is provided to FH_RSCSR_CHNL0_STTS_WPTR_REG */ + +/** + * struct iwl4965_shared - handshake area for Tx and Rx + * + * For convenience in allocating memory, this structure combines 2 areas of + * DRAM which must be shared between driver and 4965. These do not need to + * be combined, if better allocation would result from keeping them separate: + * + * 1) The Tx byte count tables occupy 1024 bytes each (16 KBytes total for + * 16 queues). Driver uses SCD_DRAM_BASE_ADDR to tell 4965 where to find + * the first of these tables. 4965 assumes tables are 1024 bytes apart. + * + * 2) The Rx status (val0 and val1) occupies only 8 bytes. Driver uses + * FH_RSCSR_CHNL0_STTS_WPTR_REG to tell 4965 where to find this area. + * Driver reads val0 to determine the latest Receive Buffer Descriptor (RBD) + * that has been filled by the 4965. + * + * Bit fields val0: + * 31-12: Not used + * 11- 0: Index of last filled Rx buffer descriptor (4965 writes, driver reads) + * + * Bit fields val1: + * 31- 0: Not used + */ struct iwl4965_shared { struct iwl4965_sched_queue_byte_cnt_tbl queues_byte_cnt_tbls[IWL_MAX_NUM_QUEUES]; -- 1.5.3.6 ^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 27/36] iwlwifi: document 4965 Tx scheduler 2007-11-29 3:10 ` [PATCH 26/36] iwlwifi: document shared Tx structures Zhu Yi @ 2007-11-29 3:10 ` Zhu Yi 2007-11-29 3:10 ` [PATCH 28/36] iwlwifi: document command header and "alive" responses Zhu Yi 0 siblings, 1 reply; 36+ messages in thread From: Zhu Yi @ 2007-11-29 3:10 UTC (permalink / raw) To: linville; +Cc: linux-wireless, Ben Cahill, Zhu Yi From: Ben Cahill <ben.m.cahill@intel.com> Document 4965 Tx scheduler Signed-off-by: Ben Cahill <ben.m.cahill@intel.com> Signed-off-by: Zhu Yi <yi.zhu@intel.com> --- drivers/net/wireless/iwlwifi/iwl-4965-hw.h | 268 ++++++++++++++++++++++++++- drivers/net/wireless/iwlwifi/iwl-prph.h | 14 +- drivers/net/wireless/iwlwifi/iwl4965-base.c | 2 + 3 files changed, 272 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h index ecfc6f5..9bad516 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h @@ -1554,33 +1554,285 @@ enum { IWL_FH_TSSR_TX_STATUS_REG_BIT_NO_PEND_REQ(_chnl)) +/********************* START TX SCHEDULER *************************************/ + +/** + * 4965 Tx Scheduler + * + * The Tx Scheduler selects the next frame to be transmitted, chosing TFDs + * (Transmit Frame Descriptors) from up to 16 circular Tx queues resident in + * host DRAM. It steers each frame's Tx command (which contains the frame + * data) into one of up to 7 prioritized Tx DMA FIFO channels within the + * device. A queue maps to only one (selectable by driver) Tx DMA channel, + * but one DMA channel may take input from several queues. + * + * Tx DMA channels have dedicated purposes. For 4965, they are used as follows: + * + * 0 -- EDCA BK (background) frames, lowest priority + * 1 -- EDCA BE (best effort) frames, normal priority + * 2 -- EDCA VI (video) frames, higher priority + * 3 -- EDCA VO (voice) and management frames, highest priority + * 4 -- Commands (e.g. RXON, etc.) + * 5 -- HCCA short frames + * 6 -- HCCA long frames + * 7 -- not used by driver (device-internal only) + * + * Driver should normally map queues 0-6 to Tx DMA/FIFO channels 0-6. + * In addition, driver can map queues 7-15 to Tx DMA/FIFO channels 0-3 to + * support 11n aggregation via EDCA DMA channels. + * + * The driver sets up each queue to work in one of two modes: + * + * 1) Scheduler-Ack, in which the scheduler automatically supports a + * block-ack (BA) window of up to 64 TFDs. In this mode, each queue + * contains TFDs for a unique combination of Recipient Address (RA) + * and Traffic Identifier (TID), that is, traffic of a given + * Quality-Of-Service (QOS) priority, destined for a single station. + * + * In scheduler-ack mode, the scheduler keeps track of the Tx status of + * each frame within the BA window, including whether it's been transmitted, + * and whether it's been acknowledged by the receiving station. The device + * automatically processes block-acks received from the receiving STA, + * and reschedules un-acked frames to be retransmitted (successful + * Tx completion may end up being out-of-order). + * + * The driver must maintain the queue's Byte Count table in host DRAM + * (struct iwl4965_sched_queue_byte_cnt_tbl) for this mode. + * This mode does not support fragmentation. + * + * 2) FIFO (a.k.a. non-Scheduler-ACK), in which each TFD is processed in order. + * The device may automatically retry Tx, but will retry only one frame + * at a time, until receiving ACK from receiving station, or reaching + * retry limit and giving up. + * + * The command queue (#4) must use this mode! + * This mode does not require use of the Byte Count table in host DRAM. + * + * Driver controls scheduler operation via 3 means: + * 1) Scheduler registers + * 2) Shared scheduler data base in internal 4956 SRAM + * 3) Shared data in host DRAM + * + * Initialization: + * + * When loading, driver should allocate memory for: + * 1) 16 TFD circular buffers, each with space for (typically) 256 TFDs. + * 2) 16 Byte Count circular buffers in 16 KBytes contiguous memory + * (1024 bytes for each queue). + * + * After receiving "Alive" response from uCode, driver must initialize + * the scheduler (especially for queue #4, the command queue, otherwise + * the driver can't issue commands!): + */ + +/** + * Max Tx window size is the max number of contiguous TFDs that the scheduler + * can keep track of at one time when creating block-ack chains of frames. + * Note that "64" matches the number of ack bits in a block-ack packet. + * Driver should use SCD_WIN_SIZE and SCD_FRAME_LIMIT values to initialize + * SCD_CONTEXT_QUEUE_OFFSET(x) values. + */ #define SCD_WIN_SIZE 64 #define SCD_FRAME_LIMIT 64 -/* SRAM structures */ -#define SCD_CONTEXT_DATA_OFFSET 0x380 -#define SCD_TX_STTS_BITMAP_OFFSET 0x400 -#define SCD_TRANSLATE_TBL_OFFSET 0x500 -#define SCD_CONTEXT_QUEUE_OFFSET(x) (SCD_CONTEXT_DATA_OFFSET + ((x) * 8)) -#define SCD_TRANSLATE_TBL_OFFSET_QUEUE(x) \ - ((SCD_TRANSLATE_TBL_OFFSET + ((x) * 2)) & 0xfffffffc) +/* SCD registers are internal, must be accessed via HBUS_TARG_PRPH regs */ +#define SCD_START_OFFSET 0xa02c00 + +/* + * 4965 tells driver SRAM address for internal scheduler structs via this reg. + * Value is valid only after "Alive" response from uCode. + */ +#define SCD_SRAM_BASE_ADDR (SCD_START_OFFSET + 0x0) +/* + * Driver may need to update queue-empty bits after changing queue's + * write and read pointers (indexes) during (re-)initialization (i.e. when + * scheduler is not tracking what's happening). + * Bit fields: + * 31-16: Write mask -- 1: update empty bit, 0: don't change empty bit + * 15-00: Empty state, one for each queue -- 1: empty, 0: non-empty + * NOTE: This register is not used by Linux driver. + */ +#define SCD_EMPTY_BITS (SCD_START_OFFSET + 0x4) + +/* + * Physical base address of array of byte count (BC) circular buffers (CBs). + * Each Tx queue has a BC CB in host DRAM to support Scheduler-ACK mode. + * This register points to BC CB for queue 0, must be on 1024-byte boundary. + * Others are spaced by 1024 bytes. + * Each BC CB is 2 bytes * (256 + 64) = 740 bytes, followed by 384 bytes pad. + * (Index into a queue's BC CB) = (index into queue's TFD CB) = (SSN & 0xff). + * Bit fields: + * 25-00: Byte Count CB physical address [35:10], must be 1024-byte aligned. + */ +#define SCD_DRAM_BASE_ADDR (SCD_START_OFFSET + 0x10) + +/* + * Enables any/all Tx DMA/FIFO channels. + * Scheduler generates requests for only the active channels. + * Set this to 0xff to enable all 8 channels (normal usage). + * Bit fields: + * 7- 0: Enable (1), disable (0), one bit for each channel 0-7 + */ +#define SCD_TXFACT (SCD_START_OFFSET + 0x1c) + +/* Mask to enable contiguous Tx DMA/FIFO channels between "lo" and "hi". */ #define SCD_TXFACT_REG_TXFIFO_MASK(lo, hi) \ ((1<<(hi))|((1<<(hi))-(1<<(lo)))) +/* + * Queue (x) Write Pointers (indexes, really!), one for each Tx queue. + * Initialized and updated by driver as new TFDs are added to queue. + * NOTE: If using Block Ack, index must correspond to frame's + * Start Sequence Number; index = (SSN & 0xff) + * NOTE: Alternative to HBUS_TARG_WRPTR, which is what Linux driver uses? + */ +#define SCD_QUEUE_WRPTR(x) (SCD_START_OFFSET + 0x24 + (x) * 4) + +/* + * Queue (x) Read Pointers (indexes, really!), one for each Tx queue. + * For FIFO mode, index indicates next frame to transmit. + * For Scheduler-ACK mode, index indicates first frame in Tx window. + * Initialized by driver, updated by scheduler. + */ +#define SCD_QUEUE_RDPTR(x) (SCD_START_OFFSET + 0x64 + (x) * 4) + +/* + * Select which queues work in chain mode (1) vs. not (0). + * Use chain mode to build chains of aggregated frames. + * Bit fields: + * 31-16: Reserved + * 15-00: Mode, one bit for each queue -- 1: Chain mode, 0: one-at-a-time + * NOTE: If driver sets up queue for chain mode, it should be also set up + * Scheduler-ACK mode as well, via SCD_QUEUE_STATUS_BITS(x). + */ +#define SCD_QUEUECHAIN_SEL (SCD_START_OFFSET + 0xd0) + +/* + * Select which queues interrupt driver when scheduler increments + * a queue's read pointer (index). + * Bit fields: + * 31-16: Reserved + * 15-00: Interrupt enable, one bit for each queue -- 1: enabled, 0: disabled + * NOTE: This functionality is apparently a no-op; driver relies on interrupts + * from Rx queue to read Tx command responses and update Tx queues. + */ +#define SCD_INTERRUPT_MASK (SCD_START_OFFSET + 0xe4) + +/* + * Queue search status registers. One for each queue. + * Sets up queue mode and assigns queue to Tx DMA channel. + * Bit fields: + * 19-10: Write mask/enable bits for bits 0-9 + * 9: Driver should init to "0" + * 8: Scheduler-ACK mode (1), non-Scheduler-ACK (i.e. FIFO) mode (0). + * Driver should init to "1" for aggregation mode, or "0" otherwise. + * 7-6: Driver should init to "0" + * 5: Window Size Left; indicates whether scheduler can request + * another TFD, based on window size, etc. Driver should init + * this bit to "1" for aggregation mode, or "0" for non-agg. + * 4-1: Tx FIFO to use (range 0-7). + * 0: Queue is active (1), not active (0). + * Other bits should be written as "0" + * + * NOTE: If enabling Scheduler-ACK mode, chain mode should also be enabled + * via SCD_QUEUECHAIN_SEL. + */ +#define SCD_QUEUE_STATUS_BITS(x) (SCD_START_OFFSET + 0x104 + (x) * 4) + +/* Bit field positions */ #define SCD_QUEUE_STTS_REG_POS_ACTIVE (0) #define SCD_QUEUE_STTS_REG_POS_TXF (1) #define SCD_QUEUE_STTS_REG_POS_WSL (5) #define SCD_QUEUE_STTS_REG_POS_SCD_ACK (8) + +/* Write masks */ #define SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN (10) #define SCD_QUEUE_STTS_REG_MSK (0x0007FC00) +/** + * 4965 internal SRAM structures for scheduler, shared with driver ... + * + * Driver should clear and initialize the following areas after receiving + * "Alive" response from 4965 uCode, i.e. after initial + * uCode load, or after a uCode load done for error recovery: + * + * SCD_CONTEXT_DATA_OFFSET (size 128 bytes) + * SCD_TX_STTS_BITMAP_OFFSET (size 256 bytes) + * SCD_TRANSLATE_TBL_OFFSET (size 32 bytes) + * + * Driver accesses SRAM via HBUS_TARG_MEM_* registers. + * Driver reads base address of this scheduler area from SCD_SRAM_BASE_ADDR. + * All OFFSET values must be added to this base address. + */ + +/* + * Queue context. One 8-byte entry for each of 16 queues. + * + * Driver should clear this entire area (size 0x80) to 0 after receiving + * "Alive" notification from uCode. Additionally, driver should init + * each queue's entry as follows: + * + * LS Dword bit fields: + * 0-06: Max Tx window size for Scheduler-ACK. Driver should init to 64. + * + * MS Dword bit fields: + * 16-22: Frame limit. Driver should init to 10 (0xa). + * + * Driver should init all other bits to 0. + * + * Init must be done after driver receives "Alive" response from 4965 uCode, + * and when setting up queue for aggregation. + */ +#define SCD_CONTEXT_DATA_OFFSET 0x380 +#define SCD_CONTEXT_QUEUE_OFFSET(x) (SCD_CONTEXT_DATA_OFFSET + ((x) * 8)) + #define SCD_QUEUE_CTX_REG1_WIN_SIZE_POS (0) #define SCD_QUEUE_CTX_REG1_WIN_SIZE_MSK (0x0000007F) - #define SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS (16) #define SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK (0x007F0000) +/* + * Tx Status Bitmap + * + * Driver should clear this entire area (size 0x100) to 0 after receiving + * "Alive" notification from uCode. Area is used only by device itself; + * no other support (besides clearing) is required from driver. + */ +#define SCD_TX_STTS_BITMAP_OFFSET 0x400 + +/* + * RAxTID to queue translation mapping. + * + * When queue is in Scheduler-ACK mode, frames placed in a that queue must be + * for only one combination of receiver address (RA) and traffic ID (TID), i.e. + * one QOS priority level destined for one station (for this wireless link, + * not final destination). The SCD_TRANSLATE_TABLE area provides 16 16-bit + * mappings, one for each of the 16 queues. If queue is not in Scheduler-ACK + * mode, the device ignores the mapping value. + * + * Bit fields, for each 16-bit map: + * 15-9: Reserved, set to 0 + * 8-4: Index into device's station table for recipient station + * 3-0: Traffic ID (tid), range 0-15 + * + * Driver should clear this entire area (size 32 bytes) to 0 after receiving + * "Alive" notification from uCode. To update a 16-bit map value, driver + * must read a dword-aligned value from device SRAM, replace the 16-bit map + * value of interest, and write the dword value back into device SRAM. + */ +#define SCD_TRANSLATE_TBL_OFFSET 0x500 + +/* Find translation table dword to read/write for given queue */ +#define SCD_TRANSLATE_TBL_OFFSET_QUEUE(x) \ + ((SCD_TRANSLATE_TBL_OFFSET + ((x) * 2)) & 0xfffffffc) + +#define SCD_TXFIFO_POS_TID (0) +#define SCD_TXFIFO_POS_RA (4) +#define SCD_QUEUE_RA_TID_MAP_RATID_MSK (0x01FF) + +/*********************** END TX SCHEDULER *************************************/ + static inline u8 iwl4965_hw_get_rate(__le32 rate_n_flags) { return le32_to_cpu(rate_n_flags) & 0xFF; diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h index 137947d..4ba1216 100644 --- a/drivers/net/wireless/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/iwlwifi/iwl-prph.h @@ -63,7 +63,10 @@ #ifndef __iwl_prph_h__ #define __iwl_prph_h__ - +/* + * Registers in this file are internal, not PCI bus memory mapped. + * Driver accesses these via HBUS_TARG_PRPH_* registers. + */ #define PRPH_BASE (0x00000) #define PRPH_END (0xFFFFF) @@ -225,8 +228,8 @@ #define BSM_SRAM_LOWER_BOUND (PRPH_BASE + 0x3800) #define BSM_SRAM_SIZE (1024) /* bytes */ -/* ALM SCD */ -/* SCD (Scheduler) */ + +/* 3945 Tx scheduler registers */ #define ALM_SCD_BASE (PRPH_BASE + 0x2E00) #define ALM_SCD_MODE_REG (ALM_SCD_BASE + 0x000) #define ALM_SCD_ARASTAT_REG (ALM_SCD_BASE + 0x004) @@ -236,7 +239,10 @@ #define ALM_SCD_SBYP_MODE_1_REG (ALM_SCD_BASE + 0x02C) #define ALM_SCD_SBYP_MODE_2_REG (ALM_SCD_BASE + 0x030) -/* 4965 SCD memory mapped registers */ +/* + * 4965 Tx Scheduler registers. + * Details are documented in iwl-4965-hw.h + */ #define KDR_SCD_BASE (PRPH_BASE + 0xa02c00) #define KDR_SCD_SRAM_BASE_ADDR (KDR_SCD_BASE + 0x0) diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index f813669..31601d7 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -201,6 +201,8 @@ static void iwl4965_print_hex_dump(int level, void *p, u32 len) * The 4965 operates with up to 17 queues: One receive queue, one transmit * queue (#4) for sending commands to the device firmware, and 15 other * Tx queues that may be mapped to prioritized Tx DMA/FIFO channels. + * + * See more detailed info in iwl-4965-hw.h. ***************************************************/ static int iwl4965_queue_space(const struct iwl4965_queue *q) -- 1.5.3.6 ^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 28/36] iwlwifi: document command header and "alive" responses 2007-11-29 3:10 ` [PATCH 27/36] iwlwifi: document 4965 Tx scheduler Zhu Yi @ 2007-11-29 3:10 ` Zhu Yi 2007-11-29 3:10 ` [PATCH 29/36] iwlwifi: add comments to RXON command and txpower formats Zhu Yi 0 siblings, 1 reply; 36+ messages in thread From: Zhu Yi @ 2007-11-29 3:10 UTC (permalink / raw) To: linville; +Cc: linux-wireless, Ben Cahill, Zhu Yi From: Ben Cahill <ben.m.cahill@intel.com> Document command header and "alive" responses Signed-off-by: Ben Cahill <ben.m.cahill@intel.com> Signed-off-by: Zhu Yi <yi.zhu@intel.com> --- drivers/net/wireless/iwlwifi/iwl-3945-commands.h | 85 +++++++++--- drivers/net/wireless/iwlwifi/iwl-4965-commands.h | 160 +++++++++++++++++----- 2 files changed, 192 insertions(+), 53 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-commands.h b/drivers/net/wireless/iwlwifi/iwl-3945-commands.h index 794db78..3d3c7e3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-commands.h @@ -121,7 +121,7 @@ enum { REPLY_TX_PWR_TABLE_CMD = 0x97, MEASURE_ABORT_NOTIFICATION = 0x99, /* not used */ - /* BT config command */ + /* Bluetooth device coexistance config command */ REPLY_BT_CONFIG = 0x9b, /* 4965 Statistics */ @@ -144,25 +144,42 @@ enum { * *****************************************************************************/ +/* iwl3945_cmd_header flags value */ #define IWL_CMD_FAILED_MSK 0x40 +/** + * struct iwl3945_cmd_header + * + * This header format appears in the beginning of each command sent from the + * driver, and each response/notification received from uCode. + */ struct iwl3945_cmd_header { - u8 cmd; - u8 flags; - /* We have 15 LSB to use as we please (MSB indicates - * a frame Rx'd from the HW). We encode the following - * information into the sequence field: + u8 cmd; /* Command ID: REPLY_RXON, etc. */ + u8 flags; /* IWL_CMD_* */ + /* + * The driver sets up the sequence number to values of its chosing. + * uCode does not use this value, but passes it back to the driver + * when sending the response to each driver-originated command, so + * the driver can match the response to the command. Since the values + * don't get used by uCode, the driver may set up an arbitrary format. + * + * There is one exception: uCode sets bit 15 when it originates + * the response/notification, i.e. when the response/notification + * is not a direct response to a command sent by the driver. For + * example, uCode issues REPLY_3945_RX when it sends a received frame + * to the driver; it is not a direct response to any driver command. * - * 0:7 index in fifo - * 8:13 fifo selection - * 14:14 bit indicating if this packet references the 'extra' - * storage at the end of the memory queue - * 15:15 (Rx indication) + * The Linux driver uses the following format: * + * 0:7 index/position within Tx queue + * 8:13 Tx queue selection + * 14:14 driver sets this to indicate command is in the 'huge' + * storage at the end of the command buffers, i.e. scan cmd + * 15:15 uCode sets this in uCode-originated response/notification */ __le16 sequence; - /* command data follows immediately */ + /* command or response/notification data follows immediately */ u8 data[0]; } __attribute__ ((packed)); @@ -176,15 +193,22 @@ struct iwl3945_cmd_header { #define INITIALIZE_SUBTYPE (9) /* - * REPLY_ALIVE = 0x1 (response only, not a command) + * ("Initialize") REPLY_ALIVE = 0x1 (response only, not a command) + * + * uCode issues this "initialize alive" notification once the initialization + * uCode image has completed its work, and is ready to load the runtime image. + * This is the *first* "alive" notification that the driver will receive after + * rebooting uCode; the "initialize" alive is indicated by subtype field == 9. + * + * See comments documenting "BSM" (bootstrap state machine). */ -struct iwl3945_alive_resp { +struct iwl3945_init_alive_resp { u8 ucode_minor; u8 ucode_major; __le16 reserved1; u8 sw_rev[8]; u8 ver_type; - u8 ver_subtype; + u8 ver_subtype; /* "9" for initialize alive */ __le16 reserved2; __le32 log_event_table_ptr; __le32 error_event_table_ptr; @@ -192,16 +216,39 @@ struct iwl3945_alive_resp { __le32 is_valid; } __attribute__ ((packed)); -struct iwl3945_init_alive_resp { + +/** + * REPLY_ALIVE = 0x1 (response only, not a command) + * + * uCode issues this "alive" notification once the runtime image is ready + * to receive commands from the driver. This is the *second* "alive" + * notification that the driver will receive after rebooting uCode; + * this "alive" is indicated by subtype field != 9. + * + * See comments documenting "BSM" (bootstrap state machine). + * + * This response includes two pointers to structures within the device's + * data SRAM (access via HBUS_TARG_MEM_* regs) that are useful for debugging: + * + * 1) log_event_table_ptr indicates base of the event log. This traces + * a 256-entry history of uCode execution within a circular buffer. + * + * 2) error_event_table_ptr indicates base of the error log. This contains + * information about any uCode error that occurs. + * + * The Linux driver can print both logs to the system log when a uCode error + * occurs. + */ +struct iwl3945_alive_resp { u8 ucode_minor; u8 ucode_major; __le16 reserved1; u8 sw_rev[8]; u8 ver_type; - u8 ver_subtype; + u8 ver_subtype; /* not "9" for runtime alive */ __le16 reserved2; - __le32 log_event_table_ptr; - __le32 error_event_table_ptr; + __le32 log_event_table_ptr; /* SRAM address for event log */ + __le32 error_event_table_ptr; /* SRAM address for error log */ __le32 timestamp; __le32 is_valid; } __attribute__ ((packed)); diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-commands.h b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h index 9910939..bde3aa0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h @@ -120,7 +120,7 @@ enum { REPLY_TX_PWR_TABLE_CMD = 0x97, MEASURE_ABORT_NOTIFICATION = 0x99, /* not used */ - /* BT config command */ + /* Bluetooth device coexistance config command */ REPLY_BT_CONFIG = 0x9b, /* 4965 Statistics */ @@ -151,25 +151,42 @@ enum { * *****************************************************************************/ +/* iwl4965_cmd_header flags value */ #define IWL_CMD_FAILED_MSK 0x40 +/** + * struct iwl4965_cmd_header + * + * This header format appears in the beginning of each command sent from the + * driver, and each response/notification received from uCode. + */ struct iwl4965_cmd_header { - u8 cmd; - u8 flags; - /* We have 15 LSB to use as we please (MSB indicates - * a frame Rx'd from the HW). We encode the following - * information into the sequence field: + u8 cmd; /* Command ID: REPLY_RXON, etc. */ + u8 flags; /* IWL_CMD_* */ + /* + * The driver sets up the sequence number to values of its chosing. + * uCode does not use this value, but passes it back to the driver + * when sending the response to each driver-originated command, so + * the driver can match the response to the command. Since the values + * don't get used by uCode, the driver may set up an arbitrary format. * - * 0:7 index in fifo - * 8:13 fifo selection - * 14:14 bit indicating if this packet references the 'extra' - * storage at the end of the memory queue - * 15:15 (Rx indication) + * There is one exception: uCode sets bit 15 when it originates + * the response/notification, i.e. when the response/notification + * is not a direct response to a command sent by the driver. For + * example, uCode issues REPLY_3945_RX when it sends a received frame + * to the driver; it is not a direct response to any driver command. * + * The Linux driver uses the following format: + * + * 0:7 index/position within Tx queue + * 8:13 Tx queue selection + * 14:14 driver sets this to indicate command is in the 'huge' + * storage at the end of the command buffers, i.e. scan cmd + * 15:15 uCode sets this in uCode-originated response/notification */ __le16 sequence; - /* command data follows immediately */ + /* command or response/notification data follows immediately */ u8 data[0]; } __attribute__ ((packed)); @@ -218,28 +235,28 @@ struct iwl4965_cmd_header { #define RATE_MCS_HT_DUP_POS 5 #define RATE_MCS_HT_DUP_MSK 0x20 -/* (1) HT format, (0) legacy format in bits 7:0 */ +/* Bit 8: (1) HT format, (0) legacy format in bits 7:0 */ #define RATE_MCS_FLAGS_POS 8 #define RATE_MCS_HT_POS 8 #define RATE_MCS_HT_MSK 0x100 -/* (1) CCK, (0) OFDM. HT (bit 8) must be "0" for this bit to be valid */ +/* Bit 9: (1) CCK, (0) OFDM. HT (bit 8) must be "0" for this bit to be valid */ #define RATE_MCS_CCK_POS 9 #define RATE_MCS_CCK_MSK 0x200 -/* (1) Use Green Field preamble */ +/* Bit 10: (1) Use Green Field preamble */ #define RATE_MCS_GF_POS 10 #define RATE_MCS_GF_MSK 0x400 -/* (1) Use 40Mhz FAT channel width, (0) use 20 MHz legacy channel width */ +/* Bit 11: (1) Use 40Mhz FAT chnl width, (0) use 20 MHz legacy chnl width */ #define RATE_MCS_FAT_POS 11 #define RATE_MCS_FAT_MSK 0x800 -/* (1) Duplicate data on both 20MHz channels. FAT (bit 11) must be set. */ +/* Bit 12: (1) Duplicate data on both 20MHz chnls. FAT (bit 11) must be set. */ #define RATE_MCS_DUP_POS 12 #define RATE_MCS_DUP_MSK 0x1000 -/* (1) Short guard interval (0.4 usec), (0) normal GI (0.8 usec) */ +/* Bit 13: (1) Short guard interval (0.4 usec), (0) normal GI (0.8 usec) */ #define RATE_MCS_SGI_POS 13 #define RATE_MCS_SGI_MSK 0x2000 @@ -266,45 +283,120 @@ struct iwl4965_cmd_header { #define INITIALIZE_SUBTYPE (9) /* - * REPLY_ALIVE = 0x1 (response only, not a command) + * ("Initialize") REPLY_ALIVE = 0x1 (response only, not a command) + * + * uCode issues this "initialize alive" notification once the initialization + * uCode image has completed its work, and is ready to load the runtime image. + * This is the *first* "alive" notification that the driver will receive after + * rebooting uCode; the "initialize" alive is indicated by subtype field == 9. + * + * See comments documenting "BSM" (bootstrap state machine). + * + * For 4965, this notification contains important calibration data for + * calculating txpower settings: + * + * 1) Power supply voltage indication. The voltage sensor outputs higher + * values for lower voltage, and vice versa. + * + * 2) Temperature measurement parameters, for each of two channel widths + * (20 MHz and 40 MHz) supported by the radios. Temperature sensing + * is done via one of the receiver chains, and channel width influences + * the results. + * + * 3) Tx gain compensation to balance 4965's 2 Tx chains for MIMO operation, + * for each of 5 frequency ranges. */ -struct iwl4965_alive_resp { +struct iwl4965_init_alive_resp { u8 ucode_minor; u8 ucode_major; __le16 reserved1; u8 sw_rev[8]; u8 ver_type; - u8 ver_subtype; + u8 ver_subtype; /* "9" for initialize alive */ __le16 reserved2; __le32 log_event_table_ptr; __le32 error_event_table_ptr; __le32 timestamp; __le32 is_valid; + + /* calibration values from "initialize" uCode */ + __le32 voltage; /* signed, higher value is lower voltage */ + __le32 therm_r1[2]; /* signed, 1st for normal, 2nd for FAT channel*/ + __le32 therm_r2[2]; /* signed */ + __le32 therm_r3[2]; /* signed */ + __le32 therm_r4[2]; /* signed */ + __le32 tx_atten[5][2]; /* signed MIMO gain comp, 5 freq groups, + * 2 Tx chains */ } __attribute__ ((packed)); -struct iwl4965_init_alive_resp { + +/** + * REPLY_ALIVE = 0x1 (response only, not a command) + * + * uCode issues this "alive" notification once the runtime image is ready + * to receive commands from the driver. This is the *second* "alive" + * notification that the driver will receive after rebooting uCode; + * this "alive" is indicated by subtype field != 9. + * + * See comments documenting "BSM" (bootstrap state machine). + * + * This response includes two pointers to structures within the device's + * data SRAM (access via HBUS_TARG_MEM_* regs) that are useful for debugging: + * + * 1) log_event_table_ptr indicates base of the event log. This traces + * a 256-entry history of uCode execution within a circular buffer. + * Its header format is: + * + * __le32 log_size; log capacity (in number of entries) + * __le32 type; (1) timestamp with each entry, (0) no timestamp + * __le32 wraps; # times uCode has wrapped to top of circular buffer + * __le32 write_index; next circular buffer entry that uCode would fill + * + * The header is followed by the circular buffer of log entries. Entries + * with timestamps have the following format: + * + * __le32 event_id; range 0 - 1500 + * __le32 timestamp; low 32 bits of TSF (of network, if associated) + * __le32 data; event_id-specific data value + * + * Entries without timestamps contain only event_id and data. + * + * 2) error_event_table_ptr indicates base of the error log. This contains + * information about any uCode error that occurs. For 4965, the format + * of the error log is: + * + * __le32 valid; (nonzero) valid, (0) log is empty + * __le32 error_id; type of error + * __le32 pc; program counter + * __le32 blink1; branch link + * __le32 blink2; branch link + * __le32 ilink1; interrupt link + * __le32 ilink2; interrupt link + * __le32 data1; error-specific data + * __le32 data2; error-specific data + * __le32 line; source code line of error + * __le32 bcon_time; beacon timer + * __le32 tsf_low; network timestamp function timer + * __le32 tsf_hi; network timestamp function timer + * + * The Linux driver can print both logs to the system log when a uCode error + * occurs. + */ +struct iwl4965_alive_resp { u8 ucode_minor; u8 ucode_major; __le16 reserved1; u8 sw_rev[8]; u8 ver_type; - u8 ver_subtype; + u8 ver_subtype; /* not "9" for runtime alive */ __le16 reserved2; - __le32 log_event_table_ptr; - __le32 error_event_table_ptr; + __le32 log_event_table_ptr; /* SRAM address for event log */ + __le32 error_event_table_ptr; /* SRAM address for error log */ __le32 timestamp; __le32 is_valid; - - /* calibration values from "initialize" uCode */ - __le32 voltage; /* signed */ - __le32 therm_r1[2]; /* signed 1st for normal, 2nd for FAT channel */ - __le32 therm_r2[2]; /* signed */ - __le32 therm_r3[2]; /* signed */ - __le32 therm_r4[2]; /* signed */ - __le32 tx_atten[5][2]; /* signed MIMO gain comp, 5 freq groups, - * 2 Tx chains */ } __attribute__ ((packed)); + union tsf { u8 byte[8]; __le16 word[4]; -- 1.5.3.6 ^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 29/36] iwlwifi: add comments to RXON command and txpower formats 2007-11-29 3:10 ` [PATCH 28/36] iwlwifi: document command header and "alive" responses Zhu Yi @ 2007-11-29 3:10 ` Zhu Yi 2007-11-29 3:10 ` [PATCH 30/36] iwlwifi: add comments to QOS and ADD_STA commands Zhu Yi 0 siblings, 1 reply; 36+ messages in thread From: Zhu Yi @ 2007-11-29 3:10 UTC (permalink / raw) To: linville; +Cc: linux-wireless, Ben Cahill, Zhu Yi From: Ben Cahill <ben.m.cahill@intel.com> Add comments to RXON command and txpower formats Signed-off-by: Ben Cahill <ben.m.cahill@intel.com> Signed-off-by: Zhu Yi <yi.zhu@intel.com> --- drivers/net/wireless/iwlwifi/iwl-3945-commands.h | 62 ++++++++++--- drivers/net/wireless/iwlwifi/iwl-4965-commands.h | 104 ++++++++++++++++------ 2 files changed, 124 insertions(+), 42 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-commands.h b/drivers/net/wireless/iwlwifi/iwl-3945-commands.h index 3d3c7e3..4a8fc68 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-commands.h @@ -124,7 +124,7 @@ enum { /* Bluetooth device coexistance config command */ REPLY_BT_CONFIG = 0x9b, - /* 4965 Statistics */ + /* Statistics */ REPLY_STATISTICS_CMD = 0x9c, STATISTICS_NOTIFICATION = 0x9d, @@ -140,7 +140,8 @@ enum { /****************************************************************************** * (0) - * Header + * Commonly used structures and definitions: + * Command header, txpower * *****************************************************************************/ @@ -183,6 +184,36 @@ struct iwl3945_cmd_header { u8 data[0]; } __attribute__ ((packed)); +/** + * struct iwl3945_tx_power + * + * Used in REPLY_TX_PWR_TABLE_CMD, REPLY_SCAN_CMD, REPLY_CHANNEL_SWITCH + * + * Each entry contains two values: + * 1) DSP gain (or sometimes called DSP attenuation). This is a fine-grained + * linear value that multiplies the output of the digital signal processor, + * before being sent to the analog radio. + * 2) Radio gain. This sets the analog gain of the radio Tx path. + * It is a coarser setting, and behaves in a logarithmic (dB) fashion. + * + * Driver obtains values from struct iwl3945_tx_power power_gain_table[][]. + */ +struct iwl3945_tx_power { + u8 tx_gain; /* gain for analog radio */ + u8 dsp_atten; /* gain for DSP */ +} __attribute__ ((packed)); + +/** + * struct iwl3945_power_per_rate + * + * Used in REPLY_TX_PWR_TABLE_CMD, REPLY_CHANNEL_SWITCH + */ +struct iwl3945_power_per_rate { + u8 rate; /* plcp */ + struct iwl3945_tx_power tpc; + u8 reserved; +} __attribute__ ((packed)); + /****************************************************************************** * (0a) * Alive and Error Commands & Responses: @@ -328,8 +359,22 @@ enum { /* transfer to host non bssid beacons in associated state */ #define RXON_FILTER_BCON_AWARE_MSK __constant_cpu_to_le32(1 << 6) -/* +/** * REPLY_RXON = 0x10 (command, has simple generic response) + * + * RXON tunes the radio tuner to a service channel, and sets up a number + * of parameters that are used primarily for Rx, but also for Tx operations. + * + * NOTE: When tuning to a new channel, driver must set the + * RXON_FILTER_ASSOC_MSK to 0. This will clear station-dependent + * info within the device, including the station tables, tx retry + * rate tables, and txpower tables. Driver must build a new station + * table and txpower table before transmitting anything on the RXON + * channel. + * + * NOTE: All RXONs wipe clean the internal txpower table. Driver must + * issue a new REPLY_TX_PWR_TABLE_CMD after each REPLY_RXON (0x10), + * regardless of whether RXON_FILTER_ASSOC_MSK is set. */ struct iwl3945_rxon_cmd { u8 node_addr[6]; @@ -373,17 +418,6 @@ struct iwl3945_rxon_time_cmd { __le16 reserved; } __attribute__ ((packed)); -struct iwl3945_tx_power { - u8 tx_gain; /* gain for analog radio */ - u8 dsp_atten; /* gain for DSP */ -} __attribute__ ((packed)); - -struct iwl3945_power_per_rate { - u8 rate; /* plcp */ - struct iwl3945_tx_power tpc; - u8 reserved; -} __attribute__ ((packed)); - /* * REPLY_CHANNEL_SWITCH = 0x72 (command, has simple generic response) */ diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-commands.h b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h index bde3aa0..0813e3e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h @@ -123,7 +123,7 @@ enum { /* Bluetooth device coexistance config command */ REPLY_BT_CONFIG = 0x9b, - /* 4965 Statistics */ + /* Statistics */ REPLY_STATISTICS_CMD = 0x9c, STATISTICS_NOTIFICATION = 0x9d, @@ -147,7 +147,7 @@ enum { /****************************************************************************** * (0) * Commonly used structures and definitions: - * Command header, rate_n_flags + * Command header, rate_n_flags, txpower * *****************************************************************************/ @@ -273,6 +273,65 @@ struct iwl4965_cmd_header { #define RATE_MCS_ANT_AB_MSK 0xc000 +/** + * struct iwl4965_tx_power - txpower format used in REPLY_SCAN_CMD + * + * Scan uses only one transmitter, so only one analog/dsp gain pair is needed. + */ +struct iwl4965_tx_power { + u8 tx_gain; /* gain for analog radio */ + u8 dsp_atten; /* gain for DSP */ +} __attribute__ ((packed)); + +#define POWER_TABLE_NUM_ENTRIES 33 +#define POWER_TABLE_NUM_HT_OFDM_ENTRIES 32 +#define POWER_TABLE_CCK_ENTRY 32 + +/** + * union iwl4965_tx_power_dual_stream + * + * Host format used for REPLY_TX_PWR_TABLE_CMD, REPLY_CHANNEL_SWITCH + * Use __le32 version (struct tx_power_dual_stream) when building command. + * + * Driver provides radio gain and DSP attenuation settings to device in pairs, + * one value for each transmitter chain. The first value is for transmitter A, + * second for transmitter B. + * + * For SISO bit rates, both values in a pair should be identical. + * For MIMO rates, one value may be different from the other, + * in order to balance the Tx output between the two transmitters. + * + * See more details in doc for TXPOWER in iwl-4965-hw.h. + */ +union iwl4965_tx_power_dual_stream { + struct { + u8 radio_tx_gain[2]; + u8 dsp_predis_atten[2]; + } s; + u32 dw; +}; + +/** + * struct tx_power_dual_stream + * + * Table entries in REPLY_TX_PWR_TABLE_CMD, REPLY_CHANNEL_SWITCH + * + * Same format as iwl_tx_power_dual_stream, but __le32 + */ +struct tx_power_dual_stream { + __le32 dw; +} __attribute__ ((packed)); + +/** + * struct iwl4965_tx_power_db + * + * Entire table within REPLY_TX_PWR_TABLE_CMD, REPLY_CHANNEL_SWITCH + */ +struct iwl4965_tx_power_db { + struct tx_power_dual_stream power_tbl[POWER_TABLE_NUM_ENTRIES]; +} __attribute__ ((packed)); + + /****************************************************************************** * (0a) * Alive and Error Commands & Responses: @@ -501,8 +560,22 @@ enum { /* transfer to host non bssid beacons in associated state */ #define RXON_FILTER_BCON_AWARE_MSK __constant_cpu_to_le32(1 << 6) -/* +/** * REPLY_RXON = 0x10 (command, has simple generic response) + * + * RXON tunes the radio tuner to a service channel, and sets up a number + * of parameters that are used primarily for Rx, but also for Tx operations. + * + * NOTE: When tuning to a new channel, driver must set the + * RXON_FILTER_ASSOC_MSK to 0. This will clear station-dependent + * info within the device, including the station tables, tx retry + * rate tables, and txpower tables. Driver must build a new station + * table and txpower table before transmitting anything on the RXON + * channel. + * + * NOTE: All RXONs wipe clean the internal txpower table. Driver must + * issue a new REPLY_TX_PWR_TABLE_CMD after each REPLY_RXON (0x10), + * regardless of whether RXON_FILTER_ASSOC_MSK is set. */ struct iwl4965_rxon_cmd { u8 node_addr[6]; @@ -550,31 +623,6 @@ struct iwl4965_rxon_time_cmd { __le16 reserved; } __attribute__ ((packed)); -struct iwl4965_tx_power { - u8 tx_gain; /* gain for analog radio */ - u8 dsp_atten; /* gain for DSP */ -} __attribute__ ((packed)); - -#define POWER_TABLE_NUM_ENTRIES 33 -#define POWER_TABLE_NUM_HT_OFDM_ENTRIES 32 -#define POWER_TABLE_CCK_ENTRY 32 - -union iwl4965_tx_power_dual_stream { - struct { - u8 radio_tx_gain[2]; - u8 dsp_predis_atten[2]; - } s; - u32 dw; -}; - -struct tx_power_dual_stream { - __le32 dw; -} __attribute__ ((packed)); - -struct iwl4965_tx_power_db { - struct tx_power_dual_stream power_tbl[POWER_TABLE_NUM_ENTRIES]; -} __attribute__ ((packed)); - /* * REPLY_CHANNEL_SWITCH = 0x72 (command, has simple generic response) */ -- 1.5.3.6 ^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 30/36] iwlwifi: add comments to QOS and ADD_STA commands 2007-11-29 3:10 ` [PATCH 29/36] iwlwifi: add comments to RXON command and txpower formats Zhu Yi @ 2007-11-29 3:10 ` Zhu Yi 2007-11-29 3:10 ` [PATCH 31/36] iwlwifi: add comments to Tx commands Zhu Yi 0 siblings, 1 reply; 36+ messages in thread From: Zhu Yi @ 2007-11-29 3:10 UTC (permalink / raw) To: linville; +Cc: linux-wireless, Ben Cahill, Zhu Yi From: Ben Cahill <ben.m.cahill@intel.com> Add comments to QOS and ADD_STA commands Signed-off-by: Ben Cahill <ben.m.cahill@intel.com> Signed-off-by: Zhu Yi <yi.zhu@intel.com> --- drivers/net/wireless/iwlwifi/iwl-3945-commands.h | 97 +++++++++++++++++---- drivers/net/wireless/iwlwifi/iwl-4965-commands.h | 99 +++++++++++++++++++--- 2 files changed, 165 insertions(+), 31 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-commands.h b/drivers/net/wireless/iwlwifi/iwl-3945-commands.h index 4a8fc68..4885971 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-commands.h @@ -445,6 +445,23 @@ struct iwl3945_csa_notification { * Quality-of-Service (QOS) Commands & Responses: * *****************************************************************************/ + +/** + * struct iwl_ac_qos -- QOS timing params for REPLY_QOS_PARAM + * One for each of 4 EDCA access categories in struct iwl_qosparam_cmd + * + * @cw_min: Contention window, start value in numbers of slots. + * Should be a power-of-2, minus 1. Device's default is 0x0f. + * @cw_max: Contention window, max value in numbers of slots. + * Should be a power-of-2, minus 1. Device's default is 0x3f. + * @aifsn: Number of slots in Arbitration Interframe Space (before + * performing random backoff timing prior to Tx). Device default 1. + * @edca_txop: Length of Tx opportunity, in uSecs. Device default is 0. + * + * Device will automatically increase contention window by (2*CW) + 1 for each + * transmission retry. Device uses cw_max as a bit mask, ANDed with new CW + * value, to cap the CW value. + */ struct iwl3945_ac_qos { __le16 cw_min; __le16 cw_max; @@ -458,14 +475,14 @@ struct iwl3945_ac_qos { #define QOS_PARAM_FLG_TGN_MSK __constant_cpu_to_le32(0x02) #define QOS_PARAM_FLG_TXOP_TYPE_MSK __constant_cpu_to_le32(0x10) -/* - * TXFIFO Queue number defines - */ -/* number of Access categories (AC) (EDCA), queues 0..3 */ +/* Number of Access Categories (AC) (EDCA), queues 0..3 */ #define AC_NUM 4 /* * REPLY_QOS_PARAM = 0x13 (command, has simple generic response) + * + * This command sets up timings for each of the 4 prioritized EDCA Tx FIFOs + * 0: Background, 1: Best Effort, 2: Video, 3: Voice. */ struct iwl3945_qosparam_cmd { __le32 qos_flags; @@ -480,22 +497,21 @@ struct iwl3945_qosparam_cmd { /* * Multi station support */ + +/* Special, dedicated locations within device's station table */ #define IWL_AP_ID 0 #define IWL_MULTICAST_ID 1 #define IWL_STA_ID 2 - #define IWL3945_BROADCAST_ID 24 #define IWL3945_STATION_COUNT 25 -#define IWL4965_BROADCAST_ID 31 -#define IWL4965_STATION_COUNT 32 - #define IWL_STATION_COUNT 32 /* MAX(3945,4965)*/ #define IWL_INVALID_STATION 255 #define STA_FLG_TX_RATE_MSK __constant_cpu_to_le32(1<<2); #define STA_FLG_PWR_SAVE_MSK __constant_cpu_to_le32(1<<8); +/* Use in mode field. 1: modify existing entry, 0: add new station entry */ #define STA_CONTROL_MODIFY_MSK 0x01 /* key flags __le16*/ @@ -508,13 +524,10 @@ struct iwl3945_qosparam_cmd { #define STA_KEY_FLG_KEYID_POS 8 #define STA_KEY_FLG_INVALID __constant_cpu_to_le16(0x0800) -/* modify flags */ +/* Flags indicate whether to modify vs. don't change various station params */ #define STA_MODIFY_KEY_MASK 0x01 #define STA_MODIFY_TID_DISABLE_TX 0x02 #define STA_MODIFY_TX_RATE_MSK 0x04 -#define STA_MODIFY_ADDBA_TID_MSK 0x08 -#define STA_MODIFY_DELBA_TID_MSK 0x10 -#define BUILD_RAxTID(sta_id, tid) (((sta_id) << 4) + (tid)) /* * Antenna masks: @@ -537,6 +550,18 @@ struct iwl3945_keyinfo { u8 key[16]; /* 16-byte unicast decryption key */ } __attribute__ ((packed)); +/** + * struct sta_id_modify + * @addr[ETH_ALEN]: station's MAC address + * @sta_id: index of station in uCode's station table + * @modify_mask: STA_MODIFY_*, 1: modify, 0: don't change + * + * Driver selects unused table index when adding new station, + * or the index to a pre-existing station entry when modifying that station. + * Some indexes have special purposes (IWL_AP_ID, index 0, is for AP). + * + * modify_mask flags select which parameters to modify vs. leave alone. + */ struct sta_id_modify { u8 addr[ETH_ALEN]; __le16 reserved1; @@ -547,29 +572,67 @@ struct sta_id_modify { /* * REPLY_ADD_STA = 0x18 (command) + * + * The device contains an internal table of per-station information, + * with info on security keys, aggregation parameters, and Tx rates for + * initial Tx attempt and any retries (4965 uses REPLY_TX_LINK_QUALITY_CMD, + * 3945 uses REPLY_RATE_SCALE to set up rate tables). + * + * REPLY_ADD_STA sets up the table entry for one station, either creating + * a new entry, or modifying a pre-existing one. + * + * NOTE: RXON command (without "associated" bit set) wipes the station table + * clean. Moving into RF_KILL state does this also. Driver must set up + * new station table before transmitting anything on the RXON channel + * (except active scans or active measurements; those commands carry + * their own txpower/rate setup data). + * + * When getting started on a new channel, driver must set up the + * IWL_BROADCAST_ID entry (last entry in the table). For a client + * station in a BSS, once an AP is selected, driver sets up the AP STA + * in the IWL_AP_ID entry (1st entry in the table). BROADCAST and AP + * are all that are needed for a BSS client station. If the device is + * used as AP, or in an IBSS network, driver must set up station table + * entries for all STAs in network, starting with index IWL_STA_ID. */ struct iwl3945_addsta_cmd { - u8 mode; + u8 mode; /* 1: modify existing, 0: add new station */ u8 reserved[3]; struct sta_id_modify sta; struct iwl3945_keyinfo key; - __le32 station_flags; - __le32 station_flags_msk; + __le32 station_flags; /* STA_FLG_* */ + __le32 station_flags_msk; /* STA_FLG_* */ + + /* bit field to disable (1) or enable (0) Tx for Traffic ID (TID) + * corresponding to bit (e.g. bit 5 controls TID 5). + * Set modify_mask bit STA_MODIFY_TID_DISABLE_TX to use this field. */ __le16 tid_disable_tx; + __le16 rate_n_flags; + + /* TID for which to add block-ack support. + * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */ u8 add_immediate_ba_tid; + + /* TID for which to remove block-ack support. + * Set modify_mask bit STA_MODIFY_DELBA_TID_MSK to use this field. */ u8 remove_immediate_ba_tid; + + /* Starting Sequence Number for added block-ack support. + * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */ __le16 add_immediate_ba_ssn; } __attribute__ ((packed)); +#define ADD_STA_SUCCESS_MSK 0x1 +#define ADD_STA_NO_ROOM_IN_TABLE 0x2 +#define ADD_STA_NO_BLOCK_ACK_RESOURCE 0x4 /* * REPLY_ADD_STA = 0x18 (response) */ struct iwl3945_add_sta_resp { - u8 status; + u8 status; /* ADD_STA_* */ } __attribute__ ((packed)); -#define ADD_STA_SUCCESS_MSK 0x1 /****************************************************************************** * (4) diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-commands.h b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h index 0813e3e..44addea 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h @@ -650,6 +650,23 @@ struct iwl4965_csa_notification { * Quality-of-Service (QOS) Commands & Responses: * *****************************************************************************/ + +/** + * struct iwl_ac_qos -- QOS timing params for REPLY_QOS_PARAM + * One for each of 4 EDCA access categories in struct iwl_qosparam_cmd + * + * @cw_min: Contention window, start value in numbers of slots. + * Should be a power-of-2, minus 1. Device's default is 0x0f. + * @cw_max: Contention window, max value in numbers of slots. + * Should be a power-of-2, minus 1. Device's default is 0x3f. + * @aifsn: Number of slots in Arbitration Interframe Space (before + * performing random backoff timing prior to Tx). Device default 1. + * @edca_txop: Length of Tx opportunity, in uSecs. Device default is 0. + * + * Device will automatically increase contention window by (2*CW) + 1 for each + * transmission retry. Device uses cw_max as a bit mask, ANDed with new CW + * value, to cap the CW value. + */ struct iwl4965_ac_qos { __le16 cw_min; __le16 cw_max; @@ -663,14 +680,14 @@ struct iwl4965_ac_qos { #define QOS_PARAM_FLG_TGN_MSK __constant_cpu_to_le32(0x02) #define QOS_PARAM_FLG_TXOP_TYPE_MSK __constant_cpu_to_le32(0x10) -/* - * TXFIFO Queue number defines - */ -/* number of Access categories (AC) (EDCA), queues 0..3 */ +/* Number of Access Categories (AC) (EDCA), queues 0..3 */ #define AC_NUM 4 /* * REPLY_QOS_PARAM = 0x13 (command, has simple generic response) + * + * This command sets up timings for each of the 4 prioritized EDCA Tx FIFOs + * 0: Background, 1: Best Effort, 2: Video, 3: Voice. */ struct iwl4965_qosparam_cmd { __le32 qos_flags; @@ -685,13 +702,11 @@ struct iwl4965_qosparam_cmd { /* * Multi station support */ + +/* Special, dedicated locations within device's station table */ #define IWL_AP_ID 0 #define IWL_MULTICAST_ID 1 #define IWL_STA_ID 2 - -#define IWL3945_BROADCAST_ID 24 -#define IWL3945_STATION_COUNT 25 - #define IWL4965_BROADCAST_ID 31 #define IWL4965_STATION_COUNT 32 @@ -708,6 +723,7 @@ struct iwl4965_qosparam_cmd { #define STA_FLG_AGG_MPDU_DENSITY_POS (23) #define STA_FLG_AGG_MPDU_DENSITY_MSK __constant_cpu_to_le32(7 << 23) +/* Use in mode field. 1: modify existing entry, 0: add new station entry */ #define STA_CONTROL_MODIFY_MSK 0x01 /* key flags __le16*/ @@ -720,12 +736,15 @@ struct iwl4965_qosparam_cmd { #define STA_KEY_FLG_KEYID_POS 8 #define STA_KEY_FLG_INVALID __constant_cpu_to_le16(0x0800) -/* modify flags */ +/* Flags indicate whether to modify vs. don't change various station params */ #define STA_MODIFY_KEY_MASK 0x01 #define STA_MODIFY_TID_DISABLE_TX 0x02 #define STA_MODIFY_TX_RATE_MSK 0x04 #define STA_MODIFY_ADDBA_TID_MSK 0x08 #define STA_MODIFY_DELBA_TID_MSK 0x10 + +/* Receiver address (actually, Rx station's index into station table), + * combined with Traffic ID (QOS priority), in format used by Tx Scheduler */ #define BUILD_RAxTID(sta_id, tid) (((sta_id) << 4) + (tid)) struct iwl4965_keyinfo { @@ -737,6 +756,18 @@ struct iwl4965_keyinfo { u8 key[16]; /* 16-byte unicast decryption key */ } __attribute__ ((packed)); +/** + * struct sta_id_modify + * @addr[ETH_ALEN]: station's MAC address + * @sta_id: index of station in uCode's station table + * @modify_mask: STA_MODIFY_*, 1: modify, 0: don't change + * + * Driver selects unused table index when adding new station, + * or the index to a pre-existing station entry when modifying that station. + * Some indexes have special purposes (IWL_AP_ID, index 0, is for AP). + * + * modify_mask flags select which parameters to modify vs. leave alone. + */ struct sta_id_modify { u8 addr[ETH_ALEN]; __le16 reserved1; @@ -747,30 +778,70 @@ struct sta_id_modify { /* * REPLY_ADD_STA = 0x18 (command) + * + * The device contains an internal table of per-station information, + * with info on security keys, aggregation parameters, and Tx rates for + * initial Tx attempt and any retries (4965 uses REPLY_TX_LINK_QUALITY_CMD, + * 3945 uses REPLY_RATE_SCALE to set up rate tables). + * + * REPLY_ADD_STA sets up the table entry for one station, either creating + * a new entry, or modifying a pre-existing one. + * + * NOTE: RXON command (without "associated" bit set) wipes the station table + * clean. Moving into RF_KILL state does this also. Driver must set up + * new station table before transmitting anything on the RXON channel + * (except active scans or active measurements; those commands carry + * their own txpower/rate setup data). + * + * When getting started on a new channel, driver must set up the + * IWL_BROADCAST_ID entry (last entry in the table). For a client + * station in a BSS, once an AP is selected, driver sets up the AP STA + * in the IWL_AP_ID entry (1st entry in the table). BROADCAST and AP + * are all that are needed for a BSS client station. If the device is + * used as AP, or in an IBSS network, driver must set up station table + * entries for all STAs in network, starting with index IWL_STA_ID. */ struct iwl4965_addsta_cmd { - u8 mode; + u8 mode; /* 1: modify existing, 0: add new station */ u8 reserved[3]; struct sta_id_modify sta; struct iwl4965_keyinfo key; - __le32 station_flags; - __le32 station_flags_msk; + __le32 station_flags; /* STA_FLG_* */ + __le32 station_flags_msk; /* STA_FLG_* */ + + /* bit field to disable (1) or enable (0) Tx for Traffic ID (TID) + * corresponding to bit (e.g. bit 5 controls TID 5). + * Set modify_mask bit STA_MODIFY_TID_DISABLE_TX to use this field. */ __le16 tid_disable_tx; + __le16 reserved1; + + /* TID for which to add block-ack support. + * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */ u8 add_immediate_ba_tid; + + /* TID for which to remove block-ack support. + * Set modify_mask bit STA_MODIFY_DELBA_TID_MSK to use this field. */ u8 remove_immediate_ba_tid; + + /* Starting Sequence Number for added block-ack support. + * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */ __le16 add_immediate_ba_ssn; + __le32 reserved2; } __attribute__ ((packed)); +#define ADD_STA_SUCCESS_MSK 0x1 +#define ADD_STA_NO_ROOM_IN_TABLE 0x2 +#define ADD_STA_NO_BLOCK_ACK_RESOURCE 0x4 +#define ADD_STA_MODIFY_NON_EXIST_STA 0x8 /* * REPLY_ADD_STA = 0x18 (response) */ struct iwl4965_add_sta_resp { - u8 status; + u8 status; /* ADD_STA_* */ } __attribute__ ((packed)); -#define ADD_STA_SUCCESS_MSK 0x1 /****************************************************************************** * (4) -- 1.5.3.6 ^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 31/36] iwlwifi: add comments to Tx commands 2007-11-29 3:10 ` [PATCH 30/36] iwlwifi: add comments to QOS and ADD_STA commands Zhu Yi @ 2007-11-29 3:10 ` Zhu Yi 2007-11-29 3:10 ` [PATCH 32/36] iwlwifi: document 4965 rate scaling Zhu Yi 0 siblings, 1 reply; 36+ messages in thread From: Zhu Yi @ 2007-11-29 3:10 UTC (permalink / raw) To: linville; +Cc: linux-wireless, Ben Cahill, Zhu Yi From: Ben Cahill <ben.m.cahill@intel.com> Add comments to Tx commands Clean up unused definitions in iwl-3945-commands.h Signed-off-by: Ben Cahill <ben.m.cahill@intel.com> Signed-off-by: Zhu Yi <yi.zhu@intel.com> --- drivers/net/wireless/iwlwifi/iwl-3945-commands.h | 161 ++++++++++-------- drivers/net/wireless/iwlwifi/iwl-4965-commands.h | 201 +++++++++++++++++++--- 2 files changed, 267 insertions(+), 95 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-commands.h b/drivers/net/wireless/iwlwifi/iwl-3945-commands.h index 4885971..3cac2c8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-commands.h @@ -743,36 +743,86 @@ struct iwl4965_rx_mpdu_res_start { * (5) * Tx Commands & Responses: * + * Driver must place each REPLY_TX command into one of the prioritized Tx + * queues in host DRAM, shared between driver and device. When the device's + * Tx scheduler and uCode are preparing to transmit, the device pulls the + * Tx command over the PCI bus via one of the device's Tx DMA channels, + * to fill an internal FIFO from which data will be transmitted. + * + * uCode handles all timing and protocol related to control frames + * (RTS/CTS/ACK), based on flags in the Tx command. + * + * uCode handles retrying Tx when an ACK is expected but not received. + * This includes trying lower data rates than the one requested in the Tx + * command, as set up by the REPLY_RATE_SCALE (for 3945) or + * REPLY_TX_LINK_QUALITY_CMD (4965). + * + * Driver sets up transmit power for various rates via REPLY_TX_PWR_TABLE_CMD. + * This command must be executed after every RXON command, before Tx can occur. *****************************************************************************/ -/* Tx flags */ +/* REPLY_TX Tx flags field */ + +/* 1: Use Request-To-Send protocol before this frame. + * Mutually exclusive vs. TX_CMD_FLG_CTS_MSK. */ #define TX_CMD_FLG_RTS_MSK __constant_cpu_to_le32(1 << 1) + +/* 1: Transmit Clear-To-Send to self before this frame. + * Driver should set this for AUTH/DEAUTH/ASSOC-REQ/REASSOC mgmnt frames. + * Mutually exclusive vs. TX_CMD_FLG_RTS_MSK. */ #define TX_CMD_FLG_CTS_MSK __constant_cpu_to_le32(1 << 2) + +/* 1: Expect ACK from receiving station + * 0: Don't expect ACK (MAC header's duration field s/b 0) + * Set this for unicast frames, but not broadcast/multicast. */ #define TX_CMD_FLG_ACK_MSK __constant_cpu_to_le32(1 << 3) + +/* 1: Use rate scale table (see REPLY_TX_LINK_QUALITY_CMD). + * Tx command's initial_rate_index indicates first rate to try; + * uCode walks through table for additional Tx attempts. + * 0: Use Tx rate/MCS from Tx command's rate_n_flags field. + * This rate will be used for all Tx attempts; it will not be scaled. */ #define TX_CMD_FLG_STA_RATE_MSK __constant_cpu_to_le32(1 << 4) + +/* 1: Expect immediate block-ack. + * Set when Txing a block-ack request frame. Also set TX_CMD_FLG_ACK_MSK. */ #define TX_CMD_FLG_IMM_BA_RSP_MASK __constant_cpu_to_le32(1 << 6) + +/* 1: Frame requires full Tx-Op protection. + * Set this if either RTS or CTS Tx Flag gets set. */ #define TX_CMD_FLG_FULL_TXOP_PROT_MSK __constant_cpu_to_le32(1 << 7) + +/* Tx antenna selection field; used only for 3945, reserved (0) for 4965. + * Set field to "0" to allow 3945 uCode to select antenna (normal usage). */ #define TX_CMD_FLG_ANT_SEL_MSK __constant_cpu_to_le32(0xf00) #define TX_CMD_FLG_ANT_A_MSK __constant_cpu_to_le32(1 << 8) #define TX_CMD_FLG_ANT_B_MSK __constant_cpu_to_le32(1 << 9) -/* ucode ignores BT priority for this frame */ +/* 1: Ignore Bluetooth priority for this frame. + * 0: Delay Tx until Bluetooth device is done (normal usage). */ #define TX_CMD_FLG_BT_DIS_MSK __constant_cpu_to_le32(1 << 12) -/* ucode overrides sequence control */ +/* 1: uCode overrides sequence control field in MAC header. + * 0: Driver provides sequence control field in MAC header. + * Set this for management frames, non-QOS data frames, non-unicast frames, + * and also in Tx command embedded in REPLY_SCAN_CMD for active scans. */ #define TX_CMD_FLG_SEQ_CTL_MSK __constant_cpu_to_le32(1 << 13) -/* signal that this frame is non-last MPDU */ +/* 1: This frame is non-last MPDU; more fragments are coming. + * 0: Last fragment, or not using fragmentation. */ #define TX_CMD_FLG_MORE_FRAG_MSK __constant_cpu_to_le32(1 << 14) -/* calculate TSF in outgoing frame */ +/* 1: uCode calculates and inserts Timestamp Function (TSF) in outgoing frame. + * 0: No TSF required in outgoing frame. + * Set this for transmitting beacons and probe responses. */ #define TX_CMD_FLG_TSF_MSK __constant_cpu_to_le32(1 << 16) -/* activate TX calibration. */ -#define TX_CMD_FLG_CALIB_MSK __constant_cpu_to_le32(1 << 17) - -/* signals that 2 bytes pad was inserted - after the MAC header */ +/* 1: Driver inserted 2 bytes pad after the MAC header, for (required) dword + * alignment of frame's payload data field. + * 0: No pad + * Set this for MAC headers with 26 or 30 bytes, i.e. those with QOS or ADDR4 + * field (but not both). Driver must align frame data (i.e. data following + * MAC header) to DWORD boundary. */ #define TX_CMD_FLG_MH_PAD_MSK __constant_cpu_to_le32(1 << 20) /* HCCA-AP - disable duration overwriting. */ @@ -789,23 +839,33 @@ struct iwl4965_rx_mpdu_res_start { #define TX_CMD_SEC_KEY128 0x08 /* - * TX command Frame life time - */ - -struct iwl3945_dram_scratch { - u8 try_cnt; - u8 bt_kill_cnt; - __le16 reserved; -} __attribute__ ((packed)); - -/* * REPLY_TX = 0x1c (command) */ struct iwl3945_tx_cmd { + /* + * MPDU byte count: + * MAC header (24/26/30/32 bytes) + 2 bytes pad if 26/30 header size, + * + 8 byte IV for CCM or TKIP (not used for WEP) + * + Data payload + * + 8-byte MIC (not used for CCM/WEP) + * NOTE: Does not include Tx command bytes, post-MAC pad bytes, + * MIC (CCM) 8 bytes, ICV (WEP/TKIP/CKIP) 4 bytes, CRC 4 bytes.i + * Range: 14-2342 bytes. + */ __le16 len; + + /* + * MPDU or MSDU byte count for next frame. + * Used for fragmentation and bursting, but not 11n aggregation. + * Same as "len", but for next frame. Set to 0 if not applicable. + */ __le16 next_frame_len; - __le32 tx_flags; + + __le32 tx_flags; /* TX_CMD_FLG_* */ + u8 rate; + + /* Index of recipient station in uCode's station table */ u8 sta_id; u8 tid_tspec; u8 sec_ctl; @@ -827,7 +887,17 @@ struct iwl3945_tx_cmd { __le16 pm_frame_timeout; __le16 attempt_duration; } timeout; + + /* + * Duration of EDCA burst Tx Opportunity, in 32-usec units. + * Set this if txop time is not specified by HCCA protocol (e.g. by AP). + */ __le16 driver_txop; + + /* + * MAC header goes here, followed by 2 bytes padding if MAC header + * length is 26 or 30 bytes, followed by payload data + */ u8 payload[0]; struct ieee80211_hdr hdr[0]; } __attribute__ ((packed)); @@ -899,37 +969,6 @@ enum { TX_ABORT_REQUIRED_MSK = 0x80000000, /* bits 31:31 */ }; -/* ******************************* - * TX aggregation state - ******************************* */ - -enum { - AGG_TX_STATE_TRANSMITTED = 0x00, - AGG_TX_STATE_UNDERRUN_MSK = 0x01, - AGG_TX_STATE_BT_PRIO_MSK = 0x02, - AGG_TX_STATE_FEW_BYTES_MSK = 0x04, - AGG_TX_STATE_ABORT_MSK = 0x08, - AGG_TX_STATE_LAST_SENT_TTL_MSK = 0x10, - AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK = 0x20, - AGG_TX_STATE_LAST_SENT_BT_KILL_MSK = 0x40, - AGG_TX_STATE_SCD_QUERY_MSK = 0x80, - AGG_TX_STATE_TEST_BAD_CRC32_MSK = 0x100, - AGG_TX_STATE_RESPONSE_MSK = 0x1ff, - AGG_TX_STATE_DUMP_TX_MSK = 0x200, - AGG_TX_STATE_DELAY_TX_MSK = 0x400 -}; - -#define AGG_TX_STATE_LAST_SENT_MSK \ -(AGG_TX_STATE_LAST_SENT_TTL_MSK | \ - AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK | \ - AGG_TX_STATE_LAST_SENT_BT_KILL_MSK) - -#define AGG_TX_STATE_TRY_CNT_POS 12 -#define AGG_TX_STATE_TRY_CNT_MSK 0xf000 - -#define AGG_TX_STATE_SEQ_NUM_POS 16 -#define AGG_TX_STATE_SEQ_NUM_MSK 0xffff0000 - /* * REPLY_TX = 0x1c (response) */ @@ -939,23 +978,7 @@ struct iwl3945_tx_resp { u8 bt_kill_count; u8 rate; __le32 wireless_media_time; - __le32 status; /* TX status (for aggregation status of 1st frame) */ -} __attribute__ ((packed)); - -/* - * REPLY_COMPRESSED_BA = 0xc5 (response only, not a command) - */ -struct iwl3945_compressed_ba_resp { - __le32 sta_addr_lo32; - __le16 sta_addr_hi16; - __le16 reserved; - u8 sta_id; - u8 tid; - __le16 ba_seq_ctl; - __le32 ba_bitmap0; - __le32 ba_bitmap1; - __le16 scd_flow; - __le16 scd_ssn; + __le32 status; /* TX status */ } __attribute__ ((packed)); /* diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-commands.h b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h index 44addea..cbe91db 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h @@ -937,8 +937,8 @@ struct iwl4965_rx_phy_res { __le16 channel; /* channel number */ __le16 non_cfg_phy[RX_RES_PHY_CNT]; /* upto 14 phy entries */ __le32 reserved2; - __le32 rate_n_flags; - __le16 byte_count; /* frame's byte-count */ + __le32 rate_n_flags; /* RATE_MCS_* */ + __le16 byte_count; /* frame's byte-count */ __le16 reserved3; } __attribute__ ((packed)); @@ -952,41 +952,96 @@ struct iwl4965_rx_mpdu_res_start { * (5) * Tx Commands & Responses: * + * Driver must place each REPLY_TX command into one of the prioritized Tx + * queues in host DRAM, shared between driver and device (see comments for + * SCD registers and Tx/Rx Queues). When the device's Tx scheduler and uCode + * are preparing to transmit, the device pulls the Tx command over the PCI + * bus via one of the device's Tx DMA channels, to fill an internal FIFO + * from which data will be transmitted. + * + * uCode handles all timing and protocol related to control frames + * (RTS/CTS/ACK), based on flags in the Tx command. uCode and Tx scheduler + * handle reception of block-acks; uCode updates the host driver via + * REPLY_COMPRESSED_BA (4965). + * + * uCode handles retrying Tx when an ACK is expected but not received. + * This includes trying lower data rates than the one requested in the Tx + * command, as set up by the REPLY_RATE_SCALE (for 3945) or + * REPLY_TX_LINK_QUALITY_CMD (4965). + * + * Driver sets up transmit power for various rates via REPLY_TX_PWR_TABLE_CMD. + * This command must be executed after every RXON command, before Tx can occur. *****************************************************************************/ -/* Tx flags */ +/* REPLY_TX Tx flags field */ + +/* 1: Use Request-To-Send protocol before this frame. + * Mutually exclusive vs. TX_CMD_FLG_CTS_MSK. */ #define TX_CMD_FLG_RTS_MSK __constant_cpu_to_le32(1 << 1) + +/* 1: Transmit Clear-To-Send to self before this frame. + * Driver should set this for AUTH/DEAUTH/ASSOC-REQ/REASSOC mgmnt frames. + * Mutually exclusive vs. TX_CMD_FLG_RTS_MSK. */ #define TX_CMD_FLG_CTS_MSK __constant_cpu_to_le32(1 << 2) + +/* 1: Expect ACK from receiving station + * 0: Don't expect ACK (MAC header's duration field s/b 0) + * Set this for unicast frames, but not broadcast/multicast. */ #define TX_CMD_FLG_ACK_MSK __constant_cpu_to_le32(1 << 3) + +/* For 4965: + * 1: Use rate scale table (see REPLY_TX_LINK_QUALITY_CMD). + * Tx command's initial_rate_index indicates first rate to try; + * uCode walks through table for additional Tx attempts. + * 0: Use Tx rate/MCS from Tx command's rate_n_flags field. + * This rate will be used for all Tx attempts; it will not be scaled. */ #define TX_CMD_FLG_STA_RATE_MSK __constant_cpu_to_le32(1 << 4) + +/* 1: Expect immediate block-ack. + * Set when Txing a block-ack request frame. Also set TX_CMD_FLG_ACK_MSK. */ #define TX_CMD_FLG_IMM_BA_RSP_MASK __constant_cpu_to_le32(1 << 6) + +/* 1: Frame requires full Tx-Op protection. + * Set this if either RTS or CTS Tx Flag gets set. */ #define TX_CMD_FLG_FULL_TXOP_PROT_MSK __constant_cpu_to_le32(1 << 7) + +/* Tx antenna selection field; used only for 3945, reserved (0) for 4965. + * Set field to "0" to allow 3945 uCode to select antenna (normal usage). */ #define TX_CMD_FLG_ANT_SEL_MSK __constant_cpu_to_le32(0xf00) #define TX_CMD_FLG_ANT_A_MSK __constant_cpu_to_le32(1 << 8) #define TX_CMD_FLG_ANT_B_MSK __constant_cpu_to_le32(1 << 9) -/* ucode ignores BT priority for this frame */ +/* 1: Ignore Bluetooth priority for this frame. + * 0: Delay Tx until Bluetooth device is done (normal usage). */ #define TX_CMD_FLG_BT_DIS_MSK __constant_cpu_to_le32(1 << 12) -/* ucode overrides sequence control */ +/* 1: uCode overrides sequence control field in MAC header. + * 0: Driver provides sequence control field in MAC header. + * Set this for management frames, non-QOS data frames, non-unicast frames, + * and also in Tx command embedded in REPLY_SCAN_CMD for active scans. */ #define TX_CMD_FLG_SEQ_CTL_MSK __constant_cpu_to_le32(1 << 13) -/* signal that this frame is non-last MPDU */ +/* 1: This frame is non-last MPDU; more fragments are coming. + * 0: Last fragment, or not using fragmentation. */ #define TX_CMD_FLG_MORE_FRAG_MSK __constant_cpu_to_le32(1 << 14) -/* calculate TSF in outgoing frame */ +/* 1: uCode calculates and inserts Timestamp Function (TSF) in outgoing frame. + * 0: No TSF required in outgoing frame. + * Set this for transmitting beacons and probe responses. */ #define TX_CMD_FLG_TSF_MSK __constant_cpu_to_le32(1 << 16) -/* activate TX calibration. */ -#define TX_CMD_FLG_CALIB_MSK __constant_cpu_to_le32(1 << 17) - -/* signals that 2 bytes pad was inserted - after the MAC header */ +/* 1: Driver inserted 2 bytes pad after the MAC header, for (required) dword + * alignment of frame's payload data field. + * 0: No pad + * Set this for MAC headers with 26 or 30 bytes, i.e. those with QOS or ADDR4 + * field (but not both). Driver must align frame data (i.e. data following + * MAC header) to DWORD boundary. */ #define TX_CMD_FLG_MH_PAD_MSK __constant_cpu_to_le32(1 << 20) /* HCCA-AP - disable duration overwriting. */ #define TX_CMD_FLG_DUR_MSK __constant_cpu_to_le32(1 << 25) + /* * TX command security control */ @@ -998,12 +1053,13 @@ struct iwl4965_rx_mpdu_res_start { #define TX_CMD_SEC_KEY128 0x08 /* - * TX command Frame life time + * 4965 uCode updates these Tx attempt count values in host DRAM. + * Used for managing Tx retries when expecting block-acks. + * Driver should set these fields to 0. */ - struct iwl4965_dram_scratch { - u8 try_cnt; - u8 bt_kill_cnt; + u8 try_cnt; /* Tx attempts */ + u8 bt_kill_cnt; /* Tx attempts blocked by Bluetooth device */ __le16 reserved; } __attribute__ ((packed)); @@ -1011,13 +1067,47 @@ struct iwl4965_dram_scratch { * REPLY_TX = 0x1c (command) */ struct iwl4965_tx_cmd { + /* + * MPDU byte count: + * MAC header (24/26/30/32 bytes) + 2 bytes pad if 26/30 header size, + * + 8 byte IV for CCM or TKIP (not used for WEP) + * + Data payload + * + 8-byte MIC (not used for CCM/WEP) + * NOTE: Does not include Tx command bytes, post-MAC pad bytes, + * MIC (CCM) 8 bytes, ICV (WEP/TKIP/CKIP) 4 bytes, CRC 4 bytes.i + * Range: 14-2342 bytes. + */ __le16 len; + + /* + * MPDU or MSDU byte count for next frame. + * Used for fragmentation and bursting, but not 11n aggregation. + * Same as "len", but for next frame. Set to 0 if not applicable. + */ __le16 next_frame_len; - __le32 tx_flags; + + __le32 tx_flags; /* TX_CMD_FLG_* */ + + /* 4965's uCode may modify this field of the Tx command (in host DRAM!). + * Driver must also set dram_lsb_ptr and dram_msb_ptr in this cmd. */ struct iwl4965_dram_scratch scratch; - __le32 rate_n_flags; + + /* Rate for *all* Tx attempts, if TX_CMD_FLG_STA_RATE_MSK is cleared. */ + __le32 rate_n_flags; /* RATE_MCS_* */ + + /* Index of destination station in uCode's station table */ u8 sta_id; - u8 sec_ctl; + + /* Type of security encryption: CCM or TKIP */ + u8 sec_ctl; /* TX_CMD_SEC_* */ + + /* + * Index into rate table (see REPLY_TX_LINK_QUALITY_CMD) for initial + * Tx attempt, if TX_CMD_FLG_STA_RATE_MSK is set. Normally "0" for + * data frames, this field may be used to selectively reduce initial + * rate (via non-0 value) for special frames (e.g. management), while + * still supporting rate scaling for all frames. + */ u8 initial_rate_index; u8 reserved; u8 key[16]; @@ -1027,8 +1117,12 @@ struct iwl4965_tx_cmd { __le32 life_time; __le32 attempt; } stop_time; + + /* Host DRAM physical address pointer to "scratch" in this command. + * Must be dword aligned. "0" in dram_lsb_ptr disables usage. */ __le32 dram_lsb_ptr; u8 dram_msb_ptr; + u8 rts_retry_limit; /*byte 50 */ u8 data_retry_limit; /*byte 51 */ u8 tid_tspec; @@ -1036,7 +1130,17 @@ struct iwl4965_tx_cmd { __le16 pm_frame_timeout; __le16 attempt_duration; } timeout; + + /* + * Duration of EDCA burst Tx Opportunity, in 32-usec units. + * Set this if txop time is not specified by HCCA protocol (e.g. by AP). + */ __le16 driver_txop; + + /* + * MAC header goes here, followed by 2 bytes padding if MAC header + * length is 26 or 30 bytes, followed by payload data + */ u8 payload[0]; struct ieee80211_hdr hdr[0]; } __attribute__ ((packed)); @@ -1109,7 +1213,7 @@ enum { }; /* ******************************* - * TX aggregation state + * TX aggregation status ******************************* */ enum { @@ -1133,35 +1237,80 @@ enum { AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK | \ AGG_TX_STATE_LAST_SENT_BT_KILL_MSK) +/* # tx attempts for first frame in aggregation */ #define AGG_TX_STATE_TRY_CNT_POS 12 #define AGG_TX_STATE_TRY_CNT_MSK 0xf000 +/* Command ID and sequence number of Tx command for this frame */ #define AGG_TX_STATE_SEQ_NUM_POS 16 #define AGG_TX_STATE_SEQ_NUM_MSK 0xffff0000 /* * REPLY_TX = 0x1c (response) + * + * This response may be in one of two slightly different formats, indicated + * by the frame_count field: + * + * 1) No aggregation (frame_count == 1). This reports Tx results for + * a single frame. Multiple attempts, at various bit rates, may have + * been made for this frame. + * + * 2) Aggregation (frame_count > 1). This reports Tx results for + * 2 or more frames that used block-acknowledge. All frames were + * transmitted at same rate. Rate scaling may have been used if first + * frame in this new agg block failed in previous agg block(s). + * + * Note that, for aggregation, ACK (block-ack) status is not delivered here; + * block-ack has not been received by the time the 4965 records this status. + * This status relates to reasons the tx might have been blocked or aborted + * within the sending station (this 4965), rather than whether it was + * received successfully by the destination station. */ struct iwl4965_tx_resp { u8 frame_count; /* 1 no aggregation, >1 aggregation */ - u8 bt_kill_count; - u8 failure_rts; - u8 failure_frame; - __le32 rate_n_flags; - __le16 wireless_media_time; + u8 bt_kill_count; /* # blocked by bluetooth (unused for agg) */ + u8 failure_rts; /* # failures due to unsuccessful RTS */ + u8 failure_frame; /* # failures due to no ACK (unused for agg) */ + + /* For non-agg: Rate at which frame was successful. + * For agg: Rate at which all frames were transmitted. */ + __le32 rate_n_flags; /* RATE_MCS_* */ + + /* For non-agg: RTS + CTS + frame tx attempts time + ACK. + * For agg: RTS + CTS + aggregation tx time + block-ack time. */ + __le16 wireless_media_time; /* uSecs */ + __le16 reserved; - __le32 pa_power1; + __le32 pa_power1; /* RF power amplifier measurement (not used) */ __le32 pa_power2; + + /* + * For non-agg: frame status TX_STATUS_* + * For agg: status of 1st frame, AGG_TX_STATE_*; other frame status + * fields follow this one, up to frame_count. + * Bit fields: + * 11- 0: AGG_TX_STATE_* status code + * 15-12: Retry count for 1st frame in aggregation (retries + * occur if tx failed for this frame when it was a + * member of a previous aggregation block). If rate + * scaling is used, retry count indicates the rate + * table entry used for all frames in the new agg. + * 31-16: Sequence # for this frame's Tx cmd (not SSN!) + */ __le32 status; /* TX status (for aggregation status of 1st frame) */ } __attribute__ ((packed)); /* * REPLY_COMPRESSED_BA = 0xc5 (response only, not a command) + * + * Reports Block-Acknowledge from recipient station */ struct iwl4965_compressed_ba_resp { __le32 sta_addr_lo32; __le16 sta_addr_hi16; __le16 reserved; + + /* Index of recipient (BA-sending) station in uCode's station table */ u8 sta_id; u8 tid; __le16 ba_seq_ctl; -- 1.5.3.6 ^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 32/36] iwlwifi: document 4965 rate scaling 2007-11-29 3:10 ` [PATCH 31/36] iwlwifi: add comments to Tx commands Zhu Yi @ 2007-11-29 3:10 ` Zhu Yi 2007-11-29 3:10 ` [PATCH 33/36] iwlwifi: enhance WPA authenication stability Zhu Yi 0 siblings, 1 reply; 36+ messages in thread From: Zhu Yi @ 2007-11-29 3:10 UTC (permalink / raw) To: linville; +Cc: linux-wireless, Ben Cahill, Zhu Yi From: Ben Cahill <ben.m.cahill@intel.com> Document 4965 rate scaling Signed-off-by: Ben Cahill <ben.m.cahill@intel.com> Signed-off-by: Zhu Yi <yi.zhu@intel.com> --- drivers/net/wireless/iwlwifi/iwl-4965-commands.h | 251 +++++++++++++++++++++- 1 files changed, 247 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-commands.h b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h index cbe91db..7988c75 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h @@ -1322,6 +1322,8 @@ struct iwl4965_compressed_ba_resp { /* * REPLY_TX_PWR_TABLE_CMD = 0x97 (command, has simple generic response) + * + * See details under "TXPOWER" in iwl-4965-hw.h. */ struct iwl4965_txpowertable_cmd { u8 band; /* 0: 5 GHz, 1: 2.4 GHz */ @@ -1333,39 +1335,280 @@ struct iwl4965_txpowertable_cmd { /*RS_NEW_API: only TLC_RTS remains and moved to bit 0 */ #define LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK (1<<0) +/* # of EDCA prioritized tx fifos */ #define LINK_QUAL_AC_NUM AC_NUM + +/* # entries in rate scale table to support Tx retries */ #define LINK_QUAL_MAX_RETRY_NUM 16 +/* Tx antenna selection values */ #define LINK_QUAL_ANT_A_MSK (1<<0) #define LINK_QUAL_ANT_B_MSK (1<<1) #define LINK_QUAL_ANT_MSK (LINK_QUAL_ANT_A_MSK|LINK_QUAL_ANT_B_MSK) + +/** + * struct iwl4965_link_qual_general_params + * + * Used in REPLY_TX_LINK_QUALITY_CMD + */ struct iwl4965_link_qual_general_params { u8 flags; + + /* No entries at or above this (driver chosen) index contain MIMO */ u8 mimo_delimiter; - u8 single_stream_ant_msk; - u8 dual_stream_ant_msk; + + /* Best single antenna to use for single stream (legacy, SISO). */ + u8 single_stream_ant_msk; /* LINK_QUAL_ANT_* */ + + /* Best antennas to use for MIMO (unused for 4965, assumes both). */ + u8 dual_stream_ant_msk; /* LINK_QUAL_ANT_* */ + + /* + * If driver needs to use different initial rates for different + * EDCA QOS access categories (as implemented by tx fifos 0-3), + * this table will set that up, by indicating the indexes in the + * rs_table[LINK_QUAL_MAX_RETRY_NUM] rate table at which to start. + * Otherwise, driver should set all entries to 0. + * + * Entry usage: + * 0 = Background, 1 = Best Effort (normal), 2 = Video, 3 = Voice + * TX FIFOs above 3 use same value (typically 0) as TX FIFO 3. + */ u8 start_rate_index[LINK_QUAL_AC_NUM]; } __attribute__ ((packed)); +/** + * struct iwl4965_link_qual_agg_params + * + * Used in REPLY_TX_LINK_QUALITY_CMD + */ struct iwl4965_link_qual_agg_params { + + /* Maximum number of uSec in aggregation. + * Driver should set this to 4000 (4 milliseconds). */ __le16 agg_time_limit; + + /* + * Number of Tx retries allowed for a frame, before that frame will + * no longer be considered for the start of an aggregation sequence + * (scheduler will then try to tx it as single frame). + * Driver should set this to 3. + */ u8 agg_dis_start_th; + + /* + * Maximum number of frames in aggregation. + * 0 = no limit (default). 1 = no aggregation. + * Other values = max # frames in aggregation. + */ u8 agg_frame_cnt_limit; + __le32 reserved; } __attribute__ ((packed)); /* * REPLY_TX_LINK_QUALITY_CMD = 0x4e (command, has simple generic response) + * + * For 4965 only; 3945 uses REPLY_RATE_SCALE. + * + * Each station in the 4965's internal station table has its own table of 16 + * Tx rates and modulation modes (e.g. legacy/SISO/MIMO) for retrying Tx when + * an ACK is not received. This command replaces the entire table for + * one station. + * + * NOTE: Station must already be in 4965's station table. Use REPLY_ADD_STA. + * + * The rate scaling procedures described below work well. Of course, other + * procedures are possible, and may work better for particular environments. + * + * + * FILLING THE RATE TABLE + * + * Given a particular initial rate and mode, as determined by the rate + * scaling algorithm described below, the Linux driver uses the following + * formula to fill the rs_table[LINK_QUAL_MAX_RETRY_NUM] rate table in the + * Link Quality command: + * + * + * 1) If using High-throughput (HT) (SISO or MIMO) initial rate: + * a) Use this same initial rate for first 3 entries. + * b) Find next lower available rate using same mode (SISO or MIMO), + * use for next 3 entries. If no lower rate available, switch to + * legacy mode (no FAT channel, no MIMO, no short guard interval). + * c) If using MIMO, set command's mimo_delimiter to number of entries + * using MIMO (3 or 6). + * d) After trying 2 HT rates, switch to legacy mode (no FAT channel, + * no MIMO, no short guard interval), at the next lower bit rate + * (e.g. if second HT bit rate was 54, try 48 legacy), and follow + * legacy procedure for remaining table entries. + * + * 2) If using legacy initial rate: + * a) Use the initial rate for only one entry. + * b) For each following entry, reduce the rate to next lower available + * rate, until reaching the lowest available rate. + * c) When reducing rate, also switch antenna selection. + * d) Once lowest available rate is reached, repeat this rate until + * rate table is filled (16 entries), switching antenna each entry. + * + * + * ACCUMULATING HISTORY + * + * The rate scaling algorithm for 4965, as implemented in Linux driver, uses + * two sets of frame Tx success history: One for the current/active modulation + * mode, and one for a speculative/search mode that is being attempted. If the + * speculative mode turns out to be more effective (i.e. actual transfer + * rate is better), then the driver continues to use the speculative mode + * as the new current active mode. + * + * Each history set contains, separately for each possible rate, data for a + * sliding window of the 62 most recent tx attempts at that rate. The data + * includes a shifting bitmap of success(1)/failure(0), and sums of successful + * and attempted frames, from which the driver can additionally calculate a + * success ratio (success / attempted) and number of failures + * (attempted - success), and control the size of the window (attempted). + * The driver uses the bit map to remove successes from the success sum, as + * the oldest tx attempts fall out of the window. + * + * When the 4965 makes multiple tx attempts for a given frame, each attempt + * might be at a different rate, and have different modulation characteristics + * (e.g. antenna, fat channel, short guard interval), as set up in the rate + * scaling table in the Link Quality command. The driver must determine + * which rate table entry was used for each tx attempt, to determine which + * rate-specific history to update, and record only those attempts that + * match the modulation characteristics of the history set. + * + * When using block-ack (aggregation), all frames are transmitted at the same + * rate, since there is no per-attempt acknowledgement from the destination + * station. The Tx response struct iwl_tx_resp indicates the Tx rate in + * rate_n_flags field. After receiving a block-ack, the driver can update + * history for the entire block all at once. + * + * + * FINDING BEST STARTING RATE: + * + * When working with a selected initial modulation mode (see below), the + * driver attempts to find a best initial rate. The initial rate is the + * first entry in the Link Quality command's rate table. + * + * 1) Calculate actual throughput (success ratio * expected throughput, see + * table below) for current initial rate. Do this only if enough frames + * have been attempted to make the value meaningful: at least 6 failed + * tx attempts, or at least 8 successes. If not enough, don't try rate + * scaling yet. + * + * 2) Find available rates adjacent to current initial rate. Available means: + * a) supported by hardware && + * b) supported by association && + * c) within any constraints selected by user + * + * 3) Gather measured throughputs for adjacent rates. These might not have + * enough history to calculate a throughput. That's okay, we might try + * using one of them anyway! + * + * 4) Try decreasing rate if, for current rate: + * a) success ratio is < 15% || + * b) lower adjacent rate has better measured throughput || + * c) higher adjacent rate has worse throughput, and lower is unmeasured + * + * As a sanity check, if decrease was determined above, leave rate + * unchanged if: + * a) lower rate unavailable + * b) success ratio at current rate > 85% (very good) + * c) current measured throughput is better than expected throughput + * of lower rate (under perfect 100% tx conditions, see table below) + * + * 5) Try increasing rate if, for current rate: + * a) success ratio is < 15% || + * b) both adjacent rates' throughputs are unmeasured (try it!) || + * b) higher adjacent rate has better measured throughput || + * c) lower adjacent rate has worse throughput, and higher is unmeasured + * + * As a sanity check, if increase was determined above, leave rate + * unchanged if: + * a) success ratio at current rate < 70%. This is not particularly + * good performance; higher rate is sure to have poorer success. + * + * 6) Re-evaluate the rate after each tx frame. If working with block- + * acknowledge, history and statistics may be calculated for the entire + * block (including prior history that fits within the history windows), + * before re-evaluation. + * + * FINDING BEST STARTING MODULATION MODE: + * + * After working with a modulation mode for a "while" (and doing rate scaling), + * the driver searches for a new initial mode in an attempt to improve + * throughput. The "while" is measured by numbers of attempted frames: + * + * For legacy mode, search for new mode after: + * 480 successful frames, or 160 failed frames + * For high-throughput modes (SISO or MIMO), search for new mode after: + * 4500 successful frames, or 400 failed frames + * + * Mode switch possibilities are (3 for each mode): + * + * For legacy: + * Change antenna, try SISO (if HT association), try MIMO (if HT association) + * For SISO: + * Change antenna, try MIMO, try shortened guard interval (SGI) + * For MIMO: + * Try SISO antenna A, SISO antenna B, try shortened guard interval (SGI) + * + * When trying a new mode, use the same bit rate as the old/current mode when + * trying antenna switches and shortened guard interval. When switching to + * SISO from MIMO or legacy, or to MIMO from SISO or legacy, use a rate + * for which the expected throughput (under perfect conditions) is about the + * same or slightly better than the actual measured throughput delivered by + * the old/current mode. + * + * Actual throughput can be estimated by multiplying the expected throughput + * by the success ratio (successful / attempted tx frames). Frame size is + * not considered in this calculation; it assumes that frame size will average + * out to be fairly consistent over several samples. The following are + * metric values for expected throughput assuming 100% success ratio. + * Only G band has support for CCK rates: + * + * RATE: 1 2 5 11 6 9 12 18 24 36 48 54 60 + * + * G: 7 13 35 58 40 57 72 98 121 154 177 186 186 + * A: 0 0 0 0 40 57 72 98 121 154 177 186 186 + * SISO 20MHz: 0 0 0 0 42 42 76 102 124 159 183 193 202 + * SGI SISO 20MHz: 0 0 0 0 46 46 82 110 132 168 192 202 211 + * MIMO 20MHz: 0 0 0 0 74 74 123 155 179 214 236 244 251 + * SGI MIMO 20MHz: 0 0 0 0 81 81 131 164 188 222 243 251 257 + * SISO 40MHz: 0 0 0 0 77 77 127 160 184 220 242 250 257 + * SGI SISO 40MHz: 0 0 0 0 83 83 135 169 193 229 250 257 264 + * MIMO 40MHz: 0 0 0 0 123 123 182 214 235 264 279 285 289 + * SGI MIMO 40MHz: 0 0 0 0 131 131 191 222 242 270 284 289 293 + * + * After the new mode has been tried for a short while (minimum of 6 failed + * frames or 8 successful frames), compare success ratio and actual throughput + * estimate of the new mode with the old. If either is better with the new + * mode, continue to use the new mode. + * + * Continue comparing modes until all 3 possibilities have been tried. + * If moving from legacy to HT, try all 3 possibilities from the new HT + * mode. After trying all 3, a best mode is found. Continue to use this mode + * for the longer "while" described above (e.g. 480 successful frames for + * legacy), and then repeat the search process. + * */ struct iwl4965_link_quality_cmd { + + /* Index of destination/recipient station in uCode's station table */ u8 sta_id; u8 reserved1; - __le16 control; + __le16 control; /* not used */ struct iwl4965_link_qual_general_params general_params; struct iwl4965_link_qual_agg_params agg_params; + + /* + * Rate info; when using rate-scaling, Tx command's initial_rate_index + * specifies 1st Tx rate attempted, via index into this table. + * 4965 works its way through table when retrying Tx. + */ struct { - __le32 rate_n_flags; + __le32 rate_n_flags; /* RATE_MCS_*, IWL_RATE_* */ } rs_table[LINK_QUAL_MAX_RETRY_NUM]; __le32 reserved2; } __attribute__ ((packed)); -- 1.5.3.6 ^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 33/36] iwlwifi: enhance WPA authenication stability 2007-11-29 3:10 ` [PATCH 32/36] iwlwifi: document 4965 rate scaling Zhu Yi @ 2007-11-29 3:10 ` Zhu Yi 2007-11-29 3:10 ` [PATCH 34/36] iwlwifi: fix ucode assertion for RX queue overrun Zhu Yi 0 siblings, 1 reply; 36+ messages in thread From: Zhu Yi @ 2007-11-29 3:10 UTC (permalink / raw) To: linville; +Cc: linux-wireless, Mohamed Abbas, Zhu Yi From: Mohamed Abbas <mabbas@linux.intel.com> This patch enhanced WPA authenication stability by avoiding scan immediately followed by association. We don't do any scanning right after association in next several seconds. This will allow WPA authentication to take place without any interruption. Signed-off-by: Mohamed Abbas <mabbas@linux.intel.com> Signed-off-by: Zhu Yi <yi.zhu@intel.com> --- drivers/net/wireless/iwlwifi/iwl-3945.c | 9 +++++++++ drivers/net/wireless/iwlwifi/iwl-3945.h | 1 + drivers/net/wireless/iwlwifi/iwl-4965.c | 8 ++++++++ drivers/net/wireless/iwlwifi/iwl-4965.h | 1 + drivers/net/wireless/iwlwifi/iwl3945-base.c | 24 +++++++++++++++++------- drivers/net/wireless/iwlwifi/iwl4965-base.c | 24 +++++++++++++++++------- 6 files changed, 53 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 51b9030..1b81545 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -285,6 +285,8 @@ static void iwl3945_handle_data_packet(struct iwl3945_priv *priv, int is_data, rxb->skb = NULL; } +#define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6) + static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv, struct iwl3945_rx_mem_buffer *rxb) { @@ -442,6 +444,13 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv, case IEEE80211_STYPE_REASSOC_RESP:{ struct ieee80211_mgmt *mgnt = (struct ieee80211_mgmt *)header; + + /* We have just associated, give some + * time for the 4-way handshake if + * any. Don't start scan too early. */ + priv->next_scan_jiffies = jiffies + + IWL_DELAY_NEXT_SCAN_AFTER_ASSOC; + priv->assoc_id = (~((1 << 15) | (1 << 14)) & le16_to_cpu(mgnt->u. assoc_resp.aid)); diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 75cef3e..1f82061 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -752,6 +752,7 @@ struct iwl3945_priv { /* Scan related variables */ unsigned long last_scan_jiffies; + unsigned long next_scan_jiffies; unsigned long scan_start; unsigned long scan_pass_start; unsigned long scan_start_tsf; diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 40c795e..c8e7adf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -3802,6 +3802,8 @@ static void iwl4965_update_ps_mode(struct iwl4965_priv *priv, u16 ps_bit, u8 *ad } } +#define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6) + /* Called for REPLY_4965_RX (legacy ABG frames), or * REPLY_RX_MPDU_CMD (HT high-throughput N frames). */ static void iwl4965_rx_reply_rx(struct iwl4965_priv *priv, @@ -3973,6 +3975,12 @@ static void iwl4965_rx_reply_rx(struct iwl4965_priv *priv, struct ieee80211_mgmt *mgnt = (struct ieee80211_mgmt *)header; + /* We have just associated, give some + * time for the 4-way handshake if + * any. Don't start scan too early. */ + priv->next_scan_jiffies = jiffies + + IWL_DELAY_NEXT_SCAN_AFTER_ASSOC; + priv->assoc_id = (~((1 << 15) | (1 << 14)) & le16_to_cpu(mgnt->u.assoc_resp.aid)); priv->assoc_capability = diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index 2930c10..c062738 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h @@ -1082,6 +1082,7 @@ struct iwl4965_priv { /* Scan related variables */ unsigned long last_scan_jiffies; + unsigned long next_scan_jiffies; unsigned long scan_start; unsigned long scan_pass_start; unsigned long scan_start_tsf; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index a892e26..82e4e1c 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -2800,7 +2800,8 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, IWL_DEBUG_TX("Sending REASSOC frame\n"); #endif - if (!iwl3945_is_associated(priv) && + /* drop all data frame if we are not associated */ + if (!iwl3945_is_associated(priv) && !priv->assoc_id && ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA)) { IWL_DEBUG_DROP("Dropping - !iwl3945_is_associated\n"); goto drop_unlock; @@ -3737,6 +3738,7 @@ static void iwl3945_rx_scan_results_notif(struct iwl3945_priv *priv, (priv->last_scan_jiffies, jiffies))); priv->last_scan_jiffies = jiffies; + priv->next_scan_jiffies = 0; } /* Service SCAN_COMPLETE_NOTIFICATION (0x84) */ @@ -3779,6 +3781,7 @@ static void iwl3945_rx_scan_complete_notif(struct iwl3945_priv *priv, } priv->last_scan_jiffies = jiffies; + priv->next_scan_jiffies = 0; IWL_DEBUG_INFO("Setting scan to off\n"); clear_bit(STATUS_SCANNING, &priv->status); @@ -6798,6 +6801,8 @@ static void iwl3945_bg_rx_replenish(struct work_struct *data) mutex_unlock(&priv->mutex); } +#define IWL_DELAY_NEXT_SCAN (HZ*2) + static void iwl3945_bg_post_associate(struct work_struct *data) { struct iwl3945_priv *priv = container_of(data, struct iwl3945_priv, @@ -6898,6 +6903,8 @@ static void iwl3945_bg_post_associate(struct work_struct *data) #ifdef CONFIG_IWL3945_QOS iwl3945_activate_qos(priv, 0); #endif /* CONFIG_IWL3945_QOS */ + /* we have just associated, don't start scan too early */ + priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN; mutex_unlock(&priv->mutex); } @@ -7327,7 +7334,6 @@ static void iwl3945_mac_remove_interface(struct ieee80211_hw *hw, } -#define IWL_DELAY_NEXT_SCAN (HZ*2) static int iwl3945_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len) { int rc = 0; @@ -7351,16 +7357,20 @@ static int iwl3945_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len) goto out_unlock; } + /* we don't schedule scan within next_scan_jiffies period */ + if (priv->next_scan_jiffies && + time_after(priv->next_scan_jiffies, jiffies)) { + rc = -EAGAIN; + goto out_unlock; + } /* if we just finished scan ask for delay */ - if (priv->last_scan_jiffies && - time_after(priv->last_scan_jiffies + IWL_DELAY_NEXT_SCAN, - jiffies)) { + if (priv->last_scan_jiffies && time_after(priv->last_scan_jiffies + + IWL_DELAY_NEXT_SCAN, jiffies)) { rc = -EAGAIN; goto out_unlock; } if (len) { - IWL_DEBUG_SCAN("direct scan for " - "%s [%d]\n ", + IWL_DEBUG_SCAN("direct scan for %s [%d]\n ", iwl3945_escape_essid(ssid, len), (int)len); priv->one_direct_scan = 1; diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 31601d7..f806e70 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -2905,7 +2905,8 @@ static int iwl4965_tx_skb(struct iwl4965_priv *priv, IWL_DEBUG_TX("Sending REASSOC frame\n"); #endif - if (!iwl4965_is_associated(priv) && + /* drop all data frame if we are not associated */ + if (!iwl4965_is_associated(priv) && !priv->assoc_id && ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA)) { IWL_DEBUG_DROP("Dropping - !iwl4965_is_associated\n"); goto drop_unlock; @@ -4055,6 +4056,7 @@ static void iwl4965_rx_scan_results_notif(struct iwl4965_priv *priv, (priv->last_scan_jiffies, jiffies))); priv->last_scan_jiffies = jiffies; + priv->next_scan_jiffies = 0; } /* Service SCAN_COMPLETE_NOTIFICATION (0x84) */ @@ -4097,6 +4099,7 @@ static void iwl4965_rx_scan_complete_notif(struct iwl4965_priv *priv, } priv->last_scan_jiffies = jiffies; + priv->next_scan_jiffies = 0; IWL_DEBUG_INFO("Setting scan to off\n"); clear_bit(STATUS_SCANNING, &priv->status); @@ -7220,6 +7223,8 @@ static void iwl4965_bg_rx_replenish(struct work_struct *data) mutex_unlock(&priv->mutex); } +#define IWL_DELAY_NEXT_SCAN (HZ*2) + static void iwl4965_bg_post_associate(struct work_struct *data) { struct iwl4965_priv *priv = container_of(data, struct iwl4965_priv, @@ -7335,6 +7340,8 @@ static void iwl4965_bg_post_associate(struct work_struct *data) #ifdef CONFIG_IWL4965_QOS iwl4965_activate_qos(priv, 0); #endif /* CONFIG_IWL4965_QOS */ + /* we have just associated, don't start scan too early */ + priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN; mutex_unlock(&priv->mutex); } @@ -7801,7 +7808,6 @@ static void iwl4965_mac_erp_ie_changed(struct ieee80211_hw *hw, iwl4965_send_rxon_assoc(priv); } -#define IWL_DELAY_NEXT_SCAN (HZ*2) static int iwl4965_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len) { int rc = 0; @@ -7825,16 +7831,20 @@ static int iwl4965_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len) goto out_unlock; } + /* we don't schedule scan within next_scan_jiffies period */ + if (priv->next_scan_jiffies && + time_after(priv->next_scan_jiffies, jiffies)) { + rc = -EAGAIN; + goto out_unlock; + } /* if we just finished scan ask for delay */ - if (priv->last_scan_jiffies && - time_after(priv->last_scan_jiffies + IWL_DELAY_NEXT_SCAN, - jiffies)) { + if (priv->last_scan_jiffies && time_after(priv->last_scan_jiffies + + IWL_DELAY_NEXT_SCAN, jiffies)) { rc = -EAGAIN; goto out_unlock; } if (len) { - IWL_DEBUG_SCAN("direct scan for " - "%s [%d]\n ", + IWL_DEBUG_SCAN("direct scan for %s [%d]\n ", iwl4965_escape_essid(ssid, len), (int)len); priv->one_direct_scan = 1; -- 1.5.3.6 ^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 34/36] iwlwifi: fix ucode assertion for RX queue overrun 2007-11-29 3:10 ` [PATCH 33/36] iwlwifi: enhance WPA authenication stability Zhu Yi @ 2007-11-29 3:10 ` Zhu Yi 2007-11-29 3:10 ` [PATCH 35/36] iwlwifi: avoid firmware command sending if rfkill is enabled Zhu Yi 0 siblings, 1 reply; 36+ messages in thread From: Zhu Yi @ 2007-11-29 3:10 UTC (permalink / raw) To: linville; +Cc: linux-wireless, Mohamed Abbas, Zhu Yi From: Mohamed Abbas <mabbas@linux.intel.com> This patch allows the driver to restock the RX queue early if the RX queue is almost empty. This will help on avoiding any ucode assert for the RX overrun problem. Signed-off-by: Mohamed Abbas <mabbas@linux.intel.com> Signed-off-by: Zhu Yi <yi.zhu@intel.com> --- drivers/net/wireless/iwlwifi/iwl3945-base.c | 37 ++++++++++++++++++++++++- drivers/net/wireless/iwlwifi/iwl4965-base.c | 38 +++++++++++++++++++++++++- 2 files changed, 71 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 82e4e1c..5bef76d 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -4123,9 +4123,8 @@ static int iwl3945_rx_queue_restock(struct iwl3945_priv *priv) * Also restock the Rx queue via iwl3945_rx_queue_restock. * This is called as a scheduled work item (except for during initialization) */ -void iwl3945_rx_replenish(void *data) +static void iwl3945_rx_allocate(struct iwl3945_priv *priv) { - struct iwl3945_priv *priv = data; struct iwl3945_rx_queue *rxq = &priv->rxq; struct list_head *element; struct iwl3945_rx_mem_buffer *rxb; @@ -4158,6 +4157,26 @@ void iwl3945_rx_replenish(void *data) rxq->free_count++; } spin_unlock_irqrestore(&rxq->lock, flags); +} + +/* + * this should be called while priv->lock is locked + */ +void __iwl3945_rx_replenish(void *data) +{ + struct iwl3945_priv *priv = data; + + iwl3945_rx_allocate(priv); + iwl3945_rx_queue_restock(priv); +} + + +void iwl3945_rx_replenish(void *data) +{ + struct iwl3945_priv *priv = data; + unsigned long flags; + + iwl3945_rx_allocate(priv); spin_lock_irqsave(&priv->lock, flags); iwl3945_rx_queue_restock(priv); @@ -4335,12 +4354,16 @@ static void iwl3945_rx_handle(struct iwl3945_priv *priv) u32 r, i; int reclaim; unsigned long flags; + u8 fill_rx = 0; + u32 count = 0; /* uCode's read index (stored in shared DRAM) indicates the last Rx * buffer that the driver may process (last buffer filled by ucode). */ r = iwl3945_hw_get_rx_read(priv); i = rxq->read; + if (iwl3945_rx_queue_space(rxq) > (RX_QUEUE_SIZE / 2)) + fill_rx = 1; /* Rx interrupt, but nothing sent from uCode */ if (i == r) IWL_DEBUG(IWL_DL_RX | IWL_DL_ISR, "r = %d, i = %d\n", r, i); @@ -4411,6 +4434,16 @@ static void iwl3945_rx_handle(struct iwl3945_priv *priv) list_add_tail(&rxb->list, &priv->rxq.rx_used); spin_unlock_irqrestore(&rxq->lock, flags); i = (i + 1) & RX_QUEUE_MASK; + /* If there are a lot of unused frames, + * restock the Rx queue so ucode won't assert. */ + if (fill_rx) { + count++; + if (count >= 8) { + priv->rxq.read = i; + __iwl3945_rx_replenish(priv); + count = 0; + } + } } /* Backtrack one entry */ diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index f806e70..c9e5b95 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -4477,9 +4477,8 @@ static int iwl4965_rx_queue_restock(struct iwl4965_priv *priv) * Also restock the Rx queue via iwl4965_rx_queue_restock. * This is called as a scheduled work item (except for during initialization) */ -void iwl4965_rx_replenish(void *data) +static void iwl4965_rx_allocate(struct iwl4965_priv *priv) { - struct iwl4965_priv *priv = data; struct iwl4965_rx_queue *rxq = &priv->rxq; struct list_head *element; struct iwl4965_rx_mem_buffer *rxb; @@ -4512,6 +4511,26 @@ void iwl4965_rx_replenish(void *data) rxq->free_count++; } spin_unlock_irqrestore(&rxq->lock, flags); +} + +/* + * this should be called while priv->lock is locked +*/ +void __iwl4965_rx_replenish(void *data) +{ + struct iwl4965_priv *priv = data; + + iwl4965_rx_allocate(priv); + iwl4965_rx_queue_restock(priv); +} + + +void iwl4965_rx_replenish(void *data) +{ + struct iwl4965_priv *priv = data; + unsigned long flags; + + iwl4965_rx_allocate(priv); spin_lock_irqsave(&priv->lock, flags); iwl4965_rx_queue_restock(priv); @@ -4689,6 +4708,8 @@ static void iwl4965_rx_handle(struct iwl4965_priv *priv) u32 r, i; int reclaim; unsigned long flags; + u8 fill_rx = 0; + u32 count = 0; /* uCode's read index (stored in shared DRAM) indicates the last Rx * buffer that the driver may process (last buffer filled by ucode). */ @@ -4699,6 +4720,9 @@ static void iwl4965_rx_handle(struct iwl4965_priv *priv) if (i == r) IWL_DEBUG(IWL_DL_RX | IWL_DL_ISR, "r = %d, i = %d\n", r, i); + if (iwl4965_rx_queue_space(rxq) > (RX_QUEUE_SIZE / 2)) + fill_rx = 1; + while (i != r) { rxb = rxq->queue[i]; @@ -4768,6 +4792,16 @@ static void iwl4965_rx_handle(struct iwl4965_priv *priv) list_add_tail(&rxb->list, &priv->rxq.rx_used); spin_unlock_irqrestore(&rxq->lock, flags); i = (i + 1) & RX_QUEUE_MASK; + /* If there are a lot of unused frames, + * restock the Rx queue so ucode wont assert. */ + if (fill_rx) { + count++; + if (count >= 8) { + priv->rxq.read = i; + __iwl4965_rx_replenish(priv); + count = 0; + } + } } /* Backtrack one entry */ -- 1.5.3.6 ^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 35/36] iwlwifi: avoid firmware command sending if rfkill is enabled 2007-11-29 3:10 ` [PATCH 34/36] iwlwifi: fix ucode assertion for RX queue overrun Zhu Yi @ 2007-11-29 3:10 ` Zhu Yi 2007-11-29 3:10 ` [PATCH 36/36] iwlwifi: update version number to 1.2.22 Zhu Yi 0 siblings, 1 reply; 36+ messages in thread From: Zhu Yi @ 2007-11-29 3:10 UTC (permalink / raw) To: linville; +Cc: linux-wireless, Mohamed Abbas, Zhu Yi From: Mohamed Abbas <mabbas@linux.intel.com> This patch fixed a ucode timeout issue and worked code with suspend to disk. Signed-off-by: Mohamed Abbas <mabbas@linux.intel.com> Signed-off-by: Zhu Yi <yi.zhu@intel.com> --- drivers/net/wireless/iwlwifi/iwl3945-base.c | 54 ++++++++++++++++---------- drivers/net/wireless/iwlwifi/iwl4965-base.c | 54 ++++++++++++++++---------- 2 files changed, 66 insertions(+), 42 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 5bef76d..963d3cd 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -2546,9 +2546,6 @@ static void iwl3945_connection_init_rx_config(struct iwl3945_priv *priv) static int iwl3945_set_mode(struct iwl3945_priv *priv, int mode) { - if (!iwl3945_is_ready_rf(priv)) - return -EAGAIN; - if (mode == IEEE80211_IF_TYPE_IBSS) { const struct iwl3945_channel_info *ch_info; @@ -2563,13 +2560,6 @@ static int iwl3945_set_mode(struct iwl3945_priv *priv, int mode) } } - cancel_delayed_work(&priv->scan_check); - if (iwl3945_scan_cancel_timeout(priv, 100)) { - IWL_WARNING("Aborted scan still in progress after 100ms\n"); - IWL_DEBUG_MAC80211("leaving - scan abort failed.\n"); - return -EAGAIN; - } - priv->iw_mode = mode; iwl3945_connection_init_rx_config(priv); @@ -2577,6 +2567,17 @@ static int iwl3945_set_mode(struct iwl3945_priv *priv, int mode) iwl3945_clear_stations_table(priv); + /* dont commit rxon if rf-kill is on*/ + if (!iwl3945_is_ready_rf(priv)) + return -EAGAIN; + + cancel_delayed_work(&priv->scan_check); + if (iwl3945_scan_cancel_timeout(priv, 100)) { + IWL_WARNING("Aborted scan still in progress after 100ms\n"); + IWL_DEBUG_MAC80211("leaving - scan abort failed.\n"); + return -EAGAIN; + } + iwl3945_commit_rxon(priv); return 0; @@ -7012,6 +7013,12 @@ static void iwl3945_mac_stop(struct ieee80211_hw *hw) * RXON_FILTER_ASSOC_MSK BIT */ priv->is_open = 0; + if (!iwl3945_is_ready_rf(priv)) { + IWL_DEBUG_MAC80211("leave - RF not ready\n"); + mutex_unlock(&priv->mutex); + return 0; + } + iwl3945_scan_cancel_timeout(priv, 100); cancel_delayed_work(&priv->post_associate); priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; @@ -7280,6 +7287,9 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, int if_id, priv->ibss_beacon = conf->beacon; } + if (iwl3945_is_rfkill(priv)) + goto done; + if (conf->bssid && !is_zero_ether_addr(conf->bssid) && !is_multicast_ether_addr(conf->bssid)) { /* If there is currently a HW scan going on in the background @@ -7314,6 +7324,7 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, int if_id, iwl3945_commit_rxon(priv); } + done: spin_lock_irqsave(&priv->lock, flags); if (!conf->ssid_len) memset(priv->essid, 0, IW_ESSID_MAX_SIZE); @@ -7350,11 +7361,12 @@ static void iwl3945_mac_remove_interface(struct ieee80211_hw *hw, mutex_lock(&priv->mutex); - iwl3945_scan_cancel_timeout(priv, 100); - cancel_delayed_work(&priv->post_associate); - priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - iwl3945_commit_rxon(priv); - + if (iwl3945_is_ready_rf(priv)) { + iwl3945_scan_cancel_timeout(priv, 100); + cancel_delayed_work(&priv->post_associate); + priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + iwl3945_commit_rxon(priv); + } if (priv->interface_id == conf->if_id) { priv->interface_id = 0; memset(priv->bssid, 0, ETH_ALEN); @@ -7625,6 +7637,12 @@ static void iwl3945_mac_reset_tsf(struct ieee80211_hw *hw) spin_unlock_irqrestore(&priv->lock, flags); + if (!iwl3945_is_ready_rf(priv)) { + IWL_DEBUG_MAC80211("leave - not ready\n"); + mutex_unlock(&priv->mutex); + return; + } + /* we are restarting association process * clear RXON_FILTER_ASSOC_MSK bit */ @@ -7642,12 +7660,6 @@ static void iwl3945_mac_reset_tsf(struct ieee80211_hw *hw) return; } - if (!iwl3945_is_ready_rf(priv)) { - IWL_DEBUG_MAC80211("leave - not ready\n"); - mutex_unlock(&priv->mutex); - return; - } - priv->only_active_channel = 0; iwl3945_set_rate(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index c9e5b95..98a394e 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -2649,9 +2649,6 @@ static void iwl4965_connection_init_rx_config(struct iwl4965_priv *priv) static int iwl4965_set_mode(struct iwl4965_priv *priv, int mode) { - if (!iwl4965_is_ready_rf(priv)) - return -EAGAIN; - if (mode == IEEE80211_IF_TYPE_IBSS) { const struct iwl4965_channel_info *ch_info; @@ -2666,13 +2663,6 @@ static int iwl4965_set_mode(struct iwl4965_priv *priv, int mode) } } - cancel_delayed_work(&priv->scan_check); - if (iwl4965_scan_cancel_timeout(priv, 100)) { - IWL_WARNING("Aborted scan still in progress after 100ms\n"); - IWL_DEBUG_MAC80211("leaving - scan abort failed.\n"); - return -EAGAIN; - } - priv->iw_mode = mode; iwl4965_connection_init_rx_config(priv); @@ -2680,6 +2670,17 @@ static int iwl4965_set_mode(struct iwl4965_priv *priv, int mode) iwl4965_clear_stations_table(priv); + /* dont commit rxon if rf-kill is on*/ + if (!iwl4965_is_ready_rf(priv)) + return -EAGAIN; + + cancel_delayed_work(&priv->scan_check); + if (iwl4965_scan_cancel_timeout(priv, 100)) { + IWL_WARNING("Aborted scan still in progress after 100ms\n"); + IWL_DEBUG_MAC80211("leaving - scan abort failed.\n"); + return -EAGAIN; + } + iwl4965_commit_rxon(priv); return 0; @@ -7450,6 +7451,12 @@ static void iwl4965_mac_stop(struct ieee80211_hw *hw) * RXON_FILTER_ASSOC_MSK BIT */ priv->is_open = 0; + if (!iwl4965_is_ready_rf(priv)) { + IWL_DEBUG_MAC80211("leave - RF not ready\n"); + mutex_unlock(&priv->mutex); + return 0; + } + iwl4965_scan_cancel_timeout(priv, 100); cancel_delayed_work(&priv->post_associate); priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; @@ -7733,6 +7740,9 @@ static int iwl4965_mac_config_interface(struct ieee80211_hw *hw, int if_id, priv->ibss_beacon = conf->beacon; } + if (iwl4965_is_rfkill(priv)) + goto done; + if (conf->bssid && !is_zero_ether_addr(conf->bssid) && !is_multicast_ether_addr(conf->bssid)) { /* If there is currently a HW scan going on in the background @@ -7767,6 +7777,7 @@ static int iwl4965_mac_config_interface(struct ieee80211_hw *hw, int if_id, iwl4965_commit_rxon(priv); } + done: spin_lock_irqsave(&priv->lock, flags); if (!conf->ssid_len) memset(priv->essid, 0, IW_ESSID_MAX_SIZE); @@ -7803,11 +7814,12 @@ static void iwl4965_mac_remove_interface(struct ieee80211_hw *hw, mutex_lock(&priv->mutex); - iwl4965_scan_cancel_timeout(priv, 100); - cancel_delayed_work(&priv->post_associate); - priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - iwl4965_commit_rxon(priv); - + if (iwl4965_is_ready_rf(priv)) { + iwl4965_scan_cancel_timeout(priv, 100); + cancel_delayed_work(&priv->post_associate); + priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + iwl4965_commit_rxon(priv); + } if (priv->interface_id == conf->if_id) { priv->interface_id = 0; memset(priv->bssid, 0, ETH_ALEN); @@ -8120,6 +8132,12 @@ static void iwl4965_mac_reset_tsf(struct ieee80211_hw *hw) spin_unlock_irqrestore(&priv->lock, flags); + if (!iwl4965_is_ready_rf(priv)) { + IWL_DEBUG_MAC80211("leave - not ready\n"); + mutex_unlock(&priv->mutex); + return; + } + /* we are restarting association process * clear RXON_FILTER_ASSOC_MSK bit */ @@ -8137,12 +8155,6 @@ static void iwl4965_mac_reset_tsf(struct ieee80211_hw *hw) return; } - if (!iwl4965_is_ready_rf(priv)) { - IWL_DEBUG_MAC80211("leave - not ready\n"); - mutex_unlock(&priv->mutex); - return; - } - priv->only_active_channel = 0; iwl4965_set_rate(priv); -- 1.5.3.6 ^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 36/36] iwlwifi: update version number to 1.2.22 2007-11-29 3:10 ` [PATCH 35/36] iwlwifi: avoid firmware command sending if rfkill is enabled Zhu Yi @ 2007-11-29 3:10 ` Zhu Yi 0 siblings, 0 replies; 36+ messages in thread From: Zhu Yi @ 2007-11-29 3:10 UTC (permalink / raw) To: linville; +Cc: linux-wireless, Zhu Yi Signed-off-by: Zhu Yi <yi.zhu@intel.com> --- drivers/net/wireless/iwlwifi/iwl3945-base.c | 2 +- drivers/net/wireless/iwlwifi/iwl4965-base.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 963d3cd..48fd1e4 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -91,7 +91,7 @@ int iwl3945_param_queues_num = IWL_MAX_NUM_QUEUES; /* def: 8 Tx queues */ #define VS #endif -#define IWLWIFI_VERSION "1.1.19k" VD VS +#define IWLWIFI_VERSION "1.2.22k" VD VS #define DRV_COPYRIGHT "Copyright(c) 2003-2007 Intel Corporation" #define DRV_VERSION IWLWIFI_VERSION diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 98a394e..25fa990 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -90,7 +90,7 @@ int iwl4965_param_queues_num = IWL_MAX_NUM_QUEUES; /* def: 16 Tx queues */ #define VS #endif -#define IWLWIFI_VERSION "1.1.19k" VD VS +#define IWLWIFI_VERSION "1.2.22k" VD VS #define DRV_COPYRIGHT "Copyright(c) 2003-2007 Intel Corporation" #define DRV_VERSION IWLWIFI_VERSION -- 1.5.3.6 ^ permalink raw reply related [flat|nested] 36+ messages in thread
* Re: [PATCH 15/36] iwlwifi: add comments to iwl*-base.c [not found] ` <1196305816-23023-16-git-send-email-yi.zhu@intel.com> 2007-11-29 3:09 ` [PATCH 16/36] iwlwifi: fix possibly NULL dereference in iwl_set_rate() Zhu Yi @ 2007-11-29 3:17 ` Zhu Yi 1 sibling, 0 replies; 36+ messages in thread From: Zhu Yi @ 2007-11-29 3:17 UTC (permalink / raw) To: linville; +Cc: linux-wireless, Cahill, Ben M Resend. Replace mail subject due to ML restriction for capital Triple-X in subject. On Thu, 2007-11-29 at 11:09 +0800, Zhu Yi wrote: > From: Cahill, Ben M <ben.m.cahill@intel.com> > > Add comments to iwlXXXX-base.c > > Signed-off-by: Cahill, Ben M <ben.m.cahill@intel.com> > Signed-off-by: Zhu Yi <yi.zhu@intel.com> > --- > drivers/net/wireless/iwlwifi/iwl3945-base.c | 215 ++++++++++++++++++++++----- > drivers/net/wireless/iwlwifi/iwl4965-base.c | 212 ++++++++++++++++++++++---- > 2 files changed, 356 insertions(+), 71 deletions(-) > > diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c > index c0b6ac3..a742309 100644 > --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c > +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c > @@ -63,13 +63,13 @@ static int iwl3945_tx_queue_update_write_ptr(struct iwl3945_priv *priv, > ******************************************************************************/ > > /* module parameters */ > -static int iwl3945_param_disable_hw_scan; > -static int iwl3945_param_debug; > -static int iwl3945_param_disable; /* def: enable radio */ > +static int iwl3945_param_disable_hw_scan; /* def: 0 = use 3945's h/w scan */ > +static int iwl3945_param_debug; /* def: 0 = minimal debug log messages */ > +static int iwl3945_param_disable; /* def: 0 = enable radio */ > static int iwl3945_param_antenna; /* def: 0 = both antennas (use diversity) */ > -int iwl3945_param_hwcrypto; /* def: using software encryption */ > -static int iwl3945_param_qos_enable = 1; > -int iwl3945_param_queues_num = IWL_MAX_NUM_QUEUES; > +int iwl3945_param_hwcrypto; /* def: 0 = use software encryption */ > +static int iwl3945_param_qos_enable = 1; /* def: 1 = use quality of service */ > +int iwl3945_param_queues_num = IWL_MAX_NUM_QUEUES; /* def: 8 Tx queues */ > > /* > * module name, copyright, version, etc. > @@ -184,17 +184,24 @@ static void iwl3945_print_hex_dump(int level, void *p, u32 len) > * > * Theory of operation > * > - * A queue is a circular buffers with 'Read' and 'Write' pointers. > - * 2 empty entries always kept in the buffer to protect from overflow. > + * A Tx or Rx queue resides in host DRAM, and is comprised of a circular buffer > + * of buffer descriptors, each of which points to one or more data buffers for > + * the device to read from or fill. Driver and device exchange status of each > + * queue via "read" and "write" pointers. Driver keeps minimum of 2 empty > + * entries in each circular buffer, to protect against confusing empty and full > + * queue states. > + * > + * The device reads or writes the data in the queues via the device's several > + * DMA/FIFO channels. Each queue is mapped to a single DMA channel. > * > * For Tx queue, there are low mark and high mark limits. If, after queuing > * the packet for Tx, free space become < low mark, Tx queue stopped. When > * reclaiming packets (on 'tx done IRQ), if free space become > high mark, > * Tx queue resumed. > * > - * The IWL operates with six queues, one receive queue in the device's > - * sram, one transmit queue for sending commands to the device firmware, > - * and four transmit queues for data. > + * The 3945 operates with six queues: One receive queue, one transmit queue > + * (#4) for sending commands to the device firmware, and four transmit queues > + * (#0-3) for data tx via EDCA. An additional 2 HCCA queues are unused. > ***************************************************/ > > static int iwl3945_queue_space(const struct iwl3945_queue *q) > @@ -213,13 +220,21 @@ static int iwl3945_queue_space(const struct iwl3945_queue *q) > return s; > } > > -/* XXX: n_bd must be power-of-two size */ > +/** > + * iwl3945_queue_inc_wrap - increment queue index, wrap back to beginning > + * @index -- current index > + * @n_bd -- total number of entries in queue (must be power of 2) > + */ > static inline int iwl3945_queue_inc_wrap(int index, int n_bd) > { > return ++index & (n_bd - 1); > } > > -/* XXX: n_bd must be power-of-two size */ > +/** > + * iwl3945_queue_dec_wrap - increment queue index, wrap back to end > + * @index -- current index > + * @n_bd -- total number of entries in queue (must be power of 2) > + */ > static inline int iwl3945_queue_dec_wrap(int index, int n_bd) > { > return --index & (n_bd - 1); > @@ -234,12 +249,17 @@ static inline int x2_queue_used(const struct iwl3945_queue *q, int i) > > static inline u8 get_cmd_index(struct iwl3945_queue *q, u32 index, int is_huge) > { > + /* This is for scan command, the big buffer at end of command array */ > if (is_huge) > - return q->n_window; > + return q->n_window; /* must be power of 2 */ > > + /* Otherwise, use normal size buffers */ > return index & (q->n_window - 1); > } > > +/** > + * iwl3945_queue_init - Initialize queue's high/low-water and read/write indexes > + */ > static int iwl3945_queue_init(struct iwl3945_priv *priv, struct iwl3945_queue *q, > int count, int slots_num, u32 id) > { > @@ -268,11 +288,16 @@ static int iwl3945_queue_init(struct iwl3945_priv *priv, struct iwl3945_queue *q > return 0; > } > > +/** > + * iwl3945_tx_queue_alloc - Alloc driver data and TFD CB for one Tx/cmd queue > + */ > static int iwl3945_tx_queue_alloc(struct iwl3945_priv *priv, > struct iwl3945_tx_queue *txq, u32 id) > { > struct pci_dev *dev = priv->pci_dev; > > + /* Driver private data, only for Tx (not command) queues, > + * not shared with device. */ > if (id != IWL_CMD_QUEUE_NUM) { > txq->txb = kmalloc(sizeof(txq->txb[0]) * > TFD_QUEUE_SIZE_MAX, GFP_KERNEL); > @@ -284,6 +309,8 @@ static int iwl3945_tx_queue_alloc(struct iwl3945_priv *priv, > } else > txq->txb = NULL; > > + /* Circular buffer of transmit frame descriptors (TFDs), > + * shared with device */ > txq->bd = pci_alloc_consistent(dev, > sizeof(txq->bd[0]) * TFD_QUEUE_SIZE_MAX, > &txq->q.dma_addr); > @@ -306,6 +333,9 @@ static int iwl3945_tx_queue_alloc(struct iwl3945_priv *priv, > return -ENOMEM; > } > > +/** > + * iwl3945_tx_queue_init - Allocate and initialize one tx/cmd queue > + */ > int iwl3945_tx_queue_init(struct iwl3945_priv *priv, > struct iwl3945_tx_queue *txq, int slots_num, u32 txq_id) > { > @@ -313,9 +343,14 @@ int iwl3945_tx_queue_init(struct iwl3945_priv *priv, > int len; > int rc = 0; > > - /* allocate command space + one big command for scan since scan > - * command is very huge the system will not have two scan at the > - * same time */ > + /* > + * Alloc buffer array for commands (Tx or other types of commands). > + * For the command queue (#4), allocate command space + one big > + * command for scan, since scan command is very huge; the system will > + * not have two scans at the same time, so only one is needed. > + * For data Tx queues (all other queues), no super-size command > + * space is needed. > + */ > len = sizeof(struct iwl3945_cmd) * slots_num; > if (txq_id == IWL_CMD_QUEUE_NUM) > len += IWL_MAX_SCAN_SIZE; > @@ -323,6 +358,7 @@ int iwl3945_tx_queue_init(struct iwl3945_priv *priv, > if (!txq->cmd) > return -ENOMEM; > > + /* Alloc driver data array and TFD circular buffer */ > rc = iwl3945_tx_queue_alloc(priv, txq, txq_id); > if (rc) { > pci_free_consistent(dev, len, txq->cmd, txq->dma_addr_cmd); > @@ -334,8 +370,11 @@ int iwl3945_tx_queue_init(struct iwl3945_priv *priv, > /* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise > * iwl3945_queue_inc_wrap and iwl3945_queue_dec_wrap are broken. */ > BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1)); > + > + /* Initialize queue high/low-water, head/tail indexes */ > iwl3945_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id); > > + /* Tell device where to find queue, enable DMA channel. */ > iwl3945_hw_tx_queue_init(priv, txq); > > return 0; > @@ -346,8 +385,8 @@ int iwl3945_tx_queue_init(struct iwl3945_priv *priv, > * @txq: Transmit queue to deallocate. > * > * Empty queue by removing and destroying all BD's. > - * Free all buffers. txq itself is not freed. > - * > + * Free all buffers. > + * 0-fill, but do not free "txq" descriptor structure. > */ > void iwl3945_tx_queue_free(struct iwl3945_priv *priv, struct iwl3945_tx_queue *txq) > { > @@ -367,19 +406,21 @@ void iwl3945_tx_queue_free(struct iwl3945_priv *priv, struct iwl3945_tx_queue *t > if (q->id == IWL_CMD_QUEUE_NUM) > len += IWL_MAX_SCAN_SIZE; > > + /* De-alloc array of command/tx buffers */ > pci_free_consistent(dev, len, txq->cmd, txq->dma_addr_cmd); > > - /* free buffers belonging to queue itself */ > + /* De-alloc circular buffer of TFDs */ > if (txq->q.n_bd) > pci_free_consistent(dev, sizeof(struct iwl3945_tfd_frame) * > txq->q.n_bd, txq->bd, txq->q.dma_addr); > > + /* De-alloc array of per-TFD driver data */ > if (txq->txb) { > kfree(txq->txb); > txq->txb = NULL; > } > > - /* 0 fill whole structure */ > + /* 0-fill queue descriptor structure */ > memset(txq, 0, sizeof(*txq)); > } > > @@ -392,6 +433,11 @@ const u8 iwl3945_broadcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF > > /**************************************************************/ > #if 0 /* temporary disable till we add real remove station */ > +/** > + * iwl3945_remove_station - Remove driver's knowledge of station. > + * > + * NOTE: This does not remove station from device's station table. > + */ > static u8 iwl3945_remove_station(struct iwl3945_priv *priv, const u8 *addr, int is_ap) > { > int index = IWL_INVALID_STATION; > @@ -428,6 +474,12 @@ out: > return 0; > } > #endif > + > +/** > + * iwl3945_clear_stations_table - Clear the driver's station table > + * > + * NOTE: This does not clear or otherwise alter the device's station table. > + */ > static void iwl3945_clear_stations_table(struct iwl3945_priv *priv) > { > unsigned long flags; > @@ -440,7 +492,9 @@ static void iwl3945_clear_stations_table(struct iwl3945_priv *priv) > spin_unlock_irqrestore(&priv->sta_lock, flags); > } > > - > +/** > + * iwl3945_add_station - Add station to station tables in driver and device > + */ > u8 iwl3945_add_station(struct iwl3945_priv *priv, const u8 *addr, int is_ap, u8 flags) > { > int i; > @@ -486,6 +540,7 @@ u8 iwl3945_add_station(struct iwl3945_priv *priv, const u8 *addr, int is_ap, u8 > station->used = 1; > priv->num_stations++; > > + /* Set up the REPLY_ADD_STA command to send to device */ > memset(&station->sta, 0, sizeof(struct iwl3945_addsta_cmd)); > memcpy(station->sta.sta.addr, addr, ETH_ALEN); > station->sta.mode = 0; > @@ -504,6 +559,8 @@ u8 iwl3945_add_station(struct iwl3945_priv *priv, const u8 *addr, int is_ap, u8 > le16_to_cpu(station->sta.rate_n_flags); > > spin_unlock_irqrestore(&priv->sta_lock, flags_spin); > + > + /* Add station to device's station table */ > iwl3945_send_add_station(priv, &station->sta, flags); > return index; > > @@ -673,6 +730,8 @@ static int iwl3945_enqueue_hcmd(struct iwl3945_priv *priv, struct iwl3945_host_c > fix_size, q->write_ptr, idx, IWL_CMD_QUEUE_NUM); > > txq->need_update = 1; > + > + /* Increment and update queue's write index */ > q->write_ptr = iwl3945_queue_inc_wrap(q->write_ptr, q->n_bd); > ret = iwl3945_tx_queue_update_write_ptr(priv, txq); > > @@ -1511,7 +1570,7 @@ static void get_eeprom_mac(struct iwl3945_priv *priv, u8 *mac) > /** > * iwl3945_eeprom_init - read EEPROM contents > * > - * Load the EEPROM from adapter into priv->eeprom > + * Load the EEPROM contents from adapter into priv->eeprom > * > * NOTE: This routine uses the non-debug IO access functions. > */ > @@ -1536,6 +1595,7 @@ int iwl3945_eeprom_init(struct iwl3945_priv *priv) > return -ENOENT; > } > > + /* Make sure driver (instead of uCode) is allowed to read EEPROM */ > rc = iwl3945_eeprom_acquire_semaphore(priv); > if (rc < 0) { > IWL_ERROR("Failed to acquire EEPROM semaphore.\n"); > @@ -2631,21 +2691,23 @@ static void iwl3945_build_tx_cmd_basic(struct iwl3945_priv *priv, > cmd->cmd.tx.next_frame_len = 0; > } > > +/** > + * iwl3945_get_sta_id - Find station's index within station table > + */ > static int iwl3945_get_sta_id(struct iwl3945_priv *priv, struct ieee80211_hdr *hdr) > { > int sta_id; > u16 fc = le16_to_cpu(hdr->frame_control); > > - /* If this frame is broadcast or not data then use the broadcast > - * station id */ > + /* If this frame is broadcast or management, use broadcast station id */ > if (((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA) || > is_multicast_ether_addr(hdr->addr1)) > return priv->hw_setting.bcast_sta_id; > > switch (priv->iw_mode) { > > - /* If this frame is part of a BSS network (we're a station), then > - * we use the AP's station id */ > + /* If we are a client station in a BSS network, use the special > + * AP station entry (that's the only station we communicate with) */ > case IEEE80211_IF_TYPE_STA: > return IWL_AP_ID; > > @@ -2656,11 +2718,12 @@ static int iwl3945_get_sta_id(struct iwl3945_priv *priv, struct ieee80211_hdr *h > return sta_id; > return priv->hw_setting.bcast_sta_id; > > - /* If this frame is part of a IBSS network, then we use the > - * target specific station id */ > + /* If this frame is going out to an IBSS network, find the station, > + * or create a new station table entry */ > case IEEE80211_IF_TYPE_IBSS: { > DECLARE_MAC_BUF(mac); > > + /* Create new station table entry */ > sta_id = iwl3945_hw_find_station(priv, hdr->addr1); > if (sta_id != IWL_INVALID_STATION) > return sta_id; > @@ -2746,6 +2809,8 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, > spin_unlock_irqrestore(&priv->lock, flags); > > hdr_len = ieee80211_get_hdrlen(fc); > + > + /* Find (or create) index into station table for destination station */ > sta_id = iwl3945_get_sta_id(priv, hdr); > if (sta_id == IWL_INVALID_STATION) { > DECLARE_MAC_BUF(mac); > @@ -2767,30 +2832,52 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, > __constant_cpu_to_le16(IEEE80211_SCTL_FRAG)); > seq_number += 0x10; > } > + > + /* Descriptor for chosen Tx queue */ > txq = &priv->txq[txq_id]; > q = &txq->q; > > spin_lock_irqsave(&priv->lock, flags); > > + /* Set up first empty TFD within this queue's circular TFD buffer */ > tfd = &txq->bd[q->write_ptr]; > memset(tfd, 0, sizeof(*tfd)); > control_flags = (u32 *) tfd; > idx = get_cmd_index(q, q->write_ptr, 0); > > + /* Set up driver data for this TFD */ > memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl3945_tx_info)); > txq->txb[q->write_ptr].skb[0] = skb; > memcpy(&(txq->txb[q->write_ptr].status.control), > ctl, sizeof(struct ieee80211_tx_control)); > + > + /* Init first empty entry in queue's array of Tx/cmd buffers */ > out_cmd = &txq->cmd[idx]; > memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr)); > memset(&out_cmd->cmd.tx, 0, sizeof(out_cmd->cmd.tx)); > + > + /* > + * Set up the Tx-command (not MAC!) header. > + * Store the chosen Tx queue and TFD index within the sequence field; > + * after Tx, uCode's Tx response will return this value so driver can > + * locate the frame within the tx queue and do post-tx processing. > + */ > out_cmd->hdr.cmd = REPLY_TX; > out_cmd->hdr.sequence = cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) | > INDEX_TO_SEQ(q->write_ptr))); > - /* copy frags header */ > + > + /* Copy MAC header from skb into command buffer */ > memcpy(out_cmd->cmd.tx.hdr, hdr, hdr_len); > > - /* hdr = (struct ieee80211_hdr *)out_cmd->cmd.tx.hdr; */ > + /* > + * Use the first empty entry in this queue's command buffer array > + * to contain the Tx command and MAC header concatenated together > + * (payload data will be in another buffer). > + * Size of this varies, due to varying MAC header length. > + * If end is not dword aligned, we'll have 2 extra bytes at the end > + * of the MAC header (device reads on dword boundaries). > + * We'll tell device about this padding later. > + */ > len = priv->hw_setting.tx_cmd_len + > sizeof(struct iwl3945_cmd_header) + hdr_len; > > @@ -2802,15 +2889,20 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, > else > len_org = 0; > > + /* Physical address of this Tx command's header (not MAC header!), > + * within command buffer array. */ > txcmd_phys = txq->dma_addr_cmd + sizeof(struct iwl3945_cmd) * idx + > offsetof(struct iwl3945_cmd, hdr); > > + /* Add buffer containing Tx command and MAC(!) header to TFD's > + * first entry */ > iwl3945_hw_txq_attach_buf_to_tfd(priv, tfd, txcmd_phys, len); > > if (!(ctl->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT)) > iwl3945_build_tx_cmd_hwcrypto(priv, ctl, out_cmd, skb, 0); > > - /* 802.11 null functions have no payload... */ > + /* Set up TFD's 2nd entry to point directly to remainder of skb, > + * if any (802.11 null frames have no payload). */ > len = skb->len - hdr_len; > if (len) { > phys_addr = pci_map_single(priv->pci_dev, skb->data + hdr_len, > @@ -2818,13 +2910,16 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, > iwl3945_hw_txq_attach_buf_to_tfd(priv, tfd, phys_addr, len); > } > > - /* If there is no payload, then only one TFD is used */ > if (!len) > + /* If there is no payload, then we use only one Tx buffer */ > *control_flags = TFD_CTL_COUNT_SET(1); > else > + /* Else use 2 buffers. > + * Tell 3945 about any padding after MAC header */ > *control_flags = TFD_CTL_COUNT_SET(2) | > TFD_CTL_PAD_SET(U32_PAD(len)); > > + /* Total # bytes to be transmitted */ > len = (u16)skb->len; > out_cmd->cmd.tx.len = cpu_to_le16(len); > > @@ -2854,6 +2949,7 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, > iwl3945_print_hex_dump(IWL_DL_TX, (u8 *)out_cmd->cmd.tx.hdr, > ieee80211_get_hdrlen(fc)); > > + /* Tell device the write index *just past* this latest filled TFD */ > q->write_ptr = iwl3945_queue_inc_wrap(q->write_ptr, q->n_bd); > rc = iwl3945_tx_queue_update_write_ptr(priv, txq); > spin_unlock_irqrestore(&priv->lock, flags); > @@ -3325,11 +3421,11 @@ static void iwl3945_txstatus_to_ieee(struct iwl3945_priv *priv, > } > > /** > - * iwl3945_tx_queue_reclaim - Reclaim Tx queue entries no more used by NIC. > + * iwl3945_tx_queue_reclaim - Reclaim Tx queue entries already Tx'd > * > - * When FW advances 'R' index, all entries between old and > - * new 'R' index need to be reclaimed. As result, some free space > - * forms. If there is enough free space (> low mark), wake Tx queue. > + * When FW advances 'R' index, all entries between old and new 'R' index > + * need to be reclaimed. As result, some free space forms. If there is > + * enough free space (> low mark), wake the stack that feeds us. > */ > static int iwl3945_tx_queue_reclaim(struct iwl3945_priv *priv, int txq_id, int index) > { > @@ -3378,6 +3474,9 @@ static int iwl3945_is_tx_success(u32 status) > * Generic RX handler implementations > * > ******************************************************************************/ > +/** > + * iwl3945_rx_reply_tx - Handle Tx response > + */ > static void iwl3945_rx_reply_tx(struct iwl3945_priv *priv, > struct iwl3945_rx_mem_buffer *rxb) > { > @@ -3913,6 +4012,7 @@ int iwl3945_rx_queue_update_write_ptr(struct iwl3945_priv *priv, struct iwl3945_ > if (q->need_update == 0) > goto exit_unlock; > > + /* If power-saving is in use, make sure device is awake */ > if (test_bit(STATUS_POWER_PMI, &priv->status)) { > reg = iwl3945_read32(priv, CSR_UCODE_DRV_GP1); > > @@ -3926,10 +4026,14 @@ int iwl3945_rx_queue_update_write_ptr(struct iwl3945_priv *priv, struct iwl3945_ > if (rc) > goto exit_unlock; > > + /* Device expects a multiple of 8 */ > iwl3945_write_direct32(priv, FH_RSCSR_CHNL0_WPTR, > q->write & ~0x7); > iwl3945_release_nic_access(priv); > + > + /* Else device is assumed to be awake */ > } else > + /* Device expects a multiple of 8 */ > iwl3945_write32(priv, FH_RSCSR_CHNL0_WPTR, q->write & ~0x7); > > > @@ -3971,9 +4075,12 @@ static int iwl3945_rx_queue_restock(struct iwl3945_priv *priv) > spin_lock_irqsave(&rxq->lock, flags); > write = rxq->write & ~0x7; > while ((iwl3945_rx_queue_space(rxq) > 0) && (rxq->free_count)) { > + /* Get next free Rx buffer, remove from free list */ > element = rxq->rx_free.next; > rxb = list_entry(element, struct iwl3945_rx_mem_buffer, list); > list_del(element); > + > + /* Point to Rx buffer via next RBD in circular buffer */ > rxq->bd[rxq->write] = iwl3945_dma_addr2rbd_ptr(priv, rxb->dma_addr); > rxq->queue[rxq->write] = rxb; > rxq->write = (rxq->write + 1) & RX_QUEUE_MASK; > @@ -3986,7 +4093,8 @@ static int iwl3945_rx_queue_restock(struct iwl3945_priv *priv) > queue_work(priv->workqueue, &priv->rx_replenish); > > > - /* If we've added more space for the firmware to place data, tell it */ > + /* If we've added more space for the firmware to place data, tell it. > + * Increment device's write pointer in multiples of 8. */ > if ((write != (rxq->write & ~0x7)) > || (abs(rxq->write - rxq->read) > 7)) { > spin_lock_irqsave(&rxq->lock, flags); > @@ -4019,6 +4127,8 @@ void iwl3945_rx_replenish(void *data) > while (!list_empty(&rxq->rx_used)) { > element = rxq->rx_used.next; > rxb = list_entry(element, struct iwl3945_rx_mem_buffer, list); > + > + /* Alloc a new receive buffer */ > rxb->skb = > alloc_skb(IWL_RX_BUF_SIZE, __GFP_NOWARN | GFP_ATOMIC); > if (!rxb->skb) { > @@ -4032,6 +4142,8 @@ void iwl3945_rx_replenish(void *data) > } > priv->alloc_rxb_skb++; > list_del(element); > + > + /* Get physical address of RB/SKB */ > rxb->dma_addr = > pci_map_single(priv->pci_dev, rxb->skb->data, > IWL_RX_BUF_SIZE, PCI_DMA_FROMDEVICE); > @@ -4076,12 +4188,16 @@ int iwl3945_rx_queue_alloc(struct iwl3945_priv *priv) > spin_lock_init(&rxq->lock); > INIT_LIST_HEAD(&rxq->rx_free); > INIT_LIST_HEAD(&rxq->rx_used); > + > + /* Alloc the circular buffer of Read Buffer Descriptors (RBDs) */ > rxq->bd = pci_alloc_consistent(dev, 4 * RX_QUEUE_SIZE, &rxq->dma_addr); > if (!rxq->bd) > return -ENOMEM; > + > /* Fill the rx_used queue with _all_ of the Rx buffers */ > for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) > list_add_tail(&rxq->pool[i].list, &rxq->rx_used); > + > /* Set us so that we have processed and used all buffers, but have > * not restocked the Rx queue with fresh buffers */ > rxq->read = rxq->write = 0; > @@ -4213,6 +4329,8 @@ static void iwl3945_rx_handle(struct iwl3945_priv *priv) > int reclaim; > unsigned long flags; > > + /* uCode's read index (stored in shared DRAM) indicates the last Rx > + * buffer that the driver may process (last buffer filled by ucode). */ > r = iwl3945_hw_get_rx_read(priv); > i = rxq->read; > > @@ -4293,6 +4411,9 @@ static void iwl3945_rx_handle(struct iwl3945_priv *priv) > iwl3945_rx_queue_restock(priv); > } > > +/** > + * iwl3945_tx_queue_update_write_ptr - Send new write index to hardware > + */ > static int iwl3945_tx_queue_update_write_ptr(struct iwl3945_priv *priv, > struct iwl3945_tx_queue *txq) > { > @@ -4920,6 +5041,11 @@ static void iwl3945_init_band_reference(const struct iwl3945_priv *priv, int ban > } > } > > +/** > + * iwl3945_get_channel_info - Find driver's private channel info > + * > + * Based on band and channel number. > + */ > const struct iwl3945_channel_info *iwl3945_get_channel_info(const struct iwl3945_priv *priv, > int phymode, u16 channel) > { > @@ -4947,6 +5073,9 @@ const struct iwl3945_channel_info *iwl3945_get_channel_info(const struct iwl3945 > #define CHECK_AND_PRINT(x) ((eeprom_ch_info[ch].flags & EEPROM_CHANNEL_##x) \ > ? # x " " : "") > > +/** > + * iwl3945_init_channel_map - Set up driver's info for all possible channels > + */ > static int iwl3945_init_channel_map(struct iwl3945_priv *priv) > { > int eeprom_ch_count = 0; > @@ -5056,6 +5185,7 @@ static int iwl3945_init_channel_map(struct iwl3945_priv *priv) > } > } > > + /* Set up txpower settings in driver for all channels */ > if (iwl3945_txpower_set_from_eeprom(priv)) > return -EIO; > > @@ -8273,6 +8403,8 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e > struct ieee80211_hw *hw; > int i; > > + /* Disabling hardware scan means that mac80211 will perform scans > + * "the hard way", rather than using device's scan. */ > if (iwl3945_param_disable_hw_scan) { > IWL_DEBUG_INFO("Disabling hw_scan\n"); > iwl3945_hw_ops.hw_scan = NULL; > @@ -8303,6 +8435,8 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e > priv->hw = hw; > > priv->pci_dev = pdev; > + > + /* Select antenna (may be helpful if only one antenna is connected) */ > priv->antenna = (enum iwl3945_antenna)iwl3945_param_antenna; > #ifdef CONFIG_IWL3945_DEBUG > iwl3945_debug_level = iwl3945_param_debug; > @@ -8324,6 +8458,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e > /* Tell mac80211 our Tx characteristics */ > hw->flags = IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE; > > + /* 4 EDCA QOS priorities */ > hw->queues = 4; > > spin_lock_init(&priv->lock); > @@ -8344,6 +8479,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e > > pci_set_master(pdev); > > + /* Clear the driver's (not device's) station table */ > iwl3945_clear_stations_table(priv); > > priv->data_retry_limit = -1; > @@ -8363,9 +8499,11 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e > err = pci_request_regions(pdev, DRV_NAME); > if (err) > goto out_pci_disable_device; > + > /* We disable the RETRY_TIMEOUT register (0x41) to keep > * PCI Tx retries from interfering with C3 CPU state */ > pci_write_config_byte(pdev, 0x41, 0x00); > + > priv->hw_base = pci_iomap(pdev, 0, 0); > if (!priv->hw_base) { > err = -ENODEV; > @@ -8378,6 +8516,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e > > /* Initialize module parameter values here */ > > + /* Disable radio (SW RF KILL) via parameter when loading driver */ > if (iwl3945_param_disable) { > set_bit(STATUS_RF_KILL_SW, &priv->status); > IWL_DEBUG_INFO("Radio disabled.\n"); > diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c > index a840d5d..01ba374 100644 > --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c > +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c > @@ -63,13 +63,13 @@ static int iwl4965_tx_queue_update_write_ptr(struct iwl4965_priv *priv, > ******************************************************************************/ > > /* module parameters */ > -static int iwl4965_param_disable_hw_scan; > -static int iwl4965_param_debug; > +static int iwl4965_param_disable_hw_scan; /* def: 0 = use 4965's h/w scan */ > +static int iwl4965_param_debug; /* def: 0 = minimal debug log messages */ > static int iwl4965_param_disable; /* def: enable radio */ > static int iwl4965_param_antenna; /* def: 0 = both antennas (use diversity) */ > int iwl4965_param_hwcrypto; /* def: using software encryption */ > -static int iwl4965_param_qos_enable = 1; > -int iwl4965_param_queues_num = IWL_MAX_NUM_QUEUES; > +static int iwl4965_param_qos_enable = 1; /* def: 1 = use quality of service */ > +int iwl4965_param_queues_num = IWL_MAX_NUM_QUEUES; /* def: 16 Tx queues */ > > /* > * module name, copyright, version, etc. > @@ -183,17 +183,24 @@ static void iwl4965_print_hex_dump(int level, void *p, u32 len) > * > * Theory of operation > * > - * A queue is a circular buffers with 'Read' and 'Write' pointers. > - * 2 empty entries always kept in the buffer to protect from overflow. > + * A Tx or Rx queue resides in host DRAM, and is comprised of a circular buffer > + * of buffer descriptors, each of which points to one or more data buffers for > + * the device to read from or fill. Driver and device exchange status of each > + * queue via "read" and "write" pointers. Driver keeps minimum of 2 empty > + * entries in each circular buffer, to protect against confusing empty and full > + * queue states. > + * > + * The device reads or writes the data in the queues via the device's several > + * DMA/FIFO channels. Each queue is mapped to a single DMA channel. > * > * For Tx queue, there are low mark and high mark limits. If, after queuing > * the packet for Tx, free space become < low mark, Tx queue stopped. When > * reclaiming packets (on 'tx done IRQ), if free space become > high mark, > * Tx queue resumed. > * > - * The IWL operates with six queues, one receive queue in the device's > - * sram, one transmit queue for sending commands to the device firmware, > - * and four transmit queues for data. > + * The 4965 operates with up to 17 queues: One receive queue, one transmit > + * queue (#4) for sending commands to the device firmware, and 15 other > + * Tx queues that may be mapped to prioritized Tx DMA/FIFO channels. > ***************************************************/ > > static int iwl4965_queue_space(const struct iwl4965_queue *q) > @@ -212,13 +219,21 @@ static int iwl4965_queue_space(const struct iwl4965_queue *q) > return s; > } > > -/* XXX: n_bd must be power-of-two size */ > +/** > + * iwl4965_queue_inc_wrap - increment queue index, wrap back to beginning > + * @index -- current index > + * @n_bd -- total number of entries in queue (must be power of 2) > + */ > static inline int iwl4965_queue_inc_wrap(int index, int n_bd) > { > return ++index & (n_bd - 1); > } > > -/* XXX: n_bd must be power-of-two size */ > +/** > + * iwl4965_queue_dec_wrap - decrement queue index, wrap back to end > + * @index -- current index > + * @n_bd -- total number of entries in queue (must be power of 2) > + */ > static inline int iwl4965_queue_dec_wrap(int index, int n_bd) > { > return --index & (n_bd - 1); > @@ -233,12 +248,17 @@ static inline int x2_queue_used(const struct iwl4965_queue *q, int i) > > static inline u8 get_cmd_index(struct iwl4965_queue *q, u32 index, int is_huge) > { > + /* This is for scan command, the big buffer at end of command array */ > if (is_huge) > - return q->n_window; > + return q->n_window; /* must be power of 2 */ > > + /* Otherwise, use normal size buffers */ > return index & (q->n_window - 1); > } > > +/** > + * iwl4965_queue_init - Initialize queue's high/low-water and read/write indexes > + */ > static int iwl4965_queue_init(struct iwl4965_priv *priv, struct iwl4965_queue *q, > int count, int slots_num, u32 id) > { > @@ -267,11 +287,16 @@ static int iwl4965_queue_init(struct iwl4965_priv *priv, struct iwl4965_queue *q > return 0; > } > > +/** > + * iwl4965_tx_queue_alloc - Alloc driver data and TFD CB for one Tx/cmd queue > + */ > static int iwl4965_tx_queue_alloc(struct iwl4965_priv *priv, > struct iwl4965_tx_queue *txq, u32 id) > { > struct pci_dev *dev = priv->pci_dev; > > + /* Driver private data, only for Tx (not command) queues, > + * not shared with device. */ > if (id != IWL_CMD_QUEUE_NUM) { > txq->txb = kmalloc(sizeof(txq->txb[0]) * > TFD_QUEUE_SIZE_MAX, GFP_KERNEL); > @@ -283,6 +308,8 @@ static int iwl4965_tx_queue_alloc(struct iwl4965_priv *priv, > } else > txq->txb = NULL; > > + /* Circular buffer of transmit frame descriptors (TFDs), > + * shared with device */ > txq->bd = pci_alloc_consistent(dev, > sizeof(txq->bd[0]) * TFD_QUEUE_SIZE_MAX, > &txq->q.dma_addr); > @@ -320,7 +347,7 @@ int iwl4965_tx_queue_init(struct iwl4965_priv *priv, > * For the command queue (#4), allocate command space + one big > * command for scan, since scan command is very huge; the system will > * not have two scans at the same time, so only one is needed. > - * For normal Tx queues (all other queues), no super-size command > + * For data Tx queues (all other queues), no super-size command > * space is needed. > */ > len = sizeof(struct iwl4965_cmd) * slots_num; > @@ -357,8 +384,8 @@ int iwl4965_tx_queue_init(struct iwl4965_priv *priv, > * @txq: Transmit queue to deallocate. > * > * Empty queue by removing and destroying all BD's. > - * Free all buffers. txq itself is not freed. > - * > + * Free all buffers. > + * 0-fill, but do not free "txq" descriptor structure. > */ > void iwl4965_tx_queue_free(struct iwl4965_priv *priv, struct iwl4965_tx_queue *txq) > { > @@ -378,19 +405,21 @@ void iwl4965_tx_queue_free(struct iwl4965_priv *priv, struct iwl4965_tx_queue *t > if (q->id == IWL_CMD_QUEUE_NUM) > len += IWL_MAX_SCAN_SIZE; > > + /* De-alloc array of command/tx buffers */ > pci_free_consistent(dev, len, txq->cmd, txq->dma_addr_cmd); > > - /* free buffers belonging to queue itself */ > + /* De-alloc circular buffer of TFDs */ > if (txq->q.n_bd) > pci_free_consistent(dev, sizeof(struct iwl4965_tfd_frame) * > txq->q.n_bd, txq->bd, txq->q.dma_addr); > > + /* De-alloc array of per-TFD driver data */ > if (txq->txb) { > kfree(txq->txb); > txq->txb = NULL; > } > > - /* 0 fill whole structure */ > + /* 0-fill queue descriptor structure */ > memset(txq, 0, sizeof(*txq)); > } > > @@ -404,6 +433,11 @@ const u8 iwl4965_broadcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF > /**************************************************************/ > > #if 0 /* temporary disable till we add real remove station */ > +/** > + * iwl4965_remove_station - Remove driver's knowledge of station. > + * > + * NOTE: This does not remove station from device's station table. > + */ > static u8 iwl4965_remove_station(struct iwl4965_priv *priv, const u8 *addr, int is_ap) > { > int index = IWL_INVALID_STATION; > @@ -441,6 +475,11 @@ out: > } > #endif > > +/** > + * iwl4965_clear_stations_table - Clear the driver's station table > + * > + * NOTE: This does not clear or otherwise alter the device's station table. > + */ > static void iwl4965_clear_stations_table(struct iwl4965_priv *priv) > { > unsigned long flags; > @@ -453,6 +492,9 @@ static void iwl4965_clear_stations_table(struct iwl4965_priv *priv) > spin_unlock_irqrestore(&priv->sta_lock, flags); > } > > +/** > + * iwl4965_add_station_flags - Add station to tables in driver and device > + */ > u8 iwl4965_add_station_flags(struct iwl4965_priv *priv, const u8 *addr, int is_ap, u8 flags) > { > int i; > @@ -499,6 +541,7 @@ u8 iwl4965_add_station_flags(struct iwl4965_priv *priv, const u8 *addr, int is_a > station->used = 1; > priv->num_stations++; > > + /* Set up the REPLY_ADD_STA command to send to device */ > memset(&station->sta, 0, sizeof(struct iwl4965_addsta_cmd)); > memcpy(station->sta.sta.addr, addr, ETH_ALEN); > station->sta.mode = 0; > @@ -513,6 +556,8 @@ u8 iwl4965_add_station_flags(struct iwl4965_priv *priv, const u8 *addr, int is_a > #endif /*CONFIG_IWL4965_HT*/ > > spin_unlock_irqrestore(&priv->sta_lock, flags_spin); > + > + /* Add station to device's station table */ > iwl4965_send_add_station(priv, &station->sta, flags); > return index; > > @@ -682,7 +727,11 @@ static int iwl4965_enqueue_hcmd(struct iwl4965_priv *priv, struct iwl4965_host_c > fix_size, q->write_ptr, idx, IWL_CMD_QUEUE_NUM); > > txq->need_update = 1; > + > + /* Set up entry in queue's byte count circular buffer */ > ret = iwl4965_tx_queue_update_wr_ptr(priv, txq, 0); > + > + /* Increment and update queue's write index */ > q->write_ptr = iwl4965_queue_inc_wrap(q->write_ptr, q->n_bd); > iwl4965_tx_queue_update_write_ptr(priv, txq); > > @@ -848,7 +897,10 @@ static int iwl4965_rxon_add_station(struct iwl4965_priv *priv, > { > u8 sta_id; > > + /* Add station to device's station table */ > sta_id = iwl4965_add_station_flags(priv, addr, is_ap, 0); > + > + /* Set up default rate scaling table in device's station table */ > iwl4965_add_station(priv, addr, is_ap); > > return sta_id; > @@ -1574,7 +1626,7 @@ static void get_eeprom_mac(struct iwl4965_priv *priv, u8 *mac) > /** > * iwl4965_eeprom_init - read EEPROM contents > * > - * Load the EEPROM from adapter into priv->eeprom > + * Load the EEPROM contents from adapter into priv->eeprom > * > * NOTE: This routine uses the non-debug IO access functions. > */ > @@ -1599,6 +1651,7 @@ int iwl4965_eeprom_init(struct iwl4965_priv *priv) > return -ENOENT; > } > > + /* Make sure driver (instead of uCode) is allowed to read EEPROM */ > rc = iwl4965_eeprom_acquire_semaphore(priv); > if (rc < 0) { > IWL_ERROR("Failed to acquire EEPROM semaphore.\n"); > @@ -2739,6 +2792,11 @@ static void iwl4965_build_tx_cmd_basic(struct iwl4965_priv *priv, > cmd->cmd.tx.next_frame_len = 0; > } > > +/** > + * iwl4965_get_sta_id - Find station's index within station table > + * > + * If new IBSS station, create new entry in station table > + */ > static int iwl4965_get_sta_id(struct iwl4965_priv *priv, > struct ieee80211_hdr *hdr) > { > @@ -2746,16 +2804,15 @@ static int iwl4965_get_sta_id(struct iwl4965_priv *priv, > u16 fc = le16_to_cpu(hdr->frame_control); > DECLARE_MAC_BUF(mac); > > - /* If this frame is broadcast or not data then use the broadcast > - * station id */ > + /* If this frame is broadcast or management, use broadcast station id */ > if (((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA) || > is_multicast_ether_addr(hdr->addr1)) > return priv->hw_setting.bcast_sta_id; > > switch (priv->iw_mode) { > > - /* If this frame is part of a BSS network (we're a station), then > - * we use the AP's station id */ > + /* If we are a client station in a BSS network, use the special > + * AP station entry (that's the only station we communicate with) */ > case IEEE80211_IF_TYPE_STA: > return IWL_AP_ID; > > @@ -2766,13 +2823,14 @@ static int iwl4965_get_sta_id(struct iwl4965_priv *priv, > return sta_id; > return priv->hw_setting.bcast_sta_id; > > - /* If this frame is part of a IBSS network, then we use the > - * target specific station id */ > + /* If this frame is going out to an IBSS network, find the station, > + * or create a new station table entry */ > case IEEE80211_IF_TYPE_IBSS: > sta_id = iwl4965_hw_find_station(priv, hdr->addr1); > if (sta_id != IWL_INVALID_STATION) > return sta_id; > > + /* Create new station table entry */ > sta_id = iwl4965_add_station_flags(priv, hdr->addr1, 0, CMD_ASYNC); > > if (sta_id != IWL_INVALID_STATION) > @@ -2854,6 +2912,8 @@ static int iwl4965_tx_skb(struct iwl4965_priv *priv, > spin_unlock_irqrestore(&priv->lock, flags); > > hdr_len = ieee80211_get_hdrlen(fc); > + > + /* Find (or create) index into station table for destination station */ > sta_id = iwl4965_get_sta_id(priv, hdr); > if (sta_id == IWL_INVALID_STATION) { > DECLARE_MAC_BUF(mac); > @@ -2882,30 +2942,52 @@ static int iwl4965_tx_skb(struct iwl4965_priv *priv, > #endif /* CONFIG_IWL4965_HT_AGG */ > #endif /* CONFIG_IWL4965_HT */ > } > + > + /* Descriptor for chosen Tx queue */ > txq = &priv->txq[txq_id]; > q = &txq->q; > > spin_lock_irqsave(&priv->lock, flags); > > + /* Set up first empty TFD within this queue's circular TFD buffer */ > tfd = &txq->bd[q->write_ptr]; > memset(tfd, 0, sizeof(*tfd)); > control_flags = (u32 *) tfd; > idx = get_cmd_index(q, q->write_ptr, 0); > > + /* Set up driver data for this TFD */ > memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl4965_tx_info)); > txq->txb[q->write_ptr].skb[0] = skb; > memcpy(&(txq->txb[q->write_ptr].status.control), > ctl, sizeof(struct ieee80211_tx_control)); > + > + /* Set up first empty entry in queue's array of Tx/cmd buffers */ > out_cmd = &txq->cmd[idx]; > memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr)); > memset(&out_cmd->cmd.tx, 0, sizeof(out_cmd->cmd.tx)); > + > + /* > + * Set up the Tx-command (not MAC!) header. > + * Store the chosen Tx queue and TFD index within the sequence field; > + * after Tx, uCode's Tx response will return this value so driver can > + * locate the frame within the tx queue and do post-tx processing. > + */ > out_cmd->hdr.cmd = REPLY_TX; > out_cmd->hdr.sequence = cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) | > INDEX_TO_SEQ(q->write_ptr))); > - /* copy frags header */ > + > + /* Copy MAC header from skb into command buffer */ > memcpy(out_cmd->cmd.tx.hdr, hdr, hdr_len); > > - /* hdr = (struct ieee80211_hdr *)out_cmd->cmd.tx.hdr; */ > + /* > + * Use the first empty entry in this queue's command buffer array > + * to contain the Tx command and MAC header concatenated together > + * (payload data will be in another buffer). > + * Size of this varies, due to varying MAC header length. > + * If end is not dword aligned, we'll have 2 extra bytes at the end > + * of the MAC header (device reads on dword boundaries). > + * We'll tell device about this padding later. > + */ > len = priv->hw_setting.tx_cmd_len + > sizeof(struct iwl4965_cmd_header) + hdr_len; > > @@ -2917,15 +2999,20 @@ static int iwl4965_tx_skb(struct iwl4965_priv *priv, > else > len_org = 0; > > + /* Physical address of this Tx command's header (not MAC header!), > + * within command buffer array. */ > txcmd_phys = txq->dma_addr_cmd + sizeof(struct iwl4965_cmd) * idx + > offsetof(struct iwl4965_cmd, hdr); > > + /* Add buffer containing Tx command and MAC(!) header to TFD's > + * first entry */ > iwl4965_hw_txq_attach_buf_to_tfd(priv, tfd, txcmd_phys, len); > > if (!(ctl->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT)) > iwl4965_build_tx_cmd_hwcrypto(priv, ctl, out_cmd, skb, 0); > > - /* 802.11 null functions have no payload... */ > + /* Set up TFD's 2nd entry to point directly to remainder of skb, > + * if any (802.11 null frames have no payload). */ > len = skb->len - hdr_len; > if (len) { > phys_addr = pci_map_single(priv->pci_dev, skb->data + hdr_len, > @@ -2933,9 +3020,11 @@ static int iwl4965_tx_skb(struct iwl4965_priv *priv, > iwl4965_hw_txq_attach_buf_to_tfd(priv, tfd, phys_addr, len); > } > > + /* Tell 4965 about any 2-byte padding after MAC header */ > if (len_org) > out_cmd->cmd.tx.tx_flags |= TX_CMD_FLG_MH_PAD_MSK; > > + /* Total # bytes to be transmitted */ > len = (u16)skb->len; > out_cmd->cmd.tx.len = cpu_to_le16(len); > > @@ -2965,8 +3054,10 @@ static int iwl4965_tx_skb(struct iwl4965_priv *priv, > iwl4965_print_hex_dump(IWL_DL_TX, (u8 *)out_cmd->cmd.tx.hdr, > ieee80211_get_hdrlen(fc)); > > + /* Set up entry for this TFD in Tx byte-count array */ > iwl4965_tx_queue_update_wr_ptr(priv, txq, len); > > + /* Tell device the write index *just past* this latest filled TFD */ > q->write_ptr = iwl4965_queue_inc_wrap(q->write_ptr, q->n_bd); > rc = iwl4965_tx_queue_update_write_ptr(priv, txq); > spin_unlock_irqrestore(&priv->lock, flags); > @@ -3439,11 +3530,11 @@ static void iwl4965_txstatus_to_ieee(struct iwl4965_priv *priv, > } > > /** > - * iwl4965_tx_queue_reclaim - Reclaim Tx queue entries no more used by NIC. > + * iwl4965_tx_queue_reclaim - Reclaim Tx queue entries already Tx'd > * > - * When FW advances 'R' index, all entries between old and > - * new 'R' index need to be reclaimed. As result, some free space > - * forms. If there is enough free space (> low mark), wake Tx queue. > + * When FW advances 'R' index, all entries between old and new 'R' index > + * need to be reclaimed. As result, some free space forms. If there is > + * enough free space (> low mark), wake the stack that feeds us. > */ > int iwl4965_tx_queue_reclaim(struct iwl4965_priv *priv, int txq_id, int index) > { > @@ -3524,6 +3615,10 @@ static inline u32 iwl4965_get_scd_ssn(struct iwl4965_tx_resp *tx_resp) > return le32_to_cpu(*scd_ssn) & MAX_SN; > > } > + > +/** > + * iwl4965_tx_status_reply_tx - Handle Tx rspnse for frames in aggregation queue > + */ > static int iwl4965_tx_status_reply_tx(struct iwl4965_priv *priv, > struct iwl4965_ht_agg *agg, > struct iwl4965_tx_resp *tx_resp, > @@ -3538,14 +3633,16 @@ static int iwl4965_tx_status_reply_tx(struct iwl4965_priv *priv, > u16 seq; > > if (agg->wait_for_ba) > - IWL_DEBUG_TX_REPLY("got tx repsons w/o back\n"); > + IWL_DEBUG_TX_REPLY("got tx response w/o block-ack\n"); > > agg->frame_count = tx_resp->frame_count; > agg->start_idx = start_idx; > agg->rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags); > agg->bitmap0 = agg->bitmap1 = 0; > > + /* # frames attempted by Tx command */ > if (agg->frame_count == 1) { > + /* Only one frame was attempted; no block-ack will arrive */ > struct iwl4965_tx_queue *txq ; > status = le32_to_cpu(frame_status[0]); > > @@ -3574,9 +3671,11 @@ static int iwl4965_tx_status_reply_tx(struct iwl4965_priv *priv, > > agg->wait_for_ba = 0; > } else { > + /* Two or more frames were attempted; expect block-ack */ > u64 bitmap = 0; > int start = agg->start_idx; > > + /* Construct bit-map of pending frames within Tx window */ > for (i = 0; i < agg->frame_count; i++) { > u16 sc; > status = le32_to_cpu(frame_status[i]); > @@ -3640,6 +3739,9 @@ static int iwl4965_tx_status_reply_tx(struct iwl4965_priv *priv, > #endif > #endif > > +/** > + * iwl4965_rx_reply_tx - Handle standard (non-aggregation) Tx response > + */ > static void iwl4965_rx_reply_tx(struct iwl4965_priv *priv, > struct iwl4965_rx_mem_buffer *rxb) > { > @@ -4261,6 +4363,7 @@ int iwl4965_rx_queue_update_write_ptr(struct iwl4965_priv *priv, struct iwl4965_ > if (q->need_update == 0) > goto exit_unlock; > > + /* If power-saving is in use, make sure device is awake */ > if (test_bit(STATUS_POWER_PMI, &priv->status)) { > reg = iwl4965_read32(priv, CSR_UCODE_DRV_GP1); > > @@ -4274,10 +4377,14 @@ int iwl4965_rx_queue_update_write_ptr(struct iwl4965_priv *priv, struct iwl4965_ > if (rc) > goto exit_unlock; > > + /* Device expects a multiple of 8 */ > iwl4965_write_direct32(priv, FH_RSCSR_CHNL0_WPTR, > q->write & ~0x7); > iwl4965_release_nic_access(priv); > + > + /* Else device is assumed to be awake */ > } else > + /* Device expects a multiple of 8 */ > iwl4965_write32(priv, FH_RSCSR_CHNL0_WPTR, q->write & ~0x7); > > > @@ -4320,9 +4427,12 @@ static int iwl4965_rx_queue_restock(struct iwl4965_priv *priv) > spin_lock_irqsave(&rxq->lock, flags); > write = rxq->write & ~0x7; > while ((iwl4965_rx_queue_space(rxq) > 0) && (rxq->free_count)) { > + /* Get next free Rx buffer, remove from free list */ > element = rxq->rx_free.next; > rxb = list_entry(element, struct iwl4965_rx_mem_buffer, list); > list_del(element); > + > + /* Point to Rx buffer via next RBD in circular buffer */ > rxq->bd[rxq->write] = iwl4965_dma_addr2rbd_ptr(priv, rxb->dma_addr); > rxq->queue[rxq->write] = rxb; > rxq->write = (rxq->write + 1) & RX_QUEUE_MASK; > @@ -4335,7 +4445,8 @@ static int iwl4965_rx_queue_restock(struct iwl4965_priv *priv) > queue_work(priv->workqueue, &priv->rx_replenish); > > > - /* If we've added more space for the firmware to place data, tell it */ > + /* If we've added more space for the firmware to place data, tell it. > + * Increment device's write pointer in multiples of 8. */ > if ((write != (rxq->write & ~0x7)) > || (abs(rxq->write - rxq->read) > 7)) { > spin_lock_irqsave(&rxq->lock, flags); > @@ -4368,6 +4479,8 @@ void iwl4965_rx_replenish(void *data) > while (!list_empty(&rxq->rx_used)) { > element = rxq->rx_used.next; > rxb = list_entry(element, struct iwl4965_rx_mem_buffer, list); > + > + /* Alloc a new receive buffer */ > rxb->skb = > alloc_skb(IWL_RX_BUF_SIZE, __GFP_NOWARN | GFP_ATOMIC); > if (!rxb->skb) { > @@ -4381,6 +4494,8 @@ void iwl4965_rx_replenish(void *data) > } > priv->alloc_rxb_skb++; > list_del(element); > + > + /* Get physical address of RB/SKB */ > rxb->dma_addr = > pci_map_single(priv->pci_dev, rxb->skb->data, > IWL_RX_BUF_SIZE, PCI_DMA_FROMDEVICE); > @@ -4425,12 +4540,16 @@ int iwl4965_rx_queue_alloc(struct iwl4965_priv *priv) > spin_lock_init(&rxq->lock); > INIT_LIST_HEAD(&rxq->rx_free); > INIT_LIST_HEAD(&rxq->rx_used); > + > + /* Alloc the circular buffer of Read Buffer Descriptors (RBDs) */ > rxq->bd = pci_alloc_consistent(dev, 4 * RX_QUEUE_SIZE, &rxq->dma_addr); > if (!rxq->bd) > return -ENOMEM; > + > /* Fill the rx_used queue with _all_ of the Rx buffers */ > for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) > list_add_tail(&rxq->pool[i].list, &rxq->rx_used); > + > /* Set us so that we have processed and used all buffers, but have > * not restocked the Rx queue with fresh buffers */ > rxq->read = rxq->write = 0; > @@ -4562,6 +4681,8 @@ static void iwl4965_rx_handle(struct iwl4965_priv *priv) > int reclaim; > unsigned long flags; > > + /* uCode's read index (stored in shared DRAM) indicates the last Rx > + * buffer that the driver may process (last buffer filled by ucode). */ > r = iwl4965_hw_get_rx_read(priv); > i = rxq->read; > > @@ -4645,6 +4766,9 @@ static void iwl4965_rx_handle(struct iwl4965_priv *priv) > iwl4965_rx_queue_restock(priv); > } > > +/** > + * iwl4965_tx_queue_update_write_ptr - Send new write index to hardware > + */ > static int iwl4965_tx_queue_update_write_ptr(struct iwl4965_priv *priv, > struct iwl4965_tx_queue *txq) > { > @@ -5276,6 +5400,11 @@ static void iwl4965_init_band_reference(const struct iwl4965_priv *priv, > } > } > > +/** > + * iwl4965_get_channel_info - Find driver's private channel info > + * > + * Based on band and channel number. > + */ > const struct iwl4965_channel_info *iwl4965_get_channel_info(const struct iwl4965_priv *priv, > int phymode, u16 channel) > { > @@ -5303,6 +5432,9 @@ const struct iwl4965_channel_info *iwl4965_get_channel_info(const struct iwl4965 > #define CHECK_AND_PRINT(x) ((eeprom_ch_info[ch].flags & EEPROM_CHANNEL_##x) \ > ? # x " " : "") > > +/** > + * iwl4965_init_channel_map - Set up driver's info for all possible channels > + */ > static int iwl4965_init_channel_map(struct iwl4965_priv *priv) > { > int eeprom_ch_count = 0; > @@ -5412,6 +5544,7 @@ static int iwl4965_init_channel_map(struct iwl4965_priv *priv) > } > } > > + /* Two additional EEPROM bands for 2.4 and 5 GHz FAT channels */ > for (band = 6; band <= 7; band++) { > int phymode; > u8 fat_extension_chan; > @@ -5419,7 +5552,9 @@ static int iwl4965_init_channel_map(struct iwl4965_priv *priv) > iwl4965_init_band_reference(priv, band, &eeprom_ch_count, > &eeprom_ch_info, &eeprom_ch_index); > > + /* EEPROM band 6 is 2.4, band 7 is 5 GHz */ > phymode = (band == 6) ? MODE_IEEE80211B : MODE_IEEE80211A; > + > /* Loop through each band adding each of the channels */ > for (ch = 0; ch < eeprom_ch_count; ch++) { > > @@ -5431,11 +5566,13 @@ static int iwl4965_init_channel_map(struct iwl4965_priv *priv) > else > fat_extension_chan = HT_IE_EXT_CHANNEL_ABOVE; > > + /* Set up driver's info for lower half */ > iwl4965_set_fat_chan_info(priv, phymode, > eeprom_ch_index[ch], > &(eeprom_ch_info[ch]), > fat_extension_chan); > > + /* Set up driver's info for upper half */ > iwl4965_set_fat_chan_info(priv, phymode, > (eeprom_ch_index[ch] + 4), > &(eeprom_ch_info[ch]), > @@ -8936,6 +9073,8 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e > struct ieee80211_hw *hw; > int i; > > + /* Disabling hardware scan means that mac80211 will perform scans > + * "the hard way", rather than using device's scan. */ > if (iwl4965_param_disable_hw_scan) { > IWL_DEBUG_INFO("Disabling hw_scan\n"); > iwl4965_hw_ops.hw_scan = NULL; > @@ -8987,9 +9126,11 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e > /* Tell mac80211 our Tx characteristics */ > hw->flags = IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE; > > + /* Default value; 4 EDCA QOS priorities */ > hw->queues = 4; > #ifdef CONFIG_IWL4965_HT > #ifdef CONFIG_IWL4965_HT_AGG > + /* Enhanced value; more queues, to support 11n aggregation */ > hw->queues = 16; > #endif /* CONFIG_IWL4965_HT_AGG */ > #endif /* CONFIG_IWL4965_HT */ > @@ -9013,6 +9154,7 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e > > pci_set_master(pdev); > > + /* Clear the driver's (not device's) station table */ > iwl4965_clear_stations_table(priv); > > priv->data_retry_limit = -1; > @@ -9032,9 +9174,11 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e > err = pci_request_regions(pdev, DRV_NAME); > if (err) > goto out_pci_disable_device; > + > /* We disable the RETRY_TIMEOUT register (0x41) to keep > * PCI Tx retries from interfering with C3 CPU state */ > pci_write_config_byte(pdev, 0x41, 0x00); > + > priv->hw_base = pci_iomap(pdev, 0, 0); > if (!priv->hw_base) { > err = -ENODEV; > @@ -9047,6 +9191,7 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e > > /* Initialize module parameter values here */ > > + /* Disable radio (SW RF KILL) via parameter when loading driver */ > if (iwl4965_param_disable) { > set_bit(STATUS_RF_KILL_SW, &priv->status); > IWL_DEBUG_INFO("Radio disabled.\n"); > @@ -9061,6 +9206,7 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e > priv->valid_antenna = 0x7; /* assume all 3 connected */ > priv->ps_mode = IWL_MIMO_PS_NONE; > > + /* Choose which receivers/antennas to use */ > iwl4965_set_rxon_chain(priv); > > printk(KERN_INFO DRV_NAME ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 12/36] iwlwifi: Partially clean-up, add comments to iwl-*-hw.h [not found] ` <1196305816-23023-13-git-send-email-yi.zhu@intel.com> 2007-11-29 3:09 ` [PATCH 13/36] iwlwifi: clean up some unused definitions in iwl-4965.h and iwl-3945.h Zhu Yi @ 2007-11-29 3:16 ` Zhu Yi 1 sibling, 0 replies; 36+ messages in thread From: Zhu Yi @ 2007-11-29 3:16 UTC (permalink / raw) To: linville; +Cc: linux-wireless, Ben Cahill Resend. Replace mail subject due to ML restriction for capital Triple-X in subject. On Thu, 2007-11-29 at 11:09 +0800, Zhu Yi wrote: > From: Ben Cahill <ben.m.cahill@intel.com> > > Partially clean-up, add comments to iwl-XXXX-hw.h > > Signed-off-by: Ben Cahill <ben.m.cahill@intel.com> > Signed-off-by: Zhu Yi <yi.zhu@intel.com> > --- > drivers/net/wireless/iwlwifi/iwl-3945-hw.h | 66 ++++++++++++++++------- > drivers/net/wireless/iwlwifi/iwl-4965-hw.h | 78 ++++++++++++++++++---------- > 2 files changed, 97 insertions(+), 47 deletions(-) > > diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h > index 243a225..9526129 100644 > --- a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h > +++ b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h > @@ -64,10 +64,11 @@ > #ifndef __iwl_3945_hw__ > #define __iwl_3945_hw__ > > -/* uCode queue management definitions */ > +/* > + * uCode queue management definitions ... > + * Queue #4 is the command queue for 3945 and 4965. > + */ > #define IWL_CMD_QUEUE_NUM 4 > -#define IWL_CMD_FIFO_NUM 4 > -#define IWL_BACK_QUEUE_FIRST_ID 7 > > /* Tx rates */ > #define IWL_CCK_RATES 4 > @@ -314,7 +315,6 @@ struct iwl3945_eeprom { > > u8 reserved9[194]; > > - > /* > * 3945 Txpower calibration data. > */ > @@ -355,7 +355,18 @@ struct iwl3945_eeprom { > #define CSR_GPIO_IN (CSR_BASE+0x018) /* read external chip pins */ > #define CSR_RESET (CSR_BASE+0x020) /* busmaster enable, NMI, etc*/ > #define CSR_GP_CNTRL (CSR_BASE+0x024) > + > +/* > + * Hardware revision info > + * Bit fields: > + * 31-8: Reserved > + * 7-4: Type of device: 0x0 = 4965, 0xd = 3945 > + * 3-2: Revision step: 0 = A, 1 = B, 2 = C, 3 = D > + * 1-0: "Dash" value, as in A-1, etc. > + */ > #define CSR_HW_REV (CSR_BASE+0x028) > + > +/* EEPROM reads */ > #define CSR_EEPROM_REG (CSR_BASE+0x02c) > #define CSR_EEPROM_GP (CSR_BASE+0x030) > #define CSR_GP_UCODE (CSR_BASE+0x044) > @@ -363,13 +374,13 @@ struct iwl3945_eeprom { > #define CSR_UCODE_DRV_GP1_SET (CSR_BASE+0x058) > #define CSR_UCODE_DRV_GP1_CLR (CSR_BASE+0x05c) > #define CSR_UCODE_DRV_GP2 (CSR_BASE+0x060) > -#define CSR_LED_REG (CSR_BASE+0x094) > -#define CSR_DRAM_INT_TBL_CTL (CSR_BASE+0x0A0) > #define CSR_GIO_CHICKEN_BITS (CSR_BASE+0x100) > + > +/* Analog phase-lock-loop configuration (3945 only) > + * Set bit 24. */ > #define CSR_ANA_PLL_CFG (CSR_BASE+0x20c) > -#define CSR_HW_REV_WA_REG (CSR_BASE+0x22C) > > -/* HW I/F configuration */ > +/* Bits for CSR_HW_IF_CONFIG_REG */ > #define CSR_HW_IF_CONFIG_REG_BIT_ALMAGOR_MB (0x00000100) > #define CSR_HW_IF_CONFIG_REG_BIT_ALMAGOR_MM (0x00000200) > #define CSR_HW_IF_CONFIG_REG_BIT_SKU_MRC (0x00000400) > @@ -468,31 +479,46 @@ struct iwl3945_eeprom { > /* CSR_ANA_PLL_CFG */ > #define CSR_ANA_PLL_CFG_SH (0x00880300) > > -#define CSR_LED_REG_TRUN_ON (0x00000078) > -#define CSR_LED_REG_TRUN_OFF (0x00000038) > -#define CSR_LED_BSM_CTRL_MSK (0xFFFFFFDF) > - > -/* DRAM_INT_TBL_CTRL */ > -#define CSR_DRAM_INT_TBL_CTRL_EN (1<<31) > -#define CSR_DRAM_INT_TBL_CTRL_WRAP_CHK (1<<27) > - > /*=== HBUS (Host-side Bus) ===*/ > #define HBUS_BASE (0x400) > > +/* > + * Registers for accessing device's internal SRAM memory (e.g. SCD SRAM > + * structures, error log, event log, verifying uCode load). > + * First write to address register, then read from or write to data register > + * to complete the job. Once the address register is set up, accesses to > + * data registers auto-increment the address by one dword. > + * Bit usage for address registers (read or write): > + * 0-31: memory address within device > + */ > #define HBUS_TARG_MEM_RADDR (HBUS_BASE+0x00c) > #define HBUS_TARG_MEM_WADDR (HBUS_BASE+0x010) > #define HBUS_TARG_MEM_WDAT (HBUS_BASE+0x018) > #define HBUS_TARG_MEM_RDAT (HBUS_BASE+0x01c) > + > +/* > + * Registers for accessing device's internal peripheral registers > + * (e.g. SCD, BSM, etc.). First write to address register, > + * then read from or write to data register to complete the job. > + * Bit usage for address registers (read or write): > + * 0-15: register address (offset) within device > + * 24-25: (# bytes - 1) to read or write (e.g. 3 for dword) > + */ > #define HBUS_TARG_PRPH_WADDR (HBUS_BASE+0x044) > #define HBUS_TARG_PRPH_RADDR (HBUS_BASE+0x048) > #define HBUS_TARG_PRPH_WDAT (HBUS_BASE+0x04c) > #define HBUS_TARG_PRPH_RDAT (HBUS_BASE+0x050) > -#define HBUS_TARG_WRPTR (HBUS_BASE+0x060) > - > -#define HBUS_TARG_MBX_C (HBUS_BASE+0x030) > > +/* > + * Per-Tx-queue write pointer (index, really!) (3945 and 4965). > + * Indicates index to next TFD that driver will fill (1 past latest filled). > + * Bit usage: > + * 0-7: queue write index > + * 11-8: queue selector > + */ > +#define HBUS_TARG_WRPTR (HBUS_BASE+0x060) > > -/* SCD (Scheduler) */ > +/* SCD (3945 Tx Frame Scheduler) */ > #define SCD_BASE (CSR_BASE + 0x2E00) > > #define SCD_MODE_REG (SCD_BASE + 0x000) > diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h > index 93e2dff..2f0da4d 100644 > --- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h > +++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h > @@ -64,7 +64,12 @@ > #ifndef __iwl_4965_hw_h__ > #define __iwl_4965_hw_h__ > > -/* uCode queue management definitions */ > +/* > + * uCode queue management definitions ... > + * Queue #4 is the command queue for 3945 and 4965; map it to Tx FIFO chnl 4. > + * The first queue used for block-ack aggregation is #7 (4965 only). > + * All block-ack aggregation queues should map to Tx DMA/FIFO channel 7. > + */ > #define IWL_CMD_QUEUE_NUM 4 > #define IWL_CMD_FIFO_NUM 4 > #define IWL_BACK_QUEUE_FIRST_ID 7 > @@ -444,7 +449,20 @@ struct iwl4965_eeprom { > #define CSR_GPIO_IN (CSR_BASE+0x018) /* read external chip pins */ > #define CSR_RESET (CSR_BASE+0x020) /* busmaster enable, NMI, etc*/ > #define CSR_GP_CNTRL (CSR_BASE+0x024) > + > +/* > + * Hardware revision info > + * Bit fields: > + * 31-8: Reserved > + * 7-4: Type of device: 0x0 = 4965, 0xd = 3945 > + * 3-2: Revision step: 0 = A, 1 = B, 2 = C, 3 = D > + * 1-0: "Dash" value, as in A-1, etc. > + * > + * NOTE: Revision step affects calculation of CCK txpower for 4965. > + */ > #define CSR_HW_REV (CSR_BASE+0x028) > + > +/* EEPROM reads */ > #define CSR_EEPROM_REG (CSR_BASE+0x02c) > #define CSR_EEPROM_GP (CSR_BASE+0x030) > #define CSR_GP_UCODE (CSR_BASE+0x044) > @@ -452,10 +470,13 @@ struct iwl4965_eeprom { > #define CSR_UCODE_DRV_GP1_SET (CSR_BASE+0x058) > #define CSR_UCODE_DRV_GP1_CLR (CSR_BASE+0x05c) > #define CSR_UCODE_DRV_GP2 (CSR_BASE+0x060) > -#define CSR_LED_REG (CSR_BASE+0x094) > -#define CSR_DRAM_INT_TBL_CTL (CSR_BASE+0x0A0) > #define CSR_GIO_CHICKEN_BITS (CSR_BASE+0x100) > -#define CSR_ANA_PLL_CFG (CSR_BASE+0x20c) > + > +/* > + * Indicates hardware rev, to determine CCK backoff for txpower calculation. > + * Bit fields: > + * 3-2: 0 = A, 1 = B, 2 = C, 3 = D step > + */ > #define CSR_HW_REV_WA_REG (CSR_BASE+0x22C) > > /* HW I/F configuration */ > @@ -554,44 +575,47 @@ struct iwl4965_eeprom { > #define CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX (0x00800000) > #define CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER (0x20000000) > > -/* CSR_ANA_PLL_CFG */ > -#define CSR_ANA_PLL_CFG_SH (0x00880300) > - > -#define CSR_LED_REG_TRUN_ON (0x00000078) > -#define CSR_LED_REG_TRUN_OFF (0x00000038) > -#define CSR_LED_BSM_CTRL_MSK (0xFFFFFFDF) > - > -/* DRAM_INT_TBL_CTRL */ > -#define CSR_DRAM_INT_TBL_CTRL_EN (1<<31) > -#define CSR_DRAM_INT_TBL_CTRL_WRAP_CHK (1<<27) > - > /*=== HBUS (Host-side Bus) ===*/ > #define HBUS_BASE (0x400) > > +/* > + * Registers for accessing device's internal SRAM memory (e.g. SCD SRAM > + * structures, error log, event log, verifying uCode load). > + * First write to address register, then read from or write to data register > + * to complete the job. Once the address register is set up, accesses to > + * data registers auto-increment the address by one dword. > + * Bit usage for address registers (read or write): > + * 0-31: memory address within device > + */ > #define HBUS_TARG_MEM_RADDR (HBUS_BASE+0x00c) > #define HBUS_TARG_MEM_WADDR (HBUS_BASE+0x010) > #define HBUS_TARG_MEM_WDAT (HBUS_BASE+0x018) > #define HBUS_TARG_MEM_RDAT (HBUS_BASE+0x01c) > + > +/* > + * Registers for accessing device's internal peripheral registers > + * (e.g. SCD, BSM, etc.). First write to address register, > + * then read from or write to data register to complete the job. > + * Bit usage for address registers (read or write): > + * 0-15: register address (offset) within device > + * 24-25: (# bytes - 1) to read or write (e.g. 3 for dword) > + */ > #define HBUS_TARG_PRPH_WADDR (HBUS_BASE+0x044) > #define HBUS_TARG_PRPH_RADDR (HBUS_BASE+0x048) > #define HBUS_TARG_PRPH_WDAT (HBUS_BASE+0x04c) > #define HBUS_TARG_PRPH_RDAT (HBUS_BASE+0x050) > + > +/* > + * Per-Tx-queue write pointer (index, really!) (3945 and 4965). > + * Indicates index to next TFD that driver will fill (1 past latest filled). > + * Bit usage: > + * 0-7: queue write index (0-255) > + * 11-8: queue selector (0-15) > + */ > #define HBUS_TARG_WRPTR (HBUS_BASE+0x060) > > #define HBUS_TARG_MBX_C (HBUS_BASE+0x030) > > - > -/* SCD (Scheduler) */ > -#define SCD_BASE (CSR_BASE + 0x2E00) > - > -#define SCD_MODE_REG (SCD_BASE + 0x000) > -#define SCD_ARASTAT_REG (SCD_BASE + 0x004) > -#define SCD_TXFACT_REG (SCD_BASE + 0x010) > -#define SCD_TXF4MF_REG (SCD_BASE + 0x014) > -#define SCD_TXF5MF_REG (SCD_BASE + 0x020) > -#define SCD_SBYP_MODE_1_REG (SCD_BASE + 0x02C) > -#define SCD_SBYP_MODE_2_REG (SCD_BASE + 0x030) > - > /*=== FH (data Flow Handler) ===*/ > #define FH_BASE (0x800) > ^ permalink raw reply [flat|nested] 36+ messages in thread
end of thread, other threads:[~2007-11-29 3:17 UTC | newest]
Thread overview: 36+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <1196305816-23023-1-git-send-email-yi.zhu@intel.com>
2007-11-29 3:09 ` [PATCH 01/36] iwlwifi: Support for uCode without init and bsm section Zhu Yi
2007-11-29 3:09 ` [PATCH 02/36] iwlwifi: continue namespace changes - fix CONFIG variables Zhu Yi
2007-11-29 3:09 ` [PATCH 03/36] iwl3945: re-align 3945 event log data Zhu Yi
2007-11-29 3:09 ` [PATCH 04/36] iwl4965: add comments to rate scaling code Zhu Yi
2007-11-29 3:09 ` [PATCH 05/36] iwlwifi: add comments to EEPROM stuff Zhu Yi
2007-11-29 3:09 ` [PATCH 06/36] iwl-4965-hw.h: clean up unused eeprom structures and definitions Zhu Yi
2007-11-29 3:09 ` [PATCH 07/36] iwlwifi: clean up and clarify some comments after 3945/4965 split Zhu Yi
2007-11-29 3:09 ` [PATCH 08/36] iwlwifi: Move is_legacy() macro family from iwl-4965-hw.h to iwl-4965-rs.h Zhu Yi
2007-11-29 3:09 ` [PATCH 09/36] iwlwifi: Add comments to some driver data structures Zhu Yi
2007-11-29 3:09 ` [PATCH 10/36] iwlwifi: Document 4965 rate_n_flags bits Zhu Yi
2007-11-29 3:09 ` [PATCH 11/36] iwlwifi: Document Rx calibration Zhu Yi
[not found] ` <1196305816-23023-13-git-send-email-yi.zhu@intel.com>
2007-11-29 3:09 ` [PATCH 13/36] iwlwifi: clean up some unused definitions in iwl-4965.h and iwl-3945.h Zhu Yi
2007-11-29 3:09 ` [PATCH 14/36] iwlwifi: add comments, mostly on Tx queues Zhu Yi
[not found] ` <1196305816-23023-16-git-send-email-yi.zhu@intel.com>
2007-11-29 3:09 ` [PATCH 16/36] iwlwifi: fix possibly NULL dereference in iwl_set_rate() Zhu Yi
2007-11-29 3:09 ` [PATCH 17/36] iwlwifi: Clean up unused definitions in iwl-3945-hw.h Zhu Yi
2007-11-29 3:09 ` [PATCH 18/36] iwlwifi: clean up unused definitions in iwl-4965-hw.h Zhu Yi
2007-11-29 3:09 ` [PATCH 19/36] iwlwifi: move uCode API definitions to iwl-4965-commands.h Zhu Yi
2007-11-29 3:10 ` [PATCH 20/36] iwlwifi: move HT_IE_EXT_CHANNEL_* driver definitions to iwl-4965.h Zhu Yi
2007-11-29 3:10 ` [PATCH 21/36] iwlwifi: document temperature calculation Zhu Yi
2007-11-29 3:10 ` [PATCH 22/36] iwlwifi: document txpower calculations Zhu Yi
2007-11-29 3:10 ` [PATCH 23/36] iwlwifi: document keep-warm buffer Zhu Yi
2007-11-29 3:10 ` [PATCH 24/36] iwlwifi: document Rx registers Zhu Yi
2007-11-29 3:10 ` [PATCH 25/36] iwlwifi: document Tx registers Zhu Yi
2007-11-29 3:10 ` [PATCH 26/36] iwlwifi: document shared Tx structures Zhu Yi
2007-11-29 3:10 ` [PATCH 27/36] iwlwifi: document 4965 Tx scheduler Zhu Yi
2007-11-29 3:10 ` [PATCH 28/36] iwlwifi: document command header and "alive" responses Zhu Yi
2007-11-29 3:10 ` [PATCH 29/36] iwlwifi: add comments to RXON command and txpower formats Zhu Yi
2007-11-29 3:10 ` [PATCH 30/36] iwlwifi: add comments to QOS and ADD_STA commands Zhu Yi
2007-11-29 3:10 ` [PATCH 31/36] iwlwifi: add comments to Tx commands Zhu Yi
2007-11-29 3:10 ` [PATCH 32/36] iwlwifi: document 4965 rate scaling Zhu Yi
2007-11-29 3:10 ` [PATCH 33/36] iwlwifi: enhance WPA authenication stability Zhu Yi
2007-11-29 3:10 ` [PATCH 34/36] iwlwifi: fix ucode assertion for RX queue overrun Zhu Yi
2007-11-29 3:10 ` [PATCH 35/36] iwlwifi: avoid firmware command sending if rfkill is enabled Zhu Yi
2007-11-29 3:10 ` [PATCH 36/36] iwlwifi: update version number to 1.2.22 Zhu Yi
2007-11-29 3:17 ` [PATCH 15/36] iwlwifi: add comments to iwl*-base.c Zhu Yi
2007-11-29 3:16 ` [PATCH 12/36] iwlwifi: Partially clean-up, add comments to iwl-*-hw.h Zhu Yi
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).