提交 d8598981 编写于 作者: J John W. Linville

Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6

Conflicts:
	drivers/net/wireless/ath/ath5k/sysfs.c
	net/bluetooth/l2cap_core.c
	net/mac80211/wpa.c
...@@ -693,14 +693,12 @@ ath5k_eeprom_free_pcal_info(struct ath5k_hw *ah, int mode) ...@@ -693,14 +693,12 @@ ath5k_eeprom_free_pcal_info(struct ath5k_hw *ah, int mode)
if (!chinfo[pier].pd_curves) if (!chinfo[pier].pd_curves)
continue; continue;
for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) { for (pdg = 0; pdg < AR5K_EEPROM_N_PD_CURVES; pdg++) {
struct ath5k_pdgain_info *pd = struct ath5k_pdgain_info *pd =
&chinfo[pier].pd_curves[pdg]; &chinfo[pier].pd_curves[pdg];
if (pd != NULL) { kfree(pd->pd_step);
kfree(pd->pd_step); kfree(pd->pd_pwr);
kfree(pd->pd_pwr);
}
} }
kfree(chinfo[pier].pd_curves); kfree(chinfo[pier].pd_curves);
......
...@@ -297,7 +297,9 @@ ath5k_pci_remove(struct pci_dev *pdev) ...@@ -297,7 +297,9 @@ ath5k_pci_remove(struct pci_dev *pdev)
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
static int ath5k_pci_suspend(struct device *dev) static int ath5k_pci_suspend(struct device *dev)
{ {
struct ath5k_softc *sc = pci_get_drvdata(to_pci_dev(dev)); struct pci_dev *pdev = to_pci_dev(dev);
struct ieee80211_hw *hw = pci_get_drvdata(pdev);
struct ath5k_softc *sc = hw->priv;
ath5k_led_off(sc); ath5k_led_off(sc);
return 0; return 0;
...@@ -306,7 +308,8 @@ static int ath5k_pci_suspend(struct device *dev) ...@@ -306,7 +308,8 @@ static int ath5k_pci_suspend(struct device *dev)
static int ath5k_pci_resume(struct device *dev) static int ath5k_pci_resume(struct device *dev)
{ {
struct pci_dev *pdev = to_pci_dev(dev); struct pci_dev *pdev = to_pci_dev(dev);
struct ath5k_softc *sc = pci_get_drvdata(pdev); struct ieee80211_hw *hw = pci_get_drvdata(pdev);
struct ath5k_softc *sc = hw->priv;
/* /*
* Suspend/Resume resets the PCI configuration space, so we have to * Suspend/Resume resets the PCI configuration space, so we have to
......
...@@ -10,7 +10,8 @@ static ssize_t ath5k_attr_show_##name(struct device *dev, \ ...@@ -10,7 +10,8 @@ static ssize_t ath5k_attr_show_##name(struct device *dev, \
struct device_attribute *attr, \ struct device_attribute *attr, \
char *buf) \ char *buf) \
{ \ { \
struct ath5k_softc *sc = dev_get_drvdata(dev); \ struct ieee80211_hw *hw = dev_get_drvdata(dev); \
struct ath5k_softc *sc = hw->priv; \
return snprintf(buf, PAGE_SIZE, "%d\n", get); \ return snprintf(buf, PAGE_SIZE, "%d\n", get); \
} \ } \
\ \
...@@ -18,7 +19,8 @@ static ssize_t ath5k_attr_store_##name(struct device *dev, \ ...@@ -18,7 +19,8 @@ static ssize_t ath5k_attr_store_##name(struct device *dev, \
struct device_attribute *attr, \ struct device_attribute *attr, \
const char *buf, size_t count) \ const char *buf, size_t count) \
{ \ { \
struct ath5k_softc *sc = dev_get_drvdata(dev); \ struct ieee80211_hw *hw = dev_get_drvdata(dev); \
struct ath5k_softc *sc = hw->priv; \
int val, ret; \ int val, ret; \
\ \
ret = kstrtoint(buf, 10, &val); \ ret = kstrtoint(buf, 10, &val); \
...@@ -35,7 +37,8 @@ static ssize_t ath5k_attr_show_##name(struct device *dev, \ ...@@ -35,7 +37,8 @@ static ssize_t ath5k_attr_show_##name(struct device *dev, \
struct device_attribute *attr, \ struct device_attribute *attr, \
char *buf) \ char *buf) \
{ \ { \
struct ath5k_softc *sc = dev_get_drvdata(dev); \ struct ieee80211_hw *hw = dev_get_drvdata(dev); \
struct ath5k_softc *sc = hw->priv; \
return snprintf(buf, PAGE_SIZE, "%d\n", get); \ return snprintf(buf, PAGE_SIZE, "%d\n", get); \
} \ } \
static DEVICE_ATTR(name, S_IRUGO, ath5k_attr_show_##name, NULL) static DEVICE_ATTR(name, S_IRUGO, ath5k_attr_show_##name, NULL)
......
...@@ -278,6 +278,12 @@ static int ath_pci_suspend(struct device *device) ...@@ -278,6 +278,12 @@ static int ath_pci_suspend(struct device *device)
ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1); ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1);
/* The device has to be moved to FULLSLEEP forcibly.
* Otherwise the chip never moved to full sleep,
* when no interface is up.
*/
ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP);
return 0; return 0;
} }
......
...@@ -661,7 +661,8 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid, ...@@ -661,7 +661,8 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,
* TODO - this could be improved to be dependent on the rate. * TODO - this could be improved to be dependent on the rate.
* The hardware can keep up at lower rates, but not higher rates * The hardware can keep up at lower rates, but not higher rates
*/ */
if (fi->keyix != ATH9K_TXKEYIX_INVALID) if ((fi->keyix != ATH9K_TXKEYIX_INVALID) &&
!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA))
ndelim += ATH_AGGR_ENCRYPTDELIM; ndelim += ATH_AGGR_ENCRYPTDELIM;
/* /*
......
...@@ -112,6 +112,8 @@ static struct usb_device_id carl9170_usb_ids[] = { ...@@ -112,6 +112,8 @@ static struct usb_device_id carl9170_usb_ids[] = {
{ USB_DEVICE(0x04bb, 0x093f) }, { USB_DEVICE(0x04bb, 0x093f) },
/* NEC WL300NU-G */ /* NEC WL300NU-G */
{ USB_DEVICE(0x0409, 0x0249) }, { USB_DEVICE(0x0409, 0x0249) },
/* NEC WL300NU-AG */
{ USB_DEVICE(0x0409, 0x02b4) },
/* AVM FRITZ!WLAN USB Stick N */ /* AVM FRITZ!WLAN USB Stick N */
{ USB_DEVICE(0x057c, 0x8401) }, { USB_DEVICE(0x057c, 0x8401) },
/* AVM FRITZ!WLAN USB Stick N 2.4 */ /* AVM FRITZ!WLAN USB Stick N 2.4 */
......
...@@ -298,6 +298,7 @@ static struct usb_device_id rtl8192c_usb_ids[] = { ...@@ -298,6 +298,7 @@ static struct usb_device_id rtl8192c_usb_ids[] = {
{RTL_USB_DEVICE(0x06f8, 0xe033, rtl92cu_hal_cfg)}, /*Hercules - Edimax*/ {RTL_USB_DEVICE(0x06f8, 0xe033, rtl92cu_hal_cfg)}, /*Hercules - Edimax*/
{RTL_USB_DEVICE(0x07b8, 0x8188, rtl92cu_hal_cfg)}, /*Abocom - Abocom*/ {RTL_USB_DEVICE(0x07b8, 0x8188, rtl92cu_hal_cfg)}, /*Abocom - Abocom*/
{RTL_USB_DEVICE(0x07b8, 0x8189, rtl92cu_hal_cfg)}, /*Funai - Abocom*/ {RTL_USB_DEVICE(0x07b8, 0x8189, rtl92cu_hal_cfg)}, /*Funai - Abocom*/
{RTL_USB_DEVICE(0x0846, 0x9041, rtl92cu_hal_cfg)}, /*NetGear WNA1000M*/
{RTL_USB_DEVICE(0x0Df6, 0x0052, rtl92cu_hal_cfg)}, /*Sitecom - Edimax*/ {RTL_USB_DEVICE(0x0Df6, 0x0052, rtl92cu_hal_cfg)}, /*Sitecom - Edimax*/
{RTL_USB_DEVICE(0x0eb0, 0x9071, rtl92cu_hal_cfg)}, /*NO Brand - Etop*/ {RTL_USB_DEVICE(0x0eb0, 0x9071, rtl92cu_hal_cfg)}, /*NO Brand - Etop*/
/* HP - Lite-On ,8188CUS Slim Combo */ /* HP - Lite-On ,8188CUS Slim Combo */
......
...@@ -516,8 +516,17 @@ static void ssb_pcicore_pcie_setup_workarounds(struct ssb_pcicore *pc) ...@@ -516,8 +516,17 @@ static void ssb_pcicore_pcie_setup_workarounds(struct ssb_pcicore *pc)
static void __devinit ssb_pcicore_init_clientmode(struct ssb_pcicore *pc) static void __devinit ssb_pcicore_init_clientmode(struct ssb_pcicore *pc)
{ {
ssb_pcicore_fix_sprom_core_index(pc);
/* Disable PCI interrupts. */ /* Disable PCI interrupts. */
ssb_write32(pc->dev, SSB_INTVEC, 0); ssb_write32(pc->dev, SSB_INTVEC, 0);
/* Additional PCIe always once-executed workarounds */
if (pc->dev->id.coreid == SSB_DEV_PCIE) {
ssb_pcicore_serdes_workaround(pc);
/* TODO: ASPM */
/* TODO: Clock Request Update */
}
} }
void __devinit ssb_pcicore_init(struct ssb_pcicore *pc) void __devinit ssb_pcicore_init(struct ssb_pcicore *pc)
...@@ -529,8 +538,6 @@ void __devinit ssb_pcicore_init(struct ssb_pcicore *pc) ...@@ -529,8 +538,6 @@ void __devinit ssb_pcicore_init(struct ssb_pcicore *pc)
if (!ssb_device_is_enabled(dev)) if (!ssb_device_is_enabled(dev))
ssb_device_enable(dev, 0); ssb_device_enable(dev, 0);
ssb_pcicore_fix_sprom_core_index(pc);
#ifdef CONFIG_SSB_PCICORE_HOSTMODE #ifdef CONFIG_SSB_PCICORE_HOSTMODE
pc->hostmode = pcicore_is_in_hostmode(pc); pc->hostmode = pcicore_is_in_hostmode(pc);
if (pc->hostmode) if (pc->hostmode)
...@@ -538,13 +545,6 @@ void __devinit ssb_pcicore_init(struct ssb_pcicore *pc) ...@@ -538,13 +545,6 @@ void __devinit ssb_pcicore_init(struct ssb_pcicore *pc)
#endif /* CONFIG_SSB_PCICORE_HOSTMODE */ #endif /* CONFIG_SSB_PCICORE_HOSTMODE */
if (!pc->hostmode) if (!pc->hostmode)
ssb_pcicore_init_clientmode(pc); ssb_pcicore_init_clientmode(pc);
/* Additional PCIe always once-executed workarounds */
if (dev->id.coreid == SSB_DEV_PCIE) {
ssb_pcicore_serdes_workaround(pc);
/* TODO: ASPM */
/* TODO: Clock Request Update */
}
} }
static u32 ssb_pcie_read(struct ssb_pcicore *pc, u32 address) static u32 ssb_pcie_read(struct ssb_pcicore *pc, u32 address)
......
...@@ -444,6 +444,9 @@ int hci_conn_del(struct hci_conn *conn) ...@@ -444,6 +444,9 @@ int hci_conn_del(struct hci_conn *conn)
hci_dev_put(hdev); hci_dev_put(hdev);
if (conn->handle == 0)
kfree(conn);
return 0; return 0;
} }
......
...@@ -464,7 +464,8 @@ static void hidp_idle_timeout(unsigned long arg) ...@@ -464,7 +464,8 @@ static void hidp_idle_timeout(unsigned long arg)
{ {
struct hidp_session *session = (struct hidp_session *) arg; struct hidp_session *session = (struct hidp_session *) arg;
kthread_stop(session->task); atomic_inc(&session->terminate);
wake_up_process(session->task);
} }
static void hidp_set_timer(struct hidp_session *session) static void hidp_set_timer(struct hidp_session *session)
...@@ -535,7 +536,8 @@ static void hidp_process_hid_control(struct hidp_session *session, ...@@ -535,7 +536,8 @@ static void hidp_process_hid_control(struct hidp_session *session,
skb_queue_purge(&session->ctrl_transmit); skb_queue_purge(&session->ctrl_transmit);
skb_queue_purge(&session->intr_transmit); skb_queue_purge(&session->intr_transmit);
kthread_stop(session->task); atomic_inc(&session->terminate);
wake_up_process(current);
} }
} }
...@@ -706,9 +708,8 @@ static int hidp_session(void *arg) ...@@ -706,9 +708,8 @@ static int hidp_session(void *arg)
add_wait_queue(sk_sleep(intr_sk), &intr_wait); add_wait_queue(sk_sleep(intr_sk), &intr_wait);
session->waiting_for_startup = 0; session->waiting_for_startup = 0;
wake_up_interruptible(&session->startup_queue); wake_up_interruptible(&session->startup_queue);
while (!kthread_should_stop()) { set_current_state(TASK_INTERRUPTIBLE);
set_current_state(TASK_INTERRUPTIBLE); while (!atomic_read(&session->terminate)) {
if (ctrl_sk->sk_state != BT_CONNECTED || if (ctrl_sk->sk_state != BT_CONNECTED ||
intr_sk->sk_state != BT_CONNECTED) intr_sk->sk_state != BT_CONNECTED)
break; break;
...@@ -726,6 +727,7 @@ static int hidp_session(void *arg) ...@@ -726,6 +727,7 @@ static int hidp_session(void *arg)
hidp_process_transmit(session); hidp_process_transmit(session);
schedule(); schedule();
set_current_state(TASK_INTERRUPTIBLE);
} }
set_current_state(TASK_RUNNING); set_current_state(TASK_RUNNING);
remove_wait_queue(sk_sleep(intr_sk), &intr_wait); remove_wait_queue(sk_sleep(intr_sk), &intr_wait);
...@@ -1060,7 +1062,8 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, ...@@ -1060,7 +1062,8 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
err_add_device: err_add_device:
hid_destroy_device(session->hid); hid_destroy_device(session->hid);
session->hid = NULL; session->hid = NULL;
kthread_stop(session->task); atomic_inc(&session->terminate);
wake_up_process(session->task);
unlink: unlink:
hidp_del_timer(session); hidp_del_timer(session);
...@@ -1111,7 +1114,8 @@ int hidp_del_connection(struct hidp_conndel_req *req) ...@@ -1111,7 +1114,8 @@ int hidp_del_connection(struct hidp_conndel_req *req)
skb_queue_purge(&session->ctrl_transmit); skb_queue_purge(&session->ctrl_transmit);
skb_queue_purge(&session->intr_transmit); skb_queue_purge(&session->intr_transmit);
kthread_stop(session->task); atomic_inc(&session->terminate);
wake_up_process(session->task);
} }
} else } else
err = -ENOENT; err = -ENOENT;
......
...@@ -142,6 +142,7 @@ struct hidp_session { ...@@ -142,6 +142,7 @@ struct hidp_session {
uint ctrl_mtu; uint ctrl_mtu;
uint intr_mtu; uint intr_mtu;
atomic_t terminate;
struct task_struct *task; struct task_struct *task;
unsigned char keys[8]; unsigned char keys[8];
......
...@@ -2530,7 +2530,8 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr ...@@ -2530,7 +2530,8 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
sk = chan->sk; sk = chan->sk;
if (chan->state != BT_CONFIG) { if ((bt_sk(sk)->defer_setup && chan->state != BT_CONNECT2) ||
(!bt_sk(sk)->defer_setup && chan->state != BT_CONFIG)) {
struct l2cap_cmd_rej rej; struct l2cap_cmd_rej rej;
rej.reason = cpu_to_le16(0x0002); rej.reason = cpu_to_le16(0x0002);
...@@ -2541,7 +2542,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr ...@@ -2541,7 +2542,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
/* Reject if config buffer is too small. */ /* Reject if config buffer is too small. */
len = cmd_len - sizeof(*req); len = cmd_len - sizeof(*req);
if (chan->conf_len + len > sizeof(chan->conf_req)) { if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) {
l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
l2cap_build_conf_rsp(chan, rsp, l2cap_build_conf_rsp(chan, rsp,
L2CAP_CONF_REJECT, flags), rsp); L2CAP_CONF_REJECT, flags), rsp);
......
...@@ -884,7 +884,8 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, ...@@ -884,7 +884,8 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
for (i = 0; i < IEEE80211_NUM_BANDS; i++) { for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
local->sched_scan_ies.ie[i] = kzalloc(2 + local->sched_scan_ies.ie[i] = kzalloc(2 +
IEEE80211_MAX_SSID_LEN + IEEE80211_MAX_SSID_LEN +
local->scan_ies_len, local->scan_ies_len +
req->ie_len,
GFP_KERNEL); GFP_KERNEL);
if (!local->sched_scan_ies.ie[i]) { if (!local->sched_scan_ies.ie[i]) {
ret = -ENOMEM; ret = -ENOMEM;
......
...@@ -366,6 +366,7 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv) ...@@ -366,6 +366,7 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
mutex_init(&rdev->mtx); mutex_init(&rdev->mtx);
mutex_init(&rdev->devlist_mtx); mutex_init(&rdev->devlist_mtx);
mutex_init(&rdev->sched_scan_mtx);
INIT_LIST_HEAD(&rdev->netdev_list); INIT_LIST_HEAD(&rdev->netdev_list);
spin_lock_init(&rdev->bss_lock); spin_lock_init(&rdev->bss_lock);
INIT_LIST_HEAD(&rdev->bss_list); INIT_LIST_HEAD(&rdev->bss_list);
...@@ -701,6 +702,7 @@ void cfg80211_dev_free(struct cfg80211_registered_device *rdev) ...@@ -701,6 +702,7 @@ void cfg80211_dev_free(struct cfg80211_registered_device *rdev)
rfkill_destroy(rdev->rfkill); rfkill_destroy(rdev->rfkill);
mutex_destroy(&rdev->mtx); mutex_destroy(&rdev->mtx);
mutex_destroy(&rdev->devlist_mtx); mutex_destroy(&rdev->devlist_mtx);
mutex_destroy(&rdev->sched_scan_mtx);
list_for_each_entry_safe(scan, tmp, &rdev->bss_list, list) list_for_each_entry_safe(scan, tmp, &rdev->bss_list, list)
cfg80211_put_bss(&scan->pub); cfg80211_put_bss(&scan->pub);
cfg80211_rdev_free_wowlan(rdev); cfg80211_rdev_free_wowlan(rdev);
...@@ -737,12 +739,16 @@ static void wdev_cleanup_work(struct work_struct *work) ...@@ -737,12 +739,16 @@ static void wdev_cleanup_work(struct work_struct *work)
___cfg80211_scan_done(rdev, true); ___cfg80211_scan_done(rdev, true);
} }
cfg80211_unlock_rdev(rdev);
mutex_lock(&rdev->sched_scan_mtx);
if (WARN_ON(rdev->sched_scan_req && if (WARN_ON(rdev->sched_scan_req &&
rdev->sched_scan_req->dev == wdev->netdev)) { rdev->sched_scan_req->dev == wdev->netdev)) {
__cfg80211_stop_sched_scan(rdev, false); __cfg80211_stop_sched_scan(rdev, false);
} }
cfg80211_unlock_rdev(rdev); mutex_unlock(&rdev->sched_scan_mtx);
mutex_lock(&rdev->devlist_mtx); mutex_lock(&rdev->devlist_mtx);
rdev->opencount--; rdev->opencount--;
...@@ -830,9 +836,9 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, ...@@ -830,9 +836,9 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
break; break;
case NL80211_IFTYPE_P2P_CLIENT: case NL80211_IFTYPE_P2P_CLIENT:
case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_STATION:
cfg80211_lock_rdev(rdev); mutex_lock(&rdev->sched_scan_mtx);
__cfg80211_stop_sched_scan(rdev, false); __cfg80211_stop_sched_scan(rdev, false);
cfg80211_unlock_rdev(rdev); mutex_unlock(&rdev->sched_scan_mtx);
wdev_lock(wdev); wdev_lock(wdev);
#ifdef CONFIG_CFG80211_WEXT #ifdef CONFIG_CFG80211_WEXT
......
...@@ -65,6 +65,8 @@ struct cfg80211_registered_device { ...@@ -65,6 +65,8 @@ struct cfg80211_registered_device {
struct work_struct scan_done_wk; struct work_struct scan_done_wk;
struct work_struct sched_scan_results_wk; struct work_struct sched_scan_results_wk;
struct mutex sched_scan_mtx;
#ifdef CONFIG_NL80211_TESTMODE #ifdef CONFIG_NL80211_TESTMODE
struct genl_info *testmode_info; struct genl_info *testmode_info;
#endif #endif
......
...@@ -3470,9 +3470,6 @@ static int nl80211_start_sched_scan(struct sk_buff *skb, ...@@ -3470,9 +3470,6 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
return -EINVAL; return -EINVAL;
if (rdev->sched_scan_req)
return -EINPROGRESS;
if (!info->attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL]) if (!info->attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL])
return -EINVAL; return -EINVAL;
...@@ -3511,12 +3508,21 @@ static int nl80211_start_sched_scan(struct sk_buff *skb, ...@@ -3511,12 +3508,21 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
if (ie_len > wiphy->max_scan_ie_len) if (ie_len > wiphy->max_scan_ie_len)
return -EINVAL; return -EINVAL;
mutex_lock(&rdev->sched_scan_mtx);
if (rdev->sched_scan_req) {
err = -EINPROGRESS;
goto out;
}
request = kzalloc(sizeof(*request) request = kzalloc(sizeof(*request)
+ sizeof(*request->ssids) * n_ssids + sizeof(*request->ssids) * n_ssids
+ sizeof(*request->channels) * n_channels + sizeof(*request->channels) * n_channels
+ ie_len, GFP_KERNEL); + ie_len, GFP_KERNEL);
if (!request) if (!request) {
return -ENOMEM; err = -ENOMEM;
goto out;
}
if (n_ssids) if (n_ssids)
request->ssids = (void *)&request->channels[n_channels]; request->ssids = (void *)&request->channels[n_channels];
...@@ -3614,6 +3620,7 @@ static int nl80211_start_sched_scan(struct sk_buff *skb, ...@@ -3614,6 +3620,7 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
out_free: out_free:
kfree(request); kfree(request);
out: out:
mutex_unlock(&rdev->sched_scan_mtx);
return err; return err;
} }
...@@ -3621,12 +3628,17 @@ static int nl80211_stop_sched_scan(struct sk_buff *skb, ...@@ -3621,12 +3628,17 @@ static int nl80211_stop_sched_scan(struct sk_buff *skb,
struct genl_info *info) struct genl_info *info)
{ {
struct cfg80211_registered_device *rdev = info->user_ptr[0]; struct cfg80211_registered_device *rdev = info->user_ptr[0];
int err;
if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) || if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) ||
!rdev->ops->sched_scan_stop) !rdev->ops->sched_scan_stop)
return -EOPNOTSUPP; return -EOPNOTSUPP;
return __cfg80211_stop_sched_scan(rdev, false); mutex_lock(&rdev->sched_scan_mtx);
err = __cfg80211_stop_sched_scan(rdev, false);
mutex_unlock(&rdev->sched_scan_mtx);
return err;
} }
static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb, static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
......
...@@ -100,14 +100,14 @@ void __cfg80211_sched_scan_results(struct work_struct *wk) ...@@ -100,14 +100,14 @@ void __cfg80211_sched_scan_results(struct work_struct *wk)
rdev = container_of(wk, struct cfg80211_registered_device, rdev = container_of(wk, struct cfg80211_registered_device,
sched_scan_results_wk); sched_scan_results_wk);
cfg80211_lock_rdev(rdev); mutex_lock(&rdev->sched_scan_mtx);
/* we don't have sched_scan_req anymore if the scan is stopping */ /* we don't have sched_scan_req anymore if the scan is stopping */
if (rdev->sched_scan_req) if (rdev->sched_scan_req)
nl80211_send_sched_scan_results(rdev, nl80211_send_sched_scan_results(rdev,
rdev->sched_scan_req->dev); rdev->sched_scan_req->dev);
cfg80211_unlock_rdev(rdev); mutex_unlock(&rdev->sched_scan_mtx);
} }
void cfg80211_sched_scan_results(struct wiphy *wiphy) void cfg80211_sched_scan_results(struct wiphy *wiphy)
...@@ -123,9 +123,9 @@ void cfg80211_sched_scan_stopped(struct wiphy *wiphy) ...@@ -123,9 +123,9 @@ void cfg80211_sched_scan_stopped(struct wiphy *wiphy)
{ {
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
cfg80211_lock_rdev(rdev); mutex_lock(&rdev->sched_scan_mtx);
__cfg80211_stop_sched_scan(rdev, true); __cfg80211_stop_sched_scan(rdev, true);
cfg80211_unlock_rdev(rdev); mutex_unlock(&rdev->sched_scan_mtx);
} }
EXPORT_SYMBOL(cfg80211_sched_scan_stopped); EXPORT_SYMBOL(cfg80211_sched_scan_stopped);
...@@ -134,7 +134,7 @@ int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev, ...@@ -134,7 +134,7 @@ int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev,
{ {
struct net_device *dev; struct net_device *dev;
ASSERT_RDEV_LOCK(rdev); lockdep_assert_held(&rdev->sched_scan_mtx);
if (!rdev->sched_scan_req) if (!rdev->sched_scan_req)
return -ENOENT; return -ENOENT;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册