diff --git a/dp/inc/cdp_txrx_cmn_struct.h b/dp/inc/cdp_txrx_cmn_struct.h index 885b2a4dcf..2b6ec91080 100644 --- a/dp/inc/cdp_txrx_cmn_struct.h +++ b/dp/inc/cdp_txrx_cmn_struct.h @@ -671,6 +671,14 @@ typedef bool (*ol_txrx_tx_flow_control_is_pause_fp)(void *osif_dev); */ typedef QDF_STATUS(*ol_txrx_rx_fp)(void *osif_dev, qdf_nbuf_t msdu_list); +/** + * ol_txrx_rx_flush_fp - receive function to hand batches of data + * frames from txrx to OS shim + * @osif_dev: handle to the OSIF virtual device object + * @vdev_id: vdev_if of the packets to be flushed + */ +typedef QDF_STATUS(*ol_txrx_rx_flush_fp)(void *osif_dev, uint8_t vdev_id); + /** * ol_txrx_rx_gro_flush_ind - function to send GRO flush indication to stack * for a given RX Context Id. @@ -832,6 +840,7 @@ struct ol_txrx_ops { struct { ol_txrx_rx_fp rx; ol_txrx_rx_fp rx_stack; + ol_txrx_rx_flush_fp rx_flush; ol_txrx_rx_gro_flush_ind_fp rx_gro_flush; ol_txrx_rx_check_wai_fp wai_check; ol_txrx_rx_mon_fp mon; diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index 12a2984116..9f8ad3290d 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -4869,6 +4869,7 @@ static void dp_vdev_register_wifi3(struct cdp_vdev *vdev_handle, vdev->ctrl_vdev = ctrl_vdev; vdev->osif_rx = txrx_ops->rx.rx; vdev->osif_rx_stack = txrx_ops->rx.rx_stack; + vdev->osif_rx_flush = txrx_ops->rx.rx_flush; vdev->osif_gro_flush = txrx_ops->rx.rx_gro_flush; vdev->osif_rsim_rx_decap = txrx_ops->rx.rsim_rx_decap; vdev->osif_get_key = txrx_ops->get_key; @@ -5085,6 +5086,7 @@ static void dp_vdev_detach_wifi3(struct cdp_vdev *vdev_handle, qdf_spin_lock_bh(&pdev->vdev_list_lock); dp_tx_vdev_detach(vdev); + dp_rx_vdev_detach(vdev); /* remove the vdev from its parent pdev's list */ TAILQ_REMOVE(&pdev->vdev_list, vdev, vdev_list_elem); QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO_HIGH, diff --git a/dp/wifi3.0/dp_rx.c b/dp/wifi3.0/dp_rx.c index 049447d0cc..4c9dd0ff92 100644 --- a/dp/wifi3.0/dp_rx.c +++ b/dp/wifi3.0/dp_rx.c @@ -2268,8 +2268,24 @@ done: return rx_bufs_used; /* Assume no scale factor for now */ } +QDF_STATUS dp_rx_vdev_detach(struct dp_vdev *vdev) +{ + QDF_STATUS ret; + + if (vdev->osif_rx_flush) { + ret = vdev->osif_rx_flush(vdev->osif_vdev, vdev->vdev_id); + if (!ret) { + dp_err("Failed to flush rx pkts for vdev %d\n", + vdev->vdev_id); + return ret; + } + } + + return QDF_STATUS_SUCCESS; +} + /** - * dp_rx_detach() - detach dp rx + * dp_rx_pdev_detach() - detach dp rx * @pdev: core txrx pdev context * * This function will detach DP RX into main device context diff --git a/dp/wifi3.0/dp_rx.h b/dp/wifi3.0/dp_rx.h index 0303695ccf..3940f34bf6 100644 --- a/dp/wifi3.0/dp_rx.h +++ b/dp/wifi3.0/dp_rx.h @@ -445,6 +445,15 @@ void dp_rx_pdev_detach(struct dp_pdev *pdev); void dp_print_napi_stats(struct dp_soc *soc); +/** + * dp_rx_vdev_detach() - detach vdev from dp rx + * @vdev: virtual device instance + * + * Return: QDF_STATUS_SUCCESS: success + * QDF_STATUS_E_RESOURCES: Error return + */ +QDF_STATUS dp_rx_vdev_detach(struct dp_vdev *vdev); + uint32_t dp_rx_process(struct dp_intr *int_ctx, hal_ring_handle_t hal_ring_hdl, uint8_t reo_ring_num, diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index 25400bbe5f..b0c7aab99e 100644 --- a/dp/wifi3.0/dp_types.h +++ b/dp/wifi3.0/dp_types.h @@ -1738,6 +1738,8 @@ struct dp_vdev { ol_txrx_rx_fp osif_rx; /* callback to deliver rx frames to the OS */ ol_txrx_rx_fp osif_rx_stack; + /* call back function to flush out queued rx packets*/ + ol_txrx_rx_flush_fp osif_rx_flush; ol_txrx_rsim_rx_decap_fp osif_rsim_rx_decap; ol_txrx_get_key_fp osif_get_key; ol_txrx_tx_free_ext_fp osif_tx_free_ext; diff --git a/qdf/inc/qdf_nbuf.h b/qdf/inc/qdf_nbuf.h index 154d5952ef..b19d0b1a65 100644 --- a/qdf/inc/qdf_nbuf.h +++ b/qdf/inc/qdf_nbuf.h @@ -757,6 +757,9 @@ qdf_nbuf_set_send_complete_flag(qdf_nbuf_t buf, bool flag) __qdf_nbuf_set_send_complete_flag(buf, flag); } +#define QDF_NBUF_QUEUE_WALK_SAFE(queue, var, tvar) \ + __qdf_nbuf_queue_walk_safe(queue, var, tvar) + #ifdef NBUF_MAP_UNMAP_DEBUG /** * qdf_nbuf_map_check_for_leaks() - check for nbut map leaks @@ -964,6 +967,28 @@ void qdf_nbuf_queue_head_purge(qdf_nbuf_queue_head_t *nbuf_queue_head) return __qdf_nbuf_queue_head_purge(nbuf_queue_head); } +/** + * qdf_nbuf_queue_head_lock() - Acquire the nbuf_queue_head lock + * @head: nbuf_queue_head of the nbuf_list for which lock is to be acquired + * + * Return: void + */ +static inline void qdf_nbuf_queue_head_lock(qdf_nbuf_queue_head_t *head) +{ + __qdf_nbuf_queue_head_lock(head); +} + +/** + * qdf_nbuf_queue_head_unlock() - Release the nbuf queue lock + * @head: nbuf_queue_head of the nbuf_list for which lock is to be release + * + * Return: void + */ +static inline void qdf_nbuf_queue_head_unlock(qdf_nbuf_queue_head_t *head) +{ + __qdf_nbuf_queue_head_unlock(head); +} + static inline void qdf_nbuf_sync_for_cpu(qdf_device_t osdev, qdf_nbuf_t buf, qdf_dma_dir_t dir) { @@ -1866,6 +1891,22 @@ static inline void qdf_nbuf_set_tail_pointer(qdf_nbuf_t buf, int len) __qdf_nbuf_set_tail_pointer(buf, len); } +/** + * qdf_nbuf_unlink_no_lock() - unlink a nbuf from nbuf list + * @buf: Network buf instance + * @list: list to use + * + * This is a lockless version, driver must acquire locks if it + * needs to synchronize + * + * Return: none + */ +static inline void +qdf_nbuf_unlink_no_lock(qdf_nbuf_t buf, qdf_nbuf_queue_head_t *list) +{ + __qdf_nbuf_unlink_no_lock(buf, list); +} + /** * qdf_nbuf_reset() - reset the buffer data and pointer * @buf: Network buf instance diff --git a/qdf/linux/src/i_qdf_nbuf.h b/qdf/linux/src/i_qdf_nbuf.h index 9dae8a7c25..6b50cb1744 100644 --- a/qdf/linux/src/i_qdf_nbuf.h +++ b/qdf/linux/src/i_qdf_nbuf.h @@ -705,6 +705,9 @@ typedef void (*qdf_nbuf_free_t)(__qdf_nbuf_t); #define __qdf_nbuf_data_attr_set(skb, data_attr) \ (QDF_NBUF_CB_TX_DATA_ATTR(skb) = (data_attr)) +#define __qdf_nbuf_queue_walk_safe(queue, var, tvar) \ + skb_queue_walk_safe(queue, var, tvar) + /** * __qdf_nbuf_num_frags_init() - init extra frags * @skb: sk buffer @@ -1085,6 +1088,22 @@ __qdf_nbuf_set_tail_pointer(struct sk_buff *skb, int len) skb_set_tail_pointer(skb, len); } +/** + * __qdf_nbuf_unlink_no_lock() - unlink an skb from skb queue + * @skb: Pointer to network buffer + * @list: list to use + * + * This is a lockless version, driver must acquire locks if it + * needs to synchronize + * + * Return: none + */ +static inline void +__qdf_nbuf_unlink_no_lock(struct sk_buff *skb, struct sk_buff_head *list) +{ + __skb_unlink(skb, list); +} + /** * __qdf_nbuf_reset() - reset the buffer data and pointer * @buf: Network buf instance @@ -2204,6 +2223,30 @@ void __qdf_nbuf_queue_head_purge(struct sk_buff_head *skb_queue_head) return skb_queue_purge(skb_queue_head); } +/** + * __qdf_nbuf_queue_head_lock() - Acquire the skb list lock + * @head: skb list for which lock is to be acquired + * + * Return: void + */ +static inline +void __qdf_nbuf_queue_head_lock(struct sk_buff_head *skb_queue_head) +{ + spin_lock_bh(&skb_queue_head->lock); +} + +/** + * __qdf_nbuf_queue_head_unlock() - Release the skb list lock + * @head: skb list for which lock is to be release + * + * Return: void + */ +static inline +void __qdf_nbuf_queue_head_unlock(struct sk_buff_head *skb_queue_head) +{ + spin_unlock_bh(&skb_queue_head->lock); +} + #ifdef CONFIG_NBUF_AP_PLATFORM #include #else