diff options
Diffstat (limited to 'drivers/scsi/sd.c')
-rw-r--r-- | drivers/scsi/sd.c | 99 |
1 files changed, 75 insertions, 24 deletions
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 956496182c80..365024b0c407 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c | |||
@@ -583,7 +583,7 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) | |||
583 | * quietly refuse to do anything to a changed disc until | 583 | * quietly refuse to do anything to a changed disc until |
584 | * the changed bit has been reset | 584 | * the changed bit has been reset |
585 | */ | 585 | */ |
586 | /* printk("SCSI disk has been changed. Prohibiting further I/O.\n"); */ | 586 | /* printk("SCSI disk has been changed or is not present. Prohibiting further I/O.\n"); */ |
587 | goto out; | 587 | goto out; |
588 | } | 588 | } |
589 | 589 | ||
@@ -1023,7 +1023,6 @@ static int sd_media_changed(struct gendisk *disk) | |||
1023 | */ | 1023 | */ |
1024 | if (!scsi_device_online(sdp)) { | 1024 | if (!scsi_device_online(sdp)) { |
1025 | set_media_not_present(sdkp); | 1025 | set_media_not_present(sdkp); |
1026 | retval = 1; | ||
1027 | goto out; | 1026 | goto out; |
1028 | } | 1027 | } |
1029 | 1028 | ||
@@ -1054,7 +1053,6 @@ static int sd_media_changed(struct gendisk *disk) | |||
1054 | /* 0x3a is medium not present */ | 1053 | /* 0x3a is medium not present */ |
1055 | sshdr->asc == 0x3a)) { | 1054 | sshdr->asc == 0x3a)) { |
1056 | set_media_not_present(sdkp); | 1055 | set_media_not_present(sdkp); |
1057 | retval = 1; | ||
1058 | goto out; | 1056 | goto out; |
1059 | } | 1057 | } |
1060 | 1058 | ||
@@ -1065,12 +1063,27 @@ static int sd_media_changed(struct gendisk *disk) | |||
1065 | */ | 1063 | */ |
1066 | sdkp->media_present = 1; | 1064 | sdkp->media_present = 1; |
1067 | 1065 | ||
1068 | retval = sdp->changed; | ||
1069 | sdp->changed = 0; | ||
1070 | out: | 1066 | out: |
1071 | if (retval != sdkp->previous_state) | 1067 | /* |
1068 | * Report a media change under the following conditions: | ||
1069 | * | ||
1070 | * Medium is present now and wasn't present before. | ||
1071 | * Medium wasn't present before and is present now. | ||
1072 | * Medium was present at all times, but it changed while | ||
1073 | * we weren't looking (sdp->changed is set). | ||
1074 | * | ||
1075 | * If there was no medium before and there is no medium now then | ||
1076 | * don't report a change, even if a medium was inserted and removed | ||
1077 | * while we weren't looking. | ||
1078 | */ | ||
1079 | retval = (sdkp->media_present != sdkp->previous_state || | ||
1080 | (sdkp->media_present && sdp->changed)); | ||
1081 | if (retval) | ||
1072 | sdev_evt_send_simple(sdp, SDEV_EVT_MEDIA_CHANGE, GFP_KERNEL); | 1082 | sdev_evt_send_simple(sdp, SDEV_EVT_MEDIA_CHANGE, GFP_KERNEL); |
1073 | sdkp->previous_state = retval; | 1083 | sdkp->previous_state = sdkp->media_present; |
1084 | |||
1085 | /* sdp->changed indicates medium was changed or is not present */ | ||
1086 | sdp->changed = !sdkp->media_present; | ||
1074 | kfree(sshdr); | 1087 | kfree(sshdr); |
1075 | return retval; | 1088 | return retval; |
1076 | } | 1089 | } |
@@ -1175,6 +1188,12 @@ static unsigned int sd_completed_bytes(struct scsi_cmnd *scmd) | |||
1175 | u64 end_lba = blk_rq_pos(scmd->request) + (scsi_bufflen(scmd) / 512); | 1188 | u64 end_lba = blk_rq_pos(scmd->request) + (scsi_bufflen(scmd) / 512); |
1176 | u64 bad_lba; | 1189 | u64 bad_lba; |
1177 | int info_valid; | 1190 | int info_valid; |
1191 | /* | ||
1192 | * resid is optional but mostly filled in. When it's unused, | ||
1193 | * its value is zero, so we assume the whole buffer transferred | ||
1194 | */ | ||
1195 | unsigned int transferred = scsi_bufflen(scmd) - scsi_get_resid(scmd); | ||
1196 | unsigned int good_bytes; | ||
1178 | 1197 | ||
1179 | if (scmd->request->cmd_type != REQ_TYPE_FS) | 1198 | if (scmd->request->cmd_type != REQ_TYPE_FS) |
1180 | return 0; | 1199 | return 0; |
@@ -1208,7 +1227,8 @@ static unsigned int sd_completed_bytes(struct scsi_cmnd *scmd) | |||
1208 | /* This computation should always be done in terms of | 1227 | /* This computation should always be done in terms of |
1209 | * the resolution of the device's medium. | 1228 | * the resolution of the device's medium. |
1210 | */ | 1229 | */ |
1211 | return (bad_lba - start_lba) * scmd->device->sector_size; | 1230 | good_bytes = (bad_lba - start_lba) * scmd->device->sector_size; |
1231 | return min(good_bytes, transferred); | ||
1212 | } | 1232 | } |
1213 | 1233 | ||
1214 | /** | 1234 | /** |
@@ -1902,10 +1922,14 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer) | |||
1902 | int old_rcd = sdkp->RCD; | 1922 | int old_rcd = sdkp->RCD; |
1903 | int old_dpofua = sdkp->DPOFUA; | 1923 | int old_dpofua = sdkp->DPOFUA; |
1904 | 1924 | ||
1905 | if (sdp->skip_ms_page_8) | 1925 | if (sdp->skip_ms_page_8) { |
1906 | goto defaults; | 1926 | if (sdp->type == TYPE_RBC) |
1907 | 1927 | goto defaults; | |
1908 | if (sdp->type == TYPE_RBC) { | 1928 | else { |
1929 | modepage = 0x3F; | ||
1930 | dbd = 0; | ||
1931 | } | ||
1932 | } else if (sdp->type == TYPE_RBC) { | ||
1909 | modepage = 6; | 1933 | modepage = 6; |
1910 | dbd = 8; | 1934 | dbd = 8; |
1911 | } else { | 1935 | } else { |
@@ -1933,13 +1957,11 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer) | |||
1933 | */ | 1957 | */ |
1934 | if (len < 3) | 1958 | if (len < 3) |
1935 | goto bad_sense; | 1959 | goto bad_sense; |
1936 | if (len > 20) | 1960 | else if (len > SD_BUF_SIZE) { |
1937 | len = 20; | 1961 | sd_printk(KERN_NOTICE, sdkp, "Truncating mode parameter " |
1938 | 1962 | "data from %d to %d bytes\n", len, SD_BUF_SIZE); | |
1939 | /* Take headers and block descriptors into account */ | 1963 | len = SD_BUF_SIZE; |
1940 | len += data.header_length + data.block_descriptor_length; | 1964 | } |
1941 | if (len > SD_BUF_SIZE) | ||
1942 | goto bad_sense; | ||
1943 | 1965 | ||
1944 | /* Get the data */ | 1966 | /* Get the data */ |
1945 | res = sd_do_mode_sense(sdp, dbd, modepage, buffer, len, &data, &sshdr); | 1967 | res = sd_do_mode_sense(sdp, dbd, modepage, buffer, len, &data, &sshdr); |
@@ -1947,16 +1969,45 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer) | |||
1947 | if (scsi_status_is_good(res)) { | 1969 | if (scsi_status_is_good(res)) { |
1948 | int offset = data.header_length + data.block_descriptor_length; | 1970 | int offset = data.header_length + data.block_descriptor_length; |
1949 | 1971 | ||
1950 | if (offset >= SD_BUF_SIZE - 2) { | 1972 | while (offset < len) { |
1951 | sd_printk(KERN_ERR, sdkp, "Malformed MODE SENSE response\n"); | 1973 | u8 page_code = buffer[offset] & 0x3F; |
1952 | goto defaults; | 1974 | u8 spf = buffer[offset] & 0x40; |
1975 | |||
1976 | if (page_code == 8 || page_code == 6) { | ||
1977 | /* We're interested only in the first 3 bytes. | ||
1978 | */ | ||
1979 | if (len - offset <= 2) { | ||
1980 | sd_printk(KERN_ERR, sdkp, "Incomplete " | ||
1981 | "mode parameter data\n"); | ||
1982 | goto defaults; | ||
1983 | } else { | ||
1984 | modepage = page_code; | ||
1985 | goto Page_found; | ||
1986 | } | ||
1987 | } else { | ||
1988 | /* Go to the next page */ | ||
1989 | if (spf && len - offset > 3) | ||
1990 | offset += 4 + (buffer[offset+2] << 8) + | ||
1991 | buffer[offset+3]; | ||
1992 | else if (!spf && len - offset > 1) | ||
1993 | offset += 2 + buffer[offset+1]; | ||
1994 | else { | ||
1995 | sd_printk(KERN_ERR, sdkp, "Incomplete " | ||
1996 | "mode parameter data\n"); | ||
1997 | goto defaults; | ||
1998 | } | ||
1999 | } | ||
1953 | } | 2000 | } |
1954 | 2001 | ||
1955 | if ((buffer[offset] & 0x3f) != modepage) { | 2002 | if (modepage == 0x3F) { |
2003 | sd_printk(KERN_ERR, sdkp, "No Caching mode page " | ||
2004 | "present\n"); | ||
2005 | goto defaults; | ||
2006 | } else if ((buffer[offset] & 0x3f) != modepage) { | ||
1956 | sd_printk(KERN_ERR, sdkp, "Got wrong page\n"); | 2007 | sd_printk(KERN_ERR, sdkp, "Got wrong page\n"); |
1957 | goto defaults; | 2008 | goto defaults; |
1958 | } | 2009 | } |
1959 | 2010 | Page_found: | |
1960 | if (modepage == 8) { | 2011 | if (modepage == 8) { |
1961 | sdkp->WCE = ((buffer[offset + 2] & 0x04) != 0); | 2012 | sdkp->WCE = ((buffer[offset + 2] & 0x04) != 0); |
1962 | sdkp->RCD = ((buffer[offset + 2] & 0x01) != 0); | 2013 | sdkp->RCD = ((buffer[offset + 2] & 0x01) != 0); |