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

wil6210: Block data till "data port open" reported

When connection established, as reported by WMI_CONNECT_EVENTID,
4-way handshaking required for the secure connection is not done
yet. It is indicated by another WMI event. Wait for it and only then
allow data traffic. In case of non-secure connection, FW reports
"data port open" immediately after connection.
Signed-off-by: default avatarVladimir Kondratiev <qca_vkondrat@qca.qualcomm.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent a70abea5
...@@ -631,7 +631,8 @@ static int wil_sta_debugfs_show(struct seq_file *s, void *data) ...@@ -631,7 +631,8 @@ static int wil_sta_debugfs_show(struct seq_file *s, void *data)
status = "connected"; status = "connected";
break; break;
} }
seq_printf(s, "[%d] %pM %s\n", i, p->addr, status); seq_printf(s, "[%d] %pM %s%s\n", i, p->addr, status,
(p->data_port_open ? " data_port_open" : ""));
if (p->status == wil_sta_connected) { if (p->status == wil_sta_connected) {
for (tid = 0; tid < WIL_STA_TID_NUM; tid++) { for (tid = 0; tid < WIL_STA_TID_NUM; tid++) {
......
...@@ -59,6 +59,7 @@ static void wil_disconnect_cid(struct wil6210_priv *wil, int cid) ...@@ -59,6 +59,7 @@ static void wil_disconnect_cid(struct wil6210_priv *wil, int cid)
uint i; uint i;
struct wil_sta_info *sta = &wil->sta[cid]; struct wil_sta_info *sta = &wil->sta[cid];
sta->data_port_open = false;
if (sta->status != wil_sta_unused) { if (sta->status != wil_sta_unused) {
wmi_disconnect_sta(wil, sta->addr, WLAN_REASON_DEAUTH_LEAVING); wmi_disconnect_sta(wil, sta->addr, WLAN_REASON_DEAUTH_LEAVING);
sta->status = wil_sta_unused; sta->status = wil_sta_unused;
......
...@@ -662,6 +662,10 @@ static struct vring *wil_find_tx_vring(struct wil6210_priv *wil, ...@@ -662,6 +662,10 @@ static struct vring *wil_find_tx_vring(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->vring2cid_tid[i][0] == cid) { if (wil->vring2cid_tid[i][0] == cid) {
...@@ -700,12 +704,19 @@ static struct vring *wil_tx_bcast(struct wil6210_priv *wil, ...@@ -700,12 +704,19 @@ static struct vring *wil_tx_bcast(struct wil6210_priv *wil,
struct vring *v, *v2; struct vring *v, *v2;
struct sk_buff *skb2; struct sk_buff *skb2;
int i; int i;
u8 cid;
/* find 1-st vring */ /* find 1-st vring eligible for data */
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];
if (v->va) if (!v->va)
goto found; continue;
cid = wil->vring2cid_tid[i][0];
if (!wil->sta[cid].data_port_open)
continue;
goto found;
} }
wil_err(wil, "Tx while no vrings active?\n"); wil_err(wil, "Tx while no vrings active?\n");
...@@ -721,6 +732,10 @@ static struct vring *wil_tx_bcast(struct wil6210_priv *wil, ...@@ -721,6 +732,10 @@ static struct vring *wil_tx_bcast(struct wil6210_priv *wil,
v2 = &wil->vring_tx[i]; v2 = &wil->vring_tx[i];
if (!v2->va) if (!v2->va)
continue; continue;
cid = wil->vring2cid_tid[i][0];
if (!wil->sta[cid].data_port_open)
continue;
skb2 = skb_copy(skb, GFP_ATOMIC); skb2 = skb_copy(skb, GFP_ATOMIC);
if (skb2) { if (skb2) {
wil_dbg_txrx(wil, "BCAST DUP -> ring %d\n", i); wil_dbg_txrx(wil, "BCAST DUP -> ring %d\n", i);
......
...@@ -321,6 +321,7 @@ struct wil_sta_info { ...@@ -321,6 +321,7 @@ struct wil_sta_info {
u8 addr[ETH_ALEN]; u8 addr[ETH_ALEN];
enum wil_sta_status status; enum wil_sta_status status;
struct wil_net_stats stats; struct wil_net_stats stats;
bool data_port_open; /* can send any data, not only EAPOL */
/* Rx BACK */ /* Rx BACK */
struct wil_tid_ampdu_rx *tid_rx[WIL_STA_TID_NUM]; struct wil_tid_ampdu_rx *tid_rx[WIL_STA_TID_NUM];
unsigned long tid_rx_timer_expired[BITS_TO_LONGS(WIL_STA_TID_NUM)]; unsigned long tid_rx_timer_expired[BITS_TO_LONGS(WIL_STA_TID_NUM)];
......
...@@ -550,9 +550,16 @@ static void wmi_evt_linkup(struct wil6210_priv *wil, int id, void *d, int len) ...@@ -550,9 +550,16 @@ static void wmi_evt_linkup(struct wil6210_priv *wil, int id, void *d, int len)
{ {
struct net_device *ndev = wil_to_ndev(wil); struct net_device *ndev = wil_to_ndev(wil);
struct wmi_data_port_open_event *evt = d; struct wmi_data_port_open_event *evt = d;
u8 cid = evt->cid;
wil_dbg_wmi(wil, "Link UP for CID %d\n", evt->cid); wil_dbg_wmi(wil, "Link UP for CID %d\n", cid);
if (cid >= ARRAY_SIZE(wil->sta)) {
wil_err(wil, "Link UP for invalid CID %d\n", cid);
return;
}
wil->sta[cid].data_port_open = true;
netif_carrier_on(ndev); netif_carrier_on(ndev);
} }
...@@ -560,10 +567,17 @@ static void wmi_evt_linkdown(struct wil6210_priv *wil, int id, void *d, int len) ...@@ -560,10 +567,17 @@ static void wmi_evt_linkdown(struct wil6210_priv *wil, int id, void *d, int len)
{ {
struct net_device *ndev = wil_to_ndev(wil); struct net_device *ndev = wil_to_ndev(wil);
struct wmi_wbe_link_down_event *evt = d; struct wmi_wbe_link_down_event *evt = d;
u8 cid = evt->cid;
wil_dbg_wmi(wil, "Link DOWN for CID %d, reason %d\n", wil_dbg_wmi(wil, "Link DOWN for CID %d, reason %d\n",
evt->cid, le32_to_cpu(evt->reason)); cid, le32_to_cpu(evt->reason));
if (cid >= ARRAY_SIZE(wil->sta)) {
wil_err(wil, "Link DOWN for invalid CID %d\n", cid);
return;
}
wil->sta[cid].data_port_open = false;
netif_carrier_off(ndev); netif_carrier_off(ndev);
} }
......
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