diff --git a/core/cds/inc/cds_sched.h b/core/cds/inc/cds_sched.h index 8bb33f742322..443533d2aa7a 100644 --- a/core/cds/inc/cds_sched.h +++ b/core/cds/inc/cds_sched.h @@ -45,6 +45,7 @@ #define MC_SUSPEND_EVENT 0x002 #define RX_POST_EVENT 0x001 #define RX_SUSPEND_EVENT 0x002 +#define RX_VDEV_DEL_EVENT 0x004 #define RX_SHUTDOWN_EVENT 0x010 #ifdef QCA_CONFIG_SMP diff --git a/core/dp/txrx3.0/dp_rx_thread.c b/core/dp/txrx3.0/dp_rx_thread.c index 925a0288f0da..817c5eeb6451 100644 --- a/core/dp/txrx3.0/dp_rx_thread.c +++ b/core/dp/txrx3.0/dp_rx_thread.c @@ -104,7 +104,7 @@ static void dp_rx_tm_thread_dump_stats(struct dp_rx_thread *rx_thread) if (!total_queued) return; - dp_info("thread:%u - qlen:%u queued:(total:%u %s) dequeued:%u stack:%u gro_flushes: %u rx_flushes: %u max_len:%u invalid(peer:%u vdev:%u rx-handle:%u others:%u)", + dp_info("thread:%u - qlen:%u queued:(total:%u %s) dequeued:%u stack:%u gro_flushes: %u gro_flushes_by_vdev_del: %u rx_flushes: %u max_len:%u invalid(peer:%u vdev:%u rx-handle:%u others:%u)", rx_thread->id, qdf_nbuf_queue_head_qlen(&rx_thread->nbuf_queue), total_queued, @@ -112,6 +112,7 @@ static void dp_rx_tm_thread_dump_stats(struct dp_rx_thread *rx_thread) rx_thread->stats.nbuf_dequeued, rx_thread->stats.nbuf_sent_to_stack, rx_thread->stats.gro_flushes, + rx_thread->stats.gro_flushes_by_vdev_del, rx_thread->stats.rx_flushed, rx_thread->stats.nbufq_max_len, rx_thread->stats.dropped_invalid_peer, @@ -384,11 +385,19 @@ static int dp_rx_thread_sub_loop(struct dp_rx_thread *rx_thread, bool *shutdown) dp_rx_thread_process_nbufq(rx_thread); - if (qdf_atomic_read(&rx_thread->gro_flush_ind)) { + if (qdf_atomic_read(&rx_thread->gro_flush_ind) | + qdf_atomic_test_bit(RX_VDEV_DEL_EVENT, + &rx_thread->event_flag)) { dp_rx_thread_gro_flush(rx_thread); qdf_atomic_set(&rx_thread->gro_flush_ind, 0); } + if (qdf_atomic_test_and_clear_bit(RX_VDEV_DEL_EVENT, + &rx_thread->event_flag)) { + rx_thread->stats.gro_flushes_by_vdev_del++; + qdf_event_set(&rx_thread->vdev_del_event); + } + if (qdf_atomic_test_and_clear_bit(RX_SUSPEND_EVENT, &rx_thread->event_flag)) { dp_debug("received suspend ind (%s) id %d pid %d", @@ -441,6 +450,8 @@ static int dp_rx_thread_loop(void *arg) qdf_atomic_test_bit(RX_POST_EVENT, &rx_thread->event_flag) || qdf_atomic_test_bit(RX_SUSPEND_EVENT, + &rx_thread->event_flag) || + qdf_atomic_test_bit(RX_VDEV_DEL_EVENT, &rx_thread->event_flag)); dp_debug("woken up"); @@ -528,6 +539,7 @@ static QDF_STATUS dp_rx_tm_thread_init(struct dp_rx_thread *rx_thread, qdf_event_create(&rx_thread->suspend_event); qdf_event_create(&rx_thread->resume_event); qdf_event_create(&rx_thread->shutdown_event); + qdf_event_create(&rx_thread->vdev_del_event); qdf_atomic_init(&rx_thread->gro_flush_ind); qdf_init_waitqueue_head(&rx_thread->wait_q); qdf_scnprintf(thread_name, sizeof(thread_name), "dp_rx_thread_%u", id); @@ -567,6 +579,7 @@ static QDF_STATUS dp_rx_tm_thread_deinit(struct dp_rx_thread *rx_thread) qdf_event_destroy(&rx_thread->suspend_event); qdf_event_destroy(&rx_thread->resume_event); qdf_event_destroy(&rx_thread->shutdown_event); + qdf_event_destroy(&rx_thread->vdev_del_event); if (cdp_cfg_get(dp_rx_tm_get_soc_handle(rx_thread->rtm_handle_cmn), cfg_dp_gro_enable)) @@ -680,6 +693,10 @@ QDF_STATUS dp_rx_tm_suspend(struct dp_rx_tm_handle *rx_tm_hdl) * to be flushed out * @vdev_id: vdev id for which packets are to be flushed * + * The function will flush the RX packets by vdev_id in a particular + * RX thead queue. And will notify and wait the TX thread to flush the + * packets in the NAPI RX GRO hash list + * * Return: void */ static inline @@ -688,6 +705,7 @@ void dp_rx_thread_flush_by_vdev_id(struct dp_rx_thread *rx_thread, { qdf_nbuf_t nbuf_list, tmp_nbuf_list; uint32_t num_list_elements = 0; + QDF_STATUS qdf_status; qdf_nbuf_queue_head_lock(&rx_thread->nbuf_queue); QDF_NBUF_QUEUE_WALK_SAFE(&rx_thread->nbuf_queue, nbuf_list, @@ -704,10 +722,20 @@ void dp_rx_thread_flush_by_vdev_id(struct dp_rx_thread *rx_thread, } qdf_nbuf_queue_head_unlock(&rx_thread->nbuf_queue); - if (qdf_atomic_read(&rx_thread->gro_flush_ind)) - qdf_atomic_set(&rx_thread->gro_flush_ind, 0); + qdf_set_bit(RX_VDEV_DEL_EVENT, &rx_thread->event_flag); + qdf_wake_up_interruptible(&rx_thread->wait_q); - dp_rx_thread_gro_flush(rx_thread); + qdf_status = qdf_wait_single_event(&rx_thread->vdev_del_event, + DP_RX_THREAD_WAIT_TIMEOUT); + if (QDF_IS_STATUS_SUCCESS(qdf_status)) + dp_debug("thread:%d napi gro flush successfully", + rx_thread->id); + else if (qdf_status == QDF_STATUS_E_TIMEOUT) + dp_err("thread:%d timed out waiting for napi gro flush", + rx_thread->id); + else + dp_err("thread:%d failed while waiting for napi gro flush", + rx_thread->id); } /** diff --git a/core/dp/txrx3.0/dp_rx_thread.h b/core/dp/txrx3.0/dp_rx_thread.h index d5335189f6b8..8d4828c1a52e 100644 --- a/core/dp/txrx3.0/dp_rx_thread.h +++ b/core/dp/txrx3.0/dp_rx_thread.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -44,6 +44,7 @@ struct dp_rx_tm_handle_cmn; * @nbuf_sent_to_stack: packets sent to the stack. some dequeued packets may be * dropped due to no peer or vdev, hence this stat. * @gro_flushes: number of GRO flushes + * @gro_flushes_by_vdev_del: number of GRO flushes triggered by vdev del. * @nbufq_max_len: maximum number of nbuf_lists queued for the thread * @dropped_invalid_vdev: packets(nbuf_list) dropped due to no vdev * @rx_flushed: packets flushed after vdev delete @@ -56,6 +57,7 @@ struct dp_rx_thread_stats { unsigned int nbuf_dequeued; unsigned int nbuf_sent_to_stack; unsigned int gro_flushes; + unsigned int gro_flushes_by_vdev_del; unsigned int nbufq_max_len; unsigned int dropped_invalid_vdev; unsigned int rx_flushed; @@ -72,6 +74,8 @@ struct dp_rx_thread_stats { * @suspend_event: handle of Event for DP Rx thread to signal suspend * @resume_event: handle of Event for DP Rx thread to signal resume * @shutdown_event: handle of Event for DP Rx thread to signal shutdown + * @vdev_del_event: handle of Event for vdev del thread to signal completion + * for gro flush * @event_flag: event flag to post events to DP Rx thread * @nbuf_queue:nbuf queue used to store RX packets * @nbufq_len: length of the nbuf queue @@ -89,6 +93,7 @@ struct dp_rx_thread { qdf_event_t suspend_event; qdf_event_t resume_event; qdf_event_t shutdown_event; + qdf_event_t vdev_del_event; qdf_atomic_t gro_flush_ind; unsigned long event_flag; qdf_nbuf_queue_head_t nbuf_queue;