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

Commit 8b000bf2 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: diag: fix read/write race with unbind"

parents fac2b313 dde93857
Loading
Loading
Loading
Loading
+24 −4
Original line number Diff line number Diff line
@@ -422,6 +422,7 @@ int usb_diag_read(struct usb_diag_ch *ch, struct diag_request *d_req)
	struct diag_context *ctxt = ch->priv_usb;
	unsigned long flags;
	struct usb_request *req;
	struct usb_ep *out;
	static DEFINE_RATELIMIT_STATE(rl, 10*HZ, 1);

	if (!ctxt)
@@ -429,11 +430,13 @@ int usb_diag_read(struct usb_diag_ch *ch, struct diag_request *d_req)

	spin_lock_irqsave(&ctxt->lock, flags);

	if (!ctxt->configured) {
	if (!ctxt->configured || !ctxt->out) {
		spin_unlock_irqrestore(&ctxt->lock, flags);
		return -EIO;
	}

	out = ctxt->out;

	if (list_empty(&ctxt->read_pool)) {
		spin_unlock_irqrestore(&ctxt->lock, flags);
		ERROR(ctxt->cdev, "%s: no requests available\n", __func__);
@@ -447,7 +450,14 @@ int usb_diag_read(struct usb_diag_ch *ch, struct diag_request *d_req)
	req->buf = d_req->buf;
	req->length = d_req->length;
	req->context = d_req;
	if (usb_ep_queue(ctxt->out, req, GFP_ATOMIC)) {

	/* make sure context is still valid after releasing lock */
	if (ctxt != ch->priv_usb) {
		usb_ep_free_request(out, req);
		return -EIO;
	}

	if (usb_ep_queue(out, req, GFP_ATOMIC)) {
		/* If error add the link to linked list again*/
		spin_lock_irqsave(&ctxt->lock, flags);
		list_add_tail(&req->list, &ctxt->read_pool);
@@ -481,6 +491,7 @@ int usb_diag_write(struct usb_diag_ch *ch, struct diag_request *d_req)
	struct diag_context *ctxt = ch->priv_usb;
	unsigned long flags;
	struct usb_request *req = NULL;
	struct usb_ep *in;
	static DEFINE_RATELIMIT_STATE(rl, 10*HZ, 1);

	if (!ctxt)
@@ -488,11 +499,13 @@ int usb_diag_write(struct usb_diag_ch *ch, struct diag_request *d_req)

	spin_lock_irqsave(&ctxt->lock, flags);

	if (!ctxt->configured) {
	if (!ctxt->configured || !ctxt->in) {
		spin_unlock_irqrestore(&ctxt->lock, flags);
		return -EIO;
	}

	in = ctxt->in;

	if (list_empty(&ctxt->write_pool)) {
		spin_unlock_irqrestore(&ctxt->lock, flags);
		ERROR(ctxt->cdev, "%s: no requests available\n", __func__);
@@ -506,7 +519,14 @@ int usb_diag_write(struct usb_diag_ch *ch, struct diag_request *d_req)
	req->buf = d_req->buf;
	req->length = d_req->length;
	req->context = d_req;
	if (usb_ep_queue(ctxt->in, req, GFP_ATOMIC)) {

	/* make sure context is still valid after releasing lock */
	if (ctxt != ch->priv_usb) {
		usb_ep_free_request(in, req);
		return -EIO;
	}

	if (usb_ep_queue(in, req, GFP_ATOMIC)) {
		/* If error add the link to linked list again*/
		spin_lock_irqsave(&ctxt->lock, flags);
		list_add_tail(&req->list, &ctxt->write_pool);