aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/block/dasd_diag.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/block/dasd_diag.c')
-rw-r--r--drivers/s390/block/dasd_diag.c107
1 files changed, 60 insertions, 47 deletions
diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c
index 571320ab9e1a..d91df38ee4f7 100644
--- a/drivers/s390/block/dasd_diag.c
+++ b/drivers/s390/block/dasd_diag.c
@@ -142,7 +142,7 @@ dasd_diag_erp(struct dasd_device *device)
142 int rc; 142 int rc;
143 143
144 mdsk_term_io(device); 144 mdsk_term_io(device);
145 rc = mdsk_init_io(device, device->bp_block, 0, NULL); 145 rc = mdsk_init_io(device, device->block->bp_block, 0, NULL);
146 if (rc) 146 if (rc)
147 DEV_MESSAGE(KERN_WARNING, device, "DIAG ERP unsuccessful, " 147 DEV_MESSAGE(KERN_WARNING, device, "DIAG ERP unsuccessful, "
148 "rc=%d", rc); 148 "rc=%d", rc);
@@ -158,11 +158,11 @@ dasd_start_diag(struct dasd_ccw_req * cqr)
158 struct dasd_diag_req *dreq; 158 struct dasd_diag_req *dreq;
159 int rc; 159 int rc;
160 160
161 device = cqr->device; 161 device = cqr->startdev;
162 if (cqr->retries < 0) { 162 if (cqr->retries < 0) {
163 DEV_MESSAGE(KERN_WARNING, device, "DIAG start_IO: request %p " 163 DEV_MESSAGE(KERN_WARNING, device, "DIAG start_IO: request %p "
164 "- no retry left)", cqr); 164 "- no retry left)", cqr);
165 cqr->status = DASD_CQR_FAILED; 165 cqr->status = DASD_CQR_ERROR;
166 return -EIO; 166 return -EIO;
167 } 167 }
168 private = (struct dasd_diag_private *) device->private; 168 private = (struct dasd_diag_private *) device->private;
@@ -184,7 +184,7 @@ dasd_start_diag(struct dasd_ccw_req * cqr)
184 switch (rc) { 184 switch (rc) {
185 case 0: /* Synchronous I/O finished successfully */ 185 case 0: /* Synchronous I/O finished successfully */
186 cqr->stopclk = get_clock(); 186 cqr->stopclk = get_clock();
187 cqr->status = DASD_CQR_DONE; 187 cqr->status = DASD_CQR_SUCCESS;
188 /* Indicate to calling function that only a dasd_schedule_bh() 188 /* Indicate to calling function that only a dasd_schedule_bh()
189 and no timer is needed */ 189 and no timer is needed */
190 rc = -EACCES; 190 rc = -EACCES;
@@ -209,12 +209,12 @@ dasd_diag_term_IO(struct dasd_ccw_req * cqr)
209{ 209{
210 struct dasd_device *device; 210 struct dasd_device *device;
211 211
212 device = cqr->device; 212 device = cqr->startdev;
213 mdsk_term_io(device); 213 mdsk_term_io(device);
214 mdsk_init_io(device, device->bp_block, 0, NULL); 214 mdsk_init_io(device, device->block->bp_block, 0, NULL);
215 cqr->status = DASD_CQR_CLEAR; 215 cqr->status = DASD_CQR_CLEAR_PENDING;
216 cqr->stopclk = get_clock(); 216 cqr->stopclk = get_clock();
217 dasd_schedule_bh(device); 217 dasd_schedule_device_bh(device);
218 return 0; 218 return 0;
219} 219}
220 220
@@ -247,7 +247,7 @@ dasd_ext_handler(__u16 code)
247 return; 247 return;
248 } 248 }
249 cqr = (struct dasd_ccw_req *) ip; 249 cqr = (struct dasd_ccw_req *) ip;
250 device = (struct dasd_device *) cqr->device; 250 device = (struct dasd_device *) cqr->startdev;
251 if (strncmp(device->discipline->ebcname, (char *) &cqr->magic, 4)) { 251 if (strncmp(device->discipline->ebcname, (char *) &cqr->magic, 4)) {
252 DEV_MESSAGE(KERN_WARNING, device, 252 DEV_MESSAGE(KERN_WARNING, device,
253 " magic number of dasd_ccw_req 0x%08X doesn't" 253 " magic number of dasd_ccw_req 0x%08X doesn't"
@@ -260,10 +260,10 @@ dasd_ext_handler(__u16 code)
260 spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); 260 spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
261 261
262 /* Check for a pending clear operation */ 262 /* Check for a pending clear operation */
263 if (cqr->status == DASD_CQR_CLEAR) { 263 if (cqr->status == DASD_CQR_CLEAR_PENDING) {
264 cqr->status = DASD_CQR_QUEUED; 264 cqr->status = DASD_CQR_CLEARED;
265 dasd_clear_timer(device); 265 dasd_device_clear_timer(device);
266 dasd_schedule_bh(device); 266 dasd_schedule_device_bh(device);
267 spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); 267 spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
268 return; 268 return;
269 } 269 }
@@ -272,11 +272,11 @@ dasd_ext_handler(__u16 code)
272 272
273 expires = 0; 273 expires = 0;
274 if (status == 0) { 274 if (status == 0) {
275 cqr->status = DASD_CQR_DONE; 275 cqr->status = DASD_CQR_SUCCESS;
276 /* Start first request on queue if possible -> fast_io. */ 276 /* Start first request on queue if possible -> fast_io. */
277 if (!list_empty(&device->ccw_queue)) { 277 if (!list_empty(&device->ccw_queue)) {
278 next = list_entry(device->ccw_queue.next, 278 next = list_entry(device->ccw_queue.next,
279 struct dasd_ccw_req, list); 279 struct dasd_ccw_req, devlist);
280 if (next->status == DASD_CQR_QUEUED) { 280 if (next->status == DASD_CQR_QUEUED) {
281 rc = dasd_start_diag(next); 281 rc = dasd_start_diag(next);
282 if (rc == 0) 282 if (rc == 0)
@@ -296,10 +296,10 @@ dasd_ext_handler(__u16 code)
296 } 296 }
297 297
298 if (expires != 0) 298 if (expires != 0)
299 dasd_set_timer(device, expires); 299 dasd_device_set_timer(device, expires);
300 else 300 else
301 dasd_clear_timer(device); 301 dasd_device_clear_timer(device);
302 dasd_schedule_bh(device); 302 dasd_schedule_device_bh(device);
303 303
304 spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); 304 spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
305} 305}
@@ -309,6 +309,7 @@ dasd_ext_handler(__u16 code)
309static int 309static int
310dasd_diag_check_device(struct dasd_device *device) 310dasd_diag_check_device(struct dasd_device *device)
311{ 311{
312 struct dasd_block *block;
312 struct dasd_diag_private *private; 313 struct dasd_diag_private *private;
313 struct dasd_diag_characteristics *rdc_data; 314 struct dasd_diag_characteristics *rdc_data;
314 struct dasd_diag_bio bio; 315 struct dasd_diag_bio bio;
@@ -328,6 +329,16 @@ dasd_diag_check_device(struct dasd_device *device)
328 ccw_device_get_id(device->cdev, &private->dev_id); 329 ccw_device_get_id(device->cdev, &private->dev_id);
329 device->private = (void *) private; 330 device->private = (void *) private;
330 } 331 }
332 block = dasd_alloc_block();
333 if (IS_ERR(block)) {
334 DEV_MESSAGE(KERN_WARNING, device, "%s",
335 "could not allocate dasd block structure");
336 kfree(device->private);
337 return PTR_ERR(block);
338 }
339 device->block = block;
340 block->base = device;
341
331 /* Read Device Characteristics */ 342 /* Read Device Characteristics */
332 rdc_data = (void *) &(private->rdc_data); 343 rdc_data = (void *) &(private->rdc_data);
333 rdc_data->dev_nr = private->dev_id.devno; 344 rdc_data->dev_nr = private->dev_id.devno;
@@ -409,14 +420,14 @@ dasd_diag_check_device(struct dasd_device *device)
409 sizeof(DASD_DIAG_CMS1)) == 0) { 420 sizeof(DASD_DIAG_CMS1)) == 0) {
410 /* get formatted blocksize from label block */ 421 /* get formatted blocksize from label block */
411 bsize = (unsigned int) label->block_size; 422 bsize = (unsigned int) label->block_size;
412 device->blocks = (unsigned long) label->block_count; 423 block->blocks = (unsigned long) label->block_count;
413 } else 424 } else
414 device->blocks = end_block; 425 block->blocks = end_block;
415 device->bp_block = bsize; 426 block->bp_block = bsize;
416 device->s2b_shift = 0; /* bits to shift 512 to get a block */ 427 block->s2b_shift = 0; /* bits to shift 512 to get a block */
417 for (sb = 512; sb < bsize; sb = sb << 1) 428 for (sb = 512; sb < bsize; sb = sb << 1)
418 device->s2b_shift++; 429 block->s2b_shift++;
419 rc = mdsk_init_io(device, device->bp_block, 0, NULL); 430 rc = mdsk_init_io(device, block->bp_block, 0, NULL);
420 if (rc) { 431 if (rc) {
421 DEV_MESSAGE(KERN_WARNING, device, "DIAG initialization " 432 DEV_MESSAGE(KERN_WARNING, device, "DIAG initialization "
422 "failed (rc=%d)", rc); 433 "failed (rc=%d)", rc);
@@ -424,9 +435,9 @@ dasd_diag_check_device(struct dasd_device *device)
424 } else { 435 } else {
425 DEV_MESSAGE(KERN_INFO, device, 436 DEV_MESSAGE(KERN_INFO, device,
426 "(%ld B/blk): %ldkB", 437 "(%ld B/blk): %ldkB",
427 (unsigned long) device->bp_block, 438 (unsigned long) block->bp_block,
428 (unsigned long) (device->blocks << 439 (unsigned long) (block->blocks <<
429 device->s2b_shift) >> 1); 440 block->s2b_shift) >> 1);
430 } 441 }
431out: 442out:
432 free_page((long) label); 443 free_page((long) label);
@@ -436,22 +447,16 @@ out:
436/* Fill in virtual disk geometry for device. Return zero on success, non-zero 447/* Fill in virtual disk geometry for device. Return zero on success, non-zero
437 * otherwise. */ 448 * otherwise. */
438static int 449static int
439dasd_diag_fill_geometry(struct dasd_device *device, struct hd_geometry *geo) 450dasd_diag_fill_geometry(struct dasd_block *block, struct hd_geometry *geo)
440{ 451{
441 if (dasd_check_blocksize(device->bp_block) != 0) 452 if (dasd_check_blocksize(block->bp_block) != 0)
442 return -EINVAL; 453 return -EINVAL;
443 geo->cylinders = (device->blocks << device->s2b_shift) >> 10; 454 geo->cylinders = (block->blocks << block->s2b_shift) >> 10;
444 geo->heads = 16; 455 geo->heads = 16;
445 geo->sectors = 128 >> device->s2b_shift; 456 geo->sectors = 128 >> block->s2b_shift;
446 return 0; 457 return 0;
447} 458}
448 459
449static dasd_era_t
450dasd_diag_examine_error(struct dasd_ccw_req * cqr, struct irb * stat)
451{
452 return dasd_era_fatal;
453}
454
455static dasd_erp_fn_t 460static dasd_erp_fn_t
456dasd_diag_erp_action(struct dasd_ccw_req * cqr) 461dasd_diag_erp_action(struct dasd_ccw_req * cqr)
457{ 462{
@@ -466,8 +471,9 @@ dasd_diag_erp_postaction(struct dasd_ccw_req * cqr)
466 471
467/* Create DASD request from block device request. Return pointer to new 472/* Create DASD request from block device request. Return pointer to new
468 * request on success, ERR_PTR otherwise. */ 473 * request on success, ERR_PTR otherwise. */
469static struct dasd_ccw_req * 474static struct dasd_ccw_req *dasd_diag_build_cp(struct dasd_device *memdev,
470dasd_diag_build_cp(struct dasd_device * device, struct request *req) 475 struct dasd_block *block,
476 struct request *req)
471{ 477{
472 struct dasd_ccw_req *cqr; 478 struct dasd_ccw_req *cqr;
473 struct dasd_diag_req *dreq; 479 struct dasd_diag_req *dreq;
@@ -486,17 +492,17 @@ dasd_diag_build_cp(struct dasd_device * device, struct request *req)
486 rw_cmd = MDSK_WRITE_REQ; 492 rw_cmd = MDSK_WRITE_REQ;
487 else 493 else
488 return ERR_PTR(-EINVAL); 494 return ERR_PTR(-EINVAL);
489 blksize = device->bp_block; 495 blksize = block->bp_block;
490 /* Calculate record id of first and last block. */ 496 /* Calculate record id of first and last block. */
491 first_rec = req->sector >> device->s2b_shift; 497 first_rec = req->sector >> block->s2b_shift;
492 last_rec = (req->sector + req->nr_sectors - 1) >> device->s2b_shift; 498 last_rec = (req->sector + req->nr_sectors - 1) >> block->s2b_shift;
493 /* Check struct bio and count the number of blocks for the request. */ 499 /* Check struct bio and count the number of blocks for the request. */
494 count = 0; 500 count = 0;
495 rq_for_each_segment(bv, req, iter) { 501 rq_for_each_segment(bv, req, iter) {
496 if (bv->bv_len & (blksize - 1)) 502 if (bv->bv_len & (blksize - 1))
497 /* Fba can only do full blocks. */ 503 /* Fba can only do full blocks. */
498 return ERR_PTR(-EINVAL); 504 return ERR_PTR(-EINVAL);
499 count += bv->bv_len >> (device->s2b_shift + 9); 505 count += bv->bv_len >> (block->s2b_shift + 9);
500 } 506 }
501 /* Paranoia. */ 507 /* Paranoia. */
502 if (count != last_rec - first_rec + 1) 508 if (count != last_rec - first_rec + 1)
@@ -505,7 +511,7 @@ dasd_diag_build_cp(struct dasd_device * device, struct request *req)
505 datasize = sizeof(struct dasd_diag_req) + 511 datasize = sizeof(struct dasd_diag_req) +
506 count*sizeof(struct dasd_diag_bio); 512 count*sizeof(struct dasd_diag_bio);
507 cqr = dasd_smalloc_request(dasd_diag_discipline.name, 0, 513 cqr = dasd_smalloc_request(dasd_diag_discipline.name, 0,
508 datasize, device); 514 datasize, memdev);
509 if (IS_ERR(cqr)) 515 if (IS_ERR(cqr))
510 return cqr; 516 return cqr;
511 517
@@ -529,7 +535,9 @@ dasd_diag_build_cp(struct dasd_device * device, struct request *req)
529 cqr->buildclk = get_clock(); 535 cqr->buildclk = get_clock();
530 if (req->cmd_flags & REQ_FAILFAST) 536 if (req->cmd_flags & REQ_FAILFAST)
531 set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags); 537 set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
532 cqr->device = device; 538 cqr->startdev = memdev;
539 cqr->memdev = memdev;
540 cqr->block = block;
533 cqr->expires = DIAG_TIMEOUT; 541 cqr->expires = DIAG_TIMEOUT;
534 cqr->status = DASD_CQR_FILLED; 542 cqr->status = DASD_CQR_FILLED;
535 return cqr; 543 return cqr;
@@ -543,10 +551,15 @@ dasd_diag_free_cp(struct dasd_ccw_req *cqr, struct request *req)
543 int status; 551 int status;
544 552
545 status = cqr->status == DASD_CQR_DONE; 553 status = cqr->status == DASD_CQR_DONE;
546 dasd_sfree_request(cqr, cqr->device); 554 dasd_sfree_request(cqr, cqr->memdev);
547 return status; 555 return status;
548} 556}
549 557
558static void dasd_diag_handle_terminated_request(struct dasd_ccw_req *cqr)
559{
560 cqr->status = DASD_CQR_FILLED;
561};
562
550/* Fill in IOCTL data for device. */ 563/* Fill in IOCTL data for device. */
551static int 564static int
552dasd_diag_fill_info(struct dasd_device * device, 565dasd_diag_fill_info(struct dasd_device * device,
@@ -583,7 +596,7 @@ static struct dasd_discipline dasd_diag_discipline = {
583 .fill_geometry = dasd_diag_fill_geometry, 596 .fill_geometry = dasd_diag_fill_geometry,
584 .start_IO = dasd_start_diag, 597 .start_IO = dasd_start_diag,
585 .term_IO = dasd_diag_term_IO, 598 .term_IO = dasd_diag_term_IO,
586 .examine_error = dasd_diag_examine_error, 599 .handle_terminated_request = dasd_diag_handle_terminated_request,
587 .erp_action = dasd_diag_erp_action, 600 .erp_action = dasd_diag_erp_action,
588 .erp_postaction = dasd_diag_erp_postaction, 601 .erp_postaction = dasd_diag_erp_postaction,
589 .build_cp = dasd_diag_build_cp, 602 .build_cp = dasd_diag_build_cp,