Loading drivers/net/wireless/ath/wil6210/config.c +4 −0 Original line number Diff line number Diff line Loading @@ -209,6 +209,10 @@ static struct wil_config_entry config_table[] = { wil_ini_param_type_signed, &agg_wsize, 0, sizeof(agg_wsize), WIL_CONFIG_AGG_WSIZE_MIN, WIL_CONFIG_AGG_WSIZE_MAX), WIL_CONFIG_INI_PARAM(WIL_CONFIG_AC_QUEUES_NAME, wil_ini_param_type_unsigned, &ac_queues, 0, WIL_CONFIG_BOOL_SIZE, WIL_CONFIG_BOOL_MIN, WIL_CONFIG_BOOL_MAX), WIL_CONFIG_INI_PARAM(WIL_CONFIG_DROP_IF_FULL_NAME, wil_ini_param_type_unsigned, &drop_if_ring_full, 0, WIL_CONFIG_BOOL_SIZE, WIL_CONFIG_BOOL_MIN, Loading drivers/net/wireless/ath/wil6210/debugfs.c +17 −0 Original line number Diff line number Diff line Loading @@ -99,6 +99,22 @@ static void wil_print_ring(struct seq_file *s, struct wil6210_priv *wil, v = (ring_id % 2 ? (v >> 16) : (v & 0xffff)); seq_printf(s, " hwhead = %u\n", v); if (!ring->is_rx) { struct wil_ring_tx_data *txdata = &wil->ring_tx_data[ring_id]; seq_printf(s, " available = %d\n", wil_ring_avail_tx(ring) - txdata->tx_reserved_count); seq_printf(s, " used = %d\n", wil_ring_used_tx(ring)); seq_printf(s, "\n tx_res_count = %d\n", txdata->tx_reserved_count); seq_printf(s, " tx_res_count_used = %d\n", txdata->tx_reserved_count_used); seq_printf(s, " tx_res_count_unavail = %d\n", txdata->tx_reserved_count_not_avail); } } seq_printf(s, " hwtail = [0x%08x] -> ", ring->hwtail); x = wmi_addr(wil, ring->hwtail); Loading Loading @@ -2653,6 +2669,7 @@ static const struct dbg_off dbg_wil_off[] = { WIL_FIELD(amsdu_en, 0644, doff_u8), WIL_FIELD(force_edmg_channel, 0644, doff_u8), WIL_FIELD(ap_ps, 0644, doff_u8), WIL_FIELD(tx_reserved_entries, 0644, doff_u32), {}, }; Loading drivers/net/wireless/ath/wil6210/main.c +4 −0 Original line number Diff line number Diff line Loading @@ -1893,6 +1893,10 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) ftm->rx_offset); } wil->tx_reserved_entries = ((drop_if_ring_full || ac_queues) ? WIL_DEFAULT_TX_RESERVED_ENTRIES : 0); if (wil->platform_ops.notify) { rc = wil->platform_ops.notify(wil->platform_handle, WIL_PLATFORM_EVT_FW_RDY); Loading drivers/net/wireless/ath/wil6210/netdev.c +48 −2 Original line number Diff line number Diff line Loading @@ -12,10 +12,17 @@ #include "ipa.h" #include "config.h" #define WIL6210_TX_QUEUES (4) static bool alt_ifname; /* = false; */ module_param(alt_ifname, bool, 0444); MODULE_PARM_DESC(alt_ifname, " use an alternate interface name wigigN instead of wlanN"); /* enable access category for transmit packets, this parameter may be controlled * via wigig.ini config file, default enabled */ bool ac_queues = true; bool wil_has_other_active_ifaces(struct wil6210_priv *wil, struct net_device *ndev, bool up, bool ok) { Loading Loading @@ -94,10 +101,45 @@ static int wil_do_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd) return wil_ioctl(wil, ifr->ifr_data, cmd); } /** * AC to queue mapping * * AC_VO -> queue 3 * AC_VI -> queue 2 * AC_BE -> queue 1 * AC_BK -> queue 0 */ static u16 wil_select_queue(struct net_device *ndev, struct sk_buff *skb, struct net_device *sb_dev, select_queue_fallback_t fallback) { static const u16 wil_1d_to_queue[8] = {1, 0, 0, 1, 2, 2, 3, 3}; struct wil6210_priv *wil = ndev_to_wil(ndev); u16 qid; if (!ac_queues) return 0; /* determine the priority */ if (wil_is_special_packet(skb)) return 7; else if (skb->priority == 0 || skb->priority > 7) skb->priority = cfg80211_classify8021d(skb, NULL); qid = wil_1d_to_queue[skb->priority]; wil_dbg_txrx(wil, "select queue for priority %d -> queue %d\n", skb->priority, qid); return qid; } static const struct net_device_ops wil_netdev_ops = { .ndo_open = wil_open, .ndo_stop = wil_stop, .ndo_start_xmit = wil_start_xmit, .ndo_select_queue = wil_select_queue, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, .ndo_do_ioctl = wil_do_ioctl, Loading Loading @@ -336,6 +378,10 @@ wil_vif_alloc(struct wil6210_priv *wil, const char *name, return ERR_PTR(-EINVAL); } if (ac_queues) ndev = alloc_netdev_mqs(sizeof(*vif), name, name_assign_type, wil_dev_setup, WIL6210_TX_QUEUES, 1); else ndev = alloc_netdev(sizeof(*vif), name, name_assign_type, wil_dev_setup); if (!ndev) { Loading drivers/net/wireless/ath/wil6210/txrx.c +48 −7 Original line number Diff line number Diff line Loading @@ -981,7 +981,8 @@ static int wil_tx_desc_map(union wil_tx_desc *desc, dma_addr_t pa, return 0; } void wil_tx_data_init(struct wil_ring_tx_data *txdata) void wil_tx_data_init(const struct wil6210_priv *wil, struct wil_ring_tx_data *txdata) { spin_lock_bh(&txdata->lock); txdata->dot1x_open = 0; Loading @@ -994,6 +995,9 @@ void wil_tx_data_init(struct wil_ring_tx_data *txdata) txdata->agg_amsdu = 0; txdata->addba_in_progress = false; txdata->mid = U8_MAX; txdata->tx_reserved_count = wil->tx_reserved_entries; txdata->tx_reserved_count_used = 0; txdata->tx_reserved_count_not_avail = 0; spin_unlock_bh(&txdata->lock); } Loading Loading @@ -1048,7 +1052,7 @@ static int wil_vring_init_tx(struct wil6210_vif *vif, int id, int size, goto out; } wil_tx_data_init(txdata); wil_tx_data_init(wil, txdata); vring->is_rx = false; vring->size = size; rc = wil_vring_alloc(wil, vring); Loading Loading @@ -1217,7 +1221,7 @@ int wil_vring_init_bcast(struct wil6210_vif *vif, int id, int size) goto out; } wil_tx_data_init(txdata); wil_tx_data_init(wil, txdata); vring->is_rx = false; vring->size = size; rc = wil_vring_alloc(wil, vring); Loading Loading @@ -1858,6 +1862,20 @@ static int __wil_tx_vring_tso(struct wil6210_priv *wil, struct wil6210_vif *vif, return rc; } bool wil_is_special_packet(const struct sk_buff *skb) { if (skb->protocol == cpu_to_be16(ETH_P_ARP) || skb->protocol == cpu_to_be16(ETH_P_RARP) || (skb->protocol == cpu_to_be16(ETH_P_IP) && ip_hdr(skb)->protocol == IPPROTO_ICMP) || (skb->protocol == cpu_to_be16(ETH_P_IPV6) && ipv6_hdr(skb)->nexthdr == IPPROTO_ICMPV6) || skb->protocol == cpu_to_be16(ETH_P_PAE)) return true; return false; } static int __wil_tx_ring(struct wil6210_priv *wil, struct wil6210_vif *vif, struct wil_ring *ring, struct sk_buff *skb) { Loading @@ -1865,7 +1883,6 @@ static int __wil_tx_ring(struct wil6210_priv *wil, struct wil6210_vif *vif, struct vring_tx_desc dd, *d = ⅆ volatile struct vring_tx_desc *_d; u32 swhead = ring->swhead; int avail = wil_ring_avail_tx(ring); int nr_frags = skb_shinfo(skb)->nr_frags; uint f = 0; int ring_index = ring - wil->ring_tx; Loading @@ -1875,6 +1892,11 @@ static int __wil_tx_ring(struct wil6210_priv *wil, struct wil6210_vif *vif, int used; bool mcast = (ring_index == vif->bcast_ring); uint len = skb_headlen(skb); bool special_packet = (wil->tx_reserved_entries != 0 && wil_is_special_packet(skb)); int avail = wil_ring_avail_tx(ring) - (special_packet ? 0 : txdata->tx_reserved_count); u8 ctx_flags = special_packet ? WIL_CTX_FLAG_RESERVED_USED : 0; wil_dbg_txrx(wil, "tx_ring: %d bytes to ring %d, nr_frags %d\n", skb->len, ring_index, nr_frags); Loading @@ -1883,9 +1905,17 @@ static int __wil_tx_ring(struct wil6210_priv *wil, struct wil6210_vif *vif, return -EINVAL; if (unlikely(avail < 1 + nr_frags)) { if (special_packet) { txdata->tx_reserved_count_not_avail++; wil_err_ratelimited(wil, "TX ring[%2d] full. No space for %d fragments for special packet. Tx-reserved-count is %d\n", ring_index, 1 + nr_frags, txdata->tx_reserved_count); } else { wil_err_ratelimited(wil, "Tx ring[%2d] full. No space for %d fragments\n", ring_index, 1 + nr_frags); } return -ENOMEM; } _d = &ring->va[i].tx.legacy; Loading @@ -1900,6 +1930,7 @@ static int __wil_tx_ring(struct wil6210_priv *wil, struct wil6210_vif *vif, if (unlikely(dma_mapping_error(dev, pa))) return -EINVAL; ring->ctx[i].mapped_as = wil_mapped_as_single; ring->ctx[i].flags = ctx_flags; /* 1-st segment */ wil->txrx_ops.tx_desc_map((union wil_tx_desc *)d, pa, len, ring_index); Loading Loading @@ -1938,6 +1969,8 @@ static int __wil_tx_ring(struct wil6210_priv *wil, struct wil6210_vif *vif, goto dma_error; } ring->ctx[i].mapped_as = wil_mapped_as_page; ring->ctx[i].flags = ctx_flags; wil->txrx_ops.tx_desc_map((union wil_tx_desc *)d, pa, len, ring_index); /* no need to check return code - Loading Loading @@ -1970,6 +2003,14 @@ static int __wil_tx_ring(struct wil6210_priv *wil, struct wil6210_vif *vif, ring_index, used, used + nr_frags + 1); } if (special_packet) { txdata->tx_reserved_count -= (f + 1); txdata->tx_reserved_count_used += (f + 1); wil_dbg_txrx(wil, "Ring[%2d] tx_reserved_count: %d, reduced by %d\n", ring_index, txdata->tx_reserved_count, f + 1); } /* Make sure to advance the head only after descriptor update is done. * This will prevent a race condition where the completion thread * will see the DU bit set from previous run and will handle the Loading Loading
drivers/net/wireless/ath/wil6210/config.c +4 −0 Original line number Diff line number Diff line Loading @@ -209,6 +209,10 @@ static struct wil_config_entry config_table[] = { wil_ini_param_type_signed, &agg_wsize, 0, sizeof(agg_wsize), WIL_CONFIG_AGG_WSIZE_MIN, WIL_CONFIG_AGG_WSIZE_MAX), WIL_CONFIG_INI_PARAM(WIL_CONFIG_AC_QUEUES_NAME, wil_ini_param_type_unsigned, &ac_queues, 0, WIL_CONFIG_BOOL_SIZE, WIL_CONFIG_BOOL_MIN, WIL_CONFIG_BOOL_MAX), WIL_CONFIG_INI_PARAM(WIL_CONFIG_DROP_IF_FULL_NAME, wil_ini_param_type_unsigned, &drop_if_ring_full, 0, WIL_CONFIG_BOOL_SIZE, WIL_CONFIG_BOOL_MIN, Loading
drivers/net/wireless/ath/wil6210/debugfs.c +17 −0 Original line number Diff line number Diff line Loading @@ -99,6 +99,22 @@ static void wil_print_ring(struct seq_file *s, struct wil6210_priv *wil, v = (ring_id % 2 ? (v >> 16) : (v & 0xffff)); seq_printf(s, " hwhead = %u\n", v); if (!ring->is_rx) { struct wil_ring_tx_data *txdata = &wil->ring_tx_data[ring_id]; seq_printf(s, " available = %d\n", wil_ring_avail_tx(ring) - txdata->tx_reserved_count); seq_printf(s, " used = %d\n", wil_ring_used_tx(ring)); seq_printf(s, "\n tx_res_count = %d\n", txdata->tx_reserved_count); seq_printf(s, " tx_res_count_used = %d\n", txdata->tx_reserved_count_used); seq_printf(s, " tx_res_count_unavail = %d\n", txdata->tx_reserved_count_not_avail); } } seq_printf(s, " hwtail = [0x%08x] -> ", ring->hwtail); x = wmi_addr(wil, ring->hwtail); Loading Loading @@ -2653,6 +2669,7 @@ static const struct dbg_off dbg_wil_off[] = { WIL_FIELD(amsdu_en, 0644, doff_u8), WIL_FIELD(force_edmg_channel, 0644, doff_u8), WIL_FIELD(ap_ps, 0644, doff_u8), WIL_FIELD(tx_reserved_entries, 0644, doff_u32), {}, }; Loading
drivers/net/wireless/ath/wil6210/main.c +4 −0 Original line number Diff line number Diff line Loading @@ -1893,6 +1893,10 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) ftm->rx_offset); } wil->tx_reserved_entries = ((drop_if_ring_full || ac_queues) ? WIL_DEFAULT_TX_RESERVED_ENTRIES : 0); if (wil->platform_ops.notify) { rc = wil->platform_ops.notify(wil->platform_handle, WIL_PLATFORM_EVT_FW_RDY); Loading
drivers/net/wireless/ath/wil6210/netdev.c +48 −2 Original line number Diff line number Diff line Loading @@ -12,10 +12,17 @@ #include "ipa.h" #include "config.h" #define WIL6210_TX_QUEUES (4) static bool alt_ifname; /* = false; */ module_param(alt_ifname, bool, 0444); MODULE_PARM_DESC(alt_ifname, " use an alternate interface name wigigN instead of wlanN"); /* enable access category for transmit packets, this parameter may be controlled * via wigig.ini config file, default enabled */ bool ac_queues = true; bool wil_has_other_active_ifaces(struct wil6210_priv *wil, struct net_device *ndev, bool up, bool ok) { Loading Loading @@ -94,10 +101,45 @@ static int wil_do_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd) return wil_ioctl(wil, ifr->ifr_data, cmd); } /** * AC to queue mapping * * AC_VO -> queue 3 * AC_VI -> queue 2 * AC_BE -> queue 1 * AC_BK -> queue 0 */ static u16 wil_select_queue(struct net_device *ndev, struct sk_buff *skb, struct net_device *sb_dev, select_queue_fallback_t fallback) { static const u16 wil_1d_to_queue[8] = {1, 0, 0, 1, 2, 2, 3, 3}; struct wil6210_priv *wil = ndev_to_wil(ndev); u16 qid; if (!ac_queues) return 0; /* determine the priority */ if (wil_is_special_packet(skb)) return 7; else if (skb->priority == 0 || skb->priority > 7) skb->priority = cfg80211_classify8021d(skb, NULL); qid = wil_1d_to_queue[skb->priority]; wil_dbg_txrx(wil, "select queue for priority %d -> queue %d\n", skb->priority, qid); return qid; } static const struct net_device_ops wil_netdev_ops = { .ndo_open = wil_open, .ndo_stop = wil_stop, .ndo_start_xmit = wil_start_xmit, .ndo_select_queue = wil_select_queue, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, .ndo_do_ioctl = wil_do_ioctl, Loading Loading @@ -336,6 +378,10 @@ wil_vif_alloc(struct wil6210_priv *wil, const char *name, return ERR_PTR(-EINVAL); } if (ac_queues) ndev = alloc_netdev_mqs(sizeof(*vif), name, name_assign_type, wil_dev_setup, WIL6210_TX_QUEUES, 1); else ndev = alloc_netdev(sizeof(*vif), name, name_assign_type, wil_dev_setup); if (!ndev) { Loading
drivers/net/wireless/ath/wil6210/txrx.c +48 −7 Original line number Diff line number Diff line Loading @@ -981,7 +981,8 @@ static int wil_tx_desc_map(union wil_tx_desc *desc, dma_addr_t pa, return 0; } void wil_tx_data_init(struct wil_ring_tx_data *txdata) void wil_tx_data_init(const struct wil6210_priv *wil, struct wil_ring_tx_data *txdata) { spin_lock_bh(&txdata->lock); txdata->dot1x_open = 0; Loading @@ -994,6 +995,9 @@ void wil_tx_data_init(struct wil_ring_tx_data *txdata) txdata->agg_amsdu = 0; txdata->addba_in_progress = false; txdata->mid = U8_MAX; txdata->tx_reserved_count = wil->tx_reserved_entries; txdata->tx_reserved_count_used = 0; txdata->tx_reserved_count_not_avail = 0; spin_unlock_bh(&txdata->lock); } Loading Loading @@ -1048,7 +1052,7 @@ static int wil_vring_init_tx(struct wil6210_vif *vif, int id, int size, goto out; } wil_tx_data_init(txdata); wil_tx_data_init(wil, txdata); vring->is_rx = false; vring->size = size; rc = wil_vring_alloc(wil, vring); Loading Loading @@ -1217,7 +1221,7 @@ int wil_vring_init_bcast(struct wil6210_vif *vif, int id, int size) goto out; } wil_tx_data_init(txdata); wil_tx_data_init(wil, txdata); vring->is_rx = false; vring->size = size; rc = wil_vring_alloc(wil, vring); Loading Loading @@ -1858,6 +1862,20 @@ static int __wil_tx_vring_tso(struct wil6210_priv *wil, struct wil6210_vif *vif, return rc; } bool wil_is_special_packet(const struct sk_buff *skb) { if (skb->protocol == cpu_to_be16(ETH_P_ARP) || skb->protocol == cpu_to_be16(ETH_P_RARP) || (skb->protocol == cpu_to_be16(ETH_P_IP) && ip_hdr(skb)->protocol == IPPROTO_ICMP) || (skb->protocol == cpu_to_be16(ETH_P_IPV6) && ipv6_hdr(skb)->nexthdr == IPPROTO_ICMPV6) || skb->protocol == cpu_to_be16(ETH_P_PAE)) return true; return false; } static int __wil_tx_ring(struct wil6210_priv *wil, struct wil6210_vif *vif, struct wil_ring *ring, struct sk_buff *skb) { Loading @@ -1865,7 +1883,6 @@ static int __wil_tx_ring(struct wil6210_priv *wil, struct wil6210_vif *vif, struct vring_tx_desc dd, *d = ⅆ volatile struct vring_tx_desc *_d; u32 swhead = ring->swhead; int avail = wil_ring_avail_tx(ring); int nr_frags = skb_shinfo(skb)->nr_frags; uint f = 0; int ring_index = ring - wil->ring_tx; Loading @@ -1875,6 +1892,11 @@ static int __wil_tx_ring(struct wil6210_priv *wil, struct wil6210_vif *vif, int used; bool mcast = (ring_index == vif->bcast_ring); uint len = skb_headlen(skb); bool special_packet = (wil->tx_reserved_entries != 0 && wil_is_special_packet(skb)); int avail = wil_ring_avail_tx(ring) - (special_packet ? 0 : txdata->tx_reserved_count); u8 ctx_flags = special_packet ? WIL_CTX_FLAG_RESERVED_USED : 0; wil_dbg_txrx(wil, "tx_ring: %d bytes to ring %d, nr_frags %d\n", skb->len, ring_index, nr_frags); Loading @@ -1883,9 +1905,17 @@ static int __wil_tx_ring(struct wil6210_priv *wil, struct wil6210_vif *vif, return -EINVAL; if (unlikely(avail < 1 + nr_frags)) { if (special_packet) { txdata->tx_reserved_count_not_avail++; wil_err_ratelimited(wil, "TX ring[%2d] full. No space for %d fragments for special packet. Tx-reserved-count is %d\n", ring_index, 1 + nr_frags, txdata->tx_reserved_count); } else { wil_err_ratelimited(wil, "Tx ring[%2d] full. No space for %d fragments\n", ring_index, 1 + nr_frags); } return -ENOMEM; } _d = &ring->va[i].tx.legacy; Loading @@ -1900,6 +1930,7 @@ static int __wil_tx_ring(struct wil6210_priv *wil, struct wil6210_vif *vif, if (unlikely(dma_mapping_error(dev, pa))) return -EINVAL; ring->ctx[i].mapped_as = wil_mapped_as_single; ring->ctx[i].flags = ctx_flags; /* 1-st segment */ wil->txrx_ops.tx_desc_map((union wil_tx_desc *)d, pa, len, ring_index); Loading Loading @@ -1938,6 +1969,8 @@ static int __wil_tx_ring(struct wil6210_priv *wil, struct wil6210_vif *vif, goto dma_error; } ring->ctx[i].mapped_as = wil_mapped_as_page; ring->ctx[i].flags = ctx_flags; wil->txrx_ops.tx_desc_map((union wil_tx_desc *)d, pa, len, ring_index); /* no need to check return code - Loading Loading @@ -1970,6 +2003,14 @@ static int __wil_tx_ring(struct wil6210_priv *wil, struct wil6210_vif *vif, ring_index, used, used + nr_frags + 1); } if (special_packet) { txdata->tx_reserved_count -= (f + 1); txdata->tx_reserved_count_used += (f + 1); wil_dbg_txrx(wil, "Ring[%2d] tx_reserved_count: %d, reduced by %d\n", ring_index, txdata->tx_reserved_count, f + 1); } /* Make sure to advance the head only after descriptor update is done. * This will prevent a race condition where the completion thread * will see the DU bit set from previous run and will handle the Loading