|
@@ -1,5 +1,5 @@
|
|
/*
|
|
/*
|
|
- * Copyright (c) 2012-2014 Qualcomm Atheros, Inc.
|
|
|
|
|
|
+ * Copyright (c) 2012-2015 Qualcomm Atheros, Inc.
|
|
*
|
|
*
|
|
* Permission to use, copy, modify, and/or distribute this software for any
|
|
* Permission to use, copy, modify, and/or distribute this software for any
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
@@ -724,6 +724,8 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size,
|
|
|
|
|
|
cmd.vring_cfg.tx_sw_ring.ring_mem_base = cpu_to_le64(vring->pa);
|
|
cmd.vring_cfg.tx_sw_ring.ring_mem_base = cpu_to_le64(vring->pa);
|
|
|
|
|
|
|
|
+ if (!wil->privacy)
|
|
|
|
+ txdata->dot1x_open = true;
|
|
rc = wmi_call(wil, WMI_VRING_CFG_CMDID, &cmd, sizeof(cmd),
|
|
rc = wmi_call(wil, WMI_VRING_CFG_CMDID, &cmd, sizeof(cmd),
|
|
WMI_VRING_CFG_DONE_EVENTID, &reply, sizeof(reply), 100);
|
|
WMI_VRING_CFG_DONE_EVENTID, &reply, sizeof(reply), 100);
|
|
if (rc)
|
|
if (rc)
|
|
@@ -738,11 +740,13 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size,
|
|
vring->hwtail = le32_to_cpu(reply.cmd.tx_vring_tail_ptr);
|
|
vring->hwtail = le32_to_cpu(reply.cmd.tx_vring_tail_ptr);
|
|
|
|
|
|
txdata->enabled = 1;
|
|
txdata->enabled = 1;
|
|
- if (wil->sta[cid].data_port_open && (agg_wsize >= 0))
|
|
|
|
|
|
+ if (txdata->dot1x_open && (agg_wsize >= 0))
|
|
wil_addba_tx_request(wil, id, agg_wsize);
|
|
wil_addba_tx_request(wil, id, agg_wsize);
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
out_free:
|
|
out_free:
|
|
|
|
+ txdata->dot1x_open = false;
|
|
|
|
+ txdata->enabled = 0;
|
|
wil_vring_free(wil, vring, 1);
|
|
wil_vring_free(wil, vring, 1);
|
|
out:
|
|
out:
|
|
|
|
|
|
@@ -792,6 +796,8 @@ int wil_vring_init_bcast(struct wil6210_priv *wil, int id, int size)
|
|
|
|
|
|
cmd.vring_cfg.tx_sw_ring.ring_mem_base = cpu_to_le64(vring->pa);
|
|
cmd.vring_cfg.tx_sw_ring.ring_mem_base = cpu_to_le64(vring->pa);
|
|
|
|
|
|
|
|
+ if (!wil->privacy)
|
|
|
|
+ txdata->dot1x_open = true;
|
|
rc = wmi_call(wil, WMI_BCAST_VRING_CFG_CMDID, &cmd, sizeof(cmd),
|
|
rc = wmi_call(wil, WMI_BCAST_VRING_CFG_CMDID, &cmd, sizeof(cmd),
|
|
WMI_VRING_CFG_DONE_EVENTID, &reply, sizeof(reply), 100);
|
|
WMI_VRING_CFG_DONE_EVENTID, &reply, sizeof(reply), 100);
|
|
if (rc)
|
|
if (rc)
|
|
@@ -809,6 +815,8 @@ int wil_vring_init_bcast(struct wil6210_priv *wil, int id, int size)
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
out_free:
|
|
out_free:
|
|
|
|
+ txdata->enabled = 0;
|
|
|
|
+ txdata->dot1x_open = false;
|
|
wil_vring_free(wil, vring, 1);
|
|
wil_vring_free(wil, vring, 1);
|
|
out:
|
|
out:
|
|
|
|
|
|
@@ -828,6 +836,7 @@ void wil_vring_fini_tx(struct wil6210_priv *wil, int id)
|
|
wil_dbg_misc(wil, "%s() id=%d\n", __func__, id);
|
|
wil_dbg_misc(wil, "%s() id=%d\n", __func__, id);
|
|
|
|
|
|
spin_lock_bh(&txdata->lock);
|
|
spin_lock_bh(&txdata->lock);
|
|
|
|
+ txdata->dot1x_open = false;
|
|
txdata->enabled = 0; /* no Tx can be in progress or start anew */
|
|
txdata->enabled = 0; /* no Tx can be in progress or start anew */
|
|
spin_unlock_bh(&txdata->lock);
|
|
spin_unlock_bh(&txdata->lock);
|
|
/* make sure NAPI won't touch this vring */
|
|
/* make sure NAPI won't touch this vring */
|
|
@@ -848,12 +857,11 @@ static struct vring *wil_find_tx_ucast(struct wil6210_priv *wil,
|
|
if (cid < 0)
|
|
if (cid < 0)
|
|
return NULL;
|
|
return NULL;
|
|
|
|
|
|
- if (!wil->sta[cid].data_port_open &&
|
|
|
|
- (skb->protocol != cpu_to_be16(ETH_P_PAE)))
|
|
|
|
- return NULL;
|
|
|
|
-
|
|
|
|
/* TODO: fix for multiple TID */
|
|
/* TODO: fix for multiple TID */
|
|
for (i = 0; i < ARRAY_SIZE(wil->vring2cid_tid); i++) {
|
|
for (i = 0; i < ARRAY_SIZE(wil->vring2cid_tid); i++) {
|
|
|
|
+ if (!wil->vring_tx_data[i].dot1x_open &&
|
|
|
|
+ (skb->protocol != cpu_to_be16(ETH_P_PAE)))
|
|
|
|
+ continue;
|
|
if (wil->vring2cid_tid[i][0] == cid) {
|
|
if (wil->vring2cid_tid[i][0] == cid) {
|
|
struct vring *v = &wil->vring_tx[i];
|
|
struct vring *v = &wil->vring_tx[i];
|
|
|
|
|
|
@@ -883,7 +891,7 @@ static struct vring *wil_find_tx_vring_sta(struct wil6210_priv *wil,
|
|
|
|
|
|
/* In the STA mode, it is expected to have only 1 VRING
|
|
/* In the STA mode, it is expected to have only 1 VRING
|
|
* for the AP we connected to.
|
|
* for the AP we connected to.
|
|
- * find 1-st vring and see whether it is eligible for data
|
|
|
|
|
|
+ * find 1-st vring eligible for this skb and use it.
|
|
*/
|
|
*/
|
|
for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) {
|
|
for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) {
|
|
v = &wil->vring_tx[i];
|
|
v = &wil->vring_tx[i];
|
|
@@ -894,9 +902,9 @@ static struct vring *wil_find_tx_vring_sta(struct wil6210_priv *wil,
|
|
if (cid >= WIL6210_MAX_CID) /* skip BCAST */
|
|
if (cid >= WIL6210_MAX_CID) /* skip BCAST */
|
|
continue;
|
|
continue;
|
|
|
|
|
|
- if (!wil->sta[cid].data_port_open &&
|
|
|
|
|
|
+ if (!wil->vring_tx_data[i].dot1x_open &&
|
|
(skb->protocol != cpu_to_be16(ETH_P_PAE)))
|
|
(skb->protocol != cpu_to_be16(ETH_P_PAE)))
|
|
- break;
|
|
|
|
|
|
+ continue;
|
|
|
|
|
|
wil_dbg_txrx(wil, "Tx -> ring %d\n", i);
|
|
wil_dbg_txrx(wil, "Tx -> ring %d\n", i);
|
|
|
|
|
|
@@ -918,7 +926,6 @@ static struct vring *wil_find_tx_vring_sta(struct wil6210_priv *wil,
|
|
* in all cases override dest address to unicast peer's address
|
|
* in all cases override dest address to unicast peer's address
|
|
* Use old strategy when new is not supported yet:
|
|
* Use old strategy when new is not supported yet:
|
|
* - for PBSS
|
|
* - for PBSS
|
|
- * - for secure link
|
|
|
|
*/
|
|
*/
|
|
static struct vring *wil_find_tx_bcast_1(struct wil6210_priv *wil,
|
|
static struct vring *wil_find_tx_bcast_1(struct wil6210_priv *wil,
|
|
struct sk_buff *skb)
|
|
struct sk_buff *skb)
|
|
@@ -931,6 +938,9 @@ static struct vring *wil_find_tx_bcast_1(struct wil6210_priv *wil,
|
|
v = &wil->vring_tx[i];
|
|
v = &wil->vring_tx[i];
|
|
if (!v->va)
|
|
if (!v->va)
|
|
return NULL;
|
|
return NULL;
|
|
|
|
+ if (!wil->vring_tx_data[i].dot1x_open &&
|
|
|
|
+ (skb->protocol != cpu_to_be16(ETH_P_PAE)))
|
|
|
|
+ return NULL;
|
|
|
|
|
|
return v;
|
|
return v;
|
|
}
|
|
}
|
|
@@ -963,7 +973,8 @@ static struct vring *wil_find_tx_bcast_2(struct wil6210_priv *wil,
|
|
cid = wil->vring2cid_tid[i][0];
|
|
cid = wil->vring2cid_tid[i][0];
|
|
if (cid >= WIL6210_MAX_CID) /* skip BCAST */
|
|
if (cid >= WIL6210_MAX_CID) /* skip BCAST */
|
|
continue;
|
|
continue;
|
|
- if (!wil->sta[cid].data_port_open)
|
|
|
|
|
|
+ if (!wil->vring_tx_data[i].dot1x_open &&
|
|
|
|
+ (skb->protocol != cpu_to_be16(ETH_P_PAE)))
|
|
continue;
|
|
continue;
|
|
|
|
|
|
/* don't Tx back to source when re-routing Rx->Tx at the AP */
|
|
/* don't Tx back to source when re-routing Rx->Tx at the AP */
|
|
@@ -989,7 +1000,8 @@ found:
|
|
cid = wil->vring2cid_tid[i][0];
|
|
cid = wil->vring2cid_tid[i][0];
|
|
if (cid >= WIL6210_MAX_CID) /* skip BCAST */
|
|
if (cid >= WIL6210_MAX_CID) /* skip BCAST */
|
|
continue;
|
|
continue;
|
|
- if (!wil->sta[cid].data_port_open)
|
|
|
|
|
|
+ if (!wil->vring_tx_data[i].dot1x_open &&
|
|
|
|
+ (skb->protocol != cpu_to_be16(ETH_P_PAE)))
|
|
continue;
|
|
continue;
|
|
|
|
|
|
if (0 == memcmp(wil->sta[cid].addr, src, ETH_ALEN))
|
|
if (0 == memcmp(wil->sta[cid].addr, src, ETH_ALEN))
|
|
@@ -1016,9 +1028,6 @@ static struct vring *wil_find_tx_bcast(struct wil6210_priv *wil,
|
|
if (wdev->iftype != NL80211_IFTYPE_AP)
|
|
if (wdev->iftype != NL80211_IFTYPE_AP)
|
|
return wil_find_tx_bcast_2(wil, skb);
|
|
return wil_find_tx_bcast_2(wil, skb);
|
|
|
|
|
|
- if (wil->privacy)
|
|
|
|
- return wil_find_tx_bcast_2(wil, skb);
|
|
|
|
-
|
|
|
|
return wil_find_tx_bcast_1(wil, skb);
|
|
return wil_find_tx_bcast_1(wil, skb);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1144,13 +1153,8 @@ static int __wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
|
|
wil_tx_desc_map(d, pa, len, vring_index);
|
|
wil_tx_desc_map(d, pa, len, vring_index);
|
|
if (unlikely(mcast)) {
|
|
if (unlikely(mcast)) {
|
|
d->mac.d[0] |= BIT(MAC_CFG_DESC_TX_0_MCS_EN_POS); /* MCS 0 */
|
|
d->mac.d[0] |= BIT(MAC_CFG_DESC_TX_0_MCS_EN_POS); /* MCS 0 */
|
|
- if (unlikely(len > WIL_BCAST_MCS0_LIMIT)) {
|
|
|
|
- /* set MCS 1 */
|
|
|
|
|
|
+ if (unlikely(len > WIL_BCAST_MCS0_LIMIT)) /* set MCS 1 */
|
|
d->mac.d[0] |= (1 << MAC_CFG_DESC_TX_0_MCS_INDEX_POS);
|
|
d->mac.d[0] |= (1 << MAC_CFG_DESC_TX_0_MCS_INDEX_POS);
|
|
- /* packet mode 2 */
|
|
|
|
- d->mac.d[1] |= BIT(MAC_CFG_DESC_TX_1_PKT_MODE_EN_POS) |
|
|
|
|
- (2 << MAC_CFG_DESC_TX_1_PKT_MODE_POS);
|
|
|
|
- }
|
|
|
|
}
|
|
}
|
|
/* Process TCP/UDP checksum offloading */
|
|
/* Process TCP/UDP checksum offloading */
|
|
if (unlikely(wil_tx_desc_offload_cksum_set(wil, d, skb))) {
|
|
if (unlikely(wil_tx_desc_offload_cksum_set(wil, d, skb))) {
|