diff options
Diffstat (limited to 'drivers/net/wireless/iwmc3200wifi/main.c')
-rw-r--r-- | drivers/net/wireless/iwmc3200wifi/main.c | 60 |
1 files changed, 52 insertions, 8 deletions
diff --git a/drivers/net/wireless/iwmc3200wifi/main.c b/drivers/net/wireless/iwmc3200wifi/main.c index cf2574442b57..d668e4756324 100644 --- a/drivers/net/wireless/iwmc3200wifi/main.c +++ b/drivers/net/wireless/iwmc3200wifi/main.c | |||
@@ -53,7 +53,12 @@ | |||
53 | static struct iwm_conf def_iwm_conf = { | 53 | static struct iwm_conf def_iwm_conf = { |
54 | 54 | ||
55 | .sdio_ior_timeout = 5000, | 55 | .sdio_ior_timeout = 5000, |
56 | .calib_map = BIT(PHY_CALIBRATE_DC_CMD) | | 56 | .calib_map = BIT(CALIB_CFG_DC_IDX) | |
57 | BIT(CALIB_CFG_LO_IDX) | | ||
58 | BIT(CALIB_CFG_TX_IQ_IDX) | | ||
59 | BIT(CALIB_CFG_RX_IQ_IDX) | | ||
60 | BIT(SHILOH_PHY_CALIBRATE_BASE_BAND_CMD), | ||
61 | .expected_calib_map = BIT(PHY_CALIBRATE_DC_CMD) | | ||
57 | BIT(PHY_CALIBRATE_LO_CMD) | | 62 | BIT(PHY_CALIBRATE_LO_CMD) | |
58 | BIT(PHY_CALIBRATE_TX_IQ_CMD) | | 63 | BIT(PHY_CALIBRATE_TX_IQ_CMD) | |
59 | BIT(PHY_CALIBRATE_RX_IQ_CMD) | | 64 | BIT(PHY_CALIBRATE_RX_IQ_CMD) | |
@@ -108,8 +113,28 @@ static void iwm_statistics_request(struct work_struct *work) | |||
108 | iwm_send_umac_stats_req(iwm, 0); | 113 | iwm_send_umac_stats_req(iwm, 0); |
109 | } | 114 | } |
110 | 115 | ||
111 | int __iwm_up(struct iwm_priv *iwm); | 116 | static void iwm_disconnect_work(struct work_struct *work) |
112 | int __iwm_down(struct iwm_priv *iwm); | 117 | { |
118 | struct iwm_priv *iwm = | ||
119 | container_of(work, struct iwm_priv, disconnect.work); | ||
120 | |||
121 | if (iwm->umac_profile_active) | ||
122 | iwm_invalidate_mlme_profile(iwm); | ||
123 | |||
124 | clear_bit(IWM_STATUS_ASSOCIATED, &iwm->status); | ||
125 | iwm->umac_profile_active = 0; | ||
126 | memset(iwm->bssid, 0, ETH_ALEN); | ||
127 | iwm->channel = 0; | ||
128 | |||
129 | iwm_link_off(iwm); | ||
130 | |||
131 | wake_up_interruptible(&iwm->mlme_queue); | ||
132 | |||
133 | cfg80211_disconnected(iwm_to_ndev(iwm), 0, NULL, 0, GFP_KERNEL); | ||
134 | } | ||
135 | |||
136 | static int __iwm_up(struct iwm_priv *iwm); | ||
137 | static int __iwm_down(struct iwm_priv *iwm); | ||
113 | 138 | ||
114 | static void iwm_reset_worker(struct work_struct *work) | 139 | static void iwm_reset_worker(struct work_struct *work) |
115 | { | 140 | { |
@@ -162,7 +187,8 @@ static void iwm_reset_worker(struct work_struct *work) | |||
162 | memcpy(iwm->umac_profile, profile, sizeof(*profile)); | 187 | memcpy(iwm->umac_profile, profile, sizeof(*profile)); |
163 | iwm_send_mlme_profile(iwm); | 188 | iwm_send_mlme_profile(iwm); |
164 | kfree(profile); | 189 | kfree(profile); |
165 | } | 190 | } else |
191 | clear_bit(IWM_STATUS_RESETTING, &iwm->status); | ||
166 | 192 | ||
167 | out: | 193 | out: |
168 | mutex_unlock(&iwm->mutex); | 194 | mutex_unlock(&iwm->mutex); |
@@ -175,7 +201,7 @@ static void iwm_watchdog(unsigned long data) | |||
175 | IWM_WARN(iwm, "Watchdog expired: UMAC stalls!\n"); | 201 | IWM_WARN(iwm, "Watchdog expired: UMAC stalls!\n"); |
176 | 202 | ||
177 | if (modparam_reset) | 203 | if (modparam_reset) |
178 | schedule_work(&iwm->reset_worker); | 204 | iwm_resetting(iwm); |
179 | } | 205 | } |
180 | 206 | ||
181 | int iwm_priv_init(struct iwm_priv *iwm) | 207 | int iwm_priv_init(struct iwm_priv *iwm) |
@@ -198,6 +224,7 @@ int iwm_priv_init(struct iwm_priv *iwm) | |||
198 | spin_lock_init(&iwm->cmd_lock); | 224 | spin_lock_init(&iwm->cmd_lock); |
199 | iwm->scan_id = 1; | 225 | iwm->scan_id = 1; |
200 | INIT_DELAYED_WORK(&iwm->stats_request, iwm_statistics_request); | 226 | INIT_DELAYED_WORK(&iwm->stats_request, iwm_statistics_request); |
227 | INIT_DELAYED_WORK(&iwm->disconnect, iwm_disconnect_work); | ||
201 | INIT_WORK(&iwm->reset_worker, iwm_reset_worker); | 228 | INIT_WORK(&iwm->reset_worker, iwm_reset_worker); |
202 | INIT_LIST_HEAD(&iwm->bss_list); | 229 | INIT_LIST_HEAD(&iwm->bss_list); |
203 | 230 | ||
@@ -233,6 +260,11 @@ int iwm_priv_init(struct iwm_priv *iwm) | |||
233 | iwm->watchdog.data = (unsigned long)iwm; | 260 | iwm->watchdog.data = (unsigned long)iwm; |
234 | mutex_init(&iwm->mutex); | 261 | mutex_init(&iwm->mutex); |
235 | 262 | ||
263 | iwm->last_fw_err = kzalloc(sizeof(struct iwm_fw_error_hdr), | ||
264 | GFP_KERNEL); | ||
265 | if (iwm->last_fw_err == NULL) | ||
266 | return -ENOMEM; | ||
267 | |||
236 | return 0; | 268 | return 0; |
237 | } | 269 | } |
238 | 270 | ||
@@ -244,6 +276,7 @@ void iwm_priv_deinit(struct iwm_priv *iwm) | |||
244 | destroy_workqueue(iwm->txq[i].wq); | 276 | destroy_workqueue(iwm->txq[i].wq); |
245 | 277 | ||
246 | destroy_workqueue(iwm->rx_wq); | 278 | destroy_workqueue(iwm->rx_wq); |
279 | kfree(iwm->last_fw_err); | ||
247 | } | 280 | } |
248 | 281 | ||
249 | /* | 282 | /* |
@@ -258,7 +291,11 @@ void iwm_reset(struct iwm_priv *iwm) | |||
258 | if (test_bit(IWM_STATUS_READY, &iwm->status)) | 291 | if (test_bit(IWM_STATUS_READY, &iwm->status)) |
259 | iwm_target_reset(iwm); | 292 | iwm_target_reset(iwm); |
260 | 293 | ||
261 | iwm->status = 0; | 294 | if (test_bit(IWM_STATUS_RESETTING, &iwm->status)) { |
295 | iwm->status = 0; | ||
296 | set_bit(IWM_STATUS_RESETTING, &iwm->status); | ||
297 | } else | ||
298 | iwm->status = 0; | ||
262 | iwm->scan_id = 1; | 299 | iwm->scan_id = 1; |
263 | 300 | ||
264 | list_for_each_entry_safe(notif, next, &iwm->pending_notif, pending) { | 301 | list_for_each_entry_safe(notif, next, &iwm->pending_notif, pending) { |
@@ -274,6 +311,13 @@ void iwm_reset(struct iwm_priv *iwm) | |||
274 | iwm_link_off(iwm); | 311 | iwm_link_off(iwm); |
275 | } | 312 | } |
276 | 313 | ||
314 | void iwm_resetting(struct iwm_priv *iwm) | ||
315 | { | ||
316 | set_bit(IWM_STATUS_RESETTING, &iwm->status); | ||
317 | |||
318 | schedule_work(&iwm->reset_worker); | ||
319 | } | ||
320 | |||
277 | /* | 321 | /* |
278 | * Notification code: | 322 | * Notification code: |
279 | * | 323 | * |
@@ -538,7 +582,7 @@ static int iwm_channels_init(struct iwm_priv *iwm) | |||
538 | return 0; | 582 | return 0; |
539 | } | 583 | } |
540 | 584 | ||
541 | int __iwm_up(struct iwm_priv *iwm) | 585 | static int __iwm_up(struct iwm_priv *iwm) |
542 | { | 586 | { |
543 | int ret; | 587 | int ret; |
544 | struct iwm_notif *notif_reboot, *notif_ack = NULL; | 588 | struct iwm_notif *notif_reboot, *notif_ack = NULL; |
@@ -672,7 +716,7 @@ int iwm_up(struct iwm_priv *iwm) | |||
672 | return ret; | 716 | return ret; |
673 | } | 717 | } |
674 | 718 | ||
675 | int __iwm_down(struct iwm_priv *iwm) | 719 | static int __iwm_down(struct iwm_priv *iwm) |
676 | { | 720 | { |
677 | int ret; | 721 | int ret; |
678 | 722 | ||