]> git.openfabrics.org - ~emulex/infiniband.git/commitdiff
wil6210: Block data till "data port open" reported
authorVladimir Kondratiev <qca_vkondrat@qca.qualcomm.com>
Mon, 17 Mar 2014 13:34:06 +0000 (15:34 +0200)
committerJohn W. Linville <linville@tuxdriver.com>
Mon, 17 Mar 2014 17:44:16 +0000 (13:44 -0400)
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: Vladimir Kondratiev <qca_vkondrat@qca.qualcomm.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/ath/wil6210/debugfs.c
drivers/net/wireless/ath/wil6210/main.c
drivers/net/wireless/ath/wil6210/txrx.c
drivers/net/wireless/ath/wil6210/wil6210.h
drivers/net/wireless/ath/wil6210/wmi.c

index 1d09a4b0a0f45fee3c8aeebc493870d86501628c..ea868bea9e2ec7aa358741e0306b0a1c4b1ff005 100644 (file)
@@ -631,7 +631,8 @@ static int wil_sta_debugfs_show(struct seq_file *s, void *data)
                        status = "connected";
                        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) {
                        for (tid = 0; tid < WIL_STA_TID_NUM; tid++) {
index 41c362dee0329a5934df1f39c8ecb06d808fded3..f10a0b2a99b2aeeac10cc4a52c9834e23769d096 100644 (file)
@@ -59,6 +59,7 @@ static void wil_disconnect_cid(struct wil6210_priv *wil, int cid)
        uint i;
        struct wil_sta_info *sta = &wil->sta[cid];
 
+       sta->data_port_open = false;
        if (sta->status != wil_sta_unused) {
                wmi_disconnect_sta(wil, sta->addr, WLAN_REASON_DEAUTH_LEAVING);
                sta->status = wil_sta_unused;
index 7afaa5e5c42e438f7bb1fcd07469e4ca67cd37e0..29f13e01b99e5fac498c01182584c3aa8792de63 100644 (file)
@@ -662,6 +662,10 @@ static struct vring *wil_find_tx_vring(struct wil6210_priv *wil,
        if (cid < 0)
                return NULL;
 
+       if (!wil->sta[cid].data_port_open &&
+           (skb->protocol != cpu_to_be16(ETH_P_PAE)))
+               return NULL;
+
        /* TODO: fix for multiple TID */
        for (i = 0; i < ARRAY_SIZE(wil->vring2cid_tid); i++) {
                if (wil->vring2cid_tid[i][0] == cid) {
@@ -700,12 +704,19 @@ static struct vring *wil_tx_bcast(struct wil6210_priv *wil,
        struct vring *v, *v2;
        struct sk_buff *skb2;
        int i;
+       u8 cid;
 
-       /* find 1-st vring */
+       /* find 1-st vring eligible for data */
        for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) {
                v = &wil->vring_tx[i];
-               if (v->va)
-                       goto found;
+               if (!v->va)
+                       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");
@@ -721,6 +732,10 @@ found:
                v2 = &wil->vring_tx[i];
                if (!v2->va)
                        continue;
+               cid = wil->vring2cid_tid[i][0];
+               if (!wil->sta[cid].data_port_open)
+                       continue;
+
                skb2 = skb_copy(skb, GFP_ATOMIC);
                if (skb2) {
                        wil_dbg_txrx(wil, "BCAST DUP -> ring %d\n", i);
index 273d00f86130ac22fc51ea4d7268dbb66ea80b56..f06f717569963df833d90aec4730d27987c11b35 100644 (file)
@@ -321,6 +321,7 @@ struct wil_sta_info {
        u8 addr[ETH_ALEN];
        enum wil_sta_status status;
        struct wil_net_stats stats;
+       bool data_port_open; /* can send any data, not only EAPOL */
        /* Rx BACK */
        struct wil_tid_ampdu_rx *tid_rx[WIL_STA_TID_NUM];
        unsigned long tid_rx_timer_expired[BITS_TO_LONGS(WIL_STA_TID_NUM)];
index 24eed096358104e7c4f4f346bb0efc1bf3066953..58c3afcf839dd29d0626cc1fcee091b7ad422db6 100644 (file)
@@ -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 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);
 }
 
@@ -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 wmi_wbe_link_down_event *evt = d;
+       u8 cid = evt->cid;
 
        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);
 }