1 /* 2 * File...........: linux/drivers/s390/block/dasd_fba.c 3 * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com> 4 * Bugreports.to..: <Linux390@de.ibm.com> 5 * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 6 * 7 * $Revision: 1.41 $ 8 */ 9 10 #include <linux/config.h> 11 #include <linux/stddef.h> 12 #include <linux/kernel.h> 13 #include <asm/debug.h> 14 15 #include <linux/slab.h> 16 #include <linux/hdreg.h> /* HDIO_GETGEO */ 17 #include <linux/bio.h> 18 #include <linux/module.h> 19 #include <linux/init.h> 20 21 #include <asm/idals.h> 22 #include <asm/ebcdic.h> 23 #include <asm/io.h> 24 #include <asm/todclk.h> 25 #include <asm/ccwdev.h> 26 27 #include "dasd_int.h" 28 #include "dasd_fba.h" 29 30 #ifdef PRINTK_HEADER 31 #undef PRINTK_HEADER 32 #endif /* PRINTK_HEADER */ 33 #define PRINTK_HEADER "dasd(fba):" 34 35 #define DASD_FBA_CCW_WRITE 0x41 36 #define DASD_FBA_CCW_READ 0x42 37 #define DASD_FBA_CCW_LOCATE 0x43 38 #define DASD_FBA_CCW_DEFINE_EXTENT 0x63 39 40 MODULE_LICENSE("GPL"); 41 42 static struct dasd_discipline dasd_fba_discipline; 43 44 struct dasd_fba_private { 45 struct dasd_fba_characteristics rdc_data; 46 }; 47 48 static struct ccw_device_id dasd_fba_ids[] = { 49 { CCW_DEVICE_DEVTYPE (0x6310, 0, 0x9336, 0), driver_info: 0x1}, 50 { CCW_DEVICE_DEVTYPE (0x3880, 0, 0x3370, 0), driver_info: 0x2}, 51 { /* end of list */ }, 52 }; 53 54 MODULE_DEVICE_TABLE(ccw, dasd_fba_ids); 55 56 static struct ccw_driver dasd_fba_driver; /* see below */ 57 static int 58 dasd_fba_probe(struct ccw_device *cdev) 59 { 60 int ret; 61 62 ret = dasd_generic_probe (cdev, &dasd_fba_discipline); 63 if (ret) 64 return ret; 65 ccw_device_set_options(cdev, CCWDEV_DO_PATHGROUP); 66 return 0; 67 } 68 69 static int 70 dasd_fba_set_online(struct ccw_device *cdev) 71 { 72 return dasd_generic_set_online (cdev, &dasd_fba_discipline); 73 } 74 75 static struct ccw_driver dasd_fba_driver = { 76 .name = "dasd-fba", 77 .owner = THIS_MODULE, 78 .ids = dasd_fba_ids, 79 .probe = dasd_fba_probe, 80 .remove = dasd_generic_remove, 81 .set_offline = dasd_generic_set_offline, 82 .set_online = dasd_fba_set_online, 83 .notify = dasd_generic_notify, 84 }; 85 86 static inline void 87 define_extent(struct ccw1 * ccw, struct DE_fba_data *data, int rw, 88 int blksize, int beg, int nr) 89 { 90 ccw->cmd_code = DASD_FBA_CCW_DEFINE_EXTENT; 91 ccw->flags = 0; 92 ccw->count = 16; 93 ccw->cda = (__u32) __pa(data); 94 memset(data, 0, sizeof (struct DE_fba_data)); 95 if (rw == WRITE) 96 (data->mask).perm = 0x0; 97 else if (rw == READ) 98 (data->mask).perm = 0x1; 99 else 100 data->mask.perm = 0x2; 101 data->blk_size = blksize; 102 data->ext_loc = beg; 103 data->ext_end = nr - 1; 104 } 105 106 static inline void 107 locate_record(struct ccw1 * ccw, struct LO_fba_data *data, int rw, 108 int block_nr, int block_ct) 109 { 110 ccw->cmd_code = DASD_FBA_CCW_LOCATE; 111 ccw->flags = 0; 112 ccw->count = 8; 113 ccw->cda = (__u32) __pa(data); 114 memset(data, 0, sizeof (struct LO_fba_data)); 115 if (rw == WRITE) 116 data->operation.cmd = 0x5; 117 else if (rw == READ) 118 data->operation.cmd = 0x6; 119 else 120 data->operation.cmd = 0x8; 121 data->blk_nr = block_nr; 122 data->blk_ct = block_ct; 123 } 124 125 static int 126 dasd_fba_check_characteristics(struct dasd_device *device) 127 { 128 struct dasd_fba_private *private; 129 struct ccw_device *cdev = device->cdev; 130 void *rdc_data; 131 int rc; 132 133 private = (struct dasd_fba_private *) device->private; 134 if (private == NULL) { 135 private = kmalloc(sizeof(struct dasd_fba_private), GFP_KERNEL); 136 if (private == NULL) { 137 DEV_MESSAGE(KERN_WARNING, device, "%s", 138 "memory allocation failed for private " 139 "data"); 140 return -ENOMEM; 141 } 142 device->private = (void *) private; 143 } 144 /* Read Device Characteristics */ 145 rdc_data = (void *) &(private->rdc_data); 146 rc = read_dev_chars(device->cdev, &rdc_data, 32); 147 if (rc) { 148 DEV_MESSAGE(KERN_WARNING, device, 149 "Read device characteristics returned error %d", 150 rc); 151 return rc; 152 } 153 154 DEV_MESSAGE(KERN_INFO, device, 155 "%04X/%02X(CU:%04X/%02X) %dMB at(%d B/blk)", 156 cdev->id.dev_type, 157 cdev->id.dev_model, 158 cdev->id.cu_type, 159 cdev->id.cu_model, 160 ((private->rdc_data.blk_bdsa * 161 (private->rdc_data.blk_size >> 9)) >> 11), 162 private->rdc_data.blk_size); 163 return 0; 164 } 165 166 static int 167 dasd_fba_do_analysis(struct dasd_device *device) 168 { 169 struct dasd_fba_private *private; 170 int sb, rc; 171 172 private = (struct dasd_fba_private *) device->private; 173 rc = dasd_check_blocksize(private->rdc_data.blk_size); 174 if (rc) { 175 DEV_MESSAGE(KERN_INFO, device, "unknown blocksize %d", 176 private->rdc_data.blk_size); 177 return rc; 178 } 179 device->blocks = private->rdc_data.blk_bdsa; 180 device->bp_block = private->rdc_data.blk_size; 181 device->s2b_shift = 0; /* bits to shift 512 to get a block */ 182 for (sb = 512; sb < private->rdc_data.blk_size; sb = sb << 1) 183 device->s2b_shift++; 184 return 0; 185 } 186 187 static int 188 dasd_fba_fill_geometry(struct dasd_device *device, struct hd_geometry *geo) 189 { 190 if (dasd_check_blocksize(device->bp_block) != 0) 191 return -EINVAL; 192 geo->cylinders = (device->blocks << device->s2b_shift) >> 10; 193 geo->heads = 16; 194 geo->sectors = 128 >> device->s2b_shift; 195 return 0; 196 } 197 198 static dasd_era_t 199 dasd_fba_examine_error(struct dasd_ccw_req * cqr, struct irb * irb) 200 { 201 struct dasd_device *device; 202 struct ccw_device *cdev; 203 204 device = (struct dasd_device *) cqr->device; 205 if (irb->scsw.cstat == 0x00 && 206 irb->scsw.dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END)) 207 return dasd_era_none; 208 209 cdev = device->cdev; 210 switch (cdev->id.dev_type) { 211 case 0x3370: 212 return dasd_3370_erp_examine(cqr, irb); 213 case 0x9336: 214 return dasd_9336_erp_examine(cqr, irb); 215 default: 216 return dasd_era_recover; 217 } 218 } 219 220 static dasd_erp_fn_t 221 dasd_fba_erp_action(struct dasd_ccw_req * cqr) 222 { 223 return dasd_default_erp_action; 224 } 225 226 static dasd_erp_fn_t 227 dasd_fba_erp_postaction(struct dasd_ccw_req * cqr) 228 { 229 if (cqr->function == dasd_default_erp_action) 230 return dasd_default_erp_postaction; 231 232 DEV_MESSAGE(KERN_WARNING, cqr->device, "unknown ERP action %p", 233 cqr->function); 234 return NULL; 235 } 236 237 static struct dasd_ccw_req * 238 dasd_fba_build_cp(struct dasd_device * device, struct request *req) 239 { 240 struct dasd_fba_private *private; 241 unsigned long *idaws; 242 struct LO_fba_data *LO_data; 243 struct dasd_ccw_req *cqr; 244 struct ccw1 *ccw; 245 struct bio *bio; 246 struct bio_vec *bv; 247 char *dst; 248 int count, cidaw, cplength, datasize; 249 sector_t recid, first_rec, last_rec; 250 unsigned int blksize, off; 251 unsigned char cmd; 252 int i; 253 254 private = (struct dasd_fba_private *) device->private; 255 if (rq_data_dir(req) == READ) { 256 cmd = DASD_FBA_CCW_READ; 257 } else if (rq_data_dir(req) == WRITE) { 258 cmd = DASD_FBA_CCW_WRITE; 259 } else 260 return ERR_PTR(-EINVAL); 261 blksize = device->bp_block; 262 /* Calculate record id of first and last block. */ 263 first_rec = req->sector >> device->s2b_shift; 264 last_rec = (req->sector + req->nr_sectors - 1) >> device->s2b_shift; 265 /* Check struct bio and count the number of blocks for the request. */ 266 count = 0; 267 cidaw = 0; 268 rq_for_each_bio(bio, req) { 269 bio_for_each_segment(bv, bio, i) { 270 if (bv->bv_len & (blksize - 1)) 271 /* Fba can only do full blocks. */ 272 return ERR_PTR(-EINVAL); 273 count += bv->bv_len >> (device->s2b_shift + 9); 274 #if defined(CONFIG_64BIT) 275 if (idal_is_needed (page_address(bv->bv_page), 276 bv->bv_len)) 277 cidaw += bv->bv_len / blksize; 278 #endif 279 } 280 } 281 /* Paranoia. */ 282 if (count != last_rec - first_rec + 1) 283 return ERR_PTR(-EINVAL); 284 /* 1x define extent + 1x locate record + number of blocks */ 285 cplength = 2 + count; 286 /* 1x define extent + 1x locate record */ 287 datasize = sizeof(struct DE_fba_data) + sizeof(struct LO_fba_data) + 288 cidaw * sizeof(unsigned long); 289 /* 290 * Find out number of additional locate record ccws if the device 291 * can't do data chaining. 292 */ 293 if (private->rdc_data.mode.bits.data_chain == 0) { 294 cplength += count - 1; 295 datasize += (count - 1)*sizeof(struct LO_fba_data); 296 } 297 /* Allocate the ccw request. */ 298 cqr = dasd_smalloc_request(dasd_fba_discipline.name, 299 cplength, datasize, device); 300 if (IS_ERR(cqr)) 301 return cqr; 302 ccw = cqr->cpaddr; 303 /* First ccw is define extent. */ 304 define_extent(ccw++, cqr->data, rq_data_dir(req), 305 device->bp_block, req->sector, req->nr_sectors); 306 /* Build locate_record + read/write ccws. */ 307 idaws = (unsigned long *) (cqr->data + sizeof(struct DE_fba_data)); 308 LO_data = (struct LO_fba_data *) (idaws + cidaw); 309 /* Locate record for all blocks for smart devices. */ 310 if (private->rdc_data.mode.bits.data_chain != 0) { 311 ccw[-1].flags |= CCW_FLAG_CC; 312 locate_record(ccw++, LO_data++, rq_data_dir(req), 0, count); 313 } 314 recid = first_rec; 315 rq_for_each_bio(bio, req) bio_for_each_segment(bv, bio, i) { 316 dst = page_address(bv->bv_page) + bv->bv_offset; 317 if (dasd_page_cache) { 318 char *copy = kmem_cache_alloc(dasd_page_cache, 319 SLAB_DMA | __GFP_NOWARN); 320 if (copy && rq_data_dir(req) == WRITE) 321 memcpy(copy + bv->bv_offset, dst, bv->bv_len); 322 if (copy) 323 dst = copy + bv->bv_offset; 324 } 325 for (off = 0; off < bv->bv_len; off += blksize) { 326 /* Locate record for stupid devices. */ 327 if (private->rdc_data.mode.bits.data_chain == 0) { 328 ccw[-1].flags |= CCW_FLAG_CC; 329 locate_record(ccw, LO_data++, 330 rq_data_dir(req), 331 recid - first_rec, 1); 332 ccw->flags = CCW_FLAG_CC; 333 ccw++; 334 } else { 335 if (recid > first_rec) 336 ccw[-1].flags |= CCW_FLAG_DC; 337 else 338 ccw[-1].flags |= CCW_FLAG_CC; 339 } 340 ccw->cmd_code = cmd; 341 ccw->count = device->bp_block; 342 if (idal_is_needed(dst, blksize)) { 343 ccw->cda = (__u32)(addr_t) idaws; 344 ccw->flags = CCW_FLAG_IDA; 345 idaws = idal_create_words(idaws, dst, blksize); 346 } else { 347 ccw->cda = (__u32)(addr_t) dst; 348 ccw->flags = 0; 349 } 350 ccw++; 351 dst += blksize; 352 recid++; 353 } 354 } 355 if (req->flags & REQ_FAILFAST) 356 set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags); 357 cqr->device = device; 358 cqr->expires = 5 * 60 * HZ; /* 5 minutes */ 359 cqr->retries = 32; 360 cqr->buildclk = get_clock(); 361 cqr->status = DASD_CQR_FILLED; 362 return cqr; 363 } 364 365 static int 366 dasd_fba_free_cp(struct dasd_ccw_req *cqr, struct request *req) 367 { 368 struct dasd_fba_private *private; 369 struct ccw1 *ccw; 370 struct bio *bio; 371 struct bio_vec *bv; 372 char *dst, *cda; 373 unsigned int blksize, off; 374 int i, status; 375 376 if (!dasd_page_cache) 377 goto out; 378 private = (struct dasd_fba_private *) cqr->device->private; 379 blksize = cqr->device->bp_block; 380 ccw = cqr->cpaddr; 381 /* Skip over define extent & locate record. */ 382 ccw++; 383 if (private->rdc_data.mode.bits.data_chain != 0) 384 ccw++; 385 rq_for_each_bio(bio, req) bio_for_each_segment(bv, bio, i) { 386 dst = page_address(bv->bv_page) + bv->bv_offset; 387 for (off = 0; off < bv->bv_len; off += blksize) { 388 /* Skip locate record. */ 389 if (private->rdc_data.mode.bits.data_chain == 0) 390 ccw++; 391 if (dst) { 392 if (ccw->flags & CCW_FLAG_IDA) 393 cda = *((char **)((addr_t) ccw->cda)); 394 else 395 cda = (char *)((addr_t) ccw->cda); 396 if (dst != cda) { 397 if (rq_data_dir(req) == READ) 398 memcpy(dst, cda, bv->bv_len); 399 kmem_cache_free(dasd_page_cache, 400 (void *)((addr_t)cda & PAGE_MASK)); 401 } 402 dst = NULL; 403 } 404 ccw++; 405 } 406 } 407 out: 408 status = cqr->status == DASD_CQR_DONE; 409 dasd_sfree_request(cqr, cqr->device); 410 return status; 411 } 412 413 static int 414 dasd_fba_fill_info(struct dasd_device * device, 415 struct dasd_information2_t * info) 416 { 417 info->label_block = 1; 418 info->FBA_layout = 1; 419 info->format = DASD_FORMAT_LDL; 420 info->characteristics_size = sizeof(struct dasd_fba_characteristics); 421 memcpy(info->characteristics, 422 &((struct dasd_fba_private *) device->private)->rdc_data, 423 sizeof (struct dasd_fba_characteristics)); 424 info->confdata_size = 0; 425 return 0; 426 } 427 428 static void 429 dasd_fba_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req, 430 struct irb *irb) 431 { 432 char *page; 433 struct ccw1 *act, *end, *last; 434 int len, sl, sct, count; 435 436 page = (char *) get_zeroed_page(GFP_ATOMIC); 437 if (page == NULL) { 438 DEV_MESSAGE(KERN_ERR, device, " %s", 439 "No memory to dump sense data"); 440 return; 441 } 442 len = sprintf(page, KERN_ERR PRINTK_HEADER 443 " I/O status report for device %s:\n", 444 device->cdev->dev.bus_id); 445 len += sprintf(page + len, KERN_ERR PRINTK_HEADER 446 " in req: %p CS: 0x%02X DS: 0x%02X\n", req, 447 irb->scsw.cstat, irb->scsw.dstat); 448 len += sprintf(page + len, KERN_ERR PRINTK_HEADER 449 " device %s: Failing CCW: %p\n", 450 device->cdev->dev.bus_id, 451 (void *) (addr_t) irb->scsw.cpa); 452 if (irb->esw.esw0.erw.cons) { 453 for (sl = 0; sl < 4; sl++) { 454 len += sprintf(page + len, KERN_ERR PRINTK_HEADER 455 " Sense(hex) %2d-%2d:", 456 (8 * sl), ((8 * sl) + 7)); 457 458 for (sct = 0; sct < 8; sct++) { 459 len += sprintf(page + len, " %02x", 460 irb->ecw[8 * sl + sct]); 461 } 462 len += sprintf(page + len, "\n"); 463 } 464 } else { 465 len += sprintf(page + len, KERN_ERR PRINTK_HEADER 466 " SORRY - NO VALID SENSE AVAILABLE\n"); 467 } 468 MESSAGE_LOG(KERN_ERR, "%s", 469 page + sizeof(KERN_ERR PRINTK_HEADER)); 470 471 /* dump the Channel Program */ 472 /* print first CCWs (maximum 8) */ 473 act = req->cpaddr; 474 for (last = act; last->flags & (CCW_FLAG_CC | CCW_FLAG_DC); last++); 475 end = min(act + 8, last); 476 len = sprintf(page, KERN_ERR PRINTK_HEADER 477 " Related CP in req: %p\n", req); 478 while (act <= end) { 479 len += sprintf(page + len, KERN_ERR PRINTK_HEADER 480 " CCW %p: %08X %08X DAT:", 481 act, ((int *) act)[0], ((int *) act)[1]); 482 for (count = 0; count < 32 && count < act->count; 483 count += sizeof(int)) 484 len += sprintf(page + len, " %08X", 485 ((int *) (addr_t) act->cda) 486 [(count>>2)]); 487 len += sprintf(page + len, "\n"); 488 act++; 489 } 490 MESSAGE_LOG(KERN_ERR, "%s", 491 page + sizeof(KERN_ERR PRINTK_HEADER)); 492 493 494 /* print failing CCW area */ 495 len = 0; 496 if (act < ((struct ccw1 *)(addr_t) irb->scsw.cpa) - 2) { 497 act = ((struct ccw1 *)(addr_t) irb->scsw.cpa) - 2; 498 len += sprintf(page + len, KERN_ERR PRINTK_HEADER "......\n"); 499 } 500 end = min((struct ccw1 *)(addr_t) irb->scsw.cpa + 2, last); 501 while (act <= end) { 502 len += sprintf(page + len, KERN_ERR PRINTK_HEADER 503 " CCW %p: %08X %08X DAT:", 504 act, ((int *) act)[0], ((int *) act)[1]); 505 for (count = 0; count < 32 && count < act->count; 506 count += sizeof(int)) 507 len += sprintf(page + len, " %08X", 508 ((int *) (addr_t) act->cda) 509 [(count>>2)]); 510 len += sprintf(page + len, "\n"); 511 act++; 512 } 513 514 /* print last CCWs */ 515 if (act < last - 2) { 516 act = last - 2; 517 len += sprintf(page + len, KERN_ERR PRINTK_HEADER "......\n"); 518 } 519 while (act <= last) { 520 len += sprintf(page + len, KERN_ERR PRINTK_HEADER 521 " CCW %p: %08X %08X DAT:", 522 act, ((int *) act)[0], ((int *) act)[1]); 523 for (count = 0; count < 32 && count < act->count; 524 count += sizeof(int)) 525 len += sprintf(page + len, " %08X", 526 ((int *) (addr_t) act->cda) 527 [(count>>2)]); 528 len += sprintf(page + len, "\n"); 529 act++; 530 } 531 if (len > 0) 532 MESSAGE_LOG(KERN_ERR, "%s", 533 page + sizeof(KERN_ERR PRINTK_HEADER)); 534 free_page((unsigned long) page); 535 } 536 537 /* 538 * max_blocks is dependent on the amount of storage that is available 539 * in the static io buffer for each device. Currently each device has 540 * 8192 bytes (=2 pages). For 64 bit one dasd_mchunkt_t structure has 541 * 24 bytes, the struct dasd_ccw_req has 136 bytes and each block can use 542 * up to 16 bytes (8 for the ccw and 8 for the idal pointer). In 543 * addition we have one define extent ccw + 16 bytes of data and a 544 * locate record ccw for each block (stupid devices!) + 16 bytes of data. 545 * That makes: 546 * (8192 - 24 - 136 - 8 - 16) / 40 = 200.2 blocks at maximum. 547 * We want to fit two into the available memory so that we can immediately 548 * start the next request if one finishes off. That makes 100.1 blocks 549 * for one request. Give a little safety and the result is 96. 550 */ 551 static struct dasd_discipline dasd_fba_discipline = { 552 .owner = THIS_MODULE, 553 .name = "FBA ", 554 .ebcname = "FBA ", 555 .max_blocks = 96, 556 .check_device = dasd_fba_check_characteristics, 557 .do_analysis = dasd_fba_do_analysis, 558 .fill_geometry = dasd_fba_fill_geometry, 559 .start_IO = dasd_start_IO, 560 .term_IO = dasd_term_IO, 561 .examine_error = dasd_fba_examine_error, 562 .erp_action = dasd_fba_erp_action, 563 .erp_postaction = dasd_fba_erp_postaction, 564 .build_cp = dasd_fba_build_cp, 565 .free_cp = dasd_fba_free_cp, 566 .dump_sense = dasd_fba_dump_sense, 567 .fill_info = dasd_fba_fill_info, 568 }; 569 570 static int __init 571 dasd_fba_init(void) 572 { 573 int ret; 574 575 ASCEBC(dasd_fba_discipline.ebcname, 4); 576 577 ret = ccw_driver_register(&dasd_fba_driver); 578 if (ret) 579 return ret; 580 581 dasd_generic_auto_online(&dasd_fba_driver); 582 return 0; 583 } 584 585 static void __exit 586 dasd_fba_cleanup(void) 587 { 588 ccw_driver_unregister(&dasd_fba_driver); 589 } 590 591 module_init(dasd_fba_init); 592 module_exit(dasd_fba_cleanup); 593 594 /* 595 * Overrides for Emacs so that we follow Linus's tabbing style. 596 * Emacs will notice this stuff at the end of the file and automatically 597 * adjust the settings for this buffer only. This must remain at the end 598 * of the file. 599 * --------------------------------------------------------------------------- 600 * Local variables: 601 * c-indent-level: 4 602 * c-brace-imaginary-offset: 0 603 * c-brace-offset: -4 604 * c-argdecl-indent: 4 605 * c-label-offset: -4 606 * c-continued-statement-offset: 4 607 * c-continued-brace-offset: 0 608 * indent-tabs-mode: 1 609 * tab-width: 8 610 * End: 611 */ 612