Browse Source

qcacld-3.0: Add target_if API implementation to DP component

Add target_if API to send ARP request, LRO config and
DHCP indiacation to firmware.

Change-Id: I2d4af7a5da6c29398ab00205654df9be3d90b665
CRs-Fixed: 3165155
Amit Mehta 3 years ago
parent
commit
a4db80f465

+ 82 - 0
components/dp/core/inc/wlan_dp_main.h

@@ -427,4 +427,86 @@ void dp_mic_deinit_work(struct wlan_dp_intf *dp_intf);
 void
 dp_rx_mic_error_ind(struct cdp_ctrl_objmgr_psoc *psoc, uint8_t pdev_id,
 		    struct cdp_rx_mic_err_info *mic_failure_info);
+/**
+ * dp_intf_get_tx_ops: get TX ops from the DP interface
+ * @psoc: pointer to psoc object
+ *
+ * Return: pointer to TX op callback
+ */
+static inline
+struct wlan_dp_psoc_sb_ops *dp_intf_get_tx_ops(struct wlan_objmgr_psoc *psoc)
+{
+	struct wlan_dp_psoc_context *dp_ctx;
+
+	if (!psoc) {
+		dp_err("psoc is null");
+		return NULL;
+	}
+
+	dp_ctx = dp_psoc_get_priv(psoc);
+	if (!dp_ctx) {
+		dp_err("psoc private object is null");
+		return NULL;
+	}
+
+	return &dp_ctx->sb_ops;
+}
+
+/**
+ * dp_intf_get_rx_ops: get RX ops from the DP interface
+ * @psoc: pointer to psoc object
+ *
+ * Return: pointer to RX op callback
+ */
+static inline
+struct wlan_dp_psoc_nb_ops *dp_intf_get_rx_ops(struct wlan_objmgr_psoc *psoc)
+{
+	struct wlan_dp_psoc_context *dp_ctx;
+
+	if (!psoc) {
+		dp_err("psoc is null");
+		return NULL;
+	}
+
+	dp_ctx = dp_psoc_get_priv(psoc);
+	if (!dp_ctx) {
+		dp_err("psoc private object is null");
+		return NULL;
+	}
+
+	return &dp_ctx->nb_ops;
+}
+
+/**
+ * dp_intf_get_rx_ops: get ARP req context from the DP context
+ * @psoc: pointer to psoc object
+ *
+ * Return: pointer to ARP request ctx.
+ */
+static inline
+void *dp_get_arp_request_ctx(struct wlan_objmgr_psoc *psoc)
+{
+	struct wlan_dp_psoc_context *dp_ctx;
+
+	dp_ctx = dp_psoc_get_priv(psoc);
+	if (!dp_ctx) {
+		dp_err("psoc private object is null");
+		return NULL;
+	}
+	return dp_ctx->sb_ops.arp_request_ctx;
+}
+
+/**
+ * dp_get_arp_stats_event_handler() - callback api to update the
+ * stats received from FW
+ * @psoc : psoc handle
+ * @rsp: pointer to data received from FW.
+ *
+ * This is called when wlan driver received response event for
+ * get arp stats to firmware.
+ *
+ * Return: None
+ */
+QDF_STATUS dp_get_arp_stats_event_handler(struct wlan_objmgr_psoc *psoc,
+					  struct dp_rsp_stats *rsp);
 #endif

+ 6 - 0
components/dp/core/inc/wlan_dp_priv.h

@@ -246,6 +246,10 @@ struct dp_tx_rx_stats {
  */
 struct dp_stats {
 	struct dp_tx_rx_stats tx_rx_stats;
+	struct dp_arp_stats arp_stats;
+	struct dp_dns_stats dns_stats;
+	struct dp_tcp_stats tcp_stats;
+	struct dp_icmpv4_stats icmpv4_stats;
 };
 
 /**
@@ -285,6 +289,8 @@ struct wlan_dp_intf {
 	qdf_mutex_t sta_periodic_stats_lock;
 #endif /* WLAN_FEATURE_PERIODIC_STA_STATS */
 	qdf_net_dev_stats stats;
+	bool con_status;
+	bool dad;
 #ifdef WLAN_FEATURE_DP_BUS_BANDWIDTH
 	unsigned long prev_rx_packets;
 	unsigned long prev_tx_packets;

+ 54 - 0
components/dp/core/src/wlan_dp_main.c

@@ -29,6 +29,8 @@
 #include <qdf_net_types.h>
 #include "wlan_objmgr_vdev_obj.h"
 #include <wlan_cm_ucfg_api.h>
+#include "wlan_dp_nud_tracking.h"
+#include "target_if_dp_comp.h"
 
 /* Global DP context */
 static struct wlan_dp_psoc_context *gp_dp_ctx;
@@ -497,6 +499,9 @@ dp_psoc_obj_create_notification(struct wlan_objmgr_psoc *psoc, void *arg)
 
 	dp_ctx->psoc = psoc;
 	dp_cfg_init(dp_ctx);
+	target_if_dp_register_tx_ops(&dp_ctx->sb_ops);
+	target_if_dp_register_rx_ops(&dp_ctx->nb_ops);
+
 	return status;
 }
 
@@ -809,3 +814,52 @@ void dp_clear_rps_cpu_mask(struct wlan_dp_psoc_context *dp_ctx)
 		dp_send_rps_disable_ind(dp_intf);
 	}
 }
+
+QDF_STATUS dp_get_arp_stats_event_handler(struct wlan_objmgr_psoc *psoc,
+					  struct dp_rsp_stats *rsp)
+{
+	struct wlan_dp_intf *dp_intf;
+	struct wlan_objmgr_vdev *vdev;
+
+	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
+						    rsp->vdev_id,
+						    WLAN_DP_ID);
+	if (!vdev) {
+		dp_err("Can't get vdev by vdev_id:%d", rsp->vdev_id);
+		return QDF_STATUS_E_INVAL;
+	}
+
+	dp_intf = dp_get_vdev_priv_obj(vdev);
+	if (!dp_intf) {
+		dp_err("Unable to get DP interface");
+		wlan_objmgr_vdev_release_ref(vdev, WLAN_DP_ID);
+		return QDF_STATUS_E_INVAL;
+	}
+
+	dp_info("rsp->arp_req_enqueue :%x", rsp->arp_req_enqueue);
+	dp_info("rsp->arp_req_tx_success :%x", rsp->arp_req_tx_success);
+	dp_info("rsp->arp_req_tx_failure :%x", rsp->arp_req_tx_failure);
+	dp_info("rsp->arp_rsp_recvd :%x", rsp->arp_rsp_recvd);
+	dp_info("rsp->out_of_order_arp_rsp_drop_cnt :%x",
+		rsp->out_of_order_arp_rsp_drop_cnt);
+	dp_info("rsp->dad_detected :%x", rsp->dad_detected);
+	dp_info("rsp->connect_status :%x", rsp->connect_status);
+	dp_info("rsp->ba_session_establishment_status :%x",
+		rsp->ba_session_establishment_status);
+
+	dp_intf->dp_stats.arp_stats.rx_fw_cnt = rsp->arp_rsp_recvd;
+	dp_intf->dad |= rsp->dad_detected;
+	dp_intf->con_status = rsp->connect_status;
+
+	/* Flag true indicates connectivity check stats present. */
+	if (rsp->connect_stats_present) {
+		dp_info("rsp->tcp_ack_recvd :%x", rsp->tcp_ack_recvd);
+		dp_info("rsp->icmpv4_rsp_recvd :%x", rsp->icmpv4_rsp_recvd);
+		dp_intf->dp_stats.tcp_stats.rx_fw_cnt = rsp->tcp_ack_recvd;
+		dp_intf->dp_stats.icmpv4_stats.rx_fw_cnt =
+							rsp->icmpv4_rsp_recvd;
+	}
+
+	wlan_objmgr_vdev_release_ref(vdev, WLAN_DP_ID);
+	return QDF_STATUS_SUCCESS;
+}

+ 209 - 0
components/dp/dispatcher/inc/wlan_dp_public_struct.h

@@ -30,6 +30,7 @@
 #include <wlan_nlink_common.h>
 #include <qca_vendor.h>
 #include <ani_system_defs.h>
+#include "cdp_txrx_ops.h"
 #include <qdf_defer.h>
 
 #ifdef TX_MULTIQ_PER_AC
@@ -50,6 +51,191 @@
 #define NUM_TX_QUEUES (4 * TX_QUEUES_PER_AC)
 #endif
 
+/**
+ * struct dp_arp_stats - arp debug stats count
+ * @tx_arp_req_count: no. of arp req received from network stack
+ * @rx_arp_rsp_count: no. of arp res received from FW
+ * @tx_dropped: no. of arp req dropped at hdd layer
+ * @rx_dropped: no. of arp res dropped
+ * @rx_delivered: no. of arp res delivered to network stack
+ * @rx_refused: no of arp rsp refused (not delivered) to network stack
+ * @tx_host_fw_sent: no of arp req sent by FW OTA
+ * @rx_host_drop_reorder: no of arp res dropped by host
+ * @rx_fw_cnt: no of arp res received by FW
+ * @tx_ack_cnt: no of arp req acked by FW
+ */
+struct dp_arp_stats {
+	uint16_t tx_arp_req_count;
+	uint16_t rx_arp_rsp_count;
+	uint16_t tx_dropped;
+	uint16_t rx_dropped;
+	uint16_t rx_delivered;
+	uint16_t rx_refused;
+	uint16_t tx_host_fw_sent;
+	uint16_t rx_host_drop_reorder;
+	uint16_t rx_fw_cnt;
+	uint16_t tx_ack_cnt;
+};
+
+/**
+ * struct dp_set_arp_stats_params - set/reset arp stats
+ * @vdev_id: session id
+ * @flag: enable/disable stats
+ * @pkt_type: type of packet(1 - arp)
+ * @ip_addr: subnet ipv4 address in case of encrypted packets
+ * @pkt_type_bitmap: pkt bitmap
+ * @tcp_src_port: tcp src port for pkt tracking
+ * @tcp_dst_port: tcp dst port for pkt tracking
+ * @icmp_ipv4: target ipv4 address to track ping packets
+ * @reserved: reserved
+ */
+struct dp_set_arp_stats_params {
+	uint32_t vdev_id;
+	uint8_t flag;
+	uint8_t pkt_type;
+	uint32_t ip_addr;
+	uint32_t pkt_type_bitmap;
+	uint32_t tcp_src_port;
+	uint32_t tcp_dst_port;
+	uint32_t icmp_ipv4;
+	uint32_t reserved;
+};
+
+/**
+ * struct dp_get_arp_stats_params - get arp stats from firmware
+ * @pkt_type: packet type(1 - ARP)
+ * @vdev_id: session id
+ */
+struct dp_get_arp_stats_params {
+	uint8_t pkt_type;
+	uint32_t vdev_id;
+};
+
+/**
+ * struct dp_dns_stats - dns debug stats count
+ * @tx_dns_req_count: no. of dns query received from network stack
+ * @rx_dns_rsp_count: no. of dns res received from FW
+ * @tx_dropped: no. of dns query dropped at hdd layer
+ * @rx_delivered: no. of dns res delivered to network stack
+ * @rx_refused: no of dns res refused (not delivered) to network stack
+ * @tx_host_fw_sent: no of dns query sent by FW OTA
+ * @rx_host_drop: no of dns res dropped by host
+ * @tx_ack_cnt: no of dns req acked by FW
+ */
+struct dp_dns_stats {
+	uint16_t tx_dns_req_count;
+	uint16_t rx_dns_rsp_count;
+	uint16_t tx_dropped;
+	uint16_t rx_delivered;
+	uint16_t rx_refused;
+	uint16_t tx_host_fw_sent;
+	uint16_t rx_host_drop;
+	uint16_t tx_ack_cnt;
+};
+
+/**
+ * struct dp_tcp_stats - tcp debug stats count
+ * @tx_tcp_syn_count: no. of tcp syn received from network stack
+ * @@tx_tcp_ack_count: no. of tcp ack received from network stack
+ * @rx_tcp_syn_ack_count: no. of tcp syn ack received from FW
+ * @tx_tcp_syn_dropped: no. of tcp syn dropped at hdd layer
+ * @tx_tcp_ack_dropped: no. of tcp ack dropped at hdd layer
+ * @rx_delivered: no. of tcp syn ack delivered to network stack
+ * @rx_refused: no of tcp syn ack refused (not delivered) to network stack
+ * @tx_tcp_syn_host_fw_sent: no of tcp syn sent by FW OTA
+ * @@tx_tcp_ack_host_fw_sent: no of tcp ack sent by FW OTA
+ * @rx_host_drop: no of tcp syn ack dropped by host
+ * @tx_tcp_syn_ack_cnt: no of tcp syn acked by FW
+ * @tx_tcp_syn_ack_cnt: no of tcp ack acked by FW
+ * @is_tcp_syn_ack_rcv: flag to check tcp syn ack received or not
+ * @is_tcp_ack_sent: flag to check tcp ack sent or not
+ */
+struct dp_tcp_stats {
+	uint16_t tx_tcp_syn_count;
+	uint16_t tx_tcp_ack_count;
+	uint16_t rx_tcp_syn_ack_count;
+	uint16_t tx_tcp_syn_dropped;
+	uint16_t tx_tcp_ack_dropped;
+	uint16_t rx_delivered;
+	uint16_t rx_refused;
+	uint16_t tx_tcp_syn_host_fw_sent;
+	uint16_t tx_tcp_ack_host_fw_sent;
+	uint16_t rx_host_drop;
+	uint16_t rx_fw_cnt;
+	uint16_t tx_tcp_syn_ack_cnt;
+	uint16_t tx_tcp_ack_ack_cnt;
+	bool is_tcp_syn_ack_rcv;
+	bool is_tcp_ack_sent;
+
+};
+
+/**
+ * struct dp_icmpv4_stats - icmpv4 debug stats count
+ * @tx_icmpv4_req_count: no. of icmpv4 req received from network stack
+ * @rx_icmpv4_rsp_count: no. of icmpv4 res received from FW
+ * @tx_dropped: no. of icmpv4 req dropped at hdd layer
+ * @rx_delivered: no. of icmpv4 res delivered to network stack
+ * @rx_refused: no of icmpv4 res refused (not delivered) to network stack
+ * @tx_host_fw_sent: no of icmpv4 req sent by FW OTA
+ * @rx_host_drop: no of icmpv4 res dropped by host
+ * @rx_fw_cnt: no of icmpv4 res received by FW
+ * @tx_ack_cnt: no of icmpv4 req acked by FW
+ */
+struct dp_icmpv4_stats {
+	uint16_t tx_icmpv4_req_count;
+	uint16_t rx_icmpv4_rsp_count;
+	uint16_t tx_dropped;
+	uint16_t rx_delivered;
+	uint16_t rx_refused;
+	uint16_t tx_host_fw_sent;
+	uint16_t rx_host_drop;
+	uint16_t rx_fw_cnt;
+	uint16_t tx_ack_cnt;
+};
+
+/**
+ * struct dp_rsp_stats - arp packet stats
+ * @arp_req_enqueue: fw tx count
+ * @arp_req_tx_success: tx ack count
+ * @arp_req_tx_failure: tx ack fail count
+ * @arp_rsp_recvd: rx fw count
+ * @out_of_order_arp_rsp_drop_cnt: out of order count
+ * @dad_detected: dad detected
+ * @connect_status: connection status
+ * @ba_session_establishment_status: BA session status
+ * @connect_stats_present: connectivity stats present or not
+ * @tcp_ack_recvd: tcp syn ack's count
+ * @icmpv4_rsp_recvd: icmpv4 responses count
+ */
+struct dp_rsp_stats {
+	uint32_t vdev_id;
+	uint32_t arp_req_enqueue;
+	uint32_t arp_req_tx_success;
+	uint32_t arp_req_tx_failure;
+	uint32_t arp_rsp_recvd;
+	uint32_t out_of_order_arp_rsp_drop_cnt;
+	uint32_t dad_detected;
+	uint32_t connect_status;
+	uint32_t ba_session_establishment_status;
+	bool connect_stats_present;
+	uint32_t tcp_ack_recvd;
+	uint32_t icmpv4_rsp_recvd;
+};
+
+/**
+ * struct dp_dhcp_ind - DHCP Start/Stop indication message
+ * @dhcp_start: Is DHCP start idication
+ * @device_mode: Mode of the device(ex:STA, AP)
+ * @intf_mac_addr: MAC address of the interface
+ * @peer_mac_addr: MAC address of the connected peer
+ */
+struct dp_dhcp_ind {
+	bool dhcp_start;
+	uint8_t device_mode;
+	struct qdf_mac_addr intf_mac_addr;
+	struct qdf_mac_addr peer_mac_addr;
+};
+
 /**
  * struct dp_mic_info - mic error info in dp
  * @ta_mac_addr: transmitter mac address
@@ -344,17 +530,40 @@ struct wlan_dp_psoc_callbacks {
 /**
  * struct wlan_dp_psoc_sb_ops - struct containing callback
  * to south bound APIs. callbacks to call traget_if APIs
+ * @dp_arp_stats_register_event_handler: Callback to register
+ * arp stas WMI handle
+ * @dp_arp_stats_unregister_event_handler: Callback to unregister
+ * arp stas WMI handle
+ * @dp_get_arp_req_stats: Callback to get arp stats
+ * @dp_set_arp_req_stats: Callback to  set arp stats
+ * @arp_request_ctx: ARP request context
+ * @dp_lro_config_cmd: Callback to  send LRO config command
+ * @dp_send_dhcp_ind: Callback to send DHCP indication
  */
 struct wlan_dp_psoc_sb_ops {
 	/*TODO to add target if TX ops*/
+	QDF_STATUS (*dp_arp_stats_register_event_handler)(struct wlan_objmgr_psoc *psoc);
+	QDF_STATUS (*dp_arp_stats_unregister_event_handler)(struct wlan_objmgr_psoc *psoc);
+	QDF_STATUS (*dp_get_arp_req_stats)(struct wlan_objmgr_psoc *psoc,
+					   struct dp_get_arp_stats_params *req_buf);
+	QDF_STATUS (*dp_set_arp_req_stats)(struct wlan_objmgr_psoc *psoc,
+					   struct dp_set_arp_stats_params *req_buf);
+	void *arp_request_ctx;
+	QDF_STATUS (*dp_lro_config_cmd)(struct wlan_objmgr_psoc *psoc,
+					struct cdp_lro_hash_config *dp_lro_cmd);
+	QDF_STATUS (*dp_send_dhcp_ind)(uint16_t vdev_id,
+				       struct dp_dhcp_ind *dhcp_ind);
 };
 
 /**
  * struct wlan_dp_psoc_nb_ops - struct containing callback
  * to north bound APIs. callbacks APIs to be called by target_if APIs
+ * @osif_dp_get_arp_stats_evt: Callback called on receiving arp stats event
  */
 struct wlan_dp_psoc_nb_ops {
 	/*TODO to add target if RX ops*/
+	void (*osif_dp_get_arp_stats_evt)(struct wlan_objmgr_psoc *psoc,
+					  struct dp_rsp_stats *rsp);
 };
 
 /**

+ 31 - 0
components/dp/dispatcher/inc/wlan_dp_ucfg_api.h

@@ -402,6 +402,27 @@ void ucfg_dp_nud_event(struct qdf_mac_addr *netdev_mac_addr,
 		       struct qdf_mac_addr *gw_mac_addr,
 		       uint8_t nud_state);
 
+/**
+ * ucfg_dp_get_arp_stats_event_handler - ARP get stats event handler
+ *
+ * @psoc: PSOC Handle
+ * @rsp : response message
+ *
+ * Return : 0 on success else error code.
+ */
+
+QDF_STATUS ucfg_dp_get_arp_stats_event_handler(struct wlan_objmgr_psoc *psoc,
+					       struct dp_rsp_stats *rsp);
+
+/**
+ * ucfg_dp_get_arp_request_ctx - Get ARP request context
+ *
+ * @psoc: PSOC Handle
+ *
+ * Return : ARP request context
+ */
+void *ucfg_dp_get_arp_request_ctx(struct wlan_objmgr_psoc *psoc);
+
 /**
  * ucfg_dp_nud_reset_tracking() - reset NUD tracking
  * @vdev: vdev handle
@@ -436,4 +457,14 @@ void ucfg_dp_nud_indicate_roam(struct wlan_objmgr_vdev *vdev);
  */
 void ucfg_dp_register_hdd_callbacks(struct wlan_objmgr_psoc *psoc,
 				    struct wlan_dp_psoc_callbacks *cb_obj);
+
+/**
+ * ucfg_dp_register_event_handler() - Resiter event handler with DP component
+ * @psoc: psoc handle
+ * @cb_obj: Callback object
+ *
+ * Returns: None
+ */
+void ucfg_dp_register_event_handler(struct wlan_objmgr_psoc *psoc,
+				    struct wlan_dp_psoc_nb_ops *cb_obj);
 #endif /* _WLAN_DP_UCFG_API_H_ */

+ 25 - 0
components/dp/dispatcher/src/wlan_dp_ucfg_api.c

@@ -636,6 +636,17 @@ void ucfg_dp_nud_event(struct qdf_mac_addr *netdev_mac_addr,
 	dp_nud_netevent_cb(netdev_mac_addr, gw_mac_addr, nud_state);
 }
 
+QDF_STATUS ucfg_dp_get_arp_stats_event_handler(struct wlan_objmgr_psoc *psoc,
+					       struct dp_rsp_stats *rsp)
+{
+	return dp_get_arp_stats_event_handler(psoc, rsp);
+}
+
+void *ucfg_dp_get_arp_request_ctx(struct wlan_objmgr_psoc *psoc)
+{
+	return dp_get_arp_request_ctx(psoc);
+}
+
 void ucfg_dp_nud_reset_tracking(struct wlan_objmgr_vdev *vdev)
 {
 	struct wlan_dp_intf *dp_intf = dp_get_vdev_priv_obj(vdev);
@@ -708,3 +719,17 @@ void ucfg_dp_register_hdd_callbacks(struct wlan_objmgr_psoc *psoc,
 	dp_ctx->dp_ops.dp_get_pause_map = cb_obj->dp_get_pause_map;
 	dp_ctx->dp_ops.dp_nud_failure_work = cb_obj->dp_nud_failure_work;
 }
+
+void ucfg_dp_register_event_handler(struct wlan_objmgr_psoc *psoc,
+				    struct wlan_dp_psoc_nb_ops *cb_obj)
+{
+	struct wlan_dp_psoc_context *dp_ctx = dp_psoc_get_priv(psoc);
+
+	if (!dp_ctx) {
+		dp_err("DP ctx is NULL");
+		return;
+	}
+
+	dp_ctx->nb_ops.osif_dp_get_arp_stats_evt =
+		cb_obj->osif_dp_get_arp_stats_evt;
+}

+ 329 - 0
components/target_if/dp/src/target_if_dp_comp.c

@@ -28,11 +28,340 @@
 #include "wlan_objmgr_psoc_obj.h"
 #include "wlan_dp_public_struct.h"
 #include "cdp_txrx_cmn.h"
+#include "cdp_txrx_ops.h"
 #include "wlan_dp_main.h"
 #include <wlan_cm_api.h>
 
+/**
+ * target_if_dp_arp_stats_event_handler() - arp stats event handler
+ * @scn: scn
+ * @data: buffer with event
+ * @datalen: buffer length
+ *
+ * Return: Return: 0 on success, failure code otherwise.
+ */
+static int
+target_if_dp_get_arp_stats_event_handler(ol_scn_t scn, uint8_t *data,
+					 uint32_t datalen)
+{
+	WMI_VDEV_GET_ARP_STAT_EVENTID_param_tlvs *param_buf;
+	wmi_vdev_get_arp_stats_event_fixed_param *data_event;
+	wmi_vdev_get_connectivity_check_stats *connect_stats_event;
+	struct wlan_objmgr_psoc *psoc;
+	struct wlan_dp_psoc_nb_ops *nb_ops;
+	uint8_t *buf_ptr;
+	struct dp_rsp_stats rsp = {0};
+
+	if (!scn || !data) {
+		dp_err("scn: 0x%pK, data: 0x%pK", scn, data);
+		return -EINVAL;
+	}
+	param_buf = (WMI_VDEV_GET_ARP_STAT_EVENTID_param_tlvs *)data;
+	if (!param_buf) {
+		dp_err("Invalid get arp stats event");
+		return -EINVAL;
+	}
+	data_event = param_buf->fixed_param;
+	if (!data_event) {
+		dp_err("Invalid get arp stats data event");
+		return -EINVAL;
+	}
+
+	psoc = target_if_get_psoc_from_scn_hdl(scn);
+	if (!psoc) {
+		dp_err("null psoc");
+		return -EINVAL;
+	}
+
+	nb_ops = dp_intf_get_rx_ops(psoc);
+	if (!nb_ops) {
+		dp_err("null tx ops");
+		return -EINVAL;
+	}
+
+	rsp.arp_req_enqueue = data_event->arp_req_enqueue;
+	rsp.vdev_id = data_event->vdev_id;
+	rsp.arp_req_tx_success = data_event->arp_req_tx_success;
+	rsp.arp_req_tx_failure = data_event->arp_req_tx_failure;
+	rsp.arp_rsp_recvd = data_event->arp_rsp_recvd;
+	rsp.out_of_order_arp_rsp_drop_cnt =
+		data_event->out_of_order_arp_rsp_drop_cnt;
+	rsp.dad_detected = data_event->dad_detected;
+	rsp.connect_status = data_event->connect_status;
+	rsp.ba_session_establishment_status =
+		data_event->ba_session_establishment_status;
+
+	buf_ptr = (uint8_t *)data_event;
+	buf_ptr = buf_ptr + sizeof(wmi_vdev_get_arp_stats_event_fixed_param) +
+		  WMI_TLV_HDR_SIZE;
+	connect_stats_event = (wmi_vdev_get_connectivity_check_stats *)buf_ptr;
+
+	if (((connect_stats_event->tlv_header & 0xFFFF0000) >> 16 ==
+	      WMITLV_TAG_STRUC_wmi_vdev_get_connectivity_check_stats)) {
+		rsp.connect_stats_present = true;
+		rsp.tcp_ack_recvd = connect_stats_event->tcp_ack_recvd;
+		rsp.icmpv4_rsp_recvd = connect_stats_event->icmpv4_rsp_recvd;
+		dp_debug("tcp_ack_recvd %d icmpv4_rsp_recvd %d",
+			 connect_stats_event->tcp_ack_recvd,
+			 connect_stats_event->icmpv4_rsp_recvd);
+	}
+
+	nb_ops->osif_dp_get_arp_stats_evt(psoc, &rsp);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+/**
+ * target_if_dp_arp_stats_register_event_handler() - register event handler
+ * @psoc: psoc handle
+ *
+ * Return: Return: 0 on success, failure code otherwise.
+ */
+static QDF_STATUS
+target_if_dp_arp_stats_register_event_handler(struct wlan_objmgr_psoc *psoc)
+{
+	struct wmi_unified *wmi_handle;
+	QDF_STATUS ret_val;
+
+	if (!psoc) {
+		dp_err("PSOC is NULL!");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
+	if (!wmi_handle) {
+		dp_err("wmi_handle is null");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	ret_val = wmi_unified_register_event_handler(wmi_handle,
+				wmi_get_arp_stats_req_id,
+				target_if_dp_get_arp_stats_event_handler,
+				WMI_RX_WORK_CTX);
+	if (QDF_IS_STATUS_ERROR(ret_val))
+		dp_err("Failed to register event_handler");
+
+	return QDF_STATUS_SUCCESS;
+}
+
+/**
+ * target_if_dp_arp_stats_unregister_event_handler() - unregister event handler
+ * @psoc: psoc handle
+ *
+ * Return: Return: 0 on success, failure code otherwise.
+ */
+static QDF_STATUS
+target_if_dp_arp_stats_unregister_event_handler(struct wlan_objmgr_psoc *psoc)
+{
+	struct wmi_unified *wmi_handle;
+
+	if (!psoc) {
+		dp_err("PSOC is NULL!");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
+	if (!wmi_handle) {
+		dp_err("wmi_handle is null");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	wmi_unified_unregister_event_handler(wmi_handle,
+					     wmi_get_arp_stats_req_id);
+	return QDF_STATUS_SUCCESS;
+}
+
+/**
+ * target_if_dp_get_arp_req_stats() - send get arp stats request command to fw
+ * @psoc: psoc handle
+ * @req_buf: get arp stats request buffer
+ *
+ * Return: Return: 0 on success, failure code otherwise.
+ */
+static QDF_STATUS
+target_if_dp_get_arp_req_stats(struct wlan_objmgr_psoc *psoc,
+			       struct dp_get_arp_stats_params *req_buf)
+{
+	QDF_STATUS status;
+	struct get_arp_stats *arp_stats;
+	struct wmi_unified *wmi_handle;
+	struct wlan_objmgr_vdev *vdev;
+
+	if (!psoc) {
+		dp_err("PSOC is NULL!");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
+	if (!wmi_handle) {
+		dp_err("wmi_handle is null");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
+						    req_buf->vdev_id,
+						    WLAN_DP_ID);
+	if (!vdev) {
+		dp_err("Can't get vdev by vdev_id:%d", req_buf->vdev_id);
+		return QDF_STATUS_E_INVAL;
+	}
+	if (!wlan_cm_is_vdev_active(vdev)) {
+		dp_debug("vdev id:%d is not started", req_buf->vdev_id);
+		status = QDF_STATUS_E_INVAL;
+		goto release_ref;
+	}
+
+	arp_stats = (struct get_arp_stats *)req_buf;
+	status = wmi_unified_get_arp_stats_req(wmi_handle, arp_stats);
+	if (QDF_IS_STATUS_ERROR(status))
+		dp_err("failed to send get arp stats to FW");
+release_ref:
+	wlan_objmgr_vdev_release_ref(vdev, WLAN_DP_ID);
+	return status;
+}
+
+/**
+ * target_if_dp_set_arp_req_stats() - send set arp stats request command to fw
+ * @psoc: psoc handle
+ * @req_buf: set srp stats request buffer
+ *
+ * Return: Return: 0 on success, failure code otherwise.
+ */
+static QDF_STATUS
+target_if_dp_set_arp_req_stats(struct wlan_objmgr_psoc *psoc,
+			       struct dp_set_arp_stats_params *req_buf)
+{
+	QDF_STATUS status;
+	struct set_arp_stats *arp_stats;
+	struct wmi_unified *wmi_handle;
+	struct wlan_objmgr_vdev *vdev;
+
+	if (!psoc) {
+		dp_err("PSOC is NULL!");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
+	if (!wmi_handle) {
+		dp_err("wmi_handle is null");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
+						    req_buf->vdev_id,
+						    WLAN_DP_ID);
+	if (!vdev) {
+		dp_err("Can't get vdev by vdev_id:%d", req_buf->vdev_id);
+		return QDF_STATUS_E_INVAL;
+	}
+	if (!wlan_vdev_is_up(vdev)) {
+		dp_debug("vdev id:%d is not started", req_buf->vdev_id);
+		status = QDF_STATUS_E_INVAL;
+		goto release_ref;
+	}
+	arp_stats = (struct set_arp_stats *)req_buf;
+	status = wmi_unified_set_arp_stats_req(wmi_handle, arp_stats);
+	if (QDF_IS_STATUS_ERROR(status))
+		dp_err("failed to set arp stats to FW");
+
+release_ref:
+	wlan_objmgr_vdev_release_ref(vdev, WLAN_DP_ID);
+	return status;
+}
+
+/**
+ * target_if_dp_lro_config_cmd() - process the LRO config command
+ * @psoc: Pointer to psoc handle
+ * @dp_lro_cmd: Pointer to LRO configuration parameters
+ *
+ * This function sends down the LRO configuration parameters to
+ * the firmware to enable LRO, sets the TCP flags and sets the
+ * seed values for the toeplitz hash generation
+ *
+ * Return: QDF_STATUS_SUCCESS for success otherwise failure
+ */
+static QDF_STATUS
+target_if_dp_lro_config_cmd(struct wlan_objmgr_psoc *psoc,
+			    struct cdp_lro_hash_config *dp_lro_cmd)
+{
+	struct wmi_lro_config_cmd_t wmi_lro_cmd = {0};
+	struct wmi_unified *wmi_handle;
+
+	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
+	if (!dp_lro_cmd || !wmi_handle) {
+		dp_err("Invalid input!");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	wmi_lro_cmd.lro_enable = dp_lro_cmd->lro_enable;
+	wmi_lro_cmd.tcp_flag = dp_lro_cmd->tcp_flag;
+	wmi_lro_cmd.tcp_flag_mask = dp_lro_cmd->tcp_flag_mask;
+	qdf_mem_copy(wmi_lro_cmd.toeplitz_hash_ipv4,
+		     dp_lro_cmd->toeplitz_hash_ipv4,
+		     LRO_IPV4_SEED_ARR_SZ * sizeof(uint32_t));
+	qdf_mem_copy(wmi_lro_cmd.toeplitz_hash_ipv6,
+		     dp_lro_cmd->toeplitz_hash_ipv6,
+		     LRO_IPV6_SEED_ARR_SZ * sizeof(uint32_t));
+
+	return wmi_unified_lro_config_cmd(wmi_handle, &wmi_lro_cmd);
+}
+
+/**
+ * target_if_dp_send_dhcp_ind() - process set arp stats request command to fw
+ * @vdev_id: vdev id
+ * @dhcp_ind: DHCP indication.
+ *
+ * Return: 0 on success, failure code otherwise.
+ */
+static QDF_STATUS
+target_if_dp_send_dhcp_ind(uint16_t vdev_id,
+			   struct dp_dhcp_ind *dhcp_ind)
+{
+	struct wmi_unified *wmi_handle;
+	struct wlan_objmgr_psoc *psoc;
+	wmi_peer_set_param_cmd_fixed_param peer_set_param_fp = {0};
+
+	psoc = wlan_objmgr_get_psoc_by_id(0, WLAN_PSOC_TARGET_IF_ID);
+	if (!psoc) {
+		dp_err("psoc null");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
+	if (!wmi_handle) {
+		dp_err("Unable to get wmi handle");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	/* fill in values */
+	peer_set_param_fp.vdev_id = vdev_id;
+	peer_set_param_fp.param_id = WMI_PEER_CRIT_PROTO_HINT_ENABLED;
+
+	if (dhcp_ind->dhcp_start)
+		peer_set_param_fp.param_value = 1;
+	else
+		peer_set_param_fp.param_value = 0;
+
+	WMI_CHAR_ARRAY_TO_MAC_ADDR(dhcp_ind->peer_mac_addr.bytes,
+				   &peer_set_param_fp.peer_macaddr);
+
+	return wmi_unified_process_dhcp_ind(wmi_handle,
+						&peer_set_param_fp);
+}
+
 void target_if_dp_register_tx_ops(struct wlan_dp_psoc_sb_ops *sb_ops)
 {
+	sb_ops->dp_arp_stats_register_event_handler =
+		target_if_dp_arp_stats_register_event_handler;
+	sb_ops->dp_arp_stats_unregister_event_handler =
+		target_if_dp_arp_stats_unregister_event_handler;
+	sb_ops->dp_get_arp_req_stats =
+		target_if_dp_get_arp_req_stats;
+	sb_ops->dp_set_arp_req_stats =
+		target_if_dp_set_arp_req_stats;
+	sb_ops->dp_lro_config_cmd = target_if_dp_lro_config_cmd;
+	sb_ops->dp_send_dhcp_ind =
+		target_if_dp_send_dhcp_ind;
 }
 
 void target_if_dp_register_rx_ops(struct wlan_dp_psoc_nb_ops *nb_ops)

+ 46 - 0
os_if/dp/src/os_if_dp.c

@@ -30,6 +30,7 @@
 #include "osif_vdev_sync.h"
 #include "osif_sync.h"
 #include <net/netevent.h>
+#include "wlan_osif_request_manager.h"
 
 #ifdef WLAN_FEATURE_DP_BUS_BANDWIDTH
 /**
@@ -252,6 +253,33 @@ osif_dp_process_sap_mic_error(struct dp_mic_error_info *info,
 				     GFP_KERNEL);
 }
 
+/**
+ * osif_dp_get_arp_stats_event_handler() - ARP get stats event handler
+ * @psoc: psoc handle
+ * @rsp: Get ARP stats response
+ *
+ * Return: None
+ */
+static void osif_dp_get_arp_stats_event_handler(struct wlan_objmgr_psoc *psoc,
+						struct dp_rsp_stats *rsp)
+{
+	struct osif_request *request = NULL;
+	void *context;
+
+	context = ucfg_dp_get_arp_request_ctx(psoc);
+	if (!context)
+		return;
+
+	request = osif_request_get(context);
+	if (!request)
+		return;
+
+	ucfg_dp_get_arp_stats_event_handler(psoc, rsp);
+
+	osif_request_complete(request);
+	osif_request_put(request);
+}
+
 #ifdef WLAN_NUD_TRACKING
 /**
  * nud_state_osif_to_dp() - convert os_if to enum
@@ -389,6 +417,23 @@ void osif_dp_nud_unregister_netevent_notifier(struct wlan_objmgr_psoc *psoc)
 {
 }
 #endif
+
+/**
+ * os_if_dp_register_event_handler() - Register osif event handler
+ * @psoc: psoc handle
+ *
+ * Return: None
+ */
+static void os_if_dp_register_event_handler(struct wlan_objmgr_psoc *psoc)
+{
+	struct wlan_dp_psoc_nb_ops cb_obj = {0};
+
+	cb_obj.osif_dp_get_arp_stats_evt =
+		osif_dp_get_arp_stats_event_handler;
+
+	ucfg_dp_register_event_handler(psoc, &cb_obj);
+}
+
 void os_if_dp_register_hdd_callbacks(struct wlan_objmgr_psoc *psoc,
 				     struct wlan_dp_psoc_callbacks *cb_obj)
 {
@@ -399,4 +444,5 @@ void os_if_dp_register_hdd_callbacks(struct wlan_objmgr_psoc *psoc,
 	cb_obj->osif_dp_process_sap_mic_error = osif_dp_process_sap_mic_error;
 
 	ucfg_dp_register_hdd_callbacks(psoc, cb_obj);
+	os_if_dp_register_event_handler(psoc);
 }