Commit 9d2be0c1 authored by Jan Höppner's avatar Jan Höppner Committed by Martin Schwidefsky

s390/dasd: Make raw I/O usable without prefix support

The Prefix CCW is not mandatory and raw I/O can also be issued without
it. Check whether the Prefix CCW is supported and if not use the
combination of Define Extent and Locate Record Extended instead.

While at it, sort the variable declarations, replace the gotos with
early exits, and remove an error check at the end which is irrelevant.
Also, remove the XRC check as it is not relevant for raw I/O.
Reviewed-by: default avatarStefan Haberland <sth@linux.vnet.ibm.com>
Signed-off-by: default avatarJan Höppner <hoeppner@linux.vnet.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent bbc7f7ea
...@@ -3783,21 +3783,24 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_raw(struct dasd_device *startdev, ...@@ -3783,21 +3783,24 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_raw(struct dasd_device *startdev,
struct dasd_block *block, struct dasd_block *block,
struct request *req) struct request *req)
{ {
unsigned long *idaws; sector_t start_padding_sectors, end_sector_offset, end_padding_sectors;
unsigned int seg_len, len_to_track_end;
unsigned int cidaw, cplength, datasize;
sector_t first_trk, last_trk, sectors;
struct dasd_eckd_private *base_priv;
struct dasd_device *basedev; struct dasd_device *basedev;
struct dasd_ccw_req *cqr;
struct ccw1 *ccw;
struct req_iterator iter; struct req_iterator iter;
struct dasd_ccw_req *cqr;
unsigned int first_offs;
unsigned int trkcount;
unsigned long *idaws;
unsigned int size;
unsigned char cmd;
struct bio_vec bv; struct bio_vec bv;
struct ccw1 *ccw;
int use_prefix;
void *data;
char *dst; char *dst;
unsigned char cmd;
unsigned int trkcount;
unsigned int seg_len, len_to_track_end;
unsigned int first_offs;
unsigned int cidaw, cplength, datasize;
sector_t first_trk, last_trk, sectors;
sector_t start_padding_sectors, end_sector_offset, end_padding_sectors;
unsigned int pfx_datasize;
/* /*
* raw track access needs to be mutiple of 64k and on 64k boundary * raw track access needs to be mutiple of 64k and on 64k boundary
...@@ -3815,8 +3818,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_raw(struct dasd_device *startdev, ...@@ -3815,8 +3818,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_raw(struct dasd_device *startdev,
DBF_DEV_EVENT(DBF_ERR, basedev, DBF_DEV_EVENT(DBF_ERR, basedev,
"raw write not track aligned (%lu,%lu) req %p", "raw write not track aligned (%lu,%lu) req %p",
start_padding_sectors, end_padding_sectors, req); start_padding_sectors, end_padding_sectors, req);
cqr = ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
goto out;
} }
first_trk = blk_rq_pos(req) / DASD_RAW_SECTORS_PER_TRACK; first_trk = blk_rq_pos(req) / DASD_RAW_SECTORS_PER_TRACK;
...@@ -3829,10 +3831,8 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_raw(struct dasd_device *startdev, ...@@ -3829,10 +3831,8 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_raw(struct dasd_device *startdev,
cmd = DASD_ECKD_CCW_READ_TRACK; cmd = DASD_ECKD_CCW_READ_TRACK;
else if (rq_data_dir(req) == WRITE) else if (rq_data_dir(req) == WRITE)
cmd = DASD_ECKD_CCW_WRITE_FULL_TRACK; cmd = DASD_ECKD_CCW_WRITE_FULL_TRACK;
else { else
cqr = ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
goto out;
}
/* /*
* Raw track based I/O needs IDAWs for each page, * Raw track based I/O needs IDAWs for each page,
...@@ -3840,38 +3840,46 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_raw(struct dasd_device *startdev, ...@@ -3840,38 +3840,46 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_raw(struct dasd_device *startdev,
*/ */
cidaw = trkcount * DASD_RAW_BLOCK_PER_TRACK; cidaw = trkcount * DASD_RAW_BLOCK_PER_TRACK;
/* 1x prefix + one read/write ccw per track */
cplength = 1 + trkcount;
/* /*
* struct PFX_eckd_data has up to 2 byte as extended parameter * struct PFX_eckd_data and struct LRE_eckd_data can have up to 2 bytes
* this is needed for write full track and has to be mentioned * of extended parameter. This is needed for write full track.
* separately
* add 8 instead of 2 to keep 8 byte boundary
*/ */
pfx_datasize = sizeof(struct PFX_eckd_data) + 8; base_priv = basedev->private;
use_prefix = base_priv->features.feature[8] & 0x01;
if (use_prefix) {
cplength = 1 + trkcount;
size = sizeof(struct PFX_eckd_data) + 2;
} else {
cplength = 2 + trkcount;
size = sizeof(struct DE_eckd_data) +
sizeof(struct LRE_eckd_data) + 2;
}
size = ALIGN(size, 8);
datasize = pfx_datasize + cidaw * sizeof(unsigned long long); datasize = size + cidaw * sizeof(unsigned long long);
/* Allocate the ccw request. */ /* Allocate the ccw request. */
cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, cplength, cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, cplength,
datasize, startdev); datasize, startdev);
if (IS_ERR(cqr)) if (IS_ERR(cqr))
goto out; return cqr;
ccw = cqr->cpaddr; ccw = cqr->cpaddr;
data = cqr->data;
if (prefix_LRE(ccw++, cqr->data, first_trk, last_trk, cmd, if (use_prefix) {
basedev, startdev, 1 /* format */, first_offs + 1, prefix_LRE(ccw++, data, first_trk, last_trk, cmd, basedev,
trkcount, 0, 0) == -EAGAIN) { startdev, 1, first_offs + 1, trkcount, 0, 0);
/* Clock not in sync and XRC is enabled. } else {
* Try again later. define_extent(ccw++, data, first_trk, last_trk, cmd, basedev, 0);
*/ ccw[-1].flags |= CCW_FLAG_CC;
dasd_sfree_request(cqr, startdev);
cqr = ERR_PTR(-EAGAIN); data += sizeof(struct DE_eckd_data);
goto out; locate_record_ext(ccw++, data, first_trk, first_offs + 1,
trkcount, cmd, basedev, 0, 0);
} }
idaws = (unsigned long *)(cqr->data + pfx_datasize); idaws = (unsigned long *)(cqr->data + size);
len_to_track_end = 0; len_to_track_end = 0;
if (start_padding_sectors) { if (start_padding_sectors) {
ccw[-1].flags |= CCW_FLAG_CC; ccw[-1].flags |= CCW_FLAG_CC;
...@@ -3921,9 +3929,6 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_raw(struct dasd_device *startdev, ...@@ -3921,9 +3929,6 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_raw(struct dasd_device *startdev,
cqr->buildclk = get_tod_clock(); cqr->buildclk = get_tod_clock();
cqr->status = DASD_CQR_FILLED; cqr->status = DASD_CQR_FILLED;
if (IS_ERR(cqr) && PTR_ERR(cqr) != -EAGAIN)
cqr = NULL;
out:
return cqr; return cqr;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment