aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVladimir Kondratiev <qca_vkondrat@qca.qualcomm.com>2014-12-23 02:47:04 -0500
committerKalle Valo <kvalo@codeaurora.org>2015-01-15 07:30:55 -0500
commit3a124ed6454a939277c6b51bea542464be43ef6f (patch)
tree58b2f34badd46c1e082761513c07ef453ce27e5f
parent3277213feb1b6625e4d7ad9eef1778dc88cdf46f (diff)
wil6210: simple ADDBA on originator (Tx) side
Upon Tx vring creation, initiate BACK establishment with maximum possible window size. When establishing secure connection, there is EAPOL data exchange between connection itself and "data port open", where security is done and non-EAPOL data may be transferred. It is better to send EAPOL frames using normal ACK because of firmware considerations. send ADDBA only is 2 conditions met: - data port open for the corresponded STA - vring created Signed-off-by: Vladimir Kondratiev <qca_vkondrat@qca.qualcomm.com> Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
-rw-r--r--drivers/net/wireless/ath/wil6210/main.c5
-rw-r--r--drivers/net/wireless/ath/wil6210/rx_reorder.c91
-rw-r--r--drivers/net/wireless/ath/wil6210/txrx.c4
-rw-r--r--drivers/net/wireless/ath/wil6210/wil6210.h15
-rw-r--r--drivers/net/wireless/ath/wil6210/wmi.c19
5 files changed, 134 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c
index 9b402b94bfa5..42e119242107 100644
--- a/drivers/net/wireless/ath/wil6210/main.c
+++ b/drivers/net/wireless/ath/wil6210/main.c
@@ -385,6 +385,7 @@ int wil_priv_init(struct wil6210_priv *wil)
385 mutex_init(&wil->mutex); 385 mutex_init(&wil->mutex);
386 mutex_init(&wil->wmi_mutex); 386 mutex_init(&wil->wmi_mutex);
387 mutex_init(&wil->back_rx_mutex); 387 mutex_init(&wil->back_rx_mutex);
388 mutex_init(&wil->back_tx_mutex);
388 389
389 init_completion(&wil->wmi_ready); 390 init_completion(&wil->wmi_ready);
390 init_completion(&wil->wmi_call); 391 init_completion(&wil->wmi_call);
@@ -398,9 +399,11 @@ int wil_priv_init(struct wil6210_priv *wil)
398 INIT_WORK(&wil->wmi_event_worker, wmi_event_worker); 399 INIT_WORK(&wil->wmi_event_worker, wmi_event_worker);
399 INIT_WORK(&wil->fw_error_worker, wil_fw_error_worker); 400 INIT_WORK(&wil->fw_error_worker, wil_fw_error_worker);
400 INIT_WORK(&wil->back_rx_worker, wil_back_rx_worker); 401 INIT_WORK(&wil->back_rx_worker, wil_back_rx_worker);
402 INIT_WORK(&wil->back_tx_worker, wil_back_tx_worker);
401 403
402 INIT_LIST_HEAD(&wil->pending_wmi_ev); 404 INIT_LIST_HEAD(&wil->pending_wmi_ev);
403 INIT_LIST_HEAD(&wil->back_rx_pending); 405 INIT_LIST_HEAD(&wil->back_rx_pending);
406 INIT_LIST_HEAD(&wil->back_tx_pending);
404 spin_lock_init(&wil->wmi_ev_lock); 407 spin_lock_init(&wil->wmi_ev_lock);
405 init_waitqueue_head(&wil->wq); 408 init_waitqueue_head(&wil->wq);
406 409
@@ -456,6 +459,8 @@ void wil_priv_deinit(struct wil6210_priv *wil)
456 wmi_event_flush(wil); 459 wmi_event_flush(wil);
457 wil_back_rx_flush(wil); 460 wil_back_rx_flush(wil);
458 cancel_work_sync(&wil->back_rx_worker); 461 cancel_work_sync(&wil->back_rx_worker);
462 wil_back_tx_flush(wil);
463 cancel_work_sync(&wil->back_tx_worker);
459 destroy_workqueue(wil->wq_service); 464 destroy_workqueue(wil->wq_service);
460 destroy_workqueue(wil->wmi_wq); 465 destroy_workqueue(wil->wmi_wq);
461} 466}
diff --git a/drivers/net/wireless/ath/wil6210/rx_reorder.c b/drivers/net/wireless/ath/wil6210/rx_reorder.c
index 8e6d25a9f223..ce1206aff5e5 100644
--- a/drivers/net/wireless/ath/wil6210/rx_reorder.c
+++ b/drivers/net/wireless/ath/wil6210/rx_reorder.c
@@ -365,3 +365,94 @@ void wil_back_rx_worker(struct work_struct *work)
365 kfree(evt); 365 kfree(evt);
366 } 366 }
367} 367}
368
369/* BACK - Tx (originator) side */
370static void wil_back_tx_handle(struct wil6210_priv *wil,
371 struct wil_back_tx *req)
372{
373 struct vring_tx_data *txdata = &wil->vring_tx_data[req->ringid];
374 int rc;
375
376 if (txdata->addba_in_progress) {
377 wil_dbg_misc(wil, "ADDBA for vring[%d] already in progress\n",
378 req->ringid);
379 return;
380 }
381 if (txdata->agg_wsize) {
382 wil_dbg_misc(wil,
383 "ADDBA for vring[%d] already established wsize %d\n",
384 req->ringid, txdata->agg_wsize);
385 return;
386 }
387 txdata->addba_in_progress = true;
388 rc = wmi_addba(wil, req->ringid, req->agg_wsize, req->agg_timeout);
389 if (rc)
390 txdata->addba_in_progress = false;
391}
392
393static struct list_head *next_back_tx(struct wil6210_priv *wil)
394{
395 struct list_head *ret = NULL;
396
397 mutex_lock(&wil->back_tx_mutex);
398
399 if (!list_empty(&wil->back_tx_pending)) {
400 ret = wil->back_tx_pending.next;
401 list_del(ret);
402 }
403
404 mutex_unlock(&wil->back_tx_mutex);
405
406 return ret;
407}
408
409void wil_back_tx_worker(struct work_struct *work)
410{
411 struct wil6210_priv *wil = container_of(work, struct wil6210_priv,
412 back_tx_worker);
413 struct wil_back_tx *evt;
414 struct list_head *lh;
415
416 while ((lh = next_back_tx(wil)) != NULL) {
417 evt = list_entry(lh, struct wil_back_tx, list);
418
419 wil_back_tx_handle(wil, evt);
420 kfree(evt);
421 }
422}
423
424void wil_back_tx_flush(struct wil6210_priv *wil)
425{
426 struct wil_back_tx *evt, *t;
427
428 wil_dbg_misc(wil, "%s()\n", __func__);
429
430 mutex_lock(&wil->back_tx_mutex);
431
432 list_for_each_entry_safe(evt, t, &wil->back_tx_pending, list) {
433 list_del(&evt->list);
434 kfree(evt);
435 }
436
437 mutex_unlock(&wil->back_tx_mutex);
438}
439
440int wil_addba_tx_request(struct wil6210_priv *wil, u8 ringid)
441{
442 struct wil_back_tx *req = kzalloc(sizeof(*req), GFP_KERNEL);
443
444 if (!req)
445 return -ENOMEM;
446
447 req->ringid = ringid;
448 req->agg_wsize = wil_agg_size(wil, 0);
449 req->agg_timeout = 0;
450
451 mutex_lock(&wil->back_tx_mutex);
452 list_add_tail(&req->list, &wil->back_tx_pending);
453 mutex_unlock(&wil->back_tx_mutex);
454
455 queue_work(wil->wq_service, &wil->back_tx_worker);
456
457 return 0;
458}
diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c
index d9268608f113..71eaeec50639 100644
--- a/drivers/net/wireless/ath/wil6210/txrx.c
+++ b/drivers/net/wireless/ath/wil6210/txrx.c
@@ -701,6 +701,8 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size,
701 vring->hwtail = le32_to_cpu(reply.cmd.tx_vring_tail_ptr); 701 vring->hwtail = le32_to_cpu(reply.cmd.tx_vring_tail_ptr);
702 702
703 txdata->enabled = 1; 703 txdata->enabled = 1;
704 if (wil->sta[cid].data_port_open)
705 wil_addba_tx_request(wil, id);
704 706
705 return 0; 707 return 0;
706 out_free: 708 out_free:
@@ -713,6 +715,7 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size,
713void wil_vring_fini_tx(struct wil6210_priv *wil, int id) 715void wil_vring_fini_tx(struct wil6210_priv *wil, int id)
714{ 716{
715 struct vring *vring = &wil->vring_tx[id]; 717 struct vring *vring = &wil->vring_tx[id];
718 struct vring_tx_data *txdata = &wil->vring_tx_data[id];
716 719
717 WARN_ON(!mutex_is_locked(&wil->mutex)); 720 WARN_ON(!mutex_is_locked(&wil->mutex));
718 721
@@ -727,6 +730,7 @@ void wil_vring_fini_tx(struct wil6210_priv *wil, int id)
727 napi_synchronize(&wil->napi_tx); 730 napi_synchronize(&wil->napi_tx);
728 731
729 wil_vring_free(wil, vring, 1); 732 wil_vring_free(wil, vring, 1);
733 memset(txdata, 0, sizeof(*txdata));
730} 734}
731 735
732static struct vring *wil_find_tx_vring(struct wil6210_priv *wil, 736static struct vring *wil_find_tx_vring(struct wil6210_priv *wil,
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h
index 4a9a68e7a007..9cd76da3738d 100644
--- a/drivers/net/wireless/ath/wil6210/wil6210.h
+++ b/drivers/net/wireless/ath/wil6210/wil6210.h
@@ -314,6 +314,7 @@ struct vring_tx_data {
314 cycles_t idle, last_idle, begin; 314 cycles_t idle, last_idle, begin;
315 u8 agg_wsize; /* agreed aggregation window, 0 - no agg */ 315 u8 agg_wsize; /* agreed aggregation window, 0 - no agg */
316 u16 agg_timeout; 316 u16 agg_timeout;
317 bool addba_in_progress; /* if set, agg_xxx is for request in progress */
317}; 318};
318 319
319enum { /* for wil6210_priv.status */ 320enum { /* for wil6210_priv.status */
@@ -418,6 +419,14 @@ struct wil_back_rx {
418 u16 ba_seq_ctrl; 419 u16 ba_seq_ctrl;
419}; 420};
420 421
422struct wil_back_tx {
423 struct list_head list;
424 /* request params, converted to CPU byte order - what we asked for */
425 u8 ringid;
426 u8 agg_wsize;
427 u16 agg_timeout;
428};
429
421struct wil6210_priv { 430struct wil6210_priv {
422 struct pci_dev *pdev; 431 struct pci_dev *pdev;
423 int n_msi; 432 int n_msi;
@@ -470,6 +479,9 @@ struct wil6210_priv {
470 struct list_head back_rx_pending; 479 struct list_head back_rx_pending;
471 struct mutex back_rx_mutex; /* protect @back_rx_pending */ 480 struct mutex back_rx_mutex; /* protect @back_rx_pending */
472 struct work_struct back_rx_worker; 481 struct work_struct back_rx_worker;
482 struct list_head back_tx_pending;
483 struct mutex back_tx_mutex; /* protect @back_tx_pending */
484 struct work_struct back_tx_worker;
473 /* DMA related */ 485 /* DMA related */
474 struct vring vring_rx; 486 struct vring vring_rx;
475 struct vring vring_tx[WIL6210_MAX_TX_RINGS]; 487 struct vring vring_tx[WIL6210_MAX_TX_RINGS];
@@ -601,6 +613,9 @@ int wil_addba_rx_request(struct wil6210_priv *wil, u8 cidxtid,
601 __le16 ba_timeout, __le16 ba_seq_ctrl); 613 __le16 ba_timeout, __le16 ba_seq_ctrl);
602void wil_back_rx_worker(struct work_struct *work); 614void wil_back_rx_worker(struct work_struct *work);
603void wil_back_rx_flush(struct wil6210_priv *wil); 615void wil_back_rx_flush(struct wil6210_priv *wil);
616int wil_addba_tx_request(struct wil6210_priv *wil, u8 ringid);
617void wil_back_tx_worker(struct work_struct *work);
618void wil_back_tx_flush(struct wil6210_priv *wil);
604 619
605void wil6210_clear_irq(struct wil6210_priv *wil); 620void wil6210_clear_irq(struct wil6210_priv *wil);
606int wil6210_init_irq(struct wil6210_priv *wil, int irq); 621int wil6210_init_irq(struct wil6210_priv *wil, int irq);
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c
index e790c45c3c68..8a4f8b7243e0 100644
--- a/drivers/net/wireless/ath/wil6210/wmi.c
+++ b/drivers/net/wireless/ath/wil6210/wmi.c
@@ -544,6 +544,22 @@ static void wmi_evt_eapol_rx(struct wil6210_priv *wil, int id,
544 } 544 }
545} 545}
546 546
547static void wil_addba_tx_cid(struct wil6210_priv *wil, u8 cid)
548{
549 struct vring_tx_data *t;
550 int i;
551
552 for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) {
553 if (cid != wil->vring2cid_tid[i][0])
554 continue;
555 t = &wil->vring_tx_data[i];
556 if (!t->enabled)
557 continue;
558
559 wil_addba_tx_request(wil, i);
560 }
561}
562
547static void wmi_evt_linkup(struct wil6210_priv *wil, int id, void *d, int len) 563static void wmi_evt_linkup(struct wil6210_priv *wil, int id, void *d, int len)
548{ 564{
549 struct net_device *ndev = wil_to_ndev(wil); 565 struct net_device *ndev = wil_to_ndev(wil);
@@ -558,6 +574,7 @@ static void wmi_evt_linkup(struct wil6210_priv *wil, int id, void *d, int len)
558 } 574 }
559 575
560 wil->sta[cid].data_port_open = true; 576 wil->sta[cid].data_port_open = true;
577 wil_addba_tx_cid(wil, cid);
561 netif_carrier_on(ndev); 578 netif_carrier_on(ndev);
562} 579}
563 580
@@ -604,6 +621,7 @@ static void wmi_evt_ba_status(struct wil6210_priv *wil, int id, void *d,
604 621
605 txdata->agg_timeout = le16_to_cpu(evt->ba_timeout); 622 txdata->agg_timeout = le16_to_cpu(evt->ba_timeout);
606 txdata->agg_wsize = evt->agg_wsize; 623 txdata->agg_wsize = evt->agg_wsize;
624 txdata->addba_in_progress = false;
607} 625}
608 626
609static void wmi_evt_addba_rx_req(struct wil6210_priv *wil, int id, void *d, 627static void wmi_evt_addba_rx_req(struct wil6210_priv *wil, int id, void *d,
@@ -642,6 +660,7 @@ static void wmi_evt_delba(struct wil6210_priv *wil, int id, void *d, int len)
642 wil_dbg_wmi(wil, "DELBA Tx vring %d\n", i); 660 wil_dbg_wmi(wil, "DELBA Tx vring %d\n", i);
643 txdata->agg_timeout = 0; 661 txdata->agg_timeout = 0;
644 txdata->agg_wsize = 0; 662 txdata->agg_wsize = 0;
663 txdata->addba_in_progress = false;
645 664
646 break; /* max. 1 matching ring */ 665 break; /* max. 1 matching ring */
647 } 666 }