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

Commit 8e422669 authored by Oliver Neukum's avatar Oliver Neukum Committed by Greg Kroah-Hartman
Browse files

USB: mutexification of usblp



this patch:
- converts usblp fully to mutex
- makes sleeping interruptible where EINTR can be returned anyway

Signed-off-by: default avatarOliver Neukum <oliver@neukum.name>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent b1cff285
Loading
Loading
Loading
Loading
+29 −25
Original line number Diff line number Diff line
@@ -130,7 +130,7 @@ MFG:HEWLETT-PACKARD;MDL:DESKJET 970C;CMD:MLC,PCL,PML;CLASS:PRINTER;DESCRIPTION:H

struct usblp {
	struct usb_device 	*dev;			/* USB device */
	struct semaphore	sem;			/* locks this struct, especially "dev" */
	struct mutex		mut;			/* locks this struct, especially "dev" */
	char			*writebuf;		/* write transfer_buffer */
	char			*readbuf;		/* read transfer_buffer */
	char			*statusbuf;		/* status transfer_buffer */
@@ -465,7 +465,7 @@ static long usblp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
	int twoints[2];
	int retval = 0;

	down (&usblp->sem);
	mutex_lock (&usblp->mut);
	if (!usblp->present) {
		retval = -ENODEV;
		goto done;
@@ -644,14 +644,14 @@ static long usblp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
		}

done:
	up (&usblp->sem);
	mutex_unlock (&usblp->mut);
	return retval;
}

static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
{
	struct usblp *usblp = file->private_data;
	int timeout, rv, err = 0, transfer_length = 0;
	int timeout, intr, rv, err = 0, transfer_length = 0;
	size_t writecount = 0;

	while (writecount < count) {
@@ -668,14 +668,16 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t
			if (rv < 0)
				return writecount ? writecount : -EINTR;
		}
		down (&usblp->sem);
		intr = mutex_lock_interruptible (&usblp->mut);
		if (intr)
			return writecount ? writecount : -EINTR;
		if (!usblp->present) {
			up (&usblp->sem);
			mutex_unlock (&usblp->mut);
			return -ENODEV;
		}

		if (usblp->sleeping) {
			up (&usblp->sem);
			mutex_unlock (&usblp->mut);
			return writecount ? writecount : -ENODEV;
		}

@@ -687,10 +689,10 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t
				err = usblp->writeurb->status;
			} else
				err = usblp_check_status(usblp, err);
			up (&usblp->sem);
			mutex_unlock (&usblp->mut);

			/* if the fault was due to disconnect, let khubd's
			 * call to usblp_disconnect() grab usblp->sem ...
			 * call to usblp_disconnect() grab usblp->mut ...
			 */
			schedule ();
			continue;
@@ -702,7 +704,7 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t
		 */
		writecount += transfer_length;
		if (writecount == count) {
			up(&usblp->sem);
			mutex_unlock(&usblp->mut);
			break;
		}

@@ -714,7 +716,7 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t

		if (copy_from_user(usblp->writeurb->transfer_buffer, 
				   buffer + writecount, transfer_length)) {
			up(&usblp->sem);
			mutex_unlock(&usblp->mut);
			return writecount ? writecount : -EFAULT;
		}

@@ -727,10 +729,10 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t
				count = -EIO;
			else
				count = writecount ? writecount : -ENOMEM;
			up (&usblp->sem);
			mutex_unlock (&usblp->mut);
			break;
		}
		up (&usblp->sem);
		mutex_unlock (&usblp->mut);
	}

	return count;
@@ -739,12 +741,14 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t
static ssize_t usblp_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
{
	struct usblp *usblp = file->private_data;
	int rv;
	int rv, intr;

	if (!usblp->bidir)
		return -EINVAL;

	down (&usblp->sem);
	intr = mutex_lock_interruptible (&usblp->mut);
	if (intr)
		return -EINTR;
	if (!usblp->present) {
		count = -ENODEV;
		goto done;
@@ -757,9 +761,9 @@ static ssize_t usblp_read(struct file *file, char __user *buffer, size_t count,
			count = -EAGAIN;
			goto done;
		}
		up(&usblp->sem);
		mutex_unlock(&usblp->mut);
		rv = wait_event_interruptible(usblp->wait, usblp->rcomplete || !usblp->present);
		down(&usblp->sem);
		mutex_lock(&usblp->mut);
		if (rv < 0) {
			count = -EINTR;
			goto done;
@@ -807,7 +811,7 @@ static ssize_t usblp_read(struct file *file, char __user *buffer, size_t count,
	}

done:
	up (&usblp->sem);
	mutex_unlock (&usblp->mut);
	return count;
}

@@ -886,7 +890,7 @@ static int usblp_probe(struct usb_interface *intf,
		goto abort;
	}
	usblp->dev = dev;
	init_MUTEX (&usblp->sem);
	mutex_init (&usblp->mut);
	init_waitqueue_head(&usblp->wait);
	usblp->ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
	usblp->intf = intf;
@@ -1178,7 +1182,7 @@ static void usblp_disconnect(struct usb_interface *intf)
	device_remove_file(&intf->dev, &dev_attr_ieee1284_id);

	mutex_lock (&usblp_mutex);
	down (&usblp->sem);
	mutex_lock (&usblp->mut);
	usblp->present = 0;
	usb_set_intfdata (intf, NULL);

@@ -1187,7 +1191,7 @@ static void usblp_disconnect(struct usb_interface *intf)
			usblp->writebuf, usblp->writeurb->transfer_dma);
	usb_buffer_free (usblp->dev, USBLP_BUF_SIZE,
			usblp->readbuf, usblp->readurb->transfer_dma);
	up (&usblp->sem);
	mutex_unlock (&usblp->mut);

	if (!usblp->used)
		usblp_cleanup (usblp);
@@ -1200,11 +1204,11 @@ static int usblp_suspend (struct usb_interface *intf, pm_message_t message)

	/* this races against normal access and open */
	mutex_lock (&usblp_mutex);
	down (&usblp->sem);
	mutex_lock (&usblp->mut);
	/* we take no more IO */
	usblp->sleeping = 1;
	usblp_unlink_urbs(usblp);
	up (&usblp->sem);
	mutex_unlock (&usblp->mut);
	mutex_unlock (&usblp_mutex);

	return 0;
@@ -1216,12 +1220,12 @@ static int usblp_resume (struct usb_interface *intf)
	int r;

	mutex_lock (&usblp_mutex);
	down (&usblp->sem);
	mutex_lock (&usblp->mut);

	usblp->sleeping = 0;
	r = handle_bidir (usblp);

	up (&usblp->sem);
	mutex_unlock (&usblp->mut);
	mutex_unlock (&usblp_mutex);

	return r;