Loading drivers/platform/msm/ipa_fmwk/ipa_fmwk.c +194 −6 Original line number Diff line number Diff line Loading @@ -110,6 +110,8 @@ struct ipa_fmwk_contex { struct mutex lock; ipa_uc_ready_cb uc_ready_cb; void *uc_ready_priv; ipa_eth_ready_cb eth_ready_cb; void *eth_userdata; enum ipa_uc_offload_proto proto; /* ipa core driver APIs */ Loading Loading @@ -356,6 +358,26 @@ struct ipa_fmwk_contex { int (*ipa_wigig_set_perf_profile)(u32 max_supported_bw_mbps); int (*ipa_wigig_save_regs)(void); /* ipa eth APIs */ int (*ipa_eth_register_ready_cb)(struct ipa_eth_ready *ready_info); int (*ipa_eth_unregister_ready_cb)(struct ipa_eth_ready *ready_info); int (*ipa_eth_client_conn_pipes)(struct ipa_eth_client *client); int (*ipa_eth_client_disconn_pipes)(struct ipa_eth_client *client); int (*ipa_eth_client_reg_intf)(struct ipa_eth_intf_info *intf); int (*ipa_eth_client_unreg_intf)(struct ipa_eth_intf_info *intf); int (*ipa_eth_client_set_perf_profile)(struct ipa_eth_client *client, struct ipa_eth_perf_profile *profile); int (*ipa_eth_client_conn_evt)(struct ipa_ecm_msg *msg); int (*ipa_eth_client_disconn_evt)(struct ipa_ecm_msg *msg); }; static struct ipa_fmwk_contex *ipa_fmwk_ctx; Loading @@ -376,23 +398,34 @@ static inline void ipa_trigger_ipa_ready_cbs(void) } } static inline void ipa_register_uc_ready_cb(void) static inline void ipa_late_register_ready_cb(void) { int ret; if (ipa_fmwk_ctx->uc_ready_cb) { struct ipa_uc_ready_params param; if (ipa_fmwk_ctx->uc_ready_cb) { param.notify = ipa_fmwk_ctx->uc_ready_cb; param.priv = ipa_fmwk_ctx->uc_ready_priv; param.proto = ipa_fmwk_ctx->proto; ret = ipa_fmwk_ctx->ipa_uc_offload_reg_rdyCB(¶m); ipa_fmwk_ctx->ipa_uc_offload_reg_rdyCB(¶m); /* if uc is already ready, client expects cb to be called */ if (param.is_uC_ready) { ipa_fmwk_ctx->uc_ready_cb( ipa_fmwk_ctx->uc_ready_priv); } } if (ipa_fmwk_ctx->eth_ready_cb) { struct ipa_eth_ready ready_info; /* just late call to ipa_eth_register_ready_cb */ ready_info.notify = ipa_fmwk_ctx->eth_ready_cb; ready_info.userdata = ipa_fmwk_ctx->eth_userdata; ipa_fmwk_ctx->ipa_eth_register_ready_cb(&ready_info); /* nobody cares anymore about ready_info->is_eth_ready since * if we got here it means that we already returned false there */ } } /* registration API for IPA core module */ Loading Loading @@ -452,7 +485,7 @@ int ipa_fmwk_register_ipa(const struct ipa_core_data *in) ipa_fmwk_ctx->ipa_ready = true; ipa_trigger_ipa_ready_cbs(); ipa_register_uc_ready_cb(); ipa_late_register_ready_cb(); mutex_unlock(&ipa_fmwk_ctx->lock); pr_info("IPA driver is now in ready state\n"); Loading Loading @@ -1781,6 +1814,161 @@ int ipa_wigig_save_regs(void) } EXPORT_SYMBOL(ipa_wigig_save_regs); /* registration API for IPA eth module */ int ipa_fmwk_register_ipa_eth(const struct ipa_eth_data *in) { if (!ipa_fmwk_ctx) { pr_err("ipa framework hasn't been initialized yet\n"); return -EPERM; } if (ipa_fmwk_ctx->ipa_eth_register_ready_cb || ipa_fmwk_ctx->ipa_eth_unregister_ready_cb || ipa_fmwk_ctx->ipa_eth_client_conn_pipes || ipa_fmwk_ctx->ipa_eth_client_disconn_pipes || ipa_fmwk_ctx->ipa_eth_client_reg_intf || ipa_fmwk_ctx->ipa_eth_client_unreg_intf || ipa_fmwk_ctx->ipa_eth_client_set_perf_profile || ipa_fmwk_ctx->ipa_eth_client_conn_evt || ipa_fmwk_ctx->ipa_eth_client_disconn_evt) { pr_err("ipa_eth APIs were already initialized\n"); return -EPERM; } ipa_fmwk_ctx->ipa_eth_register_ready_cb = in->ipa_eth_register_ready_cb; ipa_fmwk_ctx->ipa_eth_unregister_ready_cb = in->ipa_eth_unregister_ready_cb; ipa_fmwk_ctx->ipa_eth_client_conn_pipes = in->ipa_eth_client_conn_pipes; ipa_fmwk_ctx->ipa_eth_client_disconn_pipes = in->ipa_eth_client_disconn_pipes; ipa_fmwk_ctx->ipa_eth_client_reg_intf = in->ipa_eth_client_reg_intf; ipa_fmwk_ctx->ipa_eth_client_unreg_intf = in->ipa_eth_client_unreg_intf; ipa_fmwk_ctx->ipa_eth_client_set_perf_profile = in->ipa_eth_client_set_perf_profile; ipa_fmwk_ctx->ipa_eth_client_conn_evt = in->ipa_eth_client_conn_evt; ipa_fmwk_ctx->ipa_eth_client_disconn_evt = in->ipa_eth_client_disconn_evt; pr_info("ipa_eth registered successfully\n"); return 0; } EXPORT_SYMBOL(ipa_fmwk_register_ipa_eth); int ipa_eth_register_ready_cb(struct ipa_eth_ready *ready_info) { int ret; if (!ipa_fmwk_ctx) { pr_err("ipa framework hasn't been initialized yet\n"); return -EPERM; } mutex_lock(&ipa_fmwk_ctx->lock); if (ipa_fmwk_ctx->ipa_ready) { /* call real func, unlock and return */ ret = ipa_fmwk_ctx->ipa_eth_register_ready_cb(ready_info); mutex_unlock(&ipa_fmwk_ctx->lock); return ret; } ipa_fmwk_ctx->eth_ready_cb = ready_info->notify; ipa_fmwk_ctx->eth_userdata = ready_info->userdata; ready_info->is_eth_ready = false; mutex_unlock(&ipa_fmwk_ctx->lock); return 0; } EXPORT_SYMBOL(ipa_eth_register_ready_cb); int ipa_eth_unregister_ready_cb(struct ipa_eth_ready *ready_info) { int ret; IPA_FMWK_DISPATCH_RETURN_DP(ipa_eth_unregister_ready_cb, ready_info); return ret; } EXPORT_SYMBOL(ipa_eth_unregister_ready_cb); int ipa_eth_client_conn_pipes(struct ipa_eth_client *client) { int ret; IPA_FMWK_DISPATCH_RETURN_DP(ipa_eth_client_conn_pipes, client); return ret; } EXPORT_SYMBOL(ipa_eth_client_conn_pipes); int ipa_eth_client_disconn_pipes(struct ipa_eth_client *client) { int ret; IPA_FMWK_DISPATCH_RETURN_DP(ipa_eth_client_disconn_pipes, client); return ret; } EXPORT_SYMBOL(ipa_eth_client_disconn_pipes); int ipa_eth_client_reg_intf(struct ipa_eth_intf_info *intf) { int ret; IPA_FMWK_DISPATCH_RETURN_DP(ipa_eth_client_reg_intf, intf); return ret; } EXPORT_SYMBOL(ipa_eth_client_reg_intf); int ipa_eth_client_unreg_intf(struct ipa_eth_intf_info *intf) { int ret; IPA_FMWK_DISPATCH_RETURN_DP(ipa_eth_client_unreg_intf, intf); return ret; } EXPORT_SYMBOL(ipa_eth_client_unreg_intf); int ipa_eth_client_set_perf_profile(struct ipa_eth_client *client, struct ipa_eth_perf_profile *profile) { int ret; IPA_FMWK_DISPATCH_RETURN_DP(ipa_eth_client_set_perf_profile, client, profile); return ret; } EXPORT_SYMBOL(ipa_eth_client_set_perf_profile); int ipa_eth_client_conn_evt(struct ipa_ecm_msg *msg) { int ret; IPA_FMWK_DISPATCH_RETURN_DP(ipa_eth_client_conn_evt, msg); return ret; } EXPORT_SYMBOL(ipa_eth_client_conn_evt); int ipa_eth_client_disconn_evt(struct ipa_ecm_msg *msg) { int ret; IPA_FMWK_DISPATCH_RETURN_DP(ipa_eth_client_disconn_evt, msg); return ret; } EXPORT_SYMBOL(ipa_eth_client_disconn_evt); /* module functions */ static int __init ipa_fmwk_init(void) { Loading include/linux/ipa.h +18 −0 Original line number Diff line number Diff line Loading @@ -889,6 +889,24 @@ struct IpaHwRingStats_t { u32 RingUtilCount; } __packed; /** * struct ipa_uc_dbg_rtk_ring_stats - uC dbg stats info for RTK * offloading protocol * @commStats: common stats * @trCount: transfer ring count * @erCount: event ring count * @totalAosCount: total AoS completion count * @busyTime: total busy time */ struct ipa_uc_dbg_rtk_ring_stats { struct IpaHwRingStats_t commStats; u32 trCount; u32 erCount; u32 totalAosCount; u64 busyTime; } __packed; /** * struct IpaHwStatsWDIRxInfoData_t - Structure holding the WDI Rx channel * structures Loading include/linux/ipa_eth.h 0 → 100644 +255 −0 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. */ #ifndef _IPA_ETH_H_ #define _IPA_ETH_H_ #include <linux/ipa.h> #include <linux/msm_ipa.h> #include <linux/msm_gsi.h> /* New architecture prototypes */ typedef void (*ipa_eth_ready_cb)(void *user_data); typedef u32 ipa_eth_hdl_t; /** * struct ipa_eth_ready_cb - eth readiness parameters * * @notify: ipa_eth client ready callback notifier * @userdata: userdata for ipa_eth ready cb * @is_eth_ready: true if ipa_eth client is already ready */ struct ipa_eth_ready { ipa_eth_ready_cb notify; void *userdata; /* out params */ bool is_eth_ready; }; /** * enum ipa_eth_client_type - names for the various IPA * eth "clients". */ enum ipa_eth_client_type { IPA_ETH_CLIENT_AQC107, IPA_ETH_CLIENT_AQC113, IPA_ETH_CLIENT_RTK8111K, IPA_ETH_CLIENT_RTK8125B, IPA_ETH_CLIENT_NTN, IPA_ETH_CLIENT_EMAC, IPA_ETH_CLIENT_MAX, }; /** * enum ipa_eth_pipe_traffic_type - traffic type for the various IPA * eth "pipes". */ enum ipa_eth_pipe_traffic_type { IPA_ETH_PIPE_BEST_EFFORT, IPA_ETH_PIPE_LOW_LATENCY, IPA_ETH_PIPE_TRAFFIC_TYPE_MAX, }; /** * enum ipa_eth_pipe_direction - pipe direcitons for same * ethernet client. */ enum ipa_eth_pipe_direction { IPA_ETH_PIPE_DIR_TX, IPA_ETH_PIPE_DIR_RX, IPA_ETH_PIPE_DIR_MAX, }; #define IPA_ETH_INST_ID_MAX (2) /** * struct ipa_eth_aqc_setup_info - parameters for aqc ethernet * offloading * * @bar_addr: bar PA to access AQC register * @head_ptr_offs: head ptr offset * @aqc_ch: AQC ch number * @dest_tail_ptr_offs: tail ptr offset */ struct ipa_eth_aqc_setup_info { phys_addr_t bar_addr; phys_addr_t head_ptr_offs; u8 aqc_ch; phys_addr_t dest_tail_ptr_offs; }; /** * struct ipa_eth_realtek_setup_info - parameters for realtek ethernet * offloading * * @bar_addr: bar PA to access RTK register * @bar_size: bar region size * @queue_number: Which RTK queue to check the status on * @dest_tail_ptr_offs: tail ptr offset */ struct ipa_eth_realtek_setup_info { phys_addr_t bar_addr; u32 bar_size; u8 queue_number; phys_addr_t dest_tail_ptr_offs; }; /** * struct ipa_eth_buff_smmu_map - IPA iova->pa SMMU mapping * @iova: virtual address of the data buffer * @pa: physical address of the data buffer */ struct ipa_eth_buff_smmu_map { dma_addr_t iova; phys_addr_t pa; }; /** * struct ipa_eth_pipe_setup_info - info needed for IPA setups * @is_transfer_ring_valid: if transfer ring is needed * @transfer_ring_base: the base of the transfer ring * @transfer_ring_sgt: sgtable of transfer ring * @transfer_ring_size: size of the transfer ring * @is_buffer_pool_valid: if buffer pool is needed * @buffer_pool_base_addr: base of buffer pool address * @buffer_pool_base_sgt: sgtable of buffer pool * @data_buff_list_size: number of buffers * @data_buff_list: array of data buffer list * @fix_buffer_size: buffer size * @notify: callback for exception/embedded packets * @priv: priv for exception callback * @client_info: vendor specific pipe setup info * @db_pa: doorbell physical address * @db_val: doorbell value ethernet HW need to ring */ struct ipa_eth_pipe_setup_info { /* transfer ring info */ bool is_transfer_ring_valid; dma_addr_t transfer_ring_base; struct sg_table *transfer_ring_sgt; u32 transfer_ring_size; /* buffer pool info */ bool is_buffer_pool_valid; dma_addr_t buffer_pool_base_addr; struct sg_table *buffer_pool_base_sgt; /* buffer info */ u32 data_buff_list_size; struct ipa_eth_buff_smmu_map *data_buff_list; u32 fix_buffer_size; /* client notify cb */ ipa_notify_cb notify; void *priv; /* vendor specific info */ union { struct ipa_eth_aqc_setup_info aqc; struct ipa_eth_realtek_setup_info rtk; } client_info; /* output params */ phys_addr_t db_pa; u32 db_val; }; /** * struct ipa_eth_client_pipe_info - ETH pipe/gsi related configuration * @link: link of ep for different client function on same ethernet HW * @dir: TX or RX direction * @info: tx/rx pipe setup info * @client_info: client the pipe belongs to * @pipe_hdl: output params, pipe handle */ struct ipa_eth_client_pipe_info { struct list_head link; enum ipa_eth_pipe_direction dir; struct ipa_eth_pipe_setup_info info; struct ipa_eth_client *client_info; /* output params */ ipa_eth_hdl_t pipe_hdl; }; /** * struct ipa_eth_client - client info per traffic type * provided by offload client * @client_type: ethernet client type * @inst_id: instance id for dual NIC support * @traffic_type: traffic type * @pipe_list: list of pipes with same traffic type * @priv: private data for client */ struct ipa_eth_client { /* vendor driver */ enum ipa_eth_client_type client_type; u8 inst_id; /* traffic type */ enum ipa_eth_pipe_traffic_type traffic_type; struct list_head pipe_list; /* client specific priv data*/ void *priv; }; /** * struct ipa_eth_perf_profile - To set BandWidth profile * * @max_supported_bw_mbps: maximum bandwidth needed (in Mbps) */ struct ipa_eth_perf_profile { u32 max_supported_bw_mbps; }; /** * struct ipa_eth_hdr_info - Header to install on IPA HW * * @hdr: header to install on IPA HW * @hdr_len: length of header * @dst_mac_addr_offset: destination mac address offset * @hdr_type: layer two header type */ struct ipa_eth_hdr_info { u8 *hdr; u8 hdr_len; u8 dst_mac_addr_offset; enum ipa_hdr_l2_type hdr_type; }; /** * struct ipa_eth_intf_info - parameters for ipa offload * interface registration * * @netdev_name: network interface name * @hdr: hdr for ipv4/ipv6 * @pipe_hdl_list_size: number of pipes prop needed for this interface * @pipe_hdl_list: array of pipes used for this interface */ struct ipa_eth_intf_info { const char *netdev_name; struct ipa_eth_hdr_info hdr[IPA_IP_MAX]; /* tx/rx pipes for same netdev */ int pipe_hdl_list_size; ipa_eth_hdl_t *pipe_hdl_list; }; int ipa_eth_register_ready_cb(struct ipa_eth_ready *ready_info); int ipa_eth_unregister_ready_cb(struct ipa_eth_ready *ready_info); int ipa_eth_client_conn_pipes(struct ipa_eth_client *client); int ipa_eth_client_disconn_pipes(struct ipa_eth_client *client); int ipa_eth_client_reg_intf(struct ipa_eth_intf_info *intf); int ipa_eth_client_unreg_intf(struct ipa_eth_intf_info *intf); int ipa_eth_client_set_perf_profile(struct ipa_eth_client *client, struct ipa_eth_perf_profile *profile); int ipa_eth_client_conn_evt(struct ipa_ecm_msg *msg); int ipa_eth_client_disconn_evt(struct ipa_ecm_msg *msg); #endif // _IPA_ETH_H_ include/linux/ipa_fmwk.h +29 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ #include <linux/ipa_usb.h> #include <linux/ipa_odu_bridge.h> #include <linux/ipa_qmi_service_v01.h> #include <linux/ipa_eth.h> struct ipa_core_data { int (*ipa_tx_dp)(enum ipa_client_type dst, struct sk_buff *skb, Loading Loading @@ -268,6 +269,27 @@ struct ipa_wigig_data { int (*ipa_wigig_save_regs)(void); }; struct ipa_eth_data { int (*ipa_eth_register_ready_cb)(struct ipa_eth_ready *ready_info); int (*ipa_eth_unregister_ready_cb)(struct ipa_eth_ready *ready_info); int (*ipa_eth_client_conn_pipes)(struct ipa_eth_client *client); int (*ipa_eth_client_disconn_pipes)(struct ipa_eth_client *client); int (*ipa_eth_client_reg_intf)(struct ipa_eth_intf_info *intf); int (*ipa_eth_client_unreg_intf)(struct ipa_eth_intf_info *intf); int (*ipa_eth_client_set_perf_profile)(struct ipa_eth_client *client, struct ipa_eth_perf_profile *profile); int (*ipa_eth_client_conn_evt)(struct ipa_ecm_msg *msg); int (*ipa_eth_client_disconn_evt)(struct ipa_ecm_msg *msg); }; #if IS_ENABLED(CONFIG_IPA3) int ipa_fmwk_register_ipa(const struct ipa_core_data *in); Loading @@ -284,6 +306,8 @@ int ipa_fmwk_register_ipa_mhi(const struct ipa_mhi_data *in); int ipa_fmwk_register_ipa_wigig(const struct ipa_wigig_data *in); int ipa_fmwk_register_ipa_eth(const struct ipa_eth_data *in); #else /* IS_ENABLED(CONFIG_IPA3) */ int ipa_fmwk_register_ipa(const struct ipa_core_data *in) Loading Loading @@ -321,6 +345,11 @@ int ipa_fmwk_register_ipa_wigig(const struct ipa_wigig_data *in) return -EPERM; } int ipa_fmwk_register_ipa_eth(const struct ipa_eth_data *in) { return -EPERM; } #endif /* IS_ENABLED(CONFIG_IPA3) */ #endif /* _IPA_FMWK_H_ */ include/uapi/linux/msm_ipa.h +4 −1 Original line number Diff line number Diff line Loading @@ -401,9 +401,12 @@ enum ipa_client_type { IPA_CLIENT_QDSS_PROD = 106, IPA_CLIENT_MHI_QDSS_CONS = 107, IPA_CLIENT_RTK_ETHERNET_PROD = 108, IPA_CLIENT_RTK_ETHERNET_CONS = 109, }; #define IPA_CLIENT_MAX (IPA_CLIENT_MHI_QDSS_CONS + 1) #define IPA_CLIENT_MAX (IPA_CLIENT_RTK_ETHERNET_CONS + 1) #define IPA_CLIENT_WLAN2_PROD IPA_CLIENT_A5_WLAN_AMPDU_PROD #define IPA_CLIENT_Q6_DL_NLO_DATA_PROD IPA_CLIENT_Q6_DL_NLO_DATA_PROD Loading Loading
drivers/platform/msm/ipa_fmwk/ipa_fmwk.c +194 −6 Original line number Diff line number Diff line Loading @@ -110,6 +110,8 @@ struct ipa_fmwk_contex { struct mutex lock; ipa_uc_ready_cb uc_ready_cb; void *uc_ready_priv; ipa_eth_ready_cb eth_ready_cb; void *eth_userdata; enum ipa_uc_offload_proto proto; /* ipa core driver APIs */ Loading Loading @@ -356,6 +358,26 @@ struct ipa_fmwk_contex { int (*ipa_wigig_set_perf_profile)(u32 max_supported_bw_mbps); int (*ipa_wigig_save_regs)(void); /* ipa eth APIs */ int (*ipa_eth_register_ready_cb)(struct ipa_eth_ready *ready_info); int (*ipa_eth_unregister_ready_cb)(struct ipa_eth_ready *ready_info); int (*ipa_eth_client_conn_pipes)(struct ipa_eth_client *client); int (*ipa_eth_client_disconn_pipes)(struct ipa_eth_client *client); int (*ipa_eth_client_reg_intf)(struct ipa_eth_intf_info *intf); int (*ipa_eth_client_unreg_intf)(struct ipa_eth_intf_info *intf); int (*ipa_eth_client_set_perf_profile)(struct ipa_eth_client *client, struct ipa_eth_perf_profile *profile); int (*ipa_eth_client_conn_evt)(struct ipa_ecm_msg *msg); int (*ipa_eth_client_disconn_evt)(struct ipa_ecm_msg *msg); }; static struct ipa_fmwk_contex *ipa_fmwk_ctx; Loading @@ -376,23 +398,34 @@ static inline void ipa_trigger_ipa_ready_cbs(void) } } static inline void ipa_register_uc_ready_cb(void) static inline void ipa_late_register_ready_cb(void) { int ret; if (ipa_fmwk_ctx->uc_ready_cb) { struct ipa_uc_ready_params param; if (ipa_fmwk_ctx->uc_ready_cb) { param.notify = ipa_fmwk_ctx->uc_ready_cb; param.priv = ipa_fmwk_ctx->uc_ready_priv; param.proto = ipa_fmwk_ctx->proto; ret = ipa_fmwk_ctx->ipa_uc_offload_reg_rdyCB(¶m); ipa_fmwk_ctx->ipa_uc_offload_reg_rdyCB(¶m); /* if uc is already ready, client expects cb to be called */ if (param.is_uC_ready) { ipa_fmwk_ctx->uc_ready_cb( ipa_fmwk_ctx->uc_ready_priv); } } if (ipa_fmwk_ctx->eth_ready_cb) { struct ipa_eth_ready ready_info; /* just late call to ipa_eth_register_ready_cb */ ready_info.notify = ipa_fmwk_ctx->eth_ready_cb; ready_info.userdata = ipa_fmwk_ctx->eth_userdata; ipa_fmwk_ctx->ipa_eth_register_ready_cb(&ready_info); /* nobody cares anymore about ready_info->is_eth_ready since * if we got here it means that we already returned false there */ } } /* registration API for IPA core module */ Loading Loading @@ -452,7 +485,7 @@ int ipa_fmwk_register_ipa(const struct ipa_core_data *in) ipa_fmwk_ctx->ipa_ready = true; ipa_trigger_ipa_ready_cbs(); ipa_register_uc_ready_cb(); ipa_late_register_ready_cb(); mutex_unlock(&ipa_fmwk_ctx->lock); pr_info("IPA driver is now in ready state\n"); Loading Loading @@ -1781,6 +1814,161 @@ int ipa_wigig_save_regs(void) } EXPORT_SYMBOL(ipa_wigig_save_regs); /* registration API for IPA eth module */ int ipa_fmwk_register_ipa_eth(const struct ipa_eth_data *in) { if (!ipa_fmwk_ctx) { pr_err("ipa framework hasn't been initialized yet\n"); return -EPERM; } if (ipa_fmwk_ctx->ipa_eth_register_ready_cb || ipa_fmwk_ctx->ipa_eth_unregister_ready_cb || ipa_fmwk_ctx->ipa_eth_client_conn_pipes || ipa_fmwk_ctx->ipa_eth_client_disconn_pipes || ipa_fmwk_ctx->ipa_eth_client_reg_intf || ipa_fmwk_ctx->ipa_eth_client_unreg_intf || ipa_fmwk_ctx->ipa_eth_client_set_perf_profile || ipa_fmwk_ctx->ipa_eth_client_conn_evt || ipa_fmwk_ctx->ipa_eth_client_disconn_evt) { pr_err("ipa_eth APIs were already initialized\n"); return -EPERM; } ipa_fmwk_ctx->ipa_eth_register_ready_cb = in->ipa_eth_register_ready_cb; ipa_fmwk_ctx->ipa_eth_unregister_ready_cb = in->ipa_eth_unregister_ready_cb; ipa_fmwk_ctx->ipa_eth_client_conn_pipes = in->ipa_eth_client_conn_pipes; ipa_fmwk_ctx->ipa_eth_client_disconn_pipes = in->ipa_eth_client_disconn_pipes; ipa_fmwk_ctx->ipa_eth_client_reg_intf = in->ipa_eth_client_reg_intf; ipa_fmwk_ctx->ipa_eth_client_unreg_intf = in->ipa_eth_client_unreg_intf; ipa_fmwk_ctx->ipa_eth_client_set_perf_profile = in->ipa_eth_client_set_perf_profile; ipa_fmwk_ctx->ipa_eth_client_conn_evt = in->ipa_eth_client_conn_evt; ipa_fmwk_ctx->ipa_eth_client_disconn_evt = in->ipa_eth_client_disconn_evt; pr_info("ipa_eth registered successfully\n"); return 0; } EXPORT_SYMBOL(ipa_fmwk_register_ipa_eth); int ipa_eth_register_ready_cb(struct ipa_eth_ready *ready_info) { int ret; if (!ipa_fmwk_ctx) { pr_err("ipa framework hasn't been initialized yet\n"); return -EPERM; } mutex_lock(&ipa_fmwk_ctx->lock); if (ipa_fmwk_ctx->ipa_ready) { /* call real func, unlock and return */ ret = ipa_fmwk_ctx->ipa_eth_register_ready_cb(ready_info); mutex_unlock(&ipa_fmwk_ctx->lock); return ret; } ipa_fmwk_ctx->eth_ready_cb = ready_info->notify; ipa_fmwk_ctx->eth_userdata = ready_info->userdata; ready_info->is_eth_ready = false; mutex_unlock(&ipa_fmwk_ctx->lock); return 0; } EXPORT_SYMBOL(ipa_eth_register_ready_cb); int ipa_eth_unregister_ready_cb(struct ipa_eth_ready *ready_info) { int ret; IPA_FMWK_DISPATCH_RETURN_DP(ipa_eth_unregister_ready_cb, ready_info); return ret; } EXPORT_SYMBOL(ipa_eth_unregister_ready_cb); int ipa_eth_client_conn_pipes(struct ipa_eth_client *client) { int ret; IPA_FMWK_DISPATCH_RETURN_DP(ipa_eth_client_conn_pipes, client); return ret; } EXPORT_SYMBOL(ipa_eth_client_conn_pipes); int ipa_eth_client_disconn_pipes(struct ipa_eth_client *client) { int ret; IPA_FMWK_DISPATCH_RETURN_DP(ipa_eth_client_disconn_pipes, client); return ret; } EXPORT_SYMBOL(ipa_eth_client_disconn_pipes); int ipa_eth_client_reg_intf(struct ipa_eth_intf_info *intf) { int ret; IPA_FMWK_DISPATCH_RETURN_DP(ipa_eth_client_reg_intf, intf); return ret; } EXPORT_SYMBOL(ipa_eth_client_reg_intf); int ipa_eth_client_unreg_intf(struct ipa_eth_intf_info *intf) { int ret; IPA_FMWK_DISPATCH_RETURN_DP(ipa_eth_client_unreg_intf, intf); return ret; } EXPORT_SYMBOL(ipa_eth_client_unreg_intf); int ipa_eth_client_set_perf_profile(struct ipa_eth_client *client, struct ipa_eth_perf_profile *profile) { int ret; IPA_FMWK_DISPATCH_RETURN_DP(ipa_eth_client_set_perf_profile, client, profile); return ret; } EXPORT_SYMBOL(ipa_eth_client_set_perf_profile); int ipa_eth_client_conn_evt(struct ipa_ecm_msg *msg) { int ret; IPA_FMWK_DISPATCH_RETURN_DP(ipa_eth_client_conn_evt, msg); return ret; } EXPORT_SYMBOL(ipa_eth_client_conn_evt); int ipa_eth_client_disconn_evt(struct ipa_ecm_msg *msg) { int ret; IPA_FMWK_DISPATCH_RETURN_DP(ipa_eth_client_disconn_evt, msg); return ret; } EXPORT_SYMBOL(ipa_eth_client_disconn_evt); /* module functions */ static int __init ipa_fmwk_init(void) { Loading
include/linux/ipa.h +18 −0 Original line number Diff line number Diff line Loading @@ -889,6 +889,24 @@ struct IpaHwRingStats_t { u32 RingUtilCount; } __packed; /** * struct ipa_uc_dbg_rtk_ring_stats - uC dbg stats info for RTK * offloading protocol * @commStats: common stats * @trCount: transfer ring count * @erCount: event ring count * @totalAosCount: total AoS completion count * @busyTime: total busy time */ struct ipa_uc_dbg_rtk_ring_stats { struct IpaHwRingStats_t commStats; u32 trCount; u32 erCount; u32 totalAosCount; u64 busyTime; } __packed; /** * struct IpaHwStatsWDIRxInfoData_t - Structure holding the WDI Rx channel * structures Loading
include/linux/ipa_eth.h 0 → 100644 +255 −0 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. */ #ifndef _IPA_ETH_H_ #define _IPA_ETH_H_ #include <linux/ipa.h> #include <linux/msm_ipa.h> #include <linux/msm_gsi.h> /* New architecture prototypes */ typedef void (*ipa_eth_ready_cb)(void *user_data); typedef u32 ipa_eth_hdl_t; /** * struct ipa_eth_ready_cb - eth readiness parameters * * @notify: ipa_eth client ready callback notifier * @userdata: userdata for ipa_eth ready cb * @is_eth_ready: true if ipa_eth client is already ready */ struct ipa_eth_ready { ipa_eth_ready_cb notify; void *userdata; /* out params */ bool is_eth_ready; }; /** * enum ipa_eth_client_type - names for the various IPA * eth "clients". */ enum ipa_eth_client_type { IPA_ETH_CLIENT_AQC107, IPA_ETH_CLIENT_AQC113, IPA_ETH_CLIENT_RTK8111K, IPA_ETH_CLIENT_RTK8125B, IPA_ETH_CLIENT_NTN, IPA_ETH_CLIENT_EMAC, IPA_ETH_CLIENT_MAX, }; /** * enum ipa_eth_pipe_traffic_type - traffic type for the various IPA * eth "pipes". */ enum ipa_eth_pipe_traffic_type { IPA_ETH_PIPE_BEST_EFFORT, IPA_ETH_PIPE_LOW_LATENCY, IPA_ETH_PIPE_TRAFFIC_TYPE_MAX, }; /** * enum ipa_eth_pipe_direction - pipe direcitons for same * ethernet client. */ enum ipa_eth_pipe_direction { IPA_ETH_PIPE_DIR_TX, IPA_ETH_PIPE_DIR_RX, IPA_ETH_PIPE_DIR_MAX, }; #define IPA_ETH_INST_ID_MAX (2) /** * struct ipa_eth_aqc_setup_info - parameters for aqc ethernet * offloading * * @bar_addr: bar PA to access AQC register * @head_ptr_offs: head ptr offset * @aqc_ch: AQC ch number * @dest_tail_ptr_offs: tail ptr offset */ struct ipa_eth_aqc_setup_info { phys_addr_t bar_addr; phys_addr_t head_ptr_offs; u8 aqc_ch; phys_addr_t dest_tail_ptr_offs; }; /** * struct ipa_eth_realtek_setup_info - parameters for realtek ethernet * offloading * * @bar_addr: bar PA to access RTK register * @bar_size: bar region size * @queue_number: Which RTK queue to check the status on * @dest_tail_ptr_offs: tail ptr offset */ struct ipa_eth_realtek_setup_info { phys_addr_t bar_addr; u32 bar_size; u8 queue_number; phys_addr_t dest_tail_ptr_offs; }; /** * struct ipa_eth_buff_smmu_map - IPA iova->pa SMMU mapping * @iova: virtual address of the data buffer * @pa: physical address of the data buffer */ struct ipa_eth_buff_smmu_map { dma_addr_t iova; phys_addr_t pa; }; /** * struct ipa_eth_pipe_setup_info - info needed for IPA setups * @is_transfer_ring_valid: if transfer ring is needed * @transfer_ring_base: the base of the transfer ring * @transfer_ring_sgt: sgtable of transfer ring * @transfer_ring_size: size of the transfer ring * @is_buffer_pool_valid: if buffer pool is needed * @buffer_pool_base_addr: base of buffer pool address * @buffer_pool_base_sgt: sgtable of buffer pool * @data_buff_list_size: number of buffers * @data_buff_list: array of data buffer list * @fix_buffer_size: buffer size * @notify: callback for exception/embedded packets * @priv: priv for exception callback * @client_info: vendor specific pipe setup info * @db_pa: doorbell physical address * @db_val: doorbell value ethernet HW need to ring */ struct ipa_eth_pipe_setup_info { /* transfer ring info */ bool is_transfer_ring_valid; dma_addr_t transfer_ring_base; struct sg_table *transfer_ring_sgt; u32 transfer_ring_size; /* buffer pool info */ bool is_buffer_pool_valid; dma_addr_t buffer_pool_base_addr; struct sg_table *buffer_pool_base_sgt; /* buffer info */ u32 data_buff_list_size; struct ipa_eth_buff_smmu_map *data_buff_list; u32 fix_buffer_size; /* client notify cb */ ipa_notify_cb notify; void *priv; /* vendor specific info */ union { struct ipa_eth_aqc_setup_info aqc; struct ipa_eth_realtek_setup_info rtk; } client_info; /* output params */ phys_addr_t db_pa; u32 db_val; }; /** * struct ipa_eth_client_pipe_info - ETH pipe/gsi related configuration * @link: link of ep for different client function on same ethernet HW * @dir: TX or RX direction * @info: tx/rx pipe setup info * @client_info: client the pipe belongs to * @pipe_hdl: output params, pipe handle */ struct ipa_eth_client_pipe_info { struct list_head link; enum ipa_eth_pipe_direction dir; struct ipa_eth_pipe_setup_info info; struct ipa_eth_client *client_info; /* output params */ ipa_eth_hdl_t pipe_hdl; }; /** * struct ipa_eth_client - client info per traffic type * provided by offload client * @client_type: ethernet client type * @inst_id: instance id for dual NIC support * @traffic_type: traffic type * @pipe_list: list of pipes with same traffic type * @priv: private data for client */ struct ipa_eth_client { /* vendor driver */ enum ipa_eth_client_type client_type; u8 inst_id; /* traffic type */ enum ipa_eth_pipe_traffic_type traffic_type; struct list_head pipe_list; /* client specific priv data*/ void *priv; }; /** * struct ipa_eth_perf_profile - To set BandWidth profile * * @max_supported_bw_mbps: maximum bandwidth needed (in Mbps) */ struct ipa_eth_perf_profile { u32 max_supported_bw_mbps; }; /** * struct ipa_eth_hdr_info - Header to install on IPA HW * * @hdr: header to install on IPA HW * @hdr_len: length of header * @dst_mac_addr_offset: destination mac address offset * @hdr_type: layer two header type */ struct ipa_eth_hdr_info { u8 *hdr; u8 hdr_len; u8 dst_mac_addr_offset; enum ipa_hdr_l2_type hdr_type; }; /** * struct ipa_eth_intf_info - parameters for ipa offload * interface registration * * @netdev_name: network interface name * @hdr: hdr for ipv4/ipv6 * @pipe_hdl_list_size: number of pipes prop needed for this interface * @pipe_hdl_list: array of pipes used for this interface */ struct ipa_eth_intf_info { const char *netdev_name; struct ipa_eth_hdr_info hdr[IPA_IP_MAX]; /* tx/rx pipes for same netdev */ int pipe_hdl_list_size; ipa_eth_hdl_t *pipe_hdl_list; }; int ipa_eth_register_ready_cb(struct ipa_eth_ready *ready_info); int ipa_eth_unregister_ready_cb(struct ipa_eth_ready *ready_info); int ipa_eth_client_conn_pipes(struct ipa_eth_client *client); int ipa_eth_client_disconn_pipes(struct ipa_eth_client *client); int ipa_eth_client_reg_intf(struct ipa_eth_intf_info *intf); int ipa_eth_client_unreg_intf(struct ipa_eth_intf_info *intf); int ipa_eth_client_set_perf_profile(struct ipa_eth_client *client, struct ipa_eth_perf_profile *profile); int ipa_eth_client_conn_evt(struct ipa_ecm_msg *msg); int ipa_eth_client_disconn_evt(struct ipa_ecm_msg *msg); #endif // _IPA_ETH_H_
include/linux/ipa_fmwk.h +29 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ #include <linux/ipa_usb.h> #include <linux/ipa_odu_bridge.h> #include <linux/ipa_qmi_service_v01.h> #include <linux/ipa_eth.h> struct ipa_core_data { int (*ipa_tx_dp)(enum ipa_client_type dst, struct sk_buff *skb, Loading Loading @@ -268,6 +269,27 @@ struct ipa_wigig_data { int (*ipa_wigig_save_regs)(void); }; struct ipa_eth_data { int (*ipa_eth_register_ready_cb)(struct ipa_eth_ready *ready_info); int (*ipa_eth_unregister_ready_cb)(struct ipa_eth_ready *ready_info); int (*ipa_eth_client_conn_pipes)(struct ipa_eth_client *client); int (*ipa_eth_client_disconn_pipes)(struct ipa_eth_client *client); int (*ipa_eth_client_reg_intf)(struct ipa_eth_intf_info *intf); int (*ipa_eth_client_unreg_intf)(struct ipa_eth_intf_info *intf); int (*ipa_eth_client_set_perf_profile)(struct ipa_eth_client *client, struct ipa_eth_perf_profile *profile); int (*ipa_eth_client_conn_evt)(struct ipa_ecm_msg *msg); int (*ipa_eth_client_disconn_evt)(struct ipa_ecm_msg *msg); }; #if IS_ENABLED(CONFIG_IPA3) int ipa_fmwk_register_ipa(const struct ipa_core_data *in); Loading @@ -284,6 +306,8 @@ int ipa_fmwk_register_ipa_mhi(const struct ipa_mhi_data *in); int ipa_fmwk_register_ipa_wigig(const struct ipa_wigig_data *in); int ipa_fmwk_register_ipa_eth(const struct ipa_eth_data *in); #else /* IS_ENABLED(CONFIG_IPA3) */ int ipa_fmwk_register_ipa(const struct ipa_core_data *in) Loading Loading @@ -321,6 +345,11 @@ int ipa_fmwk_register_ipa_wigig(const struct ipa_wigig_data *in) return -EPERM; } int ipa_fmwk_register_ipa_eth(const struct ipa_eth_data *in) { return -EPERM; } #endif /* IS_ENABLED(CONFIG_IPA3) */ #endif /* _IPA_FMWK_H_ */
include/uapi/linux/msm_ipa.h +4 −1 Original line number Diff line number Diff line Loading @@ -401,9 +401,12 @@ enum ipa_client_type { IPA_CLIENT_QDSS_PROD = 106, IPA_CLIENT_MHI_QDSS_CONS = 107, IPA_CLIENT_RTK_ETHERNET_PROD = 108, IPA_CLIENT_RTK_ETHERNET_CONS = 109, }; #define IPA_CLIENT_MAX (IPA_CLIENT_MHI_QDSS_CONS + 1) #define IPA_CLIENT_MAX (IPA_CLIENT_RTK_ETHERNET_CONS + 1) #define IPA_CLIENT_WLAN2_PROD IPA_CLIENT_A5_WLAN_AMPDU_PROD #define IPA_CLIENT_Q6_DL_NLO_DATA_PROD IPA_CLIENT_Q6_DL_NLO_DATA_PROD Loading