Commit 076e7779 authored by John W. Linville's avatar John W. Linville

Merge branch 'master' of...

Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless into for-davem
parents 116a0fc3 66f2c99a
...@@ -75,6 +75,8 @@ static struct usb_device_id ath3k_table[] = { ...@@ -75,6 +75,8 @@ static struct usb_device_id ath3k_table[] = {
{ USB_DEVICE(0x0CF3, 0x311D) }, { USB_DEVICE(0x0CF3, 0x311D) },
{ USB_DEVICE(0x13d3, 0x3375) }, { USB_DEVICE(0x13d3, 0x3375) },
{ USB_DEVICE(0x04CA, 0x3005) }, { USB_DEVICE(0x04CA, 0x3005) },
{ USB_DEVICE(0x13d3, 0x3362) },
{ USB_DEVICE(0x0CF3, 0xE004) },
/* Atheros AR5BBU12 with sflash firmware */ /* Atheros AR5BBU12 with sflash firmware */
{ USB_DEVICE(0x0489, 0xE02C) }, { USB_DEVICE(0x0489, 0xE02C) },
...@@ -94,6 +96,8 @@ static struct usb_device_id ath3k_blist_tbl[] = { ...@@ -94,6 +96,8 @@ static struct usb_device_id ath3k_blist_tbl[] = {
{ USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
{ } /* Terminating entry */ { } /* Terminating entry */
}; };
......
...@@ -101,12 +101,16 @@ static struct usb_device_id btusb_table[] = { ...@@ -101,12 +101,16 @@ static struct usb_device_id btusb_table[] = {
{ USB_DEVICE(0x0c10, 0x0000) }, { USB_DEVICE(0x0c10, 0x0000) },
/* Broadcom BCM20702A0 */ /* Broadcom BCM20702A0 */
{ USB_DEVICE(0x0489, 0xe042) },
{ USB_DEVICE(0x0a5c, 0x21e3) }, { USB_DEVICE(0x0a5c, 0x21e3) },
{ USB_DEVICE(0x0a5c, 0x21e6) }, { USB_DEVICE(0x0a5c, 0x21e6) },
{ USB_DEVICE(0x0a5c, 0x21e8) }, { USB_DEVICE(0x0a5c, 0x21e8) },
{ USB_DEVICE(0x0a5c, 0x21f3) }, { USB_DEVICE(0x0a5c, 0x21f3) },
{ USB_DEVICE(0x413c, 0x8197) }, { USB_DEVICE(0x413c, 0x8197) },
/* Foxconn - Hon Hai */
{ USB_DEVICE(0x0489, 0xe033) },
{ } /* Terminating entry */ { } /* Terminating entry */
}; };
...@@ -133,6 +137,8 @@ static struct usb_device_id blacklist_table[] = { ...@@ -133,6 +137,8 @@ static struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
/* Atheros AR5BBU12 with sflash firmware */ /* Atheros AR5BBU12 with sflash firmware */
{ USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE }, { USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE },
......
...@@ -220,6 +220,7 @@ static int ath_ahb_remove(struct platform_device *pdev) ...@@ -220,6 +220,7 @@ static int ath_ahb_remove(struct platform_device *pdev)
} }
ath5k_deinit_ah(ah); ath5k_deinit_ah(ah);
iounmap(ah->iobase);
platform_set_drvdata(pdev, NULL); platform_set_drvdata(pdev, NULL);
ieee80211_free_hw(hw); ieee80211_free_hw(hw);
......
...@@ -4827,8 +4827,14 @@ static int b43_op_start(struct ieee80211_hw *hw) ...@@ -4827,8 +4827,14 @@ static int b43_op_start(struct ieee80211_hw *hw)
out_mutex_unlock: out_mutex_unlock:
mutex_unlock(&wl->mutex); mutex_unlock(&wl->mutex);
/* reload configuration */ /*
b43_op_config(hw, ~0); * Configuration may have been overwritten during initialization.
* Reload the configuration, but only if initialization was
* successful. Reloading the configuration after a failed init
* may hang the system.
*/
if (!err)
b43_op_config(hw, ~0);
return err; return err;
} }
......
...@@ -108,9 +108,15 @@ static inline int brcmf_sdioh_f0_write_byte(struct brcmf_sdio_dev *sdiodev, ...@@ -108,9 +108,15 @@ static inline int brcmf_sdioh_f0_write_byte(struct brcmf_sdio_dev *sdiodev,
sdio_release_host(sdfunc); sdio_release_host(sdfunc);
} }
} else if (regaddr == SDIO_CCCR_ABORT) { } else if (regaddr == SDIO_CCCR_ABORT) {
sdfunc = kmemdup(sdiodev->func[0], sizeof(struct sdio_func),
GFP_KERNEL);
if (!sdfunc)
return -ENOMEM;
sdfunc->num = 0;
sdio_claim_host(sdfunc); sdio_claim_host(sdfunc);
sdio_writeb(sdfunc, *byte, regaddr, &err_ret); sdio_writeb(sdfunc, *byte, regaddr, &err_ret);
sdio_release_host(sdfunc); sdio_release_host(sdfunc);
kfree(sdfunc);
} else if (regaddr < 0xF0) { } else if (regaddr < 0xF0) {
brcmf_dbg(ERROR, "F0 Wr:0x%02x: write disallowed\n", regaddr); brcmf_dbg(ERROR, "F0 Wr:0x%02x: write disallowed\n", regaddr);
err_ret = -EPERM; err_ret = -EPERM;
...@@ -486,7 +492,7 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func, ...@@ -486,7 +492,7 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func,
kfree(bus_if); kfree(bus_if);
return -ENOMEM; return -ENOMEM;
} }
sdiodev->func[0] = func->card->sdio_func[0]; sdiodev->func[0] = func;
sdiodev->func[1] = func; sdiodev->func[1] = func;
sdiodev->bus_if = bus_if; sdiodev->bus_if = bus_if;
bus_if->bus_priv.sdio = sdiodev; bus_if->bus_priv.sdio = sdiodev;
......
...@@ -574,6 +574,8 @@ struct brcmf_sdio { ...@@ -574,6 +574,8 @@ struct brcmf_sdio {
struct task_struct *dpc_tsk; struct task_struct *dpc_tsk;
struct completion dpc_wait; struct completion dpc_wait;
struct list_head dpc_tsklst;
spinlock_t dpc_tl_lock;
struct semaphore sdsem; struct semaphore sdsem;
...@@ -2594,29 +2596,58 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) ...@@ -2594,29 +2596,58 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
return resched; return resched;
} }
static inline void brcmf_sdbrcm_adddpctsk(struct brcmf_sdio *bus)
{
struct list_head *new_hd;
unsigned long flags;
if (in_interrupt())
new_hd = kzalloc(sizeof(struct list_head), GFP_ATOMIC);
else
new_hd = kzalloc(sizeof(struct list_head), GFP_KERNEL);
if (new_hd == NULL)
return;
spin_lock_irqsave(&bus->dpc_tl_lock, flags);
list_add_tail(new_hd, &bus->dpc_tsklst);
spin_unlock_irqrestore(&bus->dpc_tl_lock, flags);
}
static int brcmf_sdbrcm_dpc_thread(void *data) static int brcmf_sdbrcm_dpc_thread(void *data)
{ {
struct brcmf_sdio *bus = (struct brcmf_sdio *) data; struct brcmf_sdio *bus = (struct brcmf_sdio *) data;
struct list_head *cur_hd, *tmp_hd;
unsigned long flags;
allow_signal(SIGTERM); allow_signal(SIGTERM);
/* Run until signal received */ /* Run until signal received */
while (1) { while (1) {
if (kthread_should_stop()) if (kthread_should_stop())
break; break;
if (!wait_for_completion_interruptible(&bus->dpc_wait)) {
/* Call bus dpc unless it indicated down if (list_empty(&bus->dpc_tsklst))
(then clean stop) */ if (wait_for_completion_interruptible(&bus->dpc_wait))
if (bus->sdiodev->bus_if->state != BRCMF_BUS_DOWN) { break;
if (brcmf_sdbrcm_dpc(bus))
complete(&bus->dpc_wait); spin_lock_irqsave(&bus->dpc_tl_lock, flags);
} else { list_for_each_safe(cur_hd, tmp_hd, &bus->dpc_tsklst) {
spin_unlock_irqrestore(&bus->dpc_tl_lock, flags);
if (bus->sdiodev->bus_if->state == BRCMF_BUS_DOWN) {
/* after stopping the bus, exit thread */ /* after stopping the bus, exit thread */
brcmf_sdbrcm_bus_stop(bus->sdiodev->dev); brcmf_sdbrcm_bus_stop(bus->sdiodev->dev);
bus->dpc_tsk = NULL; bus->dpc_tsk = NULL;
break; break;
} }
} else
break; if (brcmf_sdbrcm_dpc(bus))
brcmf_sdbrcm_adddpctsk(bus);
spin_lock_irqsave(&bus->dpc_tl_lock, flags);
list_del(cur_hd);
kfree(cur_hd);
}
spin_unlock_irqrestore(&bus->dpc_tl_lock, flags);
} }
return 0; return 0;
} }
...@@ -2669,8 +2700,10 @@ static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt) ...@@ -2669,8 +2700,10 @@ static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt)
/* Schedule DPC if needed to send queued packet(s) */ /* Schedule DPC if needed to send queued packet(s) */
if (!bus->dpc_sched) { if (!bus->dpc_sched) {
bus->dpc_sched = true; bus->dpc_sched = true;
if (bus->dpc_tsk) if (bus->dpc_tsk) {
brcmf_sdbrcm_adddpctsk(bus);
complete(&bus->dpc_wait); complete(&bus->dpc_wait);
}
} }
return ret; return ret;
...@@ -3514,8 +3547,10 @@ void brcmf_sdbrcm_isr(void *arg) ...@@ -3514,8 +3547,10 @@ void brcmf_sdbrcm_isr(void *arg)
brcmf_dbg(ERROR, "isr w/o interrupt configured!\n"); brcmf_dbg(ERROR, "isr w/o interrupt configured!\n");
bus->dpc_sched = true; bus->dpc_sched = true;
if (bus->dpc_tsk) if (bus->dpc_tsk) {
brcmf_sdbrcm_adddpctsk(bus);
complete(&bus->dpc_wait); complete(&bus->dpc_wait);
}
} }
static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus) static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
...@@ -3559,8 +3594,10 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus) ...@@ -3559,8 +3594,10 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
bus->ipend = true; bus->ipend = true;
bus->dpc_sched = true; bus->dpc_sched = true;
if (bus->dpc_tsk) if (bus->dpc_tsk) {
brcmf_sdbrcm_adddpctsk(bus);
complete(&bus->dpc_wait); complete(&bus->dpc_wait);
}
} }
} }
...@@ -3897,6 +3934,8 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev) ...@@ -3897,6 +3934,8 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev)
} }
/* Initialize DPC thread */ /* Initialize DPC thread */
init_completion(&bus->dpc_wait); init_completion(&bus->dpc_wait);
INIT_LIST_HEAD(&bus->dpc_tsklst);
spin_lock_init(&bus->dpc_tl_lock);
bus->dpc_tsk = kthread_run(brcmf_sdbrcm_dpc_thread, bus->dpc_tsk = kthread_run(brcmf_sdbrcm_dpc_thread,
bus, "brcmf_dpc"); bus, "brcmf_dpc");
if (IS_ERR(bus->dpc_tsk)) { if (IS_ERR(bus->dpc_tsk)) {
......
...@@ -336,7 +336,7 @@ static const struct iwl_bt_params iwl6000_bt_params = { ...@@ -336,7 +336,7 @@ static const struct iwl_bt_params iwl6000_bt_params = {
#define IWL_DEVICE_6005 \ #define IWL_DEVICE_6005 \
.fw_name_pre = IWL6005_FW_PRE, \ .fw_name_pre = IWL6005_FW_PRE, \
.ucode_api_max = IWL6000G2_UCODE_API_MAX, \ .ucode_api_max = IWL6000G2_UCODE_API_MAX, \
.ucode_api_ok = IWL6000G2B_UCODE_API_OK, \ .ucode_api_ok = IWL6000G2_UCODE_API_OK, \
.ucode_api_min = IWL6000G2_UCODE_API_MIN, \ .ucode_api_min = IWL6000G2_UCODE_API_MIN, \
.max_inst_size = IWL60_RTC_INST_SIZE, \ .max_inst_size = IWL60_RTC_INST_SIZE, \
.max_data_size = IWL60_RTC_DATA_SIZE, \ .max_data_size = IWL60_RTC_DATA_SIZE, \
...@@ -390,7 +390,7 @@ const struct iwl_cfg iwl6005_2agn_mow2_cfg = { ...@@ -390,7 +390,7 @@ const struct iwl_cfg iwl6005_2agn_mow2_cfg = {
#define IWL_DEVICE_6030 \ #define IWL_DEVICE_6030 \
.fw_name_pre = IWL6030_FW_PRE, \ .fw_name_pre = IWL6030_FW_PRE, \
.ucode_api_max = IWL6000G2_UCODE_API_MAX, \ .ucode_api_max = IWL6000G2_UCODE_API_MAX, \
.ucode_api_ok = IWL6000G2_UCODE_API_OK, \ .ucode_api_ok = IWL6000G2B_UCODE_API_OK, \
.ucode_api_min = IWL6000G2_UCODE_API_MIN, \ .ucode_api_min = IWL6000G2_UCODE_API_MIN, \
.max_inst_size = IWL60_RTC_INST_SIZE, \ .max_inst_size = IWL60_RTC_INST_SIZE, \
.max_data_size = IWL60_RTC_DATA_SIZE, \ .max_data_size = IWL60_RTC_DATA_SIZE, \
......
...@@ -479,6 +479,7 @@ static void wl1251_op_stop(struct ieee80211_hw *hw) ...@@ -479,6 +479,7 @@ static void wl1251_op_stop(struct ieee80211_hw *hw)
cancel_work_sync(&wl->irq_work); cancel_work_sync(&wl->irq_work);
cancel_work_sync(&wl->tx_work); cancel_work_sync(&wl->tx_work);
cancel_work_sync(&wl->filter_work); cancel_work_sync(&wl->filter_work);
cancel_delayed_work_sync(&wl->elp_work);
mutex_lock(&wl->mutex); mutex_lock(&wl->mutex);
......
...@@ -315,8 +315,8 @@ static void __devexit wl1251_sdio_remove(struct sdio_func *func) ...@@ -315,8 +315,8 @@ static void __devexit wl1251_sdio_remove(struct sdio_func *func)
if (wl->irq) if (wl->irq)
free_irq(wl->irq, wl); free_irq(wl->irq, wl);
kfree(wl_sdio);
wl1251_free_hw(wl); wl1251_free_hw(wl);
kfree(wl_sdio);
sdio_claim_host(func); sdio_claim_host(func);
sdio_release_irq(func); sdio_release_irq(func);
......
...@@ -314,6 +314,7 @@ struct hci_conn { ...@@ -314,6 +314,7 @@ struct hci_conn {
__u8 remote_cap; __u8 remote_cap;
__u8 remote_auth; __u8 remote_auth;
bool flush_key;
unsigned int sent; unsigned int sent;
...@@ -980,7 +981,7 @@ int mgmt_discoverable(struct hci_dev *hdev, u8 discoverable); ...@@ -980,7 +981,7 @@ int mgmt_discoverable(struct hci_dev *hdev, u8 discoverable);
int mgmt_connectable(struct hci_dev *hdev, u8 connectable); int mgmt_connectable(struct hci_dev *hdev, u8 connectable);
int mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status); int mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status);
int mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key, int mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
u8 persistent); bool persistent);
int mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, int mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
u8 addr_type, u32 flags, u8 *name, u8 name_len, u8 addr_type, u32 flags, u8 *name, u8 name_len,
u8 *dev_class); u8 *dev_class);
......
...@@ -1215,40 +1215,40 @@ struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr) ...@@ -1215,40 +1215,40 @@ struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr)
return NULL; return NULL;
} }
static int hci_persistent_key(struct hci_dev *hdev, struct hci_conn *conn, static bool hci_persistent_key(struct hci_dev *hdev, struct hci_conn *conn,
u8 key_type, u8 old_key_type) u8 key_type, u8 old_key_type)
{ {
/* Legacy key */ /* Legacy key */
if (key_type < 0x03) if (key_type < 0x03)
return 1; return true;
/* Debug keys are insecure so don't store them persistently */ /* Debug keys are insecure so don't store them persistently */
if (key_type == HCI_LK_DEBUG_COMBINATION) if (key_type == HCI_LK_DEBUG_COMBINATION)
return 0; return false;
/* Changed combination key and there's no previous one */ /* Changed combination key and there's no previous one */
if (key_type == HCI_LK_CHANGED_COMBINATION && old_key_type == 0xff) if (key_type == HCI_LK_CHANGED_COMBINATION && old_key_type == 0xff)
return 0; return false;
/* Security mode 3 case */ /* Security mode 3 case */
if (!conn) if (!conn)
return 1; return true;
/* Neither local nor remote side had no-bonding as requirement */ /* Neither local nor remote side had no-bonding as requirement */
if (conn->auth_type > 0x01 && conn->remote_auth > 0x01) if (conn->auth_type > 0x01 && conn->remote_auth > 0x01)
return 1; return true;
/* Local side had dedicated bonding as requirement */ /* Local side had dedicated bonding as requirement */
if (conn->auth_type == 0x02 || conn->auth_type == 0x03) if (conn->auth_type == 0x02 || conn->auth_type == 0x03)
return 1; return true;
/* Remote side had dedicated bonding as requirement */ /* Remote side had dedicated bonding as requirement */
if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03)
return 1; return true;
/* If none of the above criteria match, then don't store the key /* If none of the above criteria match, then don't store the key
* persistently */ * persistently */
return 0; return false;
} }
struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, u8 rand[8]) struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, u8 rand[8])
...@@ -1285,7 +1285,8 @@ int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key, ...@@ -1285,7 +1285,8 @@ int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key,
bdaddr_t *bdaddr, u8 *val, u8 type, u8 pin_len) bdaddr_t *bdaddr, u8 *val, u8 type, u8 pin_len)
{ {
struct link_key *key, *old_key; struct link_key *key, *old_key;
u8 old_key_type, persistent; u8 old_key_type;
bool persistent;
old_key = hci_find_link_key(hdev, bdaddr); old_key = hci_find_link_key(hdev, bdaddr);
if (old_key) { if (old_key) {
...@@ -1328,10 +1329,8 @@ int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key, ...@@ -1328,10 +1329,8 @@ int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key,
mgmt_new_link_key(hdev, key, persistent); mgmt_new_link_key(hdev, key, persistent);
if (!persistent) { if (conn)
list_del(&key->list); conn->flush_key = !persistent;
kfree(key);
}
return 0; return 0;
} }
......
...@@ -1901,6 +1901,8 @@ static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff ...@@ -1901,6 +1901,8 @@ static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff
} }
if (ev->status == 0) { if (ev->status == 0) {
if (conn->type == ACL_LINK && conn->flush_key)
hci_remove_link_key(hdev, &conn->dst);
hci_proto_disconn_cfm(conn, ev->reason); hci_proto_disconn_cfm(conn, ev->reason);
hci_conn_del(conn); hci_conn_del(conn);
} }
...@@ -2311,6 +2313,7 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk ...@@ -2311,6 +2313,7 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk
case HCI_OP_USER_PASSKEY_NEG_REPLY: case HCI_OP_USER_PASSKEY_NEG_REPLY:
hci_cc_user_passkey_neg_reply(hdev, skb); hci_cc_user_passkey_neg_reply(hdev, skb);
break;
case HCI_OP_LE_SET_SCAN_PARAM: case HCI_OP_LE_SET_SCAN_PARAM:
hci_cc_le_set_scan_param(hdev, skb); hci_cc_le_set_scan_param(hdev, skb);
......
...@@ -2884,7 +2884,7 @@ int mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status) ...@@ -2884,7 +2884,7 @@ int mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status)
return 0; return 0;
} }
int mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key, u8 persistent) int mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key, bool persistent)
{ {
struct mgmt_ev_new_link_key ev; struct mgmt_ev_new_link_key ev;
......
...@@ -1158,7 +1158,8 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata, ...@@ -1158,7 +1158,8 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
tx->sta = rcu_dereference(sdata->u.vlan.sta); tx->sta = rcu_dereference(sdata->u.vlan.sta);
if (!tx->sta && sdata->dev->ieee80211_ptr->use_4addr) if (!tx->sta && sdata->dev->ieee80211_ptr->use_4addr)
return TX_DROP; return TX_DROP;
} else if (info->flags & IEEE80211_TX_CTL_INJECTED) { } else if (info->flags & IEEE80211_TX_CTL_INJECTED ||
tx->sdata->control_port_protocol == tx->skb->protocol) {
tx->sta = sta_info_get_bss(sdata, hdr->addr1); tx->sta = sta_info_get_bss(sdata, hdr->addr1);
} }
if (!tx->sta) if (!tx->sta)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment