aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/sd.c
diff options
context:
space:
mode:
authorLuben Tuikov <ltuikov@yahoo.com>2010-10-23 00:24:36 -0400
committerJames Bottomley <James.Bottomley@suse.de>2010-12-21 13:23:53 -0500
commit24d720b726c1a85f1962831ac30ad4d2ef8276b1 (patch)
tree35d450ec6faa907e73717541a9921d32c6f2301f /drivers/scsi/sd.c
parent00f0254ed9b19164d416dc2e3c2e81eda55a6faf (diff)
[SCSI] Retrieve the Caching mode page
Some kernel transport drivers unconditionally disable retrieval of the Caching mode page. One such for example is the BBB/CBI transport over USB.  Such a restraint is too harsh as some devices do support the Caching mode page. Unconditionally enabling the retrieval of this mode page over those transports at their transport code level may result in some devices failing and becoming unusable. This patch implements a method of retrieving the Caching mode page without unconditionally enabling it in the transports which unconditionally disable it. The idea is to ask for all supported pages, page code 0x3F, and then search for the Caching mode page in the mode parameter data returned. The sd driver already asks for all the mode pages supported by the attached device by setting the page code to 0x3F in order to find out if the media is write protected by reading the WP bit in the Device Specific Parameter field. It then attempts to retrieve only the Caching mode page by setting the page code to 8 and actually attempting to retrieve it if and only if the transport allows it. The method implemented here is that if the transport doesn't allow retrieval of the Caching mode page and the device is not RBC, then we ask for all pages supported by setting the page code to 0x3F (similarly to how the WP bit is retrieved above), and then we search for the Caching mode page in the mode parameter data returned. With this patch, devices over SATA, report this (no change): Oct 22 18:45:58 localhost kernel: sd 0:0:0:0: [sda] 976773168 512-byte logical blocks: (500 GB/465 GiB) Oct 22 18:45:58 localhost kernel: sd 0:0:0:0: Attached scsi generic sg0 type 0 Oct 22 18:45:58 localhost kernel: sd 0:0:0:0: [sda] Write Protect is off Oct 22 18:45:58 localhost kernel: sd 0:0:0:0: [sda] Mode Sense: 00 3a 00 00 Oct 22 18:45:58 localhost kernel: sd 0:0:0:0: [sda] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA Smart devices report their Caching mode page. This is a change where we'd previously see the kernel making assumption about the device's cache being write-through: Oct 22 18:45:58 localhost kernel: sd 6:0:0:0: Attached scsi generic sg2 type 0 Oct 22 18:45:58 localhost kernel: sd 6:0:0:0: [sdb] 610472646 4096-byte logical blocks: (2.50 TB/2.27 TiB) Oct 22 18:45:58 localhost kernel: sd 6:0:0:0: [sdb] Write Protect is off Oct 22 18:45:58 localhost kernel: sd 6:0:0:0: [sdb] Mode Sense: 47 00 10 08 Oct 22 18:45:58 localhost kernel: sd 6:0:0:0: [sdb] Write cache: enabled, read cache: enabled, supports DPO and FUA And "dumb" devices over BBB, are correctly shown not to support reporting the Caching mode page: Oct 22 18:49:06 localhost kernel: sd 7:0:0:0: [sdc] 15663104 512-byte logical blocks: (8.01 GB/7.46 GiB) Oct 22 18:49:06 localhost kernel: sd 7:0:0:0: [sdc] Write Protect is off Oct 22 18:49:06 localhost kernel: sd 7:0:0:0: [sdc] Mode Sense: 23 00 00 00 Oct 22 18:49:06 localhost kernel: sd 7:0:0:0: [sdc] No Caching mode page present Oct 22 18:49:06 localhost kernel: sd 7:0:0:0: [sdc] Assuming drive cache: write through Signed-off-by: Luben Tuikov <ltuikov@yahoo.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/sd.c')
-rw-r--r--drivers/scsi/sd.c63
1 files changed, 47 insertions, 16 deletions
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 26f9d54a9c92..d8e2caf9f468 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -1915,10 +1915,14 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer)
1915 int old_rcd = sdkp->RCD; 1915 int old_rcd = sdkp->RCD;
1916 int old_dpofua = sdkp->DPOFUA; 1916 int old_dpofua = sdkp->DPOFUA;
1917 1917
1918 if (sdp->skip_ms_page_8) 1918 if (sdp->skip_ms_page_8) {
1919 goto defaults; 1919 if (sdp->type == TYPE_RBC)
1920 1920 goto defaults;
1921 if (sdp->type == TYPE_RBC) { 1921 else {
1922 modepage = 0x3F;
1923 dbd = 0;
1924 }
1925 } else if (sdp->type == TYPE_RBC) {
1922 modepage = 6; 1926 modepage = 6;
1923 dbd = 8; 1927 dbd = 8;
1924 } else { 1928 } else {
@@ -1946,13 +1950,11 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer)
1946 */ 1950 */
1947 if (len < 3) 1951 if (len < 3)
1948 goto bad_sense; 1952 goto bad_sense;
1949 if (len > 20) 1953 else if (len > SD_BUF_SIZE) {
1950 len = 20; 1954 sd_printk(KERN_NOTICE, sdkp, "Truncating mode parameter "
1951 1955 "data from %d to %d bytes\n", len, SD_BUF_SIZE);
1952 /* Take headers and block descriptors into account */ 1956 len = SD_BUF_SIZE;
1953 len += data.header_length + data.block_descriptor_length; 1957 }
1954 if (len > SD_BUF_SIZE)
1955 goto bad_sense;
1956 1958
1957 /* Get the data */ 1959 /* Get the data */
1958 res = sd_do_mode_sense(sdp, dbd, modepage, buffer, len, &data, &sshdr); 1960 res = sd_do_mode_sense(sdp, dbd, modepage, buffer, len, &data, &sshdr);
@@ -1960,16 +1962,45 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer)
1960 if (scsi_status_is_good(res)) { 1962 if (scsi_status_is_good(res)) {
1961 int offset = data.header_length + data.block_descriptor_length; 1963 int offset = data.header_length + data.block_descriptor_length;
1962 1964
1963 if (offset >= SD_BUF_SIZE - 2) { 1965 while (offset < len) {
1964 sd_printk(KERN_ERR, sdkp, "Malformed MODE SENSE response\n"); 1966 u8 page_code = buffer[offset] & 0x3F;
1965 goto defaults; 1967 u8 spf = buffer[offset] & 0x40;
1968
1969 if (page_code == 8 || page_code == 6) {
1970 /* We're interested only in the first 3 bytes.
1971 */
1972 if (len - offset <= 2) {
1973 sd_printk(KERN_ERR, sdkp, "Incomplete "
1974 "mode parameter data\n");
1975 goto defaults;
1976 } else {
1977 modepage = page_code;
1978 goto Page_found;
1979 }
1980 } else {
1981 /* Go to the next page */
1982 if (spf && len - offset > 3)
1983 offset += 4 + (buffer[offset+2] << 8) +
1984 buffer[offset+3];
1985 else if (!spf && len - offset > 1)
1986 offset += 2 + buffer[offset+1];
1987 else {
1988 sd_printk(KERN_ERR, sdkp, "Incomplete "
1989 "mode parameter data\n");
1990 goto defaults;
1991 }
1992 }
1966 } 1993 }
1967 1994
1968 if ((buffer[offset] & 0x3f) != modepage) { 1995 if (modepage == 0x3F) {
1996 sd_printk(KERN_ERR, sdkp, "No Caching mode page "
1997 "present\n");
1998 goto defaults;
1999 } else if ((buffer[offset] & 0x3f) != modepage) {
1969 sd_printk(KERN_ERR, sdkp, "Got wrong page\n"); 2000 sd_printk(KERN_ERR, sdkp, "Got wrong page\n");
1970 goto defaults; 2001 goto defaults;
1971 } 2002 }
1972 2003 Page_found:
1973 if (modepage == 8) { 2004 if (modepage == 8) {
1974 sdkp->WCE = ((buffer[offset + 2] & 0x04) != 0); 2005 sdkp->WCE = ((buffer[offset + 2] & 0x04) != 0);
1975 sdkp->RCD = ((buffer[offset + 2] & 0x01) != 0); 2006 sdkp->RCD = ((buffer[offset + 2] & 0x01) != 0);