diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-14 21:37:28 +0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-14 21:37:28 +0400 |
commit | d7e9660ad9d5e0845f52848bce31bcf5cdcdea6b (patch) | |
tree | c6c67d145771187b194d79d603742b31090a59d6 /drivers/net/wireless/iwmc3200wifi/main.c | |
parent | b8cb48aae1b8c50b37dcb7710363aa69a7a0d9ca (diff) | |
parent | 13af7a6ea502fcdd4c0e3d7de6e332b102309491 (diff) | |
download | linux-d7e9660ad9d5e0845f52848bce31bcf5cdcdea6b.tar.xz |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6: (1623 commits)
netxen: update copyright
netxen: fix tx timeout recovery
netxen: fix file firmware leak
netxen: improve pci memory access
netxen: change firmware write size
tg3: Fix return ring size breakage
netxen: build fix for INET=n
cdc-phonet: autoconfigure Phonet address
Phonet: back-end for autoconfigured addresses
Phonet: fix netlink address dump error handling
ipv6: Add IFA_F_DADFAILED flag
net: Add DEVTYPE support for Ethernet based devices
mv643xx_eth.c: remove unused txq_set_wrr()
ucc_geth: Fix hangs after switching from full to half duplex
ucc_geth: Rearrange some code to avoid forward declarations
phy/marvell: Make non-aneg speed/duplex forcing work for 88E1111 PHYs
drivers/net/phy: introduce missing kfree
drivers/net/wan: introduce missing kfree
net: force bridge module(s) to be GPL
Subject: [PATCH] appletalk: Fix skb leak when ipddp interface is not loaded
...
Fixed up trivial conflicts:
- arch/x86/include/asm/socket.h
converted to <asm-generic/socket.h> in the x86 tree. The generic
header has the same new #define's, so that works out fine.
- drivers/net/tun.c
fix conflict between 89f56d1e9 ("tun: reuse struct sock fields") that
switched over to using 'tun->socket.sk' instead of the redundantly
available (and thus removed) 'tun->sk', and 2b980dbd ("lsm: Add hooks
to the TUN driver") which added a new 'tun->sk' use.
Noted in 'next' by Stephen Rothwell.
Diffstat (limited to 'drivers/net/wireless/iwmc3200wifi/main.c')
-rw-r--r-- | drivers/net/wireless/iwmc3200wifi/main.c | 103 |
1 files changed, 65 insertions, 38 deletions
diff --git a/drivers/net/wireless/iwmc3200wifi/main.c b/drivers/net/wireless/iwmc3200wifi/main.c index 8be206d58222..d668e4756324 100644 --- a/drivers/net/wireless/iwmc3200wifi/main.c +++ b/drivers/net/wireless/iwmc3200wifi/main.c @@ -53,11 +53,12 @@ static struct iwm_conf def_iwm_conf = { .sdio_ior_timeout = 5000, - .init_calib_map = BIT(PHY_CALIBRATE_DC_CMD) | - BIT(PHY_CALIBRATE_LO_CMD) | - BIT(PHY_CALIBRATE_TX_IQ_CMD) | - BIT(PHY_CALIBRATE_RX_IQ_CMD), - .periodic_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) | @@ -112,8 +113,28 @@ static void iwm_statistics_request(struct work_struct *work) iwm_send_umac_stats_req(iwm, 0); } -int __iwm_up(struct iwm_priv *iwm); -int __iwm_down(struct iwm_priv *iwm); +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); +} + +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) { @@ -166,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); @@ -179,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) @@ -191,6 +213,7 @@ int iwm_priv_init(struct iwm_priv *iwm) INIT_LIST_HEAD(&iwm->pending_notif); init_waitqueue_head(&iwm->notif_queue); init_waitqueue_head(&iwm->nonwifi_queue); + init_waitqueue_head(&iwm->wifi_ntfy_queue); init_waitqueue_head(&iwm->mlme_queue); memcpy(&iwm->conf, &def_iwm_conf, sizeof(struct iwm_conf)); spin_lock_init(&iwm->tx_credit.lock); @@ -201,6 +224,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); @@ -229,13 +253,18 @@ int iwm_priv_init(struct iwm_priv *iwm) for (i = 0; i < IWM_NUM_KEYS; i++) memset(&iwm->keys[i], 0, sizeof(struct iwm_key)); - iwm->default_key = NULL; + iwm->default_key = -1; init_timer(&iwm->watchdog); iwm->watchdog.function = iwm_watchdog; 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; } @@ -247,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); } /* @@ -261,7 +291,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) { @@ -277,6 +311,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: * @@ -500,6 +541,13 @@ void iwm_link_off(struct iwm_priv *iwm) memset(wstats, 0, sizeof(struct iw_statistics)); wstats->qual.updated = IW_QUAL_ALL_INVALID; + kfree(iwm->req_ie); + iwm->req_ie = NULL; + iwm->req_ie_len = 0; + kfree(iwm->resp_ie); + iwm->resp_ie = NULL; + iwm->resp_ie_len = 0; + del_timer_sync(&iwm->watchdog); } @@ -518,13 +566,6 @@ static int iwm_channels_init(struct iwm_priv *iwm) { int ret; -#ifdef CONFIG_IWM_B0_HW_SUPPORT - if (iwm->conf.hw_b0) { - IWM_INFO(iwm, "Workaround EEPROM channels for B0 hardware\n"); - return 0; - } -#endif - ret = iwm_send_umac_channel_list(iwm); if (ret) { IWM_ERR(iwm, "Send channel list failed\n"); @@ -541,7 +582,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; @@ -642,19 +683,10 @@ int __iwm_up(struct iwm_priv *iwm) } } - iwm->umac_profile = kmalloc(sizeof(struct iwm_umac_profile), - GFP_KERNEL); - if (!iwm->umac_profile) { - IWM_ERR(iwm, "Couldn't alloc memory for profile\n"); - goto err_fw; - } - - iwm_init_default_profile(iwm, iwm->umac_profile); - ret = iwm_channels_init(iwm); if (ret < 0) { IWM_ERR(iwm, "Couldn't init channels\n"); - goto err_profile; + goto err_fw; } /* Set the READY bit to indicate interface is brought up successfully */ @@ -662,10 +694,6 @@ int __iwm_up(struct iwm_priv *iwm) return 0; - err_profile: - kfree(iwm->umac_profile); - iwm->umac_profile = NULL; - err_fw: iwm_eeprom_exit(iwm); @@ -688,7 +716,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; @@ -704,11 +732,10 @@ int __iwm_down(struct iwm_priv *iwm) clear_bit(IWM_STATUS_READY, &iwm->status); iwm_eeprom_exit(iwm); - kfree(iwm->umac_profile); - iwm->umac_profile = NULL; iwm_bss_list_clean(iwm); - - iwm->default_key = NULL; + iwm_init_default_profile(iwm, iwm->umac_profile); + iwm->umac_profile_active = false; + iwm->default_key = -1; iwm->core_enabled = 0; ret = iwm_bus_disable(iwm); |