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

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

Merge "USB: f_qc_rndis: Add spinlock protection whereever required"

parents 327993e9 22d6ccbd
Loading
Loading
Loading
Loading
+39 −13
Original line number Diff line number Diff line
@@ -493,17 +493,26 @@ static void rndis_qc_response_available(void *_rndis)
static void rndis_qc_response_complete(struct usb_ep *ep,
					struct usb_request *req)
{
	struct f_rndis_qc		*rndis = req->context;
	struct f_rndis_qc		*rndis;
	int				status = req->status;
	struct usb_composite_dev	*cdev;
	struct usb_ep *notify_ep;

	spin_lock(&rndis_lock);
	rndis = _rndis_qc;
	if (!rndis || !rndis->notify || !rndis->notify->driver_data) {
		spin_unlock(&rndis_lock);
		return;
	}

	if (!rndis->port.func.config || !rndis->port.func.config->cdev) {
		pr_err("%s(): cdev or config is NULL.\n", __func__);
		spin_unlock(&rndis_lock);
		return;
	} else {
		cdev = rndis->port.func.config->cdev;
	}

	cdev = rndis->port.func.config->cdev;

	/* after TX:
	 *  - USB_CDC_GET_ENCAPSULATED_RESPONSE (ep0/control)
	 *  - RNDIS_RESPONSE_AVAILABLE (status/irq)
@@ -513,7 +522,7 @@ static void rndis_qc_response_complete(struct usb_ep *ep,
	case -ESHUTDOWN:
		/* connection gone */
		atomic_set(&rndis->notify_count, 0);
		break;
		goto out;
	default:
		pr_info("RNDIS %s response error %d, %d/%d\n",
			ep->name, status,
@@ -521,20 +530,30 @@ static void rndis_qc_response_complete(struct usb_ep *ep,
		/* FALLTHROUGH */
	case 0:
		if (ep != rndis->notify)
			break;
			goto out;

		/* handle multiple pending RNDIS_RESPONSE_AVAILABLE
		 * notifications by resending until we're done
		 */
		if (atomic_dec_and_test(&rndis->notify_count))
			break;
		status = usb_ep_queue(rndis->notify, req, GFP_ATOMIC);
			goto out;
		notify_ep = rndis->notify;
		spin_unlock(&rndis_lock);
		status = usb_ep_queue(notify_ep, req, GFP_ATOMIC);
		if (status) {
			atomic_dec(&rndis->notify_count);
			spin_lock(&rndis_lock);
			if (!_rndis_qc)
				goto out;
			atomic_dec(&_rndis_qc->notify_count);
			DBG(cdev, "notify/1 --> %d\n", status);
			spin_unlock(&rndis_lock);
		}
		break;
	}

	return;

out:
	spin_unlock(&rndis_lock);
}

static void rndis_qc_command_complete(struct usb_ep *ep,
@@ -545,6 +564,13 @@ static void rndis_qc_command_complete(struct usb_ep *ep,
	rndis_init_msg_type		*buf;
	u32		ul_max_xfer_size, dl_max_xfer_size;

	spin_lock(&rndis_lock);
	rndis = _rndis_qc;
	if (!rndis || !rndis->notify || !rndis->notify->driver_data) {
		spin_unlock(&rndis_lock);
		return;
	}

	/* received RNDIS command from USB_CDC_SEND_ENCAPSULATED_COMMAND */
	status = rndis_msg_parser(rndis->config, (u8 *) req->buf);
	if (status < 0)
@@ -573,6 +599,7 @@ static void rndis_qc_command_complete(struct usb_ep *ep,
				rndis_get_dl_max_xfer_size(rndis->config);
		u_bam_data_set_dl_max_xfer_size(dl_max_xfer_size);
	}
	spin_unlock(&rndis_lock);
}

static int
@@ -751,13 +778,16 @@ static void rndis_qc_disable(struct usb_function *f)
{
	struct f_rndis_qc		*rndis = func_to_rndis_qc(f);
	struct usb_composite_dev *cdev = f->config->cdev;
	unsigned long flags;

	if (!rndis->notify->driver_data)
		return;

	pr_info("rndis deactivated\n");

	spin_lock_irqsave(&rndis_lock, flags);
	rndis_uninit(rndis->config);
	spin_unlock_irqrestore(&rndis_lock, flags);
	bam_data_disconnect(&rndis->bam_port, USB_FUNC_RNDIS, rndis->port_num);
	if (rndis->xport != USB_GADGET_XPORT_BAM2BAM_IPA)
		gether_qc_disconnect_name(&rndis->port, "rndis0");
@@ -1079,18 +1109,14 @@ rndis_qc_unbind(struct usb_configuration *c, struct usb_function *f)
void rndis_ipa_reset_trigger(void)
{
	struct f_rndis_qc *rndis;
	unsigned long flags;

	spin_lock_irqsave(&rndis_lock, flags);
	rndis = _rndis_qc;
	if (!rndis) {
		pr_err("%s: No RNDIS instance", __func__);
		spin_unlock_irqrestore(&rndis_lock, flags);
		return;
	}

	rndis->net_ready_trigger = false;
	spin_unlock_irqrestore(&rndis_lock, flags);
}

/*