linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/1] scsi: retrieve cache mode using ATA_16 if normal routine fails
@ 2011-12-12 11:18 Amit Sahrawat
  2011-12-12 12:51 ` James Bottomley
  0 siblings, 1 reply; 14+ messages in thread
From: Amit Sahrawat @ 2011-12-12 11:18 UTC (permalink / raw)
  To: James E.J. Bottomley
  Cc: Nam-Jae Jeon, linux-scsi, linux-kernel, Amit Sahrawat

It has been observed that a number of USB HDD's do not respond correctly
to SCSI mode sense command(retrieve caching pages) which results in their
Write Cache being discarded by queue requests i.e., WCE if left set to
'0'(disabled).
This results in a number of Filesystem corruptions, when the device
is unplugged abruptly.

So, in order to identify the devices correctly - give it
a last try using ATA_16 after failure from normal routine.
Introduce a mechanism to store write-cache type using /sys/class/
interface, so that the normal code continues to function without errors.

Signed-off-by: Amit Sahrawat <amit.sahrawat83@gmail.com>
Signed-off-by: Nam-Jae Jeon <namjae.jeon@samsung.com>
---
 drivers/scsi/sd.c          |   49 +++++++++++++++++++++++++++++++++++++++++++-
 include/scsi/scsi.h        |   32 ++++++++++++++++++++++++++++
 include/scsi/scsi_device.h |    2 +
 3 files changed, 82 insertions(+), 1 deletions(-)

diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index fa3a591..5227d65 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -124,7 +124,7 @@ static mempool_t *sd_cdb_pool;
 
 static const char *sd_cache_types[] = {
 	"write through", "none", "write back",
-	"write back, no read (daft)"
+	"write back, no read (daft)", "write back(ata cmd)"
 };
 
 static ssize_t
@@ -156,8 +156,15 @@ sd_store_cache_type(struct device *dev, struct device_attribute *attr,
 	}
 	if (ct < 0)
 		return -EINVAL;
+
+	if (ct & 0x04) {
+		sdp->use_ata_cmd = 1;
+		goto revalidate_disk;
+	}
+
 	rcd = ct & 0x01 ? 1 : 0;
 	wce = ct & 0x02 ? 1 : 0;
+
 	if (scsi_mode_sense(sdp, 0x08, 8, buffer, sizeof(buffer), SD_TIMEOUT,
 			    SD_MAX_RETRIES, &data, NULL))
 		return -EINVAL;
@@ -175,6 +182,8 @@ sd_store_cache_type(struct device *dev, struct device_attribute *attr,
 			sd_print_sense_hdr(sdkp, &sshdr);
 		return -EINVAL;
 	}
+
+revalidate_disk:
 	revalidate_disk(sdkp->disk);
 	return count;
 }
@@ -2029,11 +2038,15 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer)
 	int old_wce = sdkp->WCE;
 	int old_rcd = sdkp->RCD;
 	int old_dpofua = sdkp->DPOFUA;
+	unsigned char cdb[ATA_16_LEN] = {0};
 
 	first_len = 4;
 	if (sdp->skip_ms_page_8) {
 		if (sdp->type == TYPE_RBC)
 			goto defaults;
+		else if (sdp->use_ata_cmd) {
+			goto WCE_USING_ATA;
+		}
 		else {
 			if (sdp->skip_ms_page_3f)
 				goto defaults;
@@ -2142,6 +2155,39 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer)
 			sdkp->DPOFUA = 0;
 		}
 
+WCE_USING_ATA:
+		if (!sdp->removable && (sdp->use_ata_cmd && !sdkp->WCE)) {
+			sd_printk(KERN_NOTICE, sdkp, "Try to check write cache "
+				"enable/disable using ATA command\n");
+			cdb[0] = ATA_16;
+			/* Packet command, Programmed I/O -
+			 * PIO - Indicates Data in */
+			cdb[1] = ATA_PROTO_PIO_IN;
+			/* Data read sectors from device */
+			cdb[2] = CDB2_TLEN_NSECT |
+				 CDB2_TLEN_SECTORS | CDB2_TDIR_FROM_DEV;
+			cdb[6] = 0x01; /* No. of Sectors To Read */
+			cdb[13] = ATA_USING_LBA;
+			cdb[14] = ATA_OP_IDENTIFY;
+
+			sdkp->WCE = 0;
+			sdkp->RCD = 0;
+			sdkp->DPOFUA = 0;
+
+			if (!scsi_execute_req(sdp, cdb, DMA_FROM_DEVICE,
+				buffer,	SD_BUF_SIZE, &sshdr, SD_TIMEOUT,
+				SD_MAX_RETRIES, NULL)) {
+				/*
+				 * '6th' Bit in Word 85 Corresponds to
+				 * Write Cache being Enabled/disabled,
+				 * Word 85 represnets the features supported
+				 */
+				if (le16_to_cpu(
+					((unsigned short *)buffer)[85]) & 0x20)
+					sdkp->WCE = 1;
+			}
+		}
+
 		if (sdkp->first_scan || old_wce != sdkp->WCE ||
 		    old_rcd != sdkp->RCD || old_dpofua != sdkp->DPOFUA)
 			sd_printk(KERN_NOTICE, sdkp,
@@ -2515,6 +2561,7 @@ static void sd_probe_async(void *data, async_cookie_t cookie)
 	sdkp->RCD = 0;
 	sdkp->ATO = 0;
 	sdkp->first_scan = 1;
+	sdp->use_ata_cmd = 0;
 
 	sd_revalidate_disk(gd);
 
diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h
index 8001ae4..9e44805 100644
--- a/include/scsi/scsi.h
+++ b/include/scsi/scsi.h
@@ -181,6 +181,38 @@ struct scsi_cmnd;
 #define	ATA_16		      0x85	/* 16-byte pass-thru */
 #define	ATA_12		      0xa1	/* 12-byte pass-thru */
 
+#define ATA_16_LEN     16
+#define ATA_OP_IDENTIFY        0xec /* Command to Identify device*/
+
+#define ATA_LBA48            1
+#define ATA_PROTO_NON_DATA   (3 << 1)
+#define ATA_PROTO_PIO_IN     (4 << 1)
+#define ATA_PROTO_PIO_OUT    (5 << 1)
+#define ATA_PROTO_DMA        (6 << 1)
+
+/*
+ * Some useful ATA register bits
+ */
+enum {
+	ATA_USING_LBA   =       (1 << 6),
+	ATA_STAT_DRQ    =       (1 << 3),
+	ATA_STAT_ERR    =       (1 << 0),
+};
+
+enum {
+	CDB2_TLEN_NODATA     = 0 << 0,
+	CDB2_TLEN_FEAT       = 1 << 0,
+	CDB2_TLEN_NSECT      = 2 << 0,
+
+	CDB2_TLEN_BYTES      = 0 << 2,
+	CDB2_TLEN_SECTORS    = 1 << 2,
+
+	CDB2_TDIR_TO_DEV     = 0 << 3,
+	CDB2_TDIR_FROM_DEV   = 1 << 3,
+
+	CDB2_CHECK_COND      = 1 << 5,
+};
+
 /*
  *	SCSI command lengths
  */
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
index 5591ed5..edfa981 100644
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -151,6 +151,8 @@ struct scsi_device {
 	unsigned no_read_disc_info:1;	/* Avoid READ_DISC_INFO cmds */
 	unsigned no_read_capacity_16:1; /* Avoid READ_CAPACITY_16 cmds */
 	unsigned is_visible:1;	/* is the device visible in sysfs */
+	unsigned use_ata_cmd; /* device which do not responed to normal routine,
+			       * try ATA_16 command on them. */
 
 	DECLARE_BITMAP(supported_events, SDEV_EVT_MAXBITS); /* supported events */
 	struct list_head event_list;	/* asserted events */
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/1] scsi: retrieve cache mode using ATA_16 if normal routine fails
  2011-12-12 11:18 [PATCH 1/1] scsi: retrieve cache mode using ATA_16 if normal routine fails Amit Sahrawat
@ 2011-12-12 12:51 ` James Bottomley
  2011-12-13  0:20   ` Namjae Jeon
  0 siblings, 1 reply; 14+ messages in thread
From: James Bottomley @ 2011-12-12 12:51 UTC (permalink / raw)
  To: Amit Sahrawat; +Cc: Nam-Jae Jeon, linux-scsi, linux-kernel

On Mon, 2011-12-12 at 16:48 +0530, Amit Sahrawat wrote:
> It has been observed that a number of USB HDD's do not respond correctly
> to SCSI mode sense command(retrieve caching pages) which results in their
> Write Cache being discarded by queue requests i.e., WCE if left set to
> '0'(disabled).
> This results in a number of Filesystem corruptions, when the device
> is unplugged abruptly.

Um, how would knowing the caching type correctly help?  If you surprise
unplug the device, we can't send a flush to it anyway ...

> So, in order to identify the devices correctly - give it
> a last try using ATA_16 after failure from normal routine.
> Introduce a mechanism to store write-cache type using /sys/class/
> interface, so that the normal code continues to function without errors.
> 
> Signed-off-by: Amit Sahrawat <amit.sahrawat83@gmail.com>
> Signed-off-by: Nam-Jae Jeon <namjae.jeon@samsung.com>

This whole patch looks like a layering violation.  Why not just update
the SAT layer to translate the MODE SENSE correctly?

James



^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/1] scsi: retrieve cache mode using ATA_16 if normal routine fails
  2011-12-12 12:51 ` James Bottomley
@ 2011-12-13  0:20   ` Namjae Jeon
       [not found]     ` <CADDb1s2SOK5sC3N0OOdkBrPuDKc2d2A4z4yso4jYs=1rbxNmkA@mail.gmail.com>
  2011-12-13  8:53     ` James Bottomley
  0 siblings, 2 replies; 14+ messages in thread
From: Namjae Jeon @ 2011-12-13  0:20 UTC (permalink / raw)
  To: James Bottomley; +Cc: Amit Sahrawat, Nam-Jae Jeon, linux-scsi, linux-kernel

2011/12/12 James Bottomley <James.Bottomley@hansenpartnership.com>:
> On Mon, 2011-12-12 at 16:48 +0530, Amit Sahrawat wrote:
>> It has been observed that a number of USB HDD's do not respond correctly
>> to SCSI mode sense command(retrieve caching pages) which results in their
>> Write Cache being discarded by queue requests i.e., WCE if left set to
>> '0'(disabled).
>> This results in a number of Filesystem corruptions, when the device
>> is unplugged abruptly.
>
> Um, how would knowing the caching type correctly help?  If you surprise
> unplug the device, we can't send a flush to it anyway ...
Hi. James.
We can get device specification buffer to use ata_16 cmd.So we are
able to distinguish caching type by using 85byte of buffer.
And filesystem is using write barrier function to protect important
data like journaling data.
If filesystem is able to use write barrier by correctly setting WCE,
ordering can be guaranteed to flush data(preflush/postflush) to
internal write cache in hdd before power off. so filesystem can get
consistency and reliability by sudden plug and power off.
>
>> So, in order to identify the devices correctly - give it
>> a last try using ATA_16 after failure from normal routine.
>> Introduce a mechanism to store write-cache type using /sys/class/
>> interface, so that the normal code continues to function without errors.
>>
>> Signed-off-by: Amit Sahrawat <amit.sahrawat83@gmail.com>
>> Signed-off-by: Nam-Jae Jeon <namjae.jeon@samsung.com>
>
> This whole patch looks like a layering violation.  Why not just update
> the SAT layer to translate the MODE SENSE correctly?
Would plz you explain more ? I didn't clearly understand your point yet.
>
> James
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/1] scsi: retrieve cache mode using ATA_16 if normal routine fails
       [not found]     ` <CADDb1s2SOK5sC3N0OOdkBrPuDKc2d2A4z4yso4jYs=1rbxNmkA@mail.gmail.com>
@ 2011-12-13  4:56       ` Amit Sahrawat
  0 siblings, 0 replies; 14+ messages in thread
From: Amit Sahrawat @ 2011-12-13  4:56 UTC (permalink / raw)
  To: Namjae Jeon; +Cc: James Bottomley, Nam-Jae Jeon, linux-scsi, linux-kernel

On Tue, Dec 13, 2011 at 10:24 AM, Amit Sahrawat
<amit.sahrawat83@gmail.com> wrote:
>
> Hi James,
>
>
>
> We verified the changes by actually putting the setup through a series of test cases. There were test cases where-in we were able to reduce the filesystem corruption by 100%.
>
> Yes, In normal operation SYNC_CACHE gets called up when we do a safe removal of the device. But, Setting WCE also takes cares of sending the SYNC_CACHE command in between the operations also.
>
>
>
> What we are making sure is, that by providing this interface we can have WCE enabled for some HDD –that will mark QUEUE ORDERING to QUEUE_ORDERED_DRAIN_FLUSH(Preflush-Postflush)(i.e., flushing will occur for all the Mass Storage devices - which in turn will keep on calling SYNC_CACHE for these devices.
>
>
>
> We checked this on USB HDD’s, USB SSD, and USB Flash from a number of vendors – all seemed to work pretty well with these changes.
>
>
>
> Please share your opinion.
>
>
>
> Thanks & Regards,
>
> Amit Sahrawat
>
>
>
>
> On Tue, Dec 13, 2011 at 5:50 AM, Namjae Jeon <linkinjeon@gmail.com> wrote:
>>
>> 2011/12/12 James Bottomley <James.Bottomley@hansenpartnership.com>:
>> > On Mon, 2011-12-12 at 16:48 +0530, Amit Sahrawat wrote:
>> >> It has been observed that a number of USB HDD's do not respond correctly
>> >> to SCSI mode sense command(retrieve caching pages) which results in their
>> >> Write Cache being discarded by queue requests i.e., WCE if left set to
>> >> '0'(disabled).
>> >> This results in a number of Filesystem corruptions, when the device
>> >> is unplugged abruptly.
>> >
>> > Um, how would knowing the caching type correctly help?  If you surprise
>> > unplug the device, we can't send a flush to it anyway ...
>> Hi. James.
>> We can get device specification buffer to use ata_16 cmd.So we are
>> able to distinguish caching type by using 85byte of buffer.
>> And filesystem is using write barrier function to protect important
>> data like journaling data.
>> If filesystem is able to use write barrier by correctly setting WCE,
>> ordering can be guaranteed to flush data(preflush/postflush) to
>> internal write cache in hdd before power off. so filesystem can get
>> consistency and reliability by sudden plug and power off.
>> >
>> >> So, in order to identify the devices correctly - give it
>> >> a last try using ATA_16 after failure from normal routine.
>> >> Introduce a mechanism to store write-cache type using /sys/class/
>> >> interface, so that the normal code continues to function without errors.
>> >>
>> >> Signed-off-by: Amit Sahrawat <amit.sahrawat83@gmail.com>
>> >> Signed-off-by: Nam-Jae Jeon <namjae.jeon@samsung.com>
>> >
>> > This whole patch looks like a layering violation.  Why not just update
>> > the SAT layer to translate the MODE SENSE correctly?
>> Would plz you explain more ? I didn't clearly understand your point yet.
>> >
>> > James
>> >
>> >
>> > --
>> > To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
>> > the body of a message to majordomo@vger.kernel.org
>> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
>> > Please read the FAQ at  http://www.tux.org/lkml/
>
>

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/1] scsi: retrieve cache mode using ATA_16 if normal routine fails
  2011-12-13  0:20   ` Namjae Jeon
       [not found]     ` <CADDb1s2SOK5sC3N0OOdkBrPuDKc2d2A4z4yso4jYs=1rbxNmkA@mail.gmail.com>
@ 2011-12-13  8:53     ` James Bottomley
  2011-12-13 12:15       ` Amit Sahrawat
  2011-12-13 20:38       ` Jeff Garzik
  1 sibling, 2 replies; 14+ messages in thread
From: James Bottomley @ 2011-12-13  8:53 UTC (permalink / raw)
  To: Namjae Jeon; +Cc: Amit Sahrawat, Nam-Jae Jeon, linux-scsi, linux-kernel

On Tue, 2011-12-13 at 09:20 +0900, Namjae Jeon wrote:
> > This whole patch looks like a layering violation.  Why not just update
> > the SAT layer to translate the MODE SENSE correctly?
> Would plz you explain more ? I didn't clearly understand your point yet.

The ATA layer does translation for SCSI commands.  Just translate the
mode sense correctly to use IDENTIFY word 85.  It's a smaller patch and
no need for any changes in SCSI.

Actually, looking at it, it seems to be correct ... why is it not
working for you?

James



^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/1] scsi: retrieve cache mode using ATA_16 if normal routine fails
  2011-12-13  8:53     ` James Bottomley
@ 2011-12-13 12:15       ` Amit Sahrawat
  2011-12-13 20:38       ` Jeff Garzik
  1 sibling, 0 replies; 14+ messages in thread
From: Amit Sahrawat @ 2011-12-13 12:15 UTC (permalink / raw)
  To: James Bottomley; +Cc: Namjae Jeon, Nam-Jae Jeon, linux-scsi, linux-kernel

On Tue, Dec 13, 2011 at 2:23 PM, James Bottomley
<James.Bottomley@hansenpartnership.com> wrote:
> On Tue, 2011-12-13 at 09:20 +0900, Namjae Jeon wrote:
>> > This whole patch looks like a layering violation.  Why not just update
>> > the SAT layer to translate the MODE SENSE correctly?
>> Would plz you explain more ? I didn't clearly understand your point yet.
>
> The ATA layer does translation for SCSI commands.  Just translate the
> mode sense correctly to use IDENTIFY word 85.  It's a smaller patch and
> no need for any changes in SCSI.
I have a confusion to this, can you please guide where exactly to look for this.
Is there any existing solution to this problem? I did a lot of
analysis and actually tried to make use of a number of USB HDD's from
different vendors to be very sure of my observations. Our's is a
target where-in we connect our HDD through the USB interface.
Do you mean that putting code changes at this place would have impact
on SATA HDD?
Please help more on this.
>
> Actually, looking at it, it seems to be correct ... why is it not
> working for you?
Again, if possible please share that code point, We can again check if
that is hitting in our case.
If need be I can provide the list of all the HDDs with their
manufaturer ID's - on which we tested.
Please let me know for this.
>
> James
>
>
Thanks & Regards,
Amit Sahrawat

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/1] scsi: retrieve cache mode using ATA_16 if normal routine fails
  2011-12-13  8:53     ` James Bottomley
  2011-12-13 12:15       ` Amit Sahrawat
@ 2011-12-13 20:38       ` Jeff Garzik
  2011-12-14  3:44         ` Amit Sahrawat
  1 sibling, 1 reply; 14+ messages in thread
From: Jeff Garzik @ 2011-12-13 20:38 UTC (permalink / raw)
  To: James Bottomley
  Cc: Namjae Jeon, Amit Sahrawat, Nam-Jae Jeon, linux-scsi, linux-kernel

On 12/13/2011 03:53 AM, James Bottomley wrote:
> On Tue, 2011-12-13 at 09:20 +0900, Namjae Jeon wrote:
>>> This whole patch looks like a layering violation.  Why not just update
>>> the SAT layer to translate the MODE SENSE correctly?
>> Would plz you explain more ? I didn't clearly understand your point yet.
>
> The ATA layer does translation for SCSI commands.  Just translate the
> mode sense correctly to use IDENTIFY word 85.  It's a smaller patch and
> no need for any changes in SCSI.

Correct.

> Actually, looking at it, it seems to be correct ... why is it not
> working for you?

Indeed -- the patch attempts to address a problem that the libata-scsi 
translation module already handles.

I would look at why the device is not properly reporting that already. 
If necessary, we would update libata not SCSI.

	Jeff



^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/1] scsi: retrieve cache mode using ATA_16 if normal routine fails
  2011-12-13 20:38       ` Jeff Garzik
@ 2011-12-14  3:44         ` Amit Sahrawat
  2011-12-14  7:39           ` James Bottomley
  0 siblings, 1 reply; 14+ messages in thread
From: Amit Sahrawat @ 2011-12-14  3:44 UTC (permalink / raw)
  To: Jeff Garzik
  Cc: James Bottomley, Namjae Jeon, Nam-Jae Jeon, linux-scsi, linux-kernel

Hi Jeff/James,

Just to add a thought - this issues is not related with ATA, this is
primarily related with HDD's with a USB interface i.e., SCSI <-> USB.
And, when I check my kernel config, CONFIG_ATA is not selected,
libata-scsi - this gets compiled only in case CONFIG_ATA is on.
Are these two things inter-related?

Please let us know.

Thanks & Regards,
Amit Sahrawat

On Wed, Dec 14, 2011 at 2:08 AM, Jeff Garzik <jeff@garzik.org> wrote:
> On 12/13/2011 03:53 AM, James Bottomley wrote:
>>
>> On Tue, 2011-12-13 at 09:20 +0900, Namjae Jeon wrote:
>>>>
>>>> This whole patch looks like a layering violation.  Why not just update
>>>> the SAT layer to translate the MODE SENSE correctly?
>>>
>>> Would plz you explain more ? I didn't clearly understand your point yet.
>>
>>
>> The ATA layer does translation for SCSI commands.  Just translate the
>> mode sense correctly to use IDENTIFY word 85.  It's a smaller patch and
>> no need for any changes in SCSI.
>
>
> Correct.
>
>
>> Actually, looking at it, it seems to be correct ... why is it not
>> working for you?
>
>
> Indeed -- the patch attempts to address a problem that the libata-scsi
> translation module already handles.
>
> I would look at why the device is not properly reporting that already. If
> necessary, we would update libata not SCSI.
>
>        Jeff
>
>

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/1] scsi: retrieve cache mode using ATA_16 if normal routine fails
  2011-12-14  3:44         ` Amit Sahrawat
@ 2011-12-14  7:39           ` James Bottomley
  2011-12-15  0:25             ` Namjae Jeon
  0 siblings, 1 reply; 14+ messages in thread
From: James Bottomley @ 2011-12-14  7:39 UTC (permalink / raw)
  To: Amit Sahrawat
  Cc: Jeff Garzik, Namjae Jeon, Nam-Jae Jeon, linux-scsi, linux-kernel

On Wed, 2011-12-14 at 09:14 +0530, Amit Sahrawat wrote:
> Just to add a thought - this issues is not related with ATA, this is
> primarily related with HDD's with a USB interface i.e., SCSI <-> USB.
> And, when I check my kernel config, CONFIG_ATA is not selected,
> libata-scsi - this gets compiled only in case CONFIG_ATA is on.
> Are these two things inter-related?

OK, so what you're telling us is that you're trying to correct a
deficiency in a SATL inside a USB device?  The device itself is ATA but
it doesn't use our libata connectors.

I think in that case, the best way forwards is a mini-SATL correction
layer within USB storage.  USB storage is certainly the place to
black/white list whether this should be done.  ATA_16 is a bit of a
dangerous command to be throwing around because it's known to crash
various USB devices (and some old SCSI ones might even choke on it).

depending on how big this SATL ends up being we should consider whether
it should share processing with the libata SATL.  If it's just a single
mode sense, my instinct is that it's probably OK to implement separately
(however, you need to use the libata headers ... no duplication of
libata opcodes and status defines like you had in the original SCSI
patch).  If there are more commands to correct on the way, it might be
better as shared code.

James



^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/1] scsi: retrieve cache mode using ATA_16 if normal routine fails
  2011-12-14  7:39           ` James Bottomley
@ 2011-12-15  0:25             ` Namjae Jeon
  2012-01-27  5:20               ` Amit Sahrawat
  0 siblings, 1 reply; 14+ messages in thread
From: Namjae Jeon @ 2011-12-15  0:25 UTC (permalink / raw)
  To: James Bottomley
  Cc: Amit Sahrawat, Jeff Garzik, Nam-Jae Jeon, linux-scsi,
	linux-kernel, mdharm-usb

2011/12/14 James Bottomley <James.Bottomley@hansenpartnership.com>:
> On Wed, 2011-12-14 at 09:14 +0530, Amit Sahrawat wrote:
>> Just to add a thought - this issues is not related with ATA, this is
>> primarily related with HDD's with a USB interface i.e., SCSI <-> USB.
>> And, when I check my kernel config, CONFIG_ATA is not selected,
>> libata-scsi - this gets compiled only in case CONFIG_ATA is on.
>> Are these two things inter-related?
>
Hi. James.

> OK, so what you're telling us is that you're trying to correct a
> deficiency in a SATL inside a USB device?  The device itself is ATA but
> it doesn't use our libata connectors.
>
> I think in that case, the best way forwards is a mini-SATL correction
> layer within USB storage.  USB storage is certainly the place to
> black/white list whether this should be done.  ATA_16 is a bit of a
> dangerous command to be throwing around because it's known to crash
> various USB devices (and some old SCSI ones might even choke on it).
Okay, how about make some option in Kconfig of scsi or usb storage to
protect from the a bit of risk ATA_16 ?
The user can select this option to use stable filesystem on USB HDD.
>
> depending on how big this SATL ends up being we should consider whether
> it should share processing with the libata SATL.  If it's just a single
> mode sense, my instinct is that it's probably OK to implement separately
> (however, you need to use the libata headers ... no duplication of
> libata opcodes and status defines like you had in the original SCSI
> patch).  If there are more commands to correct on the way, it might be
> better as shared code.
I agree. I and Amit will check the best way between SATL or miniSATL
in usb_storage accoding to your advice.

> James
>
>

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/1] scsi: retrieve cache mode using ATA_16 if normal routine fails
  2011-12-15  0:25             ` Namjae Jeon
@ 2012-01-27  5:20               ` Amit Sahrawat
  0 siblings, 0 replies; 14+ messages in thread
From: Amit Sahrawat @ 2012-01-27  5:20 UTC (permalink / raw)
  To: Namjae Jeon
  Cc: James Bottomley, Jeff Garzik, Nam-Jae Jeon, linux-scsi,
	linux-kernel, mdharm-usb

Dear James/Jeff,

I have few questions regarding the code changes which can be accepted
in this regards.

In our scenario we are not making use of CONFIG_ATA, but still if that
is the proper manner to bring out the changes – then we can enable and
make changes in the respective file which seems to be libata-scsi.c

We need a mechanism wherein we can query and then get the response so
that we set the WCE bit accordingly. For that matter, I think we can
introduce some function in libata-scsi.c and then call that function
from either drivers/scsi/sd.c or drivers/usb/storage/scsiglue.c

Please share your valuable inputs on how and where actually these
changes should be done. Otherwise, there is again a chance that our
changes gets rejected.

Please help in this regards.

Thanks & Regards,
Amit Sahrawat



On Thu, Dec 15, 2011 at 5:55 AM, Namjae Jeon <linkinjeon@gmail.com> wrote:
> 2011/12/14 James Bottomley <James.Bottomley@hansenpartnership.com>:
>> On Wed, 2011-12-14 at 09:14 +0530, Amit Sahrawat wrote:
>>> Just to add a thought - this issues is not related with ATA, this is
>>> primarily related with HDD's with a USB interface i.e., SCSI <-> USB.
>>> And, when I check my kernel config, CONFIG_ATA is not selected,
>>> libata-scsi - this gets compiled only in case CONFIG_ATA is on.
>>> Are these two things inter-related?
>>
> Hi. James.
>
>> OK, so what you're telling us is that you're trying to correct a
>> deficiency in a SATL inside a USB device?  The device itself is ATA but
>> it doesn't use our libata connectors.
>>
>> I think in that case, the best way forwards is a mini-SATL correction
>> layer within USB storage.  USB storage is certainly the place to
>> black/white list whether this should be done.  ATA_16 is a bit of a
>> dangerous command to be throwing around because it's known to crash
>> various USB devices (and some old SCSI ones might even choke on it).
> Okay, how about make some option in Kconfig of scsi or usb storage to
> protect from the a bit of risk ATA_16 ?
> The user can select this option to use stable filesystem on USB HDD.
>>
>> depending on how big this SATL ends up being we should consider whether
>> it should share processing with the libata SATL.  If it's just a single
>> mode sense, my instinct is that it's probably OK to implement separately
>> (however, you need to use the libata headers ... no duplication of
>> libata opcodes and status defines like you had in the original SCSI
>> patch).  If there are more commands to correct on the way, it might be
>> better as shared code.
> I agree. I and Amit will check the best way between SATL or miniSATL
> in usb_storage accoding to your advice.
>
>> James
>>
>>

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/1] scsi: retrieve cache mode using ATA_16 if normal routine fails
  2012-02-05 12:05 ` Sergei Shtylyov
@ 2012-02-06  5:40   ` Amit Sahrawat
  0 siblings, 0 replies; 14+ messages in thread
From: Amit Sahrawat @ 2012-02-06  5:40 UTC (permalink / raw)
  To: Sergei Shtylyov
  Cc: Jeff Garzik, James E.J. Bottomley, Nam-Jae Jeon, Amit Sahrawat,
	linux-ide, linux-scsi, linux-kernel

Hi Sergei,
Thanks for your review comments.

On Sun, Feb 5, 2012 at 5:35 PM, Sergei Shtylyov <sshtylyov@mvista.com> wrote:
> Hello.
>
>
> On 03-02-2012 16:59, Amit Sahrawat wrote:
>
>> It has been observed that a number of USB HDD's do not respond correctly
>
>
>   Why are you working around this in libata-scsi.c then if it's USB HDD?
There has been a history to this problem. It has been a long pending
problem with SCSI layer and USB HDD. We observed when we encountered
various Filesystem corruption issues on USB HDD and on analysis - we
found that there is no SYNCHRONIZE_CACHE command going to a number of
USB HDD even though - they do seem to possess WRITE CACHE.
So, drivers/scsi/sd.c - was where we found that WCE is being set for
these kind of devices which will in-turn take care of setting the
correct 'cache_type - Writeback' and also take care of proper working
(by managing correct order in requests queue).
We first did a change by introducing  - mechanism to retrieve cache
bit in sd_read_cache_type, alongwith this we provided an interface
using 'syfs' if we can change the cache type from that place.
But, we received review comments in this regards - that the layer on
which we are doing changes is not the proper place(and also ATA_16
seems to crash some old HDD's, and were advised to look out for
changes in libata-scsi  instead).(Original link -
http://lkml.org/lkml/2011/12/12/164)

So, we went for changes in libata-scsi.

Please let me know in case more information is needed in this regards,
or may be if you could provide more inputs to these sort of changes.
>
>
>> to SCSI mode sense command(retrieve caching pages) which results in their
>> Write Cache being discarded by queue requests i.e., WCE if left set to
>> '0'(disabled).
>> This results in a number of Filesystem corruptions, when the device
>> is unplugged abruptly.
>
>
>> So, in order to identify the devices correctly - give it
>> a last try using ATA_16 after failure from normal routine.
>
>
>   Shouldn't this be done in drivers/usb/storage somewhere?
>
>
>> Signed-off-by: Amit Sahrawat<a.sahrawat@samsung.com>
>> Signed-off-by: Namjae Jeon<namjae.jeon@samsung.com>
>
>
> [...]
>
>
>> diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
>> index 508a60b..d5b00e6 100644
>> --- a/drivers/ata/libata-scsi.c
>> +++ b/drivers/ata/libata-scsi.c
>> @@ -562,6 +562,57 @@ error:
>>  }
>>
>>  /**
>> + *      ata_get_cachestatus - Handler for to get WriteCache Status
>> + *                      using ATA_16 scsi command
>> + *      @scsidev: Device to which we are issuing command
>> + *
>> + *      LOCKING:
>> + *      Defined by the SCSI layer.  We don't really care.
>> + *
>> + *      RETURNS:
>> + *      '0' for Write Cache Disabled and on any error.
>> + *      '1' for Write Cache enabled
>> + */
>> +int ata_get_cachestatus(struct scsi_device *scsidev)
>> +{
>> +       int rc = 0;
>> +       u8 scsi_cmd[MAX_COMMAND_SIZE] = {0};
>> +       u8 *sensebuf = NULL, *argbuf = NULL;
>
>
>   No need to initialize them.
Tried to maintain the uniformity in the code for this file, at other
places it is being done like.
>
>
>> +       enum dma_data_direction data_dir;
>> +
>> +       sensebuf = kzalloc(SCSI_SENSE_BUFFERSIZE, GFP_NOIO);
>> +       if (!sensebuf)
>> +               return rc;
>> +
>> +       argbuf = kmalloc(ATA_SECT_SIZE, GFP_KERNEL);
>> +       if (argbuf == NULL)
>
>
>   Could you use an uniform NULL-check, either '!x' or 'x == NULL'?
Agreed, need to stick with one type of comparision.
>
>
>> +               goto error;
>> +
>> +       scsi_cmd[0] = ATA_16;
>> +       scsi_cmd[1]  = (4<<  1); /* PIO Data-in */
>> +       scsi_cmd[2]  = 0x0e;     /* no off.line or cc, read from dev,
>> +                               block count in sector count field */
>> +       data_dir = DMA_FROM_DEVICE;
>> +       scsi_cmd[14] = ATA_IDENTIFY_DEV;
>> +
>> +       if (!scsi_execute(scsidev, scsi_cmd, data_dir, argbuf,
>> ATA_SECT_SIZE,
>> +                               sensebuf, (10*HZ), 5, 0, NULL)) {
>> +               /*
>> +                * '6th' Bit in Word 85 Corresponds to Write Cache
>
>
>   No need for apostrophes here.
Tried to highlight the 6th bit, if this is not the convention, I will
remove this.
>
>> +                * being Enabled/disabled, Word 85 represnets the
>> +                * features supported
>> +                */
>> +               if (le16_to_cpu(((unsigned short *)argbuf)[85])&  0x20)
>>
>> +                       rc = 1;
>> +       }
>> +
>> +error:
>> +       kfree(sensebuf);
>> +       kfree(argbuf);
>> +       return rc;
>> +}
>> +
>> +/**
>>   *    ata_task_ioctl - Handler for HDIO_DRIVE_TASK ioctl
>>   *    @scsidev: Device to which we are issuing command
>>   *    @arg: User provided data for issuing command
>> diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
>> index c691fb5..a6b887d 100644
>> --- a/drivers/scsi/sd.c
>> +++ b/drivers/scsi/sd.c
>> @@ -50,6 +50,11 @@
>>  #include<linux/string_helpers.h>
>>  #include<linux/async.h>
>>  #include<linux/slab.h>
>> +
>> +#ifdef CONFIG_ATA
>
>
>   #ifdef not necessary here.
Yes, but just wanted to specifiy for code readability, as there is no
purpose to include - libata header in sd.c
>
>
>> +#include<linux/libata.h>
>> +#endif
>> +
>>  #include<linux/pm_runtime.h>
>>  #include<asm/uaccess.h>
>>  #include<asm/unaligned.h>
>> @@ -2129,7 +2134,11 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned
>> char *buffer)
>>                if (modepage == 0x3F) {
>>                        sd_printk(KERN_ERR, sdkp, "No Caching mode page "
>>                                  "present\n");
>> +#ifdef CONFIG_ATA
>> +                       goto WCE_USING_ATA;
>
>
>   Yikes.
>
>
>> +#else
>>                        goto defaults;
>> +#endif
>>                } else if ((buffer[offset]&  0x3f) != modepage) {
>>                        sd_printk(KERN_ERR, sdkp, "Got wrong page\n");
>>                        goto defaults;
>> @@ -2149,6 +2158,14 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned
>> char *buffer)
>>                                  "Uses READ/WRITE(6), disabling FUA\n");
>>                        sdkp->DPOFUA = 0;
>>                }
>> +#ifdef CONFIG_ATA
>> +WCE_USING_ATA:
>> +               if (!sdp->removable && !sdkp->WCE) {
>> +                       sd_printk(KERN_NOTICE, sdkp, "Try to check write
>> cache "
>> +                               "enable/disable using ATA command\n");
>> +                       sdkp->WCE = ata_get_cachestatus(sdp);
>> +               }
>> +#endif
>>
>>                if (sdkp->first_scan || old_wce != sdkp->WCE ||
>>                    old_rcd != sdkp->RCD || old_dpofua != sdkp->DPOFUA)
>> diff --git a/include/linux/libata.h b/include/linux/libata.h
>> index cafc09a..33fc73f 100644
>> --- a/include/linux/libata.h
>> +++ b/include/linux/libata.h
>> @@ -84,6 +84,8 @@
>>        }                                                       \
>>  })
>>
>> +#define ATA_IDENTIFY_DEV       0xEC
>> +
>
>
>   This is alerady #defined in <linux/ata.h> as ATA_CMD_ID_ATA.
Yes, will include that instead of redifining.
>
> MBR, Sergei

Please share your inputs to this.

Thanks & Regards,
Amit Sahrawat

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/1] scsi: retrieve cache mode using ATA_16 if normal routine fails
  2012-02-03 12:59 Amit Sahrawat
@ 2012-02-05 12:05 ` Sergei Shtylyov
  2012-02-06  5:40   ` Amit Sahrawat
  0 siblings, 1 reply; 14+ messages in thread
From: Sergei Shtylyov @ 2012-02-05 12:05 UTC (permalink / raw)
  To: Amit Sahrawat
  Cc: Jeff Garzik, James E.J. Bottomley, Nam-Jae Jeon, Amit Sahrawat,
	linux-ide, linux-scsi, linux-kernel

Hello.

On 03-02-2012 16:59, Amit Sahrawat wrote:

> It has been observed that a number of USB HDD's do not respond correctly

    Why are you working around this in libata-scsi.c then if it's USB HDD?

> to SCSI mode sense command(retrieve caching pages) which results in their
> Write Cache being discarded by queue requests i.e., WCE if left set to
> '0'(disabled).
> This results in a number of Filesystem corruptions, when the device
> is unplugged abruptly.

> So, in order to identify the devices correctly - give it
> a last try using ATA_16 after failure from normal routine.

    Shouldn't this be done in drivers/usb/storage somewhere?

> Signed-off-by: Amit Sahrawat<a.sahrawat@samsung.com>
> Signed-off-by: Namjae Jeon<namjae.jeon@samsung.com>

[...]

> diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
> index 508a60b..d5b00e6 100644
> --- a/drivers/ata/libata-scsi.c
> +++ b/drivers/ata/libata-scsi.c
> @@ -562,6 +562,57 @@ error:
>   }
>
>   /**
> + *      ata_get_cachestatus - Handler for to get WriteCache Status
> + *                      using ATA_16 scsi command
> + *      @scsidev: Device to which we are issuing command
> + *
> + *      LOCKING:
> + *      Defined by the SCSI layer.  We don't really care.
> + *
> + *      RETURNS:
> + *      '0' for Write Cache Disabled and on any error.
> + *      '1' for Write Cache enabled
> + */
> +int ata_get_cachestatus(struct scsi_device *scsidev)
> +{
> +	int rc = 0;
> +	u8 scsi_cmd[MAX_COMMAND_SIZE] = {0};
> +	u8 *sensebuf = NULL, *argbuf = NULL;

    No need to initialize them.

> +	enum dma_data_direction data_dir;
> +
> +	sensebuf = kzalloc(SCSI_SENSE_BUFFERSIZE, GFP_NOIO);
> +	if (!sensebuf)
> +		return rc;
> +
> +	argbuf = kmalloc(ATA_SECT_SIZE, GFP_KERNEL);
> +	if (argbuf == NULL)

    Could you use an uniform NULL-check, either '!x' or 'x == NULL'?

> +		goto error;
> +
> +	scsi_cmd[0] = ATA_16;
> +	scsi_cmd[1]  = (4<<  1); /* PIO Data-in */
> +	scsi_cmd[2]  = 0x0e;     /* no off.line or cc, read from dev,
> +				block count in sector count field */
> +	data_dir = DMA_FROM_DEVICE;
> +	scsi_cmd[14] = ATA_IDENTIFY_DEV;
> +
> +	if (!scsi_execute(scsidev, scsi_cmd, data_dir, argbuf, ATA_SECT_SIZE,
> +				sensebuf, (10*HZ), 5, 0, NULL)) {
> +		/*
> +		 * '6th' Bit in Word 85 Corresponds to Write Cache

    No need for apostrophes here.

> +		 * being Enabled/disabled, Word 85 represnets the
> +		 * features supported
> +		 */
> +		if (le16_to_cpu(((unsigned short *)argbuf)[85])&  0x20)
> +			rc = 1;
> +	}
> +
> +error:
> +	kfree(sensebuf);
> +	kfree(argbuf);
> +	return rc;
> +}
> +
> +/**
>    *	ata_task_ioctl - Handler for HDIO_DRIVE_TASK ioctl
>    *	@scsidev: Device to which we are issuing command
>    *	@arg: User provided data for issuing command
> diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
> index c691fb5..a6b887d 100644
> --- a/drivers/scsi/sd.c
> +++ b/drivers/scsi/sd.c
> @@ -50,6 +50,11 @@
>   #include<linux/string_helpers.h>
>   #include<linux/async.h>
>   #include<linux/slab.h>
> +
> +#ifdef CONFIG_ATA

    #ifdef not necessary here.

> +#include<linux/libata.h>
> +#endif
> +
>   #include<linux/pm_runtime.h>
>   #include<asm/uaccess.h>
>   #include<asm/unaligned.h>
> @@ -2129,7 +2134,11 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer)
>   		if (modepage == 0x3F) {
>   			sd_printk(KERN_ERR, sdkp, "No Caching mode page "
>   				  "present\n");
> +#ifdef CONFIG_ATA
> +			goto WCE_USING_ATA;

    Yikes.

> +#else
>   			goto defaults;
> +#endif
>   		} else if ((buffer[offset]&  0x3f) != modepage) {
>   			sd_printk(KERN_ERR, sdkp, "Got wrong page\n");
>   			goto defaults;
> @@ -2149,6 +2158,14 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer)
>   				  "Uses READ/WRITE(6), disabling FUA\n");
>   			sdkp->DPOFUA = 0;
>   		}
> +#ifdef CONFIG_ATA
> +WCE_USING_ATA:
> +		if (!sdp->removable && !sdkp->WCE) {
> +			sd_printk(KERN_NOTICE, sdkp, "Try to check write cache "
> +				"enable/disable using ATA command\n");
> +			sdkp->WCE = ata_get_cachestatus(sdp);
> +		}
> +#endif
>
>   		if (sdkp->first_scan || old_wce != sdkp->WCE ||
>   		    old_rcd != sdkp->RCD || old_dpofua != sdkp->DPOFUA)
> diff --git a/include/linux/libata.h b/include/linux/libata.h
> index cafc09a..33fc73f 100644
> --- a/include/linux/libata.h
> +++ b/include/linux/libata.h
> @@ -84,6 +84,8 @@
>   	}							\
>   })
>
> +#define ATA_IDENTIFY_DEV	0xEC
> +

    This is alerady #defined in <linux/ata.h> as ATA_CMD_ID_ATA.

MBR, Sergei

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 1/1] scsi: retrieve cache mode using ATA_16 if normal routine fails
@ 2012-02-03 12:59 Amit Sahrawat
  2012-02-05 12:05 ` Sergei Shtylyov
  0 siblings, 1 reply; 14+ messages in thread
From: Amit Sahrawat @ 2012-02-03 12:59 UTC (permalink / raw)
  To: Jeff Garzik, James E.J. Bottomley
  Cc: Nam-Jae Jeon, Amit Sahrawat, linux-ide, linux-scsi, linux-kernel,
	Amit Sahrawat

It has been observed that a number of USB HDD's do not respond correctly
to SCSI mode sense command(retrieve caching pages) which results in their
Write Cache being discarded by queue requests i.e., WCE if left set to
'0'(disabled).
This results in a number of Filesystem corruptions, when the device
is unplugged abruptly.

So, in order to identify the devices correctly - give it
a last try using ATA_16 after failure from normal routine.

Signed-off-by: Amit Sahrawat <a.sahrawat@samsung.com>
Signed-off-by: Namjae Jeon <namjae.jeon@samsung.com>

---
 drivers/ata/libata-scsi.c |   51 +++++++++++++++++++++++++++++++++++++++++++++
 drivers/scsi/sd.c         |   17 +++++++++++++++
 include/linux/libata.h    |    3 ++
 3 files changed, 71 insertions(+), 0 deletions(-)

diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 508a60b..d5b00e6 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -562,6 +562,57 @@ error:
 }
 
 /**
+ *      ata_get_cachestatus - Handler for to get WriteCache Status
+ *                      using ATA_16 scsi command
+ *      @scsidev: Device to which we are issuing command
+ *
+ *      LOCKING:
+ *      Defined by the SCSI layer.  We don't really care.
+ *
+ *      RETURNS:
+ *      '0' for Write Cache Disabled and on any error.
+ *      '1' for Write Cache enabled
+ */
+int ata_get_cachestatus(struct scsi_device *scsidev)
+{
+	int rc = 0;
+	u8 scsi_cmd[MAX_COMMAND_SIZE] = {0};
+	u8 *sensebuf = NULL, *argbuf = NULL;
+	enum dma_data_direction data_dir;
+
+	sensebuf = kzalloc(SCSI_SENSE_BUFFERSIZE, GFP_NOIO);
+	if (!sensebuf)
+		return rc;
+
+	argbuf = kmalloc(ATA_SECT_SIZE, GFP_KERNEL);
+	if (argbuf == NULL)
+		goto error;
+
+	scsi_cmd[0] = ATA_16;
+	scsi_cmd[1]  = (4 << 1); /* PIO Data-in */
+	scsi_cmd[2]  = 0x0e;     /* no off.line or cc, read from dev,
+				block count in sector count field */
+	data_dir = DMA_FROM_DEVICE;
+	scsi_cmd[14] = ATA_IDENTIFY_DEV;
+
+	if (!scsi_execute(scsidev, scsi_cmd, data_dir, argbuf, ATA_SECT_SIZE,
+				sensebuf, (10*HZ), 5, 0, NULL)) {
+		/*
+		 * '6th' Bit in Word 85 Corresponds to Write Cache
+		 * being Enabled/disabled, Word 85 represnets the
+		 * features supported
+		 */
+		if (le16_to_cpu(((unsigned short *)argbuf)[85]) & 0x20)
+			rc = 1;
+	}
+
+error:
+	kfree(sensebuf);
+	kfree(argbuf);
+	return rc;
+}
+
+/**
  *	ata_task_ioctl - Handler for HDIO_DRIVE_TASK ioctl
  *	@scsidev: Device to which we are issuing command
  *	@arg: User provided data for issuing command
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index c691fb5..a6b887d 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -50,6 +50,11 @@
 #include <linux/string_helpers.h>
 #include <linux/async.h>
 #include <linux/slab.h>
+
+#ifdef CONFIG_ATA
+#include <linux/libata.h>
+#endif
+
 #include <linux/pm_runtime.h>
 #include <asm/uaccess.h>
 #include <asm/unaligned.h>
@@ -2129,7 +2134,11 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer)
 		if (modepage == 0x3F) {
 			sd_printk(KERN_ERR, sdkp, "No Caching mode page "
 				  "present\n");
+#ifdef CONFIG_ATA
+			goto WCE_USING_ATA;
+#else
 			goto defaults;
+#endif
 		} else if ((buffer[offset] & 0x3f) != modepage) {
 			sd_printk(KERN_ERR, sdkp, "Got wrong page\n");
 			goto defaults;
@@ -2149,6 +2158,14 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer)
 				  "Uses READ/WRITE(6), disabling FUA\n");
 			sdkp->DPOFUA = 0;
 		}
+#ifdef CONFIG_ATA
+WCE_USING_ATA:
+		if (!sdp->removable && !sdkp->WCE) {
+			sd_printk(KERN_NOTICE, sdkp, "Try to check write cache "
+				"enable/disable using ATA command\n");
+			sdkp->WCE = ata_get_cachestatus(sdp);
+		}
+#endif
 
 		if (sdkp->first_scan || old_wce != sdkp->WCE ||
 		    old_rcd != sdkp->RCD || old_dpofua != sdkp->DPOFUA)
diff --git a/include/linux/libata.h b/include/linux/libata.h
index cafc09a..33fc73f 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -84,6 +84,8 @@
 	}							\
 })
 
+#define ATA_IDENTIFY_DEV	0xEC
+
 /* NEW: debug levels */
 #define HAVE_LIBATA_MSG 1
 
@@ -990,6 +992,7 @@ extern void ata_host_init(struct ata_host *, struct device *,
 			  unsigned long, struct ata_port_operations *);
 extern int ata_scsi_detect(struct scsi_host_template *sht);
 extern int ata_scsi_ioctl(struct scsi_device *dev, int cmd, void __user *arg);
+extern int ata_get_cachestatus(struct scsi_device *scsidev);
 extern int ata_scsi_queuecmd(struct Scsi_Host *h, struct scsi_cmnd *cmd);
 extern int ata_sas_scsi_ioctl(struct ata_port *ap, struct scsi_device *dev,
 			    int cmd, void __user *arg);
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2012-02-06  5:40 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-12-12 11:18 [PATCH 1/1] scsi: retrieve cache mode using ATA_16 if normal routine fails Amit Sahrawat
2011-12-12 12:51 ` James Bottomley
2011-12-13  0:20   ` Namjae Jeon
     [not found]     ` <CADDb1s2SOK5sC3N0OOdkBrPuDKc2d2A4z4yso4jYs=1rbxNmkA@mail.gmail.com>
2011-12-13  4:56       ` Amit Sahrawat
2011-12-13  8:53     ` James Bottomley
2011-12-13 12:15       ` Amit Sahrawat
2011-12-13 20:38       ` Jeff Garzik
2011-12-14  3:44         ` Amit Sahrawat
2011-12-14  7:39           ` James Bottomley
2011-12-15  0:25             ` Namjae Jeon
2012-01-27  5:20               ` Amit Sahrawat
2012-02-03 12:59 Amit Sahrawat
2012-02-05 12:05 ` Sergei Shtylyov
2012-02-06  5:40   ` Amit Sahrawat

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).