Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

libata: support host-aware and host-managed ZAC devices

Byte 69 bits 0:1 in the IDENTIFY DEVICE data indicate a
host-aware ZAC device.
Host-managed ZAC devices have their own individual signature,
and to not set the bits in the IDENTIFY DEVICE data.
And whenever we detect a ZAC-compatible device we should
be displaying the zoned block characteristics VPD page.

Signed-off-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Tejun Heo <tj@kernel.org>

authored by

Hannes Reinecke and committed by
Tejun Heo
6d1003ae 856c4663

+138 -2
+94
drivers/ata/libata-core.c
··· 2227 2227 } 2228 2228 } 2229 2229 2230 + static void ata_dev_config_zac(struct ata_device *dev) 2231 + { 2232 + struct ata_port *ap = dev->link->ap; 2233 + unsigned int err_mask; 2234 + u8 *identify_buf = ap->sector_buf; 2235 + int log_index = ATA_LOG_SATA_ID_DEV_DATA * 2, i, found = 0; 2236 + u16 log_pages; 2237 + 2238 + dev->zac_zones_optimal_open = U32_MAX; 2239 + dev->zac_zones_optimal_nonseq = U32_MAX; 2240 + dev->zac_zones_max_open = U32_MAX; 2241 + 2242 + /* 2243 + * Always set the 'ZAC' flag for Host-managed devices. 2244 + */ 2245 + if (dev->class == ATA_DEV_ZAC) 2246 + dev->flags |= ATA_DFLAG_ZAC; 2247 + else if (ata_id_zoned_cap(dev->id) == 0x01) 2248 + /* 2249 + * Check for host-aware devices. 2250 + */ 2251 + dev->flags |= ATA_DFLAG_ZAC; 2252 + 2253 + if (!(dev->flags & ATA_DFLAG_ZAC)) 2254 + return; 2255 + 2256 + /* 2257 + * Read Log Directory to figure out if IDENTIFY DEVICE log 2258 + * is supported. 2259 + */ 2260 + err_mask = ata_read_log_page(dev, ATA_LOG_DIRECTORY, 2261 + 0, ap->sector_buf, 1); 2262 + if (err_mask) { 2263 + ata_dev_info(dev, 2264 + "failed to get Log Directory Emask 0x%x\n", 2265 + err_mask); 2266 + return; 2267 + } 2268 + log_pages = get_unaligned_le16(&ap->sector_buf[log_index]); 2269 + if (log_pages == 0) { 2270 + ata_dev_warn(dev, 2271 + "ATA Identify Device Log not supported\n"); 2272 + return; 2273 + } 2274 + /* 2275 + * Read IDENTIFY DEVICE data log, page 0, to figure out 2276 + * if page 9 is supported. 2277 + */ 2278 + err_mask = ata_read_log_page(dev, ATA_LOG_SATA_ID_DEV_DATA, 0, 2279 + identify_buf, 1); 2280 + if (err_mask) { 2281 + ata_dev_info(dev, 2282 + "failed to get Device Identify Log Emask 0x%x\n", 2283 + err_mask); 2284 + return; 2285 + } 2286 + log_pages = identify_buf[8]; 2287 + for (i = 0; i < log_pages; i++) { 2288 + if (identify_buf[9 + i] == ATA_LOG_ZONED_INFORMATION) { 2289 + found++; 2290 + break; 2291 + } 2292 + } 2293 + if (!found) { 2294 + ata_dev_warn(dev, 2295 + "ATA Zoned Information Log not supported\n"); 2296 + return; 2297 + } 2298 + 2299 + /* 2300 + * Read IDENTIFY DEVICE data log, page 9 (Zoned-device information) 2301 + */ 2302 + err_mask = ata_read_log_page(dev, ATA_LOG_SATA_ID_DEV_DATA, 2303 + ATA_LOG_ZONED_INFORMATION, 2304 + identify_buf, 1); 2305 + if (!err_mask) { 2306 + u64 zoned_cap, opt_open, opt_nonseq, max_open; 2307 + 2308 + zoned_cap = get_unaligned_le64(&identify_buf[8]); 2309 + if ((zoned_cap >> 63)) 2310 + dev->zac_zoned_cap = (zoned_cap & 1); 2311 + opt_open = get_unaligned_le64(&identify_buf[24]); 2312 + if ((opt_open >> 63)) 2313 + dev->zac_zones_optimal_open = (u32)opt_open; 2314 + opt_nonseq = get_unaligned_le64(&identify_buf[32]); 2315 + if ((opt_nonseq >> 63)) 2316 + dev->zac_zones_optimal_nonseq = (u32)opt_nonseq; 2317 + max_open = get_unaligned_le64(&identify_buf[40]); 2318 + if ((max_open >> 63)) 2319 + dev->zac_zones_max_open = (u32)max_open; 2320 + } 2321 + } 2322 + 2230 2323 /** 2231 2324 * ata_dev_configure - Configure the specified ATA/ATAPI device 2232 2325 * @dev: Target device to configure ··· 2543 2450 } 2544 2451 } 2545 2452 ata_dev_config_sense_reporting(dev); 2453 + ata_dev_config_zac(dev); 2546 2454 dev->cdb_len = 16; 2547 2455 } 2548 2456
+36 -2
drivers/ata/libata-scsi.c
··· 2144 2144 */ 2145 2145 static unsigned int ata_scsiop_inq_00(struct ata_scsi_args *args, u8 *rbuf) 2146 2146 { 2147 + int num_pages; 2147 2148 const u8 pages[] = { 2148 2149 0x00, /* page 0x00, this page */ 2149 2150 0x80, /* page 0x80, unit serial no page */ ··· 2153 2152 0xb0, /* page 0xb0, block limits page */ 2154 2153 0xb1, /* page 0xb1, block device characteristics page */ 2155 2154 0xb2, /* page 0xb2, thin provisioning page */ 2155 + 0xb6, /* page 0xb6, zoned block device characteristics */ 2156 2156 }; 2157 2157 2158 - rbuf[3] = sizeof(pages); /* number of supported VPD pages */ 2159 - memcpy(rbuf + 4, pages, sizeof(pages)); 2158 + num_pages = sizeof(pages); 2159 + if (!(args->dev->flags & ATA_DFLAG_ZAC)) 2160 + num_pages--; 2161 + rbuf[3] = num_pages; /* number of supported VPD pages */ 2162 + memcpy(rbuf + 4, pages, num_pages); 2160 2163 return 0; 2161 2164 } 2162 2165 ··· 2344 2339 rbuf[1] = 0xb2; 2345 2340 rbuf[3] = 0x4; 2346 2341 rbuf[5] = 1 << 6; /* TPWS */ 2342 + 2343 + return 0; 2344 + } 2345 + 2346 + static unsigned int ata_scsiop_inq_b6(struct ata_scsi_args *args, u8 *rbuf) 2347 + { 2348 + /* 2349 + * zbc-r05 SCSI Zoned Block device characteristics VPD page 2350 + */ 2351 + rbuf[1] = 0xb6; 2352 + rbuf[3] = 0x3C; 2353 + 2354 + /* 2355 + * URSWRZ bit is only meaningful for host-managed ZAC drives 2356 + */ 2357 + if (args->dev->zac_zoned_cap & 1) 2358 + rbuf[4] |= 1; 2359 + put_unaligned_be32(args->dev->zac_zones_optimal_open, &rbuf[8]); 2360 + put_unaligned_be32(args->dev->zac_zones_optimal_nonseq, &rbuf[12]); 2361 + put_unaligned_be32(args->dev->zac_zones_max_open, &rbuf[16]); 2347 2362 2348 2363 return 0; 2349 2364 } ··· 2686 2661 rbuf[14] |= 0x40; /* LBPRZ */ 2687 2662 } 2688 2663 } 2664 + if (ata_id_zoned_cap(args->id) || 2665 + args->dev->class == ATA_DEV_ZAC) 2666 + rbuf[12] = (1 << 4); /* RC_BASIS */ 2689 2667 } 2690 2668 return 0; 2691 2669 } ··· 4074 4046 case 0xb2: 4075 4047 ata_scsi_rbuf_fill(&args, ata_scsiop_inq_b2); 4076 4048 break; 4049 + case 0xb6: 4050 + if (dev->flags & ATA_DFLAG_ZAC) { 4051 + ata_scsi_rbuf_fill(&args, ata_scsiop_inq_b6); 4052 + break; 4053 + } 4054 + /* Fallthrough */ 4077 4055 default: 4078 4056 ata_scsi_invalid_field(dev, cmd, 2); 4079 4057 break;
+1
include/linux/ata.h
··· 338 338 ATA_LOG_NCQ_SEND_RECV = 0x13, 339 339 ATA_LOG_SATA_ID_DEV_DATA = 0x30, 340 340 ATA_LOG_SATA_SETTINGS = 0x08, 341 + ATA_LOG_ZONED_INFORMATION = 0x09, 341 342 ATA_LOG_DEVSLP_OFFSET = 0x30, 342 343 ATA_LOG_DEVSLP_SIZE = 0x08, 343 344 ATA_LOG_DEVSLP_MDAT = 0x00,
+7
include/linux/libata.h
··· 181 181 ATA_DFLAG_DEVSLP = (1 << 27), /* device supports Device Sleep */ 182 182 ATA_DFLAG_ACPI_DISABLED = (1 << 28), /* ACPI for the device is disabled */ 183 183 ATA_DFLAG_D_SENSE = (1 << 29), /* Descriptor sense requested */ 184 + ATA_DFLAG_ZAC = (1 << 30), /* ZAC device */ 184 185 185 186 ATA_DEV_UNKNOWN = 0, /* unknown device */ 186 187 ATA_DEV_ATA = 1, /* ATA device */ ··· 731 730 /* NCQ send and receive log subcommand support */ 732 731 u8 ncq_send_recv_cmds[ATA_LOG_NCQ_SEND_RECV_SIZE]; 733 732 u8 ncq_non_data_cmds[ATA_LOG_NCQ_NON_DATA_SIZE]; 733 + 734 + /* ZAC zone configuration */ 735 + u32 zac_zoned_cap; 736 + u32 zac_zones_optimal_open; 737 + u32 zac_zones_optimal_nonseq; 738 + u32 zac_zones_max_open; 734 739 735 740 /* error history */ 736 741 int spdn_cnt;