Skip to content

Commit 5545b7b

Browse files
Haijun Liudavem330
authored andcommitted
net: wwan: t7xx: Add NAPI support
Replace the work queue based RX flow with a NAPI implementation Remove rx_thread and dpmaif_rxq_work. Enable GRO on RX path. Introduce dummy network device. its responsibility is - Binds one NAPI object for each DL HW queue and acts as the agent of all those network devices. - Use NAPI object to poll DL packets. - Helps to dispatch each packet to the network interface. Signed-off-by: Haijun Liu <[email protected]> Co-developed-by: Sreehari Kancharla <[email protected]> Signed-off-by: Sreehari Kancharla <[email protected]> Signed-off-by: Chandrashekar Devegowda <[email protected]> Acked-by: Ricardo Martinez <[email protected]> Acked-by: M Chetan Kumar <[email protected]> Reviewed-by: Ilpo Järvinen <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent c053d7b commit 5545b7b

File tree

5 files changed

+161
-166
lines changed

5 files changed

+161
-166
lines changed

drivers/net/wwan/t7xx/t7xx_hif_dpmaif.h

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
#include <linux/bitmap.h>
2222
#include <linux/mm_types.h>
23+
#include <linux/netdevice.h>
2324
#include <linux/sched.h>
2425
#include <linux/skbuff.h>
2526
#include <linux/spinlock.h>
@@ -109,20 +110,14 @@ struct dpmaif_rx_queue {
109110
struct dpmaif_bat_request *bat_req;
110111
struct dpmaif_bat_request *bat_frag;
111112

112-
wait_queue_head_t rx_wq;
113-
struct task_struct *rx_thread;
114-
struct sk_buff_head skb_list;
115-
unsigned int skb_list_max_len;
116-
117-
struct workqueue_struct *worker;
118-
struct work_struct dpmaif_rxq_work;
119-
120113
atomic_t rx_processing;
121114

122115
struct dpmaif_ctrl *dpmaif_ctrl;
123116
unsigned int expect_pit_seq;
124117
unsigned int pit_remain_release_cnt;
125118
struct dpmaif_cur_rx_skb_info rx_data_info;
119+
struct napi_struct napi;
120+
bool sleep_lock_pending;
126121
};
127122

128123
struct dpmaif_tx_queue {
@@ -168,7 +163,8 @@ enum dpmaif_txq_state {
168163
struct dpmaif_callbacks {
169164
void (*state_notify)(struct t7xx_pci_dev *t7xx_dev,
170165
enum dpmaif_txq_state state, int txq_number);
171-
void (*recv_skb)(struct t7xx_pci_dev *t7xx_dev, struct sk_buff *skb);
166+
void (*recv_skb)(struct t7xx_ccmni_ctrl *ccmni_ctlb, struct sk_buff *skb,
167+
struct napi_struct *napi);
172168
};
173169

174170
struct dpmaif_ctrl {

drivers/net/wwan/t7xx/t7xx_hif_dpmaif_rx.c

Lines changed: 66 additions & 152 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
#include "t7xx_dpmaif.h"
4646
#include "t7xx_hif_dpmaif.h"
4747
#include "t7xx_hif_dpmaif_rx.h"
48+
#include "t7xx_netdev.h"
4849
#include "t7xx_pci.h"
4950

5051
#define DPMAIF_BAT_COUNT 8192
@@ -76,43 +77,6 @@ static unsigned int t7xx_normal_pit_bid(const struct dpmaif_pit *pit_info)
7677
return value;
7778
}
7879

79-
static int t7xx_dpmaif_net_rx_push_thread(void *arg)
80-
{
81-
struct dpmaif_rx_queue *q = arg;
82-
struct dpmaif_ctrl *hif_ctrl;
83-
struct dpmaif_callbacks *cb;
84-
85-
hif_ctrl = q->dpmaif_ctrl;
86-
cb = hif_ctrl->callbacks;
87-
88-
while (!kthread_should_stop()) {
89-
struct sk_buff *skb;
90-
unsigned long flags;
91-
92-
if (skb_queue_empty(&q->skb_list)) {
93-
if (wait_event_interruptible(q->rx_wq,
94-
!skb_queue_empty(&q->skb_list) ||
95-
kthread_should_stop()))
96-
continue;
97-
98-
if (kthread_should_stop())
99-
break;
100-
}
101-
102-
spin_lock_irqsave(&q->skb_list.lock, flags);
103-
skb = __skb_dequeue(&q->skb_list);
104-
spin_unlock_irqrestore(&q->skb_list.lock, flags);
105-
106-
if (!skb)
107-
continue;
108-
109-
cb->recv_skb(hif_ctrl->t7xx_dev, skb);
110-
cond_resched();
111-
}
112-
113-
return 0;
114-
}
115-
11680
static int t7xx_dpmaif_update_bat_wr_idx(struct dpmaif_ctrl *dpmaif_ctrl,
11781
const unsigned int q_num, const unsigned int bat_cnt)
11882
{
@@ -726,21 +690,10 @@ static int t7xx_dpmaifq_rx_notify_hw(struct dpmaif_rx_queue *rxq)
726690
return ret;
727691
}
728692

729-
static void t7xx_dpmaif_rx_skb_enqueue(struct dpmaif_rx_queue *rxq, struct sk_buff *skb)
730-
{
731-
unsigned long flags;
732-
733-
spin_lock_irqsave(&rxq->skb_list.lock, flags);
734-
if (rxq->skb_list.qlen < rxq->skb_list_max_len)
735-
__skb_queue_tail(&rxq->skb_list, skb);
736-
else
737-
dev_kfree_skb_any(skb);
738-
spin_unlock_irqrestore(&rxq->skb_list.lock, flags);
739-
}
740-
741693
static void t7xx_dpmaif_rx_skb(struct dpmaif_rx_queue *rxq,
742694
struct dpmaif_cur_rx_skb_info *skb_info)
743695
{
696+
struct dpmaif_ctrl *dpmaif_ctrl = rxq->dpmaif_ctrl;
744697
struct sk_buff *skb = skb_info->cur_skb;
745698
struct t7xx_skb_cb *skb_cb;
746699
u8 netif_id;
@@ -758,11 +711,11 @@ static void t7xx_dpmaif_rx_skb(struct dpmaif_rx_queue *rxq,
758711
skb_cb = T7XX_SKB_CB(skb);
759712
skb_cb->netif_idx = netif_id;
760713
skb_cb->rx_pkt_type = skb_info->pkt_type;
761-
t7xx_dpmaif_rx_skb_enqueue(rxq, skb);
714+
dpmaif_ctrl->callbacks->recv_skb(dpmaif_ctrl->t7xx_dev->ccmni_ctlb, skb, &rxq->napi);
762715
}
763716

764717
static int t7xx_dpmaif_rx_start(struct dpmaif_rx_queue *rxq, const unsigned int pit_cnt,
765-
const unsigned long timeout)
718+
const unsigned int budget, int *once_more)
766719
{
767720
unsigned int cur_pit, pit_len, rx_cnt, recv_skb_cnt = 0;
768721
struct device *dev = rxq->dpmaif_ctrl->dev;
@@ -777,13 +730,14 @@ static int t7xx_dpmaif_rx_start(struct dpmaif_rx_queue *rxq, const unsigned int
777730
struct dpmaif_pit *pkt_info;
778731
u32 val;
779732

780-
if (!skb_info->msg_pit_received && time_after_eq(jiffies, timeout))
733+
if (!skb_info->msg_pit_received && recv_skb_cnt >= budget)
781734
break;
782735

783736
pkt_info = (struct dpmaif_pit *)rxq->pit_base + cur_pit;
784737
if (t7xx_dpmaif_check_pit_seq(rxq, pkt_info)) {
785738
dev_err_ratelimited(dev, "RXQ%u checks PIT SEQ fail\n", rxq->index);
786-
return -EAGAIN;
739+
*once_more = 1;
740+
return recv_skb_cnt;
787741
}
788742

789743
val = FIELD_GET(PD_PIT_PACKET_TYPE, le32_to_cpu(pkt_info->header));
@@ -817,12 +771,7 @@ static int t7xx_dpmaif_rx_start(struct dpmaif_rx_queue *rxq, const unsigned int
817771
}
818772

819773
memset(skb_info, 0, sizeof(*skb_info));
820-
821774
recv_skb_cnt++;
822-
if (!(recv_skb_cnt & DPMAIF_RX_PUSH_THRESHOLD_MASK)) {
823-
wake_up_all(&rxq->rx_wq);
824-
recv_skb_cnt = 0;
825-
}
826775
}
827776
}
828777

@@ -837,16 +786,13 @@ static int t7xx_dpmaif_rx_start(struct dpmaif_rx_queue *rxq, const unsigned int
837786
}
838787
}
839788

840-
if (recv_skb_cnt)
841-
wake_up_all(&rxq->rx_wq);
842-
843789
if (!ret)
844790
ret = t7xx_dpmaifq_rx_notify_hw(rxq);
845791

846792
if (ret)
847793
return ret;
848794

849-
return rx_cnt;
795+
return recv_skb_cnt;
850796
}
851797

852798
static unsigned int t7xx_dpmaifq_poll_pit(struct dpmaif_rx_queue *rxq)
@@ -863,76 +809,83 @@ static unsigned int t7xx_dpmaifq_poll_pit(struct dpmaif_rx_queue *rxq)
863809
return pit_cnt;
864810
}
865811

866-
static int t7xx_dpmaif_rx_data_collect(struct dpmaif_ctrl *dpmaif_ctrl,
867-
const unsigned int q_num, const unsigned int budget)
812+
static int t7xx_dpmaif_napi_rx_data_collect(struct dpmaif_ctrl *dpmaif_ctrl,
813+
const unsigned int q_num,
814+
const unsigned int budget, int *once_more)
868815
{
869816
struct dpmaif_rx_queue *rxq = &dpmaif_ctrl->rxq[q_num];
870-
unsigned long time_limit;
871817
unsigned int cnt;
818+
int ret = 0;
872819

873-
time_limit = jiffies + msecs_to_jiffies(DPMAIF_WQ_TIME_LIMIT_MS);
874-
875-
while ((cnt = t7xx_dpmaifq_poll_pit(rxq))) {
876-
unsigned int rd_cnt;
877-
int real_cnt;
878-
879-
rd_cnt = min(cnt, budget);
880-
881-
real_cnt = t7xx_dpmaif_rx_start(rxq, rd_cnt, time_limit);
882-
if (real_cnt < 0)
883-
return real_cnt;
884-
885-
if (real_cnt < cnt)
886-
return -EAGAIN;
887-
}
888-
889-
return 0;
890-
}
820+
cnt = t7xx_dpmaifq_poll_pit(rxq);
821+
if (!cnt)
822+
return ret;
891823

892-
static void t7xx_dpmaif_do_rx(struct dpmaif_ctrl *dpmaif_ctrl, struct dpmaif_rx_queue *rxq)
893-
{
894-
struct dpmaif_hw_info *hw_info = &dpmaif_ctrl->hw_info;
895-
int ret;
824+
ret = t7xx_dpmaif_rx_start(rxq, cnt, budget, once_more);
825+
if (ret < 0)
826+
dev_err(dpmaif_ctrl->dev, "dlq%u rx ERR:%d\n", rxq->index, ret);
896827

897-
ret = t7xx_dpmaif_rx_data_collect(dpmaif_ctrl, rxq->index, rxq->budget);
898-
if (ret < 0) {
899-
/* Try one more time */
900-
queue_work(rxq->worker, &rxq->dpmaif_rxq_work);
901-
t7xx_dpmaif_clr_ip_busy_sts(hw_info);
902-
} else {
903-
t7xx_dpmaif_clr_ip_busy_sts(hw_info);
904-
t7xx_dpmaif_dlq_unmask_rx_done(hw_info, rxq->index);
905-
}
828+
return ret;
906829
}
907830

908-
static void t7xx_dpmaif_rxq_work(struct work_struct *work)
831+
int t7xx_dpmaif_napi_rx_poll(struct napi_struct *napi, const int budget)
909832
{
910-
struct dpmaif_rx_queue *rxq = container_of(work, struct dpmaif_rx_queue, dpmaif_rxq_work);
911-
struct dpmaif_ctrl *dpmaif_ctrl = rxq->dpmaif_ctrl;
912-
int ret;
833+
struct dpmaif_rx_queue *rxq = container_of(napi, struct dpmaif_rx_queue, napi);
834+
struct t7xx_pci_dev *t7xx_dev = rxq->dpmaif_ctrl->t7xx_dev;
835+
int ret, once_more = 0, work_done = 0;
913836

914837
atomic_set(&rxq->rx_processing, 1);
915838
/* Ensure rx_processing is changed to 1 before actually begin RX flow */
916839
smp_mb();
917840

918841
if (!rxq->que_started) {
919842
atomic_set(&rxq->rx_processing, 0);
920-
dev_err(dpmaif_ctrl->dev, "Work RXQ: %d has not been started\n", rxq->index);
921-
return;
843+
dev_err(rxq->dpmaif_ctrl->dev, "Work RXQ: %d has not been started\n", rxq->index);
844+
return work_done;
922845
}
923846

924-
ret = pm_runtime_resume_and_get(dpmaif_ctrl->dev);
925-
if (ret < 0 && ret != -EACCES)
926-
return;
847+
if (!rxq->sleep_lock_pending) {
848+
pm_runtime_get_noresume(rxq->dpmaif_ctrl->dev);
849+
t7xx_pci_disable_sleep(t7xx_dev);
850+
}
927851

928-
t7xx_pci_disable_sleep(dpmaif_ctrl->t7xx_dev);
929-
if (t7xx_pci_sleep_disable_complete(dpmaif_ctrl->t7xx_dev))
930-
t7xx_dpmaif_do_rx(dpmaif_ctrl, rxq);
852+
ret = try_wait_for_completion(&t7xx_dev->sleep_lock_acquire);
853+
if (!ret) {
854+
napi_complete_done(napi, work_done);
855+
rxq->sleep_lock_pending = true;
856+
napi_reschedule(napi);
857+
return work_done;
858+
}
931859

932-
t7xx_pci_enable_sleep(dpmaif_ctrl->t7xx_dev);
933-
pm_runtime_mark_last_busy(dpmaif_ctrl->dev);
934-
pm_runtime_put_autosuspend(dpmaif_ctrl->dev);
860+
rxq->sleep_lock_pending = false;
861+
while (work_done < budget) {
862+
int each_budget = budget - work_done;
863+
int rx_cnt = t7xx_dpmaif_napi_rx_data_collect(rxq->dpmaif_ctrl, rxq->index,
864+
each_budget, &once_more);
865+
if (rx_cnt > 0)
866+
work_done += rx_cnt;
867+
else
868+
break;
869+
}
870+
871+
if (once_more) {
872+
napi_gro_flush(napi, false);
873+
work_done = budget;
874+
t7xx_dpmaif_clr_ip_busy_sts(&rxq->dpmaif_ctrl->hw_info);
875+
} else if (work_done < budget) {
876+
napi_complete_done(napi, work_done);
877+
t7xx_dpmaif_clr_ip_busy_sts(&rxq->dpmaif_ctrl->hw_info);
878+
t7xx_dpmaif_dlq_unmask_rx_done(&rxq->dpmaif_ctrl->hw_info, rxq->index);
879+
} else {
880+
t7xx_dpmaif_clr_ip_busy_sts(&rxq->dpmaif_ctrl->hw_info);
881+
}
882+
883+
t7xx_pci_enable_sleep(rxq->dpmaif_ctrl->t7xx_dev);
884+
pm_runtime_mark_last_busy(rxq->dpmaif_ctrl->dev);
885+
pm_runtime_put_noidle(rxq->dpmaif_ctrl->dev);
935886
atomic_set(&rxq->rx_processing, 0);
887+
888+
return work_done;
936889
}
937890

938891
void t7xx_dpmaif_irq_rx_done(struct dpmaif_ctrl *dpmaif_ctrl, const unsigned int que_mask)
@@ -947,7 +900,7 @@ void t7xx_dpmaif_irq_rx_done(struct dpmaif_ctrl *dpmaif_ctrl, const unsigned int
947900
}
948901

949902
rxq = &dpmaif_ctrl->rxq[qno];
950-
queue_work(rxq->worker, &rxq->dpmaif_rxq_work);
903+
napi_schedule(&rxq->napi);
951904
}
952905

953906
static void t7xx_dpmaif_base_free(const struct dpmaif_ctrl *dpmaif_ctrl,
@@ -1082,50 +1035,14 @@ int t7xx_dpmaif_rxq_init(struct dpmaif_rx_queue *queue)
10821035
int ret;
10831036

10841037
ret = t7xx_dpmaif_rx_alloc(queue);
1085-
if (ret < 0) {
1038+
if (ret < 0)
10861039
dev_err(queue->dpmaif_ctrl->dev, "Failed to allocate RX buffers: %d\n", ret);
1087-
return ret;
1088-
}
1089-
1090-
INIT_WORK(&queue->dpmaif_rxq_work, t7xx_dpmaif_rxq_work);
1091-
1092-
queue->worker = alloc_workqueue("dpmaif_rx%d_worker",
1093-
WQ_UNBOUND | WQ_MEM_RECLAIM | WQ_HIGHPRI, 1, queue->index);
1094-
if (!queue->worker) {
1095-
ret = -ENOMEM;
1096-
goto err_free_rx_buffer;
1097-
}
1098-
1099-
init_waitqueue_head(&queue->rx_wq);
1100-
skb_queue_head_init(&queue->skb_list);
1101-
queue->skb_list_max_len = queue->bat_req->pkt_buf_sz;
1102-
queue->rx_thread = kthread_run(t7xx_dpmaif_net_rx_push_thread,
1103-
queue, "dpmaif_rx%d_push", queue->index);
1104-
1105-
ret = PTR_ERR_OR_ZERO(queue->rx_thread);
1106-
if (ret)
1107-
goto err_free_workqueue;
1108-
1109-
return 0;
1110-
1111-
err_free_workqueue:
1112-
destroy_workqueue(queue->worker);
1113-
1114-
err_free_rx_buffer:
1115-
t7xx_dpmaif_rx_buf_free(queue);
11161040

11171041
return ret;
11181042
}
11191043

11201044
void t7xx_dpmaif_rxq_free(struct dpmaif_rx_queue *queue)
11211045
{
1122-
if (queue->worker)
1123-
destroy_workqueue(queue->worker);
1124-
1125-
if (queue->rx_thread)
1126-
kthread_stop(queue->rx_thread);
1127-
1128-
skb_queue_purge(&queue->skb_list);
11291046
t7xx_dpmaif_rx_buf_free(queue);
11301047
}
11311048

@@ -1188,8 +1105,6 @@ void t7xx_dpmaif_rx_stop(struct dpmaif_ctrl *dpmaif_ctrl)
11881105
struct dpmaif_rx_queue *rxq = &dpmaif_ctrl->rxq[i];
11891106
int timeout, value;
11901107

1191-
flush_work(&rxq->dpmaif_rxq_work);
1192-
11931108
timeout = readx_poll_timeout_atomic(atomic_read, &rxq->rx_processing, value,
11941109
!value, 0, DPMAIF_CHECK_INIT_TIMEOUT_US);
11951110
if (timeout)
@@ -1205,7 +1120,6 @@ static void t7xx_dpmaif_stop_rxq(struct dpmaif_rx_queue *rxq)
12051120
{
12061121
int cnt, j = 0;
12071122

1208-
flush_work(&rxq->dpmaif_rxq_work);
12091123
rxq->que_started = false;
12101124

12111125
do {

drivers/net/wwan/t7xx/t7xx_hif_dpmaif_rx.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,5 +112,6 @@ int t7xx_dpmaif_bat_alloc(const struct dpmaif_ctrl *dpmaif_ctrl, struct dpmaif_b
112112
const enum bat_type buf_type);
113113
void t7xx_dpmaif_bat_free(const struct dpmaif_ctrl *dpmaif_ctrl,
114114
struct dpmaif_bat_request *bat_req);
115+
int t7xx_dpmaif_napi_rx_poll(struct napi_struct *napi, const int budget);
115116

116117
#endif /* __T7XX_HIF_DPMA_RX_H__ */

0 commit comments

Comments
 (0)