Loading drivers/platform/msm/ipa/ipa.c +1 −1 Original line number Diff line number Diff line Loading @@ -2082,7 +2082,7 @@ static int ipa_init(const struct ipa_plat_drv_res *resource_p, if (ipa_ctx->use_ipa_teth_bridge) { /* Initialize the tethering bridge driver */ result = teth_bridge_driver_init(); result = teth_bridge_driver_init(ipa_ctx->ipa_hw_type); if (result) { IPAERR(":teth_bridge init failed (%d)\n", -result); result = -ENODEV; Loading drivers/platform/msm/ipa/ipa_client.c +8 −3 Original line number Diff line number Diff line Loading @@ -211,10 +211,15 @@ int ipa_connect(const struct ipa_connect_params *in, struct ipa_sps_params *sps, ep->client_notify = in->notify; ep->priv = in->priv; if (ipa_ctx->ipa_hw_type != IPA_HW_v2_0 || ep->priv == NULL || (enum ipa_config_this_ep)ep->priv != IPA_DO_NOT_CONFIGURE_THIS_EP) { if (ipa_cfg_ep(ipa_ep_idx, &in->ipa_ep_cfg)) { IPAERR("fail to configure EP.\n"); goto ipa_cfg_ep_fail; } } else { IPADBG("Skipping endpoint configuration.\n"); } result = ipa_connect_configure_sps(in, ep, ipa_ep_idx); if (result) { Loading drivers/platform/msm/ipa/ipa_i.h +5 −1 Original line number Diff line number Diff line Loading @@ -558,6 +558,10 @@ enum ipa_hw_mode { IPA_HW_MODE_PCIE = 2 }; enum ipa_config_this_ep { IPA_CONFIGURE_THIS_EP, IPA_DO_NOT_CONFIGURE_THIS_EP, }; struct ipa_stats { u32 imm_cmds[MAX_NUM_IMM_CMD]; Loading Loading @@ -942,7 +946,7 @@ int a2_mux_exit(void); void wwan_cleanup(void); int teth_bridge_driver_init(void); int teth_bridge_driver_init(enum ipa_hw_type ipa_hw_type); void ipa_lan_rx_cb(void *priv, enum ipa_dp_evt_type evt, unsigned long data); int __ipa_commit_flt_v1(enum ipa_ip_type ip); Loading drivers/platform/msm/ipa/teth_bridge.c +298 −119 Original line number Diff line number Diff line Loading @@ -225,6 +225,7 @@ struct teth_bridge_ctx { struct mutex init_mutex; struct mutex request_resource_mutex; u16 debugfs_lcid; enum ipa_hw_type ipa_hw_type; }; static struct teth_bridge_ctx *teth_ctx; Loading Loading @@ -253,47 +254,131 @@ struct teth_work { static char dbg_buff[TETH_MAX_MSG_LEN]; #endif static int client_prod_to_lcid[IPA_CLIENT_CONS] = { A2_MUX_TETHERED_0, /* IPA_CLIENT_HSIC1_PROD */ A2_MUX_TETHERED_0, /* IPA_CLIENT_WLAN1_PROD */ A2_MUX_TETHERED_0, /* IPA_CLIENT_HSIC2_PROD */ A2_MUX_MULTI_RMNET_10, /* IPA_CLIENT_USB2_PROD */ A2_MUX_TETHERED_0, /* IPA_CLIENT_HSIC3_PROD */ A2_MUX_MULTI_RMNET_11, /* IPA_CLIENT_USB3_PROD */ A2_MUX_TETHERED_0, /* IPA_CLIENT_HSIC4_PROD */ A2_MUX_MULTI_RMNET_12, /* IPA_CLIENT_USB4_PROD */ A2_MUX_TETHERED_0, /* IPA_CLIENT_HSIC5_PROD */ A2_MUX_TETHERED_0, /* IPA_CLIENT_USB_PROD */ A2_MUX_TETHERED_0, /* IPA_CLIENT_A5_WLAN_AMPDU_PROD */ A2_MUX_TETHERED_0, /* IPA_CLIENT_A2_EMBEDDED_PROD */ A2_MUX_TETHERED_0, /* IPA_CLIENT_A2_TETHERED_PROD */ A2_MUX_TETHERED_0, /* IPA_CLIENT_APPS_LAN_WAN_PROD */ A2_MUX_TETHERED_0, /* IPA_CLIENT_APPS_CMD_PROD */ A2_MUX_TETHERED_0, /* IPA_CLIENT_Q6_LAN_PROD */ A2_MUX_TETHERED_0, /* IPA_CLIENT_Q6_CMD_PROD */ }; static u16 get_channel_id_from_client_prod(enum ipa_client_type client) { TETH_DBG("client_id=%d\n", client); if (client == IPA_CLIENT_USB_PROD) return A2_MUX_TETHERED_0; if (client > IPA_CLIENT_USB_PROD || client <= IPA_CLIENT_PROD) { if (client >= IPA_CLIENT_CONS || client < IPA_CLIENT_PROD) { TETH_ERR("%s: Invalid client type %d\n", __func__, client); return A2_MUX_TETHERED_0; } return client - IPA_CLIENT_USB2_PROD + A2_MUX_MULTI_RMNET_10; } return client_prod_to_lcid[client]; } static int lcid_to_cons_client[A2_MUX_NUM_CHANNELS] = { IPA_CLIENT_USB_CONS, /* A2_MUX_WWAN_0 */ IPA_CLIENT_USB_CONS, /* A2_MUX_WWAN_1 */ IPA_CLIENT_USB_CONS, /* A2_MUX_WWAN_2 */ IPA_CLIENT_USB_CONS, /* A2_MUX_WWAN_3 */ IPA_CLIENT_USB_CONS, /* A2_MUX_WWAN_4 */ IPA_CLIENT_USB_CONS, /* A2_MUX_WWAN_5 */ IPA_CLIENT_USB_CONS, /* A2_MUX_WWAN_6 */ IPA_CLIENT_USB_CONS, /* A2_MUX_WWAN_7 */ IPA_CLIENT_USB_CONS, /* A2_MUX_TETHERED_0 */ IPA_CLIENT_USB_CONS, /* A2_MUX_RESERVED_9 */ IPA_CLIENT_USB2_CONS, /* A2_MUX_MULTI_RMNET_10 */ IPA_CLIENT_USB3_CONS, /* A2_MUX_MULTI_RMNET_11 */ IPA_CLIENT_USB4_CONS, /* A2_MUX_MULTI_RMNET_12 */ IPA_CLIENT_USB_CONS, /* A2_MUX_MULTI_MBIM_13 */ IPA_CLIENT_USB_CONS, /* A2_MUX_MULTI_MBIM_14 */ IPA_CLIENT_USB_CONS, /* A2_MUX_MULTI_MBIM_15 */ IPA_CLIENT_USB_CONS, /* A2_MUX_MULTI_MBIM_16 */ IPA_CLIENT_USB_CONS, /* A2_MUX_MULTI_MBIM_17 */ IPA_CLIENT_USB_CONS, /* A2_MUX_MULTI_MBIM_18 */ IPA_CLIENT_USB_CONS, /* A2_MUX_MULTI_MBIM_19 */ IPA_CLIENT_USB_CONS, /* A2_MUX_MULTI_MBIM_20 */ }; static u16 get_cons_client(enum a2_mux_logical_channel_id lcid) { TETH_DBG("lcid=%d\n", lcid); if (lcid < A2_MUX_TETHERED_0 || lcid >= A2_MUX_NUM_CHANNELS || lcid == A2_MUX_RESERVED_9) { if (lcid < 0 || lcid > A2_MUX_NUM_CHANNELS) { TETH_ERR("%s: Invalid lcid %d\n", __func__, lcid); return IPA_CLIENT_USB_CONS; } if (lcid == A2_MUX_TETHERED_0) return IPA_CLIENT_USB_CONS; return lcid - A2_MUX_MULTI_RMNET_10 + IPA_CLIENT_USB2_CONS; } return lcid_to_cons_client[lcid]; } static int lcid_to_prod_client[A2_MUX_NUM_CHANNELS] = { IPA_CLIENT_USB_PROD, /* A2_MUX_WWAN_0 */ IPA_CLIENT_USB_PROD, /* A2_MUX_WWAN_1 */ IPA_CLIENT_USB_PROD, /* A2_MUX_WWAN_2 */ IPA_CLIENT_USB_PROD, /* A2_MUX_WWAN_3 */ IPA_CLIENT_USB_PROD, /* A2_MUX_WWAN_4 */ IPA_CLIENT_USB_PROD, /* A2_MUX_WWAN_5 */ IPA_CLIENT_USB_PROD, /* A2_MUX_WWAN_6 */ IPA_CLIENT_USB_PROD, /* A2_MUX_WWAN_7 */ IPA_CLIENT_USB_PROD, /* A2_MUX_TETHERED_0 */ IPA_CLIENT_USB_PROD, /* A2_MUX_RESERVED_9 */ IPA_CLIENT_USB2_PROD, /* A2_MUX_MULTI_RMNET_10 */ IPA_CLIENT_USB3_PROD, /* A2_MUX_MULTI_RMNET_11 */ IPA_CLIENT_USB4_PROD, /* A2_MUX_MULTI_RMNET_12 */ IPA_CLIENT_USB_PROD, /* A2_MUX_MULTI_MBIM_13 */ IPA_CLIENT_USB_PROD, /* A2_MUX_MULTI_MBIM_14 */ IPA_CLIENT_USB_PROD, /* A2_MUX_MULTI_MBIM_15 */ IPA_CLIENT_USB_PROD, /* A2_MUX_MULTI_MBIM_16 */ IPA_CLIENT_USB_PROD, /* A2_MUX_MULTI_MBIM_17 */ IPA_CLIENT_USB_PROD, /* A2_MUX_MULTI_MBIM_18 */ IPA_CLIENT_USB_PROD, /* A2_MUX_MULTI_MBIM_19 */ IPA_CLIENT_USB_PROD, /* A2_MUX_MULTI_MBIM_20 */ }; static u16 get_prod_client(enum a2_mux_logical_channel_id lcid) { TETH_DBG("lcid=%d\n", lcid); if (lcid < A2_MUX_TETHERED_0 || lcid >= A2_MUX_NUM_CHANNELS || lcid == A2_MUX_RESERVED_9) { if (lcid < 0 || lcid > A2_MUX_NUM_CHANNELS) { TETH_ERR("%s: Invalid lcid %d\n", __func__, lcid); return IPA_CLIENT_USB_PROD; } if (lcid == A2_MUX_TETHERED_0) return IPA_CLIENT_USB_PROD; return lcid - A2_MUX_MULTI_RMNET_10 + IPA_CLIENT_USB2_PROD; } return lcid_to_prod_client[lcid]; } static int lcid_to_ch_info_idx[A2_MUX_NUM_CHANNELS] = { 0, /* A2_MUX_WWAN_0 */ 0, /* A2_MUX_WWAN_1 */ 0, /* A2_MUX_WWAN_2 */ 0, /* A2_MUX_WWAN_3 */ 0, /* A2_MUX_WWAN_4 */ 0, /* A2_MUX_WWAN_5 */ 0, /* A2_MUX_WWAN_6 */ 0, /* A2_MUX_WWAN_7 */ 0, /* A2_MUX_TETHERED_0 */ 0, /* A2_MUX_RESERVED_9 */ 1, /* A2_MUX_MULTI_RMNET_10 */ 2, /* A2_MUX_MULTI_RMNET_11 */ 3, /* A2_MUX_MULTI_RMNET_12 */ 4, /* A2_MUX_MULTI_MBIM_13 */ 5, /* A2_MUX_MULTI_MBIM_14 */ 6, /* A2_MUX_MULTI_MBIM_15 */ 7, /* A2_MUX_MULTI_MBIM_16 */ 8, /* A2_MUX_MULTI_MBIM_17 */ 9, /* A2_MUX_MULTI_MBIM_18 */ 10, /* A2_MUX_MULTI_MBIM_19 */ 11, /* A2_MUX_MULTI_MBIM_20 */ }; static u16 get_ch_info_idx(enum a2_mux_logical_channel_id lcid) { Loading @@ -302,10 +387,8 @@ static u16 get_ch_info_idx(enum a2_mux_logical_channel_id lcid) TETH_ERR("%s: Invalid lcid %d\n", __func__, lcid); return 0; } if (lcid == A2_MUX_TETHERED_0) return 0; return lcid - A2_MUX_RESERVED_9; return lcid_to_ch_info_idx[lcid]; } static int get_completed_ch_num(void) Loading Loading @@ -1404,6 +1487,7 @@ static int teth_request_resource(void) res = 0; } mutex_unlock(&teth_ctx->request_resource_mutex); return res; } Loading Loading @@ -1961,10 +2045,26 @@ int teth_bridge_init(ipa_notify_cb *usb_notify_cb_ptr, void **private_data_ptr, return -EINVAL; } switch (teth_ctx->ipa_hw_type) { case IPA_HW_v1_1: *usb_notify_cb_ptr = usb_notify_cb; lcid = get_channel_id_from_client_prod(client); *private_data_ptr = (void *)lcid; idx = get_ch_info_idx(lcid); TETH_DBG("init private data with lcid=%d\n", lcid); break; case IPA_HW_v2_0: *usb_notify_cb_ptr = NULL; *private_data_ptr = (void *)IPA_DO_NOT_CONFIGURE_THIS_EP; break; default: TETH_ERR("Invalid HW type.\n"); res = -EINVAL; goto bail; break; } mutex_lock(&teth_ctx->init_mutex); if (teth_ctx->init_status == TETH_INITIALIZATION_ERROR) { Loading @@ -1972,7 +2072,6 @@ int teth_bridge_init(ipa_notify_cb *usb_notify_cb_ptr, void **private_data_ptr, goto bail; } TETH_DBG("init private data with lcid=%d\n", lcid); if (teth_ctx->init_status == TETH_INITIALIZED) { teth_ctx->ch_init_cnt++; Loading @@ -1989,6 +2088,7 @@ int teth_bridge_init(ipa_notify_cb *usb_notify_cb_ptr, void **private_data_ptr, goto fail; } if (teth_ctx->ipa_hw_type == IPA_HW_v1_1) { res = ipa_rm_add_dependency(IPA_RM_RESOURCE_BRIDGE_PROD, IPA_RM_RESOURCE_A2_CONS); if (res && res != -EINPROGRESS) { Loading @@ -2009,6 +2109,7 @@ int teth_bridge_init(ipa_notify_cb *usb_notify_cb_ptr, void **private_data_ptr, TETH_ERR("ipa_rm_add_dependency() failed\n"); goto fail_add_dependency_3; } } /* Return 0 as EINPROGRESS is a valid return value at this point */ teth_ctx->init_status = TETH_INITIALIZED; Loading Loading @@ -2144,6 +2245,7 @@ static void initialize_context(void) static int delete_usb_dependencies(void) { int res; /* * Delete part of IPA resource manager dependency graph. Only the * BRIDGE_PROD <-> A2 dependency remains intact Loading @@ -2153,6 +2255,8 @@ static int delete_usb_dependencies(void) if ((res != 0) && (res != -EINPROGRESS)) TETH_ERR( "Failed deleting ipa_rm dependency BRIDGE_PROD <-> USB_CONS\n"); if (teth_ctx->ipa_hw_type == IPA_HW_v1_1) { res = ipa_rm_delete_dependency(IPA_RM_RESOURCE_USB_PROD, IPA_RM_RESOURCE_A2_CONS); if ((res != 0) && (res != -EINPROGRESS)) Loading @@ -2163,6 +2267,8 @@ static int delete_usb_dependencies(void) if ((res != 0) && (res != -EINPROGRESS)) TETH_ERR( "Failed deleting ipa_rm dependency A2_PROD <-> USB_CONS\n"); } return res; } Loading Loading @@ -2205,7 +2311,8 @@ static int disconnect_ch(u16 lcid) u16 idx = get_ch_info_idx(lcid); TETH_DBG_FUNC_ENTRY(); /* Request the BRIDGE_PROD resource, A2 and IPA should power up */ if (teth_ctx->ipa_hw_type == IPA_HW_v1_1) { /* Request the BRIDGE_PROD resource */ res = teth_request_resource(); if (res) { TETH_ERR("request_resource() failed.\n"); Loading @@ -2219,7 +2326,8 @@ static int disconnect_ch(u16 lcid) if (teth_ctx->ch_info[idx].is_hw_bridge_complete) teardown_hw_bridge(idx); ipa_rm_inactivity_timer_release_resource(IPA_RM_RESOURCE_BRIDGE_PROD); ipa_rm_inactivity_timer_release_resource( IPA_RM_RESOURCE_BRIDGE_PROD); /* Deregister from A2_PROD notifications */ if (teth_ctx->ch_info[idx].ch_type == TETH_TETHERED_CH) { Loading @@ -2231,16 +2339,20 @@ static int disconnect_ch(u16 lcid) TETH_ERR( "Failed deregistering from A2_prod notifications.\n"); } } if (get_connected_ch_num() <= 1) { initialize_context(); /* Delete the last ipa_rm dependency - BRIDGE_PROD <-> A2 */ res = ipa_rm_delete_dependency(IPA_RM_RESOURCE_BRIDGE_PROD, if (teth_ctx->ipa_hw_type == IPA_HW_v1_1) { /* Delete ipa_rm dependency - BRIDGE_PROD <-> A2 */ res = ipa_rm_delete_dependency( IPA_RM_RESOURCE_BRIDGE_PROD, IPA_RM_RESOURCE_A2_CONS); if ((res != 0) && (res != -EINPROGRESS)) TETH_ERR( "Failed deleting ipa_rm dependency BRIDGE_PROD <-> A2_CONS\n"); } } initialize_ch_info(idx); bail: Loading @@ -2264,6 +2376,7 @@ static int disconnect_first_ch(u16 lcid) teth_ctx->init_status = TETH_NOT_INITIALIZED; TETH_DBG_FUNC_EXIT(); return 0; } Loading @@ -2274,7 +2387,8 @@ int teth_bridge_disconnect(enum ipa_client_type client) { u16 lcid; u16 idx; u16 num_of_iteration = 1, i; u16 num_of_iteration = 1; u16 i; TETH_DBG_FUNC_ENTRY(); if (teth_ctx->tethering_mode == TETH_TETHERING_MODE_MBIM) { Loading Loading @@ -2308,19 +2422,18 @@ bail: EXPORT_SYMBOL(teth_bridge_disconnect); /** * teth_bridge_connect() - Connect bridge for a tethered Rmnet / MBIM call * @connect_params: Connection info * * Return codes: 0: success * -EINVAL: invalid parameters * -EPERM: Operation not permitted as the bridge is already * connected */ int teth_bridge_connect(struct teth_bridge_connect_params *connect_params) static int __teth_bridge_connect_2_0(struct teth_bridge_connect_params *connect_params) { int res, num_of_iterations = 1, i; return 0; } static int __teth_bridge_connect_1_1(struct teth_bridge_connect_params *connect_params) { int res; int num_of_iterations = 1; int i; struct ipa_ep_cfg ipa_ep_cfg; u16 lcid; u16 idx; Loading @@ -2329,7 +2442,6 @@ int teth_bridge_connect(struct teth_bridge_connect_params *connect_params) struct ipa_rm_register_params a2_prod_reg_params; TETH_DBG_FUNC_ENTRY(); if (connect_params == NULL || connect_params->ipa_usb_pipe_hdl <= 0 || connect_params->usb_ipa_pipe_hdl <= 0 || Loading Loading @@ -2471,6 +2583,33 @@ bail: return res; } /** * teth_bridge_connect() - Connect bridge for a tethered Rmnet / MBIM call * @connect_params: Connection info * * Return codes: 0: success * -EINVAL: invalid parameters * -EPERM: Operation not permitted as the bridge is already * connected */ int teth_bridge_connect(struct teth_bridge_connect_params *connect_params) { int res; TETH_DBG_FUNC_ENTRY(); if (teth_ctx->ipa_hw_type == IPA_HW_v1_1) res = __teth_bridge_connect_1_1(connect_params); else if (teth_ctx->ipa_hw_type == IPA_HW_v2_0) res = __teth_bridge_connect_2_0(connect_params); else { TETH_ERR("Non supported HW type,\n"); res = -EINVAL; } return res; } EXPORT_SYMBOL(teth_bridge_connect); static void set_aggr_default_params(struct teth_aggr_params_link *params) Loading Loading @@ -2515,6 +2654,9 @@ static int teth_bridge_set_aggr_params(struct teth_aggr_params *aggr_params, u16 lcid, i; int num_of_iteration = 1; if (teth_ctx->ipa_hw_type != IPA_HW_v1_1) return -EFAULT; TETH_DBG_FUNC_ENTRY(); if (!aggr_params) { TETH_ERR("Invalid parameter\n"); Loading Loading @@ -2595,6 +2737,9 @@ static int teth_bridge_set_aggr_params(struct teth_aggr_params *aggr_params, int teth_bridge_set_mbim_aggr_params(struct teth_aggr_params *aggr_params, enum ipa_client_type client) { if (ipa_ctx->ipa_hw_type != IPA_HW_v1_1) TETH_ERR("This API should not be called on Krypton !\n"); teth_ctx->tethering_mode = TETH_TETHERING_MODE_MBIM; return teth_bridge_set_aggr_params(aggr_params, client); } Loading @@ -2611,6 +2756,11 @@ static long teth_bridge_ioctl(struct file *filp, struct hw_bridge_work_wrap *work_data; u16 i = 0; if (teth_ctx->ipa_hw_type != IPA_HW_v1_1) { IPAERR("No ioctls are supported for krypton !\n"); return -ENOIOCTLCMD; } TETH_DBG("cmd=%x nr=%d\n", cmd, _IOC_NR(cmd)); if ((_IOC_TYPE(cmd) != TETH_BRIDGE_IOC_MAGIC) || Loading Loading @@ -3096,22 +3246,17 @@ const struct file_operations teth_hw_bridge_status_ops = { .read = teth_debugfs_hw_bridge_status, }; void teth_debugfs_init(void) static int __debugfs_create_v1_1(struct dentry *dent) { const mode_t read_only_mode = S_IRUSR | S_IRGRP | S_IROTH; const mode_t read_write_mode = S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR | S_IWGRP | S_IWOTH; dent = debugfs_create_dir("ipa_teth", 0); if (IS_ERR(dent)) { IPAERR("fail to create folder ipa_teth debug_fs.\n"); return; } dfile_lcid = debugfs_create_file("lcid", read_write_mode, dent, 0, &teth_lcid_ops); if (!dfile_lcid || IS_ERR(dfile_lcid)) { IPAERR("fail to create file lcid\n"); goto fail; return -EFAULT; } dfile_link_protocol = Loading @@ -3119,7 +3264,7 @@ void teth_debugfs_init(void) &teth_link_protocol_ops); if (!dfile_link_protocol || IS_ERR(dfile_link_protocol)) { IPAERR("fail to create file link_protocol\n"); goto fail; return -EFAULT; } dfile_get_aggr_params = Loading @@ -3127,7 +3272,7 @@ void teth_debugfs_init(void) &teth_get_aggr_params_ops); if (!dfile_get_aggr_params || IS_ERR(dfile_get_aggr_params)) { IPAERR("fail to create file get_aggr_params\n"); goto fail; return -EFAULT; } dfile_set_aggr_protocol = Loading @@ -3135,7 +3280,7 @@ void teth_debugfs_init(void) 0, &teth_set_aggr_protocol_ops); if (!dfile_set_aggr_protocol || IS_ERR(dfile_set_aggr_protocol)) { IPAERR("fail to create file set_aggr_protocol\n"); goto fail; return -EFAULT; } dfile_stats = Loading @@ -3143,7 +3288,7 @@ void teth_debugfs_init(void) 0, &teth_stats_ops); if (!dfile_stats || IS_ERR(dfile_stats)) { IPAERR("fail to create file stats\n"); goto fail; return -EFAULT; } dfile_is_hw_bridge_complete = Loading @@ -3152,12 +3297,40 @@ void teth_debugfs_init(void) if (!dfile_is_hw_bridge_complete || IS_ERR(dfile_is_hw_bridge_complete)) { IPAERR("fail to create file is_hw_bridge_complete\n"); goto fail; return -EFAULT; } return 0; } static int __debugfs_create_v2_0(struct dentry *dent) { return 0; } void teth_debugfs_init(void) { int res; dent = debugfs_create_dir("ipa_teth", 0); if (IS_ERR(dent)) { IPAERR("fail to create folder ipa_teth debug_fs.\n"); return; fail: } if (teth_ctx->ipa_hw_type == IPA_HW_v1_1) res = __debugfs_create_v1_1(dent); else if (teth_ctx->ipa_hw_type == IPA_HW_v2_0) res = __debugfs_create_v2_0(dent); else { TETH_ERR("Invalid HW type, debugfs disabled !\n"); res = -EFAULT; } if (res) debugfs_remove_recursive(dent); return; } #else void teth_debugfs_init(void) {} Loading Loading @@ -3256,7 +3429,7 @@ fail_alloc_routing_del_ipv4: * teth_bridge_driver_init() - Initialize tethering bridge driver * */ int teth_bridge_driver_init(void) int teth_bridge_driver_init(enum ipa_hw_type ipa_hw_type) { int res; struct ipa_rm_create_params bridge_prod_params; Loading @@ -3269,6 +3442,8 @@ int teth_bridge_driver_init(void) return -ENOMEM; } teth_ctx->ipa_hw_type = ipa_hw_type; teth_ctx->ch_info = kzalloc(sizeof(struct logic_ch_info)*TETH_NUM_CHANNELS, GFP_KERNEL); Loading @@ -3277,11 +3452,13 @@ int teth_bridge_driver_init(void) goto fail_alloc_channel_info; } if (teth_ctx->ipa_hw_type == IPA_HW_v1_1) { res = set_aggr_capabilities(); if (res) { TETH_ERR("kzalloc err.\n"); goto fail_alloc_aggr_caps; } } teth_ctx->class = class_create(THIS_MODULE, TETH_BRIDGE_DRV_NAME); Loading Loading @@ -3334,11 +3511,13 @@ int teth_bridge_driver_init(void) goto fail_cdev_add; } if (teth_ctx->ipa_hw_type == IPA_HW_v1_1) { teth_ctx->teth_wq = create_workqueue(TETH_WORKQUEUE_NAME); if (!teth_ctx->teth_wq) { TETH_ERR("workqueue creation failed\n"); goto fail_cdev_add; } } res = alloc_del_hnds(); if (res) { Loading Loading
drivers/platform/msm/ipa/ipa.c +1 −1 Original line number Diff line number Diff line Loading @@ -2082,7 +2082,7 @@ static int ipa_init(const struct ipa_plat_drv_res *resource_p, if (ipa_ctx->use_ipa_teth_bridge) { /* Initialize the tethering bridge driver */ result = teth_bridge_driver_init(); result = teth_bridge_driver_init(ipa_ctx->ipa_hw_type); if (result) { IPAERR(":teth_bridge init failed (%d)\n", -result); result = -ENODEV; Loading
drivers/platform/msm/ipa/ipa_client.c +8 −3 Original line number Diff line number Diff line Loading @@ -211,10 +211,15 @@ int ipa_connect(const struct ipa_connect_params *in, struct ipa_sps_params *sps, ep->client_notify = in->notify; ep->priv = in->priv; if (ipa_ctx->ipa_hw_type != IPA_HW_v2_0 || ep->priv == NULL || (enum ipa_config_this_ep)ep->priv != IPA_DO_NOT_CONFIGURE_THIS_EP) { if (ipa_cfg_ep(ipa_ep_idx, &in->ipa_ep_cfg)) { IPAERR("fail to configure EP.\n"); goto ipa_cfg_ep_fail; } } else { IPADBG("Skipping endpoint configuration.\n"); } result = ipa_connect_configure_sps(in, ep, ipa_ep_idx); if (result) { Loading
drivers/platform/msm/ipa/ipa_i.h +5 −1 Original line number Diff line number Diff line Loading @@ -558,6 +558,10 @@ enum ipa_hw_mode { IPA_HW_MODE_PCIE = 2 }; enum ipa_config_this_ep { IPA_CONFIGURE_THIS_EP, IPA_DO_NOT_CONFIGURE_THIS_EP, }; struct ipa_stats { u32 imm_cmds[MAX_NUM_IMM_CMD]; Loading Loading @@ -942,7 +946,7 @@ int a2_mux_exit(void); void wwan_cleanup(void); int teth_bridge_driver_init(void); int teth_bridge_driver_init(enum ipa_hw_type ipa_hw_type); void ipa_lan_rx_cb(void *priv, enum ipa_dp_evt_type evt, unsigned long data); int __ipa_commit_flt_v1(enum ipa_ip_type ip); Loading
drivers/platform/msm/ipa/teth_bridge.c +298 −119 Original line number Diff line number Diff line Loading @@ -225,6 +225,7 @@ struct teth_bridge_ctx { struct mutex init_mutex; struct mutex request_resource_mutex; u16 debugfs_lcid; enum ipa_hw_type ipa_hw_type; }; static struct teth_bridge_ctx *teth_ctx; Loading Loading @@ -253,47 +254,131 @@ struct teth_work { static char dbg_buff[TETH_MAX_MSG_LEN]; #endif static int client_prod_to_lcid[IPA_CLIENT_CONS] = { A2_MUX_TETHERED_0, /* IPA_CLIENT_HSIC1_PROD */ A2_MUX_TETHERED_0, /* IPA_CLIENT_WLAN1_PROD */ A2_MUX_TETHERED_0, /* IPA_CLIENT_HSIC2_PROD */ A2_MUX_MULTI_RMNET_10, /* IPA_CLIENT_USB2_PROD */ A2_MUX_TETHERED_0, /* IPA_CLIENT_HSIC3_PROD */ A2_MUX_MULTI_RMNET_11, /* IPA_CLIENT_USB3_PROD */ A2_MUX_TETHERED_0, /* IPA_CLIENT_HSIC4_PROD */ A2_MUX_MULTI_RMNET_12, /* IPA_CLIENT_USB4_PROD */ A2_MUX_TETHERED_0, /* IPA_CLIENT_HSIC5_PROD */ A2_MUX_TETHERED_0, /* IPA_CLIENT_USB_PROD */ A2_MUX_TETHERED_0, /* IPA_CLIENT_A5_WLAN_AMPDU_PROD */ A2_MUX_TETHERED_0, /* IPA_CLIENT_A2_EMBEDDED_PROD */ A2_MUX_TETHERED_0, /* IPA_CLIENT_A2_TETHERED_PROD */ A2_MUX_TETHERED_0, /* IPA_CLIENT_APPS_LAN_WAN_PROD */ A2_MUX_TETHERED_0, /* IPA_CLIENT_APPS_CMD_PROD */ A2_MUX_TETHERED_0, /* IPA_CLIENT_Q6_LAN_PROD */ A2_MUX_TETHERED_0, /* IPA_CLIENT_Q6_CMD_PROD */ }; static u16 get_channel_id_from_client_prod(enum ipa_client_type client) { TETH_DBG("client_id=%d\n", client); if (client == IPA_CLIENT_USB_PROD) return A2_MUX_TETHERED_0; if (client > IPA_CLIENT_USB_PROD || client <= IPA_CLIENT_PROD) { if (client >= IPA_CLIENT_CONS || client < IPA_CLIENT_PROD) { TETH_ERR("%s: Invalid client type %d\n", __func__, client); return A2_MUX_TETHERED_0; } return client - IPA_CLIENT_USB2_PROD + A2_MUX_MULTI_RMNET_10; } return client_prod_to_lcid[client]; } static int lcid_to_cons_client[A2_MUX_NUM_CHANNELS] = { IPA_CLIENT_USB_CONS, /* A2_MUX_WWAN_0 */ IPA_CLIENT_USB_CONS, /* A2_MUX_WWAN_1 */ IPA_CLIENT_USB_CONS, /* A2_MUX_WWAN_2 */ IPA_CLIENT_USB_CONS, /* A2_MUX_WWAN_3 */ IPA_CLIENT_USB_CONS, /* A2_MUX_WWAN_4 */ IPA_CLIENT_USB_CONS, /* A2_MUX_WWAN_5 */ IPA_CLIENT_USB_CONS, /* A2_MUX_WWAN_6 */ IPA_CLIENT_USB_CONS, /* A2_MUX_WWAN_7 */ IPA_CLIENT_USB_CONS, /* A2_MUX_TETHERED_0 */ IPA_CLIENT_USB_CONS, /* A2_MUX_RESERVED_9 */ IPA_CLIENT_USB2_CONS, /* A2_MUX_MULTI_RMNET_10 */ IPA_CLIENT_USB3_CONS, /* A2_MUX_MULTI_RMNET_11 */ IPA_CLIENT_USB4_CONS, /* A2_MUX_MULTI_RMNET_12 */ IPA_CLIENT_USB_CONS, /* A2_MUX_MULTI_MBIM_13 */ IPA_CLIENT_USB_CONS, /* A2_MUX_MULTI_MBIM_14 */ IPA_CLIENT_USB_CONS, /* A2_MUX_MULTI_MBIM_15 */ IPA_CLIENT_USB_CONS, /* A2_MUX_MULTI_MBIM_16 */ IPA_CLIENT_USB_CONS, /* A2_MUX_MULTI_MBIM_17 */ IPA_CLIENT_USB_CONS, /* A2_MUX_MULTI_MBIM_18 */ IPA_CLIENT_USB_CONS, /* A2_MUX_MULTI_MBIM_19 */ IPA_CLIENT_USB_CONS, /* A2_MUX_MULTI_MBIM_20 */ }; static u16 get_cons_client(enum a2_mux_logical_channel_id lcid) { TETH_DBG("lcid=%d\n", lcid); if (lcid < A2_MUX_TETHERED_0 || lcid >= A2_MUX_NUM_CHANNELS || lcid == A2_MUX_RESERVED_9) { if (lcid < 0 || lcid > A2_MUX_NUM_CHANNELS) { TETH_ERR("%s: Invalid lcid %d\n", __func__, lcid); return IPA_CLIENT_USB_CONS; } if (lcid == A2_MUX_TETHERED_0) return IPA_CLIENT_USB_CONS; return lcid - A2_MUX_MULTI_RMNET_10 + IPA_CLIENT_USB2_CONS; } return lcid_to_cons_client[lcid]; } static int lcid_to_prod_client[A2_MUX_NUM_CHANNELS] = { IPA_CLIENT_USB_PROD, /* A2_MUX_WWAN_0 */ IPA_CLIENT_USB_PROD, /* A2_MUX_WWAN_1 */ IPA_CLIENT_USB_PROD, /* A2_MUX_WWAN_2 */ IPA_CLIENT_USB_PROD, /* A2_MUX_WWAN_3 */ IPA_CLIENT_USB_PROD, /* A2_MUX_WWAN_4 */ IPA_CLIENT_USB_PROD, /* A2_MUX_WWAN_5 */ IPA_CLIENT_USB_PROD, /* A2_MUX_WWAN_6 */ IPA_CLIENT_USB_PROD, /* A2_MUX_WWAN_7 */ IPA_CLIENT_USB_PROD, /* A2_MUX_TETHERED_0 */ IPA_CLIENT_USB_PROD, /* A2_MUX_RESERVED_9 */ IPA_CLIENT_USB2_PROD, /* A2_MUX_MULTI_RMNET_10 */ IPA_CLIENT_USB3_PROD, /* A2_MUX_MULTI_RMNET_11 */ IPA_CLIENT_USB4_PROD, /* A2_MUX_MULTI_RMNET_12 */ IPA_CLIENT_USB_PROD, /* A2_MUX_MULTI_MBIM_13 */ IPA_CLIENT_USB_PROD, /* A2_MUX_MULTI_MBIM_14 */ IPA_CLIENT_USB_PROD, /* A2_MUX_MULTI_MBIM_15 */ IPA_CLIENT_USB_PROD, /* A2_MUX_MULTI_MBIM_16 */ IPA_CLIENT_USB_PROD, /* A2_MUX_MULTI_MBIM_17 */ IPA_CLIENT_USB_PROD, /* A2_MUX_MULTI_MBIM_18 */ IPA_CLIENT_USB_PROD, /* A2_MUX_MULTI_MBIM_19 */ IPA_CLIENT_USB_PROD, /* A2_MUX_MULTI_MBIM_20 */ }; static u16 get_prod_client(enum a2_mux_logical_channel_id lcid) { TETH_DBG("lcid=%d\n", lcid); if (lcid < A2_MUX_TETHERED_0 || lcid >= A2_MUX_NUM_CHANNELS || lcid == A2_MUX_RESERVED_9) { if (lcid < 0 || lcid > A2_MUX_NUM_CHANNELS) { TETH_ERR("%s: Invalid lcid %d\n", __func__, lcid); return IPA_CLIENT_USB_PROD; } if (lcid == A2_MUX_TETHERED_0) return IPA_CLIENT_USB_PROD; return lcid - A2_MUX_MULTI_RMNET_10 + IPA_CLIENT_USB2_PROD; } return lcid_to_prod_client[lcid]; } static int lcid_to_ch_info_idx[A2_MUX_NUM_CHANNELS] = { 0, /* A2_MUX_WWAN_0 */ 0, /* A2_MUX_WWAN_1 */ 0, /* A2_MUX_WWAN_2 */ 0, /* A2_MUX_WWAN_3 */ 0, /* A2_MUX_WWAN_4 */ 0, /* A2_MUX_WWAN_5 */ 0, /* A2_MUX_WWAN_6 */ 0, /* A2_MUX_WWAN_7 */ 0, /* A2_MUX_TETHERED_0 */ 0, /* A2_MUX_RESERVED_9 */ 1, /* A2_MUX_MULTI_RMNET_10 */ 2, /* A2_MUX_MULTI_RMNET_11 */ 3, /* A2_MUX_MULTI_RMNET_12 */ 4, /* A2_MUX_MULTI_MBIM_13 */ 5, /* A2_MUX_MULTI_MBIM_14 */ 6, /* A2_MUX_MULTI_MBIM_15 */ 7, /* A2_MUX_MULTI_MBIM_16 */ 8, /* A2_MUX_MULTI_MBIM_17 */ 9, /* A2_MUX_MULTI_MBIM_18 */ 10, /* A2_MUX_MULTI_MBIM_19 */ 11, /* A2_MUX_MULTI_MBIM_20 */ }; static u16 get_ch_info_idx(enum a2_mux_logical_channel_id lcid) { Loading @@ -302,10 +387,8 @@ static u16 get_ch_info_idx(enum a2_mux_logical_channel_id lcid) TETH_ERR("%s: Invalid lcid %d\n", __func__, lcid); return 0; } if (lcid == A2_MUX_TETHERED_0) return 0; return lcid - A2_MUX_RESERVED_9; return lcid_to_ch_info_idx[lcid]; } static int get_completed_ch_num(void) Loading Loading @@ -1404,6 +1487,7 @@ static int teth_request_resource(void) res = 0; } mutex_unlock(&teth_ctx->request_resource_mutex); return res; } Loading Loading @@ -1961,10 +2045,26 @@ int teth_bridge_init(ipa_notify_cb *usb_notify_cb_ptr, void **private_data_ptr, return -EINVAL; } switch (teth_ctx->ipa_hw_type) { case IPA_HW_v1_1: *usb_notify_cb_ptr = usb_notify_cb; lcid = get_channel_id_from_client_prod(client); *private_data_ptr = (void *)lcid; idx = get_ch_info_idx(lcid); TETH_DBG("init private data with lcid=%d\n", lcid); break; case IPA_HW_v2_0: *usb_notify_cb_ptr = NULL; *private_data_ptr = (void *)IPA_DO_NOT_CONFIGURE_THIS_EP; break; default: TETH_ERR("Invalid HW type.\n"); res = -EINVAL; goto bail; break; } mutex_lock(&teth_ctx->init_mutex); if (teth_ctx->init_status == TETH_INITIALIZATION_ERROR) { Loading @@ -1972,7 +2072,6 @@ int teth_bridge_init(ipa_notify_cb *usb_notify_cb_ptr, void **private_data_ptr, goto bail; } TETH_DBG("init private data with lcid=%d\n", lcid); if (teth_ctx->init_status == TETH_INITIALIZED) { teth_ctx->ch_init_cnt++; Loading @@ -1989,6 +2088,7 @@ int teth_bridge_init(ipa_notify_cb *usb_notify_cb_ptr, void **private_data_ptr, goto fail; } if (teth_ctx->ipa_hw_type == IPA_HW_v1_1) { res = ipa_rm_add_dependency(IPA_RM_RESOURCE_BRIDGE_PROD, IPA_RM_RESOURCE_A2_CONS); if (res && res != -EINPROGRESS) { Loading @@ -2009,6 +2109,7 @@ int teth_bridge_init(ipa_notify_cb *usb_notify_cb_ptr, void **private_data_ptr, TETH_ERR("ipa_rm_add_dependency() failed\n"); goto fail_add_dependency_3; } } /* Return 0 as EINPROGRESS is a valid return value at this point */ teth_ctx->init_status = TETH_INITIALIZED; Loading Loading @@ -2144,6 +2245,7 @@ static void initialize_context(void) static int delete_usb_dependencies(void) { int res; /* * Delete part of IPA resource manager dependency graph. Only the * BRIDGE_PROD <-> A2 dependency remains intact Loading @@ -2153,6 +2255,8 @@ static int delete_usb_dependencies(void) if ((res != 0) && (res != -EINPROGRESS)) TETH_ERR( "Failed deleting ipa_rm dependency BRIDGE_PROD <-> USB_CONS\n"); if (teth_ctx->ipa_hw_type == IPA_HW_v1_1) { res = ipa_rm_delete_dependency(IPA_RM_RESOURCE_USB_PROD, IPA_RM_RESOURCE_A2_CONS); if ((res != 0) && (res != -EINPROGRESS)) Loading @@ -2163,6 +2267,8 @@ static int delete_usb_dependencies(void) if ((res != 0) && (res != -EINPROGRESS)) TETH_ERR( "Failed deleting ipa_rm dependency A2_PROD <-> USB_CONS\n"); } return res; } Loading Loading @@ -2205,7 +2311,8 @@ static int disconnect_ch(u16 lcid) u16 idx = get_ch_info_idx(lcid); TETH_DBG_FUNC_ENTRY(); /* Request the BRIDGE_PROD resource, A2 and IPA should power up */ if (teth_ctx->ipa_hw_type == IPA_HW_v1_1) { /* Request the BRIDGE_PROD resource */ res = teth_request_resource(); if (res) { TETH_ERR("request_resource() failed.\n"); Loading @@ -2219,7 +2326,8 @@ static int disconnect_ch(u16 lcid) if (teth_ctx->ch_info[idx].is_hw_bridge_complete) teardown_hw_bridge(idx); ipa_rm_inactivity_timer_release_resource(IPA_RM_RESOURCE_BRIDGE_PROD); ipa_rm_inactivity_timer_release_resource( IPA_RM_RESOURCE_BRIDGE_PROD); /* Deregister from A2_PROD notifications */ if (teth_ctx->ch_info[idx].ch_type == TETH_TETHERED_CH) { Loading @@ -2231,16 +2339,20 @@ static int disconnect_ch(u16 lcid) TETH_ERR( "Failed deregistering from A2_prod notifications.\n"); } } if (get_connected_ch_num() <= 1) { initialize_context(); /* Delete the last ipa_rm dependency - BRIDGE_PROD <-> A2 */ res = ipa_rm_delete_dependency(IPA_RM_RESOURCE_BRIDGE_PROD, if (teth_ctx->ipa_hw_type == IPA_HW_v1_1) { /* Delete ipa_rm dependency - BRIDGE_PROD <-> A2 */ res = ipa_rm_delete_dependency( IPA_RM_RESOURCE_BRIDGE_PROD, IPA_RM_RESOURCE_A2_CONS); if ((res != 0) && (res != -EINPROGRESS)) TETH_ERR( "Failed deleting ipa_rm dependency BRIDGE_PROD <-> A2_CONS\n"); } } initialize_ch_info(idx); bail: Loading @@ -2264,6 +2376,7 @@ static int disconnect_first_ch(u16 lcid) teth_ctx->init_status = TETH_NOT_INITIALIZED; TETH_DBG_FUNC_EXIT(); return 0; } Loading @@ -2274,7 +2387,8 @@ int teth_bridge_disconnect(enum ipa_client_type client) { u16 lcid; u16 idx; u16 num_of_iteration = 1, i; u16 num_of_iteration = 1; u16 i; TETH_DBG_FUNC_ENTRY(); if (teth_ctx->tethering_mode == TETH_TETHERING_MODE_MBIM) { Loading Loading @@ -2308,19 +2422,18 @@ bail: EXPORT_SYMBOL(teth_bridge_disconnect); /** * teth_bridge_connect() - Connect bridge for a tethered Rmnet / MBIM call * @connect_params: Connection info * * Return codes: 0: success * -EINVAL: invalid parameters * -EPERM: Operation not permitted as the bridge is already * connected */ int teth_bridge_connect(struct teth_bridge_connect_params *connect_params) static int __teth_bridge_connect_2_0(struct teth_bridge_connect_params *connect_params) { int res, num_of_iterations = 1, i; return 0; } static int __teth_bridge_connect_1_1(struct teth_bridge_connect_params *connect_params) { int res; int num_of_iterations = 1; int i; struct ipa_ep_cfg ipa_ep_cfg; u16 lcid; u16 idx; Loading @@ -2329,7 +2442,6 @@ int teth_bridge_connect(struct teth_bridge_connect_params *connect_params) struct ipa_rm_register_params a2_prod_reg_params; TETH_DBG_FUNC_ENTRY(); if (connect_params == NULL || connect_params->ipa_usb_pipe_hdl <= 0 || connect_params->usb_ipa_pipe_hdl <= 0 || Loading Loading @@ -2471,6 +2583,33 @@ bail: return res; } /** * teth_bridge_connect() - Connect bridge for a tethered Rmnet / MBIM call * @connect_params: Connection info * * Return codes: 0: success * -EINVAL: invalid parameters * -EPERM: Operation not permitted as the bridge is already * connected */ int teth_bridge_connect(struct teth_bridge_connect_params *connect_params) { int res; TETH_DBG_FUNC_ENTRY(); if (teth_ctx->ipa_hw_type == IPA_HW_v1_1) res = __teth_bridge_connect_1_1(connect_params); else if (teth_ctx->ipa_hw_type == IPA_HW_v2_0) res = __teth_bridge_connect_2_0(connect_params); else { TETH_ERR("Non supported HW type,\n"); res = -EINVAL; } return res; } EXPORT_SYMBOL(teth_bridge_connect); static void set_aggr_default_params(struct teth_aggr_params_link *params) Loading Loading @@ -2515,6 +2654,9 @@ static int teth_bridge_set_aggr_params(struct teth_aggr_params *aggr_params, u16 lcid, i; int num_of_iteration = 1; if (teth_ctx->ipa_hw_type != IPA_HW_v1_1) return -EFAULT; TETH_DBG_FUNC_ENTRY(); if (!aggr_params) { TETH_ERR("Invalid parameter\n"); Loading Loading @@ -2595,6 +2737,9 @@ static int teth_bridge_set_aggr_params(struct teth_aggr_params *aggr_params, int teth_bridge_set_mbim_aggr_params(struct teth_aggr_params *aggr_params, enum ipa_client_type client) { if (ipa_ctx->ipa_hw_type != IPA_HW_v1_1) TETH_ERR("This API should not be called on Krypton !\n"); teth_ctx->tethering_mode = TETH_TETHERING_MODE_MBIM; return teth_bridge_set_aggr_params(aggr_params, client); } Loading @@ -2611,6 +2756,11 @@ static long teth_bridge_ioctl(struct file *filp, struct hw_bridge_work_wrap *work_data; u16 i = 0; if (teth_ctx->ipa_hw_type != IPA_HW_v1_1) { IPAERR("No ioctls are supported for krypton !\n"); return -ENOIOCTLCMD; } TETH_DBG("cmd=%x nr=%d\n", cmd, _IOC_NR(cmd)); if ((_IOC_TYPE(cmd) != TETH_BRIDGE_IOC_MAGIC) || Loading Loading @@ -3096,22 +3246,17 @@ const struct file_operations teth_hw_bridge_status_ops = { .read = teth_debugfs_hw_bridge_status, }; void teth_debugfs_init(void) static int __debugfs_create_v1_1(struct dentry *dent) { const mode_t read_only_mode = S_IRUSR | S_IRGRP | S_IROTH; const mode_t read_write_mode = S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR | S_IWGRP | S_IWOTH; dent = debugfs_create_dir("ipa_teth", 0); if (IS_ERR(dent)) { IPAERR("fail to create folder ipa_teth debug_fs.\n"); return; } dfile_lcid = debugfs_create_file("lcid", read_write_mode, dent, 0, &teth_lcid_ops); if (!dfile_lcid || IS_ERR(dfile_lcid)) { IPAERR("fail to create file lcid\n"); goto fail; return -EFAULT; } dfile_link_protocol = Loading @@ -3119,7 +3264,7 @@ void teth_debugfs_init(void) &teth_link_protocol_ops); if (!dfile_link_protocol || IS_ERR(dfile_link_protocol)) { IPAERR("fail to create file link_protocol\n"); goto fail; return -EFAULT; } dfile_get_aggr_params = Loading @@ -3127,7 +3272,7 @@ void teth_debugfs_init(void) &teth_get_aggr_params_ops); if (!dfile_get_aggr_params || IS_ERR(dfile_get_aggr_params)) { IPAERR("fail to create file get_aggr_params\n"); goto fail; return -EFAULT; } dfile_set_aggr_protocol = Loading @@ -3135,7 +3280,7 @@ void teth_debugfs_init(void) 0, &teth_set_aggr_protocol_ops); if (!dfile_set_aggr_protocol || IS_ERR(dfile_set_aggr_protocol)) { IPAERR("fail to create file set_aggr_protocol\n"); goto fail; return -EFAULT; } dfile_stats = Loading @@ -3143,7 +3288,7 @@ void teth_debugfs_init(void) 0, &teth_stats_ops); if (!dfile_stats || IS_ERR(dfile_stats)) { IPAERR("fail to create file stats\n"); goto fail; return -EFAULT; } dfile_is_hw_bridge_complete = Loading @@ -3152,12 +3297,40 @@ void teth_debugfs_init(void) if (!dfile_is_hw_bridge_complete || IS_ERR(dfile_is_hw_bridge_complete)) { IPAERR("fail to create file is_hw_bridge_complete\n"); goto fail; return -EFAULT; } return 0; } static int __debugfs_create_v2_0(struct dentry *dent) { return 0; } void teth_debugfs_init(void) { int res; dent = debugfs_create_dir("ipa_teth", 0); if (IS_ERR(dent)) { IPAERR("fail to create folder ipa_teth debug_fs.\n"); return; fail: } if (teth_ctx->ipa_hw_type == IPA_HW_v1_1) res = __debugfs_create_v1_1(dent); else if (teth_ctx->ipa_hw_type == IPA_HW_v2_0) res = __debugfs_create_v2_0(dent); else { TETH_ERR("Invalid HW type, debugfs disabled !\n"); res = -EFAULT; } if (res) debugfs_remove_recursive(dent); return; } #else void teth_debugfs_init(void) {} Loading Loading @@ -3256,7 +3429,7 @@ fail_alloc_routing_del_ipv4: * teth_bridge_driver_init() - Initialize tethering bridge driver * */ int teth_bridge_driver_init(void) int teth_bridge_driver_init(enum ipa_hw_type ipa_hw_type) { int res; struct ipa_rm_create_params bridge_prod_params; Loading @@ -3269,6 +3442,8 @@ int teth_bridge_driver_init(void) return -ENOMEM; } teth_ctx->ipa_hw_type = ipa_hw_type; teth_ctx->ch_info = kzalloc(sizeof(struct logic_ch_info)*TETH_NUM_CHANNELS, GFP_KERNEL); Loading @@ -3277,11 +3452,13 @@ int teth_bridge_driver_init(void) goto fail_alloc_channel_info; } if (teth_ctx->ipa_hw_type == IPA_HW_v1_1) { res = set_aggr_capabilities(); if (res) { TETH_ERR("kzalloc err.\n"); goto fail_alloc_aggr_caps; } } teth_ctx->class = class_create(THIS_MODULE, TETH_BRIDGE_DRV_NAME); Loading Loading @@ -3334,11 +3511,13 @@ int teth_bridge_driver_init(void) goto fail_cdev_add; } if (teth_ctx->ipa_hw_type == IPA_HW_v1_1) { teth_ctx->teth_wq = create_workqueue(TETH_WORKQUEUE_NAME); if (!teth_ctx->teth_wq) { TETH_ERR("workqueue creation failed\n"); goto fail_cdev_add; } } res = alloc_del_hnds(); if (res) { Loading