diff --git a/components/dp/core/inc/wlan_dp_main.h b/components/dp/core/inc/wlan_dp_main.h index b92dcf96d3..0db0898a4a 100644 --- a/components/dp/core/inc/wlan_dp_main.h +++ b/components/dp/core/inc/wlan_dp_main.h @@ -27,26 +27,213 @@ #include "wlan_dp_priv.h" #include "wlan_dp_objmgr.h" +/** + * dp_allocate_ctx() - Allocate DP context + * + */ +QDF_STATUS dp_allocate_ctx(void); + +/** + * dp_free_ctx() - Free DP context + * + */ +void dp_free_ctx(void); + +/** + * dp_get_front_intf_no_lock() - Get the first interface from the intf list + * This API doesnot use any lock in it's implementation. It is the caller's + * directive to ensure concurrency safety. + * @dp_ctx: pointer to the DP context + * @out_intf: double pointer to pass the next interface + * + * Return: QDF_STATUS + */ +QDF_STATUS +dp_get_front_intf_no_lock(struct wlan_dp_psoc_context *dp_ctx, + struct wlan_dp_intf **out_intf); + +/** + * dp_get_next_intf_no_lock() - Get the next intf from the intf list + * This API doesnot use any lock in it's implementation. It is the caller's + * directive to ensure concurrency safety. + * @dp_ctx: pointer to the DP context + * @cur_intf: pointer to the current intf + * @out_intf: double pointer to pass the next intf + * + * Return: QDF_STATUS + */ +QDF_STATUS +dp_get_next_intf_no_lock(struct wlan_dp_psoc_context *dp_ctx, + struct wlan_dp_intf *cur_intf, + struct wlan_dp_intf **out_intf); + +/** + * __dp_take_ref_and_fetch_front_intf_safe - Helper macro to lock, fetch + * front and next intf, take ref and unlock. + * @dp_ctx: the global DP context + * @dp_intf: an dp_intf pointer to use as a cursor + * @dp_intf_next: dp_intf pointer to next intf + * + */ +#define __dp_take_ref_and_fetch_front_intf_safe(dp_ctx, dp_intf, \ + dp_intf_next) \ + qdf_spin_lock_bh(&dp_ctx->intf_list_lock), \ + dp_get_front_intf_no_lock(dp_ctx, &dp_intf), \ + dp_get_next_intf_no_lock(dp_ctx, dp_intf, &dp_intf_next), \ + qdf_spin_unlock_bh(&dp_ctx->intf_list_lock) + +/** + * __dp_take_ref_and_fetch_next_intf_safe - Helper macro to lock, fetch next + * interface, take ref and unlock. + * @dp_ctx: the global DP context + * @dp_intf: dp_intf pointer to use as a cursor + * @dp_intf_next: dp_intf pointer to next interface + * + */ +#define __dp_take_ref_and_fetch_next_intf_safe(dp_ctx, dp_intf, \ + dp_intf_next) \ + qdf_spin_lock_bh(&dp_ctx->intf_list_lock), \ + dp_intf = dp_intf_next, \ + dp_get_next_intf_no_lock(dp_ctx, dp_intf, &dp_intf_next), \ + qdf_spin_unlock_bh(&dp_ctx->intf_list_lock) + +/** + * __dp_is_intf_valid - Helper macro to return true/false for valid interface. + * @_dp_intf: an dp_intf pointer to use as a cursor + */ +#define __dp_is_intf_valid(_dp_intf) !!(_dp_intf) + +/** + * dp_for_each_intf_held_safe - Interface iterator called + * in a delete safe manner + * @dp_ctx: the global DP context + * @dp_intf: an dp_intf pointer to use as a cursor + * @dp_intf_next: dp_intf pointer to the next interface + * + */ +#define dp_for_each_intf_held_safe(dp_ctx, dp_intf, dp_intf_next) \ + for (__dp_take_ref_and_fetch_front_intf_safe(dp_ctx, dp_intf, \ + dp_intf_next); \ + __dp_is_intf_valid(dp_intf); \ + __dp_take_ref_and_fetch_next_intf_safe(dp_ctx, dp_intf, \ + dp_intf_next)) + +/** + * dp_get_intf_by_macaddr() - Api to Get interface from MAC address + * @dp_ctx: DP context + * @addr: MAC address + * + * Return: Pointer to DP interface. + */ struct wlan_dp_intf* dp_get_intf_by_macaddr(struct wlan_dp_psoc_context *dp_ctx, struct qdf_mac_addr *addr); +/** + * dp_vdev_obj_destroy_notification() - Free per DP vdev object + * @vdev: vdev context + * @arg: Pointer to arguments + * + * This function gets called from object manager when vdev is being + * deleted and delete DP vdev context. + * + * Return: QDF_STATUS_SUCCESS - in case of success + */ QDF_STATUS dp_vdev_obj_destroy_notification(struct wlan_objmgr_vdev *vdev, void *arg); +/** + * dp_vdev_obj_create_notification() - Allocate per DP vdev object + * @vdev: vdev context + * @arg: Pointer to arguments + * + * This function gets called from object manager when vdev is being + * created and creates DP vdev context. + * + * Return: QDF_STATUS_SUCCESS - in case of success + */ QDF_STATUS dp_vdev_obj_create_notification(struct wlan_objmgr_vdev *vdev, void *arg); +/** + * dp_pdev_obj_create_notification() - Allocate per DP pdev object + * @pdev: pdev context + * @arg: Pointer to arguments + * + * This function gets called from object manager when pdev is being + * created and creates DP pdev context. + * + * Return: QDF_STATUS_SUCCESS - in case of success + */ QDF_STATUS dp_pdev_obj_create_notification(struct wlan_objmgr_pdev *pdev, void *arg); +/** + * dp_pdev_obj_destroy_notification() - Free per DP pdev object + * @pdev: pdev context + * @arg: Pointer to arguments + * + * This function gets called from object manager when pdev is being + * deleted and delete DP pdev context. + * + * Return: QDF_STATUS_SUCCESS - in case of success + */ QDF_STATUS dp_pdev_obj_destroy_notification(struct wlan_objmgr_pdev *pdev, void *arg); +/** + * dp_psoc_obj_create_notification() - Function to allocate per DP + * psoc private object + * @psoc: psoc context + * @arg: Pointer to arguments + * + * This function gets called from object manager when psoc is being + * created and creates DP soc context. + * + * Return: QDF_STATUS_SUCCESS - in case of success + */ QDF_STATUS dp_psoc_obj_create_notification(struct wlan_objmgr_psoc *psoc, void *arg); +/** + * dp_psoc_obj_destroy_notification() - Free psoc private object + * @psoc: psoc context + * @data: Pointer to data + * + * This function gets called from object manager when psoc is being + * deleted and delete DP soc context. + * + * Return: QDF_STATUS_SUCCESS - in case of success + */ QDF_STATUS dp_psoc_obj_destroy_notification(struct wlan_objmgr_psoc *psoc, void *arg); +/** + * dp_ttach_ctx() - Api to attach dp ctx + * @dp_ctx : DP Context + * + * Helper function to attach dp ctx + * + * Return: None. + */ +void dp_attach_ctx(struct wlan_dp_psoc_context *dp_ctx); + +/** + * dp_dettach_ctx() - to dettach dp context + * + * Helper function to dettach dp context + * + * Return: None. + */ +void dp_dettach_ctx(void); + +/** + * dp_get_context() - to get dp context + * + * Helper function to get dp context + * + * Return: dp context. + */ +struct wlan_dp_psoc_context *dp_get_context(void); + #endif diff --git a/components/dp/core/inc/wlan_dp_objmgr.h b/components/dp/core/inc/wlan_dp_objmgr.h index f1747ba94e..cbc3c8f337 100644 --- a/components/dp/core/inc/wlan_dp_objmgr.h +++ b/components/dp/core/inc/wlan_dp_objmgr.h @@ -29,6 +29,20 @@ #include "wlan_objmgr_psoc_obj.h" #include "wlan_utility.h" +/* Get/Put Ref */ + +#define dp_comp_peer_get_ref(peer) wlan_objmgr_peer_try_get_ref(peer, WLAN_DP_ID) +#define dp_comp_peer_put_ref(peer) wlan_objmgr_peer_release_ref(peer, WLAN_DP_ID) + +#define dp_comp_vdev_get_ref(vdev) wlan_objmgr_vdev_try_get_ref(vdev, WLAN_DP_ID) +#define dp_comp_vdev_put_ref(vdev) wlan_objmgr_vdev_release_ref(vdev, WLAN_DP_ID) + +#define dp_comp_pdev_get_ref(pdev) wlan_objmgr_pdev_try_get_ref(pdev, WLAN_DP_ID) +#define dp_comp_pdev_put_ref(pdev) wlan_objmgr_pdev_release_ref(pdev, WLAN_DP_ID) + +#define dp_comp_psoc_get_ref(psoc) wlan_objmgr_psoc_try_get_ref(psoc, WLAN_DP_ID) +#define dp_comp_psoc_put_ref(psoc) wlan_objmgr_psoc_release_ref(psoc, WLAN_DP_ID) + /** * dp_get_vdev_priv_obj() - Wrapper to retrieve vdev priv obj * @vdev: vdev pointer @@ -38,7 +52,16 @@ static inline struct wlan_dp_intf * dp_get_vdev_priv_obj(struct wlan_objmgr_vdev *vdev) { - return NULL; + struct wlan_dp_intf *obj; + + if (!vdev) { + dp_err("vdev is null"); + return NULL; + } + + obj = wlan_objmgr_vdev_get_comp_private_obj(vdev, WLAN_COMP_DP); + + return obj; } /** @@ -50,6 +73,11 @@ dp_get_vdev_priv_obj(struct wlan_objmgr_vdev *vdev) static inline struct wlan_dp_psoc_context * dp_psoc_get_priv(struct wlan_objmgr_psoc *psoc) { - return NULL; + struct wlan_dp_psoc_context *dp_ctx; + + dp_ctx = wlan_objmgr_psoc_get_comp_private_obj(psoc, WLAN_COMP_DP); + QDF_BUG(dp_ctx); + + return dp_ctx; } #endif /* __WLAN_DP_OBJMGR_H */ diff --git a/components/dp/core/inc/wlan_dp_priv.h b/components/dp/core/inc/wlan_dp_priv.h index 131595ca5a..574f21b075 100644 --- a/components/dp/core/inc/wlan_dp_priv.h +++ b/components/dp/core/inc/wlan_dp_priv.h @@ -27,34 +27,214 @@ #include "wlan_dp_public_struct.h" #include "cdp_txrx_cmn.h" -#include "hdd_dp_cfg.h" #include "wlan_dp_cfg.h" #include "wlan_dp_objmgr.h" #include #include "qdf_periodic_work.h" +#ifndef NUM_CPUS +#ifdef QCA_CONFIG_SMP +#define NUM_CPUS NR_CPUS +#else +#define NUM_CPUS 1 +#endif +#endif + +#ifndef NUM_TX_RX_HISTOGRAM +#define NUM_TX_RX_HISTOGRAM 128 +#endif + +#define NUM_TX_RX_HISTOGRAM_MASK (NUM_TX_RX_HISTOGRAM - 1) + #if defined(WLAN_FEATURE_DP_BUS_BANDWIDTH) && defined(FEATURE_RUNTIME_PM) +/** + * enum dp_rtpm_tput_policy_state - states to track runtime_pm tput policy + * @RTPM_TPUT_POLICY_STATE_INVALID: invalid state + * @RTPM_TPUT_POLICY_STATE_REQUIRED: state indicating runtime_pm is required + * @RTPM_TPUT_POLICY_STATE_NOT_REQUIRED: state indicating runtime_pm is NOT + * required + */ +enum dp_rtpm_tput_policy_state { + RTPM_TPUT_POLICY_STATE_INVALID, + RTPM_TPUT_POLICY_STATE_REQUIRED, + RTPM_TPUT_POLICY_STATE_NOT_REQUIRED +}; /** * struct dp_rtpm_tput_policy_context - RTPM throughput policy context + * @curr_state: current state of throughput policy (RTPM require or not) + * @wake_lock: wakelock for QDF wake_lock acquire/release APIs + * @rtpm_lock: lock use for QDF rutime PM prevent/allow APIs + * @high_tput_vote: atomic variable to keep track of voting */ struct dp_rtpm_tput_policy_context { + enum dp_rtpm_tput_policy_state curr_state; + qdf_wake_lock_t wake_lock; + qdf_runtime_lock_t rtpm_lock; + qdf_atomic_t high_tput_vote; }; #endif +/** + * struct wlan_dp_psoc_cfg - DP configuration parameters. + */ struct wlan_dp_psoc_cfg { + bool tx_orphan_enable; + + uint32_t rx_mode; + uint32_t tx_comp_loop_pkt_limit; + uint32_t rx_reap_loop_pkt_limit; + uint32_t rx_hp_oos_update_limit; + uint64_t rx_softirq_max_yield_duration_ns; +#ifdef WLAN_FEATURE_DP_BUS_BANDWIDTH + /* bandwidth threshold for ultra high bandwidth */ + uint32_t bus_bw_ultra_high_threshold; + /* bandwidth threshold for very high bandwidth */ + uint32_t bus_bw_very_high_threshold; + /* bandwidth threshold for DBS mode bandwidth */ + uint32_t bus_bw_dbs_threshold; + /* bandwidth threshold for high bandwidth */ + uint32_t bus_bw_high_threshold; + /* bandwidth threshold for medium bandwidth */ + uint32_t bus_bw_medium_threshold; + /* bandwidth threshold for low bandwidth */ + uint32_t bus_bw_low_threshold; + uint32_t bus_bw_compute_interval; + uint32_t enable_tcp_delack; + bool enable_tcp_limit_output; + uint32_t enable_tcp_adv_win_scale; + uint32_t tcp_delack_thres_high; + uint32_t tcp_delack_thres_low; + uint32_t tcp_tx_high_tput_thres; + uint32_t tcp_delack_timer_count; + bool enable_tcp_param_update; + uint32_t bus_low_cnt_threshold; + bool enable_latency_crit_clients; +#endif /*WLAN_FEATURE_DP_BUS_BANDWIDTH*/ + +#ifdef WLAN_FEATURE_MSCS + uint32_t mscs_pkt_threshold; + uint32_t mscs_voice_interval; +#endif /* WLAN_FEATURE_MSCS */ + +#ifdef QCA_SUPPORT_TXRX_DRIVER_TCP_DEL_ACK + bool del_ack_enable; + uint32_t del_ack_threshold_high; + uint32_t del_ack_threshold_low; + uint16_t del_ack_timer_value; + uint16_t del_ack_pkt_count; +#endif + uint32_t napi_cpu_affinity_mask; + /* CPU affinity mask for rx_thread */ + uint32_t rx_thread_ul_affinity_mask; + uint32_t rx_thread_affinity_mask; + uint8_t cpu_map_list[CFG_DP_RPS_RX_QUEUE_CPU_MAP_LIST_LEN]; + bool multicast_replay_filter; + uint32_t rx_wakelock_timeout; + uint8_t num_dp_rx_threads; +#ifdef CONFIG_DP_TRACE + bool enable_dp_trace; + uint8_t dp_trace_config[DP_TRACE_CONFIG_STRING_LENGTH]; +#endif + uint8_t enable_nud_tracking; + +#ifdef WLAN_SUPPORT_TXRX_HL_BUNDLE + uint32_t pkt_bundle_threshold_high; + uint32_t pkt_bundle_threshold_low; + uint16_t pkt_bundle_timer_value; + uint16_t pkt_bundle_size; +#endif + uint32_t dp_proto_event_bitmap; + uint32_t fisa_enable; + + int icmp_req_to_fw_mark_interval; + + uint32_t cfg_wmi_credit_cnt; }; /** * struct tx_rx_histogram - structure to keep track of tx and rx packets * received over 100ms intervals + * @interval_rx: # of rx packets received in the last 100ms interval + * @interval_tx: # of tx packets received in the last 100ms interval + * @next_vote_level: pld_bus_width_type voting level (high or low) + * determined on the basis of total tx and rx packets + * received in the last 100ms interval + * @next_rx_level: pld_bus_width_type voting level (high or low) + * determined on the basis of rx packets received in the + * last 100ms interval + * @next_tx_level: pld_bus_width_type voting level (high or low) + * determined on the basis of tx packets received in the + * last 100ms interval + * @is_rx_pm_qos_high Capture rx_pm_qos voting + * @is_tx_pm_qos_high Capture tx_pm_qos voting + * @qtime timestamp when the record is added + * + * The structure keeps track of throughput requirements of wlan driver. + * An entry is added if either of next_vote_level, next_rx_level or + * next_tx_level changes. An entry is not added for every 100ms interval. */ struct tx_rx_histogram { + uint64_t interval_rx; + uint64_t interval_tx; + uint32_t next_vote_level; + uint32_t next_rx_level; + uint32_t next_tx_level; + bool is_rx_pm_qos_high; + bool is_tx_pm_qos_high; + uint64_t qtime; }; struct dp_tx_rx_stats { + struct { + /* start_xmit stats */ + __u32 tx_called; + __u32 tx_dropped; + __u32 tx_orphaned; + __u32 tx_classified_ac[WLAN_MAX_AC]; + __u32 tx_dropped_ac[WLAN_MAX_AC]; +#ifdef TX_MULTIQ_PER_AC + /* Neither valid socket nor skb->hash */ + uint32_t inv_sk_and_skb_hash; + /* skb->hash already calculated */ + uint32_t qselect_existing_skb_hash; + /* valid tx queue id in socket */ + uint32_t qselect_sk_tx_map; + /* skb->hash calculated in select queue */ + uint32_t qselect_skb_hash_calc; +#endif + /* rx stats */ + __u32 rx_packets; + __u32 rx_dropped; + __u32 rx_delivered; + __u32 rx_refused; + } per_cpu[NUM_CPUS]; + + qdf_atomic_t rx_usolict_arp_n_mcast_drp; + + /* rx gro */ + __u32 rx_aggregated; + __u32 rx_gro_dropped; + __u32 rx_non_aggregated; + __u32 rx_gro_flush_skip; + __u32 rx_gro_low_tput_flush; + + /* txflow stats */ + bool is_txflow_paused; + __u32 txflow_pause_cnt; + __u32 txflow_unpause_cnt; + __u32 txflow_timer_cnt; + + /*tx timeout stats*/ + __u32 tx_timeout_cnt; + __u32 cont_txtimeout_cnt; + u64 jiffies_last_txtimeout; }; +/** + * struct dp_stats - DP stats + * @tx_rx_stats : Tx/Rx debug stats + */ struct dp_stats { struct dp_tx_rx_stats tx_rx_stats; }; @@ -62,15 +242,124 @@ struct dp_stats { /** * struct wlan_dp_intf - DP interface object related info * @dp_ctx: DP context reference + * @mac_addr: Device MAC address + * @device_mode: Device Mode + * @intf_id: Interface ID + * @node: list node for membership in the interface list + * @tx_rx_disallow_mask: TX/RX disallow mask + * @vdev: object manager vdev context + * @dev: netdev reference */ struct wlan_dp_intf { struct wlan_dp_psoc_context *dp_ctx; + + struct qdf_mac_addr mac_addr; + + enum QDF_OPMODE device_mode; + + uint8_t intf_id; + + qdf_list_node_t node; + + uint32_t tx_rx_disallow_mask; + struct wlan_objmgr_vdev *vdev; + qdf_netdev_t dev; + /**Device TX/RX statistics*/ + struct dp_stats dp_stats; +#ifdef WLAN_FEATURE_DP_BUS_BANDWIDTH + unsigned long prev_rx_packets; + unsigned long prev_tx_packets; + unsigned long prev_tx_bytes; + uint64_t prev_fwd_tx_packets; + uint64_t prev_fwd_rx_packets; +#endif /*WLAN_FEATURE_DP_BUS_BANDWIDTH*/ +#ifdef WLAN_FEATURE_MSCS + unsigned long mscs_prev_tx_vo_pkts; + uint32_t mscs_counter; +#endif /* WLAN_FEATURE_MSCS */ + }; /** * struct wlan_dp_psoc_context - psoc related data required for DP + * @pdev: object manager pdev context + * @dp_cfg: place holder for DP configuration + * @intf_list: DP interfaces list + * @cb_obj: DP callbacks registered from other modules + * @sb_ops: South bound direction call backs registered in DP + * @nb_ops: North bound direction call backs registered in DP + * @bus_bw_work: work for periodically computing DDR bus bandwidth requirements + * @cur_vote_level: Current vote level + * @bus_bw_lock: Bus bandwidth work lock + * @cur_rx_level: Current Rx level + * @rtpm_tput_policy_ctx: Runtime Tput policy context + * @txrx_hist: TxRx histogram */ struct wlan_dp_psoc_context { + struct wlan_objmgr_psoc *psoc; + struct wlan_objmgr_pdev *pdev; + /** Pointer to the qdf device */ + qdf_device_t qdf_dev; + /** Config values read from ini file */ + struct wlan_dp_psoc_cfg dp_cfg; + + qdf_spinlock_t intf_list_lock; + qdf_list_t intf_list; + + bool rps; + bool dynamic_rps; + bool enable_rxthread; + /* support for DP RX threads */ + bool enable_dp_rx_threads; + bool napi_enable; + + struct wlan_dp_psoc_callbacks dp_ops; + struct wlan_dp_psoc_sb_ops sb_ops; + struct wlan_dp_psoc_nb_ops nb_ops; + + bool en_tcp_delack_no_lro; + /* For Rx thread non GRO/LRO packet accounting */ + uint64_t no_rx_offload_pkt_cnt; + uint64_t no_tx_offload_pkt_cnt; +#ifdef QCA_CONFIG_SMP + bool is_ol_rx_thread_suspended; +#endif + bool wlan_suspended; + /* Flag keeps track of wiphy suspend/resume */ + bool is_wiphy_suspended; + + qdf_atomic_t num_latency_critical_clients; + uint8_t high_bus_bw_request; + uint64_t bw_vote_time; +#ifdef WLAN_FEATURE_DP_BUS_BANDWIDTH + struct qdf_periodic_work bus_bw_work; + int cur_vote_level; + qdf_spinlock_t bus_bw_lock; + int cur_rx_level; + uint64_t prev_no_rx_offload_pkts; + uint64_t prev_rx_offload_pkts; + /* Count of non TSO packets in previous bus bw delta time */ + uint64_t prev_no_tx_offload_pkts; + /* Count of TSO packets in previous bus bw delta time */ + uint64_t prev_tx_offload_pkts; + int cur_tx_level; + uint64_t prev_tx; + qdf_atomic_t low_tput_gro_enable; + uint32_t bus_low_vote_cnt; +#ifdef FEATURE_RUNTIME_PM + struct dp_rtpm_tput_policy_context rtpm_tput_policy_ctx; +#endif +#endif /*WLAN_FEATURE_DP_BUS_BANDWIDTH*/ + +#ifdef WLAN_NS_OFFLOAD + /* IPv6 notifier callback for handling NS offload on change in IP */ + struct notifier_block ipv6_notifier; +#endif + + uint16_t txrx_hist_idx; + struct tx_rx_histogram *txrx_hist; + + uint32_t rx_high_ind_cnt; }; #endif /* end of _WLAN_DP_PRIV_STRUCT_H_ */ diff --git a/components/dp/core/src/wlan_dp_main.c b/components/dp/core/src/wlan_dp_main.c index 2a48e950a9..f053ce6281 100644 --- a/components/dp/core/src/wlan_dp_main.c +++ b/components/dp/core/src/wlan_dp_main.c @@ -24,95 +24,296 @@ #include "wlan_dp_public_struct.h" #include "cfg_ucfg_api.h" -/** - * dp_get_intf_by_macaddr() - Get DP interface by mac address. - * @dp_ctx: dp_ctx handle - * @addr: MAC address - * - * Return: DP interface on success else NULL. - */ +/* Global DP context */ +static struct wlan_dp_psoc_context *gp_dp_ctx; + +QDF_STATUS dp_allocate_ctx(void) +{ + struct wlan_dp_psoc_context *dp_ctx; + + dp_ctx = qdf_mem_malloc(sizeof(*dp_ctx)); + if (!dp_ctx) { + dp_err("Failed to create DP context"); + return QDF_STATUS_E_NOMEM; + } + + qdf_spinlock_create(&dp_ctx->intf_list_lock); + qdf_list_create(&dp_ctx->intf_list, 0); + + dp_attach_ctx(dp_ctx); + + return QDF_STATUS_SUCCESS; +} + +void dp_free_ctx(void) +{ + struct wlan_dp_psoc_context *dp_ctx; + + dp_ctx = dp_get_context(); + + qdf_spinlock_destroy(&dp_ctx->intf_list_lock); + qdf_list_destroy(&dp_ctx->intf_list); + dp_dettach_ctx(); + qdf_mem_free(dp_ctx); +} + +QDF_STATUS dp_get_front_intf_no_lock(struct wlan_dp_psoc_context *dp_ctx, + struct wlan_dp_intf **out_intf) +{ + QDF_STATUS status; + qdf_list_node_t *node; + + *out_intf = NULL; + + status = qdf_list_peek_front(&dp_ctx->intf_list, &node); + + if (QDF_IS_STATUS_ERROR(status)) + return status; + + *out_intf = qdf_container_of(node, struct wlan_dp_intf, node); + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS dp_get_next_intf_no_lock(struct wlan_dp_psoc_context *dp_ctx, + struct wlan_dp_intf *cur_intf, + struct wlan_dp_intf **out_intf) +{ + QDF_STATUS status; + qdf_list_node_t *node; + + if (!cur_intf) + return QDF_STATUS_E_INVAL; + + *out_intf = NULL; + + status = qdf_list_peek_next(&dp_ctx->intf_list, + &cur_intf->node, + &node); + + if (QDF_IS_STATUS_ERROR(status)) + return status; + + *out_intf = qdf_container_of(node, struct wlan_dp_intf, node); + + return status; +} + struct wlan_dp_intf* dp_get_intf_by_macaddr(struct wlan_dp_psoc_context *dp_ctx, struct qdf_mac_addr *addr) { + struct wlan_dp_intf *dp_intf; + + qdf_spin_lock_bh(&dp_ctx->intf_list_lock); + for (dp_get_front_intf_no_lock(dp_ctx, &dp_intf); dp_intf; + dp_get_next_intf_no_lock(dp_ctx, dp_intf, &dp_intf)) { + if (qdf_is_macaddr_equal(&dp_intf->mac_addr, addr)) { + qdf_spin_unlock_bh(&dp_ctx->intf_list_lock); + return dp_intf; + } + } + qdf_spin_unlock_bh(&dp_ctx->intf_list_lock); + return NULL; } -/** - * dp_vdev_obj_create_notification() - DP vdev object creation notification - * @vdev: vdev handle - * @arg_list: arguments list - * - * Return: QDF_STATUS_SUCCESS on success - */ +static void dp_cfg_init(struct wlan_dp_psoc_context *ctx) +{ +} + QDF_STATUS dp_vdev_obj_create_notification(struct wlan_objmgr_vdev *vdev, void *arg) { - return QDF_STATUS_SUCCESS; + struct wlan_objmgr_psoc *psoc; + struct wlan_dp_psoc_context *dp_ctx; + struct wlan_dp_intf *dp_intf; + QDF_STATUS status = QDF_STATUS_SUCCESS; + struct qdf_mac_addr *mac_addr; + + dp_info("DP VDEV OBJ create notification"); + + psoc = wlan_vdev_get_psoc(vdev); + if (!psoc) { + dp_err("Failed to get psoc"); + return QDF_STATUS_E_INVAL; + } + + dp_ctx = dp_psoc_get_priv(psoc); + mac_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_macaddr(vdev); + + dp_intf = dp_get_intf_by_macaddr(dp_ctx, mac_addr); + if (!dp_intf) { + dp_err("Failed to get dp intf mac:" QDF_MAC_ADDR_FMT, + QDF_MAC_ADDR_REF(mac_addr)); + return QDF_STATUS_E_INVAL; + } + + dp_intf->device_mode = wlan_vdev_mlme_get_opmode(vdev); + dp_intf->intf_id = vdev->vdev_objmgr.vdev_id; + dp_intf->vdev = vdev; + + status = wlan_objmgr_vdev_component_obj_attach(vdev, + WLAN_COMP_DP, + (void *)dp_intf, + QDF_STATUS_SUCCESS); + if (QDF_IS_STATUS_ERROR(status)) { + dp_err("Failed to attach dp_intf with vdev"); + return status; + } + + return status; } -/** - * dp_vdev_obj_destroy_notification() - DP vdev object destroy notification - * @vdev: vdev handle - * @arg_list: arguments list - * - * Return: QDF_STATUS_SUCCESS on success - */ QDF_STATUS dp_vdev_obj_destroy_notification(struct wlan_objmgr_vdev *vdev, void *arg) { - return QDF_STATUS_SUCCESS; + struct wlan_dp_intf *dp_intf; + QDF_STATUS status = QDF_STATUS_SUCCESS; + + dp_info("DP VDEV OBJ destroy notification"); + + dp_intf = dp_get_vdev_priv_obj(vdev); + if (!dp_intf) { + dp_err("Failed to get DP interface obj"); + return QDF_STATUS_E_INVAL; + } + + status = wlan_objmgr_vdev_component_obj_detach(vdev, + WLAN_COMP_DP, + (void *)dp_intf); + if (QDF_IS_STATUS_ERROR(status)) { + dp_err("Failed to detach dp_intf with vdev"); + return status; + } + + return status; } -/** - * dp_pdev_obj_create_notification() - DP pdev object creation notification - * @pdev: pdev handle - * @arg_list: arguments list - * - * Return: QDF_STATUS_SUCCESS on success - */ QDF_STATUS dp_pdev_obj_create_notification(struct wlan_objmgr_pdev *pdev, void *arg) { - return QDF_STATUS_SUCCESS; + struct wlan_objmgr_psoc *psoc; + struct wlan_dp_psoc_context *dp_ctx; + QDF_STATUS status; + + dp_info("DP PDEV OBJ create notification"); + psoc = wlan_pdev_get_psoc(pdev); + if (!psoc) { + obj_mgr_err("psoc is NULL in pdev"); + return QDF_STATUS_E_FAILURE; + } + dp_ctx = dp_psoc_get_priv(psoc); + if (!dp_ctx) { + dp_err("Failed to get dp_ctx from psoc"); + return QDF_STATUS_E_FAILURE; + } + status = wlan_objmgr_pdev_component_obj_attach(pdev, + WLAN_COMP_DP, + (void *)dp_ctx, + QDF_STATUS_SUCCESS); + if (QDF_IS_STATUS_ERROR(status)) { + dp_err("Failed to attach dp_ctx to pdev"); + return status; + } + + dp_ctx->pdev = pdev; + return status; } -/** - * dp_pdev_obj_destroy_notification() - DP pdev object destroy notification - * @pdev: pdev handle - * @arg_list: arguments list - * - * Return: QDF_STATUS_SUCCESS on success - */ QDF_STATUS dp_pdev_obj_destroy_notification(struct wlan_objmgr_pdev *pdev, void *arg) { - return QDF_STATUS_SUCCESS; + struct wlan_objmgr_psoc *psoc; + struct wlan_dp_psoc_context *dp_ctx; + QDF_STATUS status; + + dp_info("DP PDEV OBJ destroy notification"); + psoc = wlan_pdev_get_psoc(pdev); + if (!psoc) { + obj_mgr_err("psoc is NULL in pdev"); + return QDF_STATUS_E_FAILURE; + } + + dp_ctx = wlan_objmgr_pdev_get_comp_private_obj(pdev, WLAN_COMP_DP); + if (!dp_ctx) { + dp_err("Failed to get dp_ctx from pdev"); + return QDF_STATUS_E_FAILURE; + } + status = wlan_objmgr_pdev_component_obj_detach(pdev, + WLAN_COMP_DP, + dp_ctx); + if (QDF_IS_STATUS_ERROR(status)) { + dp_err("Failed to detatch dp_ctx from pdev"); + return status; + } + if (!dp_ctx->pdev) + dp_err("DP Pdev is NULL"); + + dp_ctx->pdev = NULL; + return status; } -/** - * dp_psoc_obj_create_notification() - DP pdev object creation notification - * @psoc: psoc handle - * @arg_list: arguments list - * - * Return: QDF_STATUS_SUCCESS on success - */ QDF_STATUS dp_psoc_obj_create_notification(struct wlan_objmgr_psoc *psoc, void *arg) { - return QDF_STATUS_SUCCESS; + struct wlan_dp_psoc_context *dp_ctx = gp_dp_ctx; + QDF_STATUS status; + + status = wlan_objmgr_psoc_component_obj_attach( + psoc, WLAN_COMP_DP, + dp_ctx, QDF_STATUS_SUCCESS); + if (QDF_IS_STATUS_ERROR(status)) { + dp_err("Failed to attach psoc component obj"); + return status; + } + + dp_ctx->psoc = psoc; + dp_cfg_init(dp_ctx); + return status; } -/** - * dp_psoc_obj_destroy_notification() - DP psoc object destroy notification - * @psoc: psoc handle - * @arg_list: arguments list - * - * Return: QDF_STATUS_SUCCESS on success - */ QDF_STATUS dp_psoc_obj_destroy_notification(struct wlan_objmgr_psoc *psoc, void *arg) { - return QDF_STATUS_SUCCESS; + struct wlan_dp_psoc_context *dp_ctx; + QDF_STATUS status; + + dp_ctx = dp_psoc_get_priv(psoc); + if (!dp_ctx) { + dp_err("psoc priv is NULL"); + return QDF_STATUS_E_FAILURE; + } + + status = wlan_objmgr_psoc_component_obj_detach( + psoc, WLAN_COMP_DP, + dp_ctx); + if (QDF_IS_STATUS_ERROR(status)) { + dp_err("Failed to detach psoc component obj"); + return status; + } + + return status; +} + +void dp_attach_ctx(struct wlan_dp_psoc_context *dp_ctx) +{ + if (gp_dp_ctx) + dp_debug("already attached global dp ctx"); + gp_dp_ctx = dp_ctx; +} + +void dp_dettach_ctx(void) +{ + if (!gp_dp_ctx) { + dp_err("global dp ctx is already dettached"); + return; + } + gp_dp_ctx = NULL; +} + +struct wlan_dp_psoc_context *dp_get_context(void) +{ + return gp_dp_ctx; } diff --git a/components/dp/dispatcher/inc/wlan_dp_public_struct.h b/components/dp/dispatcher/inc/wlan_dp_public_struct.h index a44363ef0e..4271937195 100644 --- a/components/dp/dispatcher/inc/wlan_dp_public_struct.h +++ b/components/dp/dispatcher/inc/wlan_dp_public_struct.h @@ -26,7 +26,6 @@ #include "wlan_cmn.h" #include "wlan_objmgr_cmn.h" #include "wlan_objmgr_global_obj.h" -#include "wmi_unified.h" #include "qdf_status.h" /** @@ -39,10 +38,18 @@ struct wlan_dp_psoc_callbacks { bool flush_gro); }; +/** + * struct wlan_dp_psoc_sb_ops - struct containing callback + * to south bound APIs. callbacks to call traget_if APIs + */ struct wlan_dp_psoc_sb_ops { /*TODO to add target if TX ops*/ }; +/** + * struct wlan_dp_psoc_nb_ops - struct containing callback + * to north bound APIs. callbacks APIs to be called by target_if APIs + */ struct wlan_dp_psoc_nb_ops { /*TODO to add target if RX ops*/ }; diff --git a/components/dp/dispatcher/inc/wlan_dp_ucfg_api.h b/components/dp/dispatcher/inc/wlan_dp_ucfg_api.h index 4c1af012f8..8289baffc6 100644 --- a/components/dp/dispatcher/inc/wlan_dp_ucfg_api.h +++ b/components/dp/dispatcher/inc/wlan_dp_ucfg_api.h @@ -32,19 +32,36 @@ #include #include +/** + * ucfg_dp_create_intf() - update DP interface MAC address + * @psoc: psoc handle + * @cur_mac: Curent MAC address + * @new_mac: new MAC address + * + */ void ucfg_dp_update_inf_mac(struct wlan_objmgr_psoc *psoc, struct qdf_mac_addr *cur_mac, struct qdf_mac_addr *new_mac); +/** + * ucfg_dp_destroy_intf() - DP module interface deletion + * @psoc: psoc handle + * @intf_addr: Interface MAC address + * + */ QDF_STATUS ucfg_dp_destroy_intf(struct wlan_objmgr_psoc *psoc, struct qdf_mac_addr *intf_addr); /** * ucfg_dp_create_intf() - DP module interface creation + * @psoc: psoc handle + * @intf_addr: Interface MAC address + * @ndev : netdev object * */ QDF_STATUS ucfg_dp_create_intf(struct wlan_objmgr_psoc *psoc, - struct qdf_mac_addr *intf_addr); + struct qdf_mac_addr *intf_addr, + qdf_netdev_t ndev); /** * ucfg_dp_init() - DP module initialization API @@ -60,8 +77,42 @@ QDF_STATUS ucfg_dp_init(void); */ QDF_STATUS ucfg_dp_deinit(void); +/** + * ucfg_dp_psoc_open() - DP component Open + * @psoc: pointer to psoc object + * + * Return: QDF Status + */ +QDF_STATUS ucfg_dp_psoc_open(struct wlan_objmgr_psoc *psoc); + +/** + * ucfg_dp_psoc_close() - DP component Close + * @psoc: pointer to psoc object + * + * Return: QDF Status + */ +QDF_STATUS ucfg_dp_psoc_close(struct wlan_objmgr_psoc *psoc); + +/** + * ucfg_dp_suspend_wlan() - update suspend state in DP component + * @psoc: pointer to psoc object + * + * Return: None + */ +void ucfg_dp_suspend_wlan(struct wlan_objmgr_psoc *psoc); + +/** + * ucfg_dp_resume_wlan() - update resume state in DP component + * @psoc: pointer to psoc object + * + * Return: None + */ +void ucfg_dp_resume_wlan(struct wlan_objmgr_psoc *psoc); + /** * ucfg_dp_update_config() - DP module config update + * @psoc: pointer to psoc object + * @req : user config * * Return: QDF_STATUS */ @@ -69,6 +120,12 @@ QDF_STATUS ucfg_dp_update_config(struct wlan_objmgr_psoc *psoc, struct wlan_dp_user_config *req); +/** + * ucfg_dp_get_rx_softirq_yield_duration() - Get rx soft IRQ yield duration + * @psoc: pointer to psoc object + * + * Return: soft IRQ yield duration + */ uint64_t ucfg_dp_get_rx_softirq_yield_duration(struct wlan_objmgr_psoc *psoc); diff --git a/components/dp/dispatcher/src/wlan_dp_ucfg_api.c b/components/dp/dispatcher/src/wlan_dp_ucfg_api.c index 546b769766..1126361207 100644 --- a/components/dp/dispatcher/src/wlan_dp_ucfg_api.c +++ b/components/dp/dispatcher/src/wlan_dp_ucfg_api.c @@ -25,17 +25,57 @@ #include "wlan_dp_objmgr.h" #include "cdp_txrx_cmn.h" #include "cfg_ucfg_api.h" +#include "wlan_pmo_obj_mgmt_api.h" void ucfg_dp_update_inf_mac(struct wlan_objmgr_psoc *psoc, struct qdf_mac_addr *cur_mac, struct qdf_mac_addr *new_mac) { + struct wlan_dp_intf *dp_intf; + struct wlan_dp_psoc_context *dp_ctx; + + dp_info("MAC update"); + dp_ctx = dp_psoc_get_priv(psoc); + + dp_intf = dp_get_intf_by_macaddr(dp_ctx, cur_mac); + if (!dp_intf) { + dp_err("DP interface not found addr:" QDF_MAC_ADDR_FMT, + QDF_MAC_ADDR_REF(cur_mac)); + return; + } + + qdf_copy_macaddr(&dp_intf->mac_addr, new_mac); } QDF_STATUS ucfg_dp_create_intf(struct wlan_objmgr_psoc *psoc, - struct qdf_mac_addr *intf_addr) + struct qdf_mac_addr *intf_addr, + qdf_netdev_t ndev) { + struct wlan_dp_intf *dp_intf; + struct wlan_dp_psoc_context *dp_ctx; + + dp_ctx = dp_get_context(); + + dp_info("DP interface create addr:" QDF_MAC_ADDR_FMT, + QDF_MAC_ADDR_REF(intf_addr)); + + dp_intf = __qdf_mem_malloc(sizeof(*dp_intf), __func__, __LINE__); + if (!dp_intf) { + dp_err("DP intf memory alloc failed addr:" QDF_MAC_ADDR_FMT, + QDF_MAC_ADDR_REF(intf_addr)); + return QDF_STATUS_E_FAILURE; + } + + dp_intf->dp_ctx = dp_ctx; + dp_intf->dev = ndev; + dp_intf->intf_id = WLAN_UMAC_VDEV_ID_MAX; + qdf_copy_macaddr(&dp_intf->mac_addr, intf_addr); + + qdf_spin_lock_bh(&dp_ctx->intf_list_lock); + qdf_list_insert_front(&dp_ctx->intf_list, &dp_intf->node); + qdf_spin_unlock_bh(&dp_ctx->intf_list_lock); + return QDF_STATUS_SUCCESS; } @@ -43,28 +83,385 @@ QDF_STATUS ucfg_dp_destroy_intf(struct wlan_objmgr_psoc *psoc, struct qdf_mac_addr *intf_addr) { + struct wlan_dp_intf *dp_intf; + struct wlan_dp_psoc_context *dp_ctx; + + dp_ctx = dp_get_context(); + + dp_info("DP interface destroy addr:" QDF_MAC_ADDR_FMT, + QDF_MAC_ADDR_REF(intf_addr)); + + dp_intf = dp_get_intf_by_macaddr(dp_ctx, intf_addr); + if (!dp_intf) { + dp_err("DP interface not found addr:" QDF_MAC_ADDR_FMT, + QDF_MAC_ADDR_REF(intf_addr)); + return QDF_STATUS_E_FAILURE; + } + + qdf_spin_lock_bh(&dp_ctx->intf_list_lock); + qdf_list_remove_node(&dp_ctx->intf_list, &dp_intf->node); + qdf_spin_unlock_bh(&dp_ctx->intf_list_lock); + + __qdf_mem_free(dp_intf); + return QDF_STATUS_SUCCESS; } QDF_STATUS ucfg_dp_init(void) { - return QDF_STATUS_SUCCESS; + QDF_STATUS status; + + dp_info("DP module dispatcher init"); + + if (dp_allocate_ctx() != QDF_STATUS_SUCCESS) { + dp_err("DP ctx allocation failed"); + return QDF_STATUS_E_FAULT; + } + + status = wlan_objmgr_register_psoc_create_handler( + WLAN_COMP_DP, + dp_psoc_obj_create_notification, NULL); + if (QDF_IS_STATUS_ERROR(status)) { + dp_err("Failed to register psoc create handler for DP"); + return status; + } + + status = wlan_objmgr_register_psoc_destroy_handler( + WLAN_COMP_DP, + dp_psoc_obj_destroy_notification, NULL); + if (QDF_IS_STATUS_ERROR(status)) { + dp_err("Failed to register psoc destroy handler for DP"); + goto fail_destroy_psoc; + } + + status = wlan_objmgr_register_pdev_create_handler( + WLAN_COMP_DP, + dp_pdev_obj_create_notification, NULL); + if (QDF_IS_STATUS_ERROR(status)) { + dp_err("Failed to register pdev create handler for DP"); + goto fail_create_pdev; + } + + status = wlan_objmgr_register_pdev_destroy_handler( + WLAN_COMP_DP, + dp_pdev_obj_destroy_notification, NULL); + if (QDF_IS_STATUS_ERROR(status)) { + dp_err("Failed to register pdev destroy handler for DP"); + goto fail_destroy_pdev; + } + + status = wlan_objmgr_register_vdev_create_handler( + WLAN_COMP_DP, + dp_vdev_obj_create_notification, NULL); + if (QDF_IS_STATUS_ERROR(status)) { + dp_err("Failed to register vdev create handler"); + goto fail_create_vdev; + } + + status = wlan_objmgr_register_vdev_destroy_handler( + WLAN_COMP_DP, + dp_vdev_obj_destroy_notification, NULL); + if (QDF_IS_STATUS_ERROR(status)) { + dp_err("Failed to register vdev destroy handler"); + goto fail_destroy_vdev; + } + return status; + +fail_destroy_vdev: + wlan_objmgr_unregister_vdev_create_handler( + WLAN_COMP_DP, + dp_vdev_obj_create_notification, NULL); + +fail_create_vdev: + wlan_objmgr_unregister_pdev_destroy_handler( + WLAN_COMP_DP, + dp_pdev_obj_destroy_notification, NULL); + +fail_destroy_pdev: + wlan_objmgr_unregister_pdev_create_handler( + WLAN_COMP_DP, + dp_pdev_obj_create_notification, NULL); + +fail_create_pdev: + wlan_objmgr_unregister_psoc_destroy_handler( + WLAN_COMP_DP, + dp_psoc_obj_destroy_notification, NULL); +fail_destroy_psoc: + wlan_objmgr_unregister_psoc_create_handler( + WLAN_COMP_DP, + dp_psoc_obj_create_notification, NULL); + + dp_free_ctx(); + return status; } QDF_STATUS ucfg_dp_deinit(void) { + QDF_STATUS status; + + dp_info("DP module dispatcher deinit"); + + status = wlan_objmgr_unregister_vdev_destroy_handler( + WLAN_COMP_DP, + dp_vdev_obj_destroy_notification, + NULL); + if (QDF_IS_STATUS_ERROR(status)) + dp_err("Failed to unregister vdev delete handler:%d", status); + + status = wlan_objmgr_unregister_vdev_create_handler( + WLAN_COMP_DP, + dp_vdev_obj_create_notification, NULL); + if (QDF_IS_STATUS_ERROR(status)) + dp_err("Failed to unregister vdev create handler:%d", status); + + status = wlan_objmgr_unregister_pdev_destroy_handler( + WLAN_COMP_DP, + dp_pdev_obj_destroy_notification, NULL); + if (QDF_IS_STATUS_ERROR(status)) + dp_err("Failed to unregister pdev destroy handler:%d", status); + + status = wlan_objmgr_unregister_pdev_create_handler( + WLAN_COMP_DP, + dp_pdev_obj_create_notification, NULL); + if (QDF_IS_STATUS_ERROR(status)) + dp_err("Failed to unregister pdev create handler:%d", status); + + status = wlan_objmgr_unregister_psoc_destroy_handler( + WLAN_COMP_DP, + dp_psoc_obj_destroy_notification, NULL); + if (QDF_IS_STATUS_ERROR(status)) + dp_err("Failed to unregister DP psoc delete handle:%d", status); + + status = wlan_objmgr_unregister_psoc_create_handler( + WLAN_COMP_DP, + dp_psoc_obj_create_notification, NULL); + if (QDF_IS_STATUS_ERROR(status)) + dp_err("Failed to unregister DP psoc create handle:%d", status); + + dp_free_ctx(); + + return status; +} + +/** + * ucfg_dp_suspend_handler() - suspend handler regsitered with PMO component + * @psoc: psoc handle + * @arg: Arguments passed by the suspend handler. + * + * This handler is used to update the wiphy suspend state in DP context + * + * Return: QDF_STATUS status -in case of success else return error + */ +static QDF_STATUS +ucfg_dp_suspend_handler(struct wlan_objmgr_psoc *psoc, void *arg) +{ + struct wlan_dp_psoc_context *dp_ctx; + + dp_ctx = dp_psoc_get_priv(psoc); + if (!dp_ctx) { + dp_err("DP context not found"); + return QDF_STATUS_E_FAILURE; + } + + dp_ctx->is_wiphy_suspended = true; return QDF_STATUS_SUCCESS; } +/** + * ucfg_dp_resume_handler() - resume handler regsitered with PMO component + * @psoc: psoc handle + * @arg: Arguments passed by the resume handler. + * + * This handler is used to update the wiphy resume state in DP context + * + * Return: QDF_STATUS status -in case of success else return error + */ +static QDF_STATUS +ucfg_dp_resume_handler(struct wlan_objmgr_psoc *psoc, void *arg) +{ + struct wlan_dp_psoc_context *dp_ctx; + + dp_ctx = dp_psoc_get_priv(psoc); + if (!dp_ctx) { + dp_err("DP context not found"); + return QDF_STATUS_E_FAILURE; + } + + dp_ctx->is_wiphy_suspended = false; + return QDF_STATUS_SUCCESS; +} + +/** + * dp_register_pmo_handler() - register suspend and resume handler + * with PMO component + * + * Return: None + */ +static inline void dp_register_pmo_handler(void) +{ + pmo_register_suspend_handler(WLAN_COMP_DP, + ucfg_dp_suspend_handler, NULL); + + pmo_register_resume_handler(WLAN_COMP_DP, + ucfg_dp_resume_handler, NULL); +} + +/** + * dp_unregister_pmo_handler() - unregister suspend and resume handler + * with PMO component + * + * Return: None + */ +static inline void dp_unregister_pmo_handler(void) +{ + pmo_unregister_suspend_handler(WLAN_COMP_DP, ucfg_dp_suspend_handler); + + pmo_unregister_resume_handler(WLAN_COMP_DP, ucfg_dp_resume_handler); +} + +/** + * ucfg_dp_store_qdf_dev() - Store qdf device instance in DP component + * @psoc: psoc handle + * + * Return: QDF_STATUS status -in case of success else return error + */ +static inline QDF_STATUS +ucfg_dp_store_qdf_dev(struct wlan_objmgr_psoc *psoc) +{ + struct wlan_dp_psoc_context *dp_ctx; + + dp_ctx = dp_psoc_get_priv(psoc); + if (!dp_ctx) { + dp_err("DP context not found"); + return QDF_STATUS_E_FAILURE; + } + + dp_ctx->qdf_dev = wlan_psoc_get_qdf_dev(psoc); + if (!dp_ctx->qdf_dev) { + dp_err("QDF_DEV is NULL"); + QDF_BUG(0); + return QDF_STATUS_E_FAILURE; + } + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS ucfg_dp_psoc_open(struct wlan_objmgr_psoc *psoc) +{ + ucfg_dp_store_qdf_dev(psoc); + dp_register_pmo_handler(); + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS ucfg_dp_psoc_close(struct wlan_objmgr_psoc *psoc) +{ + dp_unregister_pmo_handler(); + + return QDF_STATUS_SUCCESS; +} + +#ifdef WLAN_FEATURE_RX_SOFTIRQ_TIME_LIMIT +/** + * dp_get_config_rx_softirq_limits() - Update DP rx softirq limit config + * datapath + * @psoc: psoc handle + * @params: DP Configuration parameters + * + * Return: None + */ +static +void dp_get_config_rx_softirq_limits(struct wlan_objmgr_psoc *psoc, + struct cdp_config_params *params) +{ + params->tx_comp_loop_pkt_limit = cfg_get(psoc, + CFG_DP_TX_COMP_LOOP_PKT_LIMIT); + params->rx_reap_loop_pkt_limit = cfg_get(psoc, + CFG_DP_RX_REAP_LOOP_PKT_LIMIT); + params->rx_hp_oos_update_limit = cfg_get(psoc, + CFG_DP_RX_HP_OOS_UPDATE_LIMIT); +} +#else +static +void dp_get_config_rx_softirq_limits(struct wlan_objmgr_psoc *psoc, + struct cdp_config_params *params) +{ +} +#endif /* WLAN_FEATURE_RX_SOFTIRQ_TIME_LIMIT */ + +#if defined(QCA_LL_TX_FLOW_CONTROL_V2) || defined(QCA_LL_PDEV_TX_FLOW_CONTROL) +/** + * dp_get_config_queue_threshold() - Update DP tx flow limit config + * datapath + * @psoc: psoc handle + * @params: DP Configuration parameters + * + * Return: None + */ +static void +dp_get_config_queue_threshold(struct wlan_objmgr_psoc *psoc, + struct cdp_config_params *params) +{ + params->tx_flow_stop_queue_threshold = + cfg_get(psoc, CFG_DP_TX_FLOW_STOP_QUEUE_TH); + params->tx_flow_start_queue_offset = + cfg_get(psoc, CFG_DP_TX_FLOW_START_QUEUE_OFFSET); +} +#else +static inline void +dp_get_config_queue_threshold(struct wlan_objmgr_psoc *psoc, + struct cdp_config_params *params) +{ +} +#endif + QDF_STATUS ucfg_dp_update_config(struct wlan_objmgr_psoc *psoc, struct wlan_dp_user_config *req) { + struct cdp_config_params params = {0}; + struct wlan_dp_psoc_context *dp_ctx; + QDF_STATUS status; + void *soc; + + dp_ctx = dp_psoc_get_priv(psoc); + + soc = cds_get_context(QDF_MODULE_ID_SOC); + params.tso_enable = cfg_get(psoc, CFG_DP_TSO); + params.lro_enable = cfg_get(psoc, CFG_DP_LRO); + + dp_get_config_queue_threshold(psoc, ¶ms); + params.flow_steering_enable = + cfg_get(psoc, CFG_DP_FLOW_STEERING_ENABLED); + params.napi_enable = dp_ctx->napi_enable; + params.p2p_tcp_udp_checksumoffload = + cfg_get(psoc, CFG_DP_P2P_TCP_UDP_CKSUM_OFFLOAD); + params.nan_tcp_udp_checksumoffload = + cfg_get(psoc, CFG_DP_NAN_TCP_UDP_CKSUM_OFFLOAD); + params.tcp_udp_checksumoffload = + cfg_get(psoc, CFG_DP_TCP_UDP_CKSUM_OFFLOAD); + params.ipa_enable = req->ipa_enable; + params.gro_enable = cfg_get(psoc, CFG_DP_GRO); + params.tx_comp_loop_pkt_limit = cfg_get(psoc, + CFG_DP_TX_COMP_LOOP_PKT_LIMIT); + params.rx_reap_loop_pkt_limit = cfg_get(psoc, + CFG_DP_RX_REAP_LOOP_PKT_LIMIT); + params.rx_hp_oos_update_limit = cfg_get(psoc, + CFG_DP_RX_HP_OOS_UPDATE_LIMIT); + dp_get_config_rx_softirq_limits(psoc, ¶ms); + + status = cdp_update_config_parameters(soc, ¶ms); + if (status) { + dp_err("Failed to attach config parameters"); + return status; + } + return QDF_STATUS_SUCCESS; } uint64_t ucfg_dp_get_rx_softirq_yield_duration(struct wlan_objmgr_psoc *psoc) { - return 0; + struct wlan_dp_psoc_context *dp_ctx = dp_psoc_get_priv(psoc); + + return dp_ctx->dp_cfg.rx_softirq_max_yield_duration_ns; }