Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ad3cda77 authored by Ido Shayevitz's avatar Ido Shayevitz
Browse files

usb: bam: Add max Mbps vote for IPA resources



Add a vote for IPA clock performance to enhance IPA clock
tuning according to the actual connection speed in use cases
which involve USB or HSIC connection to IPA.

For Bam2Bam mode we support USB high speed or super speed only, in each
there is different limitation of max mbps, therefore allow tuning
performance upon connection establishment.

CRs-Fixed: 637429
Change-Id: I7456a1d7bc6eb7c87df251acca1ba94e34caa805
Signed-off-by: default avatarIdo Shayevitz <idos@codeaurora.org>
parent 48260762
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -87,6 +87,10 @@ Optional properties :
- qcom,usb-bam-override-threshold: If present then the default 512 byte threshold
		is overriden. This threshold configures the threshold value for Read/Write
		event generation by the BAM towards another BAM.
- qcom,usb-bam-max-mbps-highspeed: max mbps in high speed connection
            for either rx or tx direction.
- qcom,usb-bam-max-mbps-superspeed: max mbps in super speed connection
            for either rx or tx direction.

Example USB BAM controller device node:

@@ -99,6 +103,8 @@ Example USB BAM controller device node:
		qcom,usb-bam-num-pipes = <16>;
		qcom,ignore-core-reset-ack;
		qcom,disable-clk-gating;
		qcom,usb-bam-max-mbps-highspeed = <400>;
		qcom,usb-bam-max-mbps-superspeed = <3600>;

		qcom,pipe0 {
			label = "hsusb-ipa-out-0";
+70 −7
Original line number Diff line number Diff line
@@ -2032,6 +2032,50 @@ void msm_bam_hsic_host_notify_on_resume(void)
	_msm_bam_host_notify_on_resume(HSIC_CTRL);
}

static int usb_bam_set_ipa_perf(enum usb_ctrl cur_bam,
			      enum usb_bam_pipe_dir dir,
			      enum usb_device_speed usb_connection_speed)
{
	int ret;
	struct ipa_rm_perf_profile ipa_rm_perf_prof;
	struct msm_usb_bam_platform_data *pdata =
					ctx.usb_bam_pdev->dev.platform_data;

	if (usb_connection_speed == USB_SPEED_SUPER)
		ipa_rm_perf_prof.max_supported_bandwidth_mbps =
			pdata->max_mbps_superspeed;
	else
		/* Bam2Bam is supported only for SS and HS (HW limitation) */
		ipa_rm_perf_prof.max_supported_bandwidth_mbps =
			pdata->max_mbps_highspeed;

	/*
	 * Having a max mbps property in dtsi file is a must
	 * for target with IPA capability.
	 */
	if (!ipa_rm_perf_prof.max_supported_bandwidth_mbps) {
		pr_err("%s: Max mbps is required for speed %d\n", __func__,
			usb_connection_speed);
		return -EINVAL;
	}

	if (dir == USB_TO_PEER_PERIPHERAL) {
		pr_debug("%s: vote ipa_perf resource=%d perf=%d mbps\n",
			__func__, ipa_rm_resource_prod[cur_bam],
			ipa_rm_perf_prof.max_supported_bandwidth_mbps);
		ret = ipa_rm_set_perf_profile(ipa_rm_resource_prod[cur_bam],
					&ipa_rm_perf_prof);
	} else {
		pr_debug("%s: vote ipa_perf resource=%d perf=%d mbps\n",
			__func__, ipa_rm_resource_cons[cur_bam],
			ipa_rm_perf_prof.max_supported_bandwidth_mbps);
		ret = ipa_rm_set_perf_profile(ipa_rm_resource_cons[cur_bam],
					&ipa_rm_perf_prof);
	}

	return ret;
}

int usb_bam_connect_ipa(struct usb_bam_connect_ipa_params *ipa_params)
{
	u8 idx;
@@ -2062,13 +2106,6 @@ int usb_bam_connect_ipa(struct usb_bam_connect_ipa_params *ipa_params)
		return -EINVAL;
	}
	pipe_connect = &usb_bam_connections[idx];
	cur_bam = pipe_connect->bam_type;
	cur_mode = pipe_connect->bam_mode;
	bam2bam = (pdata->connections[idx].pipe_type ==
			USB_BAM_PIPE_BAM2BAM);

	/* Set the BAM mode (host/device) according to connected pipe */
	info[cur_bam].cur_bam_mode = pipe_connect->bam_mode;

	if (pipe_connect->enabled) {
		pr_err("%s: connection %d was already established\n",
@@ -2076,8 +2113,24 @@ int usb_bam_connect_ipa(struct usb_bam_connect_ipa_params *ipa_params)
		return 0;
	}

	ret = usb_bam_set_ipa_perf(pipe_connect->bam_type, ipa_params->dir,
			     ipa_params->usb_connection_speed);
	if (ret) {
		pr_err("%s: call to usb_bam_set_ipa_perf failed %d\n",
			__func__, ret);
		return ret;
	}

	pr_debug("%s: enter", __func__);

	cur_bam = pipe_connect->bam_type;
	cur_mode = pipe_connect->bam_mode;
	bam2bam = (pdata->connections[idx].pipe_type ==
			USB_BAM_PIPE_BAM2BAM);

	/* Set the BAM mode (host/device) according to connected pipe */
	info[cur_bam].cur_bam_mode = pipe_connect->bam_mode;

	if (cur_mode == USB_BAM_DEVICE) {
		mutex_lock(&info[cur_bam].suspend_resume_mutex);

@@ -2801,6 +2854,16 @@ static struct msm_usb_bam_platform_data *usb_bam_dt_to_pdata(
		return NULL;
	}

	rc = of_property_read_u32(node, "qcom,usb-bam-max-mbps-highspeed",
		&pdata->max_mbps_highspeed);
	if (rc)
		pdata->max_mbps_highspeed = 0;

	rc = of_property_read_u32(node, "qcom,usb-bam-max-mbps-superspeed",
		&pdata->max_mbps_superspeed);
	if (rc)
		pdata->max_mbps_superspeed = 0;

	rc = of_property_read_u32(node, "qcom,usb-bam-fifo-baseaddr",
			&addr);
	if (rc)
+8 −0
Original line number Diff line number Diff line
@@ -1082,6 +1082,11 @@ static void gbam2bam_connect_work(struct work_struct *w)
	if (dev && dev->cdev)
		gadget = dev->cdev->gadget;

	if (!gadget) {
		pr_err("%s: NULL gadget\n", __func__);
		return;
	}

	spin_lock_irqsave(&port->port_lock_ul, flags);
	spin_lock(&port->port_lock_dl);
	if (!port->port_usb) {
@@ -1131,6 +1136,9 @@ static void gbam2bam_connect_work(struct work_struct *w)
			return;
		}
	} else if (d->trans == USB_GADGET_XPORT_BAM2BAM_IPA) {

		d->ipa_params.usb_connection_speed = gadget->speed;

		if (usb_bam_get_pipe_type(d->ipa_params.src_idx,
				&d->src_pipe_type) ||
			usb_bam_get_pipe_type(d->ipa_params.dst_idx,
+11 −1
Original line number Diff line number Diff line
@@ -701,7 +701,7 @@ static void bam2bam_data_connect_work(struct work_struct *w)
	struct teth_bridge_init_params teth_bridge_params;
	struct bam_data_ch_info *d = &port->data_ch;
	struct data_port	*d_port = port->port_usb;
	struct usb_gadget	*gadget = d_port->cdev->gadget;
	struct usb_gadget	*gadget = NULL;
	u32			sps_params;
	int			ret;
	unsigned long		flags;
@@ -713,6 +713,14 @@ static void bam2bam_data_connect_work(struct work_struct *w)
		return;
	}

	if (d_port && d_port->cdev)
		gadget = d_port->cdev->gadget;

	if (!gadget) {
		pr_err("%s: NULL gadget\n", __func__);
		return;
	}

	spin_lock_irqsave(&port->port_lock_ul, flags);
	if (!port->port_usb) {
		spin_unlock_irqrestore(&port->port_lock_ul, flags);
@@ -753,6 +761,8 @@ static void bam2bam_data_connect_work(struct work_struct *w)

	if (d->trans == USB_GADGET_XPORT_BAM2BAM_IPA) {

		d->ipa_params.usb_connection_speed = gadget->speed;

		if (d->dst_pipe_type != USB_BAM_PIPE_BAM2BAM) {
			pr_err("%s: no software preparation for DL not using bam2bam\n",
					__func__);
+35 −0
Original line number Diff line number Diff line
@@ -57,6 +57,34 @@ enum usb_bam_pipe_type {
	USB_BAM_MAX_PIPE_TYPES,
};

/**
* struct usb_bam_connect_ipa_params: Connect Bam pipe to IPA peer infromation.
* @ src_idx: Source pipe index in usb bam pipes lists.
* @ dst_idx: Destination pipe index in usb bam pipes lists.
* @ src_pipe: The source pipe index in the sps level.
* @ dst_pipe: The destination pipe index in the sps level.
* @ keep_ipa_awake: When true, IPA will not be clock gated.
* @ ipa_cons_ep_idx: The pipe index on the IPA peer bam side, consumer.
* @ ipa_prod_ep_idx: The pipe index on the IPA peer bam side, producer.
* @ prod_clnt_hdl: Producer client handle returned by IPA driver
* @ cons_clnt_hdl: Consumer client handle returned by IPA driver
* @ src_client: Source IPA client type.
* @ dst_client: Destination IPA client type.
* @ ipa_ep_cfg: Configuration of IPA end-point (see struct ipa_ep_cfg)
* @priv: Callback cookie to the notify event.
* @notify: Callback on data path event by IPA (see enum ipa_dp_evt_type)
*	 This call back gets back the priv cookie.
*	 for Bam2Bam mode, this callback is in the tethering bridge.
* @ activity_notify: Callback to be notified on and data being pushed into the
*		 USB consumer pipe.
* @ inactivity_notify: Callback to be notified on inactivity of all the current
*		   open pipes between the USB bam and its peer.
* @ skip_ep_cfg: boolean field that determines if Apps-processor
*	            should or should not confiugre this end-point.
*	            (Please see struct teth_bridge_init_params)
* @ reset_pipe_after_lpm: bool to indicate if IPA should reset pipe after LPM.
* @ usb_connection_speed: The actual speed the USB core currently works at.
*/
struct usb_bam_connect_ipa_params {
	u8 src_idx;
	u8 dst_idx;
@@ -81,6 +109,7 @@ struct usb_bam_connect_ipa_params {
	int (*inactivity_notify)(void *priv);
	bool skip_ep_cfg;
	bool reset_pipe_after_lpm;
	enum usb_device_speed usb_connection_speed;
};

/**
@@ -177,6 +206,10 @@ struct usb_bam_pipe_connect {
 * @disable_clk_gating: Disable clock gating
 * @override_threshold: Override the default threshold value for Read/Write
 *                         event generation by the BAM towards another BAM.
 * @max_mbps_highspeed: Maximum Mbits per seconds that the USB core
 *		can work at in bam2bam mode when connected to HS host.
 * @max_mbps_superspeed: Maximum Mbits per seconds that the USB core
 *		can work at in bam2bam mode when connected to SS host.
 */
struct msm_usb_bam_platform_data {
	struct usb_bam_pipe_connect *connections;
@@ -187,6 +220,8 @@ struct msm_usb_bam_platform_data {
	bool reset_on_connect[MAX_BAMS];
	bool disable_clk_gating;
	u32 override_threshold;
	u32 max_mbps_highspeed;
	u32 max_mbps_superspeed;
};

#ifdef CONFIG_USB_BAM