|
@@ -993,6 +993,169 @@ static void ipa3_gsb_msg_free_cb(void *buff, u32 len, u32 type)
|
|
|
kfree(buff);
|
|
|
}
|
|
|
|
|
|
+static void ipa3_get_usb_ep_info(
|
|
|
+ struct ipa_ioc_get_ep_info *ep_info,
|
|
|
+ struct ipa_ep_pair_info *pair_info
|
|
|
+ )
|
|
|
+{
|
|
|
+ int ep_index = -1, i;
|
|
|
+
|
|
|
+ ep_info->num_ep_pairs = 0;
|
|
|
+ for (i = 0; i < ep_info->max_ep_pairs; i++) {
|
|
|
+ pair_info[i].consumer_pipe_num = -1;
|
|
|
+ pair_info[i].producer_pipe_num = -1;
|
|
|
+ pair_info[i].ep_id = -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ ep_index = ipa3_get_ep_mapping(IPA_CLIENT_USB_PROD);
|
|
|
+
|
|
|
+ if ((ep_index != -1) && ipa3_ctx->ep[ep_index].valid) {
|
|
|
+ pair_info[ep_info->num_ep_pairs].consumer_pipe_num = ep_index;
|
|
|
+ ep_index = ipa3_get_ep_mapping(IPA_CLIENT_USB_CONS);
|
|
|
+ if ((ep_index != -1) && (ipa3_ctx->ep[ep_index].valid)) {
|
|
|
+ pair_info[ep_info->num_ep_pairs].producer_pipe_num =
|
|
|
+ ep_index;
|
|
|
+ pair_info[ep_info->num_ep_pairs].ep_id =
|
|
|
+ IPA_USB0_EP_ID;
|
|
|
+
|
|
|
+ IPADBG("ep_pair_info consumer_pipe_num %d",
|
|
|
+ pair_info[ep_info->num_ep_pairs].consumer_pipe_num);
|
|
|
+ IPADBG(" producer_pipe_num %d ep_id %d\n",
|
|
|
+ pair_info[ep_info->num_ep_pairs].producer_pipe_num,
|
|
|
+ pair_info[ep_info->num_ep_pairs].ep_id);
|
|
|
+ ep_info->num_ep_pairs++;
|
|
|
+ } else {
|
|
|
+ pair_info[ep_info->num_ep_pairs].consumer_pipe_num = -1;
|
|
|
+ IPADBG("ep_pair_info consumer_pipe_num %d",
|
|
|
+ pair_info[ep_info->num_ep_pairs].consumer_pipe_num);
|
|
|
+ IPADBG(" producer_pipe_num %d ep_id %d\n",
|
|
|
+ pair_info[ep_info->num_ep_pairs].producer_pipe_num,
|
|
|
+ pair_info[ep_info->num_ep_pairs].ep_id);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ ep_index = ipa3_get_ep_mapping(IPA_CLIENT_USB2_PROD);
|
|
|
+
|
|
|
+ if ((ep_index != -1) && ipa3_ctx->ep[ep_index].valid) {
|
|
|
+ pair_info[ep_info->num_ep_pairs].consumer_pipe_num = ep_index;
|
|
|
+ ep_index = ipa3_get_ep_mapping(IPA_CLIENT_USB2_CONS);
|
|
|
+ if ((ep_index != -1) && (ipa3_ctx->ep[ep_index].valid)) {
|
|
|
+ pair_info[ep_info->num_ep_pairs].producer_pipe_num =
|
|
|
+ ep_index;
|
|
|
+ pair_info[ep_info->num_ep_pairs].ep_id =
|
|
|
+ IPA_USB1_EP_ID;
|
|
|
+
|
|
|
+ IPADBG("ep_pair_info consumer_pipe_num %d",
|
|
|
+ pair_info[ep_info->num_ep_pairs].consumer_pipe_num);
|
|
|
+ IPADBG(" producer_pipe_num %d ep_id %d\n",
|
|
|
+ pair_info[ep_info->num_ep_pairs].producer_pipe_num,
|
|
|
+ pair_info[ep_info->num_ep_pairs].ep_id);
|
|
|
+ ep_info->num_ep_pairs++;
|
|
|
+ } else {
|
|
|
+ pair_info[ep_info->num_ep_pairs].consumer_pipe_num = -1;
|
|
|
+ IPADBG("ep_pair_info consumer_pipe_num %d",
|
|
|
+ pair_info[ep_info->num_ep_pairs].consumer_pipe_num);
|
|
|
+ IPADBG(" producer_pipe_num %d ep_id %d\n",
|
|
|
+ pair_info[ep_info->num_ep_pairs].producer_pipe_num,
|
|
|
+ pair_info[ep_info->num_ep_pairs].ep_id);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static void ipa3_get_pcie_ep_info(
|
|
|
+ struct ipa_ioc_get_ep_info *ep_info,
|
|
|
+ struct ipa_ep_pair_info *pair_info
|
|
|
+ )
|
|
|
+{
|
|
|
+ int ep_index = -1, i;
|
|
|
+
|
|
|
+ ep_info->num_ep_pairs = 0;
|
|
|
+ for (i = 0; i < ep_info->max_ep_pairs; i++) {
|
|
|
+ pair_info[i].consumer_pipe_num = -1;
|
|
|
+ pair_info[i].producer_pipe_num = -1;
|
|
|
+ pair_info[i].ep_id = -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ ep_index = ipa3_get_ep_mapping(IPA_CLIENT_MHI_PROD);
|
|
|
+
|
|
|
+ if ((ep_index != -1) && ipa3_ctx->ep[ep_index].valid) {
|
|
|
+ pair_info[ep_info->num_ep_pairs].consumer_pipe_num = ep_index;
|
|
|
+ ep_index = ipa3_get_ep_mapping(IPA_CLIENT_MHI_CONS);
|
|
|
+ if ((ep_index != -1) && (ipa3_ctx->ep[ep_index].valid)) {
|
|
|
+ pair_info[ep_info->num_ep_pairs].producer_pipe_num =
|
|
|
+ ep_index;
|
|
|
+ pair_info[ep_info->num_ep_pairs].ep_id =
|
|
|
+ IPA_PCIE0_EP_ID;
|
|
|
+
|
|
|
+ IPADBG("ep_pair_info consumer_pipe_num %d",
|
|
|
+ pair_info[ep_info->num_ep_pairs].consumer_pipe_num);
|
|
|
+ IPADBG(" producer_pipe_num %d ep_id %d\n",
|
|
|
+ pair_info[ep_info->num_ep_pairs].producer_pipe_num,
|
|
|
+ pair_info[ep_info->num_ep_pairs].ep_id);
|
|
|
+ ep_info->num_ep_pairs++;
|
|
|
+ } else {
|
|
|
+ pair_info[ep_info->num_ep_pairs].consumer_pipe_num = -1;
|
|
|
+ IPADBG("ep_pair_info consumer_pipe_num %d",
|
|
|
+ pair_info[ep_info->num_ep_pairs].consumer_pipe_num);
|
|
|
+ IPADBG(" producer_pipe_num %d ep_id %d\n",
|
|
|
+ pair_info[ep_info->num_ep_pairs].producer_pipe_num,
|
|
|
+ pair_info[ep_info->num_ep_pairs].ep_id);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ ep_index = ipa3_get_ep_mapping(IPA_CLIENT_MHI2_PROD);
|
|
|
+
|
|
|
+ if ((ep_index != -1) && ipa3_ctx->ep[ep_index].valid) {
|
|
|
+ pair_info[ep_info->num_ep_pairs].consumer_pipe_num = ep_index;
|
|
|
+ ep_index = ipa3_get_ep_mapping(IPA_CLIENT_MHI2_CONS);
|
|
|
+ if ((ep_index != -1) && (ipa3_ctx->ep[ep_index].valid)) {
|
|
|
+ pair_info[ep_info->num_ep_pairs].producer_pipe_num =
|
|
|
+ ep_index;
|
|
|
+ pair_info[ep_info->num_ep_pairs].ep_id =
|
|
|
+ IPA_PCIE1_EP_ID;
|
|
|
+
|
|
|
+ IPADBG("ep_pair_info consumer_pipe_num %d",
|
|
|
+ pair_info[ep_info->num_ep_pairs].consumer_pipe_num);
|
|
|
+ IPADBG(" producer_pipe_num %d ep_id %d\n",
|
|
|
+ pair_info[ep_info->num_ep_pairs].producer_pipe_num,
|
|
|
+ pair_info[ep_info->num_ep_pairs].ep_id);
|
|
|
+ ep_info->num_ep_pairs++;
|
|
|
+ } else {
|
|
|
+ pair_info[ep_info->num_ep_pairs].consumer_pipe_num = -1;
|
|
|
+ IPADBG("ep_pair_info consumer_pipe_num %d",
|
|
|
+ pair_info[ep_info->num_ep_pairs].consumer_pipe_num);
|
|
|
+ IPADBG(" producer_pipe_num %d ep_id %d\n",
|
|
|
+ pair_info[ep_info->num_ep_pairs].producer_pipe_num,
|
|
|
+ pair_info[ep_info->num_ep_pairs].ep_id);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+static int ipa3_get_ep_info(struct ipa_ioc_get_ep_info *ep_info,
|
|
|
+ u8 *param)
|
|
|
+{
|
|
|
+ int ret = 0;
|
|
|
+ struct ipa_ep_pair_info *pair_info = (struct ipa_ep_pair_info *)param;
|
|
|
+
|
|
|
+ switch (ep_info->ep_type) {
|
|
|
+ case IPA_DATA_EP_TYP_HSUSB:
|
|
|
+ ipa3_get_usb_ep_info(ep_info, pair_info);
|
|
|
+ break;
|
|
|
+
|
|
|
+ case IPA_DATA_EP_TYP_PCIE:
|
|
|
+ ipa3_get_pcie_ep_info(ep_info, pair_info);
|
|
|
+ break;
|
|
|
+
|
|
|
+ default:
|
|
|
+ IPAERR_RL("Undefined ep_type %d\n", ep_info->ep_type);
|
|
|
+ ret = -EFAULT;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
static int ipa3_send_gsb_msg(unsigned long usr_param, uint8_t msg_type)
|
|
|
{
|
|
|
int retval;
|
|
@@ -1959,6 +2122,8 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
|
|
size_t sz;
|
|
|
int pre_entry;
|
|
|
int hdl;
|
|
|
+ unsigned long uptr = 0;
|
|
|
+ struct ipa_ioc_get_ep_info ep_info;
|
|
|
|
|
|
IPADBG("cmd=%x nr=%d\n", cmd, _IOC_NR(cmd));
|
|
|
|
|
@@ -3179,6 +3344,71 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
|
|
}
|
|
|
break;
|
|
|
|
|
|
+ case IPA_IOC_GET_PHERIPHERAL_EP_INFO:
|
|
|
+ IPADBG("Got IPA_IOC_GET_EP_INFO\n");
|
|
|
+ if (ipa3_ctx->ipa_config_is_auto == false) {
|
|
|
+ IPADBG("not an auto config: returning error\n");
|
|
|
+ retval = -ENOTTY;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if (copy_from_user(&ep_info, (const void __user *)arg,
|
|
|
+ sizeof(struct ipa_ioc_get_ep_info))) {
|
|
|
+ IPAERR_RL("copy_from_user fails\n");
|
|
|
+ retval = -EFAULT;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ep_info.max_ep_pairs != QUERY_MAX_EP_PAIRS) {
|
|
|
+ IPAERR_RL("unexpected max_ep_pairs %d\n",
|
|
|
+ ep_info.max_ep_pairs);
|
|
|
+ retval = -EFAULT;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ep_info.ep_pair_size !=
|
|
|
+ (QUERY_MAX_EP_PAIRS * sizeof(struct ipa_ep_pair_info))) {
|
|
|
+ IPAERR_RL("unexpected ep_pair_size %d\n",
|
|
|
+ ep_info.max_ep_pairs);
|
|
|
+ retval = -EFAULT;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ uptr = ep_info.info;
|
|
|
+ if (unlikely(!uptr)) {
|
|
|
+ IPAERR_RL("unexpected NULL info\n");
|
|
|
+ retval = -EFAULT;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ param = kzalloc(ep_info.ep_pair_size, GFP_KERNEL);
|
|
|
+ if (!param) {
|
|
|
+ IPAERR_RL("kzalloc fails\n");
|
|
|
+ retval = -ENOMEM;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ retval = ipa3_get_ep_info(&ep_info, param);
|
|
|
+ if (retval < 0) {
|
|
|
+ IPAERR("ipa3_get_ep_info failed\n");
|
|
|
+ retval = -EFAULT;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (copy_to_user((void __user *)uptr, param,
|
|
|
+ ep_info.ep_pair_size)) {
|
|
|
+ IPAERR_RL("copy_to_user fails\n");
|
|
|
+ retval = -EFAULT;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (copy_to_user((void __user *)arg, &ep_info,
|
|
|
+ sizeof(struct ipa_ioc_get_ep_info))) {
|
|
|
+ IPAERR_RL("copy_to_user fails\n");
|
|
|
+ retval = -EFAULT;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
default:
|
|
|
IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
|
|
|
return -ENOTTY;
|