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

Commit 9a03014e authored by Dov Levenglick's avatar Dov Levenglick
Browse files

usb: gadget: allow working with multiple u_bam_data ports simultaneously



This change introduces a mechanism for distributing port
numbers between the different USB function drivers so
that they can work simultaneously.
Currently, only one instance per USB function is supported.
Working with more than one instance of each USB function
may require additional changes.

Change-Id: I00b4ec068519e14a49a8392dc3b35ba89d1307b8
Signed-off-by: default avatarBar Weiner <bweiner@codeaurora.org>
Signed-off-by: default avatarDov Levenglick <dovl@codeaurora.org>
parent dbd2b72e
Loading
Loading
Loading
Loading
+28 −6
Original line number Diff line number Diff line
@@ -711,7 +711,7 @@ static int mbim_bam_setup(int no_ports)

	pr_info("no_ports:%d\n", no_ports);

	ret = bam_data_setup(no_ports);
	ret = bam_data_setup(USB_FUNC_MBIM, no_ports);
	if (ret) {
		pr_err("bam_data_setup failed err: %d\n", ret);
		return ret;
@@ -728,10 +728,14 @@ static int mbim_bam_connect(struct f_mbim *dev)
	struct usb_gadget *gadget = dev->cdev->gadget;
	enum peer_bam bam_name = (dev->xport == USB_GADGET_XPORT_BAM2BAM_IPA) ?
							IPA_P_BAM : A2_P_BAM;
	int port_num;

	pr_info("dev:%p portno:%d\n", dev, dev->port_num);

	ret = bam2bam_data_port_select(MBIM_DEFAULT_PORT);
	port_num = u_bam_data_func_to_port(USB_FUNC_MBIM, MBIM_DEFAULT_PORT);
	if (port_num < 0)
		return port_num;
	ret = bam2bam_data_port_select(port_num);
	if (ret) {
		pr_err("mbim port select failed err: %d\n", ret);
		return ret;
@@ -746,7 +750,10 @@ static int mbim_bam_connect(struct f_mbim *dev)
		return ret;
	}

	ret = bam_data_connect(&dev->bam_port, dev->port_num,
	port_num = u_bam_data_func_to_port(USB_FUNC_MBIM, dev->port_num);
	if (port_num < 0)
		return port_num;
	ret = bam_data_connect(&dev->bam_port, port_num,
		dev->xport, src_connection_idx, dst_connection_idx,
		USB_FUNC_MBIM);

@@ -762,8 +769,13 @@ static int mbim_bam_connect(struct f_mbim *dev)

static int mbim_bam_disconnect(struct f_mbim *dev)
{
	int port_num;

	pr_info("%s - dev:%p port:%d\n", __func__, dev, dev->port_num);
	bam_data_disconnect(&dev->bam_port, dev->port_num);
	port_num = u_bam_data_func_to_port(USB_FUNC_MBIM, dev->port_num);
	if (port_num < 0)
		return port_num;
	bam_data_disconnect(&dev->bam_port, port_num);

	return 0;
}
@@ -1424,6 +1436,7 @@ static void mbim_suspend(struct usb_function *f)
{
	bool remote_wakeup_allowed;
	struct f_mbim	*mbim = func_to_mbim(f);
	int port_num;

	pr_info("mbim suspended\n");

@@ -1449,7 +1462,11 @@ static void mbim_suspend(struct usb_function *f)
	}

	if (remote_wakeup_allowed) {
		bam_data_suspend(MBIM_ACTIVE_PORT);
		port_num = u_bam_data_func_to_port(USB_FUNC_MBIM,
				MBIM_ACTIVE_PORT);
		if (port_num < 0)
			return;
		bam_data_suspend(port_num);
	} else {
		/*
		 * When remote wakeup is disabled, IPA BAM is disconnected
@@ -1475,6 +1492,7 @@ static void mbim_resume(struct usb_function *f)
{
	bool remote_wakeup_allowed;
	struct f_mbim	*mbim = func_to_mbim(f);
	int port_num;

	pr_info("mbim resumed\n");

@@ -1498,7 +1516,11 @@ static void mbim_resume(struct usb_function *f)
	}

	if (remote_wakeup_allowed) {
		bam_data_resume(MBIM_ACTIVE_PORT);
		port_num = u_bam_data_func_to_port(USB_FUNC_MBIM,
						   MBIM_ACTIVE_PORT);
		if (port_num < 0)
			return;
		bam_data_resume(port_num);
	} else {
		/* Restore endpoint descriptors info. */
		mbim->bam_port.in->desc  = mbim->in_ep_desc_backup;
+34 −8
Original line number Diff line number Diff line
@@ -456,8 +456,13 @@ static int ecm_qc_bam_connect(struct f_ecm_qc *dev)
	struct usb_gadget *gadget = cdev->gadget;
	enum peer_bam peer_bam = (dev->xport == USB_GADGET_XPORT_BAM2BAM_IPA) ?
		IPA_P_BAM : A2_P_BAM;
	int port_num;

	ret = bam2bam_data_port_select(ECM_QC_DEFAULT_PORT);
	port_num = (u_bam_data_func_to_port(USB_FUNC_ECM,
					    ECM_QC_DEFAULT_PORT));
	if (port_num < 0)
		return port_num;
	ret = bam2bam_data_port_select(port_num);
	if (ret) {
		pr_err("ecm_qc port select failed with err:%d\n", ret);
		return ret;
@@ -477,8 +482,9 @@ static int ecm_qc_bam_connect(struct f_ecm_qc *dev)
		pr_err("usb_bam_get_connection_idx failed\n");
		return ret;
	}
	ret = bam_data_connect(&dev->bam_port, 0, dev->xport,
		src_connection_idx, dst_connection_idx, USB_FUNC_ECM);
	ret = bam_data_connect(&dev->bam_port, port_num,
		dev->xport, src_connection_idx, dst_connection_idx,
		USB_FUNC_ECM);
	if (ret) {
		pr_err("bam_data_connect failed: err:%d\n", ret);
		return ret;
@@ -495,10 +501,15 @@ static int ecm_qc_bam_connect(struct f_ecm_qc *dev)

static int ecm_qc_bam_disconnect(struct f_ecm_qc *dev)
{
	int port_num;
	pr_debug("%s: dev:%p. Disconnect BAM.\n", __func__, dev);

	bam_data_disconnect(&dev->bam_port, 0);
	__ecm->ecm_mdm_ready_trigger = false;
	port_num = (u_bam_data_func_to_port(USB_FUNC_ECM,
					    ECM_QC_DEFAULT_PORT));
	if (port_num < 0)
		return port_num;
	bam_data_disconnect(&dev->bam_port, port_num);

	return 0;
}
@@ -779,6 +790,7 @@ static void ecm_qc_suspend(struct usb_function *f)
{
	struct f_ecm_qc	*ecm = func_to_ecm_qc(f);
	bool remote_wakeup_allowed;
	int port_num;

	/* Is DATA interface initialized? */
	if (!ecm->data_interface_up) {
@@ -794,7 +806,11 @@ static void ecm_qc_suspend(struct usb_function *f)

	pr_debug("%s(): remote_wakeup:%d\n:", __func__, remote_wakeup_allowed);
	if (remote_wakeup_allowed) {
		bam_data_suspend(ECM_QC_ACTIVE_PORT);
		port_num = (u_bam_data_func_to_port(USB_FUNC_ECM,
						    ECM_QC_ACTIVE_PORT));
		if (port_num < 0)
			return;
		bam_data_suspend(port_num);
	} else {
		/*
		 * When remote wakeup is disabled, IPA BAM is disconnected
@@ -815,6 +831,7 @@ static void ecm_qc_resume(struct usb_function *f)
{
	struct f_ecm_qc	*ecm = func_to_ecm_qc(f);
	bool remote_wakeup_allowed;
	int port_num;

	if (!ecm->data_interface_up) {
		pr_err("%s(): data interface was not up\n", __func__);
@@ -828,7 +845,11 @@ static void ecm_qc_resume(struct usb_function *f)
			f->config->cdev->gadget->remote_wakeup;

	if (remote_wakeup_allowed) {
		bam_data_resume(ECM_QC_ACTIVE_PORT);
		port_num = (u_bam_data_func_to_port(USB_FUNC_ECM,
						    ECM_QC_ACTIVE_PORT));
		if (port_num < 0)
			return;
		bam_data_resume(port_num);
	} else {
		/* Restore endpoint descriptors info. */
		ecm->bam_port.in->desc  = ecm->in_ep_desc_backup;
@@ -882,6 +903,7 @@ static void ecm_qc_close(struct qc_gether *geth)
void ecm_mdm_ready(void)
{
	struct f_ecm_qc *ecm = __ecm;
	int port_num;

	if (!ecm) {
		pr_err("can't set ecm_ready_trigger, no ecm instance\n");
@@ -897,7 +919,11 @@ void ecm_mdm_ready(void)
	ecm->ecm_mdm_ready_trigger = true;
	ecm->is_open = true;
	ecm_qc_notify(ecm);
	bam_data_start_rx_tx(0);
	port_num = (u_bam_data_func_to_port(USB_FUNC_ECM,
					    ECM_QC_ACTIVE_PORT));
	if (port_num < 0)
		return;
	bam_data_start_rx_tx(port_num);
}

/*-------------------------------------------------------------------------*/
@@ -1209,7 +1235,7 @@ static int ecm_qc_init(void)

	pr_debug("initialize ecm qc port instance\n");

	ret = bam_data_setup(ECM_QC_NO_PORTS);
	ret = bam_data_setup(USB_FUNC_ECM, ECM_QC_NO_PORTS);
	if (ret) {
		pr_err("bam_data_setup failed err: %d\n", ret);
		return ret;
+34 −8
Original line number Diff line number Diff line
@@ -425,13 +425,19 @@ static int rndis_qc_bam_connect(struct f_rndis_qc *dev)
	struct usb_gadget *gadget = cdev->gadget;
	enum peer_bam peer_bam = (dev->xport == USB_GADGET_XPORT_BAM2BAM_IPA) ?
		IPA_P_BAM : A2_P_BAM;
	int port_num;

	dev->bam_port.cdev = cdev;
	dev->bam_port.func = &dev->port.func;
	dev->bam_port.in = dev->port.in_ep;
	dev->bam_port.out = dev->port.out_ep;

	ret = bam2bam_data_port_select(RNDIS_QC_ACTIVE_PORT);
	port_num = (u_bam_data_func_to_port(USB_FUNC_RNDIS,
					    RNDIS_QC_ACTIVE_PORT));
	if (port_num < 0)
		return port_num;

	ret = bam2bam_data_port_select(port_num);
	if (ret) {
		pr_err("qc rndis bam port setup failed err:%d\n", ret);
		return ret;
@@ -447,11 +453,11 @@ static int rndis_qc_bam_connect(struct f_rndis_qc *dev)
		return ret;
	}
	if (peer_bam == A2_P_BAM)
		ret = bam_data_connect(&dev->bam_port, 0,
		ret = bam_data_connect(&dev->bam_port, port_num,
			USB_GADGET_XPORT_BAM2BAM, src_connection_idx,
			dst_connection_idx, USB_FUNC_RNDIS);
	else {
		ret = bam_data_connect(&dev->bam_port, 0,
		ret = bam_data_connect(&dev->bam_port, port_num,
			USB_GADGET_XPORT_BAM2BAM_IPA, src_connection_idx,
			dst_connection_idx, USB_FUNC_RNDIS);
		rndis_qc_open(&dev->port);
@@ -469,9 +475,14 @@ static int rndis_qc_bam_connect(struct f_rndis_qc *dev)

static int rndis_qc_bam_disconnect(struct f_rndis_qc *dev)
{
	int port_num;
	pr_debug("dev:%p. %s Disconnect BAM.\n", dev, __func__);

	bam_data_disconnect(&dev->bam_port, 0);
	port_num = (u_bam_data_func_to_port(USB_FUNC_RNDIS,
					    RNDIS_QC_ACTIVE_PORT));
	if (port_num < 0)
		return port_num;
	bam_data_disconnect(&dev->bam_port, port_num);

	return 0;
}
@@ -815,6 +826,7 @@ static void rndis_qc_suspend(struct usb_function *f)
{
	struct f_rndis_qc	*rndis = func_to_rndis_qc(f);
	bool remote_wakeup_allowed;
	int port_num;

	if (f->config->cdev->gadget->speed == USB_SPEED_SUPER)
		remote_wakeup_allowed = f->func_wakeup_allowed;
@@ -825,7 +837,11 @@ static void rndis_qc_suspend(struct usb_function *f)
					__func__, remote_wakeup_allowed);

	if (remote_wakeup_allowed) {
		bam_data_suspend(RNDIS_QC_ACTIVE_PORT);
		port_num = (u_bam_data_func_to_port(USB_FUNC_RNDIS,
					    RNDIS_QC_ACTIVE_PORT));
		if (port_num < 0)
			return;
		bam_data_suspend(port_num);
	} else {
		/*
		 * When remote wakeup is disabled, IPA BAM is disconnected
@@ -853,6 +869,7 @@ static void rndis_qc_resume(struct usb_function *f)
{
	struct f_rndis_qc	*rndis = func_to_rndis_qc(f);
	bool remote_wakeup_allowed;
	int port_num;

	pr_debug("%s: rndis resumed\n", __func__);

@@ -868,7 +885,11 @@ static void rndis_qc_resume(struct usb_function *f)
		remote_wakeup_allowed = f->config->cdev->gadget->remote_wakeup;

	if (remote_wakeup_allowed) {
		bam_data_resume(RNDIS_QC_ACTIVE_PORT);
		port_num = (u_bam_data_func_to_port(USB_FUNC_RNDIS,
						    RNDIS_QC_ACTIVE_PORT));
		if (port_num < 0)
			return;
		bam_data_resume(port_num);
	} else {
		/* Restore endpoint descriptors info. */
		rndis->bam_port.in->desc  = rndis->in_ep_desc_backup;
@@ -1140,6 +1161,7 @@ void rndis_net_ready_notify(void)
{
	struct f_rndis_qc *rndis;
	unsigned long flags;
	int port_num;

	spin_lock_irqsave(&rndis_lock, flags);
	rndis = _rndis_qc;
@@ -1157,7 +1179,11 @@ void rndis_net_ready_notify(void)
	pr_debug("%s: Set net_ready_trigger", __func__);
	rndis->net_ready_trigger = true;
	spin_unlock_irqrestore(&rndis_lock, flags);
	bam_data_start_rx_tx(0);
	port_num = (u_bam_data_func_to_port(USB_FUNC_RNDIS,
					    RNDIS_QC_ACTIVE_PORT));
	if (port_num < 0)
		return;
	bam_data_start_rx_tx(port_num);
}


@@ -1424,7 +1450,7 @@ static int rndis_qc_init(void)
		pr_err("rndis QC driver failed to register\n");
	spin_lock_init(&rndis_lock);

	ret = bam_data_setup(RNDIS_QC_NO_PORTS);
	ret = bam_data_setup(USB_FUNC_RNDIS, RNDIS_QC_NO_PORTS);
	if (ret) {
		pr_err("bam_data_setup failed err: %d\n", ret);
		return ret;
+16 −5
Original line number Diff line number Diff line
@@ -26,7 +26,6 @@

#include "u_bam_data.h"

#define BAM2BAM_DATA_N_PORTS	1
#define BAM_DATA_RX_Q_SIZE	128
#define BAM_DATA_MUX_RX_REQ_SIZE  2048   /* Must be 1KB aligned */
#define BAM_DATA_PENDING_LIMIT	220
@@ -1270,6 +1269,16 @@ out:
	spin_unlock_irqrestore(&port->port_lock, flags);
}

inline int u_bam_data_func_to_port(enum function_type func, u8 func_port)
{
	if (func >= USB_NUM_FUNCS || func_port >= PORTS_PER_FUNC) {
		pr_err("func=%d and func_port=%d are an illegal combination\n",
			func, func_port);
		return -EINVAL;
	}
	return (PORTS_PER_FUNC * func) + func_port;
}

static int bam2bam_data_port_alloc(int portno)
{
	struct bam_data_port    *port = NULL;
@@ -1671,21 +1680,23 @@ exit:
	return ret;
}

int bam_data_setup(unsigned int no_bam2bam_port)
int bam_data_setup(enum function_type func, unsigned int no_bam2bam_port)
{
	int	i;
	int	ret;

	pr_debug("requested %d BAM2BAM ports", no_bam2bam_port);

	if (!no_bam2bam_port || no_bam2bam_port > BAM2BAM_DATA_N_PORTS) {
		pr_err("Invalid num of ports count:%d\n", no_bam2bam_port);
	if (!no_bam2bam_port || no_bam2bam_port > PORTS_PER_FUNC ||
		func >= USB_NUM_FUNCS) {
		pr_err("Invalid num of ports count:%d or function type:%d\n",
			no_bam2bam_port, func);
		return -EINVAL;
	}

	for (i = 0; i < no_bam2bam_port; i++) {
		n_bam2bam_data_ports++;
		ret = bam2bam_data_port_alloc(i);
		ret = bam2bam_data_port_alloc(u_bam_data_func_to_port(func, i));
		if (ret) {
			n_bam2bam_data_ports--;
			pr_err("Failed to alloc port:%d\n", i);
+7 −1
Original line number Diff line number Diff line
@@ -19,8 +19,12 @@ enum function_type {
	USB_FUNC_ECM,
	USB_FUNC_MBIM,
	USB_FUNC_RNDIS,
	USB_NUM_FUNCS,
};

#define PORTS_PER_FUNC 1
#define BAM2BAM_DATA_N_PORTS (USB_NUM_FUNCS * PORTS_PER_FUNC)

struct data_port {
	struct usb_composite_dev	*cdev;
	struct usb_function		*func;
@@ -39,7 +43,7 @@ int bam_data_connect(struct data_port *gr, u8 port_num,
	enum transport_type trans, u8 src_connection_idx,
	u8 dst_connection_idx, enum function_type func);

int bam_data_setup(unsigned int no_bam2bam_port);
int bam_data_setup(enum function_type func, unsigned int no_bam2bam_port);

void bam_data_flush_workqueue(void);

@@ -59,4 +63,6 @@ void u_bam_data_stop_rndis_ipa(void);

void bam_data_start_rx_tx(u8 port_num);

int u_bam_data_func_to_port(enum function_type func, u8 func_port);

#endif /* __U_BAM_DATA_H */