sd_zbc.c (23a50861adda26a3f3b3ec5fbca0583133d89538) | sd_zbc.c (d41003513e61dd9d4974cb441d30b63650b85654) |
---|---|
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * SCSI Zoned Block commands 4 * 5 * Copyright (C) 2014-2015 SUSE Linux GmbH 6 * Written by: Hannes Reinecke <hare@suse.de> 7 * Modified by: Damien Le Moal <damien.lemoal@hgst.com> 8 * Modified by: Shaun Tancheff <shaun.tancheff@seagate.com> --- 5 unchanged lines hidden (view full) --- 14 15#include <asm/unaligned.h> 16 17#include <scsi/scsi.h> 18#include <scsi/scsi_cmnd.h> 19 20#include "sd.h" 21 | 1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * SCSI Zoned Block commands 4 * 5 * Copyright (C) 2014-2015 SUSE Linux GmbH 6 * Written by: Hannes Reinecke <hare@suse.de> 7 * Modified by: Damien Le Moal <damien.lemoal@hgst.com> 8 * Modified by: Shaun Tancheff <shaun.tancheff@seagate.com> --- 5 unchanged lines hidden (view full) --- 14 15#include <asm/unaligned.h> 16 17#include <scsi/scsi.h> 18#include <scsi/scsi_cmnd.h> 19 20#include "sd.h" 21 |
22/** 23 * sd_zbc_parse_report - Convert a zone descriptor to a struct blk_zone, 24 * @sdkp: The disk the report originated from 25 * @buf: Address of the report zone descriptor 26 * @zone: the destination zone structure 27 * 28 * All LBA sized values are converted to 512B sectors unit. 29 */ 30static void sd_zbc_parse_report(struct scsi_disk *sdkp, u8 *buf, 31 struct blk_zone *zone) | 22static int sd_zbc_parse_report(struct scsi_disk *sdkp, u8 *buf, 23 unsigned int idx, report_zones_cb cb, void *data) |
32{ 33 struct scsi_device *sdp = sdkp->device; | 24{ 25 struct scsi_device *sdp = sdkp->device; |
26 struct blk_zone zone = { 0 }; |
|
34 | 27 |
35 memset(zone, 0, sizeof(struct blk_zone)); 36 37 zone->type = buf[0] & 0x0f; 38 zone->cond = (buf[1] >> 4) & 0xf; | 28 zone.type = buf[0] & 0x0f; 29 zone.cond = (buf[1] >> 4) & 0xf; |
39 if (buf[1] & 0x01) | 30 if (buf[1] & 0x01) |
40 zone->reset = 1; | 31 zone.reset = 1; |
41 if (buf[1] & 0x02) | 32 if (buf[1] & 0x02) |
42 zone->non_seq = 1; | 33 zone.non_seq = 1; |
43 | 34 |
44 zone->len = logical_to_sectors(sdp, get_unaligned_be64(&buf[8])); 45 zone->start = logical_to_sectors(sdp, get_unaligned_be64(&buf[16])); 46 zone->wp = logical_to_sectors(sdp, get_unaligned_be64(&buf[24])); 47 if (zone->type != ZBC_ZONE_TYPE_CONV && 48 zone->cond == ZBC_ZONE_COND_FULL) 49 zone->wp = zone->start + zone->len; | 35 zone.len = logical_to_sectors(sdp, get_unaligned_be64(&buf[8])); 36 zone.start = logical_to_sectors(sdp, get_unaligned_be64(&buf[16])); 37 zone.wp = logical_to_sectors(sdp, get_unaligned_be64(&buf[24])); 38 if (zone.type != ZBC_ZONE_TYPE_CONV && 39 zone.cond == ZBC_ZONE_COND_FULL) 40 zone.wp = zone.start + zone.len; 41 42 return cb(&zone, idx, data); |
50} 51 52/** 53 * sd_zbc_do_report_zones - Issue a REPORT ZONES scsi command. 54 * @sdkp: The target disk 55 * @buf: vmalloc-ed buffer to use for the reply 56 * @buflen: the buffer size 57 * @lba: Start LBA of the report --- 91 unchanged lines hidden (view full) --- 149 } 150 bufsize >>= 1; 151 } 152 153 return NULL; 154} 155 156/** | 43} 44 45/** 46 * sd_zbc_do_report_zones - Issue a REPORT ZONES scsi command. 47 * @sdkp: The target disk 48 * @buf: vmalloc-ed buffer to use for the reply 49 * @buflen: the buffer size 50 * @lba: Start LBA of the report --- 91 unchanged lines hidden (view full) --- 142 } 143 bufsize >>= 1; 144 } 145 146 return NULL; 147} 148 149/** |
157 * sd_zbc_report_zones - Disk report zones operation. 158 * @disk: The target disk 159 * @sector: Start 512B sector of the report 160 * @zones: Array of zone descriptors 161 * @nr_zones: Number of descriptors in the array 162 * 163 * Execute a report zones command on the target disk. | 150 * sd_zbc_zone_sectors - Get the device zone size in number of 512B sectors. 151 * @sdkp: The target disk |
164 */ | 152 */ |
153static inline sector_t sd_zbc_zone_sectors(struct scsi_disk *sdkp) 154{ 155 return logical_to_sectors(sdkp->device, sdkp->zone_blocks); 156} 157 |
|
165int sd_zbc_report_zones(struct gendisk *disk, sector_t sector, | 158int sd_zbc_report_zones(struct gendisk *disk, sector_t sector, |
166 struct blk_zone *zones, unsigned int *nr_zones) | 159 unsigned int nr_zones, report_zones_cb cb, void *data) |
167{ 168 struct scsi_disk *sdkp = scsi_disk(disk); | 160{ 161 struct scsi_disk *sdkp = scsi_disk(disk); |
169 unsigned int i, nrz = *nr_zones; | 162 unsigned int nr, i; |
170 unsigned char *buf; | 163 unsigned char *buf; |
171 size_t buflen = 0, offset = 0; 172 int ret = 0; | 164 size_t offset, buflen = 0; 165 int zone_idx = 0; 166 int ret; |
173 174 if (!sd_is_zoned(sdkp)) 175 /* Not a zoned device */ 176 return -EOPNOTSUPP; 177 | 167 168 if (!sd_is_zoned(sdkp)) 169 /* Not a zoned device */ 170 return -EOPNOTSUPP; 171 |
178 buf = sd_zbc_alloc_report_buffer(sdkp, nrz, &buflen); | 172 buf = sd_zbc_alloc_report_buffer(sdkp, nr_zones, &buflen); |
179 if (!buf) 180 return -ENOMEM; 181 | 173 if (!buf) 174 return -ENOMEM; 175 |
182 ret = sd_zbc_do_report_zones(sdkp, buf, buflen, 183 sectors_to_logical(sdkp->device, sector), true); 184 if (ret) 185 goto out; | 176 while (zone_idx < nr_zones && sector < get_capacity(disk)) { 177 ret = sd_zbc_do_report_zones(sdkp, buf, buflen, 178 sectors_to_logical(sdkp->device, sector), true); 179 if (ret) 180 goto out; |
186 | 181 |
187 nrz = min(nrz, get_unaligned_be32(&buf[0]) / 64); 188 for (i = 0; i < nrz; i++) { 189 offset += 64; 190 sd_zbc_parse_report(sdkp, buf + offset, zones); 191 zones++; 192 } | 182 offset = 0; 183 nr = min(nr_zones, get_unaligned_be32(&buf[0]) / 64); 184 if (!nr) 185 break; |
193 | 186 |
194 *nr_zones = nrz; | 187 for (i = 0; i < nr && zone_idx < nr_zones; i++) { 188 offset += 64; 189 ret = sd_zbc_parse_report(sdkp, buf + offset, zone_idx, 190 cb, data); 191 if (ret) 192 goto out; 193 zone_idx++; 194 } |
195 | 195 |
196 sector += sd_zbc_zone_sectors(sdkp) * i; 197 } 198 199 ret = zone_idx; |
|
196out: 197 kvfree(buf); | 200out: 201 kvfree(buf); |
198 | |
199 return ret; 200} 201 202/** | 202 return ret; 203} 204 205/** |
203 * sd_zbc_zone_sectors - Get the device zone size in number of 512B sectors. 204 * @sdkp: The target disk 205 */ 206static inline sector_t sd_zbc_zone_sectors(struct scsi_disk *sdkp) 207{ 208 return logical_to_sectors(sdkp->device, sdkp->zone_blocks); 209} 210 211/** | |
212 * sd_zbc_setup_zone_mgmt_cmnd - Prepare a zone ZBC_OUT command. The operations 213 * can be RESET WRITE POINTER, OPEN, CLOSE or FINISH. 214 * @cmd: the command to setup 215 * @op: Operation to be performed 216 * @all: All zones control 217 * 218 * Called from sd_init_command() for REQ_OP_ZONE_RESET, REQ_OP_ZONE_RESET_ALL, 219 * REQ_OP_ZONE_OPEN, REQ_OP_ZONE_CLOSE or REQ_OP_ZONE_FINISH requests. --- 259 unchanged lines hidden --- | 206 * sd_zbc_setup_zone_mgmt_cmnd - Prepare a zone ZBC_OUT command. The operations 207 * can be RESET WRITE POINTER, OPEN, CLOSE or FINISH. 208 * @cmd: the command to setup 209 * @op: Operation to be performed 210 * @all: All zones control 211 * 212 * Called from sd_init_command() for REQ_OP_ZONE_RESET, REQ_OP_ZONE_RESET_ALL, 213 * REQ_OP_ZONE_OPEN, REQ_OP_ZONE_CLOSE or REQ_OP_ZONE_FINISH requests. --- 259 unchanged lines hidden --- |