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

Commit 8059ceb1 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: u_bam_data: get rid of bam rndis state"

parents 241d6d0f fcb4e34b
Loading
Loading
Loading
Loading
+72 −128
Original line number Diff line number Diff line
@@ -66,7 +66,6 @@ struct rndis_data_ch_info {
	u32 prod_clnt_hdl;
	u32 cons_clnt_hdl;
	void *priv;
	bool adaptor_disable;
};

struct sys2ipa_sw_data {
@@ -127,18 +126,8 @@ enum u_bam_data_event_type {
	U_BAM_DATA_RESUME_E
};

/*
 * Used exclusively for RNDIS adpator enable/disable
 * operation performed on host machine.
 */
enum u_bam_rndis_state {
	RNDIS_DISCONNECT = 0,
	RNDIS_SOFT_DISABLE,
	RNDIS_SOFT_ENABLE
};

struct bam_data_port {
	bool                            is_connected;
	bool                            is_ipa_connected;
	enum u_bam_data_event_type	last_event;
	unsigned			port_num;
	spinlock_t			port_lock;
@@ -150,7 +139,6 @@ struct bam_data_port {
	struct work_struct		disconnect_w;
	struct work_struct		suspend_w;
	struct work_struct		resume_w;
	enum u_bam_rndis_state		rndis_s;
};
struct  usb_bam_data_connect_info {
	u32 usb_bam_pipe_idx;
@@ -797,17 +785,12 @@ static void bam2bam_data_disconnect_work(struct work_struct *w)

	spin_lock_irqsave(&port->port_lock, flags);

	if (!port->is_connected) {
	if (!port->is_ipa_connected) {
		pr_debug("%s: Already disconnected. Bailing out.\n", __func__);
		spin_unlock_irqrestore(&port->port_lock, flags);
		return;
	}

	/*
	 * Mark port as disconnected, to maintaine this driver state,
	 * even if there gonna be errors down in this function.
	 */
	port->is_connected = false;
	d = &port->data_ch;

	/*
@@ -828,6 +811,10 @@ static void bam2bam_data_disconnect_work(struct work_struct *w)
			pr_err("usb_bam_disconnect_ipa failed: err:%d\n", ret);
	}

	spin_lock_irqsave(&port->port_lock, flags);
	port->is_ipa_connected = false;
	spin_unlock_irqrestore(&port->port_lock, flags);

	pr_debug("Disconnect workqueue done (port %p)\n", port);
}
/*
@@ -878,7 +865,6 @@ static void bam2bam_data_connect_work(struct work_struct *w)
	u32			sps_params;
	int			ret;
	unsigned long		flags;
	bool			enable_eps = true;

	pr_debug("%s: Connect workqueue started", __func__);

@@ -887,8 +873,7 @@ static void bam2bam_data_connect_work(struct work_struct *w)
	d = &port->data_ch;
	d_port = port->port_usb;

	if (port->rndis_s == RNDIS_DISCONNECT &&
		port->last_event == U_BAM_DATA_DISCONNECT_E) {
	if (port->last_event == U_BAM_DATA_DISCONNECT_E) {
		pr_debug("%s: Port is about to disconnect. Bail out.\n",
			__func__);
		spin_unlock_irqrestore(&port->port_lock, flags);
@@ -916,70 +901,6 @@ static void bam2bam_data_connect_work(struct work_struct *w)
		return;
	}

	/*
	 * Disabling RNDIS network adaptor disable/enable performs
	 * USB IPA disconect and connect respectively. This particular
	 * check makes sure that when we re-enable USB eps are not
	 * re-renabled.
	*/
	if (d->trans == USB_GADGET_XPORT_BAM2BAM_IPA &&
		d->func_type == USB_FUNC_RNDIS &&
		port->rndis_s == RNDIS_SOFT_ENABLE)
			enable_eps = false;

	if (enable_eps) {

		if (d->trans == USB_GADGET_XPORT_BAM2BAM_IPA &&
			d->src_pipe_type == USB_BAM_PIPE_SYS2BAM) {

			/* UL workaround requirements */
			skb_queue_head_init(&d->rx_skb_q);
			skb_queue_head_init(&d->rx_skb_idle);
			INIT_LIST_HEAD(&d->rx_idle);

			ret = bam_data_sys2bam_alloc_req(port, false);
			if (ret) {
				spin_unlock_irqrestore(&port->port_lock, flags);
				pr_err("%s: sys2bam_alloc_req failed(%d)",
								__func__, ret);
				return;
			}
		}

		d->rx_req = usb_ep_alloc_request(port->port_usb->out,
								GFP_ATOMIC);
		if (!d->rx_req) {
			bam_data_free_reqs(port);
			spin_unlock_irqrestore(&port->port_lock, flags);
			pr_err("%s: failed to allocate rx_req\n", __func__);
			return;
		}
		d->rx_req->context = port;
		d->rx_req->complete = bam_data_endless_rx_complete;
		d->rx_req->length = 0;
		d->rx_req->no_interrupt = 1;

		d->tx_req = usb_ep_alloc_request(port->port_usb->in,
								GFP_ATOMIC);
		if (!d->tx_req) {
			usb_ep_free_request(port->port_usb->out, d->rx_req);
			bam_data_free_reqs(port);
			spin_unlock_irqrestore(&port->port_lock, flags);
			pr_err("%s: failed to allocate tx_req\n", __func__);
			return;
		}

		d->tx_req->context = port;
		d->tx_req->complete = bam_data_endless_tx_complete;
		d->tx_req->length = 0;
		d->tx_req->no_interrupt = 1;
	}
	/*
	 * Mark port as connected, to maintaine this driver state,
	 * even if there gonna be errors down in this function.
	 */
	port->is_connected = true;

	if (d->trans == USB_GADGET_XPORT_BAM2BAM_IPA) {

		d->ipa_params.usb_connection_speed = gadget->speed;
@@ -1045,8 +966,7 @@ static void bam2bam_data_connect_work(struct work_struct *w)
		}

		spin_lock_irqsave(&port->port_lock, flags);
		if (port->rndis_s == RNDIS_DISCONNECT &&
			port->last_event ==  U_BAM_DATA_DISCONNECT_E) {
		if (port->last_event ==  U_BAM_DATA_DISCONNECT_E) {
			spin_unlock_irqrestore(&port->port_lock, flags);
			pr_err("%s:%d: Port is being disconnected.\n",
						__func__, __LINE__);
@@ -1109,14 +1029,15 @@ static void bam2bam_data_connect_work(struct work_struct *w)
		 * spinlock and re-enabling IRQs. Hence check again.
		 */
		spin_lock_irqsave(&port->port_lock, flags);
		if (port->rndis_s == RNDIS_DISCONNECT &&
			port->last_event ==  U_BAM_DATA_DISCONNECT_E) {
		if (port->last_event ==  U_BAM_DATA_DISCONNECT_E) {
			spin_unlock_irqrestore(&port->port_lock, flags);
			pr_err("%s:%d: port is beind disconnected.\n",
						__func__, __LINE__);
			goto disconnect_ipa;
		}

		port->is_ipa_connected = true;

		d_port->ipa_producer_ep = d->ipa_params.ipa_prod_ep_idx;
		pr_debug("%s(): ipa_producer_ep:%d ipa_consumer_ep:%d\n",
				__func__, d_port->ipa_producer_ep,
@@ -1309,7 +1230,7 @@ void bam_data_start_rx_tx(u8 port_num)
			d->rx_req, d->tx_req);
		goto out;
	}
	if (!port->is_connected) {
	if (!port->is_ipa_connected) {
		pr_debug("%s: pipes are disconnected", __func__);
		goto out;
	}
@@ -1365,8 +1286,7 @@ int bam2bam_data_port_select(int portno)

	port = bam2bam_data_ports[portno];
	port->port_num  = portno;
	port->is_connected = false;
	port->rndis_s = RNDIS_DISCONNECT;
	port->is_ipa_connected = false;

	spin_lock_init(&port->port_lock);

@@ -1401,18 +1321,11 @@ void u_bam_data_start_rndis_ipa(void)
{
	pr_debug("%s\n", __func__);

	if (!is_ipa_rndis_net_on) {
		int port_num = u_bam_data_func_to_port(USB_FUNC_RNDIS,
							RNDIS_QC_ACTIVE_PORT);
		struct bam_data_port *port = bam2bam_data_ports[port_num];

		if (port->rndis_s == RNDIS_SOFT_DISABLE)
			port->rndis_s = RNDIS_SOFT_ENABLE;
	if (!is_ipa_rndis_net_on)
		queue_work(bam_data_wq, rndis_conn_w);
	} else {
	else
		pr_debug("%s: Transfers already started?\n", __func__);
}
}

void u_bam_data_stop_rndis_ipa(void)
{
@@ -1425,9 +1338,8 @@ void u_bam_data_stop_rndis_ipa(void)

		rndis_ipa_reset_trigger();
		bam_data_stop_endless_tx(port);
		port->rndis_s = RNDIS_SOFT_DISABLE;
		rndis_data.adaptor_disable = true;
		bam_data_disconnect(port->port_usb, port_num);
		if (port->is_ipa_connected)
			queue_work(bam_data_wq, &port->disconnect_w);
	}
}

@@ -1456,7 +1368,6 @@ void bam_data_disconnect(struct data_port *gr, u8 port_num)
	struct bam_data_ch_info	*d;
	struct sk_buff *skb = NULL;
	unsigned long flags;
	bool disable_eps = true;

	pr_debug("dev:%p port number:%d\n", gr, port_num);

@@ -1481,25 +1392,7 @@ void bam_data_disconnect(struct data_port *gr, u8 port_num)

	d = &port->data_ch;

	/*
	 * Flag disable_eps and rndis_s state as RNDIS_SOFT_DISABLE are
	 * being used to detect that this API is being called due to
	 * performing RNDIS adaptor disable on host. In normal case,
	 * disable_eps would be always false, which would make sure to
	 * perform disconnect sequeunce.
	 */
	if (d->trans == USB_GADGET_XPORT_BAM2BAM_IPA &&
		d->func_type == USB_FUNC_RNDIS) {
		if (rndis_data.adaptor_disable &&
			port->rndis_s == RNDIS_SOFT_DISABLE) {
			disable_eps = false;
			rndis_data.adaptor_disable = false;
		} else {
			port->rndis_s = RNDIS_DISCONNECT;
		}
	}

	if (port->port_usb && disable_eps) {
	if (port->port_usb) {
		if (d->trans == USB_GADGET_XPORT_BAM2BAM_IPA) {
			port->port_usb->ipa_consumer_ep = -1;
			port->port_usb->ipa_producer_ep = -1;
@@ -1686,10 +1579,50 @@ int bam_data_connect(struct data_port *gr, u8 port_num,
	ret = usb_ep_enable(gr->out);
	if (ret) {
		pr_err("usb_ep_enable failed eptype:OUT ep:%p", gr->out);
		gr->in->driver_data = 0;
		goto exit;
		goto disable_in_ep;
	}

	gr->out->driver_data = port;

	if (d->trans == USB_GADGET_XPORT_BAM2BAM_IPA &&
		d->src_pipe_type == USB_BAM_PIPE_SYS2BAM) {

		/* UL workaround requirements */
		skb_queue_head_init(&d->rx_skb_q);
		skb_queue_head_init(&d->rx_skb_idle);
		INIT_LIST_HEAD(&d->rx_idle);

		ret = bam_data_sys2bam_alloc_req(port, false);
		if (ret) {
			pr_err("%s: sys2bam_alloc_req failed(%d)",
							__func__, ret);
			goto disable_out_ep;
		}
	}

	d->rx_req = usb_ep_alloc_request(port->port_usb->out,
							GFP_ATOMIC);
	if (!d->rx_req) {
		pr_err("%s: failed to allocate rx_req\n", __func__);
		goto bam_data_free;
	}
	d->rx_req->context = port;
	d->rx_req->complete = bam_data_endless_rx_complete;
	d->rx_req->length = 0;
	d->rx_req->no_interrupt = 1;

	d->tx_req = usb_ep_alloc_request(port->port_usb->in,
							GFP_ATOMIC);
	if (!d->tx_req) {
		pr_err("%s: failed to allocate tx_req\n", __func__);
		goto ep_out_req_free;
	}

	d->tx_req->context = port;
	d->tx_req->complete = bam_data_endless_tx_complete;
	d->tx_req->length = 0;
	d->tx_req->no_interrupt = 1;

	gr->out->driver_data = port;
	if (d->trans == USB_GADGET_XPORT_BAM2BAM_IPA && d->func_type ==
		USB_FUNC_RNDIS) {
@@ -1701,8 +1634,19 @@ int bam_data_connect(struct data_port *gr, u8 port_num,

	port->last_event = U_BAM_DATA_CONNECT_E;
	queue_work(bam_data_wq, &port->connect_w);
	ret = 0;
	spin_unlock_irqrestore(&port->port_lock, flags);
	return 0;

ep_out_req_free:
	usb_ep_free_request(port->port_usb->out, d->rx_req);
bam_data_free:
	bam_data_free_reqs(port);
disable_out_ep:
	gr->out->driver_data = 0;
	usb_ep_disable(gr->out);
disable_in_ep:
	gr->in->driver_data = 0;
	usb_ep_disable(gr->in);
exit:
	spin_unlock_irqrestore(&port->port_lock, flags);
	return ret;