aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/wil6210
diff options
context:
space:
mode:
authorVladimir Kondratiev <qca_vkondrat@qca.qualcomm.com>2015-01-25 03:52:50 -0500
committerKalle Valo <kvalo@codeaurora.org>2015-01-29 02:55:19 -0500
commit40822a901e3c07e50fe9f6a0cbbe77cba9fbc898 (patch)
treed63ee3b7473596303d82ac158039fe7af851b2a0 /drivers/net/wireless/ath/wil6210
parent713c8a29e4d869f7ca4cadc8a6ac2c12de532ed9 (diff)
wil6210: implement cfg80211 probe_client() op
Access point require this API to check peer alive status. Assume peer is alive when it is connected, because firmware implements keep alive checks and will disconnect peer if it is not alive. Signed-off-by: Vladimir Kondratiev <qca_vkondrat@qca.qualcomm.com> Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Diffstat (limited to 'drivers/net/wireless/ath/wil6210')
-rw-r--r--drivers/net/wireless/ath/wil6210/cfg80211.c91
-rw-r--r--drivers/net/wireless/ath/wil6210/main.c5
-rw-r--r--drivers/net/wireless/ath/wil6210/wil6210.h12
3 files changed, 108 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c
index f65da91e1af8..e758f430ed82 100644
--- a/drivers/net/wireless/ath/wil6210/cfg80211.c
+++ b/drivers/net/wireless/ath/wil6210/cfg80211.c
@@ -808,6 +808,96 @@ static int wil_cfg80211_del_station(struct wiphy *wiphy,
808 return 0; 808 return 0;
809} 809}
810 810
811/* probe_client handling */
812static void wil_probe_client_handle(struct wil6210_priv *wil,
813 struct wil_probe_client_req *req)
814{
815 struct net_device *ndev = wil_to_ndev(wil);
816 struct wil_sta_info *sta = &wil->sta[req->cid];
817 /* assume STA is alive if it is still connected,
818 * else FW will disconnect it
819 */
820 bool alive = (sta->status == wil_sta_connected);
821
822 cfg80211_probe_status(ndev, sta->addr, req->cookie, alive, GFP_KERNEL);
823}
824
825static struct list_head *next_probe_client(struct wil6210_priv *wil)
826{
827 struct list_head *ret = NULL;
828
829 mutex_lock(&wil->probe_client_mutex);
830
831 if (!list_empty(&wil->probe_client_pending)) {
832 ret = wil->probe_client_pending.next;
833 list_del(ret);
834 }
835
836 mutex_unlock(&wil->probe_client_mutex);
837
838 return ret;
839}
840
841void wil_probe_client_worker(struct work_struct *work)
842{
843 struct wil6210_priv *wil = container_of(work, struct wil6210_priv,
844 probe_client_worker);
845 struct wil_probe_client_req *req;
846 struct list_head *lh;
847
848 while ((lh = next_probe_client(wil)) != NULL) {
849 req = list_entry(lh, struct wil_probe_client_req, list);
850
851 wil_probe_client_handle(wil, req);
852 kfree(req);
853 }
854}
855
856void wil_probe_client_flush(struct wil6210_priv *wil)
857{
858 struct wil_probe_client_req *req, *t;
859
860 wil_dbg_misc(wil, "%s()\n", __func__);
861
862 mutex_lock(&wil->probe_client_mutex);
863
864 list_for_each_entry_safe(req, t, &wil->probe_client_pending, list) {
865 list_del(&req->list);
866 kfree(req);
867 }
868
869 mutex_unlock(&wil->probe_client_mutex);
870}
871
872static int wil_cfg80211_probe_client(struct wiphy *wiphy,
873 struct net_device *dev,
874 const u8 *peer, u64 *cookie)
875{
876 struct wil6210_priv *wil = wiphy_to_wil(wiphy);
877 struct wil_probe_client_req *req;
878 int cid = wil_find_cid(wil, peer);
879
880 wil_dbg_misc(wil, "%s(%pM => CID %d)\n", __func__, peer, cid);
881
882 if (cid < 0)
883 return -ENOLINK;
884
885 req = kzalloc(sizeof(*req), GFP_KERNEL);
886 if (!req)
887 return -ENOMEM;
888
889 req->cid = cid;
890 req->cookie = cid;
891
892 mutex_lock(&wil->probe_client_mutex);
893 list_add_tail(&req->list, &wil->probe_client_pending);
894 mutex_unlock(&wil->probe_client_mutex);
895
896 *cookie = req->cookie;
897 queue_work(wil->wq_service, &wil->probe_client_worker);
898 return 0;
899}
900
811static struct cfg80211_ops wil_cfg80211_ops = { 901static struct cfg80211_ops wil_cfg80211_ops = {
812 .scan = wil_cfg80211_scan, 902 .scan = wil_cfg80211_scan,
813 .connect = wil_cfg80211_connect, 903 .connect = wil_cfg80211_connect,
@@ -827,6 +917,7 @@ static struct cfg80211_ops wil_cfg80211_ops = {
827 .start_ap = wil_cfg80211_start_ap, 917 .start_ap = wil_cfg80211_start_ap,
828 .stop_ap = wil_cfg80211_stop_ap, 918 .stop_ap = wil_cfg80211_stop_ap,
829 .del_station = wil_cfg80211_del_station, 919 .del_station = wil_cfg80211_del_station,
920 .probe_client = wil_cfg80211_probe_client,
830}; 921};
831 922
832static void wil_wiphy_init(struct wiphy *wiphy) 923static void wil_wiphy_init(struct wiphy *wiphy)
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c
index d25941696026..b04e0afdcb21 100644
--- a/drivers/net/wireless/ath/wil6210/main.c
+++ b/drivers/net/wireless/ath/wil6210/main.c
@@ -405,6 +405,7 @@ int wil_priv_init(struct wil6210_priv *wil)
405 mutex_init(&wil->wmi_mutex); 405 mutex_init(&wil->wmi_mutex);
406 mutex_init(&wil->back_rx_mutex); 406 mutex_init(&wil->back_rx_mutex);
407 mutex_init(&wil->back_tx_mutex); 407 mutex_init(&wil->back_tx_mutex);
408 mutex_init(&wil->probe_client_mutex);
408 409
409 init_completion(&wil->wmi_ready); 410 init_completion(&wil->wmi_ready);
410 init_completion(&wil->wmi_call); 411 init_completion(&wil->wmi_call);
@@ -419,10 +420,12 @@ int wil_priv_init(struct wil6210_priv *wil)
419 INIT_WORK(&wil->fw_error_worker, wil_fw_error_worker); 420 INIT_WORK(&wil->fw_error_worker, wil_fw_error_worker);
420 INIT_WORK(&wil->back_rx_worker, wil_back_rx_worker); 421 INIT_WORK(&wil->back_rx_worker, wil_back_rx_worker);
421 INIT_WORK(&wil->back_tx_worker, wil_back_tx_worker); 422 INIT_WORK(&wil->back_tx_worker, wil_back_tx_worker);
423 INIT_WORK(&wil->probe_client_worker, wil_probe_client_worker);
422 424
423 INIT_LIST_HEAD(&wil->pending_wmi_ev); 425 INIT_LIST_HEAD(&wil->pending_wmi_ev);
424 INIT_LIST_HEAD(&wil->back_rx_pending); 426 INIT_LIST_HEAD(&wil->back_rx_pending);
425 INIT_LIST_HEAD(&wil->back_tx_pending); 427 INIT_LIST_HEAD(&wil->back_tx_pending);
428 INIT_LIST_HEAD(&wil->probe_client_pending);
426 spin_lock_init(&wil->wmi_ev_lock); 429 spin_lock_init(&wil->wmi_ev_lock);
427 init_waitqueue_head(&wil->wq); 430 init_waitqueue_head(&wil->wq);
428 431
@@ -485,6 +488,8 @@ void wil_priv_deinit(struct wil6210_priv *wil)
485 cancel_work_sync(&wil->back_rx_worker); 488 cancel_work_sync(&wil->back_rx_worker);
486 wil_back_tx_flush(wil); 489 wil_back_tx_flush(wil);
487 cancel_work_sync(&wil->back_tx_worker); 490 cancel_work_sync(&wil->back_tx_worker);
491 wil_probe_client_flush(wil);
492 cancel_work_sync(&wil->probe_client_worker);
488 destroy_workqueue(wil->wq_service); 493 destroy_workqueue(wil->wq_service);
489 destroy_workqueue(wil->wmi_wq); 494 destroy_workqueue(wil->wmi_wq);
490} 495}
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h
index 3575b5d424a4..90dc24fb60f8 100644
--- a/drivers/net/wireless/ath/wil6210/wil6210.h
+++ b/drivers/net/wireless/ath/wil6210/wil6210.h
@@ -504,6 +504,12 @@ struct wil_back_tx {
504 u16 agg_timeout; 504 u16 agg_timeout;
505}; 505};
506 506
507struct wil_probe_client_req {
508 struct list_head list;
509 u64 cookie;
510 u8 cid;
511};
512
507struct wil6210_priv { 513struct wil6210_priv {
508 struct pci_dev *pdev; 514 struct pci_dev *pdev;
509 int n_msi; 515 int n_msi;
@@ -564,6 +570,10 @@ struct wil6210_priv {
564 struct list_head back_tx_pending; 570 struct list_head back_tx_pending;
565 struct mutex back_tx_mutex; /* protect @back_tx_pending */ 571 struct mutex back_tx_mutex; /* protect @back_tx_pending */
566 struct work_struct back_tx_worker; 572 struct work_struct back_tx_worker;
573 /* keep alive */
574 struct list_head probe_client_pending;
575 struct mutex probe_client_mutex; /* protect @probe_client_pending */
576 struct work_struct probe_client_worker;
567 /* DMA related */ 577 /* DMA related */
568 struct vring vring_rx; 578 struct vring vring_rx;
569 struct vring vring_tx[WIL6210_MAX_TX_RINGS]; 579 struct vring vring_tx[WIL6210_MAX_TX_RINGS];
@@ -722,6 +732,8 @@ int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, u8 chan);
722int wmi_pcp_stop(struct wil6210_priv *wil); 732int wmi_pcp_stop(struct wil6210_priv *wil);
723void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid, 733void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid,
724 u16 reason_code, bool from_event); 734 u16 reason_code, bool from_event);
735void wil_probe_client_flush(struct wil6210_priv *wil);
736void wil_probe_client_worker(struct work_struct *work);
725 737
726int wil_rx_init(struct wil6210_priv *wil, u16 size); 738int wil_rx_init(struct wil6210_priv *wil, u16 size);
727void wil_rx_fini(struct wil6210_priv *wil); 739void wil_rx_fini(struct wil6210_priv *wil);