diff --git a/dp/inc/cdp_txrx_ipa.h b/dp/inc/cdp_txrx_ipa.h index a44629df72..64ebbaa15b 100644 --- a/dp/inc/cdp_txrx_ipa.h +++ b/dp/inc/cdp_txrx_ipa.h @@ -30,115 +30,111 @@ */ #ifndef _CDP_TXRX_IPA_H_ #define _CDP_TXRX_IPA_H_ +#include #include #include "cdp_txrx_handle.h" + +#ifdef IPA_OFFLOAD /** - * cdp_ipa_get_resource() - Get allocated wlan resources for ipa data path + * cdp_ipa_get_resource() - Get allocated WLAN resources for IPA data path * @soc - data path soc handle * @pdev - device instance pointer - * @ipa_res - ipa resources pointer * - * Get allocated wlan resources for ipa data path + * Get allocated WLAN resources for IPA data path * - * return none + * return QDF_STATUS_SUCCESS */ -static inline void -cdp_ipa_get_resource(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, - struct ol_txrx_ipa_resources *ipa_res) +static inline QDF_STATUS +cdp_ipa_get_resource(ol_txrx_soc_handle soc, struct cdp_pdev *pdev) { - if (!soc || !soc->ops || !soc->ops->ipa_ops) { + if (!soc || !soc->ops || !soc->ops->ipa_ops || !pdev) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, "%s invalid instance", __func__); - return; + return QDF_STATUS_E_FAILURE; } if (soc->ops->ipa_ops->ipa_get_resource) - return soc->ops->ipa_ops->ipa_get_resource(pdev, ipa_res); + return soc->ops->ipa_ops->ipa_get_resource(pdev); - return; + return QDF_STATUS_SUCCESS; } /** - * cdp_ipa_set_doorbell_paddr() - give IPA db paddr to fw + * cdp_ipa_set_doorbell_paddr() - give IPA db paddr to FW * @soc - data path soc handle * @pdev - device instance pointer - * @ipa_tx_uc_doorbell_paddr - tx db paddr - * @ipa_rx_uc_doorbell_paddr - rx db paddr * - * give IPA db paddr to fw + * give IPA db paddr to FW * - * return none + * return QDF_STATUS_SUCCESS */ -static inline void -cdp_ipa_set_doorbell_paddr(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, - qdf_dma_addr_t ipa_tx_uc_doorbell_paddr, - qdf_dma_addr_t ipa_rx_uc_doorbell_paddr) +static inline QDF_STATUS +cdp_ipa_set_doorbell_paddr(ol_txrx_soc_handle soc, struct cdp_pdev *pdev) { - if (!soc || !soc->ops || !soc->ops->ipa_ops) { + if (!soc || !soc->ops || !soc->ops->ipa_ops || !pdev) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, "%s invalid instance", __func__); - return; + return QDF_STATUS_E_FAILURE; } if (soc->ops->ipa_ops->ipa_set_doorbell_paddr) - return soc->ops->ipa_ops->ipa_set_doorbell_paddr(pdev, - ipa_tx_uc_doorbell_paddr, ipa_rx_uc_doorbell_paddr); + return soc->ops->ipa_ops->ipa_set_doorbell_paddr(pdev); - return; + return QDF_STATUS_SUCCESS; } /** - * cdp_ipa_set_active() - activate/de-ctivate wlan fw ipa data path + * cdp_ipa_set_active() - activate/de-ctivate IPA offload path * @soc - data path soc handle * @pdev - device instance pointer * @uc_active - activate or de-activate * @is_tx - toggle tx or rx data path * - * activate/de-ctivate wlan fw ipa data path + * activate/de-ctivate IPA offload path * - * return none + * return QDF_STATUS_SUCCESS */ -static inline void +static inline QDF_STATUS cdp_ipa_set_active(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, bool uc_active, bool is_tx) { - if (!soc || !soc->ops || !soc->ops->ipa_ops) { + if (!soc || !soc->ops || !soc->ops->ipa_ops || !pdev) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, "%s invalid instance", __func__); - return; + return QDF_STATUS_E_FAILURE; } if (soc->ops->ipa_ops->ipa_set_active) return soc->ops->ipa_ops->ipa_set_active(pdev, uc_active, is_tx); - return; + return QDF_STATUS_SUCCESS; } /** - * cdp_ipa_op_response() - event handler from fw + * cdp_ipa_op_response() - event handler from FW * @soc - data path soc handle * @pdev - device instance pointer * @op_msg - event contents from firmware * - * event handler from fw + * event handler from FW * - * return none + * return QDF_STATUS_SUCCESS */ -static inline void +static inline QDF_STATUS cdp_ipa_op_response(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, uint8_t *op_msg) { - if (!soc || !soc->ops || !soc->ops->ipa_ops) { + if (!soc || !soc->ops || !soc->ops->ipa_ops || !pdev) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, "%s invalid instance", __func__); - return; + return QDF_STATUS_E_FAILURE; } if (soc->ops->ipa_ops->ipa_op_response) return soc->ops->ipa_ops->ipa_op_response(pdev, op_msg); - return; + return QDF_STATUS_SUCCESS; } /** @@ -146,51 +142,51 @@ cdp_ipa_op_response(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, * @soc - data path soc handle * @pdev - device instance pointer * @op_cb - event handler callback function pointer - * @osif_dev - osif instance pointer + * @usr_ctxt - user context to registered * * register event handler function pointer * - * return none + * return QDF_STATUS_SUCCESS */ -static inline void +static inline QDF_STATUS cdp_ipa_register_op_cb(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, - ipa_op_cb_type op_cb, void *osif_dev) + ipa_uc_op_cb_type op_cb, void *usr_ctxt) { - if (!soc || !soc->ops || !soc->ops->ipa_ops) { + if (!soc || !soc->ops || !soc->ops->ipa_ops || !pdev) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, "%s invalid instance", __func__); - return; + return QDF_STATUS_E_FAILURE; } if (soc->ops->ipa_ops->ipa_register_op_cb) return soc->ops->ipa_ops->ipa_register_op_cb(pdev, op_cb, - osif_dev); + usr_ctxt); - return; + return QDF_STATUS_SUCCESS; } /** - * cdp_ipa_get_stat() - get ipa data path stats from fw + * cdp_ipa_get_stat() - get IPA data path stats from FW * @soc - data path soc handle * @pdev - device instance pointer * - * get ipa data path stats from fw async + * get IPA data path stats from FW async * - * return none + * return QDF_STATUS_SUCCESS */ -static inline void +static inline QDF_STATUS cdp_ipa_get_stat(ol_txrx_soc_handle soc, struct cdp_pdev *pdev) { - if (!soc || !soc->ops || !soc->ops->ipa_ops) { + if (!soc || !soc->ops || !soc->ops->ipa_ops || !pdev) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, "%s invalid instance", __func__); - return; + return QDF_STATUS_E_FAILURE; } if (soc->ops->ipa_ops->ipa_get_stat) return soc->ops->ipa_ops->ipa_get_stat(pdev); - return; + return QDF_STATUS_SUCCESS; } /** @@ -203,7 +199,7 @@ cdp_ipa_get_stat(ol_txrx_soc_handle soc, struct cdp_pdev *pdev) static inline qdf_nbuf_t cdp_ipa_tx_send_data_frame(ol_txrx_soc_handle soc, struct cdp_vdev *vdev, qdf_nbuf_t skb) { - if (!soc || !soc->ops || !soc->ops->ipa_ops) { + if (!soc || !soc->ops || !soc->ops->ipa_ops || !vdev) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, "%s invalid instance", __func__); return skb; @@ -220,45 +216,48 @@ static inline qdf_nbuf_t cdp_ipa_tx_send_data_frame(ol_txrx_soc_handle soc, * @pdev: physical device instance * @value: partition base value * - * Return: none + * Return: QDF_STATUS */ -static inline void cdp_ipa_set_uc_tx_partition_base(ol_txrx_soc_handle soc, +static inline QDF_STATUS +cdp_ipa_set_uc_tx_partition_base(ol_txrx_soc_handle soc, struct cdp_cfg *cfg_pdev, uint32_t value) { - if (!soc || !soc->ops || !soc->ops->ipa_ops) { + if (!soc || !soc->ops || !soc->ops->ipa_ops || !cfg_pdev) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, "%s invalid instance", __func__); - return; + return QDF_STATUS_E_FAILURE; } if (soc->ops->ipa_ops->ipa_set_uc_tx_partition_base) - return soc->ops->ipa_ops->ipa_set_uc_tx_partition_base(cfg_pdev, - value); + soc->ops->ipa_ops->ipa_set_uc_tx_partition_base(cfg_pdev, + value); - return; + return QDF_STATUS_SUCCESS; } +#ifdef FEATURE_METERING /** * cdp_ipa_uc_get_share_stats() - get Tx/Rx byte stats from FW * @pdev: physical device instance * @value: reset stats * - * Return: none + * Return: QDF_STATUS */ -static inline void cdp_ipa_uc_get_share_stats(ol_txrx_soc_handle soc, - struct cdp_pdev *pdev, uint8_t value) +static inline QDF_STATUS +cdp_ipa_uc_get_share_stats(ol_txrx_soc_handle soc, + struct cdp_pdev *pdev, uint8_t value) { - if (!soc || !soc->ops || !soc->ops->ipa_ops) { + if (!soc || !soc->ops || !soc->ops->ipa_ops || !pdev) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, "%s invalid instance", __func__); - return; + return QDF_STATUS_E_FAILURE; } if (soc->ops->ipa_ops->ipa_uc_get_share_stats) return soc->ops->ipa_ops->ipa_uc_get_share_stats(pdev, value); - return; + return QDF_STATUS_SUCCESS; } /** @@ -266,22 +265,272 @@ static inline void cdp_ipa_uc_get_share_stats(ol_txrx_soc_handle soc, * @pdev: physical device instance * @value: quota limit bytes * - * Return: none + * Return: QDF_STATUS */ -static inline void cdp_ipa_uc_set_quota(ol_txrx_soc_handle soc, - struct cdp_pdev *pdev, uint64_t value) +static inline QDF_STATUS +cdp_ipa_uc_set_quota(ol_txrx_soc_handle soc, + struct cdp_pdev *pdev, uint64_t value) +{ + if (!soc || !soc->ops || !soc->ops->ipa_ops || !pdev) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, + "%s invalid instance", __func__); + return QDF_STATUS_E_FAILURE; + } + + if (soc->ops->ipa_ops->ipa_uc_set_quota) + return soc->ops->ipa_ops->ipa_uc_set_quota(pdev, + value); + + return QDF_STATUS_SUCCESS; +} +#endif + +/** + * cdp_ipa_enable_autonomy() - Enable autonomy RX data path + * @soc: data path soc handle + * @pdev: handle to the device instance + * + * IPA Data path is enabled and resumed. + * All autonomy data path elements are ready to deliver packet + * All RX packet should routed to IPA_REO ring, then IPA can receive packet + * from WLAN + * + * Return: QDF_STATUS + */ +static inline QDF_STATUS +cdp_ipa_enable_autonomy(ol_txrx_soc_handle soc, struct cdp_pdev *pdev) +{ + if (!soc || !soc->ops || !soc->ops->ipa_ops || !pdev) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, + "%s invalid instance", __func__); + return QDF_STATUS_E_FAILURE; + } + + if (soc->ops->ipa_ops->ipa_enable_autonomy) + return soc->ops->ipa_ops->ipa_enable_autonomy(pdev); + + return QDF_STATUS_SUCCESS; +} + +/** + * cdp_ipa_disable_autonomy() - Disable autonomy RX data path + * @soc: data path soc handle + * @pdev: handle to the device instance + * + * IPA Data path is enabled and resumed. + * All autonomy datapath elements are ready to deliver packet + * All RX packet should routed to IPA_REO ring, then IPA can receive packet + * from WLAN + * + * Return: QDF_STATUS + */ +static inline QDF_STATUS +cdp_ipa_disable_autonomy(ol_txrx_soc_handle soc, struct cdp_pdev *pdev) +{ + if (!soc || !soc->ops || !soc->ops->ipa_ops || !pdev) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, + "%s invalid instance", __func__); + return QDF_STATUS_E_FAILURE; + } + if (soc->ops->ipa_ops->ipa_enable_autonomy) + return soc->ops->ipa_ops->ipa_disable_autonomy(pdev); + + return QDF_STATUS_SUCCESS; +} + +/** + * cdp_ipa_setup() - Setup and connect IPA pipes + * @soc: data path soc handle + * @pdev: handle to the device instance + * @ipa_i2w_cb: IPA to WLAN callback + * @ipa_w2i_cb: WLAN to IPA callback + * @ipa_wdi_meter_notifier_cb: IPA WDI metering callback + * @ipa_desc_size: IPA descriptor size + * @ipa_priv: handle to the HTT instance + * @is_rm_enabled: Is IPA RM enabled or not + * @tx_pipe_handle: pointer to Tx pipe handle + * @rx_pipe_handle: pointer to Rx pipe handle + * + * Return: QDF_STATUS + */ +static inline QDF_STATUS +cdp_ipa_setup(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, void *ipa_i2w_cb, + void *ipa_w2i_cb, void *ipa_wdi_meter_notifier_cb, + uint32_t ipa_desc_size, void *ipa_priv, bool is_rm_enabled, + uint32_t *tx_pipe_handle, uint32_t *rx_pipe_handle) + +{ + if (!soc || !soc->ops || !soc->ops->ipa_ops || !pdev) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, + "%s invalid instance", __func__); + return QDF_STATUS_E_FAILURE; + } + + if (soc->ops->ipa_ops->ipa_setup) + return soc->ops->ipa_ops->ipa_setup(pdev, ipa_i2w_cb, + ipa_w2i_cb, + ipa_wdi_meter_notifier_cb, + ipa_desc_size, ipa_priv, + is_rm_enabled, + tx_pipe_handle, + rx_pipe_handle); + + return QDF_STATUS_SUCCESS; +} + +/** + * cdp_ipa_cleanup() - Disconnect IPA pipes + * @soc: data path soc handle + * @tx_pipe_handle: Tx pipe handle + * @rx_pipe_handle: Rx pipe handle + * + * Return: QDF_STATUS + */ +static inline QDF_STATUS +cdp_ipa_cleanup(ol_txrx_soc_handle soc, uint32_t tx_pipe_handle, + uint32_t rx_pipe_handle) { if (!soc || !soc->ops || !soc->ops->ipa_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, "%s invalid instance", __func__); - return; + return QDF_STATUS_E_FAILURE; } - if (soc->ops->ipa_ops->ipa_uc_get_share_stats) - return soc->ops->ipa_ops->ipa_uc_set_quota(pdev, - value); + if (soc->ops->ipa_ops->ipa_cleanup) + return soc->ops->ipa_ops->ipa_cleanup(tx_pipe_handle, + rx_pipe_handle); - return; + return QDF_STATUS_SUCCESS; } + +/** + * cdp_ipa_setup_iface() - Setup IPA header and register interface + * @soc: data path soc handle + * @ifname: Interface name + * @mac_addr: Interface MAC address + * @prod_client: IPA prod client type + * @cons_client: IPA cons client type + * @session_id: Session ID + * @is_ipv6_enabled: Is IPV6 enabled or not + * + * Return: QDF_STATUS + */ +static inline QDF_STATUS +cdp_ipa_setup_iface(ol_txrx_soc_handle soc, char *ifname, uint8_t *mac_addr, + enum ipa_client_type prod_client, + enum ipa_client_type cons_client, + uint8_t session_id, bool is_ipv6_enabled) +{ + if (!soc || !soc->ops || !soc->ops->ipa_ops) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, + "%s invalid instance", __func__); + return QDF_STATUS_E_FAILURE; + } + + if (soc->ops->ipa_ops->ipa_setup_iface) + return soc->ops->ipa_ops->ipa_setup_iface(ifname, mac_addr, + prod_client, + cons_client, + session_id, + is_ipv6_enabled); + + return QDF_STATUS_SUCCESS; +} + +/** + * cdp_ipa_cleanup_iface() - Cleanup IPA header and deregister interface + * @soc: data path soc handle + * @ifname: Interface name + * @is_ipv6_enabled: Is IPV6 enabled or not + * + * Return: QDF_STATUS + */ +static inline QDF_STATUS +cdp_ipa_cleanup_iface(ol_txrx_soc_handle soc, char *ifname, + bool is_ipv6_enabled) +{ + if (!soc || !soc->ops || !soc->ops->ipa_ops) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, + "%s invalid instance", __func__); + return QDF_STATUS_E_FAILURE; + } + + if (soc->ops->ipa_ops->ipa_cleanup_iface) + return soc->ops->ipa_ops->ipa_cleanup_iface(ifname, + is_ipv6_enabled); + + return QDF_STATUS_SUCCESS; +} + + /** + * cdp_ipa_uc_enable_pipes() - Enable and resume traffic on Tx/Rx pipes + * @soc: data path soc handle + * @pdev: handle to the device instance + * + * Return: QDF_STATUS + */ +static inline QDF_STATUS +cdp_ipa_enable_pipes(ol_txrx_soc_handle soc, struct cdp_pdev *pdev) +{ + if (!soc || !soc->ops || !soc->ops->ipa_ops || !pdev) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, + "%s invalid instance", __func__); + return QDF_STATUS_E_FAILURE; + } + + if (soc->ops->ipa_ops->ipa_enable_pipes) + return soc->ops->ipa_ops->ipa_enable_pipes(pdev); + + return QDF_STATUS_SUCCESS; +} + +/** + * cdp_ipa_uc_disable_pipes() - Suspend traffic and disable Tx/Rx pipes + * @soc: data path soc handle + * @pdev: handle to the device instance + * + * Return: QDF_STATUS + */ +static inline QDF_STATUS +cdp_ipa_disable_pipes(ol_txrx_soc_handle soc, struct cdp_pdev *pdev) +{ + if (!soc || !soc->ops || !soc->ops->ipa_ops || !pdev) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, + "%s invalid instance", __func__); + return QDF_STATUS_E_FAILURE; + } + + if (soc->ops->ipa_ops->ipa_disable_pipes) + return soc->ops->ipa_ops->ipa_disable_pipes(pdev); + + return QDF_STATUS_SUCCESS; +} + +/** + * cdp_ipa_set_perf_level() - Set IPA clock bandwidth based on data rates + * @soc: data path soc handle + * @client: WLAN Client ID + * @max_supported_bw_mbps: Maximum bandwidth needed (in Mbps) + * + * Return: 0 on success, negative errno on error + */ +static inline QDF_STATUS +cdp_ipa_set_perf_level(ol_txrx_soc_handle soc, int client, + uint32_t max_supported_bw_mbps) +{ + if (!soc || !soc->ops || !soc->ops->ipa_ops) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, + "%s invalid instance", __func__); + return QDF_STATUS_E_FAILURE; + } + + if (soc->ops->ipa_ops->ipa_set_perf_level) + return soc->ops->ipa_ops->ipa_set_perf_level(client, + max_supported_bw_mbps); + + return QDF_STATUS_SUCCESS; +} +#endif /* IPA_OFFLOAD */ + #endif /* _CDP_TXRX_IPA_H_ */ diff --git a/dp/inc/cdp_txrx_mob_def.h b/dp/inc/cdp_txrx_mob_def.h index 00ec12057a..74e1811ab8 100644 --- a/dp/inc/cdp_txrx_mob_def.h +++ b/dp/inc/cdp_txrx_mob_def.h @@ -246,6 +246,7 @@ struct txrx_pdev_cfg_param_t { struct ol_tx_sched_wrr_ac_specs_t ac_specs[TX_WMM_AC_NUM]; }; +#ifdef IPA_OFFLOAD /** * ol_txrx_ipa_resources - Resources needed for IPA */ @@ -267,7 +268,15 @@ struct ol_txrx_ipa_resources { uint32_t rx2_rdy_ring_size; qdf_dma_addr_t rx2_proc_done_idx_paddr; void *rx2_proc_done_idx_vaddr; + + /* IPA UC doorbell registers paddr */ + qdf_dma_addr_t tx_comp_doorbell_paddr; + qdf_dma_addr_t rx_ready_doorbell_paddr; + + uint32_t tx_pipe_handle; + uint32_t rx_pipe_handle; }; +#endif struct ol_txrx_ocb_chan_info { uint32_t chan_freq; @@ -401,7 +410,7 @@ typedef void (*tx_pause_callback)(uint8_t vdev_id, enum netif_action_type action, enum netif_reason_type reason); -typedef void (*ipa_op_cb_type)(uint8_t *op_msg, +typedef void (*ipa_uc_op_cb_type)(uint8_t *op_msg, void *osif_ctxt); #endif /* __CDP_TXRX_MOB_DEF_H */ diff --git a/dp/inc/cdp_txrx_ops.h b/dp/inc/cdp_txrx_ops.h index 21c98473db..fe55a7669b 100644 --- a/dp/inc/cdp_txrx_ops.h +++ b/dp/inc/cdp_txrx_ops.h @@ -25,7 +25,6 @@ #ifndef _CDP_TXRX_CMN_OPS_H_ #define _CDP_TXRX_CMN_OPS_H_ - #include #ifdef CONFIG_WIN #include @@ -33,6 +32,9 @@ #include "cdp_txrx_handle.h" #include #include "wlan_objmgr_psoc_obj.h" +#ifdef IPA_OFFLOAD +#include +#endif /****************************************************************************** * @@ -757,6 +759,7 @@ struct cdp_lflowctl_ops { void (*vdev_unpause)(struct cdp_vdev *vdev, uint32_t reason); }; +#ifdef IPA_OFFLOAD /** * struct cdp_ipa_ops - mcl ipa data path ops * @ipa_get_resource: @@ -768,26 +771,43 @@ struct cdp_lflowctl_ops { * @ipa_tx_data_frame: */ struct cdp_ipa_ops { - void (*ipa_get_resource)(struct cdp_pdev *pdev, - struct ol_txrx_ipa_resources *ipa_res); - void (*ipa_set_doorbell_paddr)(struct cdp_pdev *pdev, - qdf_dma_addr_t ipa_tx_uc_doorbell_paddr, - qdf_dma_addr_t ipa_rx_uc_doorbell_paddr); - void (*ipa_set_active)(struct cdp_pdev *pdev, - bool uc_active, bool is_tx); - void (*ipa_op_response)(struct cdp_pdev *pdev, uint8_t *op_msg); - void (*ipa_register_op_cb)(struct cdp_pdev *pdev, + QDF_STATUS (*ipa_get_resource)(struct cdp_pdev *pdev); + QDF_STATUS (*ipa_set_doorbell_paddr)(struct cdp_pdev *pdev); + QDF_STATUS (*ipa_set_active)(struct cdp_pdev *pdev, bool uc_active, + bool is_tx); + QDF_STATUS (*ipa_op_response)(struct cdp_pdev *pdev, uint8_t *op_msg); + QDF_STATUS (*ipa_register_op_cb)(struct cdp_pdev *pdev, void (*ipa_uc_op_cb_type)(uint8_t *op_msg, void *osif_ctxt), - void *osif_dev); - void (*ipa_get_stat)(struct cdp_pdev *pdev); + void *usr_ctxt); + QDF_STATUS (*ipa_get_stat)(struct cdp_pdev *pdev); qdf_nbuf_t (*ipa_tx_data_frame)(struct cdp_vdev *vdev, qdf_nbuf_t skb); - void (*ipa_set_uc_tx_partition_base)(struct cdp_cfg *cfg_pdev, + void (*ipa_set_uc_tx_partition_base)(struct cdp_cfg *pdev, uint32_t value); - void (*ipa_uc_get_share_stats)(struct cdp_pdev *pdev, +#ifdef FEATURE_METERING + QDF_STATUS (*ipa_uc_get_share_stats)(struct cdp_pdev *pdev, uint8_t reset_stats); - void (*ipa_uc_set_quota)(struct cdp_pdev *pdev, + QDF_STATUS (*ipa_uc_set_quota)(struct cdp_pdev *pdev, uint64_t quota_bytes); +#endif + QDF_STATUS (*ipa_enable_autonomy)(struct cdp_pdev *pdev); + QDF_STATUS (*ipa_disable_autonomy)(struct cdp_pdev *pdev); + QDF_STATUS (*ipa_setup)(struct cdp_pdev *pdev, void *ipa_i2w_cb, + void *ipa_w2i_cb, void *ipa_wdi_meter_notifier_cb, + uint32_t ipa_desc_size, void *ipa_priv, bool is_rm_enabled, + uint32_t *tx_pipe_handle, uint32_t *rx_pipe_handle); + QDF_STATUS (*ipa_cleanup)(uint32_t tx_pipe_handle, + uint32_t rx_pipe_handle); + QDF_STATUS (*ipa_setup_iface)(char *ifname, uint8_t *mac_addr, + enum ipa_client_type prod_client, + enum ipa_client_type cons_client, + uint8_t session_id, bool is_ipv6_enabled); + QDF_STATUS (*ipa_cleanup_iface)(char *ifname, bool is_ipv6_enabled); + QDF_STATUS (*ipa_enable_pipes)(struct cdp_pdev *pdev); + QDF_STATUS (*ipa_disable_pipes)(struct cdp_pdev *pdev); + QDF_STATUS (*ipa_set_perf_level)(int client, + uint32_t max_supported_bw_mbps); }; +#endif /** * struct cdp_bus_ops - mcl bus suspend/resume ops @@ -919,7 +939,9 @@ struct cdp_ops { struct cdp_cfg_ops *cfg_ops; struct cdp_flowctl_ops *flowctl_ops; struct cdp_lflowctl_ops *l_flowctl_ops; +#ifdef IPA_OFFLOAD struct cdp_ipa_ops *ipa_ops; +#endif struct cdp_bus_ops *bus_ops; struct cdp_ocb_ops *ocb_ops; struct cdp_peer_ops *peer_ops; diff --git a/dp/wifi3.0/dp_htt.c b/dp/wifi3.0/dp_htt.c index f717881582..36e573f03e 100644 --- a/dp/wifi3.0/dp_htt.c +++ b/dp/wifi3.0/dp_htt.c @@ -367,25 +367,35 @@ int htt_srng_setup(void *htt_soc, int mac_id, void *hal_srng, case RXDMA_BUF: #ifdef QCA_HOST2FW_RXBUF_RING if (srng_params.ring_id == - (HAL_SRNG_WMAC1_SW2RXDMA0_BUF)) { + (HAL_SRNG_WMAC1_SW2RXDMA0_BUF0)) { htt_ring_id = HTT_HOST1_TO_FW_RXBUF_RING; htt_ring_type = HTT_SW_TO_SW_RING; +#ifdef IPA_OFFLOAD + } else if (srng_params.ring_id == + (HAL_SRNG_WMAC1_SW2RXDMA0_BUF2)) { + htt_ring_id = HTT_HOST2_TO_FW_RXBUF_RING; + htt_ring_type = HTT_SW_TO_SW_RING; +#endif #else if (srng_params.ring_id == - (HAL_SRNG_WMAC1_SW2RXDMA0_BUF + + (HAL_SRNG_WMAC1_SW2RXDMA0_BUF0 + (mac_id * HAL_MAX_RINGS_PER_LMAC))) { htt_ring_id = HTT_RXDMA_HOST_BUF_RING; htt_ring_type = HTT_SW_TO_HW_RING; #endif } else if (srng_params.ring_id == +#ifdef IPA_OFFLOAD + (HAL_SRNG_WMAC1_SW2RXDMA0_BUF1 + +#else (HAL_SRNG_WMAC1_SW2RXDMA1_BUF + +#endif (mac_id * HAL_MAX_RINGS_PER_LMAC))) { htt_ring_id = HTT_RXDMA_HOST_BUF_RING; htt_ring_type = HTT_SW_TO_HW_RING; } else { QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, - "%s: Ring %d currently not supported\n", - __func__, srng_params.ring_id); + "%s: Ring %d currently not supported\n", + __func__, srng_params.ring_id); goto fail1; } diff --git a/dp/wifi3.0/dp_internal.h b/dp/wifi3.0/dp_internal.h index d6f241fed7..773f327815 100644 --- a/dp/wifi3.0/dp_internal.h +++ b/dp/wifi3.0/dp_internal.h @@ -252,6 +252,7 @@ void *dp_peer_find_by_local_id(struct cdp_pdev *pdev_handle, uint8_t local_id); QDF_STATUS dp_peer_state_update(struct cdp_pdev *pdev_handle, uint8_t *peer_mac, enum ol_txrx_peer_state state); QDF_STATUS dp_get_vdevid(void *peer_handle, uint8_t *vdev_id); +struct cdp_vdev *dp_get_vdev_by_sta_id(uint8_t sta_id); struct cdp_vdev *dp_get_vdev_for_peer(void *peer); uint8_t *dp_peer_get_peer_mac_addr(void *peer); int dp_get_peer_state(void *peer_handle); diff --git a/dp/wifi3.0/dp_ipa.c b/dp/wifi3.0/dp_ipa.c new file mode 100644 index 0000000000..b8ff525c50 --- /dev/null +++ b/dp/wifi3.0/dp_ipa.c @@ -0,0 +1,548 @@ +/* + * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. +*/ + +#ifdef IPA_OFFLOAD + +#include +#include +#include +#include +#include +#include +#include +#include +#include "dp_types.h" +#include "dp_tx.h" +#include "dp_ipa.h" + +/** + * dp_ipa_uc_get_resource() - Client request resource information + * @ppdev - handle to the device instance + * + * IPA client will request IPA UC related resource information + * Resource information will be distributed to IPA module + * All of the required resources should be pre-allocated + * + * Return: QDF_STATUS + */ +QDF_STATUS dp_ipa_get_resource(struct cdp_pdev *ppdev) +{ + struct dp_pdev *pdev = (struct dp_pdev *)ppdev; + struct dp_soc *soc = pdev->soc; + struct dp_ipa_resources *ipa_res = &pdev->ipa_resource; + + ipa_res->tx_ring_base_paddr = + soc->ipa_uc_tx_rsc.ipa_tcl_ring_base_paddr; + ipa_res->tx_ring_size = + soc->ipa_uc_tx_rsc.ipa_tcl_ring_size; + ipa_res->tx_num_alloc_buffer = + (uint32_t)soc->ipa_uc_tx_rsc.alloc_tx_buf_cnt; + + ipa_res->tx_comp_ring_base_paddr = + soc->ipa_uc_tx_rsc.ipa_wbm_ring_base_paddr; + ipa_res->tx_comp_ring_size = + soc->ipa_uc_tx_rsc.ipa_wbm_ring_size; + + ipa_res->rx_rdy_ring_base_paddr = + soc->ipa_uc_rx_rsc.ipa_reo_ring_base_paddr; + ipa_res->rx_rdy_ring_size = + soc->ipa_uc_rx_rsc.ipa_reo_ring_size; + + ipa_res->rx_refill_ring_base_paddr = + soc->ipa_uc_rx_rsc.ipa_rx_refill_buf_ring_base_paddr; + ipa_res->rx_refill_ring_size = + soc->ipa_uc_rx_rsc.ipa_rx_refill_buf_ring_size; + + if ((0 == ipa_res->tx_comp_ring_base_paddr) || + (0 == ipa_res->rx_rdy_ring_base_paddr)) + return QDF_STATUS_E_FAILURE; + + return QDF_STATUS_SUCCESS; +} + +/** + * dp_ipa_set_doorbell_paddr () - Set doorbell register physical address to SRNG + * @ppdev - handle to the device instance + * + * Set TX_COMP_DOORBELL register physical address to WBM Head_Ptr_MemAddr_LSB + * Set RX_READ_DOORBELL register physical address to REO Head_Ptr_MemAddr_LSB + * + * Return: none + */ +QDF_STATUS dp_ipa_set_doorbell_paddr(struct cdp_pdev *ppdev) +{ + struct dp_pdev *pdev = (struct dp_pdev *)ppdev; + struct dp_soc *soc = pdev->soc; + struct dp_ipa_resources *ipa_res = &pdev->ipa_resource; + + hal_srng_set_hp_paddr(soc->tx_comp_ring[IPA_TX_COMP_RING_IDX]. + hal_srng, ipa_res->tx_comp_doorbell_paddr); + hal_srng_set_hp_paddr(soc->reo_dest_ring[IPA_REO_DEST_RING_IDX]. + hal_srng, ipa_res->rx_ready_doorbell_paddr); + + return QDF_STATUS_SUCCESS; +} + +/** + * dp_ipa_op_response() - Handle OP command response from firmware + * @ppdev - handle to the device instance + * @op_msg: op response message from firmware + * + * Return: none + */ +QDF_STATUS dp_ipa_op_response(struct cdp_pdev *ppdev, uint8_t *op_msg) +{ + struct dp_pdev *pdev = (struct dp_pdev *)ppdev; + + if (pdev->ipa_uc_op_cb) { + pdev->ipa_uc_op_cb(op_msg, pdev->usr_ctxt); + } else { + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, + "%s: IPA callback function is not registered", __func__); + qdf_mem_free(op_msg); + return QDF_STATUS_E_FAILURE; + } + + return QDF_STATUS_SUCCESS; +} + +/** + * dp_ipa_register_op_cb() - Register OP handler function + * @ppdev - handle to the device instance + * @op_cb: handler function pointer + * + * Return: none + */ +QDF_STATUS dp_ipa_register_op_cb(struct cdp_pdev *ppdev, + ipa_uc_op_cb_type op_cb, + void *usr_ctxt) +{ + struct dp_pdev *pdev = (struct dp_pdev *)ppdev; + + pdev->ipa_uc_op_cb = op_cb; + pdev->usr_ctxt = usr_ctxt; + + return QDF_STATUS_SUCCESS; +} + +/** + * dp_ipa_get_stat() - Get firmware wdi status + * @ppdev - handle to the device instance + * + * Return: none + */ +QDF_STATUS dp_ipa_get_stat(struct cdp_pdev *ppdev) +{ + /* TBD */ + return QDF_STATUS_SUCCESS; +} + +/** + * dp_tx_send_ipa_data_frame() - send IPA data frame + * @vdev: vdev + * @skb: skb + * + * Return: skb/ NULL is for success + */ +qdf_nbuf_t dp_tx_send_ipa_data_frame(struct cdp_vdev *vdev, qdf_nbuf_t skb) +{ + qdf_nbuf_t ret; + + /* Terminate the (single-element) list of tx frames */ + qdf_nbuf_set_next(skb, NULL); + ret = dp_tx_send((struct dp_vdev_t *)vdev, skb); + if (ret) { + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, + "Failed to tx"); + return ret; + } + + return NULL; +} + +/** + * dp_ipa_enable_autonomy() – Enable autonomy RX path + * @pdev - handle to the device instance + * + * Set all RX packet route to IPA REO ring + * Program Destination_Ring_Ctrl_IX_0 REO register to point IPA REO ring + * Return: none + */ +QDF_STATUS dp_ipa_enable_autonomy(struct cdp_pdev *ppdev) +{ + struct dp_pdev *pdev = (struct dp_pdev *)ppdev; + struct dp_soc *soc = pdev->soc; + uint32_t remap_val; + + /* Call HAL API to remap REO rings to REO2IPA ring */ + remap_val = HAL_REO_REMAP_VAL(REO_REMAP_TCL, REO_REMAP_TCL) | + HAL_REO_REMAP_VAL(REO_REMAP_SW1, REO_REMAP_SW4) | + HAL_REO_REMAP_VAL(REO_REMAP_SW2, REO_REMAP_SW4) | + HAL_REO_REMAP_VAL(REO_REMAP_SW3, REO_REMAP_SW4) | + HAL_REO_REMAP_VAL(REO_REMAP_SW4, REO_REMAP_SW4) | + HAL_REO_REMAP_VAL(REO_REMAP_RELEASE, REO_REMAP_RELEASE) | + HAL_REO_REMAP_VAL(REO_REMAP_FW, REO_REMAP_FW) | + HAL_REO_REMAP_VAL(REO_REMAP_UNUSED, REO_REMAP_FW); + hal_reo_remap_IX0(soc->hal_soc, remap_val); + + return QDF_STATUS_SUCCESS; +} + +/** + * dp_ipa_disable_autonomy() – Disable autonomy RX path + * @ppdev - handle to the device instance + * + * Disable RX packet routing to IPA REO + * Program Destination_Ring_Ctrl_IX_0 REO register to disable + * Return: none + */ +QDF_STATUS dp_ipa_disable_autonomy(struct cdp_pdev *ppdev) +{ + struct dp_pdev *pdev = (struct dp_pdev *)ppdev; + struct dp_soc *soc = pdev->soc; + uint32_t remap_val; + + /* Call HAL API to remap REO rings to REO2IPA ring */ + remap_val = HAL_REO_REMAP_VAL(REO_REMAP_TCL, REO_REMAP_TCL) | + HAL_REO_REMAP_VAL(REO_REMAP_SW1, REO_REMAP_SW1) | + HAL_REO_REMAP_VAL(REO_REMAP_SW2, REO_REMAP_SW2) | + HAL_REO_REMAP_VAL(REO_REMAP_SW3, REO_REMAP_SW3) | + HAL_REO_REMAP_VAL(REO_REMAP_SW4, REO_REMAP_SW2) | + HAL_REO_REMAP_VAL(REO_REMAP_RELEASE, REO_REMAP_RELEASE) | + HAL_REO_REMAP_VAL(REO_REMAP_FW, REO_REMAP_FW) | + HAL_REO_REMAP_VAL(REO_REMAP_UNUSED, REO_REMAP_FW); + hal_reo_remap_IX0(soc->hal_soc, remap_val); + + return QDF_STATUS_SUCCESS; +} + +/* This should be configurable per H/W configuration enable status */ +#define L3_HEADER_PADDING 2 + +/** + * dp_ipa_setup() - Setup and connect IPA pipes + * @ppdev - handle to the device instance + * @ipa_i2w_cb: IPA to WLAN callback + * @ipa_w2i_cb: WLAN to IPA callback + * @ipa_wdi_meter_notifier_cb: IPA WDI metering callback + * @ipa_desc_size: IPA descriptor size + * @ipa_priv: handle to the HTT instance + * @is_rm_enabled: Is IPA RM enabled or not + * @tx_pipe_handle: pointer to Tx pipe handle + * @rx_pipe_handle: pointer to Rx pipe handle + * + * Return: QDF_STATUS + */ +QDF_STATUS dp_ipa_setup(struct cdp_pdev *ppdev, void *ipa_i2w_cb, + void *ipa_w2i_cb, void *ipa_wdi_meter_notifier_cb, + uint32_t ipa_desc_size, void *ipa_priv, + bool is_rm_enabled, uint32_t *tx_pipe_handle, + uint32_t *rx_pipe_handle) +{ + struct dp_pdev *pdev = (struct dp_pdev *)ppdev; + struct dp_soc *soc = pdev->soc; + struct dp_ipa_resources *ipa_res = &pdev->ipa_resource; + struct ipa_wdi3_setup_info tx; + struct ipa_wdi3_setup_info rx; + struct ipa_wdi3_conn_in_params pipe_in; + struct ipa_wdi3_conn_out_params pipe_out; + int ret; + + qdf_mem_zero(&pipe_in, sizeof(struct ipa_wdi3_conn_in_params)); + qdf_mem_zero(&pipe_out, sizeof(struct ipa_wdi3_conn_out_params)); + + /* TX PIPE */ + /** + * Transfer Ring: WBM Ring + * Transfer Ring Doorbell PA: WBM Tail Pointer Address + * Event Ring: TCL ring + * Event Ring Doorbell PA: TCL Head Pointer Address + */ + tx.ipa_ep_cfg.nat.nat_en = IPA_BYPASS_NAT; + tx.ipa_ep_cfg.hdr.hdr_len = DP_IPA_UC_WLAN_TX_HDR_LEN; + tx.ipa_ep_cfg.hdr.hdr_ofst_pkt_size_valid = 0; + tx.ipa_ep_cfg.hdr.hdr_ofst_pkt_size = 0; + tx.ipa_ep_cfg.hdr.hdr_additional_const_len = 0; + tx.ipa_ep_cfg.mode.mode = IPA_BASIC; + tx.ipa_ep_cfg.hdr_ext.hdr_little_endian = true; + tx.client = IPA_CLIENT_WLAN1_CONS; + tx.transfer_ring_base_pa = ipa_res->tx_comp_ring_base_paddr; + tx.transfer_ring_size = ipa_res->tx_comp_ring_size; + tx.transfer_ring_doorbell_pa = /* WBM Tail Pointer Address */ + soc->ipa_uc_tx_rsc.ipa_wbm_tp_paddr; + tx.event_ring_base_pa = ipa_res->tx_ring_base_paddr; + tx.event_ring_size = ipa_res->tx_ring_size; + tx.event_ring_doorbell_pa = /* TCL Head Pointer Address */ + soc->ipa_uc_tx_rsc.ipa_tcl_hp_paddr; + tx.num_pkt_buffers = ipa_res->tx_num_alloc_buffer; + tx.pkt_offset = 0; + + /* RX PIPE */ + /** + * Transfer Ring: REO Ring + * Transfer Ring Doorbell PA: REO Tail Pointer Address + * Event Ring: FW ring + * Event Ring Doorbell PA: FW Head Pointer Address + */ + rx.ipa_ep_cfg.nat.nat_en = IPA_BYPASS_NAT; + rx.ipa_ep_cfg.hdr.hdr_len = DP_IPA_UC_WLAN_RX_HDR_LEN; + rx.ipa_ep_cfg.hdr.hdr_ofst_metadata_valid = 0; + rx.ipa_ep_cfg.hdr.hdr_metadata_reg_valid = 1; + rx.ipa_ep_cfg.mode.mode = IPA_BASIC; + rx.client = IPA_CLIENT_WLAN1_PROD; + rx.transfer_ring_base_pa = ipa_res->rx_rdy_ring_base_paddr; + rx.transfer_ring_size = ipa_res->rx_rdy_ring_size; + rx.transfer_ring_doorbell_pa = /* REO Tail Pointer Address */ + soc->ipa_uc_rx_rsc.ipa_reo_tp_paddr; + rx.event_ring_base_pa = ipa_res->rx_refill_ring_base_paddr; + rx.event_ring_size = ipa_res->rx_refill_ring_size; + rx.event_ring_doorbell_pa = /* FW Head Pointer Address */ + soc->ipa_uc_rx_rsc.ipa_rx_refill_buf_hp_paddr; + rx.pkt_offset = RX_PKT_TLVS_LEN + L3_HEADER_PADDING; + + pipe_in.notify = ipa_w2i_cb; + pipe_in.priv = ipa_priv; + memcpy(&pipe_in.tx, &tx, sizeof(struct ipa_wdi3_setup_info)); + memcpy(&pipe_in.rx, &rx, sizeof(struct ipa_wdi3_setup_info)); + + /* Connect WDI IPA PIPE */ + ret = ipa_wdi3_conn_pipes(&pipe_in, &pipe_out); + if (ret) { + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, + "ipa_wdi3_conn_pipes: IPA pipe setup failed: ret=%d", + ret); + return QDF_STATUS_E_FAILURE; + } + + /* IPA uC Doorbell registers */ + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG, + "Tx DB PA=0x%x, Rx DB PA=0x%x", + (unsigned int)pipe_out.tx_uc_db_pa, + (unsigned int)pipe_out.rx_uc_db_pa); + + ipa_res->tx_comp_doorbell_paddr = pipe_out.tx_uc_db_pa; + ipa_res->rx_ready_doorbell_paddr = pipe_out.rx_uc_db_pa; + + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG, + "Tx: %s=%p, %s=%d, %s=%p, %s=%p, %s=%d, %s=%p, %s=%d, %s=%p", + "transfer_ring_base_pa", + (void *)pipe_in.tx.transfer_ring_base_pa, + "transfer_ring_size", + pipe_in.tx.transfer_ring_size, + "transfer_ring_doorbell_pa", + (void *)pipe_in.tx.transfer_ring_doorbell_pa, + "event_ring_base_pa", + (void *)pipe_in.tx.event_ring_base_pa, + "event_ring_size", + pipe_in.tx.event_ring_size, + "event_ring_doorbell_pa", + (void *)pipe_in.tx.event_ring_doorbell_pa, + "num_pkt_buffers", + pipe_in.tx.num_pkt_buffers, + "tx_comp_doorbell_paddr", + (void *)ipa_res->tx_comp_doorbell_paddr); + + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG, + "Rx: %s=%p, %s=%d, %s=%p, %s=%p, %s=%d, %s=%p, %s=%d, %s=%p", + "transfer_ring_base_pa", + (void *)pipe_in.rx.transfer_ring_base_pa, + "transfer_ring_size", + pipe_in.rx.transfer_ring_size, + "transfer_ring_doorbell_pa", + (void *)pipe_in.rx.transfer_ring_doorbell_pa, + "event_ring_base_pa", + (void *)pipe_in.rx.event_ring_base_pa, + "event_ring_size", + pipe_in.rx.event_ring_size, + "event_ring_doorbell_pa", + (void *)pipe_in.rx.event_ring_doorbell_pa, + "num_pkt_buffers", + pipe_in.rx.num_pkt_buffers, + "tx_comp_doorbell_paddr", + (void *)ipa_res->rx_ready_doorbell_paddr); + + return QDF_STATUS_SUCCESS; +} + +/** + * dp_ipa_cleanup() - Disconnect IPA pipes + * @tx_pipe_handle: Tx pipe handle + * @rx_pipe_handle: Rx pipe handle + * + * Return: QDF_STATUS + */ +QDF_STATUS dp_ipa_cleanup(uint32_t tx_pipe_handle, uint32_t rx_pipe_handle) +{ + int ret; + + ret = ipa_wdi3_disconn_pipes(); + if (ret) { + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, + "ipa_wdi3_disconn_pipes: IPA pipe cleanup failed: ret=%d", + ret); + return QDF_STATUS_E_FAILURE; + } + + return QDF_STATUS_SUCCESS; +} + +/** + * dp_ipa_setup_iface() - Setup IPA header and register interface + * @ifname: Interface name + * @mac_addr: Interface MAC address + * @prod_client: IPA prod client type + * @cons_client: IPA cons client type + * @session_id: Session ID + * @is_ipv6_enabled: Is IPV6 enabled or not + * + * Return: QDF_STATUS + */ +QDF_STATUS dp_ipa_setup_iface(char *ifname, uint8_t *mac_addr, + enum ipa_client_type prod_client, + enum ipa_client_type cons_client, + uint8_t session_id, bool is_ipv6_enabled) +{ + struct ipa_wdi3_reg_intf_in_params in; + struct ipa_wdi3_hdr_info hdr_info; + struct dp_ipa_uc_tx_hdr uc_tx_hdr; + int ret = -EINVAL; + + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG, + "Add Partial hdr: %s, %pM", + ifname, mac_addr); + + qdf_mem_zero(&hdr_info, sizeof(struct ipa_wdi3_hdr_info)); + qdf_ether_addr_copy(uc_tx_hdr.eth.h_source, mac_addr); + + /* IPV4 header */ + uc_tx_hdr.eth.h_proto = qdf_htons(ETH_P_IP); + + hdr_info.hdr = (uint8_t *)&uc_tx_hdr; + hdr_info.hdr_len = DP_IPA_UC_WLAN_TX_HDR_LEN; + hdr_info.hdr_type = IPA_HDR_L2_ETHERNET_II; + hdr_info.dst_mac_addr_offset = DP_IPA_UC_WLAN_HDR_DES_MAC_OFFSET; + + in.netdev_name = ifname; + memcpy(&(in.hdr_info[0]), &hdr_info, sizeof(struct ipa_wdi3_hdr_info)); + in.is_meta_data_valid = 1; + in.meta_data = htonl(session_id << 16); + in.meta_data_mask = htonl(0x00FF0000); + + /* IPV6 header */ + if (is_ipv6_enabled) { + uc_tx_hdr.eth.h_proto = qdf_htons(ETH_P_IPV6); + memcpy(&(in.hdr_info[1]), &hdr_info, + sizeof(struct ipa_wdi3_hdr_info)); + } + + ret = ipa_wdi3_reg_intf(&in); + if (ret) { + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, + "ipa_wdi3_reg_intf: register IPA interface falied: ret=%d", + ret); + return QDF_STATUS_E_FAILURE; + } + + return QDF_STATUS_SUCCESS; +} + +/** + * dp_ipa_cleanup_iface() - Cleanup IPA header and deregister interface + * @ifname: Interface name + * @is_ipv6_enabled: Is IPV6 enabled or not + * + * Return: QDF_STATUS + */ +QDF_STATUS dp_ipa_cleanup_iface(char *ifname, bool is_ipv6_enabled) +{ + int ret; + + ret = ipa_wdi3_dereg_intf(ifname); + if (ret) { + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, + "ipa_wdi3_dereg_intf: IPA pipe deregistration failed: ret=%d", + ret); + return QDF_STATUS_E_FAILURE; + } + + return QDF_STATUS_SUCCESS; +} + + /** + * dp_ipa_uc_enable_pipes() - Enable and resume traffic on Tx/Rx pipes + * @ppdev - handle to the device instance + * + * Return: QDF_STATUS + */ +QDF_STATUS dp_ipa_enable_pipes(struct cdp_pdev *ppdev) +{ + QDF_STATUS result; + + result = ipa_wdi3_enable_pipes(); + if (result) { + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, + "%s: Enable WDI PIPE fail, code %d", + __func__, result); + return QDF_STATUS_E_FAILURE; + } + + return QDF_STATUS_SUCCESS; +} + +/** + * dp_ipa_uc_disable_pipes() – Suspend traffic and disable Tx/Rx pipes + * @ppdev - handle to the device instance + * + * Return: QDF_STATUS + */ +QDF_STATUS dp_ipa_disable_pipes(struct cdp_pdev *ppdev) +{ + QDF_STATUS result; + + result = ipa_wdi3_disable_pipes(); + if (result) { + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, + "%s: Disable WDI PIPE fail, code %d", + __func__, result); + return QDF_STATUS_E_FAILURE; + } + + return QDF_STATUS_SUCCESS; +} + +/** + * dp_ipa_set_perf_level() - Set IPA clock bandwidth based on data rates + * @client: Client type + * @max_supported_bw_mbps: Maximum bandwidth needed (in Mbps) + * + * Return: QDF_STATUS + */ +QDF_STATUS dp_ipa_set_perf_level(int client, uint32_t max_supported_bw_mbps) +{ + struct ipa_wdi3_perf_profile profile; + QDF_STATUS result; + + profile.client = client; + profile.max_supported_bw_mbps = max_supported_bw_mbps; + + result = ipa_wdi3_set_perf_profile(&profile); + if (result) { + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, + "%s: ipa_wdi3_set_perf_profile fail, code %d", + __func__, result); + return QDF_STATUS_E_FAILURE; + } + + return QDF_STATUS_SUCCESS; +} +#endif diff --git a/dp/wifi3.0/dp_ipa.h b/dp/wifi3.0/dp_ipa.h new file mode 100644 index 0000000000..82de687da0 --- /dev/null +++ b/dp/wifi3.0/dp_ipa.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _DP_IPA_H_ +#define _DP_IPA_H_ + +#ifdef IPA_OFFLOAD + +#define IPA_TCL_DATA_RING_IDX 2 +#define IPA_TX_COMP_RING_IDX 2 +#define IPA_REO_DEST_RING_IDX 3 + +/** + * struct dp_ipa_uc_tx_hdr - full tx header registered to IPA hardware + * @eth: ether II header + */ +struct dp_ipa_uc_tx_hdr { + struct ethhdr eth; +} __packed; + +/** + * struct dp_ipa_uc_rx_hdr - full rx header registered to IPA hardware + * @eth: ether II header + */ +struct dp_ipa_uc_rx_hdr { + struct ethhdr eth; +} __packed; + +#define DP_IPA_UC_WLAN_TX_HDR_LEN sizeof(struct dp_ipa_uc_tx_hdr) +#define DP_IPA_UC_WLAN_RX_HDR_LEN sizeof(struct dp_ipa_uc_rx_hdr) +#define DP_IPA_UC_WLAN_HDR_DES_MAC_OFFSET 0 + +QDF_STATUS dp_ipa_get_resource(struct cdp_pdev *pdev); +QDF_STATUS dp_ipa_set_doorbell_paddr(struct cdp_pdev *pdev); +QDF_STATUS dp_ipa_uc_set_active(struct cdp_pdev *pdev, bool uc_active, + bool is_tx); +QDF_STATUS dp_ipa_op_response(struct cdp_pdev *pdev, uint8_t *op_msg); +QDF_STATUS dp_ipa_register_op_cb(struct cdp_pdev *pdev, ipa_uc_op_cb_type op_cb, + void *usr_ctxt); +QDF_STATUS dp_ipa_get_stat(struct cdp_pdev *pdev); +qdf_nbuf_t dp_tx_send_ipa_data_frame(struct cdp_vdev *vdev, qdf_nbuf_t skb); +QDF_STATUS dp_ipa_enable_autonomy(struct cdp_pdev *pdev); +QDF_STATUS dp_ipa_disable_autonomy(struct cdp_pdev *pdev); +QDF_STATUS dp_ipa_setup(struct cdp_pdev *pdev, void *ipa_i2w_cb, + void *ipa_w2i_cb, void *ipa_wdi_meter_notifier_cb, + uint32_t ipa_desc_size, void *ipa_priv, bool is_rm_enabled, + uint32_t *tx_pipe_handle, uint32_t *rx_pipe_handle); +QDF_STATUS dp_ipa_cleanup(uint32_t tx_pipe_handle, + uint32_t rx_pipe_handle); +QDF_STATUS dp_ipa_remove_header(char *name); +int dp_ipa_add_header_info(char *ifname, uint8_t *mac_addr, + uint8_t session_id, bool is_ipv6_enabled); +int dp_ipa_register_interface(char *ifname, bool is_ipv6_enabled); +QDF_STATUS dp_ipa_setup_iface(char *ifname, uint8_t *mac_addr, + enum ipa_client_type prod_client, + enum ipa_client_type cons_client, + uint8_t session_id, bool is_ipv6_enabled); +QDF_STATUS dp_ipa_cleanup_iface(char *ifname, bool is_ipv6_enabled); +QDF_STATUS dp_ipa_enable_pipes(struct cdp_pdev *pdev); +QDF_STATUS dp_ipa_disable_pipes(struct cdp_pdev *pdev); +QDF_STATUS dp_ipa_set_perf_level(int client, + uint32_t max_supported_bw_mbps); + +#endif +#endif /* _DP_IPA_H_ */ diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index ae8dc9f209..07d78df812 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -48,6 +48,8 @@ cdp_dump_flow_pool_info(struct cdp_soc_t *soc) return; } #endif +#include +#include "dp_ipa.h" #define DP_INTR_POLL_TIMER_MS 10 #define DP_WDS_AGING_TIMER_DEFAULT_MS 6000 @@ -58,6 +60,14 @@ cdp_dump_flow_pool_info(struct cdp_soc_t *soc) #define DP_CURR_FW_STATS_AVAIL 19 #define DP_HTT_DBG_EXT_STATS_MAX 256 +#ifdef IPA_OFFLOAD +/* Exclude IPA rings from the interrupt context */ +#define TX_RING_MASK_VAL 0x7 +#define RX_RING_MASK_VAL 0x7 +#else +#define TX_RING_MASK_VAL 0xF +#define RX_RING_MASK_VAL 0xF +#endif /** * default_dscp_tid_map - Default DSCP-TID mapping * @@ -319,6 +329,8 @@ static int dp_srng_setup(struct dp_soc *soc, struct dp_srng *srng, * See if these settings need to passed from DP layer */ ring_params.flags = 0; + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO, + FL("Ring type: %d, num:%d"), ring_type, ring_num); num_entries = (num_entries > max_entries) ? max_entries : num_entries; srng->hal_srng = NULL; @@ -417,6 +429,201 @@ static void dp_srng_cleanup(struct dp_soc *soc, struct dp_srng *srng, srng->base_paddr_unaligned, 0); } +#ifdef IPA_OFFLOAD +/** + * dp_tx_ipa_uc_detach - Free autonomy TX resources + * @soc: data path instance + * @pdev: core txrx pdev context + * + * Free allocated TX buffers with WBM SRNG + * + * Return: none + */ +static void dp_tx_ipa_uc_detach(struct dp_soc *soc, struct dp_pdev *pdev) +{ + int idx; + + for (idx = 0; idx < soc->ipa_uc_tx_rsc.alloc_tx_buf_cnt; idx++) { + if (soc->ipa_uc_tx_rsc.tx_buf_pool_vaddr[idx]) + qdf_mem_free(soc->ipa_uc_tx_rsc.tx_buf_pool_vaddr[idx]); + } + + qdf_mem_free(soc->ipa_uc_tx_rsc.tx_buf_pool_vaddr); + soc->ipa_uc_tx_rsc.tx_buf_pool_vaddr = NULL; +} + +/** + * dp_rx_ipa_uc_detach - free autonomy RX resources + * @soc: data path instance + * @pdev: core txrx pdev context + * + * This function will detach DP RX into main device context + * will free DP Rx resources. + * + * Return: none + */ +static void dp_rx_ipa_uc_detach(struct dp_soc *soc, struct dp_pdev *pdev) +{ +} + +static int dp_ipa_uc_detach(struct dp_soc *soc, struct dp_pdev *pdev) +{ + /* TX resource detach */ + dp_tx_ipa_uc_detach(soc, pdev); + + /* RX resource detach */ + dp_rx_ipa_uc_detach(soc, pdev); + + dp_srng_cleanup(soc, &pdev->ipa_rx_refill_buf_ring, RXDMA_BUF, 2); + + return QDF_STATUS_SUCCESS; /* success */ +} + +/* Hard coded config parameters until dp_ops_cfg.cfg_attach implemented */ +#define CFG_IPA_UC_TX_BUF_SIZE_DEFAULT (2048) + +/** + * dp_tx_ipa_uc_attach - Allocate autonomy TX resources + * @soc: data path instance + * @pdev: Physical device handle + * + * Allocate TX buffer from non-cacheable memory + * Attache allocated TX buffers with WBM SRNG + * + * Return: int + */ +static int dp_tx_ipa_uc_attach(struct dp_soc *soc, struct dp_pdev *pdev) +{ + uint32_t tx_buffer_count; + uint32_t ring_base_align = 8; + void *buffer_vaddr_unaligned; + void *buffer_vaddr; + qdf_dma_addr_t buffer_paddr_unaligned; + qdf_dma_addr_t buffer_paddr; + void *wbm_srng = soc->tx_comp_ring[IPA_TX_COMP_RING_IDX].hal_srng; + uint32_t paddr_lo; + uint32_t paddr_hi; + void *ring_entry; + int ring_size = ((struct hal_srng *)wbm_srng)->ring_size; + int retval = QDF_STATUS_SUCCESS; + /* + * Uncomment when dp_ops_cfg.cfg_attach is implemented + * unsigned int uc_tx_buf_sz = + * dp_cfg_ipa_uc_tx_buf_size(pdev->osif_pdev); + */ + unsigned int uc_tx_buf_sz = CFG_IPA_UC_TX_BUF_SIZE_DEFAULT; + unsigned int alloc_size = uc_tx_buf_sz + ring_base_align - 1; + + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, + "requested %d buffers to be posted to wbm ring", + ring_size); + + soc->ipa_uc_tx_rsc.tx_buf_pool_vaddr = qdf_mem_malloc(ring_size * + sizeof(*soc->ipa_uc_tx_rsc.tx_buf_pool_vaddr)); + if (!soc->ipa_uc_tx_rsc.tx_buf_pool_vaddr) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, + "%s: IPA WBM Ring mem_info alloc fail", __func__); + return -ENOMEM; + } + + hal_srng_access_start(soc->hal_soc, wbm_srng); + + /* Allocate TX buffers as many as possible */ + for (tx_buffer_count = 0; + tx_buffer_count < ring_size; tx_buffer_count++) { + + ring_entry = hal_srng_src_get_next(soc->hal_soc, wbm_srng); + if (!ring_entry) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, + "Failed to get WBM ring entry\n"); + goto fail; + } + + buffer_vaddr_unaligned = qdf_mem_alloc_consistent(soc->osdev, + soc->osdev->dev, alloc_size, &buffer_paddr_unaligned); + if (!buffer_vaddr_unaligned) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, + "IPA WDI TX buffer alloc fail %d allocated\n", + tx_buffer_count); + break; + } + + buffer_vaddr = buffer_vaddr_unaligned + + ((unsigned long)buffer_vaddr_unaligned % + ring_base_align); + buffer_paddr = buffer_paddr_unaligned + + ((unsigned long)(buffer_vaddr) - + (unsigned long)buffer_vaddr_unaligned); + + paddr_lo = ((u64)buffer_paddr & 0x00000000ffffffff); + paddr_hi = ((u64)buffer_paddr & 0x0000001f00000000) >> 32; + HAL_WBM_PADDR_LO_SET(ring_entry, paddr_lo); + HAL_WBM_PADDR_HI_SET(ring_entry, paddr_hi); + + soc->ipa_uc_tx_rsc.tx_buf_pool_vaddr[tx_buffer_count] = + buffer_vaddr; + } + + hal_srng_access_end(soc->hal_soc, wbm_srng); + soc->ipa_uc_tx_rsc.alloc_tx_buf_cnt = tx_buffer_count; + + return retval; + +fail: + qdf_mem_free(soc->ipa_uc_tx_rsc.tx_buf_pool_vaddr); + return retval; +} + +/** + * dp_rx_ipa_uc_attach - Allocate autonomy RX resources + * @soc: data path instance + * @pdev: core txrx pdev context + * + * This function will attach a DP RX instance into the main + * device (SOC) context. + * + * Return: QDF_STATUS_SUCCESS: success + * QDF_STATUS_E_RESOURCES: Error return + */ +static int dp_rx_ipa_uc_attach(struct dp_soc *soc, struct dp_pdev *pdev) +{ + return QDF_STATUS_SUCCESS; +} + +static int dp_ipa_uc_attach(struct dp_soc *soc, struct dp_pdev *pdev) +{ + int error; + + /* TX resource attach */ + error = dp_tx_ipa_uc_attach(soc, pdev); + if (error) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, + "DP IPA UC TX attach fail code %d\n", error); + return error; + } + + /* RX resource attach */ + error = dp_rx_ipa_uc_attach(soc, pdev); + if (error) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, + "DP IPA UC RX attach fail code %d\n", error); + dp_tx_ipa_uc_detach(soc, pdev); + return error; + } + + return QDF_STATUS_SUCCESS; /* success */ +} +#else +static int dp_ipa_uc_detach(struct dp_soc *soc, struct dp_pdev *pdev) +{ + return QDF_STATUS_SUCCESS; +} +static int dp_ipa_uc_attach(struct dp_soc *soc, struct dp_pdev *pdev) +{ + return QDF_STATUS_SUCCESS; +} +#endif + /* TODO: Need this interface from HIF */ void *hif_get_hal_handle(void *hif_handle); @@ -578,8 +785,8 @@ static QDF_STATUS dp_soc_interrupt_attach_poll(void *txrx_soc) for (i = 0; i < wlan_cfg_get_num_contexts(soc->wlan_cfg_ctx); i++) { soc->intr_ctx[i].dp_intr_id = i; - soc->intr_ctx[i].tx_ring_mask = 0xF; - soc->intr_ctx[i].rx_ring_mask = 0xF; + soc->intr_ctx[i].tx_ring_mask = TX_RING_MASK_VAL; + soc->intr_ctx[i].rx_ring_mask = RX_RING_MASK_VAL; soc->intr_ctx[i].rx_mon_ring_mask = 0x1; soc->intr_ctx[i].rx_err_ring_mask = 0x1; soc->intr_ctx[i].rx_wbm_rel_ring_mask = 0x1; @@ -1330,6 +1537,10 @@ static int dp_soc_cmn_setup(struct dp_soc *soc) FL("dp_srng_setup failed for tcl_data_ring[%d]"), i); goto fail1; } + /* + * TBD: Set IPA WBM ring size with ini IPA UC tx buffer + * count + */ if (dp_srng_setup(soc, &soc->tx_comp_ring[i], WBM2SW_RELEASE, i, 0, tx_comp_ring_size)) { QDF_TRACE(QDF_MODULE_ID_DP, @@ -1603,6 +1814,99 @@ void dp_soc_reset_intr_mask(struct dp_soc *soc, struct dp_pdev *pdev) wlan_cfg_set_rxdma2host_ring_mask(soc->wlan_cfg_ctx, pdev->pdev_id, 0x0); } +/* + * dp_ipa_ring_resource_setup() - setup IPA ring resources + * @soc: data path SoC handle + * + * Return: none + */ +#ifdef IPA_OFFLOAD +static inline int dp_ipa_ring_resource_setup(struct dp_soc *soc, + struct dp_pdev *pdev) +{ + void *hal_srng; + struct hal_srng_params srng_params; + qdf_dma_addr_t hp_addr, tp_addr; + + /* IPA TCL_DATA Ring - HAL_SRNG_SW2TCL4 */ + hal_srng = soc->tcl_data_ring[IPA_TCL_DATA_RING_IDX].hal_srng; + hal_get_srng_params(soc->hal_soc, hal_srng, &srng_params); + + soc->ipa_uc_tx_rsc.ipa_tcl_ring_base_paddr = + srng_params.ring_base_paddr; + soc->ipa_uc_tx_rsc.ipa_tcl_ring_base_vaddr = + srng_params.ring_base_vaddr; + soc->ipa_uc_tx_rsc.ipa_tcl_ring_size = + srng_params.num_entries * srng_params.entry_size; + hp_addr = hal_srng_get_hp_addr(soc->hal_soc, hal_srng); + soc->ipa_uc_tx_rsc.ipa_tcl_hp_paddr = hp_addr; + + + /* IPA TX COMP Ring - HAL_SRNG_WBM2SW3_RELEASE */ + hal_srng = soc->tx_comp_ring[IPA_TX_COMP_RING_IDX].hal_srng; + hal_get_srng_params(soc->hal_soc, hal_srng, &srng_params); + + soc->ipa_uc_tx_rsc.ipa_wbm_ring_base_paddr = + srng_params.ring_base_paddr; + soc->ipa_uc_tx_rsc.ipa_wbm_ring_base_vaddr = + srng_params.ring_base_vaddr; + soc->ipa_uc_tx_rsc.ipa_wbm_ring_size = + srng_params.num_entries * srng_params.entry_size; + tp_addr = hal_srng_get_tp_addr(soc->hal_soc, hal_srng); + soc->ipa_uc_tx_rsc.ipa_wbm_tp_paddr = tp_addr; + + /* IPA REO_DEST Ring - HAL_SRNG_REO2SW4 */ + hal_srng = soc->reo_dest_ring[IPA_REO_DEST_RING_IDX].hal_srng; + hal_get_srng_params(soc->hal_soc, hal_srng, &srng_params); + + soc->ipa_uc_rx_rsc.ipa_reo_ring_base_paddr = + srng_params.ring_base_paddr; + soc->ipa_uc_rx_rsc.ipa_reo_ring_base_vaddr = + srng_params.ring_base_vaddr; + soc->ipa_uc_rx_rsc.ipa_reo_ring_size = + srng_params.num_entries * srng_params.entry_size; + tp_addr = hal_srng_get_tp_addr(soc->hal_soc, hal_srng); + soc->ipa_uc_rx_rsc.ipa_reo_tp_paddr = tp_addr; + + /* IPA RX_REFILL_BUF Ring - ipa_rx_refill_buf_ring */ + if (dp_srng_setup(soc, &pdev->ipa_rx_refill_buf_ring, RXDMA_BUF, 2, + pdev->pdev_id, RXDMA_BUF_RING_SIZE)) { + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, + "%s: dp_srng_setup failed IPA rx refill ring\n", + __func__); + return -EFAULT; + } + + hal_srng = pdev->ipa_rx_refill_buf_ring.hal_srng; + hal_get_srng_params(soc->hal_soc, hal_srng, &srng_params); + soc->ipa_uc_rx_rsc.ipa_rx_refill_buf_ring_base_paddr = + srng_params.ring_base_paddr; + soc->ipa_uc_rx_rsc.ipa_rx_refill_buf_ring_base_vaddr = + srng_params.ring_base_vaddr; + soc->ipa_uc_rx_rsc.ipa_rx_refill_buf_ring_size = + srng_params.num_entries * srng_params.entry_size; + hp_addr = hal_srng_get_hp_addr(soc->hal_soc, hal_srng); + soc->ipa_uc_rx_rsc.ipa_rx_refill_buf_hp_paddr = hp_addr; + + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, + "%s: ring_base_paddr:%p, ring_base_vaddr:%p" + "_entries:%d, hp_addr:%p\n", + __func__, + (void *)srng_params.ring_base_paddr, + (void *)srng_params.ring_base_vaddr, + srng_params.num_entries, + (void *)hp_addr); + + return 0; +} +#else +static inline int dp_ipa_ring_resource_setup(struct dp_soc *soc, + struct dp_pdev *pdev) +{ + return 0; +} +#endif + /* * dp_pdev_attach_wifi3() - attach txrx pdev * @osif_pdev: Opaque PDEV handle from OSIF/HDD @@ -1704,7 +2008,6 @@ static struct cdp_pdev *dp_pdev_attach_wifi3(struct cdp_soc_t *txrx_soc, soc->num_reo_dest_rings++; } - if (dp_srng_setup(soc, &pdev->rx_refill_buf_ring, RXDMA_BUF, 0, pdev_id, RXDMA_REFILL_RING_SIZE)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, @@ -1755,11 +2058,20 @@ static struct cdp_pdev *dp_pdev_attach_wifi3(struct cdp_soc_t *txrx_soc, goto fail1; } + if (dp_ipa_ring_resource_setup(soc, pdev)) + goto fail1; + + if (dp_ipa_uc_attach(soc, pdev) != QDF_STATUS_SUCCESS) { + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, + "%s: dp_ipa_uc_attach failed\n", __func__); + goto fail1; + } + /* Rx specific init */ if (dp_rx_pdev_attach(pdev)) { - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, - FL("dp_rx_pdev_attach failed ")); - goto fail0; + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, + FL("dp_rx_pdev_attach failed ")); + goto fail0; } DP_STATS_INIT(pdev); @@ -1880,7 +2192,9 @@ static void dp_pdev_detach_wifi3(struct cdp_pdev *txrx_pdev, int force) dp_neighbour_peers_detach(pdev); qdf_spinlock_destroy(&pdev->tx_mutex); - /* Setup per PDEV REO rings if configured */ + dp_ipa_uc_detach(soc, pdev); + + /* Cleanup per PDEV REO rings if configured */ if (wlan_cfg_per_pdev_rx_ring(soc->wlan_cfg_ctx)) { dp_srng_cleanup(soc, &soc->reo_dest_ring[pdev->pdev_id], REO_DST, pdev->pdev_id); @@ -1936,7 +2250,6 @@ static inline void dp_reo_desc_freelist_destroy(struct dp_soc *soc) /* * dp_soc_detach_wifi3() - Detach txrx SOC * @txrx_soc: DP SOC handle, struct cdp_soc_t is first element of struct dp_soc. - * */ static void dp_soc_detach_wifi3(void *txrx_soc) { @@ -2022,18 +2335,38 @@ static void dp_soc_detach_wifi3(void *txrx_soc) } /* -* dp_rxdma_ring_config() - configure the RX DMA rings -* -* This function is used to configure the MAC rings. -* On MCL host provides buffers in Host2FW ring -* FW refills (copies) buffers to the ring and updates -* ring_idx in register -* -* @soc: data path SoC handle -* @pdev: Physical device handle -* -* Return: void -*/ + * dp_setup_ipa_rx_refill_buf_ring() - setup IPA RX Refill buffer ring + * @soc: data path SoC handle + * @pdev: physical device handle + * + * Return: void + */ +#ifdef IPA_OFFLOAD +static inline void dp_config_ipa_rx_refill_buf_ring(struct dp_soc *soc, + struct dp_pdev *pdev) +{ + htt_srng_setup(soc->htt_handle, 0, + pdev->ipa_rx_refill_buf_ring.hal_srng, RXDMA_BUF); +} +#else +static inline void dp_config_ipa_rx_refill_buf_ring(struct dp_soc *soc, + struct dp_pdev *pdev) +{ +} +#endif + +/* + * dp_rxdma_ring_config() - configure the RX DMA rings + * + * This function is used to configure the MAC rings. + * On MCL host provides buffers in Host2FW ring + * FW refills (copies) buffers to the ring and updates + * ring_idx in register + * + * @soc: data path SoC handle + * + * Return: void + */ #ifdef QCA_HOST2FW_RXBUF_RING static void dp_rxdma_ring_config(struct dp_soc *soc) { @@ -2054,6 +2387,8 @@ static void dp_rxdma_ring_config(struct dp_soc *soc) pdev->rx_refill_buf_ring.hal_srng, RXDMA_BUF); + dp_config_ipa_rx_refill_buf_ring(soc, pdev); + if (soc->cdp_soc.ol_ops-> is_hw_dbs_2x2_capable) { dbs_enable = soc->cdp_soc.ol_ops-> @@ -4547,9 +4882,25 @@ static struct cdp_lflowctl_ops dp_ops_l_flowctl = { /* WIFI 3.0 DP NOT IMPLEMENTED YET */ }; +#ifdef IPA_OFFLOAD static struct cdp_ipa_ops dp_ops_ipa = { - /* WIFI 3.0 DP NOT IMPLEMENTED YET */ + .ipa_get_resource = dp_ipa_get_resource, + .ipa_set_doorbell_paddr = dp_ipa_set_doorbell_paddr, + .ipa_op_response = dp_ipa_op_response, + .ipa_register_op_cb = dp_ipa_register_op_cb, + .ipa_get_stat = dp_ipa_get_stat, + .ipa_tx_data_frame = dp_tx_send_ipa_data_frame, + .ipa_enable_autonomy = dp_ipa_enable_autonomy, + .ipa_disable_autonomy = dp_ipa_disable_autonomy, + .ipa_setup = dp_ipa_setup, + .ipa_cleanup = dp_ipa_cleanup, + .ipa_setup_iface = dp_ipa_setup_iface, + .ipa_cleanup_iface = dp_ipa_cleanup_iface, + .ipa_enable_pipes = dp_ipa_enable_pipes, + .ipa_disable_pipes = dp_ipa_disable_pipes, + .ipa_set_perf_level = dp_ipa_set_perf_level }; +#endif static struct cdp_bus_ops dp_ops_bus = { .bus_suspend = dp_bus_suspend, @@ -4582,6 +4933,7 @@ static struct cdp_peer_ops dp_ops_peer = { .peer_find_by_local_id = dp_peer_find_by_local_id, .peer_state_update = dp_peer_state_update, .get_vdevid = dp_get_vdevid, + .get_vdev_by_sta_id = dp_get_vdev_by_sta_id, .peer_get_peer_mac_addr = dp_peer_get_peer_mac_addr, .get_vdev_for_peer = dp_get_vdev_for_peer, .get_peer_state = dp_get_peer_state, @@ -4607,7 +4959,9 @@ static struct cdp_ops dp_txrx_ops = { .cfg_ops = &dp_ops_cfg, .flowctl_ops = &dp_ops_flowctl, .l_flowctl_ops = &dp_ops_l_flowctl, +#ifdef IPA_OFFLOAD .ipa_ops = &dp_ops_ipa, +#endif .bus_ops = &dp_ops_bus, .ocb_ops = &dp_ops_ocb, .peer_ops = &dp_ops_peer, diff --git a/dp/wifi3.0/dp_peer.c b/dp/wifi3.0/dp_peer.c index 95b7974603..13ab459859 100644 --- a/dp/wifi3.0/dp_peer.c +++ b/dp/wifi3.0/dp_peer.c @@ -26,6 +26,7 @@ #include #ifdef CONFIG_MCL #include +#include #endif #include #include @@ -1747,6 +1748,34 @@ QDF_STATUS dp_get_vdevid(void *peer_handle, uint8_t *vdev_id) return QDF_STATUS_SUCCESS; } +struct cdp_vdev *dp_get_vdev_by_sta_id(uint8_t sta_id) +{ + struct dp_peer *peer = NULL; + struct dp_pdev *pdev = NULL; + + if (sta_id >= WLAN_MAX_STA_COUNT) { + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_HIGH, + "Invalid sta id passed"); + return NULL; + } + + pdev = cds_get_context(QDF_MODULE_ID_TXRX); + if (!pdev) { + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_HIGH, + "PDEV not found for sta_id [%d]", sta_id); + return NULL; + } + + peer = dp_peer_find_by_local_id((struct cdp_pdev *)pdev, sta_id); + if (!peer) { + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_HIGH, + "PEER [%d] not found", sta_id); + return NULL; + } + + return (struct cdp_vdev *)peer->vdev; +} + /** * dp_get_vdev_for_peer() - Get virtual interface instance which peer belongs * @peer - peer instance diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index fea0eb91ca..df83bfcb63 100644 --- a/dp/wifi3.0/dp_types.h +++ b/dp/wifi3.0/dp_types.h @@ -143,7 +143,6 @@ union dp_rx_desc_list_elem_t; * hardware */ #define DP_SW2HW_MACID(id) ((id) + 1) - #define DP_HW2SW_MACID(id) ((id) > 0 ? ((id) - 1) : 0) #define DP_MAC_ADDR_LEN 6 @@ -770,7 +769,67 @@ struct dp_soc { uint32_t htt_msg_len; /* work queue to process htt stats */ qdf_work_t htt_stats_work; + +#ifdef IPA_OFFLOAD + /* IPA uC datapath offload Wlan Tx resources */ + struct { + /* Resource info to be passed to IPA */ + qdf_dma_addr_t ipa_tcl_ring_base_paddr; + void *ipa_tcl_ring_base_vaddr; + uint32_t ipa_tcl_ring_size; + qdf_dma_addr_t ipa_tcl_hp_paddr; + uint32_t alloc_tx_buf_cnt; + + qdf_dma_addr_t ipa_wbm_ring_base_paddr; + void *ipa_wbm_ring_base_vaddr; + uint32_t ipa_wbm_ring_size; + qdf_dma_addr_t ipa_wbm_tp_paddr; + + /* TX buffers populated into the WBM ring */ + void **tx_buf_pool_vaddr; + } ipa_uc_tx_rsc; + + /* IPA uC datapath offload Wlan Rx resources */ + struct { + /* Resource info to be passed to IPA */ + qdf_dma_addr_t ipa_reo_ring_base_paddr; + void *ipa_reo_ring_base_vaddr; + uint32_t ipa_reo_ring_size; + qdf_dma_addr_t ipa_reo_tp_paddr; + + /* Resource info to be passed to firmware and IPA */ + qdf_dma_addr_t ipa_rx_refill_buf_ring_base_paddr; + void *ipa_rx_refill_buf_ring_base_vaddr; + uint32_t ipa_rx_refill_buf_ring_size; + qdf_dma_addr_t ipa_rx_refill_buf_hp_paddr; + } ipa_uc_rx_rsc; +#endif }; + +#ifdef IPA_OFFLOAD +/** + * dp_ipa_resources - Resources needed for IPA + */ +struct dp_ipa_resources { + qdf_dma_addr_t tx_ring_base_paddr; + uint32_t tx_ring_size; + uint32_t tx_num_alloc_buffer; + + qdf_dma_addr_t tx_comp_ring_base_paddr; + uint32_t tx_comp_ring_size; + + qdf_dma_addr_t rx_rdy_ring_base_paddr; + uint32_t rx_rdy_ring_size; + + qdf_dma_addr_t rx_refill_ring_base_paddr; + uint32_t rx_refill_ring_size; + + /* IPA UC doorbell registers paddr */ + qdf_dma_addr_t tx_comp_doorbell_paddr; + qdf_dma_addr_t rx_ready_doorbell_paddr; +}; +#endif + #define MAX_RX_MAC_RINGS 2 /* Same as NAC_MAX_CLENT */ #define DP_NAC_MAX_CLIENT 24 @@ -811,6 +870,11 @@ struct dp_pdev { /* Ring used to replenish rx buffers (maybe to the firmware of MAC) */ struct dp_srng rx_refill_buf_ring; +#ifdef IPA_OFFLOAD + /* Ring used to replenish IPA rx buffers */ + struct dp_srng ipa_rx_refill_buf_ring; +#endif + /* Empty ring used by firmware to post rx buffers to the MAC */ struct dp_srng rx_mac_buf_ring[MAX_RX_MAC_RINGS]; @@ -930,6 +994,12 @@ struct dp_pdev { /* Number of VAPs with mcast enhancement enabled */ qdf_atomic_t mc_num_vap_attached; +#ifdef IPA_OFFLOAD + ipa_uc_op_cb_type ipa_uc_op_cb; + void *usr_ctxt; + struct dp_ipa_resources ipa_resource; +#endif + /* TBD */ /* map this pdev to a particular Reo Destination ring */ diff --git a/dp/wifi3.0/hal_rx.h b/dp/wifi3.0/hal_rx.h index 977de6d098..66adf4f039 100644 --- a/dp/wifi3.0/hal_rx.h +++ b/dp/wifi3.0/hal_rx.h @@ -172,6 +172,26 @@ enum hal_rx_ret_buf_manager { (cookie << BUFFER_ADDR_INFO_1_SW_BUFFER_COOKIE_LSB) & \ BUFFER_ADDR_INFO_1_SW_BUFFER_COOKIE_MASK) +/* + * macro to set the LSW of the nbuf data physical address + * to the WBM ring entry + */ +#define HAL_WBM_PADDR_LO_SET(buff_addr_info, paddr_lo) \ + ((*(((unsigned int *) buff_addr_info) + \ + (BUFFER_ADDR_INFO_0_BUFFER_ADDR_31_0_OFFSET >> 2))) = \ + (paddr_lo << BUFFER_ADDR_INFO_0_BUFFER_ADDR_31_0_LSB) & \ + BUFFER_ADDR_INFO_0_BUFFER_ADDR_31_0_MASK) + +/* + * macro to set the LSB of MSW of the nbuf data physical address + * to the WBM ring entry + */ +#define HAL_WBM_PADDR_HI_SET(buff_addr_info, paddr_hi) \ + ((*(((unsigned int *) buff_addr_info) + \ + (BUFFER_ADDR_INFO_1_BUFFER_ADDR_39_32_OFFSET >> 2))) = \ + (paddr_hi << BUFFER_ADDR_INFO_1_BUFFER_ADDR_39_32_LSB) & \ + BUFFER_ADDR_INFO_1_BUFFER_ADDR_39_32_MASK) + /* * macro to set the manager into the rxdma ring entry */ diff --git a/hal/wifi3.0/hal_api.h b/hal/wifi3.0/hal_api.h index 30cc3553d0..3f35fbf2b7 100644 --- a/hal/wifi3.0/hal_api.h +++ b/hal/wifi3.0/hal_api.h @@ -308,6 +308,42 @@ extern void hal_get_shadow_config(void *hal_soc, extern void *hal_srng_setup(void *hal_soc, int ring_type, int ring_num, int mac_id, struct hal_srng_params *ring_params); +/* Remapping ids of REO rings */ +#define REO_REMAP_TCL 0 +#define REO_REMAP_SW1 1 +#define REO_REMAP_SW2 2 +#define REO_REMAP_SW3 3 +#define REO_REMAP_SW4 4 +#define REO_REMAP_RELEASE 5 +#define REO_REMAP_FW 6 +#define REO_REMAP_UNUSED 7 + +/* + * currently this macro only works for IX0 since all the rings we are remapping + * can be remapped from HWIO_REO_R0_DESTINATION_RING_CTRL_IX_0 + */ +#define HAL_REO_REMAP_VAL(_ORIGINAL_DEST, _NEW_DEST) \ + HAL_REO_REMAP_VAL_(_ORIGINAL_DEST, _NEW_DEST) +/* allow the destination macros to be expanded */ +#define HAL_REO_REMAP_VAL_(_ORIGINAL_DEST, _NEW_DEST) \ + (_NEW_DEST << \ + (HWIO_REO_R0_DESTINATION_RING_CTRL_IX_0_DEST_RING_MAPPING_ ## \ + _ORIGINAL_DEST ## _SHFT)) + +/** + * hal_reo_remap_IX0 - Remap REO ring destination + * @hal: HAL SOC handle + * @remap_val: Remap value + */ +extern void hal_reo_remap_IX0(struct hal_soc *hal, uint32_t remap_val); + +/** + * hal_srng_set_hp_paddr() - Set physical address to SRNG head pointer + * @sring: sring pointer + * @paddr: physical address + */ +extern void hal_srng_set_hp_paddr(struct hal_srng *sring, uint64_t paddr); + /** * hal_srng_cleanup - Deinitialize HW SRNG ring. * @hal_soc: Opaque HAL SOC handle @@ -939,11 +975,6 @@ static inline qdf_dma_addr_t hal_srng_get_hp_addr(void *hal_soc, void *hal_ring) struct hal_srng *srng = (struct hal_srng *)hal_ring; struct hal_soc *hal = (struct hal_soc *)hal_soc; - if (!(srng->flags & HAL_SRNG_LMAC_RING)) { - /* Currently this interface is required only for LMAC rings */ - return (qdf_dma_addr_t)NULL; - } - if (srng->ring_dir == HAL_SRNG_SRC_RING) { return hal->shadow_wrptr_mem_paddr + ((unsigned long)(srng->u.src_ring.hp_addr) - @@ -967,11 +998,6 @@ static inline qdf_dma_addr_t hal_srng_get_tp_addr(void *hal_soc, void *hal_ring) struct hal_srng *srng = (struct hal_srng *)hal_ring; struct hal_soc *hal = (struct hal_soc *)hal_soc; - if (!(srng->flags & HAL_SRNG_LMAC_RING)) { - /* Currently this interface is required only for LMAC rings */ - return (qdf_dma_addr_t)NULL; - } - if (srng->ring_dir == HAL_SRNG_SRC_RING) { return hal->shadow_rdptr_mem_paddr + ((unsigned long)(srng->u.src_ring.tp_addr) - diff --git a/hal/wifi3.0/hal_internal.h b/hal/wifi3.0/hal_internal.h index 0081f1fa27..dd7f1e43af 100644 --- a/hal/wifi3.0/hal_internal.h +++ b/hal/wifi3.0/hal_internal.h @@ -150,18 +150,25 @@ enum hal_srng_ring_id { HAL_SRNG_UMAC_ID_END = 127, /* LMAC rings - The following set will be replicated for each LMAC */ HAL_SRNG_LMAC1_ID_START = 128, - HAL_SRNG_WMAC1_SW2RXDMA0_BUF = HAL_SRNG_LMAC1_ID_START, - HAL_SRNG_WMAC1_SW2RXDMA1_BUF = 129, - HAL_SRNG_WMAC1_SW2RXDMA2_BUF = 130, - HAL_SRNG_WMAC1_SW2RXDMA0_STATBUF = 131, - HAL_SRNG_WMAC1_SW2RXDMA1_STATBUF = 132, - HAL_SRNG_WMAC1_RXDMA2SW0 = 133, - HAL_SRNG_WMAC1_RXDMA2SW1 = 134, - HAL_SRNG_WMAC1_SW2RXDMA1_DESC = 135, -#ifdef WLAN_FEATURE_CIF_CFR - HAL_SRNG_WIFI_POS_SRC_DMA_RING = 136, + HAL_SRNG_WMAC1_SW2RXDMA0_BUF0 = HAL_SRNG_LMAC1_ID_START, +#ifdef IPA_OFFLOAD + HAL_SRNG_WMAC1_SW2RXDMA0_BUF1 = (HAL_SRNG_LMAC1_ID_START + 1), + HAL_SRNG_WMAC1_SW2RXDMA0_BUF2 = (HAL_SRNG_LMAC1_ID_START + 2), + HAL_SRNG_WMAC1_SW2RXDMA1_BUF = (HAL_SRNG_WMAC1_SW2RXDMA0_BUF2 + 1), +#else + HAL_SRNG_WMAC1_SW2RXDMA1_BUF = (HAL_SRNG_WMAC1_SW2RXDMA0_BUF0 + 1), #endif - /* 137-142 unused */ + HAL_SRNG_WMAC1_SW2RXDMA2_BUF = (HAL_SRNG_WMAC1_SW2RXDMA1_BUF + 1), + HAL_SRNG_WMAC1_SW2RXDMA0_STATBUF = (HAL_SRNG_WMAC1_SW2RXDMA2_BUF + 1), + HAL_SRNG_WMAC1_SW2RXDMA1_STATBUF = + (HAL_SRNG_WMAC1_SW2RXDMA0_STATBUF + 1), + HAL_SRNG_WMAC1_RXDMA2SW0 = (HAL_SRNG_WMAC1_SW2RXDMA1_STATBUF + 1), + HAL_SRNG_WMAC1_RXDMA2SW1 = (HAL_SRNG_WMAC1_RXDMA2SW0 + 1), + HAL_SRNG_WMAC1_SW2RXDMA1_DESC = (HAL_SRNG_WMAC1_RXDMA2SW1 + 1), +#ifdef WLAN_FEATURE_CIF_CFR + HAL_SRNG_WIFI_POS_SRC_DMA_RING = (HAL_SRNG_WMAC1_SW2RXDMA1_DESC + 1), +#endif + /* -142 unused */ HAL_SRNG_LMAC1_ID_END = 143 }; diff --git a/hal/wifi3.0/hal_srng.c b/hal/wifi3.0/hal_srng.c index 81c80060e6..91343f34ac 100644 --- a/hal/wifi3.0/hal_srng.c +++ b/hal/wifi3.0/hal_srng.c @@ -422,12 +422,12 @@ static struct hal_hw_srng_config hw_srng_table[] = { }, }, { /* RXDMA_BUF */ - .start_ring_id = HAL_SRNG_WMAC1_SW2RXDMA0_BUF, + .start_ring_id = HAL_SRNG_WMAC1_SW2RXDMA0_BUF0, +#ifdef IPA_OFFLOAD + .max_rings = 3, +#else .max_rings = 2, - /* TODO: Check if the additional IPA buffer ring needs to be - * setup here (in which case max_rings should be set to 2), - * or it will be setup by IPA host driver - */ +#endif .entry_size = sizeof(struct wbm_buffer_ring) >> 2, .lmac_ring = TRUE, .ring_dir = HAL_SRNG_SRC_RING, @@ -578,8 +578,8 @@ static void hal_update_srng_hp_tp_address(void *hal_soc, } QDF_STATUS hal_set_one_shadow_config(void *hal_soc, - int ring_type, - int ring_num) + int ring_type, + int ring_num) { uint32_t target_register; struct hal_soc *hal = (struct hal_soc *)hal_soc; @@ -608,9 +608,9 @@ QDF_STATUS hal_set_one_shadow_config(void *hal_soc, ring_num); QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO, - "%s: target_reg %x, shadow_index %x, ring_type %d, ring num %d\n", - __func__, target_register, shadow_config_index, - ring_type, ring_num); + "%s: target_reg %x, shadow_index %x, ring_type %d, ring num %d\n", + __func__, target_register, shadow_config_index, + ring_type, ring_num); return QDF_STATUS_SUCCESS; } @@ -813,8 +813,6 @@ extern void hal_detach(void *hal_soc) return; } - - /** * hal_srng_src_hw_init - Private function to initialize SRNG * source ring HW @@ -955,6 +953,31 @@ static inline void hal_ce_dst_setup(struct hal_soc *hal, struct hal_srng *srng, HAL_REG_WRITE(hal, reg_addr, reg_val); } +/** + * hal_reo_remap_IX0 - Remap REO ring destination + * @hal: HAL SOC handle + * @remap_val: Remap value + */ +void hal_reo_remap_IX0(struct hal_soc *hal, uint32_t remap_val) +{ + uint32_t reg_offset = HWIO_REO_R0_DESTINATION_RING_CTRL_IX_0_ADDR( + SEQ_WCSS_UMAC_REO_REG_OFFSET); + HAL_REG_WRITE(hal, reg_offset, remap_val); +} + +/** + * hal_srng_set_hp_paddr() - Set physical address to SRNG head pointer + * @sring: sring pointer + * @paddr: physical address + */ +void hal_srng_set_hp_paddr(struct hal_srng *sring, + uint64_t paddr) +{ + SRNG_DST_REG_WRITE(sring, HP_ADDR_LSB, + paddr & 0xffffffff); + SRNG_DST_REG_WRITE(sring, HP_ADDR_MSB, + paddr >> 32); +} /** * hal_srng_dst_hw_init - Private function to initialize SRNG * destination ring HW @@ -1165,9 +1188,9 @@ void *hal_srng_setup(void *hal_soc, int ring_type, int ring_num, if (CHECK_SHADOW_REGISTERS) { QDF_TRACE(QDF_MODULE_ID_TXRX, - QDF_TRACE_LEVEL_ERROR, - "%s: Ring (%d, %d) missing shadow config\n", - __func__, ring_type, ring_num); + QDF_TRACE_LEVEL_ERROR, + "%s: Ring (%d, %d) missing shadow config\n", + __func__, ring_type, ring_num); } } else { hal_validate_shadow_register(hal, @@ -1200,9 +1223,9 @@ void *hal_srng_setup(void *hal_soc, int ring_type, int ring_num, if (CHECK_SHADOW_REGISTERS) { QDF_TRACE(QDF_MODULE_ID_TXRX, - QDF_TRACE_LEVEL_ERROR, - "%s: Ring (%d, %d) missing shadow config\n", - __func__, ring_type, ring_num); + QDF_TRACE_LEVEL_ERROR, + "%s: Ring (%d, %d) missing shadow config\n", + __func__, ring_type, ring_num); } } else { hal_validate_shadow_register(hal, diff --git a/qdf/inc/qdf_mem.h b/qdf/inc/qdf_mem.h index 8f04ed6b67..e746a2681a 100644 --- a/qdf/inc/qdf_mem.h +++ b/qdf/inc/qdf_mem.h @@ -134,6 +134,8 @@ void qdf_mem_free_consistent(qdf_device_t osdev, void *dev, qdf_size_t size, void qdf_mem_zero_outline(void *buf, qdf_size_t size); +void qdf_ether_addr_copy(void *dst_addr, const void *src_addr); + /** * qdf_mem_cmp() - memory compare * @memory1: pointer to one location in memory to compare. diff --git a/qdf/linux/src/qdf_mem.c b/qdf/linux/src/qdf_mem.c index aa57c3b7b5..57e0a56b06 100644 --- a/qdf/linux/src/qdf_mem.c +++ b/qdf/linux/src/qdf_mem.c @@ -1708,3 +1708,27 @@ void qdf_mem_exit(void) qdf_mem_debug_exit(); } EXPORT_SYMBOL(qdf_mem_exit); + +/** + * qdf_ether_addr_copy() - copy an Ethernet address + * + * @dst_addr: A six-byte array Ethernet address destination + * @src_addr: A six-byte array Ethernet address source + * + * Please note: dst & src must both be aligned to u16. + * + * Return: none + */ +void qdf_ether_addr_copy(void *dst_addr, const void *src_addr) +{ + if ((dst_addr == NULL) || (src_addr == NULL)) { + QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, + "%s called with NULL parameter, source:%p destination:%p", + __func__, src_addr, dst_addr); + QDF_ASSERT(0); + return; + } + ether_addr_copy(dst_addr, src_addr); +} +EXPORT_SYMBOL(qdf_ether_addr_copy); + diff --git a/wlan_cfg/wlan_cfg.c b/wlan_cfg/wlan_cfg.c index 1bda52d31f..42dc8d337c 100644 --- a/wlan_cfg/wlan_cfg.c +++ b/wlan_cfg/wlan_cfg.c @@ -36,7 +36,11 @@ #define WLAN_CFG_PER_PDEV_RX_RING 0 #define NUM_RXDMA_RINGS_PER_PDEV 2 #define WLAN_LRO_ENABLE 1 +#ifdef IPA_OFFLOAD +#define WLAN_CFG_TX_RING_SIZE 2048 +#else #define WLAN_CFG_TX_RING_SIZE 512 +#endif #define WLAN_CFG_TX_COMP_RING_SIZE 1024 /* Tx Descriptor and Tx Extension Descriptor pool sizes */ @@ -161,7 +165,11 @@ #define WLAN_CFG_MAX_CLIENTS 64 +#ifdef IPA_OFFLOAD +#define WLAN_CFG_PER_PDEV_TX_RING 0 +#else #define WLAN_CFG_PER_PDEV_TX_RING 1 +#endif #define WLAN_CFG_NUM_TCL_DATA_RINGS 3 #define WLAN_CFG_NUM_REO_DEST_RING 4