Merge "msm: ipa: Add MBIM tethering support"
diff --git a/arch/arm/mach-msm/include/mach/ipa.h b/arch/arm/mach-msm/include/mach/ipa.h
index 2010abb..cc03c48 100644
--- a/arch/arm/mach-msm/include/mach/ipa.h
+++ b/arch/arm/mach-msm/include/mach/ipa.h
@@ -652,6 +652,8 @@
int teth_bridge_connect(struct teth_bridge_connect_params *connect_params);
+int teth_bridge_set_aggr_params(struct teth_aggr_params *aggr_params);
+
#else /* CONFIG_IPA */
static inline int a2_mux_open_channel(enum a2_mux_logical_channel_id lcid,
@@ -1073,6 +1075,12 @@
return -EPERM;
}
+static inline int teth_bridge_set_aggr_params(struct teth_aggr_params
+ *aggr_params)
+{
+ return -EPERM;
+}
+
#endif /* CONFIG_IPA*/
#endif /* _IPA_H_ */
diff --git a/drivers/platform/msm/ipa/teth_bridge.c b/drivers/platform/msm/ipa/teth_bridge.c
index 29253cd..5b26e41 100644
--- a/drivers/platform/msm/ipa/teth_bridge.c
+++ b/drivers/platform/msm/ipa/teth_bridge.c
@@ -29,7 +29,6 @@
#define TETH_BRIDGE_DRV_NAME "ipa_tethering_bridge"
-#ifdef TETH_DEBUG
#define TETH_DBG(fmt, args...) \
pr_debug(TETH_BRIDGE_DRV_NAME " %s:%d " fmt, \
__func__, __LINE__, ## args)
@@ -37,12 +36,6 @@
pr_debug(TETH_BRIDGE_DRV_NAME " %s:%d ENTRY\n", __func__, __LINE__)
#define TETH_DBG_FUNC_EXIT() \
pr_debug(TETH_BRIDGE_DRV_NAME " %s:%d EXIT\n", __func__, __LINE__)
-#else
-#define TETH_DBG(fmt, args...)
-#define TETH_DBG_FUNC_ENTRY()
-#define TETH_DBG_FUNC_EXIT()
-#endif
-
#define TETH_ERR(fmt, args...) \
pr_err(TETH_BRIDGE_DRV_NAME " %s:%d " fmt, __func__, __LINE__, ## args)
@@ -62,6 +55,9 @@
#define ETHERTYPE_IPV4 0x0800
#define ETHERTYPE_IPV6 0x86DD
+#define TETH_AGGR_MAX_DATAGRAMS_DEFAULT 16
+#define TETH_AGGR_MAX_AGGR_PACKET_SIZE_DEFAULT (8*1024)
+
struct mac_addresses_type {
u8 host_pc_mac_addr[ETH_ALEN];
bool host_pc_mac_addr_known;
@@ -905,7 +901,6 @@
int teth_bridge_init(ipa_notify_cb *usb_notify_cb_ptr, void **private_data_ptr)
{
int res = 0;
- struct ipa_rm_create_params bridge_prod_params;
TETH_DBG_FUNC_ENTRY();
if (usb_notify_cb_ptr == NULL) {
@@ -918,48 +913,34 @@
*private_data_ptr = NULL;
/* Build IPA Resource manager dependency graph */
- bridge_prod_params.name = IPA_RM_RESOURCE_BRIDGE_PROD;
- bridge_prod_params.reg_params.user_data = NULL;
- bridge_prod_params.reg_params.notify_cb = bridge_prod_notify_cb;
- res = ipa_rm_create_resource(&bridge_prod_params);
- if (res) {
- TETH_ERR("ipa_rm_create_resource() failed\n");
- goto bail;
- }
-
res = ipa_rm_add_dependency(IPA_RM_RESOURCE_BRIDGE_PROD,
IPA_RM_RESOURCE_USB_CONS);
- if (res) {
+ if (res && res != -EEXIST) {
TETH_ERR("ipa_rm_add_dependency() failed\n");
goto bail;
}
res = ipa_rm_add_dependency(IPA_RM_RESOURCE_BRIDGE_PROD,
IPA_RM_RESOURCE_A2_CONS);
- if (res) {
+ if (res && res != -EEXIST) {
TETH_ERR("ipa_rm_add_dependency() failed\n");
goto fail_add_dependency_1;
}
res = ipa_rm_add_dependency(IPA_RM_RESOURCE_USB_PROD,
IPA_RM_RESOURCE_A2_CONS);
- if (res) {
+ if (res && res != -EEXIST) {
TETH_ERR("ipa_rm_add_dependency() failed\n");
goto fail_add_dependency_2;
}
res = ipa_rm_add_dependency(IPA_RM_RESOURCE_A2_PROD,
IPA_RM_RESOURCE_USB_CONS);
- if (res) {
+ if (res && res != -EEXIST) {
TETH_ERR("ipa_rm_add_dependency() failed\n");
goto fail_add_dependency_3;
}
- init_completion(&teth_ctx->is_bridge_prod_up);
- init_completion(&teth_ctx->is_bridge_prod_down);
-
- /* The default link protocol is Ethernet */
- teth_ctx->link_protocol = TETH_LINK_PROTOCOL_ETHERNET;
goto bail;
fail_add_dependency_3:
@@ -1001,6 +982,20 @@
if (res == -EINPROGRESS)
wait_for_completion(&teth_ctx->is_bridge_prod_down);
+ /* Initialize statistics */
+ memset(&teth_ctx->stats, 0, sizeof(teth_ctx->stats));
+
+ /* Delete IPA Resource manager dependency graph */
+ res = ipa_rm_delete_dependency(IPA_RM_RESOURCE_BRIDGE_PROD,
+ IPA_RM_RESOURCE_USB_CONS);
+ res |= ipa_rm_delete_dependency(IPA_RM_RESOURCE_BRIDGE_PROD,
+ IPA_RM_RESOURCE_A2_CONS);
+ res |= ipa_rm_delete_dependency(IPA_RM_RESOURCE_USB_PROD,
+ IPA_RM_RESOURCE_A2_CONS);
+ res |= ipa_rm_delete_dependency(IPA_RM_RESOURCE_A2_PROD,
+ IPA_RM_RESOURCE_USB_CONS);
+ if (res)
+ TETH_ERR("Failed deleting ipa_rm dependency.\n");
bail:
TETH_DBG_FUNC_EXIT();
return res;
@@ -1084,9 +1079,11 @@
static void set_aggr_default_params(struct teth_aggr_params_link *params)
{
if (params->max_datagrams == 0)
- params->max_datagrams = 16;
+ params->max_datagrams =
+ TETH_AGGR_MAX_DATAGRAMS_DEFAULT;
if (params->max_transfer_size_byte == 0)
- params->max_transfer_size_byte = 16*1024;
+ params->max_transfer_size_byte =
+ TETH_AGGR_MAX_AGGR_PACKET_SIZE_DEFAULT;
}
static void teth_set_bridge_mode(enum teth_link_protocol_type link_protocol)
@@ -1096,11 +1093,38 @@
memset(&teth_ctx->mac_addresses, 0, sizeof(teth_ctx->mac_addresses));
}
+int teth_bridge_set_aggr_params(struct teth_aggr_params *aggr_params)
+{
+ int res;
+
+ if (!aggr_params) {
+ TETH_ERR("Invalid parameter\n");
+ return -EINVAL;
+ }
+
+ memcpy(&teth_ctx->aggr_params,
+ aggr_params,
+ sizeof(struct teth_aggr_params));
+ set_aggr_default_params(&teth_ctx->aggr_params.dl);
+ set_aggr_default_params(&teth_ctx->aggr_params.ul);
+
+ teth_ctx->aggr_params_known = true;
+ res = teth_set_aggregation();
+ if (res) {
+ TETH_ERR("Failed setting aggregation params\n");
+ res = -EFAULT;
+ }
+
+ return res;
+}
+EXPORT_SYMBOL(teth_bridge_set_aggr_params);
+
static long teth_bridge_ioctl(struct file *filp,
unsigned int cmd,
unsigned long arg)
{
int res = 0;
+ struct teth_aggr_params aggr_params;
TETH_DBG("cmd=%x nr=%d\n", cmd, _IOC_NR(cmd));
@@ -1119,7 +1143,7 @@
case TETH_BRIDGE_IOC_SET_AGGR_PARAMS:
TETH_DBG("TETH_BRIDGE_IOC_SET_AGGR_PARAMS ioctl called\n");
- res = copy_from_user(&teth_ctx->aggr_params,
+ res = copy_from_user(&aggr_params,
(struct teth_aggr_params *)arg,
sizeof(struct teth_aggr_params));
if (res) {
@@ -1127,9 +1151,8 @@
res = -EFAULT;
break;
}
- set_aggr_default_params(&teth_ctx->aggr_params.dl);
- set_aggr_default_params(&teth_ctx->aggr_params.ul);
- teth_ctx->aggr_params_known = true;
+
+ res = teth_bridge_set_aggr_params(&aggr_params);
break;
case TETH_BRIDGE_IOC_GET_AGGR_PARAMS:
@@ -1201,12 +1224,10 @@
teth_ctx->aggr_caps->num_protocols = NUM_PROTOCOLS;
teth_ctx->aggr_caps->prot_caps[0].aggr_prot = TETH_AGGR_PROTOCOL_MBIM;
- teth_ctx->aggr_caps->prot_caps[0].max_datagrams = 16;
- teth_ctx->aggr_caps->prot_caps[0].max_transfer_size_byte = 16*1024;
+ set_aggr_default_params(&teth_ctx->aggr_caps->prot_caps[0]);
teth_ctx->aggr_caps->prot_caps[1].aggr_prot = TETH_AGGR_PROTOCOL_TLP;
- teth_ctx->aggr_caps->prot_caps[1].max_datagrams = 16;
- teth_ctx->aggr_caps->prot_caps[1].max_transfer_size_byte = 16*1024;
+ set_aggr_default_params(&teth_ctx->aggr_caps->prot_caps[1]);
}
void teth_bridge_get_client_handles(u32 *producer_handle,
@@ -1287,7 +1308,7 @@
aggr_prot_to_str(teth_ctx->aggr_params.ul.aggr_prot,
aggr_str,
sizeof(aggr_str)-1);
- nbytes += scnprintf(&dbg_buff[nbytes], TETH_MAX_MSG_LEN,
+ nbytes += scnprintf(&dbg_buff[nbytes], TETH_MAX_MSG_LEN - nbytes,
"Aggregation parameters for uplink:\n");
nbytes += scnprintf(&dbg_buff[nbytes], TETH_MAX_MSG_LEN - nbytes,
" Aggregation protocol: %s\n",
@@ -1493,6 +1514,7 @@
int teth_bridge_driver_init(void)
{
int res;
+ struct ipa_rm_create_params bridge_prod_params;
TETH_DBG("Tethering bridge driver init\n");
teth_ctx = kzalloc(sizeof(*teth_ctx), GFP_KERNEL);
@@ -1535,6 +1557,22 @@
teth_ctx->comp_hw_bridge_in_progress = false;
teth_debugfs_init();
+
+ /* Create BRIDGE_PROD entity in IPA Resource Manager */
+ bridge_prod_params.name = IPA_RM_RESOURCE_BRIDGE_PROD;
+ bridge_prod_params.reg_params.user_data = NULL;
+ bridge_prod_params.reg_params.notify_cb = bridge_prod_notify_cb;
+ res = ipa_rm_create_resource(&bridge_prod_params);
+ if (res) {
+ TETH_ERR("ipa_rm_create_resource() failed\n");
+ goto fail_cdev_add;
+ }
+ init_completion(&teth_ctx->is_bridge_prod_up);
+ init_completion(&teth_ctx->is_bridge_prod_down);
+
+ /* The default link protocol is Ethernet */
+ teth_ctx->link_protocol = TETH_LINK_PROTOCOL_ETHERNET;
+
TETH_DBG("Tethering bridge driver init OK\n");
return 0;