diff options
-rw-r--r-- | drivers/net/wireless/ath/wil6210/cfg80211.c | 341 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/debug.c | 9 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/debugfs.c | 62 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/ethtool.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/interrupt.c | 6 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/main.c | 207 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/netdev.c | 102 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/p2p.c | 145 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/pcie_bus.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/pm.c | 9 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/pmc.c | 8 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/rx_reorder.c | 13 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/txrx.c | 106 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/wil6210.h | 150 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/wmi.c | 326 |
15 files changed, 877 insertions, 615 deletions
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index c959f152091f..2fd4af8d94dc 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c @@ -260,9 +260,10 @@ int wil_iftype_nl2wmi(enum nl80211_iftype type) return -EOPNOTSUPP; } -int wil_cid_fill_sinfo(struct wil6210_priv *wil, int cid, +int wil_cid_fill_sinfo(struct wil6210_vif *vif, int cid, struct station_info *sinfo) { + struct wil6210_priv *wil = vif_to_wil(vif); struct wmi_notify_req_cmd cmd = { .cid = cid, .interval_usec = 0, @@ -274,17 +275,17 @@ int wil_cid_fill_sinfo(struct wil6210_priv *wil, int cid, struct wil_net_stats *stats = &wil->sta[cid].stats; int rc; - rc = wmi_call(wil, WMI_NOTIFY_REQ_CMDID, &cmd, sizeof(cmd), + rc = wmi_call(wil, WMI_NOTIFY_REQ_CMDID, vif->mid, &cmd, sizeof(cmd), WMI_NOTIFY_REQ_DONE_EVENTID, &reply, sizeof(reply), 20); if (rc) return rc; - wil_dbg_wmi(wil, "Link status for CID %d: {\n" + wil_dbg_wmi(wil, "Link status for CID %d MID %d: {\n" " MCS %d TSF 0x%016llx\n" " BF status 0x%08x RSSI %d SQI %d%%\n" " Tx Tpt %d goodput %d Rx goodput %d\n" " Sectors(rx:tx) my %d:%d peer %d:%d\n""}\n", - cid, le16_to_cpu(reply.evt.bf_mcs), + cid, vif->mid, le16_to_cpu(reply.evt.bf_mcs), le64_to_cpu(reply.evt.tsf), reply.evt.status, reply.evt.rssi, reply.evt.sqi, @@ -333,30 +334,34 @@ static int wil_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, const u8 *mac, struct station_info *sinfo) { + struct wil6210_vif *vif = ndev_to_vif(ndev); struct wil6210_priv *wil = wiphy_to_wil(wiphy); int rc; - int cid = wil_find_cid(wil, mac); + int cid = wil_find_cid(wil, vif->mid, mac); - wil_dbg_misc(wil, "get_station: %pM CID %d\n", mac, cid); + wil_dbg_misc(wil, "get_station: %pM CID %d MID %d\n", mac, cid, + vif->mid); if (cid < 0) return cid; - rc = wil_cid_fill_sinfo(wil, cid, sinfo); + rc = wil_cid_fill_sinfo(vif, cid, sinfo); return rc; } /* - * Find @idx-th active STA for station dump. + * Find @idx-th active STA for specific MID for station dump. */ -static int wil_find_cid_by_idx(struct wil6210_priv *wil, int idx) +static int wil_find_cid_by_idx(struct wil6210_priv *wil, u8 mid, int idx) { int i; for (i = 0; i < ARRAY_SIZE(wil->sta); i++) { if (wil->sta[i].status == wil_sta_unused) continue; + if (wil->sta[i].mid != mid) + continue; if (idx == 0) return i; idx--; @@ -369,17 +374,19 @@ static int wil_cfg80211_dump_station(struct wiphy *wiphy, struct net_device *dev, int idx, u8 *mac, struct station_info *sinfo) { + struct wil6210_vif *vif = ndev_to_vif(dev); struct wil6210_priv *wil = wiphy_to_wil(wiphy); int rc; - int cid = wil_find_cid_by_idx(wil, idx); + int cid = wil_find_cid_by_idx(wil, vif->mid, idx); if (cid < 0) return -ENOENT; ether_addr_copy(mac, wil->sta[cid].addr); - wil_dbg_misc(wil, "dump_station: %pM CID %d\n", mac, cid); + wil_dbg_misc(wil, "dump_station: %pM CID %d MID %d\n", mac, cid, + vif->mid); - rc = wil_cid_fill_sinfo(wil, cid, sinfo); + rc = wil_cid_fill_sinfo(vif, cid, sinfo); return rc; } @@ -390,7 +397,7 @@ static int wil_cfg80211_start_p2p_device(struct wiphy *wiphy, struct wil6210_priv *wil = wiphy_to_wil(wiphy); wil_dbg_misc(wil, "start_p2p_device: entered\n"); - wil->p2p.p2p_dev_started = 1; + wil->p2p_dev_started = 1; return 0; } @@ -398,16 +405,15 @@ static void wil_cfg80211_stop_p2p_device(struct wiphy *wiphy, struct wireless_dev *wdev) { struct wil6210_priv *wil = wiphy_to_wil(wiphy); - struct wil_p2p_info *p2p = &wil->p2p; - if (!p2p->p2p_dev_started) + if (!wil->p2p_dev_started) return; wil_dbg_misc(wil, "stop_p2p_device: entered\n"); mutex_lock(&wil->mutex); mutex_lock(&wil->p2p_wdev_mutex); wil_p2p_stop_radio_operations(wil); - p2p->p2p_dev_started = 0; + wil->p2p_dev_started = 0; mutex_unlock(&wil->p2p_wdev_mutex); mutex_unlock(&wil->mutex); } @@ -419,7 +425,7 @@ wil_cfg80211_add_iface(struct wiphy *wiphy, const char *name, struct vif_params *params) { struct wil6210_priv *wil = wiphy_to_wil(wiphy); - struct net_device *ndev = wil_to_ndev(wil); + struct net_device *ndev = wil->main_ndev; struct wil6210_vif *vif; struct wireless_dev *p2p_wdev; @@ -474,12 +480,13 @@ static int wil_cfg80211_change_iface(struct wiphy *wiphy, struct vif_params *params) { struct wil6210_priv *wil = wiphy_to_wil(wiphy); - struct wireless_dev *wdev = wil_to_wdev(wil); + struct wil6210_vif *vif = ndev_to_vif(ndev); + struct wireless_dev *wdev = vif_to_wdev(vif); int rc; wil_dbg_misc(wil, "change_iface: type=%d\n", type); - if (netif_running(wil_to_ndev(wil)) && !wil_is_recovery_blocked(wil)) { + if (netif_running(ndev) && !wil_is_recovery_blocked(wil)) { wil_dbg_misc(wil, "interface is up. resetting...\n"); mutex_lock(&wil->mutex); __wil_down(wil); @@ -514,6 +521,7 @@ static int wil_cfg80211_scan(struct wiphy *wiphy, { struct wil6210_priv *wil = wiphy_to_wil(wiphy); struct wireless_dev *wdev = request->wdev; + struct wil6210_vif *vif = wdev_to_vif(wil, wdev); struct { struct wmi_start_scan_cmd cmd; u16 chnl[4]; @@ -542,7 +550,7 @@ static int wil_cfg80211_scan(struct wiphy *wiphy, mutex_lock(&wil->mutex); mutex_lock(&wil->p2p_wdev_mutex); - if (wil->scan_request || wil->p2p.discovery_started) { + if (vif->scan_request || vif->p2p.discovery_started) { wil_err(wil, "Already scanning\n"); mutex_unlock(&wil->p2p_wdev_mutex); rc = -EAGAIN; @@ -551,25 +559,28 @@ static int wil_cfg80211_scan(struct wiphy *wiphy, mutex_unlock(&wil->p2p_wdev_mutex); if (wdev->iftype == NL80211_IFTYPE_P2P_DEVICE) { - if (!wil->p2p.p2p_dev_started) { + if (!wil->p2p_dev_started) { wil_err(wil, "P2P search requested on stopped P2P device\n"); rc = -EIO; goto out; } /* social scan on P2P_DEVICE is handled as p2p search */ if (wil_p2p_is_social_scan(request)) { - wil->scan_request = request; - wil->radio_wdev = wdev; - rc = wil_p2p_search(wil, request); + vif->scan_request = request; + if (vif->mid == 0) + wil->radio_wdev = wdev; + rc = wil_p2p_search(vif, request); if (rc) { - wil->radio_wdev = wil_to_wdev(wil); - wil->scan_request = NULL; + if (vif->mid == 0) + wil->radio_wdev = + wil->main_ndev->ieee80211_ptr; + vif->scan_request = NULL; } goto out; } } - (void)wil_p2p_stop_discovery(wil); + (void)wil_p2p_stop_discovery(vif); wil_dbg_misc(wil, "Start scan_request 0x%p\n", request); wil_dbg_misc(wil, "SSID count: %d", request->n_ssids); @@ -582,18 +593,18 @@ static int wil_cfg80211_scan(struct wiphy *wiphy, } if (request->n_ssids) - rc = wmi_set_ssid(wil, request->ssids[0].ssid_len, + rc = wmi_set_ssid(vif, request->ssids[0].ssid_len, request->ssids[0].ssid); else - rc = wmi_set_ssid(wil, 0, NULL); + rc = wmi_set_ssid(vif, 0, NULL); if (rc) { wil_err(wil, "set SSID for scan request failed: %d\n", rc); goto out; } - wil->scan_request = request; - mod_timer(&wil->scan_timer, jiffies + WIL6210_SCAN_TO); + vif->scan_request = request; + mod_timer(&vif->scan_timer, jiffies + WIL6210_SCAN_TO); memset(&cmd, 0, sizeof(cmd)); cmd.cmd.scan_type = WMI_ACTIVE_SCAN; @@ -620,7 +631,8 @@ static int wil_cfg80211_scan(struct wiphy *wiphy, else wil_dbg_misc(wil, "Scan has no IE's\n"); - rc = wmi_set_ie(wil, WMI_FRAME_PROBE_REQ, request->ie_len, request->ie); + rc = wmi_set_ie(vif, WMI_FRAME_PROBE_REQ, + request->ie_len, request->ie); if (rc) goto out_restore; @@ -629,15 +641,18 @@ static int wil_cfg80211_scan(struct wiphy *wiphy, wil_dbg_misc(wil, "active scan with discovery_mode=1\n"); } - wil->radio_wdev = wdev; - rc = wmi_send(wil, WMI_START_SCAN_CMDID, &cmd, sizeof(cmd.cmd) + - cmd.cmd.num_channels * sizeof(cmd.cmd.channel_list[0])); + if (vif->mid == 0) + wil->radio_wdev = wdev; + rc = wmi_send(wil, WMI_START_SCAN_CMDID, vif->mid, + &cmd, sizeof(cmd.cmd) + + cmd.cmd.num_channels * sizeof(cmd.cmd.channel_list[0])); out_restore: if (rc) { - del_timer_sync(&wil->scan_timer); - wil->radio_wdev = wil_to_wdev(wil); - wil->scan_request = NULL; + del_timer_sync(&vif->scan_timer); + if (vif->mid == 0) + wil->radio_wdev = wil->main_ndev->ieee80211_ptr; + vif->scan_request = NULL; } out: mutex_unlock(&wil->mutex); @@ -648,24 +663,25 @@ static void wil_cfg80211_abort_scan(struct wiphy *wiphy, struct wireless_dev *wdev) { struct wil6210_priv *wil = wiphy_to_wil(wiphy); + struct wil6210_vif *vif = wdev_to_vif(wil, wdev); wil_dbg_misc(wil, "wdev=0x%p iftype=%d\n", wdev, wdev->iftype); mutex_lock(&wil->mutex); mutex_lock(&wil->p2p_wdev_mutex); - if (!wil->scan_request) + if (!vif->scan_request) goto out; - if (wdev != wil->scan_request->wdev) { + if (wdev != vif->scan_request->wdev) { wil_dbg_misc(wil, "abort scan was called on the wrong iface\n"); goto out; } - if (wil->radio_wdev == wil->p2p_wdev) + if (wdev == wil->p2p_wdev && wil->radio_wdev == wil->p2p_wdev) wil_p2p_stop_radio_operations(wil); else - wil_abort_scan(wil, true); + wil_abort_scan(vif, true); out: mutex_unlock(&wil->p2p_wdev_mutex); @@ -719,6 +735,7 @@ static int wil_cfg80211_connect(struct wiphy *wiphy, struct cfg80211_connect_params *sme) { struct wil6210_priv *wil = wiphy_to_wil(wiphy); + struct wil6210_vif *vif = ndev_to_vif(ndev); struct cfg80211_bss *bss; struct wmi_connect_cmd conn; const u8 *ssid_eid; @@ -727,7 +744,7 @@ static int wil_cfg80211_connect(struct wiphy *wiphy, int rc = 0; enum ieee80211_bss_type bss_type = IEEE80211_BSS_TYPE_ESS; - wil_dbg_misc(wil, "connect\n"); + wil_dbg_misc(wil, "connect, mid=%d\n", vif->mid); wil_print_connect_params(wil, sme); if (test_bit(wil_status_fwconnecting, wil->status) || @@ -762,18 +779,18 @@ static int wil_cfg80211_connect(struct wiphy *wiphy, rc = -ENOENT; goto out; } - wil->privacy = sme->privacy; - wil->pbss = sme->pbss; + vif->privacy = sme->privacy; + vif->pbss = sme->pbss; - if (wil->privacy) { + if (vif->privacy) { /* For secure assoc, remove old keys */ - rc = wmi_del_cipher_key(wil, 0, bss->bssid, + rc = wmi_del_cipher_key(vif, 0, bss->bssid, WMI_KEY_USE_PAIRWISE); if (rc) { wil_err(wil, "WMI_DELETE_CIPHER_KEY_CMD(PTK) failed\n"); goto out; } - rc = wmi_del_cipher_key(wil, 0, bss->bssid, + rc = wmi_del_cipher_key(vif, 0, bss->bssid, WMI_KEY_USE_RX_GROUP); if (rc) { wil_err(wil, "WMI_DELETE_CIPHER_KEY_CMD(GTK) failed\n"); @@ -785,7 +802,7 @@ static int wil_cfg80211_connect(struct wiphy *wiphy, * elements. Send it also in case it's empty, to erase previously set * ies in FW. */ - rc = wmi_set_ie(wil, WMI_FRAME_ASSOC_REQ, sme->ie_len, sme->ie); + rc = wmi_set_ie(vif, WMI_FRAME_ASSOC_REQ, sme->ie_len, sme->ie); if (rc) goto out; @@ -803,7 +820,7 @@ static int wil_cfg80211_connect(struct wiphy *wiphy, bss->capability); goto out; } - if (wil->privacy) { + if (vif->privacy) { if (rsn_eid) { /* regular secure connection */ conn.dot11_auth_mode = WMI_AUTH11_SHARED; conn.auth_mode = WMI_AUTH_WPA2_PSK; @@ -837,13 +854,13 @@ static int wil_cfg80211_connect(struct wiphy *wiphy, set_bit(wil_status_fwconnecting, wil->status); - rc = wmi_send(wil, WMI_CONNECT_CMDID, &conn, sizeof(conn)); + rc = wmi_send(wil, WMI_CONNECT_CMDID, vif->mid, &conn, sizeof(conn)); if (rc == 0) { netif_carrier_on(ndev); wil6210_bus_request(wil, WIL_MAX_BUS_REQUEST_KBPS); - wil->bss = bss; + vif->bss = bss; /* Connect can take lots of time */ - mod_timer(&wil->connect_timer, + mod_timer(&vif->connect_timer, jiffies + msecs_to_jiffies(5000)); } else { clear_bit(wil_status_fwconnecting, wil->status); @@ -861,8 +878,10 @@ static int wil_cfg80211_disconnect(struct wiphy *wiphy, { int rc; struct wil6210_priv *wil = wiphy_to_wil(wiphy); + struct wil6210_vif *vif = ndev_to_vif(ndev); - wil_dbg_misc(wil, "disconnect: reason=%d\n", reason_code); + wil_dbg_misc(wil, "disconnect: reason=%d, mid=%d\n", + reason_code, vif->mid); if (!(test_bit(wil_status_fwconnecting, wil->status) || test_bit(wil_status_fwconnected, wil->status))) { @@ -870,8 +889,8 @@ static int wil_cfg80211_disconnect(struct wiphy *wiphy, return 0; } - wil->locally_generated_disc = true; - rc = wmi_call(wil, WMI_DISCONNECT_CMDID, NULL, 0, + vif->locally_generated_disc = true; + rc = wmi_call(wil, WMI_DISCONNECT_CMDID, vif->mid, NULL, 0, WMI_DISCONNECT_EVENTID, NULL, 0, WIL6210_DISCONNECT_TO_MS); if (rc) @@ -907,6 +926,7 @@ int wil_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, const u8 *buf = params->buf; size_t len = params->len, total; struct wil6210_priv *wil = wiphy_to_wil(wiphy); + struct wil6210_vif *vif = wdev_to_vif(wil, wdev); int rc; bool tx_status = false; struct ieee80211_mgmt *mgmt_frame = (void *)buf; @@ -923,7 +943,7 @@ int wil_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, * different from currently "listened" channel and fail if it is. */ - wil_dbg_misc(wil, "mgmt_tx\n"); + wil_dbg_misc(wil, "mgmt_tx mid %d\n", vif->mid); wil_hex_dump_misc("mgmt tx frame ", DUMP_PREFIX_OFFSET, 16, 1, buf, len, true); @@ -944,7 +964,7 @@ int wil_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, cmd->len = cpu_to_le16(len); memcpy(cmd->payload, buf, len); - rc = wmi_call(wil, WMI_SW_TX_REQ_CMDID, cmd, total, + rc = wmi_call(wil, WMI_SW_TX_REQ_CMDID, vif->mid, cmd, total, WMI_SW_TX_COMPLETE_EVENTID, &evt, sizeof(evt), 2000); if (rc == 0) tx_status = !evt.evt.status; @@ -966,10 +986,10 @@ static int wil_cfg80211_set_channel(struct wiphy *wiphy, return 0; } -static enum wmi_key_usage wil_detect_key_usage(struct wil6210_priv *wil, +static enum wmi_key_usage wil_detect_key_usage(struct wireless_dev *wdev, bool pairwise) { - struct wireless_dev *wdev = wil_to_wdev(wil); + struct wil6210_priv *wil = wdev_to_wil(wdev); enum wmi_key_usage rc; if (pairwise) { @@ -997,7 +1017,7 @@ static enum wmi_key_usage wil_detect_key_usage(struct wil6210_priv *wil, } static struct wil_sta_info * -wil_find_sta_by_key_usage(struct wil6210_priv *wil, +wil_find_sta_by_key_usage(struct wil6210_priv *wil, u8 mid, enum wmi_key_usage key_usage, const u8 *mac_addr) { int cid = -EINVAL; @@ -1007,9 +1027,9 @@ wil_find_sta_by_key_usage(struct wil6210_priv *wil, /* supplicant provides Rx group key in STA mode with NULL MAC address */ if (mac_addr) - cid = wil_find_cid(wil, mac_addr); + cid = wil_find_cid(wil, mid, mac_addr); else if (key_usage == WMI_KEY_USE_RX_GROUP) - cid = wil_find_cid_by_idx(wil, 0); + cid = wil_find_cid_by_idx(wil, mid, 0); if (cid < 0) { wil_err(wil, "No CID for %pM %s\n", mac_addr, key_usage_str[key_usage]); @@ -1086,9 +1106,12 @@ static int wil_cfg80211_add_key(struct wiphy *wiphy, struct key_params *params) { int rc; + struct wil6210_vif *vif = ndev_to_vif(ndev); struct wil6210_priv *wil = wiphy_to_wil(wiphy); - enum wmi_key_usage key_usage = wil_detect_key_usage(wil, pairwise); - struct wil_sta_info *cs = wil_find_sta_by_key_usage(wil, key_usage, + struct wireless_dev *wdev = vif_to_wdev(vif); + enum wmi_key_usage key_usage = wil_detect_key_usage(wdev, pairwise); + struct wil_sta_info *cs = wil_find_sta_by_key_usage(wil, vif->mid, + key_usage, mac_addr); if (!params) { @@ -1118,7 +1141,7 @@ static int wil_cfg80211_add_key(struct wiphy *wiphy, return -EINVAL; } - rc = wmi_add_cipher_key(wil, key_index, mac_addr, params->key_len, + rc = wmi_add_cipher_key(vif, key_index, mac_addr, params->key_len, params->key, key_usage); if (!rc) wil_set_crypto_rx(key_index, key_usage, cs, params); @@ -1131,9 +1154,12 @@ static int wil_cfg80211_del_key(struct wiphy *wiphy, u8 key_index, bool pairwise, const u8 *mac_addr) { + struct wil6210_vif *vif = ndev_to_vif(ndev); struct wil6210_priv *wil = wiphy_to_wil(wiphy); - enum wmi_key_usage key_usage = wil_detect_key_usage(wil, pairwise); - struct wil_sta_info *cs = wil_find_sta_by_key_usage(wil, key_usage, + struct wireless_dev *wdev = vif_to_wdev(vif); + enum wmi_key_usage key_usage = wil_detect_key_usage(wdev, pairwise); + struct wil_sta_info *cs = wil_find_sta_by_key_usage(wil, vif->mid, + key_usage, mac_addr); wil_dbg_misc(wil, "del_key: %pM %s[%d]\n", mac_addr, @@ -1146,7 +1172,7 @@ static int wil_cfg80211_del_key(struct wiphy *wiphy, if (!IS_ERR_OR_NULL(cs)) wil_del_rx_key(key_index, key_usage, cs); - return wmi_del_cipher_key(wil, key_index, mac_addr, key_usage); + return wmi_del_cipher_key(vif, key_index, mac_addr, key_usage); } /* Need to be present or wiphy_new() will WARN */ @@ -1183,10 +1209,11 @@ static int wil_cancel_remain_on_channel(struct wiphy *wiphy, u64 cookie) { struct wil6210_priv *wil = wiphy_to_wil(wiphy); + struct wil6210_vif *vif = wdev_to_vif(wil, wdev); wil_dbg_misc(wil, "cancel_remain_on_channel\n"); - return wil_p2p_cancel_listen(wil, cookie); + return wil_p2p_cancel_listen(vif, cookie); } /** @@ -1279,11 +1306,10 @@ static void wil_print_bcon_data(struct cfg80211_beacon_data *b) } /* internal functions for device reset and starting AP */ -static int _wil_cfg80211_set_ies(struct wiphy *wiphy, +static int _wil_cfg80211_set_ies(struct wil6210_vif *vif, struct cfg80211_beacon_data *bcon) { int rc; - struct wil6210_priv *wil = wiphy_to_wil(wiphy); u16 len = 0, proberesp_len = 0; u8 *ies = NULL, *proberesp = NULL; @@ -1304,20 +1330,21 @@ static int _wil_cfg80211_set_ies(struct wiphy *wiphy, if (rc) goto out; - rc = wmi_set_ie(wil, WMI_FRAME_PROBE_RESP, len, ies); + rc = wmi_set_ie(vif, WMI_FRAME_PROBE_RESP, len, ies); if (rc) goto out; if (bcon->assocresp_ies) - rc = wmi_set_ie(wil, WMI_FRAME_ASSOC_RESP, + rc = wmi_set_ie(vif, WMI_FRAME_ASSOC_RESP, bcon->assocresp_ies_len, bcon->assocresp_ies); else - rc = wmi_set_ie(wil, WMI_FRAME_ASSOC_RESP, len, ies); + rc = wmi_set_ie(vif, WMI_FRAME_ASSOC_RESP, len, ies); #if 0 /* to use beacon IE's, remove this #if 0 */ if (rc) goto out; - rc = wmi_set_ie(wil, WMI_FRAME_BEACON, bcon->tail_len, bcon->tail); + rc = wmi_set_ie(vif, WMI_FRAME_BEACON, + bcon->tail_len, bcon->tail); #endif out: kfree(ies); @@ -1332,6 +1359,7 @@ static int _wil_cfg80211_start_ap(struct wiphy *wiphy, u8 hidden_ssid, u32 pbss) { struct wil6210_priv *wil = wiphy_to_wil(wiphy); + struct wil6210_vif *vif = ndev_to_vif(ndev); int rc; struct wireless_dev *wdev = ndev->ieee80211_ptr; u8 wmi_nettype = wil_iftype_nl2wmi(wdev->iftype); @@ -1340,7 +1368,7 @@ static int _wil_cfg80211_start_ap(struct wiphy *wiphy, if (pbss) wmi_nettype = WMI_NETTYPE_P2P; - wil_dbg_misc(wil, "start_ap: is_go=%d\n", is_go); + wil_dbg_misc(wil, "start_ap: mid=%d, is_go=%d\n", vif->mid, is_go); if (is_go && !pbss) { wil_err(wil, "P2P GO must be in PBSS\n"); return -ENOTSUPP; @@ -1355,34 +1383,34 @@ static int _wil_cfg80211_start_ap(struct wiphy *wiphy, if (rc) goto out; - rc = wmi_set_ssid(wil, ssid_len, ssid); + rc = wmi_set_ssid(vif, ssid_len, ssid); if (rc) goto out; - rc = _wil_cfg80211_set_ies(wiphy, bcon); + rc = _wil_cfg80211_set_ies(vif, bcon); if (rc) goto out; - wil->privacy = privacy; - wil->channel = chan; - wil->hidden_ssid = hidden_ssid; - wil->pbss = pbss; + vif->privacy = privacy; + vif->channel = chan; + vif->hidden_ssid = hidden_ssid; + vif->pbss = pbss; netif_carrier_on(ndev); wil6210_bus_request(wil, WIL_MAX_BUS_REQUEST_KBPS); - rc = wmi_pcp_start(wil, bi, wmi_nettype, chan, hidden_ssid, is_go); + rc = wmi_pcp_start(vif, bi, wmi_nettype, chan, hidden_ssid, is_go); if (rc) goto err_pcp_start; - rc = wil_bcast_init(wil); + rc = wil_bcast_init(vif); if (rc) goto err_bcast; goto out; /* success */ err_bcast: - wmi_pcp_stop(wil); + wmi_pcp_stop(vif); err_pcp_start: netif_carrier_off(ndev); wil6210_bus_request(wil, WIL_DEFAULT_BUS_REQUEST_KBPS); @@ -1396,10 +1424,11 @@ static int wil_cfg80211_change_beacon(struct wiphy *wiphy, struct cfg80211_beacon_data *bcon) { struct wil6210_priv *wil = wiphy_to_wil(wiphy); + struct wil6210_vif *vif = ndev_to_vif(ndev); int rc; u32 privacy = 0; - wil_dbg_misc(wil, "change_beacon\n"); + wil_dbg_misc(wil, "change_beacon, mid=%d\n", vif->mid); wil_print_bcon_data(bcon); if (bcon->tail && @@ -1408,20 +1437,20 @@ static int wil_cfg80211_change_beacon(struct wiphy *wiphy, privacy = 1; /* in case privacy has changed, need to restart the AP */ - if (wil->privacy != privacy) { + if (vif->privacy != privacy) { struct wireless_dev *wdev = ndev->ieee80211_ptr; wil_dbg_misc(wil, "privacy changed %d=>%d. Restarting AP\n", - wil->privacy, privacy); + vif->privacy, privacy); rc = _wil_cfg80211_start_ap(wiphy, ndev, wdev->ssid, wdev->ssid_len, privacy, wdev->beacon_interval, - wil->channel, bcon, - wil->hidden_ssid, - wil->pbss); + vif->channel, bcon, + vif->hidden_ssid, + vif->pbss); } else { - rc = _wil_cfg80211_set_ies(wiphy, bcon); + rc = _wil_cfg80211_set_ies(vif, bcon); } return rc; @@ -1488,6 +1517,7 @@ static int wil_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev) { struct wil6210_priv *wil = wiphy_to_wil(wiphy); + struct wil6210_vif *vif = ndev_to_vif(ndev); wil_dbg_misc(wil, "stop_ap\n"); @@ -1499,7 +1529,7 @@ static int wil_cfg80211_stop_ap(struct wiphy *wiphy, mutex_lock(&wil->mutex); - wmi_pcp_stop(wil); + wmi_pcp_stop(vif); __wil_down(wil); @@ -1513,9 +1543,11 @@ static int wil_cfg80211_add_station(struct wiphy *wiphy, const u8 *mac, struct station_parameters *params) { + struct wil6210_vif *vif = ndev_to_vif(dev); struct wil6210_priv *wil = wiphy_to_wil(wiphy); - wil_dbg_misc(wil, "add station %pM aid %d\n", mac, params->aid); + wil_dbg_misc(wil, "add station %pM aid %d mid %d\n", + mac, params->aid, vif->mid); if (!disable_ap_sme) { wil_err(wil, "not supported with AP SME enabled\n"); @@ -1527,20 +1559,21 @@ static int wil_cfg80211_add_station(struct wiphy *wiphy, return -EINVAL; } - return wmi_new_sta(wil, mac, params->aid); + return wmi_new_sta(vif, mac, params->aid); } static int wil_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev, struct station_del_parameters *params) { + struct wil6210_vif *vif = ndev_to_vif(dev); struct wil6210_priv *wil = wiphy_to_wil(wiphy); - wil_dbg_misc(wil, "del_station: %pM, reason=%d\n", params->mac, - params->reason_code); + wil_dbg_misc(wil, "del_station: %pM, reason=%d mid=%d\n", + params->mac, params->reason_code, vif->mid); mutex_lock(&wil->mutex); - wil6210_disconnect(wil, params->mac, params->reason_code, false); + wil6210_disconnect(vif, params->mac, params->reason_code, false); mutex_unlock(&wil->mutex); return 0; @@ -1551,13 +1584,15 @@ static int wil_cfg80211_change_station(struct wiphy *wiphy, const u8 *mac, struct station_parameters *params) { + struct wil6210_vif *vif = ndev_to_vif(dev); struct wil6210_priv *wil = wiphy_to_wil(wiphy); int authorize; int cid, i; struct vring_tx_data *txdata = NULL; - wil_dbg_misc(wil, "change station %pM mask 0x%x set 0x%x\n", mac, - params->sta_flags_mask, params->sta_flags_set); + wil_dbg_misc(wil, "change station %pM mask 0x%x set 0x%x mid %d\n", + mac, params->sta_flags_mask, params->sta_flags_set, + vif->mid); if (!disable_ap_sme) { wil_dbg_misc(wil, "not supported with AP SME enabled\n"); @@ -1567,7 +1602,7 @@ static int wil_cfg80211_change_station(struct wiphy *wiphy, if (!(params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED))) return 0; - cid = wil_find_cid(wil, mac); + cid = wil_find_cid(wil, vif->mid, mac); if (cid < 0) { wil_err(wil, "station not found\n"); return -ENOLINK; @@ -1594,9 +1629,10 @@ static int wil_cfg80211_change_station(struct wiphy *wiphy, /* probe_client handling */ static void wil_probe_client_handle(struct wil6210_priv *wil, + struct wil6210_vif *vif, struct wil_probe_client_req *req) { - struct net_device *ndev = wil_to_ndev(wil); + struct net_device *ndev = vif_to_ndev(vif); struct wil_sta_info *sta = &wil->sta[req->cid]; /* assume STA is alive if it is still connected, * else FW will disconnect it @@ -1607,51 +1643,53 @@ static void wil_probe_client_handle(struct wil6210_priv *wil, 0, false, GFP_KERNEL); } -static struct list_head *next_probe_client(struct wil6210_priv *wil) +static struct list_head *next_probe_client(struct wil6210_vif *vif) { struct list_head *ret = NULL; - mutex_lock(&wil->probe_client_mutex); + mutex_lock(&vif->probe_client_mutex); - if (!list_empty(&wil->probe_client_pending)) { - ret = wil->probe_client_pending.next; + if (!list_empty(&vif->probe_client_pending)) { + ret = vif->probe_client_pending.next; list_del(ret); } - mutex_unlock(&wil->probe_client_mutex); + mutex_unlock(&vif->probe_client_mutex); return ret; } void wil_probe_client_worker(struct work_struct *work) { - struct wil6210_priv *wil = container_of(work, struct wil6210_priv, - probe_client_worker); + struct wil6210_vif *vif = container_of(work, struct wil6210_vif, + probe_client_worker); + struct wil6210_priv *wil = vif_to_wil(vif); struct wil_probe_client_req *req; struct list_head *lh; - while ((lh = next_probe_client(wil)) != NULL) { + while ((lh = next_probe_client(vif)) != NULL) { req = list_entry(lh, struct wil_probe_client_req, list); - wil_probe_client_handle(wil, req); + wil_probe_client_handle(wil, vif, req); kfree(req); } } -void wil_probe_client_flush(struct wil6210_priv *wil) +void wil_probe_client_flush(struct wil6210_vif *vif) { struct wil_probe_client_req *req, *t; + struct wil6210_priv *wil = vif_to_wil(vif); wil_dbg_misc(wil, "probe_client_flush\n"); - mutex_lock(&wil->probe_client_mutex); + mutex_lock(&vif->probe_client_mutex); - list_for_each_entry_safe(req, t, &wil->probe_client_pending, list) { + list_for_each_entry_safe(req, t, &vif->probe_client_pending, list) { list_del(&req->list); kfree(req); } - mutex_unlock(&wil->probe_client_mutex); + mutex_unlock(&vif->probe_client_mutex); } static int wil_cfg80211_probe_client(struct wiphy *wiphy, @@ -1659,10 +1697,12 @@ static int wil_cfg80211_probe_client(struct wiphy *wiphy, const u8 *peer, u64 *cookie) { struct wil6210_priv *wil = wiphy_to_wil(wiphy); + struct wil6210_vif *vif = ndev_to_vif(dev); struct wil_probe_client_req *req; - int cid = wil_find_cid(wil, peer); + int cid = wil_find_cid(wil, vif->mid, peer); - wil_dbg_misc(wil, "probe_client: %pM => CID %d\n", peer, cid); + wil_dbg_misc(wil, "probe_client: %pM => CID %d MID %d\n", + peer, cid, vif->mid); if (cid < 0) return -ENOLINK; @@ -1674,12 +1714,12 @@ static int wil_cfg80211_probe_client(struct wiphy *wiphy, req->cid = cid; req->cookie = cid; - mutex_lock(&wil->probe_client_mutex); - list_add_tail(&req->list, &wil->probe_client_pending); - mutex_unlock(&wil->probe_client_mutex); + mutex_lock(&vif->probe_client_mutex); + list_add_tail(&req->list, &vif->probe_client_pending); + mutex_unlock(&vif->probe_client_mutex); *cookie = req->cookie; - queue_work(wil->wq_service, &wil->probe_client_worker); + queue_work(wil->wq_service, &vif->probe_client_worker); return 0; } @@ -1688,11 +1728,12 @@ static int wil_cfg80211_change_bss(struct wiphy *wiphy, struct bss_parameters *params) { struct wil6210_priv *wil = wiphy_to_wil(wiphy); + struct wil6210_vif *vif = ndev_to_vif(dev); if (params->ap_isolate >= 0) { - wil_dbg_misc(wil, "change_bss: ap_isolate %d => %d\n", - wil->ap_isolate, params->ap_isolate); - wil->ap_isolate = params->ap_isolate; + wil_dbg_misc(wil, "change_bss: ap_isolate MID %d, %d => %d\n", + vif->mid, vif->ap_isolate, params->ap_isolate); + vif->ap_isolate = params->ap_isolate; } return 0; @@ -1738,7 +1779,7 @@ static int wil_cfg80211_suspend(struct wiphy *wiphy, mutex_lock(&wil->mutex); mutex_lock(&wil->p2p_wdev_mutex); wil_p2p_stop_radio_operations(wil); - wil_abort_scan(wil, true); + wil_abort_scan(ndev_to_vif(wil->main_ndev), true); mutex_unlock(&wil->p2p_wdev_mutex); mutex_unlock(&wil->mutex); @@ -1761,8 +1802,12 @@ wil_cfg80211_sched_scan_start(struct wiphy *wiphy, struct cfg80211_sched_scan_request *request) { struct wil6210_priv *wil = wiphy_to_wil(wiphy); + struct wil6210_vif *vif = ndev_to_vif(dev); int i, rc; + if (vif->mid != 0) + return -EOPNOTSUPP; + wil_dbg_misc(wil, "sched scan start: n_ssids %d, ie_len %zu, flags 0x%x\n", request->n_ssids, request->ie_len, request->flags); @@ -1796,7 +1841,8 @@ wil_cfg80211_sched_scan_start(struct wiphy *wiphy, i, sp->interval, sp->iterations); } - rc = wmi_set_ie(wil, WMI_FRAME_PROBE_REQ, request->ie_len, request->ie); + rc = wmi_set_ie(vif, WMI_FRAME_PROBE_REQ, + request->ie_len, request->ie); if (rc) return rc; return wmi_start_sched_scan(wil, request); @@ -1807,8 +1853,12 @@ wil_cfg80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev, u64 reqid) { struct wil6210_priv *wil = wiphy_to_wil(wiphy); + struct wil6210_vif *vif = ndev_to_vif(dev); int rc; + if (vif->mid != 0) + return -EOPNOTSUPP; + rc = wmi_stop_sched_scan(wil); /* device would return error if it thinks PNO is already stopped. * ignore the return code so user space and driver gets back in-sync @@ -2015,11 +2065,11 @@ void wil_p2p_wdev_free(struct wil6210_priv *wil) mutex_lock(&wil->p2p_wdev_mutex); p2p_wdev = wil->p2p_wdev; wil->p2p_wdev = NULL; - wil->radio_wdev = wil_to_wdev(wil); + wil->radio_wdev = wil->main_ndev->ieee80211_ptr; mutex_unlock(&wil->p2p_wdev_mutex); if (p2p_wdev) { cfg80211_unregister_wdev(p2p_wdev); - vif = wdev_to_vif(p2p_wdev); + vif = wdev_to_vif(wil, p2p_wdev); kfree(vif); } } @@ -2045,6 +2095,7 @@ static int wil_rf_sector_get_cfg(struct wiphy *wiphy, const void *data, int data_len) { struct wil6210_priv *wil = wdev_to_wil(wdev); + struct wil6210_vif *vif = wdev_to_vif(wil, wdev); int rc; struct nlattr *tb[QCA_ATTR_DMG_RF_SECTOR_MAX + 1]; u16 sector_index; @@ -2101,8 +2152,8 @@ static int wil_rf_sector_get_cfg(struct wiphy *wiphy, cmd.sector_type = sector_type; cmd.rf_modules_vec = rf_modules_vec & 0xFF; memset(&reply, 0, sizeof(reply)); - rc = wmi_call(wil, WMI_GET_RF_SECTOR_PARAMS_CMDID, &cmd, sizeof(cmd), - WMI_GET_RF_SECTOR_PARAMS_DONE_EVENTID, + rc = wmi_call(wil, WMI_GET_RF_SECTOR_PARAMS_CMDID, vif->mid, + &cmd, sizeof(cmd), WMI_GET_RF_SECTOR_PARAMS_DONE_EVENTID, &reply, sizeof(reply), 500); if (rc) @@ -2164,6 +2215,7 @@ static int wil_rf_sector_set_cfg(struct wiphy *wiphy, const void *data, int data_len) { struct wil6210_priv *wil = wdev_to_wil(wdev); + struct wil6210_vif *vif = wdev_to_vif(wil, wdev); int rc, tmp; struct nlattr *tb[QCA_ATTR_DMG_RF_SECTOR_MAX + 1]; struct nlattr *tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_MAX + 1]; @@ -2258,8 +2310,8 @@ static int wil_rf_sector_set_cfg(struct wiphy *wiphy, cmd.rf_modules_vec = rf_modules_vec & 0xFF; memset(&reply, 0, sizeof(reply)); - rc = wmi_call(wil, WMI_SET_RF_SECTOR_PARAMS_CMDID, &cmd, sizeof(cmd), - WMI_SET_RF_SECTOR_PARAMS_DONE_EVENTID, + rc = wmi_call(wil, WMI_SET_RF_SECTOR_PARAMS_CMDID, vif->mid, + &cmd, sizeof(cmd), WMI_SET_RF_SECTOR_PARAMS_DONE_EVENTID, &reply, sizeof(reply), 500); if (rc) @@ -2272,6 +2324,7 @@ static int wil_rf_sector_get_selected(struct wiphy *wiphy, const void *data, int data_len) { struct wil6210_priv *wil = wdev_to_wil(wdev); + struct wil6210_vif *vif = wdev_to_vif(wil, wdev); int rc; struct nlattr *tb[QCA_ATTR_DMG_RF_SECTOR_MAX + 1]; u8 sector_type, mac_addr[ETH_ALEN]; @@ -2305,7 +2358,7 @@ static int wil_rf_sector_get_selected(struct wiphy *wiphy, if (tb[QCA_ATTR_MAC_ADDR]) { ether_addr_copy(mac_addr, nla_data(tb[QCA_ATTR_MAC_ADDR])); - cid = wil_find_cid(wil, mac_addr); + cid = wil_find_cid(wil, vif->mid, mac_addr); if (cid < 0) { wil_err(wil, "invalid MAC address %pM\n", mac_addr); return -ENOENT; @@ -2321,7 +2374,7 @@ static int wil_rf_sector_get_selected(struct wiphy *wiphy, cmd.cid = (u8)cid; cmd.sector_type = sector_type; memset(&reply, 0, sizeof(reply)); - rc = wmi_call(wil, WMI_GET_SELECTED_RF_SECTOR_INDEX_CMDID, + rc = wmi_call(wil, WMI_GET_SELECTED_RF_SECTOR_INDEX_CMDID, vif->mid, &cmd, sizeof(cmd), WMI_GET_SELECTED_RF_SECTOR_INDEX_DONE_EVENTID, &reply, sizeof(reply), @@ -2354,7 +2407,7 @@ nla_put_failure: } static int wil_rf_sector_wmi_set_selected(struct wil6210_priv *wil, - u16 sector_index, + u8 mid, u16 sector_index, u8 sector_type, u8 cid) { struct wmi_set_selected_rf_sector_index_cmd cmd; @@ -2369,7 +2422,7 @@ static int wil_rf_sector_wmi_set_selected(struct wil6210_priv *wil, cmd.sector_type = sector_type; cmd.cid = (u8)cid; memset(&reply, 0, sizeof(reply)); - rc = wmi_call(wil, WMI_SET_SELECTED_RF_SECTOR_INDEX_CMDID, + rc = wmi_call(wil, WMI_SET_SELECTED_RF_SECTOR_INDEX_CMDID, mid, &cmd, sizeof(cmd), WMI_SET_SELECTED_RF_SECTOR_INDEX_DONE_EVENTID, &reply, sizeof(reply), @@ -2384,6 +2437,7 @@ static int wil_rf_sector_set_selected(struct wiphy *wiphy, const void *data, int data_len) { struct wil6210_priv *wil = wdev_to_wil(wdev); + struct wil6210_vif *vif = wdev_to_vif(wil, wdev); int rc; struct nlattr *tb[QCA_ATTR_DMG_RF_SECTOR_MAX + 1]; u16 sector_index; @@ -2423,7 +2477,7 @@ static int wil_rf_sector_set_selected(struct wiphy *wiphy, if (tb[QCA_ATTR_MAC_ADDR]) { ether_addr_copy(mac_addr, nla_data(tb[QCA_ATTR_MAC_ADDR])); if (!is_broadcast_ether_addr(mac_addr)) { - cid = wil_find_cid(wil, mac_addr); + cid = wil_find_cid(wil, vif->mid, mac_addr); if (cid < 0) { wil_err(wil, "invalid MAC address %pM\n", mac_addr); @@ -2445,17 +2499,20 @@ static int wil_rf_sector_set_selected(struct wiphy *wiphy, } if (cid >= 0) { - rc = wil_rf_sector_wmi_set_selected(wil, sector_index, + rc = wil_rf_sector_wmi_set_selected(wil, vif->mid, sector_index, sector_type, cid); } else { /* unlock all cids */ rc = wil_rf_sector_wmi_set_selected( - wil, WMI_INVALID_RF_SECTOR_INDEX, sector_type, - WIL_CID_ALL); + wil, vif->mid, WMI_INVALID_RF_SECTOR_INDEX, + sector_type, WIL_CID_ALL); if (rc == -EINVAL) { for (i = 0; i < WIL6210_MAX_CID; i++) { + if (wil->sta[i].mid != vif->mid) + continue; rc = wil_rf_sector_wmi_set_selected( - wil, WMI_INVALID_RF_SECTOR_INDEX, + wil, vif->mid, + WMI_INVALID_RF_SECTOR_INDEX, sector_type, i); /* the FW will silently ignore and return * success for unused cid, so abort the loop diff --git a/drivers/net/wireless/ath/wil6210/debug.c b/drivers/net/wireless/ath/wil6210/debug.c index 217a4591bde4..a9befb971cc4 100644 --- a/drivers/net/wireless/ath/wil6210/debug.c +++ b/drivers/net/wireless/ath/wil6210/debug.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2013,2016 Qualcomm Atheros, Inc. + * Copyright (c) 2018, The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -25,7 +26,7 @@ void __wil_err(struct wil6210_priv *wil, const char *fmt, ...) va_start(args, fmt); vaf.fmt = fmt; vaf.va = &args; - netdev_err(wil_to_ndev(wil), "%pV", &vaf); + netdev_err(wil->main_ndev, "%pV", &vaf); trace_wil6210_log_err(&vaf); va_end(args); } @@ -41,7 +42,7 @@ void __wil_err_ratelimited(struct wil6210_priv *wil, const char *fmt, ...) va_start(args, fmt); vaf.fmt = fmt; vaf.va = &args; - netdev_err(wil_to_ndev(wil), "%pV", &vaf); + netdev_err(wil->main_ndev, "%pV", &vaf); trace_wil6210_log_err(&vaf); va_end(args); } @@ -57,7 +58,7 @@ void wil_dbg_ratelimited(const struct wil6210_priv *wil, const char *fmt, ...) va_start(args, fmt); vaf.fmt = fmt; vaf.va = &args; - netdev_dbg(wil_to_ndev(wil), "%pV", &vaf); + netdev_dbg(wil->main_ndev, "%pV", &vaf); trace_wil6210_log_dbg(&vaf); va_end(args); } @@ -70,7 +71,7 @@ void __wil_info(struct wil6210_priv *wil, const char *fmt, ...) va_start(args, fmt); vaf.fmt = fmt; vaf.va = &args; - netdev_info(wil_to_ndev(wil), "%pV", &vaf); + netdev_info(wil->main_ndev, "%pV", &vaf); trace_wil6210_log_info(&vaf); va_end(args); } diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c index 4a4888246e8c..636da5e32ae1 100644 --- a/drivers/net/wireless/ath/wil6210/debugfs.c +++ b/drivers/net/wireless/ath/wil6210/debugfs.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. + * Copyright (c) 2018, The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -621,7 +622,7 @@ static ssize_t wil_write_file_reset(struct file *file, const char __user *buf, size_t len, loff_t *ppos) { struct wil6210_priv *wil = file->private_data; - struct net_device *ndev = wil_to_ndev(wil); + struct net_device *ndev = wil->main_ndev; /** * BUG: @@ -716,27 +717,44 @@ static ssize_t wil_write_back(struct file *file, const char __user *buf, if (rc < 2) return -EINVAL; - if (0 == strcmp(cmd, "add")) { - if (rc < 3) { - wil_err(wil, "BACK: add require at least 2 params\n"); + if ((strcmp(cmd, "add") == 0) || + (strcmp(cmd, "del_tx") == 0)) { + struct vring_tx_data *txdata; + + if (p1 < 0 || p1 >= WIL6210_MAX_TX_RINGS) { + wil_err(wil, "BACK: invalid ring id %d\n", p1); return -EINVAL; } - if (rc < 4) - p3 = 0; - wmi_addba(wil, p1, p2, p3); - } else if (0 == strcmp(cmd, "del_tx")) { - if (rc < 3) - p2 = WLAN_REASON_QSTA_LEAVE_QBSS; - wmi_delba_tx(wil, p1, p2); - } else if (0 == strcmp(cmd, "del_rx")) { + txdata = &wil->vring_tx_data[p1]; + if (strcmp(cmd, "add") == 0) { + if (rc < 3) { + wil_err(wil, "BACK: add require at least 2 params\n"); + return -EINVAL; + } + if (rc < 4) + p3 = 0; + wmi_addba(wil, txdata->mid, p1, p2, p3); + } else { + if (rc < 3) + p2 = WLAN_REASON_QSTA_LEAVE_QBSS; + wmi_delba_tx(wil, txdata->mid, p1, p2); + } + } else if (strcmp(cmd, "del_rx") == 0) { + struct wil_sta_info *sta; + if (rc < 3) { wil_err(wil, "BACK: del_rx require at least 2 params\n"); return -EINVAL; } + if (p1 < 0 || p1 >= WIL6210_MAX_CID) { + wil_err(wil, "BACK: invalid CID %d\n", p1); + return -EINVAL; + } if (rc < 4) p3 = WLAN_REASON_QSTA_LEAVE_QBSS; - wmi_delba_rx(wil, mk_cidxtid(p1, p2), p3); + sta = &wil->sta[p1]; + wmi_delba_rx(wil, sta->mid, mk_cidxtid(p1, p2), p3); } else { wil_err(wil, "BACK: Unrecognized command \"%s\"\n", cmd); return -EINVAL; @@ -855,7 +873,7 @@ static ssize_t wil_write_file_txmgmt(struct file *file, const char __user *buf, { struct wil6210_priv *wil = file->private_data; struct wiphy *wiphy = wil_to_wiphy(wil); - struct wireless_dev *wdev = wil_to_wdev(wil); + struct wireless_dev *wdev = wil->main_ndev->ieee80211_ptr; struct cfg80211_mgmt_tx_params params; int rc; void *frame; @@ -890,6 +908,7 @@ static ssize_t wil_write_file_wmi(struct file *file, const char __user *buf, size_t len, loff_t *ppos) { struct wil6210_priv *wil = file->private_data; + struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev); struct wmi_cmd_hdr *wmi; void *cmd; int cmdlen = len - sizeof(struct wmi_cmd_hdr); @@ -912,7 +931,7 @@ static ssize_t wil_write_file_wmi(struct file *file, const char __user *buf, cmd = (cmdlen > 0) ? &wmi[1] : NULL; cmdid = le16_to_cpu(wmi->command_id); - rc1 = wmi_send(wil, cmdid, cmd, cmdlen); + rc1 = wmi_send(wil, cmdid, vif->mid, cmd, cmdlen); kfree(wmi); wil_info(wil, "0x%04x[%d] -> %d\n", cmdid, cmdlen, rc1); @@ -1050,6 +1069,7 @@ static int wil_bf_debugfs_show(struct seq_file *s, void *data) int rc; int i; struct wil6210_priv *wil = s->private; + struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev); struct wmi_notify_req_cmd cmd = { .interval_usec = 0, }; @@ -1062,7 +1082,8 @@ static int wil_bf_debugfs_show(struct seq_file *s, void *data) u32 status; cmd.cid = i; - rc = wmi_call(wil, WMI_NOTIFY_REQ_CMDID, &cmd, sizeof(cmd), + rc = wmi_call(wil, WMI_NOTIFY_REQ_CMDID, vif->mid, + &cmd, sizeof(cmd), WMI_NOTIFY_REQ_DONE_EVENTID, &reply, sizeof(reply), 20); /* if reply is all-0, ignore this CID */ @@ -1155,7 +1176,7 @@ static const struct file_operations fops_temp = { static int wil_freq_debugfs_show(struct seq_file *s, void *data) { struct wil6210_priv *wil = s->private; - struct wireless_dev *wdev = wil_to_wdev(wil); + struct wireless_dev *wdev = wil->main_ndev->ieee80211_ptr; u16 freq = wdev->chandef.chan ? wdev->chandef.chan->center_freq : 0; seq_printf(s, "Freq = %d\n", freq); @@ -1180,6 +1201,7 @@ static int wil_link_debugfs_show(struct seq_file *s, void *data) { struct wil6210_priv *wil = s->private; struct station_info sinfo; + struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev); int i, rc; for (i = 0; i < ARRAY_SIZE(wil->sta); i++) { @@ -1200,7 +1222,7 @@ static int wil_link_debugfs_show(struct seq_file *s, void *data) seq_printf(s, "[%d] %pM %s\n", i, p->addr, status); if (p->status == wil_sta_connected) { - rc = wil_cid_fill_sinfo(wil, i, &sinfo); + rc = wil_cid_fill_sinfo(vif, i, &sinfo); if (rc) return rc; @@ -1229,7 +1251,7 @@ static const struct file_operations fops_link = { static int wil_info_debugfs_show(struct seq_file *s, void *data) { struct wil6210_priv *wil = s->private; - struct net_device *ndev = wil_to_ndev(wil); + struct net_device *ndev = wil->main_ndev; int is_ac = power_supply_is_system_supplied(); int rx = atomic_xchg(&wil->isr_count_rx, 0); int tx = atomic_xchg(&wil->isr_count_tx, 0); @@ -1773,11 +1795,9 @@ static void wil6210_debugfs_init_isr(struct wil6210_priv *wil, /* fields in struct wil6210_priv */ static const struct dbg_off dbg_wil_off[] = { - WIL_FIELD(privacy, 0444, doff_u32), WIL_FIELD(status[0], 0644, doff_ulong), WIL_FIELD(hw_version, 0444, doff_x32), WIL_FIELD(recovery_count, 0444, doff_u32), - WIL_FIELD(ap_isolate, 0444, doff_u32), WIL_FIELD(discovery_mode, 0644, doff_u8), WIL_FIELD(chip_revision, 0444, doff_u8), WIL_FIELD(abft_len, 0644, doff_u8), diff --git a/drivers/net/wireless/ath/wil6210/ethtool.c b/drivers/net/wireless/ath/wil6210/ethtool.c index 66200f616a37..e7ff41e623d2 100644 --- a/drivers/net/wireless/ath/wil6210/ethtool.c +++ b/drivers/net/wireless/ath/wil6210/ethtool.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2014,2017 Qualcomm Atheros, Inc. + * Copyright (c) 2018, The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -74,12 +75,13 @@ static int wil_ethtoolops_set_coalesce(struct net_device *ndev, struct ethtool_coalesce *cp) { struct wil6210_priv *wil = ndev_to_wil(ndev); + struct wireless_dev *wdev = ndev->ieee80211_ptr; int ret; wil_dbg_misc(wil, "ethtoolops_set_coalesce: rx %d usec, tx %d usec\n", cp->rx_coalesce_usecs, cp->tx_coalesce_usecs); - if (wil->wdev->iftype == NL80211_IFTYPE_MONITOR) { + if (wdev->iftype == NL80211_IFTYPE_MONITOR) { wil_dbg_misc(wil, "No IRQ coalescing in monitor mode\n"); return -EINVAL; } diff --git a/drivers/net/wireless/ath/wil6210/interrupt.c b/drivers/net/wireless/ath/wil6210/interrupt.c index 1835187ea075..ef8f9a769833 100644 --- a/drivers/net/wireless/ath/wil6210/interrupt.c +++ b/drivers/net/wireless/ath/wil6210/interrupt.c @@ -188,12 +188,14 @@ void wil_unmask_irq(struct wil6210_priv *wil) void wil_configure_interrupt_moderation(struct wil6210_priv *wil) { + struct wireless_dev *wdev = wil->main_ndev->ieee80211_ptr; + wil_dbg_irq(wil, "configure_interrupt_moderation\n"); /* disable interrupt moderation for monitor * to get better timestamp precision */ - if (wil->wdev->iftype == NL80211_IFTYPE_MONITOR) + if (wdev->iftype == NL80211_IFTYPE_MONITOR) return; /* Disable and clear tx counter before (re)configuration */ @@ -340,7 +342,7 @@ static irqreturn_t wil6210_irq_tx(int irq, void *cookie) static void wil_notify_fw_error(struct wil6210_priv *wil) { - struct device *dev = &wil_to_ndev(wil)->dev; + struct device *dev = &wil->main_ndev->dev; char *envp[3] = { [0] = "SOURCE=wil6210", [1] = "EVENT=FW_ERROR", diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index 04c8651274d9..b151f1c7ce85 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c @@ -160,24 +160,25 @@ void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src, } } -static void wil_disconnect_cid(struct wil6210_priv *wil, int cid, +static void wil_disconnect_cid(struct wil6210_vif *vif, int cid, u16 reason_code, bool from_event) __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) { uint i; - struct net_device *ndev = wil_to_ndev(wil); - struct wireless_dev *wdev = wil->wdev; + struct wil6210_priv *wil = vif_to_wil(vif); + struct net_device *ndev = vif_to_ndev(vif); + struct wireless_dev *wdev = vif_to_wdev(vif); struct wil_sta_info *sta = &wil->sta[cid]; might_sleep(); - wil_dbg_misc(wil, "disconnect_cid: CID %d, status %d\n", - cid, sta->status); + wil_dbg_misc(wil, "disconnect_cid: CID %d, MID %d, status %d\n", + cid, sta->mid, sta->status); /* inform upper/lower layers */ if (sta->status != wil_sta_unused) { if (!from_event) { bool del_sta = (wdev->iftype == NL80211_IFTYPE_AP) ? disable_ap_sme : false; - wmi_disconnect_sta(wil, sta->addr, reason_code, + wmi_disconnect_sta(vif, sta->addr, reason_code, true, del_sta); } @@ -191,6 +192,7 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) break; } sta->status = wil_sta_unused; + sta->mid = U8_MAX; } /* reorder buffers */ for (i = 0; i < WIL_STA_TID_NUM; i++) { @@ -216,28 +218,33 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) memset(&sta->stats, 0, sizeof(sta->stats)); } -static bool wil_is_connected(struct wil6210_priv *wil) +static bool wil_vif_is_connected(struct wil6210_priv *wil, u8 mid) { int i; for (i = 0; i < ARRAY_SIZE(wil->sta); i++) { - if (wil->sta[i].status == wil_sta_connected) + if (wil->sta[i].mid == mid && + wil->sta[i].status == wil_sta_connected) return true; } return false; } -static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid, +static void _wil6210_disconnect(struct wil6210_vif *vif, const u8 *bssid, u16 reason_code, bool from_event) { + struct wil6210_priv *wil = vif_to_wil(vif); int cid = -ENOENT; - struct net_device *ndev = wil_to_ndev(wil); - struct wireless_dev *wdev = wil->wdev; + struct net_device *ndev; + struct wireless_dev *wdev; - if (unlikely(!ndev)) + if (unlikely(!vif)) return; + ndev = vif_to_ndev(vif); + wdev = vif_to_wdev(vif); + might_sleep(); wil_info(wil, "bssid=%pM, reason=%d, ev%s\n", bssid, reason_code, from_event ? "+" : "-"); @@ -254,22 +261,22 @@ static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid, */ if (bssid && !is_broadcast_ether_addr(bssid) && !ether_addr_equal_unaligned(ndev->dev_addr, bssid)) { - cid = wil_find_cid(wil, bssid); + cid = wil_find_cid(wil, vif->mid, bssid); wil_dbg_misc(wil, "Disconnect %pM, CID=%d, reason=%d\n", bssid, cid, reason_code); if (cid >= 0) /* disconnect 1 peer */ - wil_disconnect_cid(wil, cid, reason_code, from_event); + wil_disconnect_cid(vif, cid, reason_code, from_event); } else { /* all */ wil_dbg_misc(wil, "Disconnect all\n"); for (cid = 0; cid < WIL6210_MAX_CID; cid++) - wil_disconnect_cid(wil, cid, reason_code, from_event); + wil_disconnect_cid(vif, cid, reason_code, from_event); } /* link state */ switch (wdev->iftype) { case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_P2P_CLIENT: - wil_bcast_fini(wil); + wil_bcast_fini(vif); wil_update_net_queues_bh(wil, NULL, true); netif_carrier_off(ndev); wil6210_bus_request(wil, WIL_DEFAULT_BUS_REQUEST_KBPS); @@ -278,20 +285,20 @@ static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid, clear_bit(wil_status_fwconnected, wil->status); cfg80211_disconnected(ndev, reason_code, NULL, 0, - wil->locally_generated_disc, + vif->locally_generated_disc, GFP_KERNEL); - wil->locally_generated_disc = false; + vif->locally_generated_disc = false; } else if (test_bit(wil_status_fwconnecting, wil->status)) { cfg80211_connect_result(ndev, bssid, NULL, 0, NULL, 0, WLAN_STATUS_UNSPECIFIED_FAILURE, GFP_KERNEL); - wil->bss = NULL; + vif->bss = NULL; } clear_bit(wil_status_fwconnecting, wil->status); break; case NL80211_IFTYPE_AP: case NL80211_IFTYPE_P2P_GO: - if (!wil_is_connected(wil)) { + if (!wil_vif_is_connected(wil, vif->mid)) { wil_update_net_queues_bh(wil, NULL, true); clear_bit(wil_status_fwconnected, wil->status); } else { @@ -303,11 +310,12 @@ static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid, } } -static void wil_disconnect_worker(struct work_struct *work) +void wil_disconnect_worker(struct work_struct *work) { - struct wil6210_priv *wil = container_of(work, - struct wil6210_priv, disconnect_worker); - struct net_device *ndev = wil_to_ndev(wil); + struct wil6210_vif *vif = container_of(work, + struct wil6210_vif, disconnect_worker); + struct wil6210_priv *wil = vif_to_wil(vif); + struct net_device *ndev = vif_to_ndev(vif); int rc; struct { struct wmi_cmd_hdr wmi; @@ -322,7 +330,7 @@ static void wil_disconnect_worker(struct work_struct *work) /* already disconnected */ return; - rc = wmi_call(wil, WMI_DISCONNECT_CMDID, NULL, 0, + rc = wmi_call(wil, WMI_DISCONNECT_CMDID, vif->mid, NULL, 0, WMI_DISCONNECT_EVENTID, &reply, sizeof(reply), WIL6210_DISCONNECT_TO_MS); if (rc) { @@ -337,30 +345,6 @@ static void wil_disconnect_worker(struct work_struct *work) clear_bit(wil_status_fwconnecting, wil->status); } -static void wil_connect_timer_fn(struct timer_list *t) -{ - struct wil6210_priv *wil = from_timer(wil, t, connect_timer); - bool q; - - wil_err(wil, "Connect timeout detected, disconnect station\n"); - - /* reschedule to thread context - disconnect won't - * run from atomic context. - * queue on wmi_wq to prevent race with connect event. - */ - q = queue_work(wil->wmi_wq, &wil->disconnect_worker); - wil_dbg_wmi(wil, "queue_work of disconnect_worker -> %d\n", q); -} - -static void wil_scan_timer_fn(struct timer_list *t) -{ - struct wil6210_priv *wil = from_timer(wil, t, scan_timer); - - clear_bit(wil_status_fwready, wil->status); - wil_err(wil, "Scan timeout detected, start fw error recovery\n"); - wil_fw_error_recovery(wil); -} - static int wil_wait_for_recovery(struct wil6210_priv *wil) { if (wait_event_interruptible(wil->wq, wil->recovery_state != @@ -394,12 +378,12 @@ static void wil_fw_error_worker(struct work_struct *work) { struct wil6210_priv *wil = container_of(work, struct wil6210_priv, fw_error_worker); - struct wireless_dev *wdev = wil->wdev; - struct net_device *ndev = wil_to_ndev(wil); + struct net_device *ndev = wil->main_ndev; + struct wireless_dev *wdev = ndev->ieee80211_ptr; wil_dbg_misc(wil, "fw error worker\n"); - if (!(ndev->flags & IFF_UP)) { + if (!ndev || !(ndev->flags & IFF_UP)) { wil_info(wil, "No recovery - interface is down\n"); return; } @@ -429,6 +413,10 @@ static void wil_fw_error_worker(struct work_struct *work) return; mutex_lock(&wil->mutex); + /* Needs adaptation for multiple VIFs + * need to go over all VIFs and consider the appropriate + * recovery. + */ switch (wdev->iftype) { case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_P2P_CLIENT: @@ -461,8 +449,9 @@ static int wil_find_free_vring(struct wil6210_priv *wil) return -EINVAL; } -int wil_tx_init(struct wil6210_priv *wil, int cid) +int wil_tx_init(struct wil6210_vif *vif, int cid) { + struct wil6210_priv *wil = vif_to_wil(vif); int rc = -EINVAL, ringid; if (cid < 0) { @@ -475,21 +464,22 @@ int wil_tx_init(struct wil6210_priv *wil, int cid) goto out; } - wil_dbg_wmi(wil, "Configure for connection CID %d vring %d\n", - cid, ringid); + wil_dbg_wmi(wil, "Configure for connection CID %d MID %d vring %d\n", + cid, vif->mid, ringid); - rc = wil_vring_init_tx(wil, ringid, 1 << tx_ring_order, cid, 0); + rc = wil_vring_init_tx(vif, ringid, 1 << tx_ring_order, cid, 0); if (rc) - wil_err(wil, "wil_vring_init_tx for CID %d vring %d failed\n", - cid, ringid); + wil_err(wil, "init TX for CID %d MID %d vring %d failed\n", + cid, vif->mid, ringid); out: return rc; } -int wil_bcast_init(struct wil6210_priv *wil) +int wil_bcast_init(struct wil6210_vif *vif) { - int ri = wil->bcast_vring, rc; + struct wil6210_priv *wil = vif_to_wil(vif); + int ri = vif->bcast_vring, rc; if ((ri >= 0) && wil->vring_tx[ri].va) return 0; @@ -498,22 +488,23 @@ int wil_bcast_init(struct wil6210_priv *wil) if (ri < 0) return ri; - wil->bcast_vring = ri; - rc = wil_vring_init_bcast(wil, ri, 1 << bcast_ring_order); + vif->bcast_vring = ri; + rc = wil_vring_init_bcast(vif, ri, 1 << bcast_ring_order); if (rc) - wil->bcast_vring = -1; + vif->bcast_vring = -1; return rc; } -void wil_bcast_fini(struct wil6210_priv *wil) +void wil_bcast_fini(struct wil6210_vif *vif) { - int ri = wil->bcast_vring; + struct wil6210_priv *wil = vif_to_wil(vif); + int ri = vif->bcast_vring; if (ri < 0) return; - wil->bcast_vring = -1; + vif->bcast_vring = -1; wil_vring_fini_tx(wil, ri); } @@ -524,15 +515,16 @@ int wil_priv_init(struct wil6210_priv *wil) wil_dbg_misc(wil, "priv_init\n"); memset(wil->sta, 0, sizeof(wil->sta)); - for (i = 0; i < WIL6210_MAX_CID; i++) + for (i = 0; i < WIL6210_MAX_CID; i++) { spin_lock_init(&wil->sta[i].tid_rx_lock); + wil->sta[i].mid = U8_MAX; + } for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) spin_lock_init(&wil->vring_tx_data[i].lock); mutex_init(&wil->mutex); mutex_init(&wil->wmi_mutex); - mutex_init(&wil->probe_client_mutex); mutex_init(&wil->p2p_wdev_mutex); mutex_init(&wil->halp.lock); @@ -540,22 +532,12 @@ int wil_priv_init(struct wil6210_priv *wil) init_completion(&wil->wmi_call); init_completion(&wil->halp.comp); - wil->bcast_vring = -1; - timer_setup(&wil->connect_timer, wil_connect_timer_fn, 0); - timer_setup(&wil->scan_timer, wil_scan_timer_fn, 0); - timer_setup(&wil->p2p.discovery_timer, wil_p2p_discovery_timer_fn, 0); - - INIT_WORK(&wil->disconnect_worker, wil_disconnect_worker); INIT_WORK(&wil->wmi_event_worker, wmi_event_worker); INIT_WORK(&wil->fw_error_worker, wil_fw_error_worker); - INIT_WORK(&wil->probe_client_worker, wil_probe_client_worker); - INIT_WORK(&wil->p2p.delayed_listen_work, wil_p2p_delayed_listen_work); INIT_LIST_HEAD(&wil->pending_wmi_ev); - INIT_LIST_HEAD(&wil->probe_client_pending); spin_lock_init(&wil->wmi_ev_lock); spin_lock_init(&wil->net_queue_lock); - wil->net_queue_stopped = 1; init_waitqueue_head(&wil->wq); wil->wmi_wq = create_singlethread_workqueue(WIL_NAME "_wmi"); @@ -582,6 +564,8 @@ int wil_priv_init(struct wil6210_priv *wil) memset(&wil->suspend_stats, 0, sizeof(wil->suspend_stats)); wil->vring_idle_trsh = 16; + wil->reply_mid = U8_MAX; + return 0; out_wmi_wq: @@ -600,7 +584,7 @@ void wil6210_bus_request(struct wil6210_priv *wil, u32 kbps) /** * wil6210_disconnect - disconnect one connection - * @wil: driver context + * @vif: virtual interface context * @bssid: peer to disconnect, NULL to disconnect all * @reason_code: Reason code for the Disassociation frame * @from_event: whether is invoked from FW event handler @@ -608,13 +592,15 @@ void wil6210_bus_request(struct wil6210_priv *wil, u32 kbps) * Disconnect and release associated resources. If invoked not from the * FW event handler, issue WMI command(s) to trigger MAC disconnect. */ -void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid, +void wil6210_disconnect(struct wil6210_vif *vif, const u8 *bssid, u16 reason_code, bool from_event) { + struct wil6210_priv *wil = vif_to_wil(vif); + wil_dbg_misc(wil, "disconnect\n"); - del_timer_sync(&wil->connect_timer); - _wil6210_disconnect(wil, bssid, reason_code, from_event); + del_timer_sync(&vif->connect_timer); + _wil6210_disconnect(vif, bssid, reason_code, from_event); } void wil_priv_deinit(struct wil6210_priv *wil) @@ -622,18 +608,8 @@ void wil_priv_deinit(struct wil6210_priv *wil) wil_dbg_misc(wil, "priv_deinit\n"); wil_set_recovery_state(wil, fw_recovery_idle); - del_timer_sync(&wil->scan_timer); - del_timer_sync(&wil->p2p.discovery_timer); - cancel_work_sync(&wil->disconnect_worker); cancel_work_sync(&wil->fw_error_worker); - cancel_work_sync(&wil->p2p.discovery_expired_work); - cancel_work_sync(&wil->p2p.delayed_listen_work); - mutex_lock(&wil->mutex); - wil6210_disconnect(wil, NULL, WLAN_REASON_DEAUTH_LEAVING, false); - mutex_unlock(&wil->mutex); wmi_event_flush(wil); - wil_probe_client_flush(wil); - cancel_work_sync(&wil->probe_client_worker); destroy_workqueue(wil->wq_service); destroy_workqueue(wil->wmi_wq); } @@ -943,7 +919,7 @@ void wil_mbox_ring_le2cpus(struct wil6210_mbox_ring *r) static int wil_get_bl_info(struct wil6210_priv *wil) { - struct net_device *ndev = wil_to_ndev(wil); + struct net_device *ndev = wil->main_ndev; struct wiphy *wiphy = wil_to_wiphy(wil); union { struct bl_dedicated_registers_v0 bl0; @@ -1035,7 +1011,7 @@ static void wil_bl_crash_info(struct wil6210_priv *wil, bool is_err) static int wil_get_otp_info(struct wil6210_priv *wil) { - struct net_device *ndev = wil_to_ndev(wil); + struct net_device *ndev = wil->main_ndev; struct wiphy *wiphy = wil_to_wiphy(wil); u8 mac[8]; @@ -1069,8 +1045,9 @@ static int wil_wait_for_fw_ready(struct wil6210_priv *wil) return 0; } -void wil_abort_scan(struct wil6210_priv *wil, bool sync) +void wil_abort_scan(struct wil6210_vif *vif, bool sync) { + struct wil6210_priv *wil = vif_to_wil(vif); int rc; struct cfg80211_scan_info info = { .aborted = true, @@ -1078,22 +1055,22 @@ void wil_abort_scan(struct wil6210_priv *wil, bool sync) lockdep_assert_held(&wil->p2p_wdev_mutex); - if (!wil->scan_request) + if (!vif->scan_request) return; - wil_dbg_misc(wil, "Abort scan_request 0x%p\n", wil->scan_request); - del_timer_sync(&wil->scan_timer); + wil_dbg_misc(wil, "Abort scan_request 0x%p\n", vif->scan_request); + del_timer_sync(&vif->scan_timer); mutex_unlock(&wil->p2p_wdev_mutex); - rc = wmi_abort_scan(wil); + rc = wmi_abort_scan(vif); if (!rc && sync) - wait_event_interruptible_timeout(wil->wq, !wil->scan_request, + wait_event_interruptible_timeout(wil->wq, !vif->scan_request, msecs_to_jiffies( WAIT_FOR_SCAN_ABORT_MS)); mutex_lock(&wil->p2p_wdev_mutex); - if (wil->scan_request) { - cfg80211_scan_done(wil->scan_request, &info); - wil->scan_request = NULL; + if (vif->scan_request) { + cfg80211_scan_done(vif->scan_request, &info); + vif->scan_request = NULL; } } @@ -1148,6 +1125,7 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) int rc; unsigned long status_flags = BIT(wil_status_resetting); int no_flash; + struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev); wil_dbg_misc(wil, "reset\n"); @@ -1158,7 +1136,7 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) static const u8 mac[ETH_ALEN] = { 0x00, 0xde, 0xad, 0x12, 0x34, 0x56, }; - struct net_device *ndev = wil_to_ndev(wil); + struct net_device *ndev = wil->main_ndev; ether_addr_copy(ndev->perm_addr, mac); ether_addr_copy(ndev->dev_addr, ndev->perm_addr); @@ -1196,15 +1174,15 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) goto out; } - cancel_work_sync(&wil->disconnect_worker); - wil6210_disconnect(wil, NULL, WLAN_REASON_DEAUTH_LEAVING, false); - wil_bcast_fini(wil); + cancel_work_sync(&vif->disconnect_worker); + wil6210_disconnect(vif, NULL, WLAN_REASON_DEAUTH_LEAVING, false); + wil_bcast_fini(vif); /* Disable device led before reset*/ wmi_led_cfg(wil, false); mutex_lock(&wil->p2p_wdev_mutex); - wil_abort_scan(wil, false); + wil_abort_scan(vif, false); mutex_unlock(&wil->p2p_wdev_mutex); /* prevent NAPI from being scheduled and prevent wmi commands */ @@ -1276,7 +1254,7 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) } /* init after reset */ - wil->ap_isolate = 0; + vif->ap_isolate = 0; reinit_completion(&wil->wmi_ready); reinit_completion(&wil->wmi_call); reinit_completion(&wil->halp.comp); @@ -1337,8 +1315,8 @@ void wil_fw_error_recovery(struct wil6210_priv *wil) int __wil_up(struct wil6210_priv *wil) { - struct net_device *ndev = wil_to_ndev(wil); - struct wireless_dev *wdev = wil->wdev; + struct net_device *ndev = wil->main_ndev; + struct wireless_dev *wdev = ndev->ieee80211_ptr; int rc; WARN_ON(!mutex_is_locked(&wil->mutex)); @@ -1422,7 +1400,7 @@ int __wil_down(struct wil6210_priv *wil) mutex_lock(&wil->p2p_wdev_mutex); wil_p2p_stop_radio_operations(wil); - wil_abort_scan(wil, false); + wil_abort_scan(ndev_to_vif(wil->main_ndev), false); mutex_unlock(&wil->p2p_wdev_mutex); return wil_reset(wil, false); @@ -1442,13 +1420,14 @@ int wil_down(struct wil6210_priv *wil) return rc; } -int wil_find_cid(struct wil6210_priv *wil, const u8 *mac) +int wil_find_cid(struct wil6210_priv *wil, u8 mid, const u8 *mac) { int i; int rc = -ENOENT; for (i = 0; i < ARRAY_SIZE(wil->sta); i++) { - if ((wil->sta[i].status != wil_sta_unused) && + if (wil->sta[i].mid == mid && + wil->sta[i].status != wil_sta_unused && ether_addr_equal(wil->sta[i].addr, mac)) { rc = i; break; diff --git a/drivers/net/wireless/ath/wil6210/netdev.c b/drivers/net/wireless/ath/wil6210/netdev.c index 648f63682f59..95570b8f1f6d 100644 --- a/drivers/net/wireless/ath/wil6210/netdev.c +++ b/drivers/net/wireless/ath/wil6210/netdev.c @@ -122,6 +122,85 @@ static void wil_dev_setup(struct net_device *dev) dev->tx_queue_len = WIL_TX_Q_LEN_DEFAULT; } +static void wil_vif_deinit(struct wil6210_vif *vif) +{ + del_timer_sync(&vif->scan_timer); + del_timer_sync(&vif->p2p.discovery_timer); + cancel_work_sync(&vif->disconnect_worker); + cancel_work_sync(&vif->p2p.discovery_expired_work); + cancel_work_sync(&vif->p2p.delayed_listen_work); + wil_probe_client_flush(vif); + cancel_work_sync(&vif->probe_client_worker); +} + +void wil_vif_free(struct wil6210_vif *vif) +{ + struct net_device *ndev = vif_to_ndev(vif); + + wil_vif_deinit(vif); + free_netdev(ndev); +} + +static void wil_ndev_destructor(struct net_device *ndev) +{ + struct wil6210_vif *vif = ndev_to_vif(ndev); + + wil_vif_deinit(vif); +} + +static void wil_connect_timer_fn(struct timer_list *t) +{ + struct wil6210_vif *vif = from_timer(vif, t, connect_timer); + struct wil6210_priv *wil = vif_to_wil(vif); + bool q; + + wil_err(wil, "Connect timeout detected, disconnect station\n"); + + /* reschedule to thread context - disconnect won't + * run from atomic context. + * queue on wmi_wq to prevent race with connect event. + */ + q = queue_work(wil->wmi_wq, &vif->disconnect_worker); + wil_dbg_wmi(wil, "queue_work of disconnect_worker -> %d\n", q); +} + +static void wil_scan_timer_fn(struct timer_list *t) +{ + struct wil6210_vif *vif = from_timer(vif, t, scan_timer); + struct wil6210_priv *wil = vif_to_wil(vif); + + clear_bit(wil_status_fwready, wil->status); + wil_err(wil, "Scan timeout detected, start fw error recovery\n"); + wil_fw_error_recovery(wil); +} + +static void wil_p2p_discovery_timer_fn(struct timer_list *t) +{ + struct wil6210_vif *vif = from_timer(vif, t, p2p.discovery_timer); + struct wil6210_priv *wil = vif_to_wil(vif); + + wil_dbg_misc(wil, "p2p_discovery_timer_fn\n"); + + schedule_work(&vif->p2p.discovery_expired_work); +} + +static void wil_vif_init(struct wil6210_vif *vif) +{ + vif->bcast_vring = -1; + + mutex_init(&vif->probe_client_mutex); + + timer_setup(&vif->connect_timer, wil_connect_timer_fn, 0); + timer_setup(&vif->scan_timer, wil_scan_timer_fn, 0); + timer_setup(&vif->p2p.discovery_timer, wil_p2p_discovery_timer_fn, 0); + + INIT_WORK(&vif->probe_client_worker, wil_probe_client_worker); + INIT_WORK(&vif->disconnect_worker, wil_disconnect_worker); + INIT_WORK(&vif->p2p.delayed_listen_work, wil_p2p_delayed_listen_work); + + INIT_LIST_HEAD(&vif->probe_client_pending); +} + struct wil6210_vif * wil_vif_alloc(struct wil6210_priv *wil, const char *name, unsigned char name_assign_type, enum nl80211_iftype iftype, @@ -138,10 +217,12 @@ wil_vif_alloc(struct wil6210_priv *wil, const char *name, return ERR_PTR(-ENOMEM); } if (mid == 0) - wil->ndev = ndev; + wil->main_ndev = ndev; vif = ndev_to_vif(ndev); + vif->ndev = ndev; vif->wil = wil; vif->mid = mid; + wil_vif_init(vif); wdev = &vif->wdev; wdev->wiphy = wil->wiphy; @@ -163,7 +244,6 @@ wil_vif_alloc(struct wil6210_priv *wil, const char *name, void *wil_if_alloc(struct device *dev) { - struct wireless_dev *wdev; struct wil6210_priv *wil; struct wil6210_vif *vif; int rc = 0; @@ -190,9 +270,7 @@ void *wil_if_alloc(struct device *dev) goto out_priv; } - wdev = &vif->wdev; - wil->wdev = wdev; - wil->radio_wdev = wdev; + wil->radio_wdev = vif_to_wdev(vif); return wil; @@ -207,7 +285,7 @@ out_cfg: void wil_if_free(struct wil6210_priv *wil) { - struct net_device *ndev = wil_to_ndev(wil); + struct net_device *ndev = wil->main_ndev; wil_dbg_misc(wil, "if_free\n"); @@ -216,7 +294,8 @@ void wil_if_free(struct wil6210_priv *wil) wil_priv_deinit(wil); - wil_to_ndev(wil) = NULL; + wil->main_ndev = NULL; + wil_ndev_destructor(ndev); free_netdev(ndev); wil_cfg80211_deinit(wil); @@ -224,9 +303,8 @@ void wil_if_free(struct wil6210_priv *wil) int wil_if_add(struct wil6210_priv *wil) { - struct wireless_dev *wdev = wil_to_wdev(wil); struct wiphy *wiphy = wil->wiphy; - struct net_device *ndev = wil_to_ndev(wil); + struct net_device *ndev = wil->main_ndev; int rc; wil_dbg_misc(wil, "entered"); @@ -255,14 +333,14 @@ int wil_if_add(struct wil6210_priv *wil) return 0; out_wiphy: - wiphy_unregister(wdev->wiphy); + wiphy_unregister(wiphy); return rc; } void wil_if_remove(struct wil6210_priv *wil) { - struct net_device *ndev = wil_to_ndev(wil); - struct wireless_dev *wdev = wil_to_wdev(wil); + struct net_device *ndev = wil->main_ndev; + struct wireless_dev *wdev = ndev->ieee80211_ptr; wil_dbg_misc(wil, "if_remove\n"); diff --git a/drivers/net/wireless/ath/wil6210/p2p.c b/drivers/net/wireless/ath/wil6210/p2p.c index 7dbee2c3e482..8b34f18590d9 100644 --- a/drivers/net/wireless/ath/wil6210/p2p.c +++ b/drivers/net/wireless/ath/wil6210/p2p.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2014-2017 Qualcomm Atheros, Inc. + * Copyright (c) 2018, The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -22,27 +23,28 @@ #define P2P_SEARCH_DURATION_MS 500 #define P2P_DEFAULT_BI 100 -static int wil_p2p_start_listen(struct wil6210_priv *wil) +static int wil_p2p_start_listen(struct wil6210_vif *vif) { - struct wil_p2p_info *p2p = &wil->p2p; + struct wil6210_priv *wil = vif_to_wil(vif); + struct wil_p2p_info *p2p = &vif->p2p; u8 channel = p2p->listen_chan.hw_value; int rc; lockdep_assert_held(&wil->mutex); - rc = wmi_p2p_cfg(wil, channel, P2P_DEFAULT_BI); + rc = wmi_p2p_cfg(vif, channel, P2P_DEFAULT_BI); if (rc) { wil_err(wil, "wmi_p2p_cfg failed\n"); goto out; } - rc = wmi_set_ssid(wil, strlen(P2P_WILDCARD_SSID), P2P_WILDCARD_SSID); + rc = wmi_set_ssid(vif, strlen(P2P_WILDCARD_SSID), P2P_WILDCARD_SSID); if (rc) { wil_err(wil, "wmi_set_ssid failed\n"); goto out_stop; } - rc = wmi_start_listen(wil); + rc = wmi_start_listen(vif); if (rc) { wil_err(wil, "wmi_start_listen failed\n"); goto out_stop; @@ -53,7 +55,7 @@ static int wil_p2p_start_listen(struct wil6210_priv *wil) jiffies + msecs_to_jiffies(p2p->listen_duration)); out_stop: if (rc) - wmi_stop_discovery(wil); + wmi_stop_discovery(vif); out: return rc; @@ -65,20 +67,12 @@ bool wil_p2p_is_social_scan(struct cfg80211_scan_request *request) (request->channels[0]->hw_value == P2P_DMG_SOCIAL_CHANNEL); } -void wil_p2p_discovery_timer_fn(struct timer_list *t) -{ - struct wil6210_priv *wil = from_timer(wil, t, p2p.discovery_timer); - - wil_dbg_misc(wil, "p2p_discovery_timer_fn\n"); - - schedule_work(&wil->p2p.discovery_expired_work); -} - -int wil_p2p_search(struct wil6210_priv *wil, +int wil_p2p_search(struct wil6210_vif *vif, struct cfg80211_scan_request *request) { + struct wil6210_priv *wil = vif_to_wil(vif); int rc; - struct wil_p2p_info *p2p = &wil->p2p; + struct wil_p2p_info *p2p = &vif->p2p; wil_dbg_misc(wil, "p2p_search: channel %d\n", P2P_DMG_SOCIAL_CHANNEL); @@ -90,20 +84,20 @@ int wil_p2p_search(struct wil6210_priv *wil, goto out; } - rc = wmi_p2p_cfg(wil, P2P_DMG_SOCIAL_CHANNEL, P2P_DEFAULT_BI); + rc = wmi_p2p_cfg(vif, P2P_DMG_SOCIAL_CHANNEL, P2P_DEFAULT_BI); if (rc) { wil_err(wil, "wmi_p2p_cfg failed\n"); goto out; } - rc = wmi_set_ssid(wil, strlen(P2P_WILDCARD_SSID), P2P_WILDCARD_SSID); + rc = wmi_set_ssid(vif, strlen(P2P_WILDCARD_SSID), P2P_WILDCARD_SSID); if (rc) { wil_err(wil, "wmi_set_ssid failed\n"); goto out_stop; } /* Set application IE to probe request and probe response */ - rc = wmi_set_ie(wil, WMI_FRAME_PROBE_REQ, + rc = wmi_set_ie(vif, WMI_FRAME_PROBE_REQ, request->ie_len, request->ie); if (rc) { wil_err(wil, "wmi_set_ie(WMI_FRAME_PROBE_REQ) failed\n"); @@ -113,14 +107,14 @@ int wil_p2p_search(struct wil6210_priv *wil, /* supplicant doesn't provide Probe Response IEs. As a workaround - * re-use Probe Request IEs */ - rc = wmi_set_ie(wil, WMI_FRAME_PROBE_RESP, + rc = wmi_set_ie(vif, WMI_FRAME_PROBE_RESP, request->ie_len, request->ie); if (rc) { wil_err(wil, "wmi_set_ie(WMI_FRAME_PROBE_RESP) failed\n"); goto out_stop; } - rc = wmi_start_search(wil); + rc = wmi_start_search(vif); if (rc) { wil_err(wil, "wmi_start_search failed\n"); goto out_stop; @@ -133,7 +127,7 @@ int wil_p2p_search(struct wil6210_priv *wil, out_stop: if (rc) - wmi_stop_discovery(wil); + wmi_stop_discovery(vif); out: return rc; @@ -143,7 +137,8 @@ int wil_p2p_listen(struct wil6210_priv *wil, struct wireless_dev *wdev, unsigned int duration, struct ieee80211_channel *chan, u64 *cookie) { - struct wil_p2p_info *p2p = &wil->p2p; + struct wil6210_vif *vif = wdev_to_vif(wil, wdev); + struct wil_p2p_info *p2p = &vif->p2p; int rc; if (!chan) @@ -164,7 +159,7 @@ int wil_p2p_listen(struct wil6210_priv *wil, struct wireless_dev *wdev, p2p->listen_duration = duration; mutex_lock(&wil->p2p_wdev_mutex); - if (wil->scan_request) { + if (vif->scan_request) { wil_dbg_misc(wil, "Delaying p2p listen until scan done\n"); p2p->pending_listen_wdev = wdev; p2p->discovery_started = 1; @@ -174,12 +169,13 @@ int wil_p2p_listen(struct wil6210_priv *wil, struct wireless_dev *wdev, } mutex_unlock(&wil->p2p_wdev_mutex); - rc = wil_p2p_start_listen(wil); + rc = wil_p2p_start_listen(vif); if (rc) goto out; p2p->discovery_started = 1; - wil->radio_wdev = wdev; + if (vif->mid == 0) + wil->radio_wdev = wdev; cfg80211_ready_on_channel(wdev, *cookie, chan, duration, GFP_KERNEL); @@ -189,9 +185,9 @@ out: return rc; } -u8 wil_p2p_stop_discovery(struct wil6210_priv *wil) +u8 wil_p2p_stop_discovery(struct wil6210_vif *vif) { - struct wil_p2p_info *p2p = &wil->p2p; + struct wil_p2p_info *p2p = &vif->p2p; u8 started = p2p->discovery_started; if (p2p->discovery_started) { @@ -200,7 +196,7 @@ u8 wil_p2p_stop_discovery(struct wil6210_priv *wil) p2p->pending_listen_wdev = NULL; } else { del_timer_sync(&p2p->discovery_timer); - wmi_stop_discovery(wil); + wmi_stop_discovery(vif); } p2p->discovery_started = 0; } @@ -208,9 +204,10 @@ u8 wil_p2p_stop_discovery(struct wil6210_priv *wil) return started; } -int wil_p2p_cancel_listen(struct wil6210_priv *wil, u64 cookie) +int wil_p2p_cancel_listen(struct wil6210_vif *vif, u64 cookie) { - struct wil_p2p_info *p2p = &wil->p2p; + struct wil6210_priv *wil = vif_to_wil(vif); + struct wil_p2p_info *p2p = &vif->p2p; u8 started; mutex_lock(&wil->mutex); @@ -222,7 +219,7 @@ int wil_p2p_cancel_listen(struct wil6210_priv *wil, u64 cookie) return -ENOENT; } - started = wil_p2p_stop_discovery(wil); + started = wil_p2p_stop_discovery(vif); mutex_unlock(&wil->mutex); @@ -232,11 +229,12 @@ int wil_p2p_cancel_listen(struct wil6210_priv *wil, u64 cookie) } mutex_lock(&wil->p2p_wdev_mutex); - cfg80211_remain_on_channel_expired(wil->radio_wdev, + cfg80211_remain_on_channel_expired(vif_to_radio_wdev(wil, vif), p2p->cookie, &p2p->listen_chan, GFP_KERNEL); - wil->radio_wdev = wil->wdev; + if (vif->mid == 0) + wil->radio_wdev = wil->main_ndev->ieee80211_ptr; mutex_unlock(&wil->p2p_wdev_mutex); return 0; } @@ -245,40 +243,43 @@ void wil_p2p_listen_expired(struct work_struct *work) { struct wil_p2p_info *p2p = container_of(work, struct wil_p2p_info, discovery_expired_work); - struct wil6210_priv *wil = container_of(p2p, - struct wil6210_priv, p2p); + struct wil6210_vif *vif = container_of(p2p, + struct wil6210_vif, p2p); + struct wil6210_priv *wil = vif_to_wil(vif); u8 started; wil_dbg_misc(wil, "p2p_listen_expired\n"); mutex_lock(&wil->mutex); - started = wil_p2p_stop_discovery(wil); + started = wil_p2p_stop_discovery(vif); mutex_unlock(&wil->mutex); - if (started) { - mutex_lock(&wil->p2p_wdev_mutex); - cfg80211_remain_on_channel_expired(wil->radio_wdev, - p2p->cookie, - &p2p->listen_chan, - GFP_KERNEL); - wil->radio_wdev = wil->wdev; - mutex_unlock(&wil->p2p_wdev_mutex); - } + if (!started) + return; + mutex_lock(&wil->p2p_wdev_mutex); + cfg80211_remain_on_channel_expired(vif_to_radio_wdev(wil, vif), + p2p->cookie, + &p2p->listen_chan, + GFP_KERNEL); + if (vif->mid == 0) + wil->radio_wdev = wil->main_ndev->ieee80211_ptr; + mutex_unlock(&wil->p2p_wdev_mutex); } void wil_p2p_search_expired(struct work_struct *work) { struct wil_p2p_info *p2p = container_of(work, struct wil_p2p_info, discovery_expired_work); - struct wil6210_priv *wil = container_of(p2p, - struct wil6210_priv, p2p); + struct wil6210_vif *vif = container_of(p2p, + struct wil6210_vif, p2p); + struct wil6210_priv *wil = vif_to_wil(vif); u8 started; wil_dbg_misc(wil, "p2p_search_expired\n"); mutex_lock(&wil->mutex); - started = wil_p2p_stop_discovery(wil); + started = wil_p2p_stop_discovery(vif); mutex_unlock(&wil->mutex); if (started) { @@ -287,10 +288,12 @@ void wil_p2p_search_expired(struct work_struct *work) }; mutex_lock(&wil->p2p_wdev_mutex); - if (wil->scan_request) { - cfg80211_scan_done(wil->scan_request, &info); - wil->scan_request = NULL; - wil->radio_wdev = wil->wdev; + if (vif->scan_request) { + cfg80211_scan_done(vif->scan_request, &info); + vif->scan_request = NULL; + if (vif->mid == 0) + wil->radio_wdev = + wil->main_ndev->ieee80211_ptr; } mutex_unlock(&wil->p2p_wdev_mutex); } @@ -300,8 +303,9 @@ void wil_p2p_delayed_listen_work(struct work_struct *work) { struct wil_p2p_info *p2p = container_of(work, struct wil_p2p_info, delayed_listen_work); - struct wil6210_priv *wil = container_of(p2p, - struct wil6210_priv, p2p); + struct wil6210_vif *vif = container_of(p2p, + struct wil6210_vif, p2p); + struct wil6210_priv *wil = vif_to_wil(vif); int rc; mutex_lock(&wil->mutex); @@ -311,14 +315,14 @@ void wil_p2p_delayed_listen_work(struct work_struct *work) goto out; mutex_lock(&wil->p2p_wdev_mutex); - if (wil->scan_request) { + if (vif->scan_request) { /* another scan started, wait again... */ mutex_unlock(&wil->p2p_wdev_mutex); goto out; } mutex_unlock(&wil->p2p_wdev_mutex); - rc = wil_p2p_start_listen(wil); + rc = wil_p2p_start_listen(vif); mutex_lock(&wil->p2p_wdev_mutex); if (rc) { @@ -326,12 +330,14 @@ void wil_p2p_delayed_listen_work(struct work_struct *work) p2p->cookie, &p2p->listen_chan, GFP_KERNEL); - wil->radio_wdev = wil->wdev; + if (vif->mid == 0) + wil->radio_wdev = wil->main_ndev->ieee80211_ptr; } else { cfg80211_ready_on_channel(p2p->pending_listen_wdev, p2p->cookie, &p2p->listen_chan, p2p->listen_duration, GFP_KERNEL); - wil->radio_wdev = p2p->pending_listen_wdev; + if (vif->mid == 0) + wil->radio_wdev = p2p->pending_listen_wdev; } p2p->pending_listen_wdev = NULL; mutex_unlock(&wil->p2p_wdev_mutex); @@ -342,7 +348,8 @@ out: void wil_p2p_stop_radio_operations(struct wil6210_priv *wil) { - struct wil_p2p_info *p2p = &wil->p2p; + struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev); + struct wil_p2p_info *p2p = &vif->p2p; struct cfg80211_scan_info info = { .aborted = true, }; @@ -355,21 +362,21 @@ void wil_p2p_stop_radio_operations(struct wil6210_priv *wil) if (!p2p->discovery_started) { /* Regular scan on the p2p device */ - if (wil->scan_request && - wil->scan_request->wdev == wil->p2p_wdev) - wil_abort_scan(wil, true); + if (vif->scan_request && + vif->scan_request->wdev == wil->p2p_wdev) + wil_abort_scan(vif, true); goto out; } /* Search or listen on p2p device */ mutex_unlock(&wil->p2p_wdev_mutex); - wil_p2p_stop_discovery(wil); + wil_p2p_stop_discovery(vif); mutex_lock(&wil->p2p_wdev_mutex); - if (wil->scan_request) { + if (vif->scan_request) { /* search */ - cfg80211_scan_done(wil->scan_request, &info); - wil->scan_request = NULL; + cfg80211_scan_done(vif->scan_request, &info); + vif->scan_request = NULL; } else { /* listen */ cfg80211_remain_on_channel_expired(wil->radio_wdev, @@ -379,5 +386,5 @@ void wil_p2p_stop_radio_operations(struct wil6210_priv *wil) } out: - wil->radio_wdev = wil->wdev; + wil->radio_wdev = wil->main_ndev->ieee80211_ptr; } diff --git a/drivers/net/wireless/ath/wil6210/pcie_bus.c b/drivers/net/wireless/ath/wil6210/pcie_bus.c index 809092a49192..a61ffd9dce0f 100644 --- a/drivers/net/wireless/ath/wil6210/pcie_bus.c +++ b/drivers/net/wireless/ath/wil6210/pcie_bus.c @@ -425,7 +425,7 @@ static int wil6210_suspend(struct device *dev, bool is_runtime) int rc = 0; struct pci_dev *pdev = to_pci_dev(dev); struct wil6210_priv *wil = pci_get_drvdata(pdev); - struct net_device *ndev = wil_to_ndev(wil); + struct net_device *ndev = wil->main_ndev; bool keep_radio_on = ndev->flags & IFF_UP && wil->keep_radio_on_during_sleep; @@ -457,7 +457,7 @@ static int wil6210_resume(struct device *dev, bool is_runtime) int rc = 0; struct pci_dev *pdev = to_pci_dev(dev); struct wil6210_priv *wil = pci_get_drvdata(pdev); - struct net_device *ndev = wil_to_ndev(wil); + struct net_device *ndev = wil->main_ndev; bool keep_radio_on = ndev->flags & IFF_UP && wil->keep_radio_on_during_sleep; diff --git a/drivers/net/wireless/ath/wil6210/pm.c b/drivers/net/wireless/ath/wil6210/pm.c index 0a96518a566f..12f6d78bcf63 100644 --- a/drivers/net/wireless/ath/wil6210/pm.c +++ b/drivers/net/wireless/ath/wil6210/pm.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2014,2017 Qualcomm Atheros, Inc. + * Copyright (c) 2018, The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -23,8 +24,8 @@ int wil_can_suspend(struct wil6210_priv *wil, bool is_runtime) { int rc = 0; - struct wireless_dev *wdev = wil->wdev; - struct net_device *ndev = wil_to_ndev(wil); + struct net_device *ndev = wil->main_ndev; + struct wireless_dev *wdev = ndev->ieee80211_ptr; bool wmi_only = test_bit(WMI_FW_CAPABILITY_WMI_ONLY, wil->fw_capabilities); @@ -258,7 +259,7 @@ reject_suspend: static int wil_suspend_radio_off(struct wil6210_priv *wil) { int rc = 0; - struct net_device *ndev = wil_to_ndev(wil); + struct net_device *ndev = wil->main_ndev; wil_dbg_pm(wil, "suspend radio off\n"); @@ -306,7 +307,7 @@ out: static int wil_resume_radio_off(struct wil6210_priv *wil) { int rc = 0; - struct net_device *ndev = wil_to_ndev(wil); + struct net_device *ndev = wil->main_ndev; wil_dbg_pm(wil, "Enabling PCIe IRQ\n"); wil_enable_irq(wil); diff --git a/drivers/net/wireless/ath/wil6210/pmc.c b/drivers/net/wireless/ath/wil6210/pmc.c index 4ea27b0bd278..c49f7988369e 100644 --- a/drivers/net/wireless/ath/wil6210/pmc.c +++ b/drivers/net/wireless/ath/wil6210/pmc.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2012-2015,2017 Qualcomm Atheros, Inc. + * Copyright (c) 2018, The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -53,6 +54,7 @@ void wil_pmc_alloc(struct wil6210_priv *wil, u32 i; struct pmc_ctx *pmc = &wil->pmc; struct device *dev = wil_to_dev(wil); + struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev); struct wmi_pmc_cmd pmc_cmd = {0}; int last_cmd_err = -ENOMEM; @@ -186,6 +188,7 @@ void wil_pmc_alloc(struct wil6210_priv *wil, wil_dbg_misc(wil, "pmc_alloc: send WMI_PMC_CMD with ALLOCATE op\n"); pmc->last_cmd_status = wmi_send(wil, WMI_PMC_CMDID, + vif->mid, &pmc_cmd, sizeof(pmc_cmd)); if (pmc->last_cmd_status) { @@ -236,6 +239,7 @@ void wil_pmc_free(struct wil6210_priv *wil, int send_pmc_cmd) { struct pmc_ctx *pmc = &wil->pmc; struct device *dev = wil_to_dev(wil); + struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev); struct wmi_pmc_cmd pmc_cmd = {0}; mutex_lock(&pmc->lock); @@ -254,8 +258,8 @@ void wil_pmc_free(struct wil6210_priv *wil, int send_pmc_cmd) wil_dbg_misc(wil, "send WMI_PMC_CMD with RELEASE op\n"); pmc_cmd.op = WMI_PMC_RELEASE; pmc->last_cmd_status = - wmi_send(wil, WMI_PMC_CMDID, &pmc_cmd, - sizeof(pmc_cmd)); + wmi_send(wil, WMI_PMC_CMDID, vif->mid, + &pmc_cmd, sizeof(pmc_cmd)); if (pmc->last_cmd_status) { wil_err(wil, "WMI_PMC_CMD with RELEASE op failed, status %d", diff --git a/drivers/net/wireless/ath/wil6210/rx_reorder.c b/drivers/net/wireless/ath/wil6210/rx_reorder.c index a43cffcf1bbf..c2140b3d9496 100644 --- a/drivers/net/wireless/ath/wil6210/rx_reorder.c +++ b/drivers/net/wireless/ath/wil6210/rx_reorder.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2014-2017 Qualcomm Atheros, Inc. + * Copyright (c) 2018, The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -44,7 +45,7 @@ static void wil_release_reorder_frame(struct wil6210_priv *wil, struct wil_tid_ampdu_rx *r, int index) { - struct net_device *ndev = wil_to_ndev(wil); + struct net_device *ndev = wil->main_ndev; struct sk_buff *skb = r->reorder_buf[index]; if (!skb) @@ -93,7 +94,7 @@ static void wil_reorder_release(struct wil6210_priv *wil, void wil_rx_reorder(struct wil6210_priv *wil, struct sk_buff *skb) __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) { - struct net_device *ndev = wil_to_ndev(wil); + struct net_device *ndev = wil->main_ndev; struct vring_rx_desc *d = wil_skb_rxdesc(skb); int tid = wil_rxdesc_tid(d); int cid = wil_rxdesc_cid(d); @@ -292,8 +293,8 @@ static u16 wil_agg_size(struct wil6210_priv *wil, u16 req_agg_wsize) } /* Block Ack - Rx side (recipient) */ -int wil_addba_rx_request(struct wil6210_priv *wil, u8 cidxtid, - u8 dialog_token, __le16 ba_param_set, +int wil_addba_rx_request(struct wil6210_priv *wil, u8 mid, + u8 cidxtid, u8 dialog_token, __le16 ba_param_set, __le16 ba_timeout, __le16 ba_seq_ctrl) __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) { @@ -354,7 +355,7 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) } } - rc = wmi_addba_rx_resp(wil, cid, tid, dialog_token, status, + rc = wmi_addba_rx_resp(wil, mid, cid, tid, dialog_token, status, agg_amsdu, agg_wsize, agg_timeout); if (rc || (status != WLAN_STATUS_SUCCESS)) { wil_err(wil, "do not apply ba, rc(%d), status(%d)\n", rc, @@ -393,7 +394,7 @@ int wil_addba_tx_request(struct wil6210_priv *wil, u8 ringid, u16 wsize) goto out; } txdata->addba_in_progress = true; - rc = wmi_addba(wil, ringid, agg_wsize, agg_timeout); + rc = wmi_addba(wil, txdata->mid, ringid, agg_wsize, agg_timeout); if (rc) { wil_err(wil, "wmi_addba failed, rc (%d)", rc); txdata->addba_in_progress = false; diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index 16b8a4e5201f..a53238647b95 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. + * Copyright (c) 2018, The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -474,7 +475,7 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, struct vring *vring) { struct device *dev = wil_to_dev(wil); - struct net_device *ndev = wil_to_ndev(wil); + struct net_device *ndev = wil->main_ndev; volatile struct vring_rx_desc *_d; struct vring_rx_desc *d; struct sk_buff *skb; @@ -624,7 +625,7 @@ again: */ static int wil_rx_refill(struct wil6210_priv *wil, int count) { - struct net_device *ndev = wil_to_ndev(wil); + struct net_device *ndev = wil->main_ndev; struct vring *v = &wil->vring_rx; u32 next_tail; int rc = 0; @@ -713,8 +714,9 @@ static int wil_rx_crypto_check(struct wil6210_priv *wil, struct sk_buff *skb) void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev) { gro_result_t rc = GRO_NORMAL; + struct wil6210_vif *vif = ndev_to_vif(ndev); struct wil6210_priv *wil = ndev_to_wil(ndev); - struct wireless_dev *wdev = wil_to_wdev(wil); + struct wireless_dev *wdev = vif_to_wdev(vif); unsigned int len = skb->len; struct vring_rx_desc *d = wil_skb_rxdesc(skb); int cid = wil_rxdesc_cid(d); /* always 0..7, no need to check */ @@ -751,14 +753,15 @@ void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev) goto stats; } - if (wdev->iftype == NL80211_IFTYPE_AP && !wil->ap_isolate) { + if (wdev->iftype == NL80211_IFTYPE_AP && !vif->ap_isolate) { if (mcast) { /* send multicast frames both to higher layers in * local net stack and back to the wireless medium */ xmit_skb = skb_copy(skb, GFP_ATOMIC); } else { - int xmit_cid = wil_find_cid(wil, eth->h_dest); + int xmit_cid = wil_find_cid(wil, vif->mid, + eth->h_dest); if (xmit_cid >= 0) { /* The destination station is associated to @@ -815,7 +818,8 @@ stats: */ void wil_rx_handle(struct wil6210_priv *wil, int *quota) { - struct net_device *ndev = wil_to_ndev(wil); + struct net_device *ndev = wil->main_ndev; + struct wireless_dev *wdev = ndev->ieee80211_ptr; struct vring *v = &wil->vring_rx; struct sk_buff *skb; @@ -827,7 +831,8 @@ void wil_rx_handle(struct wil6210_priv *wil, int *quota) while ((*quota > 0) && (NULL != (skb = wil_vring_reap_rx(wil, v)))) { (*quota)--; - if (wil->wdev->iftype == NL80211_IFTYPE_MONITOR) { + /* monitor is currently supported on main interface only */ + if (wdev->iftype == NL80211_IFTYPE_MONITOR) { skb->dev = ndev; skb_reset_mac_header(skb); skb->ip_summed = CHECKSUM_UNNECESSARY; @@ -911,12 +916,14 @@ static inline void wil_tx_data_init(struct vring_tx_data *txdata) txdata->agg_timeout = 0; txdata->agg_amsdu = 0; txdata->addba_in_progress = false; + txdata->mid = U8_MAX; spin_unlock_bh(&txdata->lock); } -int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, +int wil_vring_init_tx(struct wil6210_vif *vif, int id, int size, int cid, int tid) { + struct wil6210_priv *wil = vif_to_wil(vif); int rc; struct wmi_vring_cfg_cmd cmd = { .action = cpu_to_le32(WMI_VRING_CMD_ADD), @@ -966,9 +973,9 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, cmd.vring_cfg.tx_sw_ring.ring_mem_base = cpu_to_le64(vring->pa); - if (!wil->privacy) + if (!vif->privacy) txdata->dot1x_open = true; - rc = wmi_call(wil, WMI_VRING_CFG_CMDID, &cmd, sizeof(cmd), + rc = wmi_call(wil, WMI_VRING_CFG_CMDID, vif->mid, &cmd, sizeof(cmd), WMI_VRING_CFG_DONE_EVENTID, &reply, sizeof(reply), 100); if (rc) goto out_free; @@ -982,6 +989,7 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, spin_lock_bh(&txdata->lock); vring->hwtail = le32_to_cpu(reply.cmd.tx_vring_tail_ptr); + txdata->mid = vif->mid; txdata->enabled = 1; spin_unlock_bh(&txdata->lock); @@ -1003,8 +1011,9 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, return rc; } -int wil_vring_init_bcast(struct wil6210_priv *wil, int id, int size) +int wil_vring_init_bcast(struct wil6210_vif *vif, int id, int size) { + struct wil6210_priv *wil = vif_to_wil(vif); int rc; struct wmi_bcast_vring_cfg_cmd cmd = { .action = cpu_to_le32(WMI_VRING_CMD_ADD), @@ -1046,9 +1055,10 @@ int wil_vring_init_bcast(struct wil6210_priv *wil, int id, int size) cmd.vring_cfg.tx_sw_ring.ring_mem_base = cpu_to_le64(vring->pa); - if (!wil->privacy) + if (!vif->privacy) txdata->dot1x_open = true; - rc = wmi_call(wil, WMI_BCAST_VRING_CFG_CMDID, &cmd, sizeof(cmd), + rc = wmi_call(wil, WMI_BCAST_VRING_CFG_CMDID, vif->mid, + &cmd, sizeof(cmd), WMI_VRING_CFG_DONE_EVENTID, &reply, sizeof(reply), 100); if (rc) goto out_free; @@ -1062,6 +1072,7 @@ int wil_vring_init_bcast(struct wil6210_priv *wil, int id, int size) spin_lock_bh(&txdata->lock); vring->hwtail = le32_to_cpu(reply.cmd.tx_vring_tail_ptr); + txdata->mid = vif->mid; txdata->enabled = 1; spin_unlock_bh(&txdata->lock); @@ -1091,6 +1102,7 @@ void wil_vring_fini_tx(struct wil6210_priv *wil, int id) spin_lock_bh(&txdata->lock); txdata->dot1x_open = false; + txdata->mid = U8_MAX; txdata->enabled = 0; /* no Tx can be in progress or start anew */ spin_unlock_bh(&txdata->lock); /* napi_synchronize waits for completion of the current NAPI but will @@ -1108,11 +1120,12 @@ void wil_vring_fini_tx(struct wil6210_priv *wil, int id) } static struct vring *wil_find_tx_ucast(struct wil6210_priv *wil, + struct wil6210_vif *vif, struct sk_buff *skb) { int i; struct ethhdr *eth = (void *)skb->data; - int cid = wil_find_cid(wil, eth->h_dest); + int cid = wil_find_cid(wil, vif->mid, eth->h_dest); if (cid < 0) return NULL; @@ -1142,10 +1155,11 @@ static struct vring *wil_find_tx_ucast(struct wil6210_priv *wil, return NULL; } -static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, - struct sk_buff *skb); +static int wil_tx_vring(struct wil6210_priv *wil, struct wil6210_vif *vif, + struct vring *vring, struct sk_buff *skb); static struct vring *wil_find_tx_vring_sta(struct wil6210_priv *wil, + struct wil6210_vif *vif, struct sk_buff *skb) { struct vring *v; @@ -1160,7 +1174,7 @@ static struct vring *wil_find_tx_vring_sta(struct wil6210_priv *wil, for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) { v = &wil->vring_tx[i]; txdata = &wil->vring_tx_data[i]; - if (!v->va || !txdata->enabled) + if (!v->va || !txdata->enabled || txdata->mid != vif->mid) continue; cid = wil->vring2cid_tid[i][0]; @@ -1193,11 +1207,12 @@ static struct vring *wil_find_tx_vring_sta(struct wil6210_priv *wil, * - for PBSS */ static struct vring *wil_find_tx_bcast_1(struct wil6210_priv *wil, + struct wil6210_vif *vif, struct sk_buff *skb) { struct vring *v; struct vring_tx_data *txdata; - int i = wil->bcast_vring; + int i = vif->bcast_vring; if (i < 0) return NULL; @@ -1222,6 +1237,7 @@ static void wil_set_da_for_vring(struct wil6210_priv *wil, } static struct vring *wil_find_tx_bcast_2(struct wil6210_priv *wil, + struct wil6210_vif *vif, struct sk_buff *skb) { struct vring *v, *v2; @@ -1230,13 +1246,13 @@ static struct vring *wil_find_tx_bcast_2(struct wil6210_priv *wil, u8 cid; struct ethhdr *eth = (void *)skb->data; char *src = eth->h_source; - struct vring_tx_data *txdata; + struct vring_tx_data *txdata, *txdata2; /* find 1-st vring eligible for data */ for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) { v = &wil->vring_tx[i]; txdata = &wil->vring_tx_data[i]; - if (!v->va || !txdata->enabled) + if (!v->va || !txdata->enabled || txdata->mid != vif->mid) continue; cid = wil->vring2cid_tid[i][0]; @@ -1264,7 +1280,8 @@ found: /* find other active vrings and duplicate skb for each */ for (i++; i < WIL6210_MAX_TX_RINGS; i++) { v2 = &wil->vring_tx[i]; - if (!v2->va) + txdata2 = &wil->vring_tx_data[i]; + if (!v2->va || txdata2->mid != vif->mid) continue; cid = wil->vring2cid_tid[i][0]; if (cid >= WIL6210_MAX_CID) /* skip BCAST */ @@ -1280,7 +1297,7 @@ found: if (skb2) { wil_dbg_txrx(wil, "BCAST DUP -> ring %d\n", i); wil_set_da_for_vring(wil, skb2, i); - wil_tx_vring(wil, v2, skb2); + wil_tx_vring(wil, vif, v2, skb2); } else { wil_err(wil, "skb_copy failed\n"); } @@ -1417,8 +1434,8 @@ static inline void wil_set_tx_desc_last_tso(volatile struct vring_tx_desc *d) DMA_CFG_DESC_TX_0_SEGMENT_BUF_DETAILS_POS; } -static int __wil_tx_vring_tso(struct wil6210_priv *wil, struct vring *vring, - struct sk_buff *skb) +static int __wil_tx_vring_tso(struct wil6210_priv *wil, struct wil6210_vif *vif, + struct vring *vring, struct sk_buff *skb) { struct device *dev = wil_to_dev(wil); @@ -1710,8 +1727,8 @@ err_exit: return rc; } -static int __wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, - struct sk_buff *skb) +static int __wil_tx_vring(struct wil6210_priv *wil, struct wil6210_vif *vif, + struct vring *vring, struct sk_buff *skb) { struct device *dev = wil_to_dev(wil); struct vring_tx_desc dd, *d = ⅆ @@ -1725,7 +1742,7 @@ static int __wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, uint i = swhead; dma_addr_t pa; int used; - bool mcast = (vring_index == wil->bcast_vring); + bool mcast = (vring_index == vif->bcast_vring); uint len = skb_headlen(skb); wil_dbg_txrx(wil, "tx_vring: %d bytes to vring %d\n", skb->len, @@ -1860,8 +1877,8 @@ static int __wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, return -EINVAL; } -static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, - struct sk_buff *skb) +static int wil_tx_vring(struct wil6210_priv *wil, struct wil6210_vif *vif, + struct vring *vring, struct sk_buff *skb) { int vring_index = vring - wil->vring_tx; struct vring_tx_data *txdata = &wil->vring_tx_data[vring_index]; @@ -1879,7 +1896,7 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, } rc = (skb_is_gso(skb) ? __wil_tx_vring_tso : __wil_tx_vring) - (wil, vring, skb); + (wil, vif, vring, skb); spin_unlock(&txdata->lock); @@ -1923,7 +1940,7 @@ static inline void __wil_update_net_queues(struct wil6210_priv *wil, if (check_stop) { if (!vring || unlikely(wil_vring_avail_low(vring))) { /* not enough room in the vring */ - netif_tx_stop_all_queues(wil_to_ndev(wil)); + netif_tx_stop_all_queues(wil->main_ndev); wil->net_queue_stopped = true; wil_dbg_txrx(wil, "netif_tx_stop called\n"); } @@ -1953,7 +1970,7 @@ static inline void __wil_update_net_queues(struct wil6210_priv *wil, if (!vring || wil_vring_avail_high(vring)) { /* enough room in the vring */ wil_dbg_txrx(wil, "calling netif_tx_wake\n"); - netif_tx_wake_all_queues(wil_to_ndev(wil)); + netif_tx_wake_all_queues(wil->main_ndev); wil->net_queue_stopped = false; } } @@ -1976,7 +1993,8 @@ void wil_update_net_queues_bh(struct wil6210_priv *wil, struct vring *vring, netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev) { - struct wil6210_priv *wil = ndev_to_wil(ndev); + struct wil6210_vif *vif = ndev_to_vif(ndev); + struct wil6210_priv *wil = vif_to_wil(vif); struct ethhdr *eth = (void *)skb->data; bool bcast = is_multicast_ether_addr(eth->h_dest); struct vring *vring; @@ -1995,40 +2013,40 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev) wil_dbg_ratelimited(wil, "FW not connected, packet dropped\n"); goto drop; } - if (unlikely(wil->wdev->iftype == NL80211_IFTYPE_MONITOR)) { + if (unlikely(vif->wdev.iftype == NL80211_IFTYPE_MONITOR)) { wil_err(wil, "Xmit in monitor mode not supported\n"); goto drop; } pr_once_fw = false; /* find vring */ - if (wil->wdev->iftype == NL80211_IFTYPE_STATION && !wil->pbss) { + if (vif->wdev.iftype == NL80211_IFTYPE_STATION && !vif->pbss) { /* in STA mode (ESS), all to same VRING (to AP) */ - vring = wil_find_tx_vring_sta(wil, skb); + vring = wil_find_tx_vring_sta(wil, vif, skb); } else if (bcast) { - if (wil->pbss) + if (vif->pbss) /* in pbss, no bcast VRING - duplicate skb in * all stations VRINGs */ - vring = wil_find_tx_bcast_2(wil, skb); - else if (wil->wdev->iftype == NL80211_IFTYPE_AP) + vring = wil_find_tx_bcast_2(wil, vif, skb); + else if (vif->wdev.iftype == NL80211_IFTYPE_AP) /* AP has a dedicated bcast VRING */ - vring = wil_find_tx_bcast_1(wil, skb); + vring = wil_find_tx_bcast_1(wil, vif, skb); else /* unexpected combination, fallback to duplicating * the skb in all stations VRINGs */ - vring = wil_find_tx_bcast_2(wil, skb); + vring = wil_find_tx_bcast_2(wil, vif, skb); } else { /* unicast, find specific VRING by dest. address */ - vring = wil_find_tx_ucast(wil, skb); + vring = wil_find_tx_ucast(wil, vif, skb); } if (unlikely(!vring)) { wil_dbg_txrx(wil, "No Tx VRING found for %pM\n", eth->h_dest); goto drop; } /* set up vring entry */ - rc = wil_tx_vring(wil, vring, skb); + rc = wil_tx_vring(wil, vif, vring, skb); switch (rc) { case 0: @@ -2074,7 +2092,7 @@ static inline void wil_consume_skb(struct sk_buff *skb, bool acked) */ int wil_tx_complete(struct wil6210_priv *wil, int ringid) { - struct net_device *ndev = wil_to_ndev(wil); + struct net_device *ndev = wil->main_ndev; struct device *dev = wil_to_dev(wil); struct vring *vring = &wil->vring_tx[ringid]; struct vring_tx_data *txdata = &wil->vring_tx_data[ringid]; diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index 81cb27af64e4..fa8df41b045f 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -464,6 +464,7 @@ struct vring_tx_data { u16 agg_timeout; u8 agg_amsdu; bool addba_in_progress; /* if set, agg_xxx is for request in progress */ + u8 mid; spinlock_t lock; }; @@ -542,7 +543,6 @@ struct wil_tid_crypto_rx { struct wil_p2p_info { struct ieee80211_channel listen_chan; u8 discovery_started; - u8 p2p_dev_started; u64 cookie; struct wireless_dev *pending_listen_wdev; unsigned int listen_duration; @@ -585,6 +585,7 @@ struct wil_net_stats { */ struct wil_sta_info { u8 addr[ETH_ALEN]; + u8 mid; enum wil_sta_status status; struct wil_net_stats stats; /* Rx BACK */ @@ -672,16 +673,34 @@ extern u8 led_polarity; struct wil6210_vif { struct wireless_dev wdev; + struct net_device *ndev; struct wil6210_priv *wil; u8 mid; + u32 privacy; /* secure connection? */ + u16 channel; /* relevant in AP mode */ + u8 hidden_ssid; /* relevant in AP mode */ + u32 ap_isolate; /* no intra-BSS communication */ + bool pbss; + int bcast_vring; + struct cfg80211_bss *bss; /* connected bss, relevant in STA mode */ + int locally_generated_disc; /* relevant in STA mode */ + struct timer_list connect_timer; + struct work_struct disconnect_worker; + /* scan */ + struct cfg80211_scan_request *scan_request; + struct timer_list scan_timer; /* detect scan timeout */ + struct wil_p2p_info p2p; + /* keep alive */ + struct list_head probe_client_pending; + struct mutex probe_client_mutex; /* protect @probe_client_pending */ + struct work_struct probe_client_worker; }; struct wil6210_priv { struct pci_dev *pdev; u32 bar_size; struct wiphy *wiphy; - struct wireless_dev *wdev; - struct net_device *ndev; + struct net_device *main_ndev; void __iomem *csr; DECLARE_BITMAP(status, wil_status_last); u8 fw_version[ETHTOOL_FWVERS_LEN]; @@ -703,13 +722,7 @@ struct wil6210_priv { /* profile */ struct cfg80211_chan_def monitor_chandef; u32 monitor_flags; - u32 privacy; /* secure connection? */ - u8 hidden_ssid; /* relevant in AP mode */ - u16 channel; /* relevant in AP mode */ int sinfo_gen; - u32 ap_isolate; /* no intra-BSS communication */ - struct cfg80211_bss *bss; /* connected bss, relevant in STA mode */ - int locally_generated_disc; /* relevant in STA mode */ /* interrupt moderation */ u32 tx_max_burst_duration; u32 tx_interframe_timeout; @@ -724,15 +737,13 @@ struct wil6210_priv { struct completion wmi_call; u16 wmi_seq; u16 reply_id; /**< wait for this WMI event */ + u8 reply_mid; void *reply_buf; u16 reply_size; struct workqueue_struct *wmi_wq; /* for deferred calls */ struct work_struct wmi_event_worker; struct workqueue_struct *wq_service; - struct work_struct disconnect_worker; struct work_struct fw_error_worker; /* for FW error recovery */ - struct timer_list connect_timer; - struct timer_list scan_timer; /* detect scan timeout */ struct list_head pending_wmi_ev; /* * protect pending_wmi_ev @@ -744,10 +755,6 @@ struct wil6210_priv { int net_queue_stopped; /* netif_tx_stop_all_queues invoked */ struct napi_struct napi_rx; struct napi_struct napi_tx; - /* keep alive */ - struct list_head probe_client_pending; - struct mutex probe_client_mutex; /* protect @probe_client_pending */ - struct work_struct probe_client_worker; /* DMA related */ struct vring vring_rx; unsigned int rx_buf_len; @@ -755,11 +762,8 @@ struct wil6210_priv { struct vring_tx_data vring_tx_data[WIL6210_MAX_TX_RINGS]; u8 vring2cid_tid[WIL6210_MAX_TX_RINGS][2]; /* [0] - CID, [1] - TID */ struct wil_sta_info sta[WIL6210_MAX_CID]; - int bcast_vring; u32 vring_idle_trsh; /* HW fetches up to 16 descriptors at once */ u32 dma_addr_size; /* indicates dma addr size */ - /* scan */ - struct cfg80211_scan_request *scan_request; struct mutex mutex; /* for wil6210_priv access in wil_{up|down} */ /* statistics */ @@ -779,9 +783,7 @@ struct wil6210_priv { struct pmc_ctx pmc; - bool pbss; - - struct wil_p2p_info p2p; + u8 p2p_dev_started; /* P2P_DEVICE vif */ struct wireless_dev *p2p_wdev; @@ -810,12 +812,32 @@ struct wil6210_priv { #define wil_to_wiphy(i) (i->wiphy) #define wil_to_dev(i) (wiphy_dev(wil_to_wiphy(i))) #define wiphy_to_wil(w) (struct wil6210_priv *)(wiphy_priv(w)) -#define wil_to_wdev(i) (i->wdev) #define wdev_to_wil(w) (struct wil6210_priv *)(wdev_priv(w)) -#define wil_to_ndev(i) (i->ndev) #define ndev_to_wil(n) (wdev_to_wil(n->ieee80211_ptr)) #define ndev_to_vif(n) (struct wil6210_vif *)(netdev_priv(n)) -#define wdev_to_vif(w) (container_of(w, struct wil6210_vif, wdev)) +#define vif_to_wil(v) (v->wil) +#define vif_to_ndev(v) (v->ndev) +#define vif_to_wdev(v) (&v->wdev) + +static inline struct wil6210_vif *wdev_to_vif(struct wil6210_priv *wil, + struct wireless_dev *wdev) +{ + /* main interface is shared with P2P device */ + if (wdev == wil->p2p_wdev) + return ndev_to_vif(wil->main_ndev); + else + return container_of(wdev, struct wil6210_vif, wdev); +} + +static inline struct wireless_dev * +vif_to_radio_wdev(struct wil6210_priv *wil, struct wil6210_vif *vif) +{ + /* main interface is shared with P2P device */ + if (vif->mid) + return vif_to_wdev(vif); + else + return wil->radio_wdev; +} __printf(2, 3) void wil_dbg_trace(struct wil6210_priv *wil, const char *fmt, ...); @@ -828,7 +850,7 @@ void __wil_info(struct wil6210_priv *wil, const char *fmt, ...); __printf(2, 3) void wil_dbg_ratelimited(const struct wil6210_priv *wil, const char *fmt, ...); #define wil_dbg(wil, fmt, arg...) do { \ - netdev_dbg(wil_to_ndev(wil), fmt, ##arg); \ + netdev_dbg(wil->main_ndev, fmt, ##arg); \ wil_dbg_trace(wil, fmt, ##arg); \ } while (0) @@ -933,7 +955,7 @@ int wil_down(struct wil6210_priv *wil); int __wil_down(struct wil6210_priv *wil); void wil_refresh_fw_capabilities(struct wil6210_priv *wil); void wil_mbox_ring_le2cpus(struct wil6210_mbox_ring *r); -int wil_find_cid(struct wil6210_priv *wil, const u8 *mac); +int wil_find_cid(struct wil6210_priv *wil, u8 mid, const u8 *mac); void wil_set_ethtoolops(struct net_device *ndev); struct fw_map *wil_find_fw_mapping(const char *section); @@ -942,40 +964,42 @@ void __iomem *wmi_buffer(struct wil6210_priv *wil, __le32 ptr); void __iomem *wmi_addr(struct wil6210_priv *wil, u32 ptr); int wmi_read_hdr(struct wil6210_priv *wil, __le32 ptr, struct wil6210_mbox_hdr *hdr); -int wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len); +int wmi_send(struct wil6210_priv *wil, u16 cmdid, u8 mid, void *buf, u16 len); void wmi_recv_cmd(struct wil6210_priv *wil); -int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len, +int wmi_call(struct wil6210_priv *wil, u16 cmdid, u8 mid, void *buf, u16 len, u16 reply_id, void *reply, u8 reply_size, int to_msec); void wmi_event_worker(struct work_struct *work); void wmi_event_flush(struct wil6210_priv *wil); -int wmi_set_ssid(struct wil6210_priv *wil, u8 ssid_len, const void *ssid); -int wmi_get_ssid(struct wil6210_priv *wil, u8 *ssid_len, void *ssid); +int wmi_set_ssid(struct wil6210_vif *vif, u8 ssid_len, const void *ssid); +int wmi_get_ssid(struct wil6210_vif *vif, u8 *ssid_len, void *ssid); int wmi_set_channel(struct wil6210_priv *wil, int channel); int wmi_get_channel(struct wil6210_priv *wil, int *channel); -int wmi_del_cipher_key(struct wil6210_priv *wil, u8 key_index, +int wmi_del_cipher_key(struct wil6210_vif *vif, u8 key_index, const void *mac_addr, int key_usage); -int wmi_add_cipher_key(struct wil6210_priv *wil, u8 key_index, +int wmi_add_cipher_key(struct wil6210_vif *vif, u8 key_index, const void *mac_addr, int key_len, const void *key, int key_usage); int wmi_echo(struct wil6210_priv *wil); -int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie); +int wmi_set_ie(struct wil6210_vif *vif, u8 type, u16 ie_len, const void *ie); int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring); int wmi_rxon(struct wil6210_priv *wil, bool on); int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_m, u32 *t_r); -int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac, +int wmi_disconnect_sta(struct wil6210_vif *vif, const u8 *mac, u16 reason, bool full_disconnect, bool del_sta); -int wmi_addba(struct wil6210_priv *wil, u8 ringid, u8 size, u16 timeout); -int wmi_delba_tx(struct wil6210_priv *wil, u8 ringid, u16 reason); -int wmi_delba_rx(struct wil6210_priv *wil, u8 cidxtid, u16 reason); -int wmi_addba_rx_resp(struct wil6210_priv *wil, u8 cid, u8 tid, u8 token, +int wmi_addba(struct wil6210_priv *wil, u8 mid, + u8 ringid, u8 size, u16 timeout); +int wmi_delba_tx(struct wil6210_priv *wil, u8 mid, u8 ringid, u16 reason); +int wmi_delba_rx(struct wil6210_priv *wil, u8 mid, u8 cidxtid, u16 reason); +int wmi_addba_rx_resp(struct wil6210_priv *wil, + u8 mid, u8 cid, u8 tid, u8 token, u16 status, bool amsdu, u16 agg_wsize, u16 timeout); int wmi_ps_dev_profile_cfg(struct wil6210_priv *wil, enum wmi_ps_profile_type ps_profile); int wmi_set_mgmt_retry(struct wil6210_priv *wil, u8 retry_short); int wmi_get_mgmt_retry(struct wil6210_priv *wil, u8 *retry_short); -int wmi_new_sta(struct wil6210_priv *wil, const u8 *mac, u8 aid); -int wil_addba_rx_request(struct wil6210_priv *wil, u8 cidxtid, - u8 dialog_token, __le16 ba_param_set, +int wmi_new_sta(struct wil6210_vif *vif, const u8 *mac, u8 aid); +int wil_addba_rx_request(struct wil6210_priv *wil, u8 mid, + u8 cidxtid, u8 dialog_token, __le16 ba_param_set, __le16 ba_timeout, __le16 ba_seq_ctrl); int wil_addba_tx_request(struct wil6210_priv *wil, u8 ringid, u16 wsize); @@ -991,24 +1015,23 @@ void wil6210_mask_halp(struct wil6210_priv *wil); /* P2P */ bool wil_p2p_is_social_scan(struct cfg80211_scan_request *request); -void wil_p2p_discovery_timer_fn(struct timer_list *t); -int wil_p2p_search(struct wil6210_priv *wil, +int wil_p2p_search(struct wil6210_vif *vif, struct cfg80211_scan_request *request); int wil_p2p_listen(struct wil6210_priv *wil, struct wireless_dev *wdev, unsigned int duration, struct ieee80211_channel *chan, u64 *cookie); -u8 wil_p2p_stop_discovery(struct wil6210_priv *wil); -int wil_p2p_cancel_listen(struct wil6210_priv *wil, u64 cookie); +u8 wil_p2p_stop_discovery(struct wil6210_vif *vif); +int wil_p2p_cancel_listen(struct wil6210_vif *vif, u64 cookie); void wil_p2p_listen_expired(struct work_struct *work); void wil_p2p_search_expired(struct work_struct *work); void wil_p2p_stop_radio_operations(struct wil6210_priv *wil); void wil_p2p_delayed_listen_work(struct work_struct *work); /* WMI for P2P */ -int wmi_p2p_cfg(struct wil6210_priv *wil, int channel, int bi); -int wmi_start_listen(struct wil6210_priv *wil); -int wmi_start_search(struct wil6210_priv *wil); -int wmi_stop_discovery(struct wil6210_priv *wil); +int wmi_p2p_cfg(struct wil6210_vif *vif, int channel, int bi); +int wmi_start_listen(struct wil6210_vif *vif); +int wmi_start_search(struct wil6210_vif *vif); +int wmi_stop_discovery(struct wil6210_vif *vif); int wil_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, struct cfg80211_mgmt_tx_params *params, @@ -1025,7 +1048,7 @@ static inline int wil6210_debugfs_init(struct wil6210_priv *wil) { return 0; } static inline void wil6210_debugfs_remove(struct wil6210_priv *wil) {} #endif -int wil_cid_fill_sinfo(struct wil6210_priv *wil, int cid, +int wil_cid_fill_sinfo(struct wil6210_vif *vif, int cid, struct station_info *sinfo); struct wil6210_priv *wil_cfg80211_init(struct device *dev); @@ -1033,29 +1056,30 @@ void wil_cfg80211_deinit(struct wil6210_priv *wil); void wil_p2p_wdev_free(struct wil6210_priv *wil); int wmi_set_mac_address(struct wil6210_priv *wil, void *addr); -int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, - u8 chan, u8 hidden_ssid, u8 is_go); -int wmi_pcp_stop(struct wil6210_priv *wil); +int wmi_pcp_start(struct wil6210_vif *vif, int bi, u8 wmi_nettype, u8 chan, + u8 hidden_ssid, u8 is_go); +int wmi_pcp_stop(struct wil6210_vif *vif); int wmi_led_cfg(struct wil6210_priv *wil, bool enable); -int wmi_abort_scan(struct wil6210_priv *wil); -void wil_abort_scan(struct wil6210_priv *wil, bool sync); +int wmi_abort_scan(struct wil6210_vif *vif); +void wil_abort_scan(struct wil6210_vif *vif, bool sync); void wil6210_bus_request(struct wil6210_priv *wil, u32 kbps); -void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid, +void wil6210_disconnect(struct wil6210_vif *vif, const u8 *bssid, u16 reason_code, bool from_event); -void wil_probe_client_flush(struct wil6210_priv *wil); +void wil_probe_client_flush(struct wil6210_vif *vif); void wil_probe_client_worker(struct work_struct *work); +void wil_disconnect_worker(struct work_struct *work); int wil_rx_init(struct wil6210_priv *wil, u16 size); void wil_rx_fini(struct wil6210_priv *wil); /* TX API */ -int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, +int wil_vring_init_tx(struct wil6210_vif *vif, int id, int size, int cid, int tid); void wil_vring_fini_tx(struct wil6210_priv *wil, int id); -int wil_tx_init(struct wil6210_priv *wil, int cid); -int wil_vring_init_bcast(struct wil6210_priv *wil, int id, int size); -int wil_bcast_init(struct wil6210_priv *wil); -void wil_bcast_fini(struct wil6210_priv *wil); +int wil_tx_init(struct wil6210_vif *vif, int cid); +int wil_vring_init_bcast(struct wil6210_vif *vif, int id, int size); +int wil_bcast_init(struct wil6210_vif *vif); +void wil_bcast_fini(struct wil6210_vif *vif); void wil_update_net_queues(struct wil6210_priv *wil, struct vring *vring, bool should_stop); diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index b31e2514f8c2..044d69850353 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c @@ -516,7 +516,8 @@ static const char *eventid2name(u16 eventid) } } -static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len) +static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, u8 mid, + void *buf, u16 len) { struct { struct wil6210_mbox_hdr hdr; @@ -528,7 +529,7 @@ static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len) .len = cpu_to_le16(sizeof(cmd.wmi) + len), }, .wmi = { - .mid = 0, + .mid = mid, .command_id = cpu_to_le16(cmdid), }, }; @@ -612,8 +613,8 @@ static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len) } cmd.hdr.seq = cpu_to_le16(++wil->wmi_seq); /* set command */ - wil_dbg_wmi(wil, "sending %s (0x%04x) [%d]\n", - cmdid2name(cmdid), cmdid, len); + wil_dbg_wmi(wil, "sending %s (0x%04x) [%d] mid %d\n", + cmdid2name(cmdid), cmdid, len, mid); wil_hex_dump_wmi("Cmd ", DUMP_PREFIX_OFFSET, 16, 1, &cmd, sizeof(cmd), true); wil_hex_dump_wmi("cmd ", DUMP_PREFIX_OFFSET, 16, 1, buf, @@ -637,21 +638,22 @@ out: return rc; } -int wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len) +int wmi_send(struct wil6210_priv *wil, u16 cmdid, u8 mid, void *buf, u16 len) { int rc; mutex_lock(&wil->wmi_mutex); - rc = __wmi_send(wil, cmdid, buf, len); + rc = __wmi_send(wil, cmdid, mid, buf, len); mutex_unlock(&wil->wmi_mutex); return rc; } /*=== Event handlers ===*/ -static void wmi_evt_ready(struct wil6210_priv *wil, int id, void *d, int len) +static void wmi_evt_ready(struct wil6210_vif *vif, int id, void *d, int len) { - struct wireless_dev *wdev = wil->wdev; + struct wil6210_priv *wil = vif_to_wil(vif); + struct wiphy *wiphy = wil_to_wiphy(wil); struct wmi_ready_event *evt = d; wil->n_mids = evt->numof_additional_mids; @@ -660,8 +662,7 @@ static void wmi_evt_ready(struct wil6210_priv *wil, int id, void *d, int len) wil->fw_version, le32_to_cpu(evt->sw_version), evt->mac, wil->n_mids); /* ignore MAC address, we already have it from the boot loader */ - strlcpy(wdev->wiphy->fw_version, wil->fw_version, - sizeof(wdev->wiphy->fw_version)); + strlcpy(wiphy->fw_version, wil->fw_version, sizeof(wiphy->fw_version)); if (len > offsetof(struct wmi_ready_event, rfc_read_calib_result)) { wil_dbg_wmi(wil, "rfc calibration result %d\n", @@ -674,8 +675,9 @@ static void wmi_evt_ready(struct wil6210_priv *wil, int id, void *d, int len) complete(&wil->wmi_ready); } -static void wmi_evt_rx_mgmt(struct wil6210_priv *wil, int id, void *d, int len) +static void wmi_evt_rx_mgmt(struct wil6210_vif *vif, int id, void *d, int len) { + struct wil6210_priv *wil = vif_to_wil(vif); struct wmi_rx_mgmt_packet_event *data = d; struct wiphy *wiphy = wil_to_wiphy(wil); struct ieee80211_mgmt *rx_mgmt_frame = @@ -754,13 +756,13 @@ static void wmi_evt_rx_mgmt(struct wil6210_priv *wil, int id, void *d, int len) } } else { mutex_lock(&wil->p2p_wdev_mutex); - cfg80211_rx_mgmt(wil->radio_wdev, freq, signal, + cfg80211_rx_mgmt(vif_to_radio_wdev(wil, vif), freq, signal, (void *)rx_mgmt_frame, d_len, 0); mutex_unlock(&wil->p2p_wdev_mutex); } } -static void wmi_evt_tx_mgmt(struct wil6210_priv *wil, int id, void *d, int len) +static void wmi_evt_tx_mgmt(struct wil6210_vif *vif, int id, void *d, int len) { struct wmi_tx_mgmt_packet_event *data = d; struct ieee80211_mgmt *mgmt_frame = @@ -771,11 +773,13 @@ static void wmi_evt_tx_mgmt(struct wil6210_priv *wil, int id, void *d, int len) flen, true); } -static void wmi_evt_scan_complete(struct wil6210_priv *wil, int id, +static void wmi_evt_scan_complete(struct wil6210_vif *vif, int id, void *d, int len) { + struct wil6210_priv *wil = vif_to_wil(vif); + mutex_lock(&wil->p2p_wdev_mutex); - if (wil->scan_request) { + if (vif->scan_request) { struct wmi_scan_complete_event *data = d; int status = le32_to_cpu(data->status); struct cfg80211_scan_info info = { @@ -785,15 +789,16 @@ static void wmi_evt_scan_complete(struct wil6210_priv *wil, int id, wil_dbg_wmi(wil, "SCAN_COMPLETE(0x%08x)\n", status); wil_dbg_misc(wil, "Complete scan_request 0x%p aborted %d\n", - wil->scan_request, info.aborted); - del_timer_sync(&wil->scan_timer); - cfg80211_scan_done(wil->scan_request, &info); - wil->radio_wdev = wil->wdev; - wil->scan_request = NULL; + vif->scan_request, info.aborted); + del_timer_sync(&vif->scan_timer); + cfg80211_scan_done(vif->scan_request, &info); + if (vif->mid == 0) + wil->radio_wdev = wil->main_ndev->ieee80211_ptr; + vif->scan_request = NULL; wake_up_interruptible(&wil->wq); - if (wil->p2p.pending_listen_wdev) { + if (vif->p2p.pending_listen_wdev) { wil_dbg_misc(wil, "Scheduling delayed listen\n"); - schedule_work(&wil->p2p.delayed_listen_work); + schedule_work(&vif->p2p.delayed_listen_work); } } else { wil_err(wil, "SCAN_COMPLETE while not scanning\n"); @@ -801,10 +806,11 @@ static void wmi_evt_scan_complete(struct wil6210_priv *wil, int id, mutex_unlock(&wil->p2p_wdev_mutex); } -static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len) +static void wmi_evt_connect(struct wil6210_vif *vif, int id, void *d, int len) { - struct net_device *ndev = wil_to_ndev(wil); - struct wireless_dev *wdev = wil->wdev; + struct wil6210_priv *wil = vif_to_wil(vif); + struct net_device *ndev = vif_to_ndev(vif); + struct wireless_dev *wdev = vif_to_wdev(vif); struct wmi_connect_event *evt = d; int ch; /* channel number */ struct station_info sinfo; @@ -874,7 +880,7 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len) mutex_unlock(&wil->mutex); return; } - del_timer_sync(&wil->connect_timer); + del_timer_sync(&vif->connect_timer); } else if ((wdev->iftype == NL80211_IFTYPE_AP) || (wdev->iftype == NL80211_IFTYPE_P2P_GO)) { if (wil->sta[evt->cid].status != wil_sta_unused) { @@ -886,13 +892,14 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len) } ether_addr_copy(wil->sta[evt->cid].addr, evt->bssid); + wil->sta[evt->cid].mid = vif->mid; wil->sta[evt->cid].status = wil_sta_conn_pending; - rc = wil_tx_init(wil, evt->cid); + rc = wil_tx_init(vif, evt->cid); if (rc) { wil_err(wil, "config tx vring failed for CID %d, rc (%d)\n", evt->cid, rc); - wmi_disconnect_sta(wil, wil->sta[evt->cid].addr, + wmi_disconnect_sta(vif, wil->sta[evt->cid].addr, WLAN_REASON_UNSPECIFIED, false, false); } else { wil_info(wil, "successful connection to CID %d\n", evt->cid); @@ -912,14 +919,14 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len) } else { struct wiphy *wiphy = wil_to_wiphy(wil); - cfg80211_ref_bss(wiphy, wil->bss); - cfg80211_connect_bss(ndev, evt->bssid, wil->bss, + cfg80211_ref_bss(wiphy, vif->bss); + cfg80211_connect_bss(ndev, evt->bssid, vif->bss, assoc_req_ie, assoc_req_ielen, assoc_resp_ie, assoc_resp_ielen, WLAN_STATUS_SUCCESS, GFP_KERNEL, NL80211_TIMEOUT_UNSPECIFIED); } - wil->bss = NULL; + vif->bss = NULL; } else if ((wdev->iftype == NL80211_IFTYPE_AP) || (wdev->iftype == NL80211_IFTYPE_P2P_GO)) { if (rc) { @@ -951,15 +958,18 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len) wil_update_net_queues_bh(wil, NULL, false); out: - if (rc) + if (rc) { wil->sta[evt->cid].status = wil_sta_unused; + wil->sta[evt->cid].mid = U8_MAX; + } clear_bit(wil_status_fwconnecting, wil->status); mutex_unlock(&wil->mutex); } -static void wmi_evt_disconnect(struct wil6210_priv *wil, int id, +static void wmi_evt_disconnect(struct wil6210_vif *vif, int id, void *d, int len) { + struct wil6210_priv *wil = vif_to_wil(vif); struct wmi_disconnect_event *evt = d; u16 reason_code = le16_to_cpu(evt->protocol_reason_status); @@ -976,7 +986,7 @@ static void wmi_evt_disconnect(struct wil6210_priv *wil, int id, } mutex_lock(&wil->mutex); - wil6210_disconnect(wil, evt->bssid, reason_code, true); + wil6210_disconnect(vif, evt->bssid, reason_code, true); mutex_unlock(&wil->mutex); } @@ -984,10 +994,10 @@ static void wmi_evt_disconnect(struct wil6210_priv *wil, int id, * Firmware reports EAPOL frame using WME event. * Reconstruct Ethernet frame and deliver it via normal Rx */ -static void wmi_evt_eapol_rx(struct wil6210_priv *wil, int id, - void *d, int len) +static void wmi_evt_eapol_rx(struct wil6210_vif *vif, int id, void *d, int len) { - struct net_device *ndev = wil_to_ndev(wil); + struct wil6210_priv *wil = vif_to_wil(vif); + struct net_device *ndev = vif_to_ndev(vif); struct wmi_eapol_rx_event *evt = d; u16 eapol_len = le16_to_cpu(evt->eapol_len); int sz = eapol_len + ETH_HLEN; @@ -996,10 +1006,10 @@ static void wmi_evt_eapol_rx(struct wil6210_priv *wil, int id, int cid; struct wil_net_stats *stats = NULL; - wil_dbg_wmi(wil, "EAPOL len %d from %pM\n", eapol_len, - evt->src_mac); + wil_dbg_wmi(wil, "EAPOL len %d from %pM MID %d\n", eapol_len, + evt->src_mac, vif->mid); - cid = wil_find_cid(wil, evt->src_mac); + cid = wil_find_cid(wil, vif->mid, evt->src_mac); if (cid >= 0) stats = &wil->sta[cid].stats; @@ -1034,13 +1044,14 @@ static void wmi_evt_eapol_rx(struct wil6210_priv *wil, int id, } } -static void wmi_evt_vring_en(struct wil6210_priv *wil, int id, void *d, int len) +static void wmi_evt_vring_en(struct wil6210_vif *vif, int id, void *d, int len) { + struct wil6210_priv *wil = vif_to_wil(vif); struct wmi_vring_en_event *evt = d; u8 vri = evt->vring_index; - struct wireless_dev *wdev = wil_to_wdev(wil); + struct wireless_dev *wdev = vif_to_wdev(vif); - wil_dbg_wmi(wil, "Enable vring %d\n", vri); + wil_dbg_wmi(wil, "Enable vring %d MID %d\n", vri, vif->mid); if (vri >= ARRAY_SIZE(wil->vring_tx)) { wil_err(wil, "Enable for invalid vring %d\n", vri); @@ -1052,15 +1063,16 @@ static void wmi_evt_vring_en(struct wil6210_priv *wil, int id, void *d, int len) * wil_cfg80211_change_station() */ wil->vring_tx_data[vri].dot1x_open = true; - if (vri == wil->bcast_vring) /* no BA for bcast */ + if (vri == vif->bcast_vring) /* no BA for bcast */ return; if (agg_wsize >= 0) wil_addba_tx_request(wil, vri, agg_wsize); } -static void wmi_evt_ba_status(struct wil6210_priv *wil, int id, void *d, - int len) +static void wmi_evt_ba_status(struct wil6210_vif *vif, int id, + void *d, int len) { + struct wil6210_priv *wil = vif_to_wil(vif); struct wmi_ba_status_event *evt = d; struct vring_tx_data *txdata; @@ -1089,19 +1101,21 @@ static void wmi_evt_ba_status(struct wil6210_priv *wil, int id, void *d, txdata->addba_in_progress = false; } -static void wmi_evt_addba_rx_req(struct wil6210_priv *wil, int id, void *d, - int len) +static void wmi_evt_addba_rx_req(struct wil6210_vif *vif, int id, + void *d, int len) { + struct wil6210_priv *wil = vif_to_wil(vif); struct wmi_rcp_addba_req_event *evt = d; - wil_addba_rx_request(wil, evt->cidxtid, evt->dialog_token, + wil_addba_rx_request(wil, vif->mid, evt->cidxtid, evt->dialog_token, evt->ba_param_set, evt->ba_timeout, evt->ba_seq_ctrl); } -static void wmi_evt_delba(struct wil6210_priv *wil, int id, void *d, int len) +static void wmi_evt_delba(struct wil6210_vif *vif, int id, void *d, int len) __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) { + struct wil6210_priv *wil = vif_to_wil(vif); struct wmi_delba_event *evt = d; u8 cid, tid; u16 reason = __le16_to_cpu(evt->reason); @@ -1110,8 +1124,8 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) might_sleep(); parse_cidxtid(evt->cidxtid, &cid, &tid); - wil_dbg_wmi(wil, "DELBA CID %d TID %d from %s reason %d\n", - cid, tid, + wil_dbg_wmi(wil, "DELBA MID %d CID %d TID %d from %s reason %d\n", + vif->mid, cid, tid, evt->from_initiator ? "originator" : "recipient", reason); if (!evt->from_initiator) { @@ -1148,8 +1162,9 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) } static void -wmi_evt_sched_scan_result(struct wil6210_priv *wil, int id, void *d, int len) +wmi_evt_sched_scan_result(struct wil6210_vif *vif, int id, void *d, int len) { + struct wil6210_priv *wil = vif_to_wil(vif); struct wmi_sched_scan_result_event *data = d; struct wiphy *wiphy = wil_to_wiphy(wil); struct ieee80211_mgmt *rx_mgmt_frame = @@ -1220,15 +1235,17 @@ wmi_evt_sched_scan_result(struct wil6210_priv *wil, int id, void *d, int len) * Some events are ignored for purpose; and need not be interpreted as * "unhandled events" */ -static void wmi_evt_ignore(struct wil6210_priv *wil, int id, void *d, int len) +static void wmi_evt_ignore(struct wil6210_vif *vif, int id, void *d, int len) { + struct wil6210_priv *wil = vif_to_wil(vif); + wil_dbg_wmi(wil, "Ignore event 0x%04x len %d\n", id, len); } static const struct { int eventid; - void (*handler)(struct wil6210_priv *wil, int eventid, - void *data, int data_len); + void (*handler)(struct wil6210_vif *vif, + int eventid, void *data, int data_len); } wmi_evt_handlers[] = { {WMI_READY_EVENTID, wmi_evt_ready}, {WMI_FW_READY_EVENTID, wmi_evt_ignore}, @@ -1325,6 +1342,7 @@ void wmi_recv_cmd(struct wil6210_priv *wil) (len >= sizeof(struct wmi_cmd_hdr))) { struct wmi_cmd_hdr *wmi = &evt->event.wmi; u16 id = le16_to_cpu(wmi->command_id); + u8 mid = wmi->mid; u32 tstamp = le32_to_cpu(wmi->fw_timestamp); if (test_bit(wil_status_resuming, wil->status)) { if (id == WMI_TRAFFIC_RESUME_EVENTID) @@ -1336,7 +1354,8 @@ void wmi_recv_cmd(struct wil6210_priv *wil) id); } spin_lock_irqsave(&wil->wmi_ev_lock, flags); - if (wil->reply_id && wil->reply_id == id) { + if (wil->reply_id && wil->reply_id == id && + wil->reply_mid == mid) { if (wil->reply_buf) { memcpy(wil->reply_buf, wmi, min(len, wil->reply_size)); @@ -1384,7 +1403,7 @@ void wmi_recv_cmd(struct wil6210_priv *wil) n - num_immed_reply, num_immed_reply); } -int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len, +int wmi_call(struct wil6210_priv *wil, u16 cmdid, u8 mid, void *buf, u16 len, u16 reply_id, void *reply, u8 reply_size, int to_msec) { int rc; @@ -1394,12 +1413,13 @@ int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len, spin_lock(&wil->wmi_ev_lock); wil->reply_id = reply_id; + wil->reply_mid = mid; wil->reply_buf = reply; wil->reply_size = reply_size; reinit_completion(&wil->wmi_call); spin_unlock(&wil->wmi_ev_lock); - rc = __wmi_send(wil, cmdid, buf, len); + rc = __wmi_send(wil, cmdid, mid, buf, len); if (rc) goto out; @@ -1419,6 +1439,7 @@ int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len, out: spin_lock(&wil->wmi_ev_lock); wil->reply_id = 0; + wil->reply_mid = U8_MAX; wil->reply_buf = NULL; wil->reply_size = 0; spin_unlock(&wil->wmi_ev_lock); @@ -1430,27 +1451,31 @@ out: int wmi_echo(struct wil6210_priv *wil) { + struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev); struct wmi_echo_cmd cmd = { .value = cpu_to_le32(0x12345678), }; - return wmi_call(wil, WMI_ECHO_CMDID, &cmd, sizeof(cmd), + return wmi_call(wil, WMI_ECHO_CMDID, vif->mid, &cmd, sizeof(cmd), WMI_ECHO_RSP_EVENTID, NULL, 0, 50); } int wmi_set_mac_address(struct wil6210_priv *wil, void *addr) { + struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev); struct wmi_set_mac_address_cmd cmd; ether_addr_copy(cmd.mac, addr); wil_dbg_wmi(wil, "Set MAC %pM\n", addr); - return wmi_send(wil, WMI_SET_MAC_ADDRESS_CMDID, &cmd, sizeof(cmd)); + return wmi_send(wil, WMI_SET_MAC_ADDRESS_CMDID, vif->mid, + &cmd, sizeof(cmd)); } int wmi_led_cfg(struct wil6210_priv *wil, bool enable) { + struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev); int rc = 0; struct wmi_led_cfg_cmd cmd = { .led_mode = enable, @@ -1487,7 +1512,7 @@ int wmi_led_cfg(struct wil6210_priv *wil, bool enable) "%s led %d\n", enable ? "enabling" : "disabling", led_id); - rc = wmi_call(wil, WMI_LED_CFG_CMDID, &cmd, sizeof(cmd), + rc = wmi_call(wil, WMI_LED_CFG_CMDID, vif->mid, &cmd, sizeof(cmd), WMI_LED_CFG_DONE_EVENTID, &reply, sizeof(reply), 100); if (rc) @@ -1503,9 +1528,10 @@ out: return rc; } -int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, - u8 chan, u8 hidden_ssid, u8 is_go) +int wmi_pcp_start(struct wil6210_vif *vif, + int bi, u8 wmi_nettype, u8 chan, u8 hidden_ssid, u8 is_go) { + struct wil6210_priv *wil = vif_to_wil(vif); int rc; struct wmi_pcp_start_cmd cmd = { @@ -1524,7 +1550,7 @@ int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, struct wmi_pcp_started_event evt; } __packed reply; - if (!wil->privacy) + if (!vif->privacy) cmd.disable_sec = 1; if ((cmd.pcp_max_assoc_sta > WIL6210_MAX_CID) || @@ -1546,7 +1572,7 @@ int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, * Processing time may be huge, in case of secure AP it takes about * 3500ms for FW to start AP */ - rc = wmi_call(wil, WMI_PCP_START_CMDID, &cmd, sizeof(cmd), + rc = wmi_call(wil, WMI_PCP_START_CMDID, vif->mid, &cmd, sizeof(cmd), WMI_PCP_STARTED_EVENTID, &reply, sizeof(reply), 5000); if (rc) return rc; @@ -1561,20 +1587,22 @@ int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, return rc; } -int wmi_pcp_stop(struct wil6210_priv *wil) +int wmi_pcp_stop(struct wil6210_vif *vif) { + struct wil6210_priv *wil = vif_to_wil(vif); int rc; rc = wmi_led_cfg(wil, false); if (rc) return rc; - return wmi_call(wil, WMI_PCP_STOP_CMDID, NULL, 0, + return wmi_call(wil, WMI_PCP_STOP_CMDID, vif->mid, NULL, 0, WMI_PCP_STOPPED_EVENTID, NULL, 0, 20); } -int wmi_set_ssid(struct wil6210_priv *wil, u8 ssid_len, const void *ssid) +int wmi_set_ssid(struct wil6210_vif *vif, u8 ssid_len, const void *ssid) { + struct wil6210_priv *wil = vif_to_wil(vif); struct wmi_set_ssid_cmd cmd = { .ssid_len = cpu_to_le32(ssid_len), }; @@ -1584,11 +1612,12 @@ int wmi_set_ssid(struct wil6210_priv *wil, u8 ssid_len, const void *ssid) memcpy(cmd.ssid, ssid, ssid_len); - return wmi_send(wil, WMI_SET_SSID_CMDID, &cmd, sizeof(cmd)); + return wmi_send(wil, WMI_SET_SSID_CMDID, vif->mid, &cmd, sizeof(cmd)); } -int wmi_get_ssid(struct wil6210_priv *wil, u8 *ssid_len, void *ssid) +int wmi_get_ssid(struct wil6210_vif *vif, u8 *ssid_len, void *ssid) { + struct wil6210_priv *wil = vif_to_wil(vif); int rc; struct { struct wmi_cmd_hdr wmi; @@ -1596,8 +1625,8 @@ int wmi_get_ssid(struct wil6210_priv *wil, u8 *ssid_len, void *ssid) } __packed reply; int len; /* reply.cmd.ssid_len in CPU order */ - rc = wmi_call(wil, WMI_GET_SSID_CMDID, NULL, 0, WMI_GET_SSID_EVENTID, - &reply, sizeof(reply), 20); + rc = wmi_call(wil, WMI_GET_SSID_CMDID, vif->mid, NULL, 0, + WMI_GET_SSID_EVENTID, &reply, sizeof(reply), 20); if (rc) return rc; @@ -1613,22 +1642,25 @@ int wmi_get_ssid(struct wil6210_priv *wil, u8 *ssid_len, void *ssid) int wmi_set_channel(struct wil6210_priv *wil, int channel) { + struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev); struct wmi_set_pcp_channel_cmd cmd = { .channel = channel - 1, }; - return wmi_send(wil, WMI_SET_PCP_CHANNEL_CMDID, &cmd, sizeof(cmd)); + return wmi_send(wil, WMI_SET_PCP_CHANNEL_CMDID, vif->mid, + &cmd, sizeof(cmd)); } int wmi_get_channel(struct wil6210_priv *wil, int *channel) { + struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev); int rc; struct { struct wmi_cmd_hdr wmi; struct wmi_set_pcp_channel_cmd cmd; } __packed reply; - rc = wmi_call(wil, WMI_GET_PCP_CHANNEL_CMDID, NULL, 0, + rc = wmi_call(wil, WMI_GET_PCP_CHANNEL_CMDID, vif->mid, NULL, 0, WMI_GET_PCP_CHANNEL_EVENTID, &reply, sizeof(reply), 20); if (rc) return rc; @@ -1641,8 +1673,9 @@ int wmi_get_channel(struct wil6210_priv *wil, int *channel) return 0; } -int wmi_p2p_cfg(struct wil6210_priv *wil, int channel, int bi) +int wmi_p2p_cfg(struct wil6210_vif *vif, int channel, int bi) { + struct wil6210_priv *wil = vif_to_wil(vif); int rc; struct wmi_p2p_cfg_cmd cmd = { .discovery_mode = WMI_DISCOVERY_MODE_PEER2PEER, @@ -1656,7 +1689,7 @@ int wmi_p2p_cfg(struct wil6210_priv *wil, int channel, int bi) wil_dbg_wmi(wil, "sending WMI_P2P_CFG_CMDID\n"); - rc = wmi_call(wil, WMI_P2P_CFG_CMDID, &cmd, sizeof(cmd), + rc = wmi_call(wil, WMI_P2P_CFG_CMDID, vif->mid, &cmd, sizeof(cmd), WMI_P2P_CFG_DONE_EVENTID, &reply, sizeof(reply), 300); if (!rc && reply.evt.status != WMI_FW_STATUS_SUCCESS) { wil_err(wil, "P2P_CFG failed. status %d\n", reply.evt.status); @@ -1666,8 +1699,9 @@ int wmi_p2p_cfg(struct wil6210_priv *wil, int channel, int bi) return rc; } -int wmi_start_listen(struct wil6210_priv *wil) +int wmi_start_listen(struct wil6210_vif *vif) { + struct wil6210_priv *wil = vif_to_wil(vif); int rc; struct { struct wmi_cmd_hdr wmi; @@ -1676,7 +1710,7 @@ int wmi_start_listen(struct wil6210_priv *wil) wil_dbg_wmi(wil, "sending WMI_START_LISTEN_CMDID\n"); - rc = wmi_call(wil, WMI_START_LISTEN_CMDID, NULL, 0, + rc = wmi_call(wil, WMI_START_LISTEN_CMDID, vif->mid, NULL, 0, WMI_LISTEN_STARTED_EVENTID, &reply, sizeof(reply), 300); if (!rc && reply.evt.status != WMI_FW_STATUS_SUCCESS) { wil_err(wil, "device failed to start listen. status %d\n", @@ -1687,8 +1721,9 @@ int wmi_start_listen(struct wil6210_priv *wil) return rc; } -int wmi_start_search(struct wil6210_priv *wil) +int wmi_start_search(struct wil6210_vif *vif) { + struct wil6210_priv *wil = vif_to_wil(vif); int rc; struct { struct wmi_cmd_hdr wmi; @@ -1697,7 +1732,7 @@ int wmi_start_search(struct wil6210_priv *wil) wil_dbg_wmi(wil, "sending WMI_START_SEARCH_CMDID\n"); - rc = wmi_call(wil, WMI_START_SEARCH_CMDID, NULL, 0, + rc = wmi_call(wil, WMI_START_SEARCH_CMDID, vif->mid, NULL, 0, WMI_SEARCH_STARTED_EVENTID, &reply, sizeof(reply), 300); if (!rc && reply.evt.status != WMI_FW_STATUS_SUCCESS) { wil_err(wil, "device failed to start search. status %d\n", @@ -1708,13 +1743,14 @@ int wmi_start_search(struct wil6210_priv *wil) return rc; } -int wmi_stop_discovery(struct wil6210_priv *wil) +int wmi_stop_discovery(struct wil6210_vif *vif) { + struct wil6210_priv *wil = vif_to_wil(vif); int rc; wil_dbg_wmi(wil, "sending WMI_DISCOVERY_STOP_CMDID\n"); - rc = wmi_call(wil, WMI_DISCOVERY_STOP_CMDID, NULL, 0, + rc = wmi_call(wil, WMI_DISCOVERY_STOP_CMDID, vif->mid, NULL, 0, WMI_DISCOVERY_STOPPED_EVENTID, NULL, 0, 100); if (rc) @@ -1723,9 +1759,10 @@ int wmi_stop_discovery(struct wil6210_priv *wil) return rc; } -int wmi_del_cipher_key(struct wil6210_priv *wil, u8 key_index, +int wmi_del_cipher_key(struct wil6210_vif *vif, u8 key_index, const void *mac_addr, int key_usage) { + struct wil6210_priv *wil = vif_to_wil(vif); struct wmi_delete_cipher_key_cmd cmd = { .key_index = key_index, }; @@ -1733,13 +1770,15 @@ int wmi_del_cipher_key(struct wil6210_priv *wil, u8 key_index, if (mac_addr) memcpy(cmd.mac, mac_addr, WMI_MAC_LEN); - return wmi_send(wil, WMI_DELETE_CIPHER_KEY_CMDID, &cmd, sizeof(cmd)); + return wmi_send(wil, WMI_DELETE_CIPHER_KEY_CMDID, vif->mid, + &cmd, sizeof(cmd)); } -int wmi_add_cipher_key(struct wil6210_priv *wil, u8 key_index, +int wmi_add_cipher_key(struct wil6210_vif *vif, u8 key_index, const void *mac_addr, int key_len, const void *key, int key_usage) { + struct wil6210_priv *wil = vif_to_wil(vif); struct wmi_add_cipher_key_cmd cmd = { .key_index = key_index, .key_usage = key_usage, @@ -1753,11 +1792,13 @@ int wmi_add_cipher_key(struct wil6210_priv *wil, u8 key_index, if (mac_addr) memcpy(cmd.mac, mac_addr, WMI_MAC_LEN); - return wmi_send(wil, WMI_ADD_CIPHER_KEY_CMDID, &cmd, sizeof(cmd)); + return wmi_send(wil, WMI_ADD_CIPHER_KEY_CMDID, vif->mid, + &cmd, sizeof(cmd)); } -int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie) +int wmi_set_ie(struct wil6210_vif *vif, u8 type, u16 ie_len, const void *ie) { + struct wil6210_priv *wil = vif_to_wil(vif); static const char *const names[] = { [WMI_FRAME_BEACON] = "BEACON", [WMI_FRAME_PROBE_REQ] = "PROBE_REQ", @@ -1786,7 +1827,7 @@ int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie) /* BUG: FW API define ieLen as u8. Will fix FW */ cmd->ie_len = cpu_to_le16(ie_len); memcpy(cmd->ie_info, ie, ie_len); - rc = wmi_send(wil, WMI_SET_APPIE_CMDID, cmd, len); + rc = wmi_send(wil, WMI_SET_APPIE_CMDID, vif->mid, cmd, len); kfree(cmd); out: if (rc) { @@ -1808,6 +1849,7 @@ out: */ int wmi_rxon(struct wil6210_priv *wil, bool on) { + struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev); int rc; struct { struct wmi_cmd_hdr wmi; @@ -1817,13 +1859,13 @@ int wmi_rxon(struct wil6210_priv *wil, bool on) wil_info(wil, "(%s)\n", on ? "on" : "off"); if (on) { - rc = wmi_call(wil, WMI_START_LISTEN_CMDID, NULL, 0, + rc = wmi_call(wil, WMI_START_LISTEN_CMDID, vif->mid, NULL, 0, WMI_LISTEN_STARTED_EVENTID, &reply, sizeof(reply), 100); if ((rc == 0) && (reply.evt.status != WMI_FW_STATUS_SUCCESS)) rc = -EINVAL; } else { - rc = wmi_call(wil, WMI_DISCOVERY_STOP_CMDID, NULL, 0, + rc = wmi_call(wil, WMI_DISCOVERY_STOP_CMDID, vif->mid, NULL, 0, WMI_DISCOVERY_STOPPED_EVENTID, NULL, 0, 20); } @@ -1832,8 +1874,9 @@ int wmi_rxon(struct wil6210_priv *wil, bool on) int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring) { - struct wireless_dev *wdev = wil->wdev; - struct net_device *ndev = wil_to_ndev(wil); + struct net_device *ndev = wil->main_ndev; + struct wireless_dev *wdev = ndev->ieee80211_ptr; + struct wil6210_vif *vif = ndev_to_vif(ndev); struct wmi_cfg_rx_chain_cmd cmd = { .action = WMI_RX_CHAIN_ADD, .rx_sw_ring = { @@ -1877,7 +1920,7 @@ int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring) L2_802_3_OFFLOAD_CTRL_SNAP_KEEP_MSK; /* typical time for secure PCP is 840ms */ - rc = wmi_call(wil, WMI_CFG_RX_CHAIN_CMDID, &cmd, sizeof(cmd), + rc = wmi_call(wil, WMI_CFG_RX_CHAIN_CMDID, vif->mid, &cmd, sizeof(cmd), WMI_CFG_RX_CHAIN_DONE_EVENTID, &evt, sizeof(evt), 2000); if (rc) return rc; @@ -1895,6 +1938,7 @@ int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring) int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_bb, u32 *t_rf) { + struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev); int rc; struct wmi_temp_sense_cmd cmd = { .measure_baseband_en = cpu_to_le32(!!t_bb), @@ -1906,7 +1950,7 @@ int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_bb, u32 *t_rf) struct wmi_temp_sense_done_event evt; } __packed reply; - rc = wmi_call(wil, WMI_TEMP_SENSE_CMDID, &cmd, sizeof(cmd), + rc = wmi_call(wil, WMI_TEMP_SENSE_CMDID, vif->mid, &cmd, sizeof(cmd), WMI_TEMP_SENSE_DONE_EVENTID, &reply, sizeof(reply), 100); if (rc) return rc; @@ -1919,9 +1963,10 @@ int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_bb, u32 *t_rf) return 0; } -int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac, +int wmi_disconnect_sta(struct wil6210_vif *vif, const u8 *mac, u16 reason, bool full_disconnect, bool del_sta) { + struct wil6210_priv *wil = vif_to_wil(vif); int rc; u16 reason_code; struct wmi_disconnect_sta_cmd disc_sta_cmd = { @@ -1937,16 +1982,17 @@ int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac, wil_dbg_wmi(wil, "disconnect_sta: (%pM, reason %d)\n", mac, reason); - wil->locally_generated_disc = true; + vif->locally_generated_disc = true; if (del_sta) { ether_addr_copy(del_sta_cmd.dst_mac, mac); - rc = wmi_call(wil, WMI_DEL_STA_CMDID, &del_sta_cmd, + rc = wmi_call(wil, WMI_DEL_STA_CMDID, vif->mid, &del_sta_cmd, sizeof(del_sta_cmd), WMI_DISCONNECT_EVENTID, &reply, sizeof(reply), 1000); } else { ether_addr_copy(disc_sta_cmd.dst_mac, mac); - rc = wmi_call(wil, WMI_DISCONNECT_STA_CMDID, &disc_sta_cmd, - sizeof(disc_sta_cmd), WMI_DISCONNECT_EVENTID, + rc = wmi_call(wil, WMI_DISCONNECT_STA_CMDID, vif->mid, + &disc_sta_cmd, sizeof(disc_sta_cmd), + WMI_DISCONNECT_EVENTID, &reply, sizeof(reply), 1000); } /* failure to disconnect in reasonable time treated as FW error */ @@ -1967,12 +2013,13 @@ int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac, reply.evt.disconnect_reason); wil->sinfo_gen++; - wil6210_disconnect(wil, reply.evt.bssid, reason_code, true); + wil6210_disconnect(vif, reply.evt.bssid, reason_code, true); } return 0; } -int wmi_addba(struct wil6210_priv *wil, u8 ringid, u8 size, u16 timeout) +int wmi_addba(struct wil6210_priv *wil, u8 mid, + u8 ringid, u8 size, u16 timeout) { struct wmi_vring_ba_en_cmd cmd = { .ringid = ringid, @@ -1984,10 +2031,10 @@ int wmi_addba(struct wil6210_priv *wil, u8 ringid, u8 size, u16 timeout) wil_dbg_wmi(wil, "addba: (ring %d size %d timeout %d)\n", ringid, size, timeout); - return wmi_send(wil, WMI_VRING_BA_EN_CMDID, &cmd, sizeof(cmd)); + return wmi_send(wil, WMI_VRING_BA_EN_CMDID, mid, &cmd, sizeof(cmd)); } -int wmi_delba_tx(struct wil6210_priv *wil, u8 ringid, u16 reason) +int wmi_delba_tx(struct wil6210_priv *wil, u8 mid, u8 ringid, u16 reason) { struct wmi_vring_ba_dis_cmd cmd = { .ringid = ringid, @@ -1996,10 +2043,10 @@ int wmi_delba_tx(struct wil6210_priv *wil, u8 ringid, u16 reason) wil_dbg_wmi(wil, "delba_tx: (ring %d reason %d)\n", ringid, reason); - return wmi_send(wil, WMI_VRING_BA_DIS_CMDID, &cmd, sizeof(cmd)); + return wmi_send(wil, WMI_VRING_BA_DIS_CMDID, mid, &cmd, sizeof(cmd)); } -int wmi_delba_rx(struct wil6210_priv *wil, u8 cidxtid, u16 reason) +int wmi_delba_rx(struct wil6210_priv *wil, u8 mid, u8 cidxtid, u16 reason) { struct wmi_rcp_delba_cmd cmd = { .cidxtid = cidxtid, @@ -2009,10 +2056,11 @@ int wmi_delba_rx(struct wil6210_priv *wil, u8 cidxtid, u16 reason) wil_dbg_wmi(wil, "delba_rx: (CID %d TID %d reason %d)\n", cidxtid & 0xf, (cidxtid >> 4) & 0xf, reason); - return wmi_send(wil, WMI_RCP_DELBA_CMDID, &cmd, sizeof(cmd)); + return wmi_send(wil, WMI_RCP_DELBA_CMDID, mid, &cmd, sizeof(cmd)); } -int wmi_addba_rx_resp(struct wil6210_priv *wil, u8 cid, u8 tid, u8 token, +int wmi_addba_rx_resp(struct wil6210_priv *wil, + u8 mid, u8 cid, u8 tid, u8 token, u16 status, bool amsdu, u16 agg_wsize, u16 timeout) { int rc; @@ -2035,10 +2083,11 @@ int wmi_addba_rx_resp(struct wil6210_priv *wil, u8 cid, u8 tid, u8 token, } __packed reply; wil_dbg_wmi(wil, - "ADDBA response for CID %d TID %d size %d timeout %d status %d AMSDU%s\n", - cid, tid, agg_wsize, timeout, status, amsdu ? "+" : "-"); + "ADDBA response for MID %d CID %d TID %d size %d timeout %d status %d AMSDU%s\n", + mid, cid, tid, agg_wsize, + timeout, status, amsdu ? "+" : "-"); - rc = wmi_call(wil, WMI_RCP_ADDBA_RESP_CMDID, &cmd, sizeof(cmd), + rc = wmi_call(wil, WMI_RCP_ADDBA_RESP_CMDID, mid, &cmd, sizeof(cmd), WMI_RCP_ADDBA_RESP_SENT_EVENTID, &reply, sizeof(reply), 100); if (rc) @@ -2056,6 +2105,7 @@ int wmi_addba_rx_resp(struct wil6210_priv *wil, u8 cid, u8 tid, u8 token, int wmi_ps_dev_profile_cfg(struct wil6210_priv *wil, enum wmi_ps_profile_type ps_profile) { + struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev); int rc; struct wmi_ps_dev_profile_cfg_cmd cmd = { .ps_profile = ps_profile, @@ -2070,7 +2120,8 @@ int wmi_ps_dev_profile_cfg(struct wil6210_priv *wil, reply.evt.status = cpu_to_le32(WMI_PS_CFG_CMD_STATUS_ERROR); - rc = wmi_call(wil, WMI_PS_DEV_PROFILE_CFG_CMDID, &cmd, sizeof(cmd), + rc = wmi_call(wil, WMI_PS_DEV_PROFILE_CFG_CMDID, vif->mid, + &cmd, sizeof(cmd), WMI_PS_DEV_PROFILE_CFG_EVENTID, &reply, sizeof(reply), 100); if (rc) @@ -2089,6 +2140,7 @@ int wmi_ps_dev_profile_cfg(struct wil6210_priv *wil, int wmi_set_mgmt_retry(struct wil6210_priv *wil, u8 retry_short) { + struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev); int rc; struct wmi_set_mgmt_retry_limit_cmd cmd = { .mgmt_retry_limit = retry_short, @@ -2105,7 +2157,8 @@ int wmi_set_mgmt_retry(struct wil6210_priv *wil, u8 retry_short) reply.evt.status = WMI_FW_STATUS_FAILURE; - rc = wmi_call(wil, WMI_SET_MGMT_RETRY_LIMIT_CMDID, &cmd, sizeof(cmd), + rc = wmi_call(wil, WMI_SET_MGMT_RETRY_LIMIT_CMDID, vif->mid, + &cmd, sizeof(cmd), WMI_SET_MGMT_RETRY_LIMIT_EVENTID, &reply, sizeof(reply), 100); if (rc) @@ -2122,6 +2175,7 @@ int wmi_set_mgmt_retry(struct wil6210_priv *wil, u8 retry_short) int wmi_get_mgmt_retry(struct wil6210_priv *wil, u8 *retry_short) { + struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev); int rc; struct { struct wmi_cmd_hdr wmi; @@ -2134,7 +2188,7 @@ int wmi_get_mgmt_retry(struct wil6210_priv *wil, u8 *retry_short) return -ENOTSUPP; reply.evt.mgmt_retry_limit = 0; - rc = wmi_call(wil, WMI_GET_MGMT_RETRY_LIMIT_CMDID, NULL, 0, + rc = wmi_call(wil, WMI_GET_MGMT_RETRY_LIMIT_CMDID, vif->mid, NULL, 0, WMI_GET_MGMT_RETRY_LIMIT_EVENTID, &reply, sizeof(reply), 100); if (rc) @@ -2146,21 +2200,23 @@ int wmi_get_mgmt_retry(struct wil6210_priv *wil, u8 *retry_short) return 0; } -int wmi_abort_scan(struct wil6210_priv *wil) +int wmi_abort_scan(struct wil6210_vif *vif) { + struct wil6210_priv *wil = vif_to_wil(vif); int rc; wil_dbg_wmi(wil, "sending WMI_ABORT_SCAN_CMDID\n"); - rc = wmi_send(wil, WMI_ABORT_SCAN_CMDID, NULL, 0); + rc = wmi_send(wil, WMI_ABORT_SCAN_CMDID, vif->mid, NULL, 0); if (rc) wil_err(wil, "Failed to abort scan (%d)\n", rc); return rc; } -int wmi_new_sta(struct wil6210_priv *wil, const u8 *mac, u8 aid) +int wmi_new_sta(struct wil6210_vif *vif, const u8 *mac, u8 aid) { + struct wil6210_priv *wil = vif_to_wil(vif); int rc; struct wmi_new_sta_cmd cmd = { .aid = aid, @@ -2170,7 +2226,7 @@ int wmi_new_sta(struct wil6210_priv *wil, const u8 *mac, u8 aid) ether_addr_copy(cmd.dst_mac, mac); - rc = wmi_send(wil, WMI_NEW_STA_CMDID, &cmd, sizeof(cmd)); + rc = wmi_send(wil, WMI_NEW_STA_CMDID, vif->mid, &cmd, sizeof(cmd)); if (rc) wil_err(wil, "Failed to send new sta (%d)\n", rc); @@ -2206,6 +2262,7 @@ static const char *suspend_status2name(u8 status) int wmi_suspend(struct wil6210_priv *wil) { + struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev); int rc; struct wmi_traffic_suspend_cmd cmd = { .wakeup_trigger = wil->wakeup_trigger, @@ -2221,7 +2278,8 @@ int wmi_suspend(struct wil6210_priv *wil) reply.evt.status = WMI_TRAFFIC_SUSPEND_REJECTED_LINK_NOT_IDLE; - rc = wmi_call(wil, WMI_TRAFFIC_SUSPEND_CMDID, &cmd, sizeof(cmd), + rc = wmi_call(wil, WMI_TRAFFIC_SUSPEND_CMDID, vif->mid, + &cmd, sizeof(cmd), WMI_TRAFFIC_SUSPEND_EVENTID, &reply, sizeof(reply), suspend_to); if (rc) { @@ -2289,6 +2347,7 @@ static void resume_triggers2string(u32 triggers, char *string, int str_size) int wmi_resume(struct wil6210_priv *wil) { + struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev); int rc; char string[100]; struct { @@ -2299,7 +2358,7 @@ int wmi_resume(struct wil6210_priv *wil) reply.evt.status = WMI_TRAFFIC_RESUME_FAILED; reply.evt.resume_triggers = WMI_RESUME_TRIGGER_UNKNOWN; - rc = wmi_call(wil, WMI_TRAFFIC_RESUME_CMDID, NULL, 0, + rc = wmi_call(wil, WMI_TRAFFIC_RESUME_CMDID, vif->mid, NULL, 0, WMI_TRAFFIC_RESUME_EVENTID, &reply, sizeof(reply), WIL_WAIT_FOR_SUSPEND_RESUME_COMP); if (rc) @@ -2313,14 +2372,14 @@ int wmi_resume(struct wil6210_priv *wil) return reply.evt.status; } -static bool wmi_evt_call_handler(struct wil6210_priv *wil, int id, +static bool wmi_evt_call_handler(struct wil6210_vif *vif, int id, void *d, int len) { uint i; for (i = 0; i < ARRAY_SIZE(wmi_evt_handlers); i++) { if (wmi_evt_handlers[i].eventid == id) { - wmi_evt_handlers[i].handler(wil, id, d, len); + wmi_evt_handlers[i].handler(vif, id, d, len); return true; } } @@ -2332,19 +2391,25 @@ static void wmi_event_handle(struct wil6210_priv *wil, struct wil6210_mbox_hdr *hdr) { u16 len = le16_to_cpu(hdr->len); + struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev); if ((hdr->type == WIL_MBOX_HDR_TYPE_WMI) && (len >= sizeof(struct wmi_cmd_hdr))) { struct wmi_cmd_hdr *wmi = (void *)(&hdr[1]); void *evt_data = (void *)(&wmi[1]); u16 id = le16_to_cpu(wmi->command_id); + u8 mid = wmi->mid; + + wil_dbg_wmi(wil, "Handle %s (0x%04x) (reply_id 0x%04x,%d)\n", + eventid2name(id), id, wil->reply_id, + wil->reply_mid); - wil_dbg_wmi(wil, "Handle %s (0x%04x) (reply_id 0x%04x)\n", - eventid2name(id), id, wil->reply_id); /* check if someone waits for this event */ - if (wil->reply_id && wil->reply_id == id) { + if (wil->reply_id && wil->reply_id == id && + wil->reply_mid == mid) { WARN_ON(wil->reply_buf); - wmi_evt_call_handler(wil, id, evt_data, + + wmi_evt_call_handler(vif, id, evt_data, len - sizeof(*wmi)); wil_dbg_wmi(wil, "event_handle: Complete WMI 0x%04x\n", id); @@ -2353,7 +2418,7 @@ static void wmi_event_handle(struct wil6210_priv *wil, } /* unsolicited event */ /* search for handler */ - if (!wmi_evt_call_handler(wil, id, evt_data, + if (!wmi_evt_call_handler(vif, id, evt_data, len - sizeof(*wmi))) { wil_info(wil, "Unhandled event 0x%04x\n", id); } @@ -2523,6 +2588,7 @@ wmi_sched_scan_set_plans(struct wil6210_priv *wil, int wmi_start_sched_scan(struct wil6210_priv *wil, struct cfg80211_sched_scan_request *request) { + struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev); int rc; struct wmi_start_sched_scan_cmd cmd = { .min_rssi_threshold = S8_MIN, @@ -2549,7 +2615,8 @@ int wmi_start_sched_scan(struct wil6210_priv *wil, reply.evt.result = WMI_PNO_REJECT; - rc = wmi_call(wil, WMI_START_SCHED_SCAN_CMDID, &cmd, sizeof(cmd), + rc = wmi_call(wil, WMI_START_SCHED_SCAN_CMDID, vif->mid, + &cmd, sizeof(cmd), WMI_START_SCHED_SCAN_EVENTID, &reply, sizeof(reply), WIL_WMI_CALL_GENERAL_TO_MS); if (rc) @@ -2566,6 +2633,7 @@ int wmi_start_sched_scan(struct wil6210_priv *wil, int wmi_stop_sched_scan(struct wil6210_priv *wil) { + struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev); int rc; struct { struct wmi_cmd_hdr wmi; @@ -2577,7 +2645,7 @@ int wmi_stop_sched_scan(struct wil6210_priv *wil) reply.evt.result = WMI_PNO_REJECT; - rc = wmi_call(wil, WMI_STOP_SCHED_SCAN_CMDID, NULL, 0, + rc = wmi_call(wil, WMI_STOP_SCHED_SCAN_CMDID, vif->mid, NULL, 0, WMI_STOP_SCHED_SCAN_EVENTID, &reply, sizeof(reply), WIL_WMI_CALL_GENERAL_TO_MS); if (rc) |