aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwmc3200wifi/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwmc3200wifi/main.c')
-rw-r--r--drivers/net/wireless/iwmc3200wifi/main.c60
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 @@
53static struct iwm_conf def_iwm_conf = { 53static 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
111int __iwm_up(struct iwm_priv *iwm); 116static void iwm_disconnect_work(struct work_struct *work)
112int __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
136static int __iwm_up(struct iwm_priv *iwm);
137static int __iwm_down(struct iwm_priv *iwm);
113 138
114static void iwm_reset_worker(struct work_struct *work) 139static 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
181int iwm_priv_init(struct iwm_priv *iwm) 207int 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
314void 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
541int __iwm_up(struct iwm_priv *iwm) 585static 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
675int __iwm_down(struct iwm_priv *iwm) 719static int __iwm_down(struct iwm_priv *iwm)
676{ 720{
677 int ret; 721 int ret;
678 722