Loading drivers/net/wireless/ath/wil6210/cfg80211.c +15 −17 Original line number Diff line number Diff line Loading @@ -391,7 +391,7 @@ int wil_cid_fill_sinfo(struct wil6210_vif *vif, int cid, sinfo->tx_packets = stats->tx_packets; sinfo->tx_failed = stats->tx_errors; if (test_bit(wil_status_fwconnected, wil->status)) { if (test_bit(wil_vif_fwconnected, vif->status)) { sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL); if (test_bit(WMI_FW_CAPABILITY_RSSI_REPORTING, wil->fw_capabilities)) Loading Loading @@ -562,11 +562,10 @@ wil_cfg80211_add_iface(struct wiphy *wiphy, const char *name, return ERR_PTR(-EINVAL); } vif = kzalloc(sizeof(*vif), GFP_KERNEL); if (!vif) p2p_wdev = kzalloc(sizeof(*p2p_wdev), GFP_KERNEL); if (!p2p_wdev) return ERR_PTR(-ENOMEM); p2p_wdev = vif_to_wdev(vif); p2p_wdev->iftype = type; p2p_wdev->wiphy = wiphy; /* use our primary ethernet address */ Loading Loading @@ -976,8 +975,8 @@ static int wil_cfg80211_connect(struct wiphy *wiphy, wil_dbg_misc(wil, "connect, mid=%d\n", vif->mid); wil_print_connect_params(wil, sme); if (test_bit(wil_status_fwconnecting, wil->status) || test_bit(wil_status_fwconnected, wil->status)) if (test_bit(wil_vif_fwconnecting, vif->status) || test_bit(wil_vif_fwconnected, vif->status)) return -EALREADY; if (sme->ie_len > WMI_MAX_IE_LEN) { Loading Loading @@ -1081,18 +1080,19 @@ static int wil_cfg80211_connect(struct wiphy *wiphy, ether_addr_copy(conn.bssid, bss->bssid); ether_addr_copy(conn.dst_mac, bss->bssid); set_bit(wil_status_fwconnecting, wil->status); set_bit(wil_vif_fwconnecting, vif->status); rc = wmi_send(wil, WMI_CONNECT_CMDID, vif->mid, &conn, sizeof(conn)); if (rc == 0) { netif_carrier_on(ndev); if (!wil_has_other_active_ifaces(wil, ndev, false, true)) wil6210_bus_request(wil, WIL_MAX_BUS_REQUEST_KBPS); vif->bss = bss; /* Connect can take lots of time */ mod_timer(&vif->connect_timer, jiffies + msecs_to_jiffies(5000)); } else { clear_bit(wil_status_fwconnecting, wil->status); clear_bit(wil_vif_fwconnecting, vif->status); } out: Loading @@ -1112,8 +1112,8 @@ static int wil_cfg80211_disconnect(struct wiphy *wiphy, 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))) { if (!(test_bit(wil_vif_fwconnecting, vif->status) || test_bit(wil_vif_fwconnected, vif->status))) { wil_err(wil, "Disconnect was called while disconnected\n"); return 0; } Loading Loading @@ -2017,7 +2017,7 @@ static int wil_cfg80211_suspend(struct wiphy *wiphy, mutex_lock(&wil->mutex); mutex_lock(&wil->vif_mutex); wil_p2p_stop_radio_operations(wil); wil_abort_scan(ndev_to_vif(wil->main_ndev), true); wil_abort_scan_all_vifs(wil, true); mutex_unlock(&wil->vif_mutex); mutex_unlock(&wil->mutex); Loading Loading @@ -2312,7 +2312,6 @@ void wil_cfg80211_deinit(struct wil6210_priv *wil) void wil_p2p_wdev_free(struct wil6210_priv *wil) { struct wireless_dev *p2p_wdev; struct wil6210_vif *vif; mutex_lock(&wil->vif_mutex); p2p_wdev = wil->p2p_wdev; Loading @@ -2321,8 +2320,7 @@ void wil_p2p_wdev_free(struct wil6210_priv *wil) mutex_unlock(&wil->vif_mutex); if (p2p_wdev) { cfg80211_unregister_wdev(p2p_wdev); vif = wdev_to_vif(wil, p2p_wdev); kfree(vif); kfree(p2p_wdev); } } Loading Loading @@ -2616,7 +2614,7 @@ static int wil_rf_sector_get_selected(struct wiphy *wiphy, return -ENOENT; } } else { if (test_bit(wil_status_fwconnected, wil->status)) { if (test_bit(wil_vif_fwconnected, vif->status)) { wil_err(wil, "must specify MAC address when connected\n"); return -EINVAL; } Loading Loading @@ -2743,7 +2741,7 @@ static int wil_rf_sector_set_selected(struct wiphy *wiphy, cid = -1; } } else { if (test_bit(wil_status_fwconnected, wil->status)) { if (test_bit(wil_vif_fwconnected, vif->status)) { wil_err(wil, "must specify MAC address when connected\n"); return -EINVAL; } Loading drivers/net/wireless/ath/wil6210/debugfs.c +16 −4 Original line number Diff line number Diff line Loading @@ -1246,12 +1246,13 @@ 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++) { struct wil_sta_info *p = &wil->sta[i]; char *status = "unknown"; struct wil6210_vif *vif; u8 mid; switch (p->status) { case wil_sta_unused: Loading @@ -1264,9 +1265,15 @@ static int wil_link_debugfs_show(struct seq_file *s, void *data) status = "connected"; break; } seq_printf(s, "[%d] %pM %s\n", i, p->addr, status); mid = (p->status != wil_sta_unused) ? p->mid : U8_MAX; seq_printf(s, "[%d][MID %d] %pM %s\n", i, mid, p->addr, status); if (p->status == wil_sta_connected) { if (p->status != wil_sta_connected) continue; vif = (mid < wil->max_vifs) ? wil->vifs[mid] : NULL; if (vif) { rc = wil_cid_fill_sinfo(vif, i, &sinfo); if (rc) return rc; Loading @@ -1274,6 +1281,8 @@ static int wil_link_debugfs_show(struct seq_file *s, void *data) seq_printf(s, " Tx_mcs = %d\n", sinfo.txrate.mcs); seq_printf(s, " Rx_mcs = %d\n", sinfo.rxrate.mcs); seq_printf(s, " SQ = %d\n", sinfo.signal); } else { seq_puts(s, " INVALID MID\n"); } } Loading Loading @@ -1465,6 +1474,7 @@ __acquires(&p->tid_rx_lock) __releases(&p->tid_rx_lock) struct wil_sta_info *p = &wil->sta[i]; char *status = "unknown"; u8 aid = 0; u8 mid; switch (p->status) { case wil_sta_unused: Loading @@ -1478,7 +1488,9 @@ __acquires(&p->tid_rx_lock) __releases(&p->tid_rx_lock) aid = p->aid; break; } seq_printf(s, "[%d] %pM %s AID %d\n", i, p->addr, status, aid); mid = (p->status != wil_sta_unused) ? p->mid : U8_MAX; seq_printf(s, "[%d] %pM %s MID %d AID %d\n", i, p->addr, status, mid, aid); if (p->status == wil_sta_connected) { spin_lock_bh(&p->tid_rx_lock); Loading drivers/net/wireless/ath/wil6210/interrupt.c +1 −1 Original line number Diff line number Diff line Loading @@ -127,7 +127,7 @@ void wil6210_unmask_irq_tx(struct wil6210_priv *wil) void wil6210_unmask_irq_rx(struct wil6210_priv *wil) { bool unmask_rx_htrsh = test_bit(wil_status_fwconnected, wil->status); bool unmask_rx_htrsh = atomic_read(&wil->connected_vifs) > 0; wil_w(wil, RGF_DMA_EP_RX_ICR + offsetof(struct RGF_ICR, IMC), unmask_rx_htrsh ? WIL6210_IMC_RX : WIL6210_IMC_RX_NO_RX_HTRSH); Loading drivers/net/wireless/ath/wil6210/main.c +55 −23 Original line number Diff line number Diff line Loading @@ -175,6 +175,15 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) cid, sta->mid, sta->status); /* inform upper/lower layers */ if (sta->status != wil_sta_unused) { if (vif->mid != sta->mid) { wil_err(wil, "STA MID mismatch with VIF MID(%d)\n", vif->mid); /* let FW override sta->mid but be more strict with * user space requests */ if (!from_event) return; } if (!from_event) { bool del_sta = (wdev->iftype == NL80211_IFTYPE_AP) ? disable_ap_sme : false; Loading Loading @@ -278,32 +287,35 @@ static void _wil6210_disconnect(struct wil6210_vif *vif, const u8 *bssid, case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_P2P_CLIENT: wil_bcast_fini(vif); wil_update_net_queues_bh(wil, NULL, true); wil_update_net_queues_bh(wil, vif, NULL, true); netif_carrier_off(ndev); if (!wil_has_other_active_ifaces(wil, ndev, false, true)) wil6210_bus_request(wil, WIL_DEFAULT_BUS_REQUEST_KBPS); if (test_bit(wil_status_fwconnected, wil->status)) { clear_bit(wil_status_fwconnected, wil->status); if (test_and_clear_bit(wil_vif_fwconnected, vif->status)) { atomic_dec(&wil->connected_vifs); cfg80211_disconnected(ndev, reason_code, NULL, 0, vif->locally_generated_disc, GFP_KERNEL); vif->locally_generated_disc = false; } else if (test_bit(wil_status_fwconnecting, wil->status)) { } else if (test_bit(wil_vif_fwconnecting, vif->status)) { cfg80211_connect_result(ndev, bssid, NULL, 0, NULL, 0, WLAN_STATUS_UNSPECIFIED_FAILURE, GFP_KERNEL); vif->bss = NULL; } clear_bit(wil_status_fwconnecting, wil->status); clear_bit(wil_vif_fwconnecting, vif->status); break; case NL80211_IFTYPE_AP: case NL80211_IFTYPE_P2P_GO: if (!wil_vif_is_connected(wil, vif->mid)) { wil_update_net_queues_bh(wil, NULL, true); clear_bit(wil_status_fwconnected, wil->status); wil_update_net_queues_bh(wil, vif, NULL, true); if (test_and_clear_bit(wil_vif_fwconnected, vif->status)) atomic_dec(&wil->connected_vifs); } else { wil_update_net_queues_bh(wil, NULL, false); wil_update_net_queues_bh(wil, vif, NULL, false); } break; default: Loading @@ -323,11 +335,11 @@ void wil_disconnect_worker(struct work_struct *work) struct wmi_disconnect_event evt; } __packed reply; if (test_bit(wil_status_fwconnected, wil->status)) if (test_bit(wil_vif_fwconnected, vif->status)) /* connect succeeded after all */ return; if (!test_bit(wil_status_fwconnecting, wil->status)) if (!test_bit(wil_vif_fwconnecting, vif->status)) /* already disconnected */ return; Loading @@ -339,11 +351,11 @@ void wil_disconnect_worker(struct work_struct *work) return; } wil_update_net_queues_bh(wil, NULL, true); wil_update_net_queues_bh(wil, vif, NULL, true); netif_carrier_off(ndev); cfg80211_connect_result(ndev, NULL, NULL, 0, NULL, 0, WLAN_STATUS_UNSPECIFIED_FAILURE, GFP_KERNEL); clear_bit(wil_status_fwconnecting, wil->status); clear_bit(wil_vif_fwconnecting, vif->status); } static int wil_wait_for_recovery(struct wil6210_priv *wil) Loading Loading @@ -1096,6 +1108,20 @@ void wil_abort_scan(struct wil6210_vif *vif, bool sync) } } void wil_abort_scan_all_vifs(struct wil6210_priv *wil, bool sync) { int i; lockdep_assert_held(&wil->vif_mutex); for (i = 0; i < wil->max_vifs; i++) { struct wil6210_vif *vif = wil->vifs[i]; if (vif) wil_abort_scan(vif, sync); } } int wil_ps_update(struct wil6210_priv *wil, enum wmi_ps_profile_type ps_profile) { int rc; Loading Loading @@ -1148,6 +1174,7 @@ static int wil_restore_vifs(struct wil6210_priv *wil) vif = wil->vifs[i]; if (!vif) continue; vif->ap_isolate = 0; if (vif->mid) { ndev = vif_to_ndev(vif); wdev = vif_to_wdev(vif); Loading @@ -1171,10 +1198,10 @@ static int wil_restore_vifs(struct wil6210_priv *wil) */ int wil_reset(struct wil6210_priv *wil, bool load_fw) { int rc; int rc, i; unsigned long status_flags = BIT(wil_status_resetting); int no_flash; struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev); struct wil6210_vif *vif; wil_dbg_misc(wil, "reset\n"); Loading Loading @@ -1226,17 +1253,23 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) goto out; } mutex_lock(&wil->vif_mutex); wil_abort_scan_all_vifs(wil, false); mutex_unlock(&wil->vif_mutex); for (i = 0; i < wil->max_vifs; i++) { vif = wil->vifs[i]; if (vif) { cancel_work_sync(&vif->disconnect_worker); wil6210_disconnect(vif, NULL, WLAN_REASON_DEAUTH_LEAVING, false); wil6210_disconnect(vif, NULL, WLAN_REASON_DEAUTH_LEAVING, false); } } wil_bcast_fini_all(wil); /* Disable device led before reset*/ wmi_led_cfg(wil, false); mutex_lock(&wil->vif_mutex); wil_abort_scan(vif, false); mutex_unlock(&wil->vif_mutex); /* prevent NAPI from being scheduled and prevent wmi commands */ mutex_lock(&wil->wmi_mutex); if (test_bit(wil_status_suspending, wil->status)) Loading Loading @@ -1306,7 +1339,6 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) } /* init after reset */ vif->ap_isolate = 0; reinit_completion(&wil->wmi_ready); reinit_completion(&wil->wmi_call); reinit_completion(&wil->halp.comp); Loading Loading @@ -1467,7 +1499,7 @@ int __wil_down(struct wil6210_priv *wil) mutex_lock(&wil->vif_mutex); wil_p2p_stop_radio_operations(wil); wil_abort_scan(ndev_to_vif(wil->main_ndev), false); wil_abort_scan_all_vifs(wil, false); mutex_unlock(&wil->vif_mutex); return wil_reset(wil, false); Loading drivers/net/wireless/ath/wil6210/netdev.c +42 −5 Original line number Diff line number Diff line Loading @@ -48,6 +48,7 @@ bool wil_has_other_active_ifaces(struct wil6210_priv *wil, bool wil_has_active_ifaces(struct wil6210_priv *wil, bool up, bool ok) { /* use NULL ndev argument to check all interfaces */ return wil_has_other_active_ifaces(wil, NULL, up, ok); } Loading Loading @@ -143,11 +144,19 @@ static int wil6210_netdev_poll_tx(struct napi_struct *napi, int budget) for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) { struct vring *vring = &wil->vring_tx[i]; struct vring_tx_data *txdata = &wil->vring_tx_data[i]; struct wil6210_vif *vif; if (!vring->va || !txdata->enabled || txdata->mid >= wil->max_vifs) continue; if (!vring->va || !txdata->enabled) vif = wil->vifs[txdata->mid]; if (unlikely(!vif)) { wil_dbg_txrx(wil, "Invalid MID %d\n", txdata->mid); continue; } tx_done += wil_tx_complete(wil, i); tx_done += wil_tx_complete(vif, i); } if (tx_done < budget) { Loading Loading @@ -246,7 +255,10 @@ static void wil_vif_init(struct wil6210_vif *vif) INIT_WORK(&vif->p2p.delayed_listen_work, wil_p2p_delayed_listen_work); INIT_LIST_HEAD(&vif->probe_client_pending); wil_ftm_init(vif); vif->net_queue_stopped = 1; } static u8 wil_vif_find_free_mid(struct wil6210_priv *wil) Loading Loading @@ -422,12 +434,14 @@ int wil_if_add(struct wil6210_priv *wil) return rc; } netif_napi_add(ndev, &wil->napi_rx, wil6210_netdev_poll_rx, init_dummy_netdev(&wil->napi_ndev); netif_napi_add(&wil->napi_ndev, &wil->napi_rx, wil6210_netdev_poll_rx, WIL6210_NAPI_BUDGET); netif_tx_napi_add(ndev, &wil->napi_tx, wil6210_netdev_poll_tx, netif_tx_napi_add(&wil->napi_ndev, &wil->napi_tx, wil6210_netdev_poll_tx, WIL6210_NAPI_BUDGET); wil_update_net_queues_bh(wil, NULL, true); wil_update_net_queues_bh(wil, vif, NULL, true); rtnl_lock(); rc = wil_vif_add(wil, vif); Loading Loading @@ -466,10 +480,29 @@ void wil_vif_remove(struct wil6210_priv *wil, u8 mid) */ unregister_netdevice(ndev); mutex_lock(&wil->mutex); wil6210_disconnect(vif, NULL, WLAN_REASON_DEAUTH_LEAVING, false); mutex_unlock(&wil->mutex); if (any_active && vif->mid != 0) wmi_port_delete(wil, vif->mid); /* make sure no one is accessing the VIF before removing */ mutex_lock(&wil->vif_mutex); wil->vifs[mid] = NULL; /* ensure NAPI code will see the NULL VIF */ wmb(); if (test_bit(wil_status_napi_en, wil->status)) { napi_synchronize(&wil->napi_rx); napi_synchronize(&wil->napi_tx); } mutex_unlock(&wil->vif_mutex); flush_work(&wil->wmi_event_worker); del_timer_sync(&vif->connect_timer); cancel_work_sync(&vif->disconnect_worker); wil_probe_client_flush(vif); cancel_work_sync(&vif->probe_client_worker); /* for VIFs, ndev will be freed by destructor after RTNL is unlocked. * the main interface will be freed in wil_if_free, we need to keep it * a bit longer so logging macros will work. Loading @@ -486,5 +519,9 @@ void wil_if_remove(struct wil6210_priv *wil) rtnl_lock(); wil_vif_remove(wil, 0); rtnl_unlock(); netif_napi_del(&wil->napi_tx); netif_napi_del(&wil->napi_rx); wiphy_unregister(wdev->wiphy); } Loading
drivers/net/wireless/ath/wil6210/cfg80211.c +15 −17 Original line number Diff line number Diff line Loading @@ -391,7 +391,7 @@ int wil_cid_fill_sinfo(struct wil6210_vif *vif, int cid, sinfo->tx_packets = stats->tx_packets; sinfo->tx_failed = stats->tx_errors; if (test_bit(wil_status_fwconnected, wil->status)) { if (test_bit(wil_vif_fwconnected, vif->status)) { sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL); if (test_bit(WMI_FW_CAPABILITY_RSSI_REPORTING, wil->fw_capabilities)) Loading Loading @@ -562,11 +562,10 @@ wil_cfg80211_add_iface(struct wiphy *wiphy, const char *name, return ERR_PTR(-EINVAL); } vif = kzalloc(sizeof(*vif), GFP_KERNEL); if (!vif) p2p_wdev = kzalloc(sizeof(*p2p_wdev), GFP_KERNEL); if (!p2p_wdev) return ERR_PTR(-ENOMEM); p2p_wdev = vif_to_wdev(vif); p2p_wdev->iftype = type; p2p_wdev->wiphy = wiphy; /* use our primary ethernet address */ Loading Loading @@ -976,8 +975,8 @@ static int wil_cfg80211_connect(struct wiphy *wiphy, wil_dbg_misc(wil, "connect, mid=%d\n", vif->mid); wil_print_connect_params(wil, sme); if (test_bit(wil_status_fwconnecting, wil->status) || test_bit(wil_status_fwconnected, wil->status)) if (test_bit(wil_vif_fwconnecting, vif->status) || test_bit(wil_vif_fwconnected, vif->status)) return -EALREADY; if (sme->ie_len > WMI_MAX_IE_LEN) { Loading Loading @@ -1081,18 +1080,19 @@ static int wil_cfg80211_connect(struct wiphy *wiphy, ether_addr_copy(conn.bssid, bss->bssid); ether_addr_copy(conn.dst_mac, bss->bssid); set_bit(wil_status_fwconnecting, wil->status); set_bit(wil_vif_fwconnecting, vif->status); rc = wmi_send(wil, WMI_CONNECT_CMDID, vif->mid, &conn, sizeof(conn)); if (rc == 0) { netif_carrier_on(ndev); if (!wil_has_other_active_ifaces(wil, ndev, false, true)) wil6210_bus_request(wil, WIL_MAX_BUS_REQUEST_KBPS); vif->bss = bss; /* Connect can take lots of time */ mod_timer(&vif->connect_timer, jiffies + msecs_to_jiffies(5000)); } else { clear_bit(wil_status_fwconnecting, wil->status); clear_bit(wil_vif_fwconnecting, vif->status); } out: Loading @@ -1112,8 +1112,8 @@ static int wil_cfg80211_disconnect(struct wiphy *wiphy, 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))) { if (!(test_bit(wil_vif_fwconnecting, vif->status) || test_bit(wil_vif_fwconnected, vif->status))) { wil_err(wil, "Disconnect was called while disconnected\n"); return 0; } Loading Loading @@ -2017,7 +2017,7 @@ static int wil_cfg80211_suspend(struct wiphy *wiphy, mutex_lock(&wil->mutex); mutex_lock(&wil->vif_mutex); wil_p2p_stop_radio_operations(wil); wil_abort_scan(ndev_to_vif(wil->main_ndev), true); wil_abort_scan_all_vifs(wil, true); mutex_unlock(&wil->vif_mutex); mutex_unlock(&wil->mutex); Loading Loading @@ -2312,7 +2312,6 @@ void wil_cfg80211_deinit(struct wil6210_priv *wil) void wil_p2p_wdev_free(struct wil6210_priv *wil) { struct wireless_dev *p2p_wdev; struct wil6210_vif *vif; mutex_lock(&wil->vif_mutex); p2p_wdev = wil->p2p_wdev; Loading @@ -2321,8 +2320,7 @@ void wil_p2p_wdev_free(struct wil6210_priv *wil) mutex_unlock(&wil->vif_mutex); if (p2p_wdev) { cfg80211_unregister_wdev(p2p_wdev); vif = wdev_to_vif(wil, p2p_wdev); kfree(vif); kfree(p2p_wdev); } } Loading Loading @@ -2616,7 +2614,7 @@ static int wil_rf_sector_get_selected(struct wiphy *wiphy, return -ENOENT; } } else { if (test_bit(wil_status_fwconnected, wil->status)) { if (test_bit(wil_vif_fwconnected, vif->status)) { wil_err(wil, "must specify MAC address when connected\n"); return -EINVAL; } Loading Loading @@ -2743,7 +2741,7 @@ static int wil_rf_sector_set_selected(struct wiphy *wiphy, cid = -1; } } else { if (test_bit(wil_status_fwconnected, wil->status)) { if (test_bit(wil_vif_fwconnected, vif->status)) { wil_err(wil, "must specify MAC address when connected\n"); return -EINVAL; } Loading
drivers/net/wireless/ath/wil6210/debugfs.c +16 −4 Original line number Diff line number Diff line Loading @@ -1246,12 +1246,13 @@ 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++) { struct wil_sta_info *p = &wil->sta[i]; char *status = "unknown"; struct wil6210_vif *vif; u8 mid; switch (p->status) { case wil_sta_unused: Loading @@ -1264,9 +1265,15 @@ static int wil_link_debugfs_show(struct seq_file *s, void *data) status = "connected"; break; } seq_printf(s, "[%d] %pM %s\n", i, p->addr, status); mid = (p->status != wil_sta_unused) ? p->mid : U8_MAX; seq_printf(s, "[%d][MID %d] %pM %s\n", i, mid, p->addr, status); if (p->status == wil_sta_connected) { if (p->status != wil_sta_connected) continue; vif = (mid < wil->max_vifs) ? wil->vifs[mid] : NULL; if (vif) { rc = wil_cid_fill_sinfo(vif, i, &sinfo); if (rc) return rc; Loading @@ -1274,6 +1281,8 @@ static int wil_link_debugfs_show(struct seq_file *s, void *data) seq_printf(s, " Tx_mcs = %d\n", sinfo.txrate.mcs); seq_printf(s, " Rx_mcs = %d\n", sinfo.rxrate.mcs); seq_printf(s, " SQ = %d\n", sinfo.signal); } else { seq_puts(s, " INVALID MID\n"); } } Loading Loading @@ -1465,6 +1474,7 @@ __acquires(&p->tid_rx_lock) __releases(&p->tid_rx_lock) struct wil_sta_info *p = &wil->sta[i]; char *status = "unknown"; u8 aid = 0; u8 mid; switch (p->status) { case wil_sta_unused: Loading @@ -1478,7 +1488,9 @@ __acquires(&p->tid_rx_lock) __releases(&p->tid_rx_lock) aid = p->aid; break; } seq_printf(s, "[%d] %pM %s AID %d\n", i, p->addr, status, aid); mid = (p->status != wil_sta_unused) ? p->mid : U8_MAX; seq_printf(s, "[%d] %pM %s MID %d AID %d\n", i, p->addr, status, mid, aid); if (p->status == wil_sta_connected) { spin_lock_bh(&p->tid_rx_lock); Loading
drivers/net/wireless/ath/wil6210/interrupt.c +1 −1 Original line number Diff line number Diff line Loading @@ -127,7 +127,7 @@ void wil6210_unmask_irq_tx(struct wil6210_priv *wil) void wil6210_unmask_irq_rx(struct wil6210_priv *wil) { bool unmask_rx_htrsh = test_bit(wil_status_fwconnected, wil->status); bool unmask_rx_htrsh = atomic_read(&wil->connected_vifs) > 0; wil_w(wil, RGF_DMA_EP_RX_ICR + offsetof(struct RGF_ICR, IMC), unmask_rx_htrsh ? WIL6210_IMC_RX : WIL6210_IMC_RX_NO_RX_HTRSH); Loading
drivers/net/wireless/ath/wil6210/main.c +55 −23 Original line number Diff line number Diff line Loading @@ -175,6 +175,15 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) cid, sta->mid, sta->status); /* inform upper/lower layers */ if (sta->status != wil_sta_unused) { if (vif->mid != sta->mid) { wil_err(wil, "STA MID mismatch with VIF MID(%d)\n", vif->mid); /* let FW override sta->mid but be more strict with * user space requests */ if (!from_event) return; } if (!from_event) { bool del_sta = (wdev->iftype == NL80211_IFTYPE_AP) ? disable_ap_sme : false; Loading Loading @@ -278,32 +287,35 @@ static void _wil6210_disconnect(struct wil6210_vif *vif, const u8 *bssid, case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_P2P_CLIENT: wil_bcast_fini(vif); wil_update_net_queues_bh(wil, NULL, true); wil_update_net_queues_bh(wil, vif, NULL, true); netif_carrier_off(ndev); if (!wil_has_other_active_ifaces(wil, ndev, false, true)) wil6210_bus_request(wil, WIL_DEFAULT_BUS_REQUEST_KBPS); if (test_bit(wil_status_fwconnected, wil->status)) { clear_bit(wil_status_fwconnected, wil->status); if (test_and_clear_bit(wil_vif_fwconnected, vif->status)) { atomic_dec(&wil->connected_vifs); cfg80211_disconnected(ndev, reason_code, NULL, 0, vif->locally_generated_disc, GFP_KERNEL); vif->locally_generated_disc = false; } else if (test_bit(wil_status_fwconnecting, wil->status)) { } else if (test_bit(wil_vif_fwconnecting, vif->status)) { cfg80211_connect_result(ndev, bssid, NULL, 0, NULL, 0, WLAN_STATUS_UNSPECIFIED_FAILURE, GFP_KERNEL); vif->bss = NULL; } clear_bit(wil_status_fwconnecting, wil->status); clear_bit(wil_vif_fwconnecting, vif->status); break; case NL80211_IFTYPE_AP: case NL80211_IFTYPE_P2P_GO: if (!wil_vif_is_connected(wil, vif->mid)) { wil_update_net_queues_bh(wil, NULL, true); clear_bit(wil_status_fwconnected, wil->status); wil_update_net_queues_bh(wil, vif, NULL, true); if (test_and_clear_bit(wil_vif_fwconnected, vif->status)) atomic_dec(&wil->connected_vifs); } else { wil_update_net_queues_bh(wil, NULL, false); wil_update_net_queues_bh(wil, vif, NULL, false); } break; default: Loading @@ -323,11 +335,11 @@ void wil_disconnect_worker(struct work_struct *work) struct wmi_disconnect_event evt; } __packed reply; if (test_bit(wil_status_fwconnected, wil->status)) if (test_bit(wil_vif_fwconnected, vif->status)) /* connect succeeded after all */ return; if (!test_bit(wil_status_fwconnecting, wil->status)) if (!test_bit(wil_vif_fwconnecting, vif->status)) /* already disconnected */ return; Loading @@ -339,11 +351,11 @@ void wil_disconnect_worker(struct work_struct *work) return; } wil_update_net_queues_bh(wil, NULL, true); wil_update_net_queues_bh(wil, vif, NULL, true); netif_carrier_off(ndev); cfg80211_connect_result(ndev, NULL, NULL, 0, NULL, 0, WLAN_STATUS_UNSPECIFIED_FAILURE, GFP_KERNEL); clear_bit(wil_status_fwconnecting, wil->status); clear_bit(wil_vif_fwconnecting, vif->status); } static int wil_wait_for_recovery(struct wil6210_priv *wil) Loading Loading @@ -1096,6 +1108,20 @@ void wil_abort_scan(struct wil6210_vif *vif, bool sync) } } void wil_abort_scan_all_vifs(struct wil6210_priv *wil, bool sync) { int i; lockdep_assert_held(&wil->vif_mutex); for (i = 0; i < wil->max_vifs; i++) { struct wil6210_vif *vif = wil->vifs[i]; if (vif) wil_abort_scan(vif, sync); } } int wil_ps_update(struct wil6210_priv *wil, enum wmi_ps_profile_type ps_profile) { int rc; Loading Loading @@ -1148,6 +1174,7 @@ static int wil_restore_vifs(struct wil6210_priv *wil) vif = wil->vifs[i]; if (!vif) continue; vif->ap_isolate = 0; if (vif->mid) { ndev = vif_to_ndev(vif); wdev = vif_to_wdev(vif); Loading @@ -1171,10 +1198,10 @@ static int wil_restore_vifs(struct wil6210_priv *wil) */ int wil_reset(struct wil6210_priv *wil, bool load_fw) { int rc; int rc, i; unsigned long status_flags = BIT(wil_status_resetting); int no_flash; struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev); struct wil6210_vif *vif; wil_dbg_misc(wil, "reset\n"); Loading Loading @@ -1226,17 +1253,23 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) goto out; } mutex_lock(&wil->vif_mutex); wil_abort_scan_all_vifs(wil, false); mutex_unlock(&wil->vif_mutex); for (i = 0; i < wil->max_vifs; i++) { vif = wil->vifs[i]; if (vif) { cancel_work_sync(&vif->disconnect_worker); wil6210_disconnect(vif, NULL, WLAN_REASON_DEAUTH_LEAVING, false); wil6210_disconnect(vif, NULL, WLAN_REASON_DEAUTH_LEAVING, false); } } wil_bcast_fini_all(wil); /* Disable device led before reset*/ wmi_led_cfg(wil, false); mutex_lock(&wil->vif_mutex); wil_abort_scan(vif, false); mutex_unlock(&wil->vif_mutex); /* prevent NAPI from being scheduled and prevent wmi commands */ mutex_lock(&wil->wmi_mutex); if (test_bit(wil_status_suspending, wil->status)) Loading Loading @@ -1306,7 +1339,6 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) } /* init after reset */ vif->ap_isolate = 0; reinit_completion(&wil->wmi_ready); reinit_completion(&wil->wmi_call); reinit_completion(&wil->halp.comp); Loading Loading @@ -1467,7 +1499,7 @@ int __wil_down(struct wil6210_priv *wil) mutex_lock(&wil->vif_mutex); wil_p2p_stop_radio_operations(wil); wil_abort_scan(ndev_to_vif(wil->main_ndev), false); wil_abort_scan_all_vifs(wil, false); mutex_unlock(&wil->vif_mutex); return wil_reset(wil, false); Loading
drivers/net/wireless/ath/wil6210/netdev.c +42 −5 Original line number Diff line number Diff line Loading @@ -48,6 +48,7 @@ bool wil_has_other_active_ifaces(struct wil6210_priv *wil, bool wil_has_active_ifaces(struct wil6210_priv *wil, bool up, bool ok) { /* use NULL ndev argument to check all interfaces */ return wil_has_other_active_ifaces(wil, NULL, up, ok); } Loading Loading @@ -143,11 +144,19 @@ static int wil6210_netdev_poll_tx(struct napi_struct *napi, int budget) for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) { struct vring *vring = &wil->vring_tx[i]; struct vring_tx_data *txdata = &wil->vring_tx_data[i]; struct wil6210_vif *vif; if (!vring->va || !txdata->enabled || txdata->mid >= wil->max_vifs) continue; if (!vring->va || !txdata->enabled) vif = wil->vifs[txdata->mid]; if (unlikely(!vif)) { wil_dbg_txrx(wil, "Invalid MID %d\n", txdata->mid); continue; } tx_done += wil_tx_complete(wil, i); tx_done += wil_tx_complete(vif, i); } if (tx_done < budget) { Loading Loading @@ -246,7 +255,10 @@ static void wil_vif_init(struct wil6210_vif *vif) INIT_WORK(&vif->p2p.delayed_listen_work, wil_p2p_delayed_listen_work); INIT_LIST_HEAD(&vif->probe_client_pending); wil_ftm_init(vif); vif->net_queue_stopped = 1; } static u8 wil_vif_find_free_mid(struct wil6210_priv *wil) Loading Loading @@ -422,12 +434,14 @@ int wil_if_add(struct wil6210_priv *wil) return rc; } netif_napi_add(ndev, &wil->napi_rx, wil6210_netdev_poll_rx, init_dummy_netdev(&wil->napi_ndev); netif_napi_add(&wil->napi_ndev, &wil->napi_rx, wil6210_netdev_poll_rx, WIL6210_NAPI_BUDGET); netif_tx_napi_add(ndev, &wil->napi_tx, wil6210_netdev_poll_tx, netif_tx_napi_add(&wil->napi_ndev, &wil->napi_tx, wil6210_netdev_poll_tx, WIL6210_NAPI_BUDGET); wil_update_net_queues_bh(wil, NULL, true); wil_update_net_queues_bh(wil, vif, NULL, true); rtnl_lock(); rc = wil_vif_add(wil, vif); Loading Loading @@ -466,10 +480,29 @@ void wil_vif_remove(struct wil6210_priv *wil, u8 mid) */ unregister_netdevice(ndev); mutex_lock(&wil->mutex); wil6210_disconnect(vif, NULL, WLAN_REASON_DEAUTH_LEAVING, false); mutex_unlock(&wil->mutex); if (any_active && vif->mid != 0) wmi_port_delete(wil, vif->mid); /* make sure no one is accessing the VIF before removing */ mutex_lock(&wil->vif_mutex); wil->vifs[mid] = NULL; /* ensure NAPI code will see the NULL VIF */ wmb(); if (test_bit(wil_status_napi_en, wil->status)) { napi_synchronize(&wil->napi_rx); napi_synchronize(&wil->napi_tx); } mutex_unlock(&wil->vif_mutex); flush_work(&wil->wmi_event_worker); del_timer_sync(&vif->connect_timer); cancel_work_sync(&vif->disconnect_worker); wil_probe_client_flush(vif); cancel_work_sync(&vif->probe_client_worker); /* for VIFs, ndev will be freed by destructor after RTNL is unlocked. * the main interface will be freed in wil_if_free, we need to keep it * a bit longer so logging macros will work. Loading @@ -486,5 +519,9 @@ void wil_if_remove(struct wil6210_priv *wil) rtnl_lock(); wil_vif_remove(wil, 0); rtnl_unlock(); netif_napi_del(&wil->napi_tx); netif_napi_del(&wil->napi_rx); wiphy_unregister(wdev->wiphy); }