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