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.40 $ 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_ARCH_S390X) 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 cqr->device = device; 356 cqr->expires = 5 * 60 * HZ; /* 5 minutes */ 357 cqr->retries = 32; 358 cqr->buildclk = get_clock(); 359 cqr->status = DASD_CQR_FILLED; 360 return cqr; 361 } 362 363 static int 364 dasd_fba_free_cp(struct dasd_ccw_req *cqr, struct request *req) 365 { 366 struct dasd_fba_private *private; 367 struct ccw1 *ccw; 368 struct bio *bio; 369 struct bio_vec *bv; 370 char *dst, *cda; 371 unsigned int blksize, off; 372 int i, status; 373 374 if (!dasd_page_cache) 375 goto out; 376 private = (struct dasd_fba_private *) cqr->device->private; 377 blksize = cqr->device->bp_block; 378 ccw = cqr->cpaddr; 379 /* Skip over define extent & locate record. */ 380 ccw++; 381 if (private->rdc_data.mode.bits.data_chain != 0) 382 ccw++; 383 rq_for_each_bio(bio, req) bio_for_each_segment(bv, bio, i) { 384 dst = page_address(bv->bv_page) + bv->bv_offset; 385 for (off = 0; off < bv->bv_len; off += blksize) { 386 /* Skip locate record. */ 387 if (private->rdc_data.mode.bits.data_chain == 0) 388 ccw++; 389 if (dst) { 390 if (ccw->flags & CCW_FLAG_IDA) 391 cda = *((char **)((addr_t) ccw->cda)); 392 else 393 cda = (char *)((addr_t) ccw->cda); 394 if (dst != cda) { 395 if (rq_data_dir(req) == READ) 396 memcpy(dst, cda, bv->bv_len); 397 kmem_cache_free(dasd_page_cache, 398 (void *)((addr_t)cda & PAGE_MASK)); 399 } 400 dst = NULL; 401 } 402 ccw++; 403 } 404 } 405 out: 406 status = cqr->status == DASD_CQR_DONE; 407 dasd_sfree_request(cqr, cqr->device); 408 return status; 409 } 410 411 static int 412 dasd_fba_fill_info(struct dasd_device * device, 413 struct dasd_information2_t * info) 414 { 415 info->label_block = 1; 416 info->FBA_layout = 1; 417 info->format = DASD_FORMAT_LDL; 418 info->characteristics_size = sizeof(struct dasd_fba_characteristics); 419 memcpy(info->characteristics, 420 &((struct dasd_fba_private *) device->private)->rdc_data, 421 sizeof (struct dasd_fba_characteristics)); 422 info->confdata_size = 0; 423 return 0; 424 } 425 426 static void 427 dasd_fba_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req, 428 struct irb *irb) 429 { 430 char *page; 431 struct ccw1 *act, *end, *last; 432 int len, sl, sct, count; 433 434 page = (char *) get_zeroed_page(GFP_ATOMIC); 435 if (page == NULL) { 436 DEV_MESSAGE(KERN_ERR, device, " %s", 437 "No memory to dump sense data"); 438 return; 439 } 440 len = sprintf(page, KERN_ERR PRINTK_HEADER 441 " I/O status report for device %s:\n", 442 device->cdev->dev.bus_id); 443 len += sprintf(page + len, KERN_ERR PRINTK_HEADER 444 " in req: %p CS: 0x%02X DS: 0x%02X\n", req, 445 irb->scsw.cstat, irb->scsw.dstat); 446 len += sprintf(page + len, KERN_ERR PRINTK_HEADER 447 " device %s: Failing CCW: %p\n", 448 device->cdev->dev.bus_id, 449 (void *) (addr_t) irb->scsw.cpa); 450 if (irb->esw.esw0.erw.cons) { 451 for (sl = 0; sl < 4; sl++) { 452 len += sprintf(page + len, KERN_ERR PRINTK_HEADER 453 " Sense(hex) %2d-%2d:", 454 (8 * sl), ((8 * sl) + 7)); 455 456 for (sct = 0; sct < 8; sct++) { 457 len += sprintf(page + len, " %02x", 458 irb->ecw[8 * sl + sct]); 459 } 460 len += sprintf(page + len, "\n"); 461 } 462 } else { 463 len += sprintf(page + len, KERN_ERR PRINTK_HEADER 464 " SORRY - NO VALID SENSE AVAILABLE\n"); 465 } 466 MESSAGE_LOG(KERN_ERR, "%s", 467 page + sizeof(KERN_ERR PRINTK_HEADER)); 468 469 /* dump the Channel Program */ 470 /* print first CCWs (maximum 8) */ 471 act = req->cpaddr; 472 for (last = act; last->flags & (CCW_FLAG_CC | CCW_FLAG_DC); last++); 473 end = min(act + 8, last); 474 len = sprintf(page, KERN_ERR PRINTK_HEADER 475 " Related CP in req: %p\n", req); 476 while (act <= end) { 477 len += sprintf(page + len, KERN_ERR PRINTK_HEADER 478 " CCW %p: %08X %08X DAT:", 479 act, ((int *) act)[0], ((int *) act)[1]); 480 for (count = 0; count < 32 && count < act->count; 481 count += sizeof(int)) 482 len += sprintf(page + len, " %08X", 483 ((int *) (addr_t) act->cda) 484 [(count>>2)]); 485 len += sprintf(page + len, "\n"); 486 act++; 487 } 488 MESSAGE_LOG(KERN_ERR, "%s", 489 page + sizeof(KERN_ERR PRINTK_HEADER)); 490 491 492 /* print failing CCW area */ 493 len = 0; 494 if (act < ((struct ccw1 *)(addr_t) irb->scsw.cpa) - 2) { 495 act = ((struct ccw1 *)(addr_t) irb->scsw.cpa) - 2; 496 len += sprintf(page + len, KERN_ERR PRINTK_HEADER "......\n"); 497 } 498 end = min((struct ccw1 *)(addr_t) irb->scsw.cpa + 2, last); 499 while (act <= end) { 500 len += sprintf(page + len, KERN_ERR PRINTK_HEADER 501 " CCW %p: %08X %08X DAT:", 502 act, ((int *) act)[0], ((int *) act)[1]); 503 for (count = 0; count < 32 && count < act->count; 504 count += sizeof(int)) 505 len += sprintf(page + len, " %08X", 506 ((int *) (addr_t) act->cda) 507 [(count>>2)]); 508 len += sprintf(page + len, "\n"); 509 act++; 510 } 511 512 /* print last CCWs */ 513 if (act < last - 2) { 514 act = last - 2; 515 len += sprintf(page + len, KERN_ERR PRINTK_HEADER "......\n"); 516 } 517 while (act <= last) { 518 len += sprintf(page + len, KERN_ERR PRINTK_HEADER 519 " CCW %p: %08X %08X DAT:", 520 act, ((int *) act)[0], ((int *) act)[1]); 521 for (count = 0; count < 32 && count < act->count; 522 count += sizeof(int)) 523 len += sprintf(page + len, " %08X", 524 ((int *) (addr_t) act->cda) 525 [(count>>2)]); 526 len += sprintf(page + len, "\n"); 527 act++; 528 } 529 if (len > 0) 530 MESSAGE_LOG(KERN_ERR, "%s", 531 page + sizeof(KERN_ERR PRINTK_HEADER)); 532 free_page((unsigned long) page); 533 } 534 535 /* 536 * max_blocks is dependent on the amount of storage that is available 537 * in the static io buffer for each device. Currently each device has 538 * 8192 bytes (=2 pages). For 64 bit one dasd_mchunkt_t structure has 539 * 24 bytes, the struct dasd_ccw_req has 136 bytes and each block can use 540 * up to 16 bytes (8 for the ccw and 8 for the idal pointer). In 541 * addition we have one define extent ccw + 16 bytes of data and a 542 * locate record ccw for each block (stupid devices!) + 16 bytes of data. 543 * That makes: 544 * (8192 - 24 - 136 - 8 - 16) / 40 = 200.2 blocks at maximum. 545 * We want to fit two into the available memory so that we can immediately 546 * start the next request if one finishes off. That makes 100.1 blocks 547 * for one request. Give a little safety and the result is 96. 548 */ 549 static struct dasd_discipline dasd_fba_discipline = { 550 .owner = THIS_MODULE, 551 .name = "FBA ", 552 .ebcname = "FBA ", 553 .max_blocks = 96, 554 .check_device = dasd_fba_check_characteristics, 555 .do_analysis = dasd_fba_do_analysis, 556 .fill_geometry = dasd_fba_fill_geometry, 557 .start_IO = dasd_start_IO, 558 .term_IO = dasd_term_IO, 559 .examine_error = dasd_fba_examine_error, 560 .erp_action = dasd_fba_erp_action, 561 .erp_postaction = dasd_fba_erp_postaction, 562 .build_cp = dasd_fba_build_cp, 563 .free_cp = dasd_fba_free_cp, 564 .dump_sense = dasd_fba_dump_sense, 565 .fill_info = dasd_fba_fill_info, 566 }; 567 568 static int __init 569 dasd_fba_init(void) 570 { 571 int ret; 572 573 ASCEBC(dasd_fba_discipline.ebcname, 4); 574 575 ret = ccw_driver_register(&dasd_fba_driver); 576 if (ret) 577 return ret; 578 579 dasd_generic_auto_online(&dasd_fba_driver); 580 return 0; 581 } 582 583 static void __exit 584 dasd_fba_cleanup(void) 585 { 586 ccw_driver_unregister(&dasd_fba_driver); 587 } 588 589 module_init(dasd_fba_init); 590 module_exit(dasd_fba_cleanup); 591 592 /* 593 * Overrides for Emacs so that we follow Linus's tabbing style. 594 * Emacs will notice this stuff at the end of the file and automatically 595 * adjust the settings for this buffer only. This must remain at the end 596 * of the file. 597 * --------------------------------------------------------------------------- 598 * Local variables: 599 * c-indent-level: 4 600 * c-brace-imaginary-offset: 0 601 * c-brace-offset: -4 602 * c-argdecl-indent: 4 603 * c-label-offset: -4 604 * c-continued-statement-offset: 4 605 * c-continued-brace-offset: 0 606 * indent-tabs-mode: 1 607 * tab-width: 8 608 * End: 609 */ 610