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 ---