677 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>4 * Based on.......: linux/drivers/s390/block/mdisk.c5 * ...............: by Hartmunt Penner <hpenner@de.ibm.com>6 * Bugreports.to..: <Linux390@de.ibm.com>7 * Copyright IBM Corp. 1999, 20008 *9 */10 11#include <linux/kernel_stat.h>12#include <linux/stddef.h>13#include <linux/kernel.h>14#include <linux/slab.h>15#include <linux/hdreg.h>16#include <linux/bio.h>17#include <linux/module.h>18#include <linux/init.h>19#include <linux/jiffies.h>20#include <asm/asm-extable.h>21#include <asm/dasd.h>22#include <asm/debug.h>23#include <asm/diag.h>24#include <asm/ebcdic.h>25#include <linux/io.h>26#include <asm/irq.h>27#include <asm/vtoc.h>28 29#include "dasd_int.h"30#include "dasd_diag.h"31 32MODULE_DESCRIPTION("S/390 Support for DIAG access to DASD Disks");33MODULE_LICENSE("GPL");34 35/* The maximum number of blocks per request (max_blocks) is dependent on the36 * amount of storage that is available in the static I/O buffer for each37 * device. Currently each device gets 2 pages. We want to fit two requests38 * into the available memory so that we can immediately start the next if one39 * finishes. */40#define DIAG_MAX_BLOCKS (((2 * PAGE_SIZE - sizeof(struct dasd_ccw_req) - \41 sizeof(struct dasd_diag_req)) / \42 sizeof(struct dasd_diag_bio)) / 2)43#define DIAG_MAX_RETRIES 3244#define DIAG_TIMEOUT 5045 46static struct dasd_discipline dasd_diag_discipline;47 48struct dasd_diag_private {49 struct dasd_diag_characteristics rdc_data;50 struct dasd_diag_rw_io iob;51 struct dasd_diag_init_io iib;52 blocknum_t pt_block;53 struct ccw_dev_id dev_id;54};55 56struct dasd_diag_req {57 unsigned int block_count;58 struct dasd_diag_bio bio[];59};60 61static const u8 DASD_DIAG_CMS1[] = { 0xc3, 0xd4, 0xe2, 0xf1 };/* EBCDIC CMS1 */62 63/* Perform DIAG250 call with block I/O parameter list iob (input and output)64 * and function code cmd.65 * In case of an exception return 3. Otherwise return result of bitwise OR of66 * resulting condition code and DIAG return code. */67static inline int __dia250(void *iob, int cmd)68{69 union register_pair rx = { .even = (unsigned long)iob, };70 typedef union {71 struct dasd_diag_init_io init_io;72 struct dasd_diag_rw_io rw_io;73 } addr_type;74 int cc;75 76 cc = 3;77 asm volatile(78 " diag %[rx],%[cmd],0x250\n"79 "0: ipm %[cc]\n"80 " srl %[cc],28\n"81 "1:\n"82 EX_TABLE(0b,1b)83 : [cc] "+&d" (cc), [rx] "+&d" (rx.pair), "+m" (*(addr_type *)iob)84 : [cmd] "d" (cmd)85 : "cc");86 return cc | rx.odd;87}88 89static inline int dia250(void *iob, int cmd)90{91 diag_stat_inc(DIAG_STAT_X250);92 return __dia250(iob, cmd);93}94 95/* Initialize block I/O to DIAG device using the specified blocksize and96 * block offset. On success, return zero and set end_block to contain the97 * number of blocks on the device minus the specified offset. Return non-zero98 * otherwise. */99static inline int100mdsk_init_io(struct dasd_device *device, unsigned int blocksize,101 blocknum_t offset, blocknum_t *end_block)102{103 struct dasd_diag_private *private = device->private;104 struct dasd_diag_init_io *iib = &private->iib;105 int rc;106 107 memset(iib, 0, sizeof (struct dasd_diag_init_io));108 109 iib->dev_nr = private->dev_id.devno;110 iib->block_size = blocksize;111 iib->offset = offset;112 iib->flaga = DASD_DIAG_FLAGA_DEFAULT;113 114 rc = dia250(iib, INIT_BIO);115 116 if ((rc & 3) == 0 && end_block)117 *end_block = iib->end_block;118 119 return rc;120}121 122/* Remove block I/O environment for device. Return zero on success, non-zero123 * otherwise. */124static inline int125mdsk_term_io(struct dasd_device * device)126{127 struct dasd_diag_private *private = device->private;128 struct dasd_diag_init_io *iib = &private->iib;129 int rc;130 131 memset(iib, 0, sizeof (struct dasd_diag_init_io));132 iib->dev_nr = private->dev_id.devno;133 rc = dia250(iib, TERM_BIO);134 return rc;135}136 137/* Error recovery for failed DIAG requests - try to reestablish the DIAG138 * environment. */139static void140dasd_diag_erp(struct dasd_device *device)141{142 int rc;143 144 mdsk_term_io(device);145 rc = mdsk_init_io(device, device->block->bp_block, 0, NULL);146 if (rc == 4) {147 if (!(test_and_set_bit(DASD_FLAG_DEVICE_RO, &device->flags)))148 pr_warn("%s: The access mode of a DIAG device changed to read-only\n",149 dev_name(&device->cdev->dev));150 rc = 0;151 }152 if (rc)153 pr_warn("%s: DIAG ERP failed with rc=%d\n",154 dev_name(&device->cdev->dev), rc);155}156 157/* Start a given request at the device. Return zero on success, non-zero158 * otherwise. */159static int160dasd_start_diag(struct dasd_ccw_req * cqr)161{162 struct dasd_device *device;163 struct dasd_diag_private *private;164 struct dasd_diag_req *dreq;165 int rc;166 167 device = cqr->startdev;168 if (cqr->retries < 0) {169 DBF_DEV_EVENT(DBF_ERR, device, "DIAG start_IO: request %p "170 "- no retry left)", cqr);171 cqr->status = DASD_CQR_ERROR;172 return -EIO;173 }174 private = device->private;175 dreq = cqr->data;176 177 private->iob.dev_nr = private->dev_id.devno;178 private->iob.key = 0;179 private->iob.flags = DASD_DIAG_RWFLAG_ASYNC;180 private->iob.block_count = dreq->block_count;181 private->iob.interrupt_params = (addr_t) cqr;182 private->iob.bio_list = dreq->bio;183 private->iob.flaga = DASD_DIAG_FLAGA_DEFAULT;184 185 cqr->startclk = get_tod_clock();186 cqr->starttime = jiffies;187 cqr->retries--;188 189 rc = dia250(&private->iob, RW_BIO);190 switch (rc) {191 case 0: /* Synchronous I/O finished successfully */192 cqr->stopclk = get_tod_clock();193 cqr->status = DASD_CQR_SUCCESS;194 /* Indicate to calling function that only a dasd_schedule_bh()195 and no timer is needed */196 rc = -EACCES;197 break;198 case 8: /* Asynchronous I/O was started */199 cqr->status = DASD_CQR_IN_IO;200 rc = 0;201 break;202 default: /* Error condition */203 cqr->status = DASD_CQR_QUEUED;204 DBF_DEV_EVENT(DBF_WARNING, device, "dia250 returned rc=%d", rc);205 dasd_diag_erp(device);206 rc = -EIO;207 break;208 }209 cqr->intrc = rc;210 return rc;211}212 213/* Terminate given request at the device. */214static int215dasd_diag_term_IO(struct dasd_ccw_req * cqr)216{217 struct dasd_device *device;218 219 device = cqr->startdev;220 mdsk_term_io(device);221 mdsk_init_io(device, device->block->bp_block, 0, NULL);222 cqr->status = DASD_CQR_CLEAR_PENDING;223 cqr->stopclk = get_tod_clock();224 dasd_schedule_device_bh(device);225 return 0;226}227 228/* Handle external interruption. */229static void dasd_ext_handler(struct ext_code ext_code,230 unsigned int param32, unsigned long param64)231{232 struct dasd_ccw_req *cqr, *next;233 struct dasd_device *device;234 unsigned long expires;235 unsigned long flags;236 addr_t ip;237 int rc;238 239 switch (ext_code.subcode >> 8) {240 case DASD_DIAG_CODE_31BIT:241 ip = (addr_t) param32;242 break;243 case DASD_DIAG_CODE_64BIT:244 ip = (addr_t) param64;245 break;246 default:247 return;248 }249 inc_irq_stat(IRQEXT_DSD);250 if (!ip) { /* no intparm: unsolicited interrupt */251 DBF_EVENT(DBF_NOTICE, "%s", "caught unsolicited "252 "interrupt");253 return;254 }255 cqr = (struct dasd_ccw_req *) ip;256 device = (struct dasd_device *) cqr->startdev;257 if (strncmp(device->discipline->ebcname, (char *) &cqr->magic, 4)) {258 DBF_DEV_EVENT(DBF_WARNING, device,259 " magic number of dasd_ccw_req 0x%08X doesn't"260 " match discipline 0x%08X",261 cqr->magic, *(int *) (&device->discipline->name));262 return;263 }264 265 /* get irq lock to modify request queue */266 spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);267 268 /* Check for a pending clear operation */269 if (cqr->status == DASD_CQR_CLEAR_PENDING) {270 cqr->status = DASD_CQR_CLEARED;271 dasd_device_clear_timer(device);272 dasd_schedule_device_bh(device);273 spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);274 return;275 }276 277 cqr->stopclk = get_tod_clock();278 279 expires = 0;280 if ((ext_code.subcode & 0xff) == 0) {281 cqr->status = DASD_CQR_SUCCESS;282 /* Start first request on queue if possible -> fast_io. */283 if (!list_empty(&device->ccw_queue)) {284 next = list_entry(device->ccw_queue.next,285 struct dasd_ccw_req, devlist);286 if (next->status == DASD_CQR_QUEUED) {287 rc = dasd_start_diag(next);288 if (rc == 0)289 expires = next->expires;290 }291 }292 } else {293 cqr->status = DASD_CQR_QUEUED;294 DBF_DEV_EVENT(DBF_DEBUG, device, "interrupt status for "295 "request %p was %d (%d retries left)", cqr,296 ext_code.subcode & 0xff, cqr->retries);297 dasd_diag_erp(device);298 }299 300 if (expires != 0)301 dasd_device_set_timer(device, expires);302 else303 dasd_device_clear_timer(device);304 dasd_schedule_device_bh(device);305 306 spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);307}308 309/* Check whether device can be controlled by DIAG discipline. Return zero on310 * success, non-zero otherwise. */311static int312dasd_diag_check_device(struct dasd_device *device)313{314 struct dasd_diag_private *private = device->private;315 struct dasd_diag_characteristics *rdc_data;316 struct vtoc_cms_label *label;317 struct dasd_block *block;318 struct dasd_diag_bio *bio;319 unsigned int sb, bsize;320 blocknum_t end_block;321 int rc;322 323 if (private == NULL) {324 private = kzalloc(sizeof(*private), GFP_KERNEL);325 if (private == NULL) {326 DBF_DEV_EVENT(DBF_WARNING, device, "%s",327 "Allocating memory for private DASD data "328 "failed\n");329 return -ENOMEM;330 }331 ccw_device_get_id(device->cdev, &private->dev_id);332 device->private = private;333 }334 block = dasd_alloc_block();335 if (IS_ERR(block)) {336 DBF_DEV_EVENT(DBF_WARNING, device, "%s",337 "could not allocate dasd block structure");338 device->private = NULL;339 kfree(private);340 return PTR_ERR(block);341 }342 device->block = block;343 block->base = device;344 345 /* Read Device Characteristics */346 rdc_data = &private->rdc_data;347 rdc_data->dev_nr = private->dev_id.devno;348 rdc_data->rdc_len = sizeof (struct dasd_diag_characteristics);349 350 rc = diag210((struct diag210 *) rdc_data);351 if (rc) {352 DBF_DEV_EVENT(DBF_WARNING, device, "failed to retrieve device "353 "information (rc=%d)", rc);354 rc = -EOPNOTSUPP;355 goto out;356 }357 358 device->default_expires = DIAG_TIMEOUT;359 device->default_retries = DIAG_MAX_RETRIES;360 361 /* Figure out position of label block */362 switch (private->rdc_data.vdev_class) {363 case DEV_CLASS_FBA:364 private->pt_block = 1;365 break;366 case DEV_CLASS_ECKD:367 private->pt_block = 2;368 break;369 default:370 pr_warn("%s: Device type %d is not supported in DIAG mode\n",371 dev_name(&device->cdev->dev),372 private->rdc_data.vdev_class);373 rc = -EOPNOTSUPP;374 goto out;375 }376 377 DBF_DEV_EVENT(DBF_INFO, device,378 "%04X: %04X on real %04X/%02X",379 rdc_data->dev_nr,380 rdc_data->vdev_type,381 rdc_data->rdev_type, rdc_data->rdev_model);382 383 /* terminate all outstanding operations */384 mdsk_term_io(device);385 386 /* figure out blocksize of device */387 label = (struct vtoc_cms_label *) get_zeroed_page(GFP_KERNEL);388 if (label == NULL) {389 DBF_DEV_EVENT(DBF_WARNING, device, "%s",390 "No memory to allocate initialization request");391 rc = -ENOMEM;392 goto out;393 }394 bio = kzalloc(sizeof(*bio), GFP_KERNEL);395 if (bio == NULL) {396 DBF_DEV_EVENT(DBF_WARNING, device, "%s",397 "No memory to allocate initialization bio");398 rc = -ENOMEM;399 goto out_label;400 }401 rc = 0;402 end_block = 0;403 /* try all sizes - needed for ECKD devices */404 for (bsize = 512; bsize <= PAGE_SIZE; bsize <<= 1) {405 mdsk_init_io(device, bsize, 0, &end_block);406 memset(bio, 0, sizeof(*bio));407 bio->type = MDSK_READ_REQ;408 bio->block_number = private->pt_block + 1;409 bio->buffer = label;410 memset(&private->iob, 0, sizeof (struct dasd_diag_rw_io));411 private->iob.dev_nr = rdc_data->dev_nr;412 private->iob.key = 0;413 private->iob.flags = 0; /* do synchronous io */414 private->iob.block_count = 1;415 private->iob.interrupt_params = 0;416 private->iob.bio_list = bio;417 private->iob.flaga = DASD_DIAG_FLAGA_DEFAULT;418 rc = dia250(&private->iob, RW_BIO);419 if (rc == 3) {420 pr_warn("%s: A 64-bit DIAG call failed\n",421 dev_name(&device->cdev->dev));422 rc = -EOPNOTSUPP;423 goto out_bio;424 }425 mdsk_term_io(device);426 if (rc == 0)427 break;428 }429 if (bsize > PAGE_SIZE) {430 pr_warn("%s: Accessing the DASD failed because of an incorrect format (rc=%d)\n",431 dev_name(&device->cdev->dev), rc);432 rc = -EIO;433 goto out_bio;434 }435 /* check for label block */436 if (memcmp(label->label_id, DASD_DIAG_CMS1,437 sizeof(DASD_DIAG_CMS1)) == 0) {438 /* get formatted blocksize from label block */439 bsize = (unsigned int) label->block_size;440 block->blocks = (unsigned long) label->block_count;441 } else442 block->blocks = end_block;443 block->bp_block = bsize;444 block->s2b_shift = 0; /* bits to shift 512 to get a block */445 for (sb = 512; sb < bsize; sb = sb << 1)446 block->s2b_shift++;447 rc = mdsk_init_io(device, block->bp_block, 0, NULL);448 if (rc && (rc != 4)) {449 pr_warn("%s: DIAG initialization failed with rc=%d\n",450 dev_name(&device->cdev->dev), rc);451 rc = -EIO;452 } else {453 if (rc == 4)454 set_bit(DASD_FLAG_DEVICE_RO, &device->flags);455 pr_info("%s: New DASD with %ld byte/block, total size %ld "456 "KB%s\n", dev_name(&device->cdev->dev),457 (unsigned long) block->bp_block,458 (unsigned long) (block->blocks <<459 block->s2b_shift) >> 1,460 (rc == 4) ? ", read-only device" : "");461 rc = 0;462 }463out_bio:464 kfree(bio);465out_label:466 free_page((long) label);467out:468 if (rc) {469 device->block = NULL;470 dasd_free_block(block);471 device->private = NULL;472 kfree(private);473 }474 return rc;475}476 477/* Fill in virtual disk geometry for device. Return zero on success, non-zero478 * otherwise. */479static int480dasd_diag_fill_geometry(struct dasd_block *block, struct hd_geometry *geo)481{482 if (dasd_check_blocksize(block->bp_block) != 0)483 return -EINVAL;484 geo->cylinders = (block->blocks << block->s2b_shift) >> 10;485 geo->heads = 16;486 geo->sectors = 128 >> block->s2b_shift;487 return 0;488}489 490static dasd_erp_fn_t491dasd_diag_erp_action(struct dasd_ccw_req * cqr)492{493 return dasd_default_erp_action;494}495 496static dasd_erp_fn_t497dasd_diag_erp_postaction(struct dasd_ccw_req * cqr)498{499 return dasd_default_erp_postaction;500}501 502/* Create DASD request from block device request. Return pointer to new503 * request on success, ERR_PTR otherwise. */504static struct dasd_ccw_req *dasd_diag_build_cp(struct dasd_device *memdev,505 struct dasd_block *block,506 struct request *req)507{508 struct dasd_ccw_req *cqr;509 struct dasd_diag_req *dreq;510 struct dasd_diag_bio *dbio;511 struct req_iterator iter;512 struct bio_vec bv;513 char *dst;514 unsigned int count;515 sector_t recid, first_rec, last_rec;516 unsigned int blksize, off;517 unsigned char rw_cmd;518 519 if (rq_data_dir(req) == READ)520 rw_cmd = MDSK_READ_REQ;521 else if (rq_data_dir(req) == WRITE)522 rw_cmd = MDSK_WRITE_REQ;523 else524 return ERR_PTR(-EINVAL);525 blksize = block->bp_block;526 /* Calculate record id of first and last block. */527 first_rec = blk_rq_pos(req) >> block->s2b_shift;528 last_rec =529 (blk_rq_pos(req) + blk_rq_sectors(req) - 1) >> block->s2b_shift;530 /* Check struct bio and count the number of blocks for the request. */531 count = 0;532 rq_for_each_segment(bv, req, iter) {533 if (bv.bv_len & (blksize - 1))534 /* Fba can only do full blocks. */535 return ERR_PTR(-EINVAL);536 count += bv.bv_len >> (block->s2b_shift + 9);537 }538 /* Paranoia. */539 if (count != last_rec - first_rec + 1)540 return ERR_PTR(-EINVAL);541 /* Build the request */542 cqr = dasd_smalloc_request(DASD_DIAG_MAGIC, 0, struct_size(dreq, bio, count),543 memdev, blk_mq_rq_to_pdu(req));544 if (IS_ERR(cqr))545 return cqr;546 547 dreq = (struct dasd_diag_req *) cqr->data;548 dreq->block_count = count;549 dbio = dreq->bio;550 recid = first_rec;551 rq_for_each_segment(bv, req, iter) {552 dst = bvec_virt(&bv);553 for (off = 0; off < bv.bv_len; off += blksize) {554 memset(dbio, 0, sizeof (struct dasd_diag_bio));555 dbio->type = rw_cmd;556 dbio->block_number = recid + 1;557 dbio->buffer = dst;558 dbio++;559 dst += blksize;560 recid++;561 }562 }563 cqr->retries = memdev->default_retries;564 cqr->buildclk = get_tod_clock();565 if (blk_noretry_request(req) ||566 block->base->features & DASD_FEATURE_FAILFAST)567 set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);568 cqr->startdev = memdev;569 cqr->memdev = memdev;570 cqr->block = block;571 cqr->expires = memdev->default_expires * HZ;572 cqr->status = DASD_CQR_FILLED;573 return cqr;574}575 576/* Release DASD request. Return non-zero if request was successful, zero577 * otherwise. */578static int579dasd_diag_free_cp(struct dasd_ccw_req *cqr, struct request *req)580{581 int status;582 583 status = cqr->status == DASD_CQR_DONE;584 dasd_sfree_request(cqr, cqr->memdev);585 return status;586}587 588static void dasd_diag_handle_terminated_request(struct dasd_ccw_req *cqr)589{590 if (cqr->retries < 0)591 cqr->status = DASD_CQR_FAILED;592 else593 cqr->status = DASD_CQR_FILLED;594};595 596/* Fill in IOCTL data for device. */597static int598dasd_diag_fill_info(struct dasd_device * device,599 struct dasd_information2_t * info)600{601 struct dasd_diag_private *private = device->private;602 603 info->label_block = (unsigned int) private->pt_block;604 info->FBA_layout = 1;605 info->format = DASD_FORMAT_LDL;606 info->characteristics_size = sizeof(private->rdc_data);607 memcpy(info->characteristics, &private->rdc_data,608 sizeof(private->rdc_data));609 info->confdata_size = 0;610 return 0;611}612 613static void614dasd_diag_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req,615 struct irb *stat)616{617 DBF_DEV_EVENT(DBF_WARNING, device, "%s",618 "dump sense not available for DIAG data");619}620 621static unsigned int dasd_diag_max_sectors(struct dasd_block *block)622{623 return DIAG_MAX_BLOCKS << block->s2b_shift;624}625 626static int dasd_diag_pe_handler(struct dasd_device *device,627 __u8 tbvpm, __u8 fcsecpm)628{629 return dasd_generic_verify_path(device, tbvpm);630}631 632static struct dasd_discipline dasd_diag_discipline = {633 .owner = THIS_MODULE,634 .name = "DIAG",635 .ebcname = "DIAG",636 .max_sectors = dasd_diag_max_sectors,637 .check_device = dasd_diag_check_device,638 .pe_handler = dasd_diag_pe_handler,639 .fill_geometry = dasd_diag_fill_geometry,640 .start_IO = dasd_start_diag,641 .term_IO = dasd_diag_term_IO,642 .handle_terminated_request = dasd_diag_handle_terminated_request,643 .erp_action = dasd_diag_erp_action,644 .erp_postaction = dasd_diag_erp_postaction,645 .build_cp = dasd_diag_build_cp,646 .free_cp = dasd_diag_free_cp,647 .dump_sense = dasd_diag_dump_sense,648 .fill_info = dasd_diag_fill_info,649};650 651static int __init652dasd_diag_init(void)653{654 if (!MACHINE_IS_VM) {655 pr_info("Discipline %s cannot be used without z/VM\n",656 dasd_diag_discipline.name);657 return -ENODEV;658 }659 ASCEBC(dasd_diag_discipline.ebcname, 4);660 661 irq_subclass_register(IRQ_SUBCLASS_SERVICE_SIGNAL);662 register_external_irq(EXT_IRQ_CP_SERVICE, dasd_ext_handler);663 dasd_diag_discipline_pointer = &dasd_diag_discipline;664 return 0;665}666 667static void __exit668dasd_diag_cleanup(void)669{670 unregister_external_irq(EXT_IRQ_CP_SERVICE, dasd_ext_handler);671 irq_subclass_unregister(IRQ_SUBCLASS_SERVICE_SIGNAL);672 dasd_diag_discipline_pointer = NULL;673}674 675module_init(dasd_diag_init);676module_exit(dasd_diag_cleanup);677