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

Commit 762f007b authored by Jarek Poplawski's avatar Jarek Poplawski Committed by Greg Kroah-Hartman
Browse files

USB: fix cdc-acm problems with hard irq? (inconsistent lock state)

parent a7a0c9cd
Loading
Loading
Loading
Loading
+13 −13
Original line number Diff line number Diff line
@@ -325,7 +325,7 @@ static void acm_rx_tasklet(unsigned long _acm)
	struct acm_rb *buf;
	struct tty_struct *tty = acm->tty;
	struct acm_ru *rcv;
	//unsigned long flags;
	unsigned long flags;
	int i = 0;
	dbg("Entering acm_rx_tasklet");

@@ -333,15 +333,15 @@ static void acm_rx_tasklet(unsigned long _acm)
		return;

next_buffer:
	spin_lock(&acm->read_lock);
	spin_lock_irqsave(&acm->read_lock, flags);
	if (list_empty(&acm->filled_read_bufs)) {
		spin_unlock(&acm->read_lock);
		spin_unlock_irqrestore(&acm->read_lock, flags);
		goto urbs;
	}
	buf = list_entry(acm->filled_read_bufs.next,
			 struct acm_rb, list);
	list_del(&buf->list);
	spin_unlock(&acm->read_lock);
	spin_unlock_irqrestore(&acm->read_lock, flags);

	dbg("acm_rx_tasklet: procesing buf 0x%p, size = %d", buf, buf->size);

@@ -356,29 +356,29 @@ next_buffer:
		memmove(buf->base, buf->base + i, buf->size - i);
		buf->size -= i;
		spin_unlock(&acm->throttle_lock);
		spin_lock(&acm->read_lock);
		spin_lock_irqsave(&acm->read_lock, flags);
		list_add(&buf->list, &acm->filled_read_bufs);
		spin_unlock(&acm->read_lock);
		spin_unlock_irqrestore(&acm->read_lock, flags);
		return;
	}
	spin_unlock(&acm->throttle_lock);

	spin_lock(&acm->read_lock);
	spin_lock_irqsave(&acm->read_lock, flags);
	list_add(&buf->list, &acm->spare_read_bufs);
	spin_unlock(&acm->read_lock);
	spin_unlock_irqrestore(&acm->read_lock, flags);
	goto next_buffer;

urbs:
	while (!list_empty(&acm->spare_read_bufs)) {
		spin_lock(&acm->read_lock);
		spin_lock_irqsave(&acm->read_lock, flags);
		if (list_empty(&acm->spare_read_urbs)) {
			spin_unlock(&acm->read_lock);
			spin_unlock_irqrestore(&acm->read_lock, flags);
			return;
		}
		rcv = list_entry(acm->spare_read_urbs.next,
				 struct acm_ru, list);
		list_del(&rcv->list);
		spin_unlock(&acm->read_lock);
		spin_unlock_irqrestore(&acm->read_lock, flags);

		buf = list_entry(acm->spare_read_bufs.next,
				 struct acm_rb, list);
@@ -400,9 +400,9 @@ urbs:
		   free-urbs-pool and resubmited ASAP */
		if (usb_submit_urb(rcv->urb, GFP_ATOMIC) < 0) {
			list_add(&buf->list, &acm->spare_read_bufs);
			spin_lock(&acm->read_lock);
			spin_lock_irqsave(&acm->read_lock, flags);
			list_add(&rcv->list, &acm->spare_read_urbs);
			spin_unlock(&acm->read_lock);
			spin_unlock_irqrestore(&acm->read_lock, flags);
			return;
		}
	}