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

Commit 8472ae67 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: Don't call IPA functions's disconnect from atomic context"

parents f5bd9728 67640d5e
Loading
Loading
Loading
Loading
+10 −1
Original line number Diff line number Diff line
@@ -1102,8 +1102,17 @@ ecm_qc_unbind(struct usb_configuration *c, struct usb_function *f)

	ecm_qc_string_defs[1].s = NULL;

	if (ecm->xport == USB_GADGET_XPORT_BAM2BAM_IPA)
	if (ecm->xport == USB_GADGET_XPORT_BAM2BAM_IPA) {
		/*
		 * call flush_workqueue to make sure that any pending
		 * disconnect_work() from u_bam_data.c file is being
		 * flushed before calling this rndis_ipa_cleanup API
		 * as rndis ipa disconnect API is required to be
		 * called before this.
		 */
		bam_data_flush_workqueue();
		ecm_ipa_cleanup(ipa_params.private);
	}

	kfree(ecm);
	__ecm = NULL;
+8 −0
Original line number Diff line number Diff line
@@ -1137,6 +1137,14 @@ rndis_qc_unbind(struct usb_configuration *c, struct usb_function *f)
	usb_ep_free_request(rndis->notify, rndis->notify_req);

	if (rndis->xport == USB_GADGET_XPORT_BAM2BAM_IPA) {
		/*
		 * call flush_workqueue to make sure that any pending
		 * disconnect_work() from u_bam_data.c file is being
		 * flushed before calling this rndis_ipa_cleanup API
		 * as rndis ipa disconnect API is required to be
		 * called before this.
		 */
		bam_data_flush_workqueue();
		rndis_ipa_cleanup(rndis_ipa_params.private);
		rndis_ipa_supported = false;
	}
+42 −33
Original line number Diff line number Diff line
@@ -727,6 +727,45 @@ static void bam2bam_free_rx_skb_idle_list(struct bam_data_port *port)
							d->freed_skb);
}

/*
 * bam_data_ipa_disconnect()- Perform USB IPA function level disconnect
 * struct bam_data_ch_info - Per USB IPA port data structure
 *
 * Make sure to call IPA rndis/ecm/mbim related disconnect APIs() only
 * if those APIs init counterpart is already performed.
 * MBIM: teth_bridge_connect() is NO_OPS and teth_bridge_init() is
 * being called with atomic context on cable connect, hence there is no
 * need to consider for this check. is_net_interface_up is being used
 * for RNDIS/ECM driver due to its different design with usage of
 * network interface created by IPA driver.
 */
static void bam_data_ipa_disconnect(struct bam_data_ch_info *d)
{
	pr_debug("%s(): is_net_interface_up:%d\n",
		__func__, atomic_read(&d->is_net_interface_up));
	/*
	 * Check if is_net_interface_up is set to 1, then perform disconnect
	 * part and set is_net_interface_up to zero.
	 */
	if (atomic_xchg(&d->is_net_interface_up, 0) == 1) {
		void *priv;
		if (d->func_type == USB_FUNC_ECM) {
			priv = ecm_qc_get_ipa_priv();
			ecm_ipa_disconnect(priv);
		} else if (d->func_type == USB_FUNC_RNDIS) {
			priv = rndis_qc_get_ipa_priv();
			rndis_ipa_pipe_disconnect_notify(priv);
			is_ipa_rndis_net_on = false;
		}
		pr_debug("%s(): net interface is disconnected.\n", __func__);
	}

	if (d->func_type == USB_FUNC_MBIM) {
		pr_debug("%s(): teth_bridge() disconnected\n", __func__);
		teth_bridge_disconnect(d->ipa_params.src_client);
	}
}

static void bam2bam_data_disconnect_work(struct work_struct *w)
{
	struct bam_data_port *port =
@@ -748,6 +787,7 @@ static void bam2bam_data_disconnect_work(struct work_struct *w)
	 * even if there gonna be errors down in this function.
	 */
	port->is_connected = false;
	d = &port->data_ch;

	/*
	 * Unlock the port here and not at the end of this work,
@@ -759,8 +799,9 @@ static void bam2bam_data_disconnect_work(struct work_struct *w)
	*/
	spin_unlock_irqrestore(&port->port_lock, flags);

	d = &port->data_ch;
	if (d->trans == USB_GADGET_XPORT_BAM2BAM_IPA) {
		/* Perform IPA functions' disconnect */
		bam_data_ipa_disconnect(d);
		ret = usb_bam_disconnect_ipa(&d->ipa_params);
		if (ret)
			pr_err("usb_bam_disconnect_ipa failed: err:%d\n", ret);
@@ -1514,39 +1555,7 @@ void bam_data_disconnect(struct data_port *gr, u8 port_num)
		}
	}

	/*
	 * Make sure to call IPA rndis/ecm/mbim related disconnect APIs() only
	 * if those APIs init counterpart is already performed.
	 * MBIM: teth_bridge_connect() is NO_OPS and teth_bridge_init() is
	 * being called with atomic context on cable connect, hence there is no
	 * need to consider for this check. is_net_interface_up is being used
	 * for RNDIS/ECM driver due to its different design with usage of
	 * network interface created by IPA driver.
	 */
	if (d->trans == USB_GADGET_XPORT_BAM2BAM_IPA) {
		pr_debug("%s(): is_net_interface_up:%d\n",
			__func__, atomic_read(&d->is_net_interface_up));
		if (atomic_read(&d->is_net_interface_up)) {
			void *priv;

			if (d->func_type == USB_FUNC_ECM) {
				priv = ecm_qc_get_ipa_priv();
				ecm_ipa_disconnect(priv);
			} else if (d->func_type == USB_FUNC_RNDIS) {
				priv = rndis_qc_get_ipa_priv();
				rndis_ipa_pipe_disconnect_notify(priv);
				is_ipa_rndis_net_on = false;
			}
			pr_debug("%s(): net interface is disconnected.\n",
								__func__);
			atomic_set(&d->is_net_interface_up, 0);
		}

		if (d->func_type == USB_FUNC_MBIM) {
			pr_debug("%s(): teth_bridge() disconnected\n",
								__func__);
			teth_bridge_disconnect(d->ipa_params.src_client);
		}
		port->last_event = U_BAM_DATA_DISCONNECT_E;
		queue_work(bam_data_wq, &port->disconnect_w);
	} else {