diff options
author | Abhijeet Kolekar <abhijeet.kolekar@intel.com> | 2009-04-08 14:26:37 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-04-22 16:54:41 -0400 |
commit | e0158e61108bdadd70865c2149dc829a5c84dd73 (patch) | |
tree | 7ef8284cf26e6b3bc98ff8c47a407e1d87d8edaa /drivers/net/wireless/iwlwifi/iwl-3945.c | |
parent | 9944b938f23fdd1ce2f5da190f771f176bb51eef (diff) |
iwlwifi: add commit_rxon lib
Patch adds commit_rxon lib operation to iwlwifi and iwl3945 drivers.
Signed-off-by: Abhijeet Kolekar <abhijeet.kolekar@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-3945.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-3945.c | 145 |
1 files changed, 145 insertions, 0 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 519e8922d9f4..9a0fb80023ab 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c | |||
@@ -2008,6 +2008,150 @@ static int iwl3945_send_rxon_assoc(struct iwl_priv *priv) | |||
2008 | return rc; | 2008 | return rc; |
2009 | } | 2009 | } |
2010 | 2010 | ||
2011 | /** | ||
2012 | * iwl3945_commit_rxon - commit staging_rxon to hardware | ||
2013 | * | ||
2014 | * The RXON command in staging_rxon is committed to the hardware and | ||
2015 | * the active_rxon structure is updated with the new data. This | ||
2016 | * function correctly transitions out of the RXON_ASSOC_MSK state if | ||
2017 | * a HW tune is required based on the RXON structure changes. | ||
2018 | */ | ||
2019 | static int iwl3945_commit_rxon(struct iwl_priv *priv) | ||
2020 | { | ||
2021 | /* cast away the const for active_rxon in this function */ | ||
2022 | struct iwl3945_rxon_cmd *active_rxon = (void *)&priv->active_rxon; | ||
2023 | struct iwl3945_rxon_cmd *staging_rxon = (void *)&priv->staging_rxon; | ||
2024 | int rc = 0; | ||
2025 | bool new_assoc = | ||
2026 | !!(priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK); | ||
2027 | |||
2028 | if (!iwl_is_alive(priv)) | ||
2029 | return -1; | ||
2030 | |||
2031 | /* always get timestamp with Rx frame */ | ||
2032 | staging_rxon->flags |= RXON_FLG_TSF2HOST_MSK; | ||
2033 | |||
2034 | /* select antenna */ | ||
2035 | staging_rxon->flags &= | ||
2036 | ~(RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_SEL_MSK); | ||
2037 | staging_rxon->flags |= iwl3945_get_antenna_flags(priv); | ||
2038 | |||
2039 | rc = iwl_check_rxon_cmd(priv); | ||
2040 | if (rc) { | ||
2041 | IWL_ERR(priv, "Invalid RXON configuration. Not committing.\n"); | ||
2042 | return -EINVAL; | ||
2043 | } | ||
2044 | |||
2045 | /* If we don't need to send a full RXON, we can use | ||
2046 | * iwl3945_rxon_assoc_cmd which is used to reconfigure filter | ||
2047 | * and other flags for the current radio configuration. */ | ||
2048 | if (!iwl_full_rxon_required(priv)) { | ||
2049 | rc = iwl_send_rxon_assoc(priv); | ||
2050 | if (rc) { | ||
2051 | IWL_ERR(priv, "Error setting RXON_ASSOC " | ||
2052 | "configuration (%d).\n", rc); | ||
2053 | return rc; | ||
2054 | } | ||
2055 | |||
2056 | memcpy(active_rxon, staging_rxon, sizeof(*active_rxon)); | ||
2057 | |||
2058 | return 0; | ||
2059 | } | ||
2060 | |||
2061 | /* If we are currently associated and the new config requires | ||
2062 | * an RXON_ASSOC and the new config wants the associated mask enabled, | ||
2063 | * we must clear the associated from the active configuration | ||
2064 | * before we apply the new config */ | ||
2065 | if (iwl_is_associated(priv) && new_assoc) { | ||
2066 | IWL_DEBUG_INFO(priv, "Toggling associated bit on current RXON\n"); | ||
2067 | active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; | ||
2068 | |||
2069 | /* | ||
2070 | * reserved4 and 5 could have been filled by the iwlcore code. | ||
2071 | * Let's clear them before pushing to the 3945. | ||
2072 | */ | ||
2073 | active_rxon->reserved4 = 0; | ||
2074 | active_rxon->reserved5 = 0; | ||
2075 | rc = iwl_send_cmd_pdu(priv, REPLY_RXON, | ||
2076 | sizeof(struct iwl3945_rxon_cmd), | ||
2077 | &priv->active_rxon); | ||
2078 | |||
2079 | /* If the mask clearing failed then we set | ||
2080 | * active_rxon back to what it was previously */ | ||
2081 | if (rc) { | ||
2082 | active_rxon->filter_flags |= RXON_FILTER_ASSOC_MSK; | ||
2083 | IWL_ERR(priv, "Error clearing ASSOC_MSK on current " | ||
2084 | "configuration (%d).\n", rc); | ||
2085 | return rc; | ||
2086 | } | ||
2087 | } | ||
2088 | |||
2089 | IWL_DEBUG_INFO(priv, "Sending RXON\n" | ||
2090 | "* with%s RXON_FILTER_ASSOC_MSK\n" | ||
2091 | "* channel = %d\n" | ||
2092 | "* bssid = %pM\n", | ||
2093 | (new_assoc ? "" : "out"), | ||
2094 | le16_to_cpu(staging_rxon->channel), | ||
2095 | staging_rxon->bssid_addr); | ||
2096 | |||
2097 | /* | ||
2098 | * reserved4 and 5 could have been filled by the iwlcore code. | ||
2099 | * Let's clear them before pushing to the 3945. | ||
2100 | */ | ||
2101 | staging_rxon->reserved4 = 0; | ||
2102 | staging_rxon->reserved5 = 0; | ||
2103 | |||
2104 | iwl_set_rxon_hwcrypto(priv, !priv->hw_params.sw_crypto); | ||
2105 | |||
2106 | /* Apply the new configuration */ | ||
2107 | rc = iwl_send_cmd_pdu(priv, REPLY_RXON, | ||
2108 | sizeof(struct iwl3945_rxon_cmd), | ||
2109 | staging_rxon); | ||
2110 | if (rc) { | ||
2111 | IWL_ERR(priv, "Error setting new configuration (%d).\n", rc); | ||
2112 | return rc; | ||
2113 | } | ||
2114 | |||
2115 | memcpy(active_rxon, staging_rxon, sizeof(*active_rxon)); | ||
2116 | |||
2117 | iwl3945_clear_stations_table(priv); | ||
2118 | |||
2119 | /* If we issue a new RXON command which required a tune then we must | ||
2120 | * send a new TXPOWER command or we won't be able to Tx any frames */ | ||
2121 | rc = priv->cfg->ops->lib->send_tx_power(priv); | ||
2122 | if (rc) { | ||
2123 | IWL_ERR(priv, "Error setting Tx power (%d).\n", rc); | ||
2124 | return rc; | ||
2125 | } | ||
2126 | |||
2127 | /* Add the broadcast address so we can send broadcast frames */ | ||
2128 | if (iwl3945_add_station(priv, iwl_bcast_addr, 0, 0) == | ||
2129 | IWL_INVALID_STATION) { | ||
2130 | IWL_ERR(priv, "Error adding BROADCAST address for transmit.\n"); | ||
2131 | return -EIO; | ||
2132 | } | ||
2133 | |||
2134 | /* If we have set the ASSOC_MSK and we are in BSS mode then | ||
2135 | * add the IWL_AP_ID to the station rate table */ | ||
2136 | if (iwl_is_associated(priv) && | ||
2137 | (priv->iw_mode == NL80211_IFTYPE_STATION)) | ||
2138 | if (iwl3945_add_station(priv, priv->active_rxon.bssid_addr, | ||
2139 | 1, 0) | ||
2140 | == IWL_INVALID_STATION) { | ||
2141 | IWL_ERR(priv, "Error adding AP address for transmit\n"); | ||
2142 | return -EIO; | ||
2143 | } | ||
2144 | |||
2145 | /* Init the hardware's rate fallback order based on the band */ | ||
2146 | rc = iwl3945_init_hw_rate_table(priv); | ||
2147 | if (rc) { | ||
2148 | IWL_ERR(priv, "Error setting HW rate table: %02X\n", rc); | ||
2149 | return -EIO; | ||
2150 | } | ||
2151 | |||
2152 | return 0; | ||
2153 | } | ||
2154 | |||
2011 | /* will add 3945 channel switch cmd handling later */ | 2155 | /* will add 3945 channel switch cmd handling later */ |
2012 | int iwl3945_hw_channel_switch(struct iwl_priv *priv, u16 channel) | 2156 | int iwl3945_hw_channel_switch(struct iwl_priv *priv, u16 channel) |
2013 | { | 2157 | { |
@@ -2775,6 +2919,7 @@ static int iwl3945_load_bsm(struct iwl_priv *priv) | |||
2775 | 2919 | ||
2776 | static struct iwl_hcmd_ops iwl3945_hcmd = { | 2920 | static struct iwl_hcmd_ops iwl3945_hcmd = { |
2777 | .rxon_assoc = iwl3945_send_rxon_assoc, | 2921 | .rxon_assoc = iwl3945_send_rxon_assoc, |
2922 | .commit_rxon = iwl3945_commit_rxon, | ||
2778 | }; | 2923 | }; |
2779 | 2924 | ||
2780 | static struct iwl_lib_ops iwl3945_lib = { | 2925 | static struct iwl_lib_ops iwl3945_lib = { |