iwmc3200wifi updates
PATCH 2/9 iwmc3200wifi: Set WEP key from connect
In reply to Samuel OrtizWhen connect is called with the LEGACY_PSK authentication type set, and a proper sme->key, we need to set the WEP key straight after setting the profile otherwise the authentication will never start.
--- drivers/net/wireless/iwmc3200wifi/cfg80211.c | 44 +++++++++++++++++++++++++- 1 files changed, 43 insertions(+), 1 deletions(-)
drivers/net/wireless/iwmc3200wifi/cfg80211.c +43 -1
@@ -562,6 +562,7 @@ static int iwm_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, {struct iwm_priv *iwm =wiphy_to_iwm (wiphy);struct ieee80211_channel *chan = sme->channel; +struct key_params key_param;int ret;if (!test_bit (IWM_STATUS_READY , &iwm->status))
@@ -619,7 +620,48 @@ static int iwm_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,return ret; } -return iwm_send_mlme_profile (iwm); +/* +* We save the WEP key in case we want to do shared authentication. +* We have to do it so because UMAC will assert whenever it gets a +* key before a profile. +*/ +if (sme->key) { + key_param.key =kmemdup (sme->key, sme->key_len,GFP_KERNEL ); +if (key_param.key ==NULL ) +return -ENOMEM ; + key_param.key_len = sme->key_len; + key_param.seq_len =0 ; + key_param.cipher = sme->crypto.ciphers_pairwise[0 ]; + + ret =iwm_key_init (&iwm->keys[sme->key_idx], sme->key_idx, +NULL , &key_param); +kfree (key_param.key); +if (ret <0 ) { +IWM_ERR (iwm,"Invalid key_params\n" ); +return ret; + } + + iwm->default_key = sme->key_idx; + } + + ret =iwm_send_mlme_profile (iwm); + +if (iwm->umac_profile->sec.auth_type !=UMAC_AUTH_TYPE_LEGACY_PSK || + sme->key ==NULL ) +return ret; + +/* +* We want to do shared auth. +* We need to actually set the key we previously cached, +* and then tell the UMAC it's the default one. +* That will trigger the auth+assoc UMAC machinery, and again, +* this must be done after setting the profile. +*/ + ret =iwm_set_key (iwm,0 , &iwm->keys[sme->key_idx]); +if (ret <0 ) +return ret; + +return iwm_set_tx_key (iwm, iwm->default_key); } static int iwm_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
Signature · 1 line
1.6.3.3
PATCH 3/9 iwmc3200wifi: Fix sparse warning
iwm_cfg80211_get_station() should be static.
--- drivers/net/wireless/iwmc3200wifi/cfg80211.c | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-)
drivers/net/wireless/iwmc3200wifi/cfg80211.c +3 -2
@@ -238,8 +238,9 @@ static int iwm_cfg80211_set_default_key(struct wiphy *wiphy,return iwm_set_tx_key (iwm, key_index); } -int iwm_cfg80211_get_station (struct wiphy *wiphy,struct net_device *ndev, -u8 *mac,struct station_info *sinfo) +static int iwm_cfg80211_get_station (struct wiphy *wiphy, +struct net_device *ndev, +u8 *mac,struct station_info *sinfo) {struct iwm_priv *iwm =ndev_to_iwm (ndev);
Signature · 1 line
1.6.3.3
PATCH 4/9 iwmc3200wifi: use cfg80211_roamed to send roam event
From: Zhu Yi <[email protected]>
The device sends connection terminated and [re]association success (or failure) events when roaming occours. The patch uses cfg80211_roamed instead of cfg80211_connect_result to notify SME for roaming.
--- drivers/net/wireless/iwmc3200wifi/cfg80211.c | 2 +- drivers/net/wireless/iwmc3200wifi/commands.c | 1 + drivers/net/wireless/iwmc3200wifi/iwm.h | 2 +- drivers/net/wireless/iwmc3200wifi/rx.c | 26 ++++++++++++++++++++------ 4 files changed, 23 insertions(+), 8 deletions(-)
drivers/net/wireless/iwmc3200wifi/cfg80211.c +1 -1
@@ -673,7 +673,7 @@ static int iwm_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,IWM_DBG_WEXT (iwm,DBG ,"Active: %d\n" , iwm->umac_profile_active);if (iwm->umac_profile_active) -return iwm_invalidate_mlme_profile (iwm); +iwm_invalidate_mlme_profile (iwm);return 0 ; }
drivers/net/wireless/iwmc3200wifi/commands.c +1 -0
@@ -756,6 +756,7 @@ int iwm_send_mlme_profile(struct iwm_priv *iwm)return ret; } +set_bit (IWM_STATUS_SME_CONNECTING , &iwm->status);return 0 ; }
drivers/net/wireless/iwmc3200wifi/iwm.h +1 -1
@@ -175,7 +175,7 @@ struct iwm_key {#define IWM_STATUS_READY 0#define IWM_STATUS_SCANNING 1#define IWM_STATUS_SCAN_ABORTING 2 -#define IWM_STATUS_ASSOCIATING 3 +#define IWM_STATUS_SME_CONNECTING 3#define IWM_STATUS_ASSOCIATED 4struct iwm_tx_queue {
drivers/net/wireless/iwmc3200wifi/rx.c +20 -6
@@ -487,8 +487,6 @@ static int iwm_mlme_assoc_start(struct iwm_priv *iwm, u8 *buf, start = (struct iwm_umac_notif_assoc_start *)buf; -set_bit (IWM_STATUS_ASSOCIATING , &iwm->status); -IWM_DBG_MLME (iwm,INFO ,"Association with %pM Started, reason: %d\n" , start->bssid,le32_to_cpu (start->roam_reason));
@@ -507,14 +505,23 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf,IWM_DBG_MLME (iwm,INFO ,"Association with %pM completed, status: %d\n" , complete->bssid, complete->status); -clear_bit (IWM_STATUS_ASSOCIATING , &iwm->status); -switch (le32_to_cpu (complete->status)) {case UMAC_ASSOC_COMPLETE_SUCCESS :set_bit (IWM_STATUS_ASSOCIATED , &iwm->status);memcpy (iwm->bssid, complete->bssid,ETH_ALEN ); iwm->channel = complete->channel; +/* Internal roaming state, avoid notifying SME. */ +if (!test_and_clear_bit (IWM_STATUS_SME_CONNECTING , &iwm->status) + && iwm->conf.mode ==UMAC_MODE_BSS ) { +cfg80211_roamed (iwm_to_ndev (iwm), + complete->bssid, + iwm->req_ie, iwm->req_ie_len, + iwm->resp_ie, iwm->resp_ie_len, +GFP_KERNEL ); +break ; + } +iwm_link_on (iwm);if (iwm->conf.mode ==UMAC_MODE_IBSS )
@@ -531,6 +538,11 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf,memset (iwm->bssid,0 ,ETH_ALEN ); iwm->channel =0 ; +/* Internal roaming state, avoid notifying SME. */ +if (!test_and_clear_bit (IWM_STATUS_SME_CONNECTING , &iwm->status) + && iwm->conf.mode ==UMAC_MODE_BSS ) +break ; +iwm_link_off (iwm);if (iwm->conf.mode ==UMAC_MODE_IBSS )
@@ -540,6 +552,7 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf,NULL ,0 ,NULL ,0 ,WLAN_STATUS_UNSPECIFIED_FAILURE , GFP_KERNEL); +break ;default :break ; }
@@ -562,7 +575,7 @@ static int iwm_mlme_profile_invalidate(struct iwm_priv *iwm, u8 *buf,IWM_DBG_MLME (iwm,INFO ,"Profile Invalidated. Reason: %d\n" ,le32_to_cpu (invalid->reason)); -clear_bit (IWM_STATUS_ASSOCIATING , &iwm->status); +clear_bit (IWM_STATUS_SME_CONNECTING , &iwm->status);clear_bit (IWM_STATUS_ASSOCIATED , &iwm->status); iwm->umac_profile_active =0 ;
@@ -813,7 +826,8 @@ static int iwm_mlme_mgt_frame(struct iwm_priv *iwm, u8 *buf, iwm->resp_ie =kmemdup (mgt->u.reassoc_resp.variable, iwm->resp_ie_len,GFP_KERNEL ); }else { -IWM_ERR (iwm,"Unsupported management frame" ); +IWM_ERR (iwm,"Unsupported management frame: 0x%x" , +cpu_to_le16 (mgt->frame_control));return 0 ; }
Signature · 1 line
1.6.3.3
cover iwmc3200wifi updates
Hi John,
This 9 patches serie is the latest iwmc3200wifi update.
All of them are targeted for a wireless-testing inclusion, hoping it's not too late to make it to the next merge window.
Samuel Ortiz (5):
iwmc3200wifi: Set WEP key from connect
iwmc3200wifi: Fix sparse warning
iwmc3200wifi: New initial LMAC calibration
iwmc3200wifi: Handle UMAC stalls and UMAC assert properly
iwmc3200wifi: Add a last_fw_err debugfs entry
Zhu Yi (4):
iwmc3200wifi: invalidate profile when necessary before connect
iwmc3200wifi: use cfg80211_roamed to send roam event
iwmc3200wifi: add disconnect work
iwmc3200wifi: fix misuse of le16_to_cpu
drivers/net/wireless/iwmc3200wifi/cfg80211.c | 66 ++++++++++++++-- drivers/net/wireless/iwmc3200wifi/commands.c | 1 + drivers/net/wireless/iwmc3200wifi/debug.h | 2 + drivers/net/wireless/iwmc3200wifi/debugfs.c | 105 +++++++++++++++++++++++++- drivers/net/wireless/iwmc3200wifi/fw.c | 56 ++++++++++---- drivers/net/wireless/iwmc3200wifi/iwm.h | 8 ++- drivers/net/wireless/iwmc3200wifi/lmac.h | 15 ++++ drivers/net/wireless/iwmc3200wifi/main.c | 60 +++++++++++++-- drivers/net/wireless/iwmc3200wifi/rx.c | 87 +++++++++++++++++---- 9 files changed, 345 insertions(+), 55 deletions(-)
PATCH 1/9 iwmc3200wifi: invalidate profile when necessary before connect
From: Zhu Yi <[email protected]>
If cfg80211 requests to connect when we have already had an active profile, invalidate the current profile first before sending a new profile to UMAC.
--- drivers/net/wireless/iwmc3200wifi/cfg80211.c | 15 ++++++++++----- 1 files changed, 10 insertions(+), 5 deletions(-)
drivers/net/wireless/iwmc3200wifi/cfg80211.c +10 -5
@@ -326,11 +326,8 @@ static int iwm_cfg80211_change_iface(struct wiphy *wiphy, iwm->umac_profile->mode =cpu_to_le32 (iwm->conf.mode); -if (iwm->umac_profile_active) { -int ret =iwm_invalidate_mlme_profile (iwm); -if (ret <0 ) -IWM_ERR (iwm,"Couldn't invalidate profile\n" ); - } +if (iwm->umac_profile_active) +iwm_invalidate_mlme_profile (iwm);return 0 ; }
@@ -573,6 +570,14 @@ static int iwm_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,if (!sme->ssid)return -EINVAL ; +if (iwm->umac_profile_active) { + ret =iwm_invalidate_mlme_profile (iwm); +if (ret) { +IWM_ERR (iwm,"Couldn't invalidate profile\n" ); +return ret; + } + } +if (chan) iwm->channel =ieee80211_frequency_to_channel (chan->center_freq);
Signature · 1 line
1.6.3.3
PATCH 5/9 iwmc3200wifi: add disconnect work
In reply to Samuel OrtizFrom: Zhu Yi <[email protected]>
When the driver receives "connection terminated" event from device, it could be caused by 2 reasons: the firmware is roaming or the connection is lost (AP disappears). For the former, an association complete event is supposed to come within 3 seconds. For the latter, the driver won't receive any event except the connection terminated. So we kick a delayed work (5*HZ) when we receive the connection terminated event. It will be canceled if it turns out to be a roaming event later. Otherwise we notify SME and userspace the disconnection.
--- drivers/net/wireless/iwmc3200wifi/iwm.h | 1 + drivers/net/wireless/iwmc3200wifi/main.c | 21 +++++++++++++++++++ drivers/net/wireless/iwmc3200wifi/rx.c | 32 +++++++++++++++++++++++++---- 3 files changed, 49 insertions(+), 5 deletions(-)
drivers/net/wireless/iwmc3200wifi/iwm.h +1 -0
@@ -273,6 +273,7 @@ struct iwm_priv {struct iw_statistics wstats;struct delayed_work stats_request; +struct delayed_work disconnect;struct iwm_debugfs dbg;
drivers/net/wireless/iwmc3200wifi/main.c +21 -0
@@ -108,6 +108,26 @@ static void iwm_statistics_request(struct work_struct *work)iwm_send_umac_stats_req (iwm,0 ); } +static void iwm_disconnect_work (struct work_struct *work) +{ +struct iwm_priv *iwm = + container_of(work, struct iwm_priv, disconnect.work); + +if (iwm->umac_profile_active) +iwm_invalidate_mlme_profile (iwm); + +clear_bit (IWM_STATUS_ASSOCIATED , &iwm->status); + iwm->umac_profile_active =0 ; +memset (iwm->bssid,0 ,ETH_ALEN ); + iwm->channel =0 ; + +iwm_link_off (iwm); + +wake_up_interruptible (&iwm->mlme_queue); + +cfg80211_disconnected (iwm_to_ndev (iwm),0 ,NULL ,0 ,GFP_KERNEL ); +} +int __iwm_up (struct iwm_priv *iwm);int __iwm_down (struct iwm_priv *iwm);
@@ -198,6 +218,7 @@ int iwm_priv_init(struct iwm_priv *iwm)spin_lock_init (&iwm->cmd_lock); iwm->scan_id =1 ;INIT_DELAYED_WORK (&iwm->stats_request, iwm_statistics_request); +INIT_DELAYED_WORK (&iwm->disconnect, iwm_disconnect_work);INIT_WORK (&iwm->reset_worker, iwm_reset_worker);INIT_LIST_HEAD (&iwm->bss_list);
drivers/net/wireless/iwmc3200wifi/rx.c +27 -5
@@ -514,6 +514,7 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf,/* Internal roaming state, avoid notifying SME. */ if (!test_and_clear_bit (IWM_STATUS_SME_CONNECTING , &iwm->status) && iwm->conf.mode ==UMAC_MODE_BSS ) { +cancel_delayed_work (&iwm->disconnect); cfg80211_roamed(iwm_to_ndev(iwm), complete->bssid, iwm->req_ie, iwm->req_ie_len,
@@ -540,8 +541,10 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf,/* Internal roaming state, avoid notifying SME. */ if (!test_and_clear_bit (IWM_STATUS_SME_CONNECTING , &iwm->status) - && iwm->conf.mode ==UMAC_MODE_BSS ) + && iwm->conf.mode ==UMAC_MODE_BSS ) { +cancel_delayed_work (&iwm->disconnect);break ; + }iwm_link_off (iwm);
@@ -569,11 +572,18 @@ static int iwm_mlme_profile_invalidate(struct iwm_priv *iwm, u8 *buf, struct iwm_wifi_cmd *cmd) {struct iwm_umac_notif_profile_invalidate *invalid; +u32 reason; invalid = (struct iwm_umac_notif_profile_invalidate *)buf; + reason =le32_to_cpu (invalid->reason); + +IWM_DBG_MLME (iwm,INFO ,"Profile Invalidated. Reason: %d\n" , reason); -IWM_DBG_MLME (iwm,INFO ,"Profile Invalidated. Reason: %d\n" , -le32_to_cpu (invalid->reason)); +if (reason !=UMAC_PROFILE_INVALID_REQUEST && +test_bit (IWM_STATUS_SME_CONNECTING , &iwm->status)) +cfg80211_connect_result (iwm_to_ndev (iwm),NULL ,NULL ,0 ,NULL , +0 ,WLAN_STATUS_UNSPECIFIED_FAILURE , +GFP_KERNEL );clear_bit (IWM_STATUS_SME_CONNECTING , &iwm->status);clear_bit (IWM_STATUS_ASSOCIATED , &iwm->status);
@@ -589,6 +599,19 @@ static int iwm_mlme_profile_invalidate(struct iwm_priv *iwm, u8 *buf,return 0 ; } +#define IWM_DISCONNECT_INTERVAL (5 * HZ) + +static int iwm_mlme_connection_terminated (struct iwm_priv *iwm,u8 *buf, +unsigned long buf_size, +struct iwm_wifi_cmd *cmd) +{ +IWM_DBG_MLME (iwm,DBG ,"Connection terminated\n" ); + +schedule_delayed_work (&iwm->disconnect,IWM_DISCONNECT_INTERVAL ); + +return 0 ; +} +static int iwm_mlme_scan_complete (struct iwm_priv *iwm,u8 *buf,unsigned long buf_size,struct iwm_wifi_cmd *cmd)
@@ -848,8 +871,7 @@ static int iwm_ntf_mlme(struct iwm_priv *iwm, u8 *buf,case WIFI_IF_NTFY_PROFILE_INVALIDATE_COMPLETE :return iwm_mlme_profile_invalidate (iwm, buf, buf_size, cmd);case WIFI_IF_NTFY_CONNECTION_TERMINATED : -IWM_DBG_MLME (iwm,DBG ,"Connection terminated\n" ); -break ; +return iwm_mlme_connection_terminated (iwm, buf, buf_size, cmd);case WIFI_IF_NTFY_SCAN_COMPLETE :return iwm_mlme_scan_complete (iwm, buf, buf_size, cmd);case WIFI_IF_NTFY_STA_TABLE_CHANGE :
Signature · 1 line
1.6.3.3
PATCH 7/9 iwmc3200wifi: New initial LMAC calibration
In reply to Samuel OrtizThe LMAC calibration API got broken mostly by having a configuration bitmap being different than the result one.
This patch tries to address that issue by correctly running calibrations with the newest firmwares, and keeping a backward compatibility fallback path for older firmwares, where the configuration and result bitmaps were identical.
--- drivers/net/wireless/iwmc3200wifi/fw.c | 56 +++++++++++++++++++++--------- drivers/net/wireless/iwmc3200wifi/iwm.h | 1 + drivers/net/wireless/iwmc3200wifi/lmac.h | 15 ++++++++ drivers/net/wireless/iwmc3200wifi/main.c | 7 +++- 4 files changed, 61 insertions(+), 18 deletions(-)
drivers/net/wireless/iwmc3200wifi/fw.c +39 -17
@@ -261,6 +261,33 @@ static int iwm_load_lmac(struct iwm_priv *iwm, const char *img_name) cpu_to_le32(UMAC_RST_CTRL_FLG_LARC_CLK_EN), 0); } +static int iwm_init_calib (struct iwm_priv *iwm,unsigned long cfg_bitmap, +unsigned long expected_bitmap,u8 rx_iq_cmd) +{ +/* Read RX IQ calibration result from EEPROM */ +if (test_bit (rx_iq_cmd, &cfg_bitmap)) { +iwm_store_rxiq_calib_result (iwm); +set_bit (PHY_CALIBRATE_RX_IQ_CMD , &iwm->calib_done_map); + } + +iwm_send_prio_table (iwm); +iwm_send_init_calib_cfg (iwm, cfg_bitmap); + +while (iwm->calib_done_map != expected_bitmap) { +if (iwm_notif_handle (iwm,CALIBRATION_RES_NOTIFICATION , +IWM_SRC_LMAC ,WAIT_NOTIF_TIMEOUT )) { +IWM_DBG_FW (iwm,DBG ,"Initial calibration timeout\n" ); +return -ETIMEDOUT ; + } + +IWM_DBG_FW (iwm,DBG ,"Got calibration result. calib_done_map: " +"0x%lx, expected calibrations: 0x%lx\n" , + iwm->calib_done_map, expected_bitmap); + } + +return 0 ; +} +/* * We currently have to load 3 FWs: * 1) The UMAC (Upper MAC).
@@ -276,6 +303,7 @@ static int iwm_load_lmac(struct iwm_priv *iwm, const char *img_name)int iwm_load_fw (struct iwm_priv *iwm) {unsigned long init_calib_map, periodic_calib_map; +unsigned long expected_calib_map;int ret;/* We first start downloading the UMAC */
@@ -317,27 +345,21 @@ int iwm_load_fw(struct iwm_priv *iwm) } init_calib_map = iwm->conf.calib_map &IWM_CALIB_MAP_INIT_MSK ; + expected_calib_map = iwm->conf.expected_calib_map & +IWM_CALIB_MAP_INIT_MSK ; periodic_calib_map =IWM_CALIB_MAP_PER_LMAC (iwm->conf.calib_map); -/* Read RX IQ calibration result from EEPROM */ -if (test_bit (PHY_CALIBRATE_RX_IQ_CMD , &init_calib_map)) { -iwm_store_rxiq_calib_result (iwm); -set_bit (PHY_CALIBRATE_RX_IQ_CMD , &iwm->calib_done_map); - } - -iwm_send_prio_table (iwm); -iwm_send_init_calib_cfg (iwm, init_calib_map); - -while (iwm->calib_done_map != init_calib_map) { - ret =iwm_notif_handle (iwm,CALIBRATION_RES_NOTIFICATION , -IWM_SRC_LMAC ,WAIT_NOTIF_TIMEOUT ); -if (ret) { -IWM_ERR (iwm,"Wait for calibration result timeout\n" ); + ret =iwm_init_calib (iwm, init_calib_map, expected_calib_map, +CALIB_CFG_RX_IQ_IDX ); +if (ret <0 ) { +/* Let's try the old way */ + ret =iwm_init_calib (iwm, expected_calib_map, + expected_calib_map, +PHY_CALIBRATE_RX_IQ_CMD ); +if (ret <0 ) { +IWM_ERR (iwm,"Calibration result timeout\n" ); goto out; } -IWM_DBG_FW (iwm,DBG ,"Got calibration result. calib_done_map: " -"0x%lx, requested calibrations: 0x%lx\n" , - iwm->calib_done_map, init_calib_map); }/* Handle LMAC CALIBRATION_COMPLETE notification */
drivers/net/wireless/iwmc3200wifi/iwm.h +1 -0
@@ -64,6 +64,7 @@struct iwm_conf {u32 sdio_ior_timeout;unsigned long calib_map; +unsigned long expected_calib_map;bool reset_on_fatal_err;bool auto_connect;bool wimax_not_present;
drivers/net/wireless/iwmc3200wifi/lmac.h +15 -0
@@ -396,9 +396,24 @@ enum { CALIBRATION_CMD_NUM, }; +enum { +CALIB_CFG_RX_BB_IDX =0 , +CALIB_CFG_DC_IDX =1 , +CALIB_CFG_LO_IDX =2 , +CALIB_CFG_TX_IQ_IDX =3 , +CALIB_CFG_RX_IQ_IDX =4 , +CALIB_CFG_NOISE_IDX =5 , +CALIB_CFG_CRYSTAL_IDX =6 , +CALIB_CFG_TEMPERATURE_IDX =7 , +CALIB_CFG_PAPD_IDX =8 , +CALIB_CFG_LAST_IDX =CALIB_CFG_PAPD_IDX , +CALIB_CFG_MODULE_NUM , +}; +#define IWM_CALIB_MAP_INIT_MSK 0xFFFF#define IWM_CALIB_MAP_PER_LMAC (m) ((m & 0xFF0000) >> 16)#define IWM_CALIB_MAP_PER_UMAC (m) ((m & 0xFF000000) >> 24) +#define IWM_CALIB_OPCODE_TO_INDEX (op) (op - PHY_CALIBRATE_OPCODES_NUM)struct iwm_lmac_calib_hdr {u8 opcode;
drivers/net/wireless/iwmc3200wifi/main.c +6 -1
@@ -53,7 +53,12 @@static struct iwm_conf def_iwm_conf = { .sdio_ior_timeout =5000 , - .calib_map =BIT (PHY_CALIBRATE_DC_CMD ) | + .calib_map =BIT (CALIB_CFG_DC_IDX ) | +BIT (CALIB_CFG_LO_IDX ) | +BIT (CALIB_CFG_TX_IQ_IDX ) | +BIT (CALIB_CFG_RX_IQ_IDX ) | +BIT (SHILOH_PHY_CALIBRATE_BASE_BAND_CMD ), + .expected_calib_map =BIT (PHY_CALIBRATE_DC_CMD ) |BIT (PHY_CALIBRATE_LO_CMD ) |BIT (PHY_CALIBRATE_TX_IQ_CMD ) | BIT(PHY_CALIBRATE_RX_IQ_CMD) |
Signature · 1 line
1.6.3.3
PATCH 6/9 iwmc3200wifi: fix misuse of le16_to_cpu
In reply to Samuel OrtizFrom: Zhu Yi <[email protected]>
Also mark some functions static.
--- drivers/net/wireless/iwmc3200wifi/main.c | 8 ++++---- drivers/net/wireless/iwmc3200wifi/rx.c | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-)
drivers/net/wireless/iwmc3200wifi/main.c +4 -4
@@ -128,8 +128,8 @@ static void iwm_disconnect_work(struct work_struct *work)cfg80211_disconnected (iwm_to_ndev (iwm),0 ,NULL ,0 ,GFP_KERNEL ); } -int __iwm_up (struct iwm_priv *iwm); -int __iwm_down (struct iwm_priv *iwm); +static int __iwm_up (struct iwm_priv *iwm); +static int __iwm_down (struct iwm_priv *iwm);static void iwm_reset_worker (struct work_struct *work) {
@@ -559,7 +559,7 @@ static int iwm_channels_init(struct iwm_priv *iwm)return 0 ; } -int __iwm_up (struct iwm_priv *iwm) +static int __iwm_up (struct iwm_priv *iwm) {int ret;struct iwm_notif *notif_reboot, *notif_ack =NULL ;
@@ -693,7 +693,7 @@ int iwm_up(struct iwm_priv *iwm)return ret; } -int __iwm_down (struct iwm_priv *iwm) +static int __iwm_down (struct iwm_priv *iwm) {int ret;
drivers/net/wireless/iwmc3200wifi/rx.c +1 -1
@@ -850,7 +850,7 @@ static int iwm_mlme_mgt_frame(struct iwm_priv *iwm, u8 *buf, iwm->resp_ie_len, GFP_KERNEL); }else {IWM_ERR (iwm,"Unsupported management frame: 0x%x" , -cpu_to_le16 (mgt->frame_control)); +le16_to_cpu (mgt->frame_control));return 0 ; }
Signature · 1 line
1.6.3.3
PATCH 8/9 iwmc3200wifi: Handle UMAC stalls and UMAC assert properly
In reply to Samuel OrtizWhen UMAC stalls or asserts, we want to reset the device. But when we're associated, the current reset worker will end up calling cfg80211_connect_result() with the cfg80211 sme layer knowing that we're reassociating. That ends up with some ugly warnings.
With this patch we're telling the upper layer that we've roamed if reassociation succeeds, and that we're disconnected if it fails.
--- drivers/net/wireless/iwmc3200wifi/iwm.h | 2 ++ drivers/net/wireless/iwmc3200wifi/main.c | 18 +++++++++++++++--- drivers/net/wireless/iwmc3200wifi/rx.c | 29 +++++++++++++++++++++++------ 3 files changed, 40 insertions(+), 9 deletions(-)
drivers/net/wireless/iwmc3200wifi/iwm.h +2 -0
@@ -178,6 +178,7 @@ struct iwm_key {#define IWM_STATUS_SCAN_ABORTING 2#define IWM_STATUS_SME_CONNECTING 3#define IWM_STATUS_ASSOCIATED 4 +#define IWM_STATUS_RESETTING 5struct iwm_tx_queue {int id;
@@ -317,6 +318,7 @@ int iwm_mode_to_nl80211_iftype(int mode);int iwm_priv_init (struct iwm_priv *iwm);void iwm_priv_deinit (struct iwm_priv *iwm);void iwm_reset (struct iwm_priv *iwm); +void iwm_resetting (struct iwm_priv *iwm);void iwm_tx_credit_init_pools (struct iwm_priv *iwm,struct iwm_umac_notif_alive *alive);int iwm_tx_credit_alloc (struct iwm_priv *iwm,int id,int nb);
drivers/net/wireless/iwmc3200wifi/main.c +15 -3
@@ -187,7 +187,8 @@ static void iwm_reset_worker(struct work_struct *work)memcpy (iwm->umac_profile, profile,sizeof (*profile));iwm_send_mlme_profile (iwm);kfree (profile); - } + }else +clear_bit (IWM_STATUS_RESETTING , &iwm->status); out:mutex_unlock (&iwm->mutex);
@@ -200,7 +201,7 @@ static void iwm_watchdog(unsigned long data)IWM_WARN (iwm,"Watchdog expired: UMAC stalls!\n" );if (modparam_reset) -schedule_work (&iwm->reset_worker); +iwm_resetting (iwm); }int iwm_priv_init (struct iwm_priv *iwm)
@@ -284,7 +285,11 @@ void iwm_reset(struct iwm_priv *iwm)if (test_bit (IWM_STATUS_READY , &iwm->status))iwm_target_reset (iwm); - iwm->status =0 ; +if (test_bit (IWM_STATUS_RESETTING , &iwm->status)) { + iwm->status =0 ; +set_bit (IWM_STATUS_RESETTING , &iwm->status); + }else + iwm->status =0 ; iwm->scan_id =1 ;list_for_each_entry_safe (notif, next, &iwm->pending_notif, pending) {
@@ -300,6 +305,13 @@ void iwm_reset(struct iwm_priv *iwm)iwm_link_off (iwm); } +void iwm_resetting (struct iwm_priv *iwm) +{ +set_bit (IWM_STATUS_RESETTING , &iwm->status); + +schedule_work (&iwm->reset_worker); +} +/* * Notification code: *
drivers/net/wireless/iwmc3200wifi/rx.c +23 -6
@@ -118,6 +118,8 @@ static int iwm_ntf_error(struct iwm_priv *iwm, u8 *buf,IWM_ERR (iwm,"\tLMAC status: 0x%x\n" ,le32_to_cpu (fw_err->lmac_status));IWM_ERR (iwm,"\tSDIO status: 0x%x\n" ,le32_to_cpu (fw_err->sdio_status)); +iwm_resetting (iwm); +return 0 ; }
@@ -528,11 +530,19 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf,if (iwm->conf.mode ==UMAC_MODE_IBSS ) goto ibss; -cfg80211_connect_result (iwm_to_ndev (iwm), +if (!test_bit (IWM_STATUS_RESETTING , &iwm->status)) +cfg80211_connect_result (iwm_to_ndev (iwm), + complete->bssid, + iwm->req_ie, iwm->req_ie_len, + iwm->resp_ie, iwm->resp_ie_len, +WLAN_STATUS_SUCCESS , +GFP_KERNEL ); +else +cfg80211_roamed (iwm_to_ndev (iwm), complete->bssid, iwm->req_ie, iwm->req_ie_len, iwm->resp_ie, iwm->resp_ie_len, -WLAN_STATUS_SUCCESS ,GFP_KERNEL ); +GFP_KERNEL );break ;case UMAC_ASSOC_COMPLETE_FAILURE :clear_bit (IWM_STATUS_ASSOCIATED , &iwm->status);
@@ -551,19 +561,26 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf,if (iwm->conf.mode ==UMAC_MODE_IBSS ) goto ibss; -cfg80211_connect_result (iwm_to_ndev (iwm), complete->bssid, -NULL ,0 ,NULL ,0 , -WLAN_STATUS_UNSPECIFIED_FAILURE , -GFP_KERNEL ); +if (!test_bit (IWM_STATUS_RESETTING , &iwm->status)) +cfg80211_connect_result (iwm_to_ndev (iwm), + complete->bssid, +NULL ,0 ,NULL ,0 , +WLAN_STATUS_UNSPECIFIED_FAILURE , +GFP_KERNEL ); +else +cfg80211_disconnected (iwm_to_ndev (iwm),0 ,NULL ,0 , +GFP_KERNEL );break ;default :break ; } +clear_bit (IWM_STATUS_RESETTING , &iwm->status);return 0 ; ibss:cfg80211_ibss_joined (iwm_to_ndev (iwm), iwm->bssid,GFP_KERNEL ); +clear_bit (IWM_STATUS_RESETTING , &iwm->status);return 0 ; }
Signature · 1 line
1.6.3.3
PATCH 9/9 iwmc3200wifi: Add a last_fw_err debugfs entry
In order to check what was the last fw error we got accross resets, we add this debugfs entry. It displays the complete ASSERT information.
--- drivers/net/wireless/iwmc3200wifi/debug.h | 2 + drivers/net/wireless/iwmc3200wifi/debugfs.c | 105 ++++++++++++++++++++++++++- drivers/net/wireless/iwmc3200wifi/iwm.h | 2 + drivers/net/wireless/iwmc3200wifi/main.c | 6 ++ drivers/net/wireless/iwmc3200wifi/rx.c | 2 + 5 files changed, 113 insertions(+), 4 deletions(-)
drivers/net/wireless/iwmc3200wifi/debug.h +2 -0
@@ -108,6 +108,8 @@ struct iwm_debugfs {struct dentry *txq_dentry;struct dentry *tx_credit_dentry;struct dentry *rx_ticket_dentry; + +struct dentry *fw_err_dentry; };#ifdef CONFIG_IWM_DEBUG
drivers/net/wireless/iwmc3200wifi/debugfs.c +101 -4
145 lines not on this page · raw message
drivers/net/wireless/iwmc3200wifi/iwm.h +2 -0
@@ -289,6 +289,8 @@ struct iwm_priv {u8 *resp_ie;int resp_ie_len; +struct iwm_fw_error_hdr *last_fw_err; + char private[0] __attribute__((__aligned__(NETDEV_ALIGN))); };
drivers/net/wireless/iwmc3200wifi/main.c +6 -0
@@ -260,6 +260,11 @@ int iwm_priv_init(struct iwm_priv *iwm) iwm->watchdog.data = (unsigned long )iwm;mutex_init (&iwm->mutex); + iwm->last_fw_err =kzalloc (sizeof (struct iwm_fw_error_hdr ), +GFP_KERNEL ); +if (iwm->last_fw_err ==NULL ) +return -ENOMEM ; +return 0 ; }
@@ -271,6 +276,7 @@ void iwm_priv_deinit(struct iwm_priv *iwm)destroy_workqueue (iwm->txq[i].wq);destroy_workqueue (iwm->rx_wq); +kfree (iwm->last_fw_err); }/*
drivers/net/wireless/iwmc3200wifi/rx.c +2 -0
@@ -102,6 +102,8 @@ static int iwm_ntf_error(struct iwm_priv *iwm, u8 *buf, error = (struct iwm_umac_notif_error *)buf; fw_err = &error->err; +memcpy (iwm->last_fw_err, fw_err,sizeof (struct iwm_fw_error_hdr )); +IWM_ERR (iwm,"%cMAC FW ERROR:\n" , (le32_to_cpu (fw_err->category) ==UMAC_SYS_ERR_CAT_LMAC ) ?'L' :'U' );IWM_ERR (iwm,"\tCategory: %d\n" ,le32_to_cpu (fw_err->category));
Signature · 1 line
1.6.3.3