Re: [PATCH] gadget: mass_storage: make mass_storage support multi-luns with different logic block size

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



here you are , :)

diff --git a/drivers/usb/gadget/f_mass_storage.c
b/drivers/usb/gadget/f_mass_storage.c
index 524381a..6a5c42d 100644
--- a/drivers/usb/gadget/f_mass_storage.c
+++ b/drivers/usb/gadget/f_mass_storage.c
@@ -379,6 +379,7 @@ struct fsg_common {
 	enum data_direction	data_dir;
 	u32			data_size;
 	u32			data_size_from_cmnd;
+	u32			data_size_is_in_blocks;
 	u32			tag;
 	u32			residue;
 	u32			usb_amount_left;
@@ -1851,6 +1852,18 @@ static int check_command(struct fsg_common
*common, int cmnd_size,
 	char			hdlen[20];
 	struct fsg_lun		*curlun;

+	curlun = common->curlun;
+	/* Convert the data size's unit from CDB */
+	if (common->data_size_is_in_blocks == 1) {
+		common->data_size_is_in_blocks = 0;
+		if (!curlun) {
+			DBG(common, "curlun NULL\n");
+			return -EINVAL;
+		}
+		common->data_size_from_cmnd =
+			common->data_size_from_cmnd << curlun->blkbits;
+	}
+
 	hdlen[0] = 0;
 	if (common->data_dir != DATA_DIR_UNKNOWN)
 		sprintf(hdlen, ", H%c=%u", dirletter[(int) common->data_dir],
@@ -1859,6 +1872,7 @@ static int check_command(struct fsg_common
*common, int cmnd_size,
 	     name, cmnd_size, dirletter[(int) data_dir],
 	     common->data_size_from_cmnd, common->cmnd_size, hdlen);

+
 	/*
 	 * We can't reply at all until we know the correct data direction
 	 * and size.
@@ -1916,17 +1930,13 @@ static int check_command(struct fsg_common
*common, int cmnd_size,
 		    common->lun, lun);

 	/* Check the LUN */
-	if (common->lun >= 0 && common->lun < common->nluns) {
-		curlun = &common->luns[common->lun];
-		common->curlun = curlun;
+	if (curlun) {
 		if (common->cmnd[0] != REQUEST_SENSE) {
 			curlun->sense_data = SS_NO_SENSE;
 			curlun->sense_data_info = 0;
 			curlun->info_valid = 0;
 		}
 	} else {
-		common->curlun = NULL;
-		curlun = NULL;
 		common->bad_lun_okay = 0;

 		/*
@@ -2054,8 +2064,8 @@ static int do_scsi_command(struct fsg_common *common)

 	case READ_6:
 		i = common->cmnd[4];
-		common->data_size_from_cmnd = (i == 0 ? 256 : i) <<
-				common->curlun->blkbits;
+		common->data_size_from_cmnd = (i == 0 ? 256 : i);
+		common->data_size_is_in_blocks = 1;
 		reply = check_command(common, 6, DATA_DIR_TO_HOST,
 				      (7<<1) | (1<<4), 1,
 				      "READ(6)");
@@ -2065,8 +2075,8 @@ static int do_scsi_command(struct fsg_common *common)

 	case READ_10:
 		common->data_size_from_cmnd =
-				get_unaligned_be16(&common->cmnd[7]) <<
-						common->curlun->blkbits;
+				get_unaligned_be16(&common->cmnd[7]);
+		common->data_size_is_in_blocks = 1;
 		reply = check_command(common, 10, DATA_DIR_TO_HOST,
 				      (1<<1) | (0xf<<2) | (3<<7), 1,
 				      "READ(10)");
@@ -2076,8 +2086,8 @@ static int do_scsi_command(struct fsg_common *common)

 	case READ_12:
 		common->data_size_from_cmnd =
-				get_unaligned_be32(&common->cmnd[6]) <<
-						common->curlun->blkbits;
+				get_unaligned_be32(&common->cmnd[6]);
+		common->data_size_is_in_blocks = 1;
 		reply = check_command(common, 12, DATA_DIR_TO_HOST,
 				      (1<<1) | (0xf<<2) | (0xf<<6), 1,
 				      "READ(12)");
@@ -2177,8 +2187,8 @@ static int do_scsi_command(struct fsg_common *common)

 	case WRITE_6:
 		i = common->cmnd[4];
-		common->data_size_from_cmnd = (i == 0 ? 256 : i) <<
-					common->curlun->blkbits;
+		common->data_size_from_cmnd = (i == 0 ? 256 : i);
+		common->data_size_is_in_blocks = 1;
 		reply = check_command(common, 6, DATA_DIR_FROM_HOST,
 				      (7<<1) | (1<<4), 1,
 				      "WRITE(6)");
@@ -2188,8 +2198,8 @@ static int do_scsi_command(struct fsg_common *common)

 	case WRITE_10:
 		common->data_size_from_cmnd =
-				get_unaligned_be16(&common->cmnd[7]) <<
-						common->curlun->blkbits;
+				get_unaligned_be16(&common->cmnd[7]);
+		common->data_size_is_in_blocks = 1;
 		reply = check_command(common, 10, DATA_DIR_FROM_HOST,
 				      (1<<1) | (0xf<<2) | (3<<7), 1,
 				      "WRITE(10)");
@@ -2199,8 +2209,8 @@ static int do_scsi_command(struct fsg_common *common)

 	case WRITE_12:
 		common->data_size_from_cmnd =
-				get_unaligned_be32(&common->cmnd[6]) <<
-						common->curlun->blkbits;
+				get_unaligned_be32(&common->cmnd[6]);
+		common->data_size_is_in_blocks = 1;
 		reply = check_command(common, 12, DATA_DIR_FROM_HOST,
 				      (1<<1) | (0xf<<2) | (0xf<<6), 1,
 				      "WRITE(12)");
@@ -2316,7 +2326,10 @@ static int received_cbw(struct fsg_dev *fsg,
struct fsg_buffhd *bh)
 	if (common->data_size == 0)
 		common->data_dir = DATA_DIR_NONE;
 	common->lun = cbw->Lun;
-	common->curlun = &common->luns[cbw->Lun];
+	if (common->lun >= 0 && common->lun < common->nluns)
+		common->curlun = &common->luns[common->lun];
+	else
+		common->curlun = NULL;
 	common->tag = cbw->Tag;
 	return 0;
 }
diff --git a/drivers/usb/gadget/file_storage.c
b/drivers/usb/gadget/file_storage.c
index e081e28..2775012 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -472,6 +472,7 @@ struct fsg_dev {
 	enum data_direction	data_dir;
 	u32			data_size;
 	u32			data_size_from_cmnd;
+	u32			data_size_is_in_blocks;
 	u32			tag;
 	unsigned int		lun;
 	u32			residue;
@@ -2249,6 +2250,18 @@ static int check_command(struct fsg_dev *fsg,
int cmnd_size,
 	} else
 		cmnd_size = 12;

+	curlun = fsg->curlun;
+	/* Convert the data size's unit from CDB */
+	if (fsg->data_size_is_in_blocks == 1) {
+		fsg->data_size_is_in_blocks = 0;
+		if (!curlun) {
+			DBG(fsg, "curlun NULL\n");
+			return -EINVAL;
+		}
+		fsg->data_size_from_cmnd =
+			fsg->data_size_from_cmnd << curlun->blkbits;
+	}
+
 	hdlen[0] = 0;
 	if (fsg->data_dir != DATA_DIR_UNKNOWN)
 		sprintf(hdlen, ", H%c=%u", dirletter[(int) fsg->data_dir],
@@ -2319,15 +2332,13 @@ static int check_command(struct fsg_dev *fsg,
int cmnd_size,
 		fsg->lun = lun;		// Use LUN from the command

 	/* Check the LUN */
-	if (fsg->lun >= 0 && fsg->lun < fsg->nluns) {
-		fsg->curlun = curlun = &fsg->luns[fsg->lun];
+	if (curlun) {
 		if (fsg->cmnd[0] != REQUEST_SENSE) {
 			curlun->sense_data = SS_NO_SENSE;
 			curlun->sense_data_info = 0;
 			curlun->info_valid = 0;
 		}
 	} else {
-		fsg->curlun = curlun = NULL;
 		fsg->bad_lun_okay = 0;

 		/* INQUIRY and REQUEST SENSE commands are explicitly allowed
@@ -2443,8 +2454,8 @@ static int do_scsi_command(struct fsg_dev *fsg)

 	case READ_6:
 		i = fsg->cmnd[4];
-		fsg->data_size_from_cmnd = (i == 0 ? 256 : i)
-				<< fsg->curlun->blkbits;
+		fsg->data_size_from_cmnd = (i == 0 ? 256 : i);
+		fsg->data_size_is_in_blocks = 1;
 		if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST,
 				(7<<1) | (1<<4), 1,
 				"READ(6)")) == 0)
@@ -2453,8 +2464,8 @@ static int do_scsi_command(struct fsg_dev *fsg)

 	case READ_10:
 		fsg->data_size_from_cmnd =
-				get_unaligned_be16(&fsg->cmnd[7])
-						<< fsg->curlun->blkbits;
+				get_unaligned_be16(&fsg->cmnd[7]);
+		fsg->data_size_is_in_blocks = 1;
 		if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
 				(1<<1) | (0xf<<2) | (3<<7), 1,
 				"READ(10)")) == 0)
@@ -2463,8 +2474,8 @@ static int do_scsi_command(struct fsg_dev *fsg)

 	case READ_12:
 		fsg->data_size_from_cmnd =
-				get_unaligned_be32(&fsg->cmnd[6])
-						<< fsg->curlun->blkbits;
+				get_unaligned_be32(&fsg->cmnd[6]);
+		fsg->data_size_is_in_blocks = 1;
 		if ((reply = check_command(fsg, 12, DATA_DIR_TO_HOST,
 				(1<<1) | (0xf<<2) | (0xf<<6), 1,
 				"READ(12)")) == 0)
@@ -2550,8 +2561,8 @@ static int do_scsi_command(struct fsg_dev *fsg)

 	case WRITE_6:
 		i = fsg->cmnd[4];
-		fsg->data_size_from_cmnd = (i == 0 ? 256 : i)
-				<< fsg->curlun->blkbits;
+		fsg->data_size_from_cmnd = (i == 0 ? 256 : i);
+		fsg->data_size_is_in_blocks = 1;
 		if ((reply = check_command(fsg, 6, DATA_DIR_FROM_HOST,
 				(7<<1) | (1<<4), 1,
 				"WRITE(6)")) == 0)
@@ -2560,8 +2571,8 @@ static int do_scsi_command(struct fsg_dev *fsg)

 	case WRITE_10:
 		fsg->data_size_from_cmnd =
-				get_unaligned_be16(&fsg->cmnd[7])
-						<< fsg->curlun->blkbits;
+				get_unaligned_be16(&fsg->cmnd[7]);
+		fsg->data_size_is_in_blocks = 1;
 		if ((reply = check_command(fsg, 10, DATA_DIR_FROM_HOST,
 				(1<<1) | (0xf<<2) | (3<<7), 1,
 				"WRITE(10)")) == 0)
@@ -2570,8 +2581,8 @@ static int do_scsi_command(struct fsg_dev *fsg)

 	case WRITE_12:
 		fsg->data_size_from_cmnd =
-				get_unaligned_be32(&fsg->cmnd[6])
-						<< fsg->curlun->blkbits;
+				get_unaligned_be32(&fsg->cmnd[6]);
+		fsg->data_size_is_in_blocks = 1;
 		if ((reply = check_command(fsg, 12, DATA_DIR_FROM_HOST,
 				(1<<1) | (0xf<<2) | (0xf<<6), 1,
 				"WRITE(12)")) == 0)
@@ -2688,6 +2699,12 @@ static int get_next_command(struct fsg_dev *fsg)
 	struct fsg_buffhd	*bh;
 	int			rc = 0;

+	/* Update current lun */
+	if (fsg->lun >= 0 && fsg->lun < fsg->nluns)
+		fsg->curlun = &fsg->luns[fsg->lun];
+	else
+		fsg->curlun = NULL;
+
 	if (transport_is_bbb()) {

 		/* Wait for the next buffer to become available */

Thanks
Yuping Luo

On Fri, Oct 14, 2011 at 9:45 AM, Alan Stern <stern@xxxxxxxxxxxxxxxxxxx> wrote:
> On Fri, 14 Oct 2011, Barry Song wrote:
>
>> > Checking the LUN value and doing the bit shifts in a single place is
>> > better than doing them repeatedly in many different command handlers.
>>
>> i don't see too much benefit we can get from adding a new flag. might
>> it is clearer.
>> if you prefer that way, we can take.
>
> Sure, go ahead.  Let's compare the new patch with this one; I think it
> will look better.
>
> Alan Stern
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-usb" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux