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

Commit b9d39fdb authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "usb: gadget: allow working with multiple u_bam_data ports simultaneously"

parents e99e38b3 9a03014e
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 {
		/* This is required as Linux host side RNDIS driver doesn't
		 * send RNDIS_MESSAGE_PACKET_FILTER before suspending USB bus.
@@ -861,6 +877,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__);

@@ -876,7 +893,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;
@@ -1156,6 +1177,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;
@@ -1173,7 +1195,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);
}


@@ -1440,7 +1466,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 */