Message ID | 1329375141-6944-1-git-send-email-amit.sahrawat83@gmail.com |
---|---|
State | Not Applicable |
Headers | show |
On Thu, 2012-02-16 at 12:22 +0530, Amit Sahrawat wrote: > diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c > index c691fb5..3ca507a 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,15 @@ 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 > + I already said before, this is a non starter: we can't randomly send SCSI encapsulated ATA commands to disks from sd. What we can do is give you a WCE variable you can change on the fly in sysfs via whatever mechanism is most appropriate (but this would have to be a mechanism external to sd.c). Alternatively, you can co-opt the USB quirks handling to set it for you. James -- To unsubscribe from this list: send the line "unsubscribe linux-ide" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
2012/2/16 James Bottomley <James.Bottomley@hansenpartnership.com>: > On Thu, 2012-02-16 at 12:22 +0530, Amit Sahrawat wrote: > >> diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c >> index c691fb5..3ca507a 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,15 @@ 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 >> + > > I already said before, this is a non starter: we can't randomly send > SCSI encapsulated ATA commands to disks from sd. What we can do is give > you a WCE variable you can change on the fly in sysfs via whatever > mechanism is most appropriate (but this would have to be a mechanism > external to sd.c). Oops.. it is mistake. we will make patch v2 included setting via sysfs. Thanks for your reply. > > Alternatively, you can co-opt the USB quirks handling to set it for you. > > James > > > -- > To unsubscribe from this list: send the line "unsubscribe linux-ide" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe linux-ide" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Hi James, Few queries relating to solution for this long pending problem. As per your suggestions - it is clear - we cannot have this as part of default routine to retrieve WCE using ATA - as for some USB HDD - it will result in halting their operations. So, 1) USB quirks -> i think this will only be a workaround for few USB hard disks - wherein we can their add their entries in the quirks list and control this WC. So, this wont be a solution which can be used as part of a long term solution. 2) As part of 'sysfs' interface - there is already an array for cache_types in sd.c - Can we make an entry in this array for "write back(ata cmd)" and make corresponding changes - to reflect this when we do " echo "write back(ata cmd) > /sys/class/scsi_disk/<>/cache_type". So, these changes won't be part of default routine - but this will still need minor changes in sd.c - will those changes be acceptable? sd_store_cache_type()->revalidate_disk()->sd_revalidate_disk()->sd_read_cache_type() Please share your opinion to bring out a solution to this. Thanks & Regards, Amit Sahrawat On Thu, Feb 16, 2012 at 6:58 PM, James Bottomley <James.Bottomley@hansenpartnership.com> wrote: > On Thu, 2012-02-16 at 12:22 +0530, Amit Sahrawat wrote: > >> diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c >> index c691fb5..3ca507a 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,15 @@ 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 >> + > > I already said before, this is a non starter: we can't randomly send > SCSI encapsulated ATA commands to disks from sd. What we can do is give > you a WCE variable you can change on the fly in sysfs via whatever > mechanism is most appropriate (but this would have to be a mechanism > external to sd.c). > > Alternatively, you can co-opt the USB quirks handling to set it for you. > > James > > -- To unsubscribe from this list: send the line "unsubscribe linux-ide" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 508a60b..218df4f 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -561,6 +561,45 @@ error: return rc; } +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; + int cmd_result; + sensebuf = kzalloc(SCSI_SENSE_BUFFERSIZE, GFP_NOIO); + if (!sensebuf) + return rc; + + argbuf = kzalloc(ATA_SECT_SIZE, GFP_KERNEL); + if (!argbuf) + 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_CMD_ID_ATA; + + 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 diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index c691fb5..3ca507a 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,15 @@ 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..20c5c33 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -990,6 +990,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);