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