[SCSI] sd: Identify DIF protection type and application tag ownership

If a disk is formatted with protection information (Inquiry bit
PROTECT=1) it is required to support Read Capacity(16). Force use of
the 16-bit command in this case and extract the P_TYPE field which
indicates whether the disk is formatted using DIF Type 1, 2 or 3.

The ATO (App Tag Own) bit in the Control Mode Page indicates whether
the storage device or the initiator own the contents of the
DIF application tag.

Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>

authored by

Martin K. Petersen and committed by
James Bottomley
e0597d70 511e44f4

+141 -4
+118 -4
drivers/scsi/sd.c
··· 233 233 return snprintf(buf, 40, "%d\n", sdkp->device->allow_restart); 234 234 } 235 235 236 + static ssize_t 237 + sd_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 + 245 + static ssize_t 246 + sd_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 + 236 254 static struct device_attribute sd_disk_attrs[] = { 237 255 __ATTR(cache_type, S_IRUGO|S_IWUSR, sd_show_cache_type, 238 256 sd_store_cache_type), ··· 259 241 sd_store_allow_restart), 260 242 __ATTR(manage_start_stop, S_IRUGO|S_IWUSR, sd_show_manage_start_stop, 261 243 sd_store_manage_start_stop), 244 + __ATTR(protection_type, S_IRUGO, sd_show_protection_type, NULL), 245 + __ATTR(app_tag_own, S_IRUGO, sd_show_app_tag_own, NULL), 262 246 __ATTR_NULL, 263 247 }; 264 248 ··· 1184 1164 } 1185 1165 } 1186 1166 1167 + 1168 + /* 1169 + * Determine whether disk supports Data Integrity Field. 1170 + */ 1171 + void sd_read_protection_type(struct scsi_disk *sdkp, unsigned char *buffer) 1172 + { 1173 + struct scsi_device *sdp = sdkp->device; 1174 + u8 type; 1175 + 1176 + if (scsi_device_protection(sdp) == 0 || (buffer[12] & 1) == 0) 1177 + type = 0; 1178 + else 1179 + type = ((buffer[12] >> 1) & 7) + 1; /* P_TYPE 0 = Type 1 */ 1180 + 1181 + switch (type) { 1182 + case SD_DIF_TYPE0_PROTECTION: 1183 + sdkp->protection_type = 0; 1184 + break; 1185 + 1186 + case SD_DIF_TYPE1_PROTECTION: 1187 + case SD_DIF_TYPE3_PROTECTION: 1188 + sdkp->protection_type = type; 1189 + break; 1190 + 1191 + case SD_DIF_TYPE2_PROTECTION: 1192 + sd_printk(KERN_ERR, sdkp, "formatted with DIF Type 2 " \ 1193 + "protection which is currently unsupported. " \ 1194 + "Disabling disk!\n"); 1195 + goto disable; 1196 + 1197 + default: 1198 + sd_printk(KERN_ERR, sdkp, "formatted with unknown " \ 1199 + "protection type %d. Disabling disk!\n", type); 1200 + goto disable; 1201 + } 1202 + 1203 + return; 1204 + 1205 + disable: 1206 + sdkp->protection_type = 0; 1207 + sdkp->capacity = 0; 1208 + } 1209 + 1187 1210 /* 1188 1211 * read disk capacity 1189 1212 */ ··· 1236 1173 unsigned char cmd[16]; 1237 1174 int the_result, retries; 1238 1175 int sector_size = 0; 1239 - int longrc = 0; 1176 + /* Force READ CAPACITY(16) when PROTECT=1 */ 1177 + int longrc = scsi_device_protection(sdkp->device) ? 1 : 0; 1240 1178 struct scsi_sense_hdr sshdr; 1241 1179 int sense_valid = 0; 1242 1180 struct scsi_device *sdp = sdkp->device; ··· 1249 1185 memset((void *) cmd, 0, 16); 1250 1186 cmd[0] = SERVICE_ACTION_IN; 1251 1187 cmd[1] = SAI_READ_CAPACITY_16; 1252 - cmd[13] = 12; 1253 - memset((void *) buffer, 0, 12); 1188 + cmd[13] = 13; 1189 + memset((void *) buffer, 0, 13); 1254 1190 } else { 1255 1191 cmd[0] = READ_CAPACITY; 1256 1192 memset((void *) &cmd[1], 0, 9); ··· 1258 1194 } 1259 1195 1260 1196 the_result = scsi_execute_req(sdp, cmd, DMA_FROM_DEVICE, 1261 - buffer, longrc ? 12 : 8, &sshdr, 1197 + buffer, longrc ? 13 : 8, &sshdr, 1262 1198 SD_TIMEOUT, SD_MAX_RETRIES); 1263 1199 1264 1200 if (media_not_present(sdkp, &sshdr)) ··· 1333 1269 1334 1270 sector_size = (buffer[8] << 24) | 1335 1271 (buffer[9] << 16) | (buffer[10] << 8) | buffer[11]; 1272 + 1273 + sd_read_protection_type(sdkp, buffer); 1336 1274 } 1337 1275 1338 1276 /* Some devices return the total number of sectors, not the ··· 1596 1530 sdkp->DPOFUA = 0; 1597 1531 } 1598 1532 1533 + /* 1534 + * The ATO bit indicates whether the DIF application tag is available 1535 + * for use by the operating system. 1536 + */ 1537 + void sd_read_app_tag_own(struct scsi_disk *sdkp, unsigned char *buffer) 1538 + { 1539 + int res, offset; 1540 + struct scsi_device *sdp = sdkp->device; 1541 + struct scsi_mode_data data; 1542 + struct scsi_sense_hdr sshdr; 1543 + 1544 + if (sdp->type != TYPE_DISK) 1545 + return; 1546 + 1547 + if (sdkp->protection_type == 0) 1548 + return; 1549 + 1550 + res = scsi_mode_sense(sdp, 1, 0x0a, buffer, 36, SD_TIMEOUT, 1551 + SD_MAX_RETRIES, &data, &sshdr); 1552 + 1553 + if (!scsi_status_is_good(res) || !data.header_length || 1554 + data.length < 6) { 1555 + sd_printk(KERN_WARNING, sdkp, 1556 + "getting Control mode page failed, assume no ATO\n"); 1557 + 1558 + if (scsi_sense_valid(&sshdr)) 1559 + sd_print_sense_hdr(sdkp, &sshdr); 1560 + 1561 + return; 1562 + } 1563 + 1564 + offset = data.header_length + data.block_descriptor_length; 1565 + 1566 + if ((buffer[offset] & 0x3f) != 0x0a) { 1567 + sd_printk(KERN_ERR, sdkp, "ATO Got wrong page\n"); 1568 + return; 1569 + } 1570 + 1571 + if ((buffer[offset + 5] & 0x80) == 0) 1572 + return; 1573 + 1574 + sdkp->ATO = 1; 1575 + 1576 + return; 1577 + } 1578 + 1599 1579 /** 1600 1580 * sd_revalidate_disk - called the first time a new disk is seen, 1601 1581 * performs disk spin up, read_capacity, etc. ··· 1678 1566 sdkp->write_prot = 0; 1679 1567 sdkp->WCE = 0; 1680 1568 sdkp->RCD = 0; 1569 + sdkp->ATO = 0; 1681 1570 1682 1571 sd_spinup_disk(sdkp); 1683 1572 ··· 1690 1577 sd_read_capacity(sdkp, buffer); 1691 1578 sd_read_write_protect_flag(sdkp, buffer); 1692 1579 sd_read_cache_type(sdkp, buffer); 1580 + sd_read_app_tag_own(sdkp, buffer); 1693 1581 } 1694 1582 1695 1583 /*
+23
drivers/scsi/sd.h
··· 41 41 u32 index; 42 42 u8 media_present; 43 43 u8 write_prot; 44 + u8 protection_type;/* Data Integrity Field */ 44 45 unsigned previous_state : 1; 46 + unsigned ATO : 1; /* state of disk ATO bit */ 45 47 unsigned WCE : 1; /* state of disk WCE bit */ 46 48 unsigned RCD : 1; /* state of disk RCD bit, unused */ 47 49 unsigned DPOFUA : 1; /* state of disk DPOFUA bit */ ··· 60 58 sdev_printk(prefix, (sdsk)->device, "[%s] " fmt, \ 61 59 (sdsk)->disk->disk_name, ##a) : \ 62 60 sdev_printk(prefix, (sdsk)->device, fmt, ##a) 61 + 62 + /* 63 + * A DIF-capable target device can be formatted with different 64 + * protection schemes. Currently 0 through 3 are defined: 65 + * 66 + * Type 0 is regular (unprotected) I/O 67 + * 68 + * Type 1 defines the contents of the guard and reference tags 69 + * 70 + * Type 2 defines the contents of the guard and reference tags and 71 + * uses 32-byte commands to seed the latter 72 + * 73 + * Type 3 defines the contents of the guard tag only 74 + */ 75 + 76 + enum sd_dif_target_protection_types { 77 + SD_DIF_TYPE0_PROTECTION = 0x0, 78 + SD_DIF_TYPE1_PROTECTION = 0x1, 79 + SD_DIF_TYPE2_PROTECTION = 0x2, 80 + SD_DIF_TYPE3_PROTECTION = 0x3, 81 + }; 63 82 64 83 #endif /* _SCSI_DISK_H */