Loading drivers/net/wireless/ath/wil6210/cfg80211.c +1 −1 Original line number Diff line number Diff line Loading @@ -2305,7 +2305,7 @@ static int wil_cfg80211_del_station(struct wiphy *wiphy, params->mac, params->reason_code, vif->mid); mutex_lock(&wil->mutex); wil6210_disconnect(vif, params->mac, params->reason_code, false); wil6210_disconnect(vif, params->mac, params->reason_code); mutex_unlock(&wil->mutex); return 0; Loading drivers/net/wireless/ath/wil6210/debugfs.c +10 −5 Original line number Diff line number Diff line Loading @@ -651,10 +651,10 @@ static ssize_t wil_read_file_ioblob(struct file *file, char __user *user_buf, enum { max_count = 4096 }; struct wil_blob_wrapper *wil_blob = file->private_data; struct wil6210_priv *wil = wil_blob->wil; loff_t pos = *ppos; loff_t aligned_pos, pos = *ppos; size_t available = wil_blob->blob.size; void *buf; size_t ret; size_t unaligned_bytes, aligned_count, ret; int rc; if (test_bit(wil_status_suspending, wil_blob->wil->status) || Loading @@ -672,7 +672,12 @@ static ssize_t wil_read_file_ioblob(struct file *file, char __user *user_buf, if (count > max_count) count = max_count; buf = kmalloc(count, GFP_KERNEL); /* set pos to 4 bytes aligned */ unaligned_bytes = pos % 4; aligned_pos = pos - unaligned_bytes; aligned_count = count + unaligned_bytes; buf = kmalloc(aligned_count, GFP_KERNEL); if (!buf) return -ENOMEM; Loading @@ -683,9 +688,9 @@ static ssize_t wil_read_file_ioblob(struct file *file, char __user *user_buf, } wil_memcpy_fromio_32(buf, (const void __iomem *) wil_blob->blob.data + pos, count); wil_blob->blob.data + aligned_pos, aligned_count); ret = copy_to_user(user_buf, buf, count); ret = copy_to_user(user_buf, buf + unaligned_bytes, count); wil_pm_runtime_put(wil); Loading drivers/net/wireless/ath/wil6210/main.c +133 −46 Original line number Diff line number Diff line Loading @@ -204,8 +204,21 @@ static void wil_ring_fini_tx(struct wil6210_priv *wil, int id) wil->txrx_ops.ring_fini_tx(wil, ring); } static void wil_disconnect_cid(struct wil6210_vif *vif, int cid, u16 reason_code, bool from_event) static bool wil_vif_is_connected(struct wil6210_priv *wil, u8 mid) { int i; for (i = 0; i < WIL6210_MAX_CID; i++) { if (wil->sta[i].mid == mid && wil->sta[i].status == wil_sta_connected) return true; } return false; } static void wil_disconnect_cid_complete(struct wil6210_vif *vif, int cid, u16 reason_code) __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) { uint i; Loading @@ -216,24 +229,14 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) int min_ring_id = wil_get_min_tx_ring_id(wil); might_sleep(); wil_dbg_misc(wil, "disconnect_cid: CID %d, MID %d, status %d\n", wil_dbg_misc(wil, "disconnect_cid_complete: CID %d, MID %d, status %d\n", cid, sta->mid, sta->status); /* inform upper/lower layers */ /* inform upper 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; wmi_disconnect_sta(vif, sta->addr, reason_code, true, del_sta); } switch (wdev->iftype) { Loading Loading @@ -274,36 +277,20 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) sta->stats.tx_latency_min_us = U32_MAX; } 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].mid == mid && wil->sta[i].status == wil_sta_connected) return true; } return false; } static void _wil6210_disconnect(struct wil6210_vif *vif, const u8 *bssid, u16 reason_code, bool from_event) static void _wil6210_disconnect_complete(struct wil6210_vif *vif, const u8 *bssid, u16 reason_code) { struct wil6210_priv *wil = vif_to_wil(vif); int cid = -ENOENT; struct net_device *ndev; struct wireless_dev *wdev; 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 ? "+" : "-"); wil_info(wil, "disconnect_complete: bssid=%pM, reason=%d\n", bssid, reason_code); /* Cases are: * - disconnect single STA, still connected Loading @@ -318,14 +305,15 @@ static void _wil6210_disconnect(struct wil6210_vif *vif, const u8 *bssid, if (bssid && !is_broadcast_ether_addr(bssid) && !ether_addr_equal_unaligned(ndev->dev_addr, bssid)) { cid = wil_find_cid(wil, vif->mid, bssid); wil_dbg_misc(wil, "Disconnect %pM, CID=%d, reason=%d\n", wil_dbg_misc(wil, "Disconnect complete %pM, CID=%d, reason=%d\n", bssid, cid, reason_code); if (cid >= 0) /* disconnect 1 peer */ wil_disconnect_cid(vif, cid, reason_code, from_event); wil_disconnect_cid_complete(vif, cid, reason_code); } else { /* all */ wil_dbg_misc(wil, "Disconnect all\n"); wil_dbg_misc(wil, "Disconnect complete all\n"); for (cid = 0; cid < WIL6210_MAX_CID; cid++) wil_disconnect_cid(vif, cid, reason_code, from_event); wil_disconnect_cid_complete(vif, cid, reason_code); } /* link state */ Loading Loading @@ -371,6 +359,84 @@ static void _wil6210_disconnect(struct wil6210_vif *vif, const u8 *bssid, } } static int wil_disconnect_cid(struct wil6210_vif *vif, int cid, u16 reason_code) { struct wil6210_priv *wil = vif_to_wil(vif); struct wireless_dev *wdev = vif_to_wdev(vif); struct wil_sta_info *sta = &wil->sta[cid]; bool del_sta = false; might_sleep(); wil_dbg_misc(wil, "disconnect_cid: CID %d, MID %d, status %d\n", cid, sta->mid, sta->status); if (sta->status == wil_sta_unused) return 0; if (vif->mid != sta->mid) { wil_err(wil, "STA MID mismatch with VIF MID(%d)\n", vif->mid); return -EINVAL; } /* inform lower layers */ if (wdev->iftype == NL80211_IFTYPE_AP && disable_ap_sme) del_sta = true; /* disconnect by sending command disconnect/del_sta and wait * synchronously for WMI_DISCONNECT_EVENTID event. */ return wmi_disconnect_sta(vif, sta->addr, reason_code, del_sta); } static void _wil6210_disconnect(struct wil6210_vif *vif, const u8 *bssid, u16 reason_code) { struct wil6210_priv *wil; struct net_device *ndev; struct wireless_dev *wdev; int cid = -ENOENT; if (unlikely(!vif)) return; wil = vif_to_wil(vif); ndev = vif_to_ndev(vif); wdev = vif_to_wdev(vif); might_sleep(); wil_info(wil, "disconnect bssid=%pM, reason=%d\n", bssid, reason_code); /* Cases are: * - disconnect single STA, still connected * - disconnect single STA, already disconnected * - disconnect all * * For "disconnect all", there are 3 options: * - bssid == NULL * - bssid is broadcast address (ff:ff:ff:ff:ff:ff) * - bssid is our MAC address */ if (bssid && !is_broadcast_ether_addr(bssid) && !ether_addr_equal_unaligned(ndev->dev_addr, 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(vif, cid, reason_code); } else { /* all */ wil_dbg_misc(wil, "Disconnect all\n"); for (cid = 0; cid < WIL6210_MAX_CID; cid++) wil_disconnect_cid(vif, cid, reason_code); } /* call event handler manually after processing wmi_call, * to avoid deadlock - disconnect event handler acquires * wil->mutex while it is already held here */ _wil6210_disconnect_complete(vif, bssid, reason_code); } void wil_disconnect_worker(struct work_struct *work) { struct wil6210_vif *vif = container_of(work, Loading Loading @@ -695,20 +761,41 @@ void wil6210_bus_request(struct wil6210_priv *wil, u32 kbps) * @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 * * Disconnect and release associated resources. If invoked not from the * FW event handler, issue WMI command(s) to trigger MAC disconnect. * Disconnect and release associated resources. Issue WMI * command(s) to trigger MAC disconnect. When command was issued * successfully, call the wil6210_disconnect_complete function * to handle the event synchronously */ void wil6210_disconnect(struct wil6210_vif *vif, const u8 *bssid, u16 reason_code, bool from_event) u16 reason_code) { struct wil6210_priv *wil = vif_to_wil(vif); wil_dbg_misc(wil, "disconnecting\n"); del_timer_sync(&vif->connect_timer); _wil6210_disconnect(vif, bssid, reason_code); } /** * wil6210_disconnect_complete - handle disconnect event * @vif: virtual interface context * @bssid: peer to disconnect, NULL to disconnect all * @reason_code: Reason code for the Disassociation frame * * Release associated resources and indicate upper layers the * connection is terminated. */ void wil6210_disconnect_complete(struct wil6210_vif *vif, const u8 *bssid, u16 reason_code) { struct wil6210_priv *wil = vif_to_wil(vif); wil_dbg_misc(wil, "disconnect\n"); wil_dbg_misc(wil, "got disconnect\n"); del_timer_sync(&vif->connect_timer); _wil6210_disconnect(vif, bssid, reason_code, from_event); _wil6210_disconnect_complete(vif, bssid, reason_code); } void wil_priv_deinit(struct wil6210_priv *wil) Loading Loading @@ -1545,7 +1632,7 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) if (vif) { cancel_work_sync(&vif->disconnect_worker); wil6210_disconnect(vif, NULL, WLAN_REASON_DEAUTH_LEAVING, false); WLAN_REASON_DEAUTH_LEAVING); } } wil_bcast_fini_all(wil); Loading drivers/net/wireless/ath/wil6210/netdev.c +1 −1 Original line number Diff line number Diff line Loading @@ -510,7 +510,7 @@ void wil_vif_remove(struct wil6210_priv *wil, u8 mid) } mutex_lock(&wil->mutex); wil6210_disconnect(vif, NULL, WLAN_REASON_DEAUTH_LEAVING, false); wil6210_disconnect(vif, NULL, WLAN_REASON_DEAUTH_LEAVING); mutex_unlock(&wil->mutex); ndev = vif_to_ndev(vif); Loading drivers/net/wireless/ath/wil6210/txrx_edma.c +18 −36 Original line number Diff line number Diff line Loading @@ -160,7 +160,7 @@ static int wil_ring_alloc_skb_edma(struct wil6210_priv *wil, struct wil_ring *ring, u32 i) { struct device *dev = wil_to_dev(wil); unsigned int sz = ALIGN(wil->rx_buf_len, 4); unsigned int sz = wil->rx_buf_len; dma_addr_t pa; u16 buff_id; struct list_head *active = &wil->rx_buff_mgmt.active; Loading Loading @@ -234,9 +234,10 @@ static int wil_rx_refill_edma(struct wil6210_priv *wil) struct wil_ring *ring = &wil->ring_rx; u32 next_head; int rc = 0; u32 swtail = *ring->edma_rx_swtail.va; ring->swtail = *ring->edma_rx_swtail.va; for (; next_head = wil_ring_next_head(ring), (next_head != swtail); for (; next_head = wil_ring_next_head(ring), (next_head != ring->swtail); ring->swhead = next_head) { rc = wil_ring_alloc_skb_edma(wil, ring, ring->swhead); if (unlikely(rc)) { Loading Loading @@ -264,43 +265,26 @@ static void wil_move_all_rx_buff_to_free_list(struct wil6210_priv *wil, struct wil_ring *ring) { struct device *dev = wil_to_dev(wil); u32 next_tail; u32 swhead = (ring->swhead + 1) % ring->size; struct list_head *active = &wil->rx_buff_mgmt.active; dma_addr_t pa; u16 dmalen; for (; next_tail = wil_ring_next_tail(ring), (next_tail != swhead); ring->swtail = next_tail) { struct wil_rx_enhanced_desc dd, *d = ⅆ struct wil_rx_enhanced_desc *_d = (struct wil_rx_enhanced_desc *) &ring->va[ring->swtail].rx.enhanced; struct sk_buff *skb; u16 buff_id; *d = *_d; while (!list_empty(active)) { struct wil_rx_buff *rx_buff = list_first_entry(active, struct wil_rx_buff, list); struct sk_buff *skb = rx_buff->skb; /* Extract the SKB from the rx_buff management array */ buff_id = __le16_to_cpu(d->mac.buff_id); if (buff_id >= wil->rx_buff_mgmt.size) { wil_err(wil, "invalid buff_id %d\n", buff_id); continue; } skb = wil->rx_buff_mgmt.buff_arr[buff_id].skb; wil->rx_buff_mgmt.buff_arr[buff_id].skb = NULL; if (unlikely(!skb)) { wil_err(wil, "No Rx skb at buff_id %d\n", buff_id); wil_err(wil, "No Rx skb at buff_id %d\n", rx_buff->id); } else { pa = wil_rx_desc_get_addr_edma(&d->dma); dmalen = le16_to_cpu(d->dma.length); dma_unmap_single(dev, pa, dmalen, DMA_FROM_DEVICE); rx_buff->skb = NULL; memcpy(&pa, skb->cb, sizeof(pa)); dma_unmap_single(dev, pa, wil->rx_buf_len, DMA_FROM_DEVICE); kfree_skb(skb); } /* Move the buffer from the active to the free list */ list_move(&wil->rx_buff_mgmt.buff_arr[buff_id].list, &wil->rx_buff_mgmt.free); list_move(&rx_buff->list, &wil->rx_buff_mgmt.free); } } Loading Loading @@ -602,6 +586,7 @@ static bool wil_is_rx_idle_edma(struct wil6210_priv *wil) static void wil_rx_buf_len_init_edma(struct wil6210_priv *wil) { /* RX buffer size must be aligned to 4 bytes */ wil->rx_buf_len = rx_large_buf ? WIL_MAX_ETH_MTU : WIL_EDMA_RX_BUF_LEN_DEFAULT; } Loading @@ -615,7 +600,6 @@ static int wil_rx_init_edma(struct wil6210_priv *wil, uint desc_ring_order) sizeof(struct wil_rx_status_compressed) : sizeof(struct wil_rx_status_extended); int i; u16 max_rx_pl_per_desc; /* In SW reorder one must use extended status messages */ if (wil->use_compressed_rx_status && !wil->use_rx_hw_reordering) { Loading @@ -641,8 +625,6 @@ static int wil_rx_init_edma(struct wil6210_priv *wil, uint desc_ring_order) wil_rx_buf_len_init_edma(wil); max_rx_pl_per_desc = ALIGN(wil->rx_buf_len, 4); /* Use debugfs dbg_num_rx_srings if set, reserve one sring for TX */ if (wil->num_rx_status_rings > WIL6210_MAX_STATUS_RINGS - 1) wil->num_rx_status_rings = WIL6210_MAX_STATUS_RINGS - 1; Loading @@ -650,7 +632,7 @@ static int wil_rx_init_edma(struct wil6210_priv *wil, uint desc_ring_order) wil_dbg_misc(wil, "rx_init: allocate %d status rings\n", wil->num_rx_status_rings); rc = wil_wmi_cfg_def_rx_offload(wil, max_rx_pl_per_desc); rc = wil_wmi_cfg_def_rx_offload(wil, wil->rx_buf_len); if (rc) return rc; Loading Loading @@ -887,7 +869,7 @@ static struct sk_buff *wil_sring_reap_rx_edma(struct wil6210_priv *wil, struct sk_buff *skb; dma_addr_t pa; struct wil_ring_rx_data *rxdata = &sring->rx_data; unsigned int sz = ALIGN(wil->rx_buf_len, 4); unsigned int sz = wil->rx_buf_len; struct wil_net_stats *stats = NULL; u16 dmalen; int cid; Loading Loading
drivers/net/wireless/ath/wil6210/cfg80211.c +1 −1 Original line number Diff line number Diff line Loading @@ -2305,7 +2305,7 @@ static int wil_cfg80211_del_station(struct wiphy *wiphy, params->mac, params->reason_code, vif->mid); mutex_lock(&wil->mutex); wil6210_disconnect(vif, params->mac, params->reason_code, false); wil6210_disconnect(vif, params->mac, params->reason_code); mutex_unlock(&wil->mutex); return 0; Loading
drivers/net/wireless/ath/wil6210/debugfs.c +10 −5 Original line number Diff line number Diff line Loading @@ -651,10 +651,10 @@ static ssize_t wil_read_file_ioblob(struct file *file, char __user *user_buf, enum { max_count = 4096 }; struct wil_blob_wrapper *wil_blob = file->private_data; struct wil6210_priv *wil = wil_blob->wil; loff_t pos = *ppos; loff_t aligned_pos, pos = *ppos; size_t available = wil_blob->blob.size; void *buf; size_t ret; size_t unaligned_bytes, aligned_count, ret; int rc; if (test_bit(wil_status_suspending, wil_blob->wil->status) || Loading @@ -672,7 +672,12 @@ static ssize_t wil_read_file_ioblob(struct file *file, char __user *user_buf, if (count > max_count) count = max_count; buf = kmalloc(count, GFP_KERNEL); /* set pos to 4 bytes aligned */ unaligned_bytes = pos % 4; aligned_pos = pos - unaligned_bytes; aligned_count = count + unaligned_bytes; buf = kmalloc(aligned_count, GFP_KERNEL); if (!buf) return -ENOMEM; Loading @@ -683,9 +688,9 @@ static ssize_t wil_read_file_ioblob(struct file *file, char __user *user_buf, } wil_memcpy_fromio_32(buf, (const void __iomem *) wil_blob->blob.data + pos, count); wil_blob->blob.data + aligned_pos, aligned_count); ret = copy_to_user(user_buf, buf, count); ret = copy_to_user(user_buf, buf + unaligned_bytes, count); wil_pm_runtime_put(wil); Loading
drivers/net/wireless/ath/wil6210/main.c +133 −46 Original line number Diff line number Diff line Loading @@ -204,8 +204,21 @@ static void wil_ring_fini_tx(struct wil6210_priv *wil, int id) wil->txrx_ops.ring_fini_tx(wil, ring); } static void wil_disconnect_cid(struct wil6210_vif *vif, int cid, u16 reason_code, bool from_event) static bool wil_vif_is_connected(struct wil6210_priv *wil, u8 mid) { int i; for (i = 0; i < WIL6210_MAX_CID; i++) { if (wil->sta[i].mid == mid && wil->sta[i].status == wil_sta_connected) return true; } return false; } static void wil_disconnect_cid_complete(struct wil6210_vif *vif, int cid, u16 reason_code) __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) { uint i; Loading @@ -216,24 +229,14 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) int min_ring_id = wil_get_min_tx_ring_id(wil); might_sleep(); wil_dbg_misc(wil, "disconnect_cid: CID %d, MID %d, status %d\n", wil_dbg_misc(wil, "disconnect_cid_complete: CID %d, MID %d, status %d\n", cid, sta->mid, sta->status); /* inform upper/lower layers */ /* inform upper 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; wmi_disconnect_sta(vif, sta->addr, reason_code, true, del_sta); } switch (wdev->iftype) { Loading Loading @@ -274,36 +277,20 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) sta->stats.tx_latency_min_us = U32_MAX; } 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].mid == mid && wil->sta[i].status == wil_sta_connected) return true; } return false; } static void _wil6210_disconnect(struct wil6210_vif *vif, const u8 *bssid, u16 reason_code, bool from_event) static void _wil6210_disconnect_complete(struct wil6210_vif *vif, const u8 *bssid, u16 reason_code) { struct wil6210_priv *wil = vif_to_wil(vif); int cid = -ENOENT; struct net_device *ndev; struct wireless_dev *wdev; 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 ? "+" : "-"); wil_info(wil, "disconnect_complete: bssid=%pM, reason=%d\n", bssid, reason_code); /* Cases are: * - disconnect single STA, still connected Loading @@ -318,14 +305,15 @@ static void _wil6210_disconnect(struct wil6210_vif *vif, const u8 *bssid, if (bssid && !is_broadcast_ether_addr(bssid) && !ether_addr_equal_unaligned(ndev->dev_addr, bssid)) { cid = wil_find_cid(wil, vif->mid, bssid); wil_dbg_misc(wil, "Disconnect %pM, CID=%d, reason=%d\n", wil_dbg_misc(wil, "Disconnect complete %pM, CID=%d, reason=%d\n", bssid, cid, reason_code); if (cid >= 0) /* disconnect 1 peer */ wil_disconnect_cid(vif, cid, reason_code, from_event); wil_disconnect_cid_complete(vif, cid, reason_code); } else { /* all */ wil_dbg_misc(wil, "Disconnect all\n"); wil_dbg_misc(wil, "Disconnect complete all\n"); for (cid = 0; cid < WIL6210_MAX_CID; cid++) wil_disconnect_cid(vif, cid, reason_code, from_event); wil_disconnect_cid_complete(vif, cid, reason_code); } /* link state */ Loading Loading @@ -371,6 +359,84 @@ static void _wil6210_disconnect(struct wil6210_vif *vif, const u8 *bssid, } } static int wil_disconnect_cid(struct wil6210_vif *vif, int cid, u16 reason_code) { struct wil6210_priv *wil = vif_to_wil(vif); struct wireless_dev *wdev = vif_to_wdev(vif); struct wil_sta_info *sta = &wil->sta[cid]; bool del_sta = false; might_sleep(); wil_dbg_misc(wil, "disconnect_cid: CID %d, MID %d, status %d\n", cid, sta->mid, sta->status); if (sta->status == wil_sta_unused) return 0; if (vif->mid != sta->mid) { wil_err(wil, "STA MID mismatch with VIF MID(%d)\n", vif->mid); return -EINVAL; } /* inform lower layers */ if (wdev->iftype == NL80211_IFTYPE_AP && disable_ap_sme) del_sta = true; /* disconnect by sending command disconnect/del_sta and wait * synchronously for WMI_DISCONNECT_EVENTID event. */ return wmi_disconnect_sta(vif, sta->addr, reason_code, del_sta); } static void _wil6210_disconnect(struct wil6210_vif *vif, const u8 *bssid, u16 reason_code) { struct wil6210_priv *wil; struct net_device *ndev; struct wireless_dev *wdev; int cid = -ENOENT; if (unlikely(!vif)) return; wil = vif_to_wil(vif); ndev = vif_to_ndev(vif); wdev = vif_to_wdev(vif); might_sleep(); wil_info(wil, "disconnect bssid=%pM, reason=%d\n", bssid, reason_code); /* Cases are: * - disconnect single STA, still connected * - disconnect single STA, already disconnected * - disconnect all * * For "disconnect all", there are 3 options: * - bssid == NULL * - bssid is broadcast address (ff:ff:ff:ff:ff:ff) * - bssid is our MAC address */ if (bssid && !is_broadcast_ether_addr(bssid) && !ether_addr_equal_unaligned(ndev->dev_addr, 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(vif, cid, reason_code); } else { /* all */ wil_dbg_misc(wil, "Disconnect all\n"); for (cid = 0; cid < WIL6210_MAX_CID; cid++) wil_disconnect_cid(vif, cid, reason_code); } /* call event handler manually after processing wmi_call, * to avoid deadlock - disconnect event handler acquires * wil->mutex while it is already held here */ _wil6210_disconnect_complete(vif, bssid, reason_code); } void wil_disconnect_worker(struct work_struct *work) { struct wil6210_vif *vif = container_of(work, Loading Loading @@ -695,20 +761,41 @@ void wil6210_bus_request(struct wil6210_priv *wil, u32 kbps) * @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 * * Disconnect and release associated resources. If invoked not from the * FW event handler, issue WMI command(s) to trigger MAC disconnect. * Disconnect and release associated resources. Issue WMI * command(s) to trigger MAC disconnect. When command was issued * successfully, call the wil6210_disconnect_complete function * to handle the event synchronously */ void wil6210_disconnect(struct wil6210_vif *vif, const u8 *bssid, u16 reason_code, bool from_event) u16 reason_code) { struct wil6210_priv *wil = vif_to_wil(vif); wil_dbg_misc(wil, "disconnecting\n"); del_timer_sync(&vif->connect_timer); _wil6210_disconnect(vif, bssid, reason_code); } /** * wil6210_disconnect_complete - handle disconnect event * @vif: virtual interface context * @bssid: peer to disconnect, NULL to disconnect all * @reason_code: Reason code for the Disassociation frame * * Release associated resources and indicate upper layers the * connection is terminated. */ void wil6210_disconnect_complete(struct wil6210_vif *vif, const u8 *bssid, u16 reason_code) { struct wil6210_priv *wil = vif_to_wil(vif); wil_dbg_misc(wil, "disconnect\n"); wil_dbg_misc(wil, "got disconnect\n"); del_timer_sync(&vif->connect_timer); _wil6210_disconnect(vif, bssid, reason_code, from_event); _wil6210_disconnect_complete(vif, bssid, reason_code); } void wil_priv_deinit(struct wil6210_priv *wil) Loading Loading @@ -1545,7 +1632,7 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) if (vif) { cancel_work_sync(&vif->disconnect_worker); wil6210_disconnect(vif, NULL, WLAN_REASON_DEAUTH_LEAVING, false); WLAN_REASON_DEAUTH_LEAVING); } } wil_bcast_fini_all(wil); Loading
drivers/net/wireless/ath/wil6210/netdev.c +1 −1 Original line number Diff line number Diff line Loading @@ -510,7 +510,7 @@ void wil_vif_remove(struct wil6210_priv *wil, u8 mid) } mutex_lock(&wil->mutex); wil6210_disconnect(vif, NULL, WLAN_REASON_DEAUTH_LEAVING, false); wil6210_disconnect(vif, NULL, WLAN_REASON_DEAUTH_LEAVING); mutex_unlock(&wil->mutex); ndev = vif_to_ndev(vif); Loading
drivers/net/wireless/ath/wil6210/txrx_edma.c +18 −36 Original line number Diff line number Diff line Loading @@ -160,7 +160,7 @@ static int wil_ring_alloc_skb_edma(struct wil6210_priv *wil, struct wil_ring *ring, u32 i) { struct device *dev = wil_to_dev(wil); unsigned int sz = ALIGN(wil->rx_buf_len, 4); unsigned int sz = wil->rx_buf_len; dma_addr_t pa; u16 buff_id; struct list_head *active = &wil->rx_buff_mgmt.active; Loading Loading @@ -234,9 +234,10 @@ static int wil_rx_refill_edma(struct wil6210_priv *wil) struct wil_ring *ring = &wil->ring_rx; u32 next_head; int rc = 0; u32 swtail = *ring->edma_rx_swtail.va; ring->swtail = *ring->edma_rx_swtail.va; for (; next_head = wil_ring_next_head(ring), (next_head != swtail); for (; next_head = wil_ring_next_head(ring), (next_head != ring->swtail); ring->swhead = next_head) { rc = wil_ring_alloc_skb_edma(wil, ring, ring->swhead); if (unlikely(rc)) { Loading Loading @@ -264,43 +265,26 @@ static void wil_move_all_rx_buff_to_free_list(struct wil6210_priv *wil, struct wil_ring *ring) { struct device *dev = wil_to_dev(wil); u32 next_tail; u32 swhead = (ring->swhead + 1) % ring->size; struct list_head *active = &wil->rx_buff_mgmt.active; dma_addr_t pa; u16 dmalen; for (; next_tail = wil_ring_next_tail(ring), (next_tail != swhead); ring->swtail = next_tail) { struct wil_rx_enhanced_desc dd, *d = ⅆ struct wil_rx_enhanced_desc *_d = (struct wil_rx_enhanced_desc *) &ring->va[ring->swtail].rx.enhanced; struct sk_buff *skb; u16 buff_id; *d = *_d; while (!list_empty(active)) { struct wil_rx_buff *rx_buff = list_first_entry(active, struct wil_rx_buff, list); struct sk_buff *skb = rx_buff->skb; /* Extract the SKB from the rx_buff management array */ buff_id = __le16_to_cpu(d->mac.buff_id); if (buff_id >= wil->rx_buff_mgmt.size) { wil_err(wil, "invalid buff_id %d\n", buff_id); continue; } skb = wil->rx_buff_mgmt.buff_arr[buff_id].skb; wil->rx_buff_mgmt.buff_arr[buff_id].skb = NULL; if (unlikely(!skb)) { wil_err(wil, "No Rx skb at buff_id %d\n", buff_id); wil_err(wil, "No Rx skb at buff_id %d\n", rx_buff->id); } else { pa = wil_rx_desc_get_addr_edma(&d->dma); dmalen = le16_to_cpu(d->dma.length); dma_unmap_single(dev, pa, dmalen, DMA_FROM_DEVICE); rx_buff->skb = NULL; memcpy(&pa, skb->cb, sizeof(pa)); dma_unmap_single(dev, pa, wil->rx_buf_len, DMA_FROM_DEVICE); kfree_skb(skb); } /* Move the buffer from the active to the free list */ list_move(&wil->rx_buff_mgmt.buff_arr[buff_id].list, &wil->rx_buff_mgmt.free); list_move(&rx_buff->list, &wil->rx_buff_mgmt.free); } } Loading Loading @@ -602,6 +586,7 @@ static bool wil_is_rx_idle_edma(struct wil6210_priv *wil) static void wil_rx_buf_len_init_edma(struct wil6210_priv *wil) { /* RX buffer size must be aligned to 4 bytes */ wil->rx_buf_len = rx_large_buf ? WIL_MAX_ETH_MTU : WIL_EDMA_RX_BUF_LEN_DEFAULT; } Loading @@ -615,7 +600,6 @@ static int wil_rx_init_edma(struct wil6210_priv *wil, uint desc_ring_order) sizeof(struct wil_rx_status_compressed) : sizeof(struct wil_rx_status_extended); int i; u16 max_rx_pl_per_desc; /* In SW reorder one must use extended status messages */ if (wil->use_compressed_rx_status && !wil->use_rx_hw_reordering) { Loading @@ -641,8 +625,6 @@ static int wil_rx_init_edma(struct wil6210_priv *wil, uint desc_ring_order) wil_rx_buf_len_init_edma(wil); max_rx_pl_per_desc = ALIGN(wil->rx_buf_len, 4); /* Use debugfs dbg_num_rx_srings if set, reserve one sring for TX */ if (wil->num_rx_status_rings > WIL6210_MAX_STATUS_RINGS - 1) wil->num_rx_status_rings = WIL6210_MAX_STATUS_RINGS - 1; Loading @@ -650,7 +632,7 @@ static int wil_rx_init_edma(struct wil6210_priv *wil, uint desc_ring_order) wil_dbg_misc(wil, "rx_init: allocate %d status rings\n", wil->num_rx_status_rings); rc = wil_wmi_cfg_def_rx_offload(wil, max_rx_pl_per_desc); rc = wil_wmi_cfg_def_rx_offload(wil, wil->rx_buf_len); if (rc) return rc; Loading Loading @@ -887,7 +869,7 @@ static struct sk_buff *wil_sring_reap_rx_edma(struct wil6210_priv *wil, struct sk_buff *skb; dma_addr_t pa; struct wil_ring_rx_data *rxdata = &sring->rx_data; unsigned int sz = ALIGN(wil->rx_buf_len, 4); unsigned int sz = wil->rx_buf_len; struct wil_net_stats *stats = NULL; u16 dmalen; int cid; Loading