aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/sd.c122
-rw-r--r--drivers/scsi/sd.h23
2 files changed, 141 insertions, 4 deletions
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 99dddcae7851..56b9501d12f3 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -233,6 +233,24 @@ sd_show_allow_restart(struct device *dev, struct device_attribute *attr,
233 return snprintf(buf, 40, "%d\n", sdkp->device->allow_restart); 233 return snprintf(buf, 40, "%d\n", sdkp->device->allow_restart);
234} 234}
235 235
236static ssize_t
237sd_show_protection_type(struct device *dev, struct device_attribute *attr,
238 char *buf)
239{
240 struct scsi_disk *sdkp = to_scsi_disk(dev);
241
242 return snprintf(buf, 20, "%u\n", sdkp->protection_type);
243}
244
245static ssize_t
246sd_show_app_tag_own(struct device *dev, struct device_attribute *attr,
247 char *buf)
248{
249 struct scsi_disk *sdkp = to_scsi_disk(dev);
250
251 return snprintf(buf, 20, "%u\n", sdkp->ATO);
252}
253
236static struct device_attribute sd_disk_attrs[] = { 254static struct device_attribute sd_disk_attrs[] = {
237 __ATTR(cache_type, S_IRUGO|S_IWUSR, sd_show_cache_type, 255 __ATTR(cache_type, S_IRUGO|S_IWUSR, sd_show_cache_type,
238 sd_store_cache_type), 256 sd_store_cache_type),
@@ -241,6 +259,8 @@ static struct device_attribute sd_disk_attrs[] = {
241 sd_store_allow_restart), 259 sd_store_allow_restart),
242 __ATTR(manage_start_stop, S_IRUGO|S_IWUSR, sd_show_manage_start_stop, 260 __ATTR(manage_start_stop, S_IRUGO|S_IWUSR, sd_show_manage_start_stop,
243 sd_store_manage_start_stop), 261 sd_store_manage_start_stop),
262 __ATTR(protection_type, S_IRUGO, sd_show_protection_type, NULL),
263 __ATTR(app_tag_own, S_IRUGO, sd_show_app_tag_own, NULL),
244 __ATTR_NULL, 264 __ATTR_NULL,
245}; 265};
246 266
@@ -1164,6 +1184,49 @@ sd_spinup_disk(struct scsi_disk *sdkp)
1164 } 1184 }
1165} 1185}
1166 1186
1187
1188/*
1189 * Determine whether disk supports Data Integrity Field.
1190 */
1191void sd_read_protection_type(struct scsi_disk *sdkp, unsigned char *buffer)
1192{
1193 struct scsi_device *sdp = sdkp->device;
1194 u8 type;
1195
1196 if (scsi_device_protection(sdp) == 0 || (buffer[12] & 1) == 0)
1197 type = 0;
1198 else
1199 type = ((buffer[12] >> 1) & 7) + 1; /* P_TYPE 0 = Type 1 */
1200
1201 switch (type) {
1202 case SD_DIF_TYPE0_PROTECTION:
1203 sdkp->protection_type = 0;
1204 break;
1205
1206 case SD_DIF_TYPE1_PROTECTION:
1207 case SD_DIF_TYPE3_PROTECTION:
1208 sdkp->protection_type = type;
1209 break;
1210
1211 case SD_DIF_TYPE2_PROTECTION:
1212 sd_printk(KERN_ERR, sdkp, "formatted with DIF Type 2 " \
1213 "protection which is currently unsupported. " \
1214 "Disabling disk!\n");
1215 goto disable;
1216
1217 default:
1218 sd_printk(KERN_ERR, sdkp, "formatted with unknown " \
1219 "protection type %d. Disabling disk!\n", type);
1220 goto disable;
1221 }
1222
1223 return;
1224
1225disable:
1226 sdkp->protection_type = 0;
1227 sdkp->capacity = 0;
1228}
1229
1167/* 1230/*
1168 * read disk capacity 1231 * read disk capacity
1169 */ 1232 */
@@ -1173,7 +1236,8 @@ sd_read_capacity(struct scsi_disk *sdkp, unsigned char *buffer)
1173 unsigned char cmd[16]; 1236 unsigned char cmd[16];
1174 int the_result, retries; 1237 int the_result, retries;
1175 int sector_size = 0; 1238 int sector_size = 0;
1176 int longrc = 0; 1239 /* Force READ CAPACITY(16) when PROTECT=1 */
1240 int longrc = scsi_device_protection(sdkp->device) ? 1 : 0;
1177 struct scsi_sense_hdr sshdr; 1241 struct scsi_sense_hdr sshdr;
1178 int sense_valid = 0; 1242 int sense_valid = 0;
1179 struct scsi_device *sdp = sdkp->device; 1243 struct scsi_device *sdp = sdkp->device;
@@ -1185,8 +1249,8 @@ repeat:
1185 memset((void *) cmd, 0, 16); 1249 memset((void *) cmd, 0, 16);
1186 cmd[0] = SERVICE_ACTION_IN; 1250 cmd[0] = SERVICE_ACTION_IN;
1187 cmd[1] = SAI_READ_CAPACITY_16; 1251 cmd[1] = SAI_READ_CAPACITY_16;
1188 cmd[13] = 12; 1252 cmd[13] = 13;
1189 memset((void *) buffer, 0, 12); 1253 memset((void *) buffer, 0, 13);
1190 } else { 1254 } else {
1191 cmd[0] = READ_CAPACITY; 1255 cmd[0] = READ_CAPACITY;
1192 memset((void *) &cmd[1], 0, 9); 1256 memset((void *) &cmd[1], 0, 9);
@@ -1194,7 +1258,7 @@ repeat:
1194 } 1258 }
1195 1259
1196 the_result = scsi_execute_req(sdp, cmd, DMA_FROM_DEVICE, 1260 the_result = scsi_execute_req(sdp, cmd, DMA_FROM_DEVICE,
1197 buffer, longrc ? 12 : 8, &sshdr, 1261 buffer, longrc ? 13 : 8, &sshdr,
1198 SD_TIMEOUT, SD_MAX_RETRIES); 1262 SD_TIMEOUT, SD_MAX_RETRIES);
1199 1263
1200 if (media_not_present(sdkp, &sshdr)) 1264 if (media_not_present(sdkp, &sshdr))
@@ -1269,6 +1333,8 @@ repeat:
1269 1333
1270 sector_size = (buffer[8] << 24) | 1334 sector_size = (buffer[8] << 24) |
1271 (buffer[9] << 16) | (buffer[10] << 8) | buffer[11]; 1335 (buffer[9] << 16) | (buffer[10] << 8) | buffer[11];
1336
1337 sd_read_protection_type(sdkp, buffer);
1272 } 1338 }
1273 1339
1274 /* Some devices return the total number of sectors, not the 1340 /* Some devices return the total number of sectors, not the
@@ -1530,6 +1596,52 @@ defaults:
1530 sdkp->DPOFUA = 0; 1596 sdkp->DPOFUA = 0;
1531} 1597}
1532 1598
1599/*
1600 * The ATO bit indicates whether the DIF application tag is available
1601 * for use by the operating system.
1602 */
1603void sd_read_app_tag_own(struct scsi_disk *sdkp, unsigned char *buffer)
1604{
1605 int res, offset;
1606 struct scsi_device *sdp = sdkp->device;
1607 struct scsi_mode_data data;
1608 struct scsi_sense_hdr sshdr;
1609
1610 if (sdp->type != TYPE_DISK)
1611 return;
1612
1613 if (sdkp->protection_type == 0)
1614 return;
1615
1616 res = scsi_mode_sense(sdp, 1, 0x0a, buffer, 36, SD_TIMEOUT,
1617 SD_MAX_RETRIES, &data, &sshdr);
1618
1619 if (!scsi_status_is_good(res) || !data.header_length ||
1620 data.length < 6) {
1621 sd_printk(KERN_WARNING, sdkp,
1622 "getting Control mode page failed, assume no ATO\n");
1623
1624 if (scsi_sense_valid(&sshdr))
1625 sd_print_sense_hdr(sdkp, &sshdr);
1626
1627 return;
1628 }
1629
1630 offset = data.header_length + data.block_descriptor_length;
1631
1632 if ((buffer[offset] & 0x3f) != 0x0a) {
1633 sd_printk(KERN_ERR, sdkp, "ATO Got wrong page\n");
1634 return;
1635 }
1636
1637 if ((buffer[offset + 5] & 0x80) == 0)
1638 return;
1639
1640 sdkp->ATO = 1;
1641
1642 return;
1643}
1644
1533/** 1645/**
1534 * sd_revalidate_disk - called the first time a new disk is seen, 1646 * sd_revalidate_disk - called the first time a new disk is seen,
1535 * performs disk spin up, read_capacity, etc. 1647 * performs disk spin up, read_capacity, etc.
@@ -1566,6 +1678,7 @@ static int sd_revalidate_disk(struct gendisk *disk)
1566 sdkp->write_prot = 0; 1678 sdkp->write_prot = 0;
1567 sdkp->WCE = 0; 1679 sdkp->WCE = 0;
1568 sdkp->RCD = 0; 1680 sdkp->RCD = 0;
1681 sdkp->ATO = 0;
1569 1682
1570 sd_spinup_disk(sdkp); 1683 sd_spinup_disk(sdkp);
1571 1684
@@ -1577,6 +1690,7 @@ static int sd_revalidate_disk(struct gendisk *disk)
1577 sd_read_capacity(sdkp, buffer); 1690 sd_read_capacity(sdkp, buffer);
1578 sd_read_write_protect_flag(sdkp, buffer); 1691 sd_read_write_protect_flag(sdkp, buffer);
1579 sd_read_cache_type(sdkp, buffer); 1692 sd_read_cache_type(sdkp, buffer);
1693 sd_read_app_tag_own(sdkp, buffer);
1580 } 1694 }
1581 1695
1582 /* 1696 /*
diff --git a/drivers/scsi/sd.h b/drivers/scsi/sd.h
index 03a3d45cfa42..86b18d4170fe 100644
--- a/drivers/scsi/sd.h
+++ b/drivers/scsi/sd.h
@@ -41,7 +41,9 @@ struct scsi_disk {
41 u32 index; 41 u32 index;
42 u8 media_present; 42 u8 media_present;
43 u8 write_prot; 43 u8 write_prot;
44 u8 protection_type;/* Data Integrity Field */
44 unsigned previous_state : 1; 45 unsigned previous_state : 1;
46 unsigned ATO : 1; /* state of disk ATO bit */
45 unsigned WCE : 1; /* state of disk WCE bit */ 47 unsigned WCE : 1; /* state of disk WCE bit */
46 unsigned RCD : 1; /* state of disk RCD bit, unused */ 48 unsigned RCD : 1; /* state of disk RCD bit, unused */
47 unsigned DPOFUA : 1; /* state of disk DPOFUA bit */ 49 unsigned DPOFUA : 1; /* state of disk DPOFUA bit */
@@ -59,4 +61,25 @@ static inline struct scsi_disk *scsi_disk(struct gendisk *disk)
59 (sdsk)->disk->disk_name, ##a) : \ 61 (sdsk)->disk->disk_name, ##a) : \
60 sdev_printk(prefix, (sdsk)->device, fmt, ##a) 62 sdev_printk(prefix, (sdsk)->device, fmt, ##a)
61 63
64/*
65 * A DIF-capable target device can be formatted with different
66 * protection schemes. Currently 0 through 3 are defined:
67 *
68 * Type 0 is regular (unprotected) I/O
69 *
70 * Type 1 defines the contents of the guard and reference tags
71 *
72 * Type 2 defines the contents of the guard and reference tags and
73 * uses 32-byte commands to seed the latter
74 *
75 * Type 3 defines the contents of the guard tag only
76 */
77
78enum sd_dif_target_protection_types {
79 SD_DIF_TYPE0_PROTECTION = 0x0,
80 SD_DIF_TYPE1_PROTECTION = 0x1,
81 SD_DIF_TYPE2_PROTECTION = 0x2,
82 SD_DIF_TYPE3_PROTECTION = 0x3,
83};
84
62#endif /* _SCSI_DISK_H */ 85#endif /* _SCSI_DISK_H */