Commit fb3cac57 authored by Vladimir Kondratiev's avatar Vladimir Kondratiev Committed by John W. Linville

wil6210: broadcast Tx

Hardware do not support "real" broadcast on the air.
Use method similar to the Directed Multicast Service (DMS) as
described in the 10.23.15.2 "DMS procedures"

This service copies frame and delivers unicast for each associated peer

Do the following: send original frame to 1-st Tx vring, and send copies
to all other active vrings.

As currently hardware/firmware don't support A-MSDU, convert broadcast
frame to unicast instead of wrapping it in A-MSDU
Signed-off-by: default avatarVladimir Kondratiev <qca_vkondrat@qca.qualcomm.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 9a177384
......@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment