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

Commit 884ce1f1 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_mass_storage: Add timer to catch VFS read/write/sync stuck issues"

parents 9484d749 c58e420a
Loading
Loading
Loading
Loading
+51 −1
Original line number Diff line number Diff line
@@ -237,6 +237,14 @@ static int csw_hack_sent;
#endif
/*-------------------------------------------------------------------------*/

/*If USB mass storage vfs operation is stuck for more than 10 sec
host will initiate the reset. Configure the timer with 9 sec to print
the error message before host is intiating the resume on it.*/
#define MSC_VFS_TIMER_PERIOD_MS	9000
static int msc_vfs_timer_period_ms = MSC_VFS_TIMER_PERIOD_MS;
module_param(msc_vfs_timer_period_ms, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(msc_vfs_timer_period_ms, "Set period for MSC VFS timer");

struct fsg_dev;
struct fsg_common;

@@ -315,6 +323,7 @@ struct fsg_common {
	char inquiry_string[8 + 16 + 4 + 1];

	struct kref		ref;
	struct timer_list	vfs_timer;
};

struct fsg_config {
@@ -355,6 +364,26 @@ struct fsg_dev {
	struct usb_ep		*bulk_out;
};

static void msc_usb_vfs_timer_func(unsigned long data)
{
	struct fsg_common *common = (struct fsg_common *) data;

	switch (common->data_dir) {
	case DATA_DIR_FROM_HOST:
		dev_err(&common->curlun->dev,
				"usb mass storage stuck in vfs_write\n");
		break;
	case DATA_DIR_TO_HOST:
		dev_err(&common->curlun->dev,
				"usb mass storage stuck in vfs_read\n");
		break;
	default:
		dev_err(&common->curlun->dev,
				"usb mass storage stuck in vfs_sync\n");
		break;
	}
}

static inline int __fsg_is_set(struct fsg_common *common,
			       const char *func, unsigned line)
{
@@ -745,9 +774,12 @@ static int do_read(struct fsg_common *common)
#ifdef CONFIG_USB_MSC_PROFILING
		start = ktime_get();
#endif
		mod_timer(&common->vfs_timer, jiffies +
			msecs_to_jiffies(msc_vfs_timer_period_ms));
		nread = vfs_read(curlun->filp,
				 (char __user *)bh->buf,
				 amount, &file_offset_tmp);
		del_timer_sync(&common->vfs_timer);
		VLDBG(curlun, "file read %u @ %llu -> %d\n", amount,
		     (unsigned long long) file_offset, (int) nread);
#ifdef CONFIG_USB_MSC_PROFILING
@@ -965,9 +997,12 @@ static int do_write(struct fsg_common *common)
#ifdef CONFIG_USB_MSC_PROFILING
			start = ktime_get();
#endif
			mod_timer(&common->vfs_timer, jiffies +
				msecs_to_jiffies(msc_vfs_timer_period_ms));
			nwritten = vfs_write(curlun->filp,
					     (char __user *)bh->buf,
					     amount, &file_offset_tmp);
			del_timer_sync(&common->vfs_timer);
			VLDBG(curlun, "file write %u @ %llu -> %d\n", amount,
			      (unsigned long long)file_offset, (int)nwritten);
#ifdef CONFIG_USB_MSC_PROFILING
@@ -1067,9 +1102,12 @@ static int do_synchronize_cache(struct fsg_common *common)

	/* We ignore the requested LBA and write out all file's
	 * dirty data buffers. */
	mod_timer(&common->vfs_timer, jiffies +
		msecs_to_jiffies(msc_vfs_timer_period_ms));
	rc = fsg_lun_fsync_sub(curlun);
	if (rc)
		curlun->sense_data = SS_WRITE_ERROR;
	del_timer_sync(&common->vfs_timer);
	return 0;
}

@@ -1125,7 +1163,10 @@ static int do_verify(struct fsg_common *common)
	file_offset = ((loff_t) lba) << curlun->blkbits;

	/* Write out all the dirty buffers before invalidating them */
	mod_timer(&common->vfs_timer, jiffies +
		msecs_to_jiffies(msc_vfs_timer_period_ms));
	fsg_lun_fsync_sub(curlun);
	del_timer_sync(&common->vfs_timer);
	if (signal_pending(current))
		return -EINTR;

@@ -1155,9 +1196,12 @@ static int do_verify(struct fsg_common *common)

		/* Perform the read */
		file_offset_tmp = file_offset;
		mod_timer(&common->vfs_timer, jiffies +
			msecs_to_jiffies(msc_vfs_timer_period_ms));
		nread = vfs_read(curlun->filp,
				(char __user *) bh->buf,
				amount, &file_offset_tmp);
		del_timer_sync(&common->vfs_timer);
		VLDBG(curlun, "file read %u @ %llu -> %d\n", amount,
				(unsigned long long) file_offset,
				(int) nread);
@@ -1487,8 +1531,12 @@ static int do_prevent_allow(struct fsg_common *common)
		curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
		return -EINVAL;
	}
	if (!curlun->nofua && curlun->prevent_medium_removal && !prevent)
	if (!curlun->nofua && curlun->prevent_medium_removal && !prevent) {
		mod_timer(&common->vfs_timer, jiffies +
			msecs_to_jiffies(msc_vfs_timer_period_ms));
		fsg_lun_fsync_sub(curlun);
		del_timer_sync(&common->vfs_timer);
	}
	curlun->prevent_medium_removal = prevent;
	return 0;
}
@@ -3183,6 +3231,8 @@ static int fsg_bind_config(struct usb_composite_dev *cdev,
	fsg->function.disable     = fsg_disable;

	fsg->common               = common;
	setup_timer(&common->vfs_timer, msc_usb_vfs_timer_func,
			(unsigned long) common);
	/*
	 * Our caller holds a reference to common structure so we
	 * don't have to be worry about it being freed until we return