diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index 48d97156f3db39e919a0fad86e5ad15c23e5a5ff..5ff59ee9c9f6c2988ba8ddf552e3967eccbd4d53 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c @@ -662,6 +662,60 @@ static struct vring *wil_find_tx_vring(struct wil6210_priv *wil, return NULL; } +static void wil_set_da_for_vring(struct wil6210_priv *wil, + struct sk_buff *skb, int vring_index) +{ + struct ethhdr *eth = (void *)skb->data; + int cid = wil->vring2cid_tid[vring_index][0]; + memcpy(eth->h_dest, wil->sta[cid].addr, ETH_ALEN); +} + +static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, + struct sk_buff *skb); +/* + * Find 1-st vring and return it; set dest address for this vring in skb + * duplicate skb and send it to other active vrings + */ +static struct vring *wil_tx_bcast(struct wil6210_priv *wil, + struct sk_buff *skb) +{ + struct vring *v, *v2; + struct sk_buff *skb2; + int i; + + /* find 1-st vring */ + for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) { + v = &wil->vring_tx[i]; + if (v->va) + goto found; + } + + wil_err(wil, "Tx while no vrings active?\n"); + + return NULL; + +found: + wil_dbg_txrx(wil, "BCAST -> ring %d\n", i); + wil_set_da_for_vring(wil, skb, i); + + /* 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) + continue; + skb2 = skb_copy(skb, GFP_ATOMIC); + 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); + } else { + wil_err(wil, "skb_copy failed\n"); + } + } + + return v; +} + static int wil_tx_desc_map(struct vring_tx_desc *d, dma_addr_t pa, u32 len, int vring_index) { @@ -875,16 +929,7 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev) if (is_unicast_ether_addr(eth->h_dest)) { vring = wil_find_tx_vring(wil, skb); } else { - int i = 0; - /* TODO: duplicate for all CID's */ - vring = &wil->vring_tx[i]; - if (vring->va) { - int cid = wil->vring2cid_tid[i][0]; - /* FIXME FW can accept only unicast frames */ - memcpy(skb->data, wil->sta[cid].addr, ETH_ALEN); - } else { - vring = NULL; - } + vring = wil_tx_bcast(wil, skb); } if (!vring) { wil_err(wil, "No Tx VRING found for %pM\n", eth->h_dest);