cciss: change the way we notify scsi midlayer of tape drives

This patch changes way we notify the scsi layer that something has changed
on the SCSI tape side of the driver. The user can now just tell the driver
to rescan a particular controller rather than having to know the SCSI nexus
to echo into the SCSI mid-layer.

Signed-off-by: Stephen M. Cameron <scameron@beardog.cca.cpqcorp.net>
Signed-off-by: Mike Miller <mike.miller@hp.com>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>

authored by Mike Miller and committed by Jens Axboe f4a93bcd eece695f

+124 -54
+6 -15
Documentation/cciss.txt
··· 112 112 113 113 Hot plugging of SCSI tape drives is supported, with some caveats. 114 114 The cciss driver must be informed that changes to the SCSI bus 115 - have been made, in addition to and prior to informing the SCSI 116 - mid layer. This may be done via the /proc filesystem. For example: 115 + have been made. This may be done via the /proc filesystem. 116 + For example: 117 117 118 118 echo "rescan" > /proc/scsi/cciss0/1 119 119 120 - This causes the adapter to query the adapter about changes to the 121 - physical SCSI buses and/or fibre channel arbitrated loop and the 120 + This causes the driver to query the adapter about changes to the 121 + physical SCSI buses and/or fibre channel arbitrated loop and the 122 122 driver to make note of any new or removed sequential access devices 123 123 or medium changers. The driver will output messages indicating what 124 124 devices have been added or removed and the controller, bus, target and 125 - lun used to address the device. Once this is done, the SCSI mid layer 126 - can be informed of changes to the virtual SCSI bus which the driver 127 - presents to it in the usual way. For example: 128 - 129 - echo scsi add-single-device 3 2 1 0 > /proc/scsi/scsi 130 - 131 - to add a device on controller 3, bus 2, target 1, lun 0. Note that 132 - the driver makes an effort to preserve the devices positions 133 - in the virtual SCSI bus, so if you are only moving tape drives 134 - around on the same adapter and not adding or removing tape drives 135 - from the adapter, informing the SCSI mid layer may not be necessary. 125 + lun used to address the device. It then notifies the SCSI mid layer 126 + of these changes. 136 127 137 128 Note that the naming convention of the /proc filesystem entries 138 129 contains a number in addition to the driver name. (E.g. "cciss0"
+118 -39
drivers/block/cciss_scsi.c
··· 358 358 } 359 359 return (!found); 360 360 } 361 + struct scsi2map { 362 + char scsi3addr[8]; 363 + int bus, target, lun; 364 + }; 361 365 362 366 static int 363 367 cciss_scsi_add_entry(int ctlr, int hostno, 364 - unsigned char *scsi3addr, int devtype) 368 + unsigned char *scsi3addr, int devtype, 369 + struct scsi2map *added, int *nadded) 365 370 { 366 371 /* assumes hba[ctlr]->scsi_ctlr->lock is held */ 367 372 int n = ccissscsi[ctlr].ndevices; ··· 380 375 sd = &ccissscsi[ctlr].dev[n]; 381 376 if (find_bus_target_lun(ctlr, &sd->bus, &sd->target, &sd->lun) != 0) 382 377 return -1; 378 + 379 + added[*nadded].bus = sd->bus; 380 + added[*nadded].target = sd->target; 381 + added[*nadded].lun = sd->lun; 382 + (*nadded)++; 383 + 383 384 memcpy(&sd->scsi3addr[0], scsi3addr, 8); 384 385 sd->devtype = devtype; 385 386 ccissscsi[ctlr].ndevices++; ··· 401 390 } 402 391 403 392 static void 404 - cciss_scsi_remove_entry(int ctlr, int hostno, int entry) 393 + cciss_scsi_remove_entry(int ctlr, int hostno, int entry, 394 + struct scsi2map *removed, int *nremoved) 405 395 { 406 396 /* assumes hba[ctlr]->scsi_ctlr->lock is held */ 407 397 int i; ··· 410 398 411 399 if (entry < 0 || entry >= CCISS_MAX_SCSI_DEVS_PER_HBA) return; 412 400 sd = ccissscsi[ctlr].dev[entry]; 401 + removed[*nremoved].bus = sd.bus; 402 + removed[*nremoved].target = sd.target; 403 + removed[*nremoved].lun = sd.lun; 404 + (*nremoved)++; 413 405 for (i=entry;i<ccissscsi[ctlr].ndevices-1;i++) 414 406 ccissscsi[ctlr].dev[i] = ccissscsi[ctlr].dev[i+1]; 415 407 ccissscsi[ctlr].ndevices--; ··· 433 417 (a)[1] == (b)[1] && \ 434 418 (a)[0] == (b)[0]) 435 419 420 + static void fixup_botched_add(int ctlr, char *scsi3addr) 421 + { 422 + /* called when scsi_add_device fails in order to re-adjust */ 423 + /* ccissscsi[] to match the mid layer's view. */ 424 + unsigned long flags; 425 + int i, j; 426 + CPQ_TAPE_LOCK(ctlr, flags); 427 + for (i = 0; i < ccissscsi[ctlr].ndevices; i++) { 428 + if (memcmp(scsi3addr, 429 + ccissscsi[ctlr].dev[i].scsi3addr, 8) == 0) { 430 + for (j = i; j < ccissscsi[ctlr].ndevices-1; j++) 431 + ccissscsi[ctlr].dev[j] = 432 + ccissscsi[ctlr].dev[j+1]; 433 + ccissscsi[ctlr].ndevices--; 434 + break; 435 + } 436 + } 437 + CPQ_TAPE_UNLOCK(ctlr, flags); 438 + } 439 + 436 440 static int 437 441 adjust_cciss_scsi_table(int ctlr, int hostno, 438 442 struct cciss_scsi_dev_t sd[], int nsds) ··· 465 429 int i,j, found, changes=0; 466 430 struct cciss_scsi_dev_t *csd; 467 431 unsigned long flags; 432 + struct scsi2map *added, *removed; 433 + int nadded, nremoved; 434 + struct Scsi_Host *sh = NULL; 435 + 436 + added = kzalloc(sizeof(*added) * CCISS_MAX_SCSI_DEVS_PER_HBA, 437 + GFP_KERNEL); 438 + removed = kzalloc(sizeof(*removed) * CCISS_MAX_SCSI_DEVS_PER_HBA, 439 + GFP_KERNEL); 440 + 441 + if (!added || !removed) { 442 + printk(KERN_WARNING "cciss%d: Out of memory in " 443 + "adjust_cciss_scsi_table\n", ctlr); 444 + goto free_and_out; 445 + } 468 446 469 447 CPQ_TAPE_LOCK(ctlr, flags); 448 + 449 + if (hostno != -1) /* if it's not the first time... */ 450 + sh = ((struct cciss_scsi_adapter_data_t *) 451 + hba[ctlr]->scsi_ctlr)->scsi_host; 470 452 471 453 /* find any devices in ccissscsi[] that are not in 472 454 sd[] and remove them from ccissscsi[] */ 473 455 474 456 i = 0; 457 + nremoved = 0; 458 + nadded = 0; 475 459 while(i<ccissscsi[ctlr].ndevices) { 476 460 csd = &ccissscsi[ctlr].dev[i]; 477 461 found=0; ··· 511 455 /* printk("cciss%d: %s device c%db%dt%dl%d removed.\n", 512 456 ctlr, scsi_device_type(csd->devtype), hostno, 513 457 csd->bus, csd->target, csd->lun); */ 514 - cciss_scsi_remove_entry(ctlr, hostno, i); 515 - /* note, i not incremented */ 458 + cciss_scsi_remove_entry(ctlr, hostno, i, 459 + removed, &nremoved); 460 + /* remove ^^^, hence i not incremented */ 516 461 } 517 462 else if (found == 1) { /* device is different kind */ 518 463 changes++; ··· 521 464 "(device type now %s).\n", 522 465 ctlr, hostno, csd->bus, csd->target, csd->lun, 523 466 scsi_device_type(csd->devtype)); 467 + cciss_scsi_remove_entry(ctlr, hostno, i, 468 + removed, &nremoved); 469 + /* remove ^^^, hence i not incremented */ 470 + if (cciss_scsi_add_entry(ctlr, hostno, 471 + &sd[j].scsi3addr[0], sd[j].devtype, 472 + added, &nadded) != 0) 473 + /* we just removed one, so add can't fail. */ 474 + BUG(); 524 475 csd->devtype = sd[j].devtype; 525 - i++; /* so just move along. */ 526 476 } else /* device is same as it ever was, */ 527 477 i++; /* so just move along. */ 528 478 } ··· 553 489 if (!found) { 554 490 changes++; 555 491 if (cciss_scsi_add_entry(ctlr, hostno, 556 - &sd[i].scsi3addr[0], sd[i].devtype) != 0) 492 + 493 + &sd[i].scsi3addr[0], sd[i].devtype, 494 + added, &nadded) != 0) 557 495 break; 558 496 } else if (found == 1) { 559 497 /* should never happen... */ ··· 567 501 } 568 502 CPQ_TAPE_UNLOCK(ctlr, flags); 569 503 570 - if (!changes) 571 - printk("cciss%d: No device changes detected.\n", ctlr); 504 + /* Don't notify scsi mid layer of any changes the first time through */ 505 + /* (or if there are no changes) scsi_scan_host will do it later the */ 506 + /* first time through. */ 507 + if (hostno == -1 || !changes) 508 + goto free_and_out; 572 509 510 + /* Notify scsi mid layer of any removed devices */ 511 + for (i = 0; i < nremoved; i++) { 512 + struct scsi_device *sdev = 513 + scsi_device_lookup(sh, removed[i].bus, 514 + removed[i].target, removed[i].lun); 515 + if (sdev != NULL) { 516 + scsi_remove_device(sdev); 517 + scsi_device_put(sdev); 518 + } else { 519 + /* We don't expect to get here. */ 520 + /* future cmds to this device will get selection */ 521 + /* timeout as if the device was gone. */ 522 + printk(KERN_WARNING "cciss%d: didn't find " 523 + "c%db%dt%dl%d\n for removal.", 524 + ctlr, hostno, removed[i].bus, 525 + removed[i].target, removed[i].lun); 526 + } 527 + } 528 + 529 + /* Notify scsi mid layer of any added devices */ 530 + for (i = 0; i < nadded; i++) { 531 + int rc; 532 + rc = scsi_add_device(sh, added[i].bus, 533 + added[i].target, added[i].lun); 534 + if (rc == 0) 535 + continue; 536 + printk(KERN_WARNING "cciss%d: scsi_add_device " 537 + "c%db%dt%dl%d failed, device not added.\n", 538 + ctlr, hostno, 539 + added[i].bus, added[i].target, added[i].lun); 540 + /* now we have to remove it from ccissscsi, */ 541 + /* since it didn't get added to scsi mid layer */ 542 + fixup_botched_add(ctlr, added[i].scsi3addr); 543 + } 544 + 545 + free_and_out: 546 + kfree(added); 547 + kfree(removed); 573 548 return 0; 574 549 } 575 550 ··· 1462 1355 } 1463 1356 1464 1357 static int 1465 - cciss_register_scsi(int ctlr) 1466 - { 1467 - unsigned long flags; 1468 - 1469 - CPQ_TAPE_LOCK(ctlr, flags); 1470 - 1471 - /* Since this is really a block driver, the SCSI core may not be 1472 - initialized at init time, in which case, calling scsi_register_host 1473 - would hang. Instead, we do it later, via /proc filesystem 1474 - and rc scripts, when we know SCSI core is good to go. */ 1475 - 1476 - /* Only register if SCSI devices are detected. */ 1477 - if (ccissscsi[ctlr].ndevices != 0) { 1478 - ((struct cciss_scsi_adapter_data_t *) 1479 - hba[ctlr]->scsi_ctlr)->registered = 1; 1480 - CPQ_TAPE_UNLOCK(ctlr, flags); 1481 - return cciss_scsi_detect(ctlr); 1482 - } 1483 - CPQ_TAPE_UNLOCK(ctlr, flags); 1484 - printk(KERN_INFO 1485 - "cciss%d: No appropriate SCSI device detected, " 1486 - "SCSI subsystem not engaged.\n", ctlr); 1487 - return 0; 1488 - } 1489 - 1490 - static int 1491 1358 cciss_engage_scsi(int ctlr) 1492 1359 { 1493 1360 struct cciss_scsi_adapter_data_t *sa; ··· 1472 1391 sa = (struct cciss_scsi_adapter_data_t *) hba[ctlr]->scsi_ctlr; 1473 1392 stk = &sa->cmd_stack; 1474 1393 1475 - if (((struct cciss_scsi_adapter_data_t *) 1476 - hba[ctlr]->scsi_ctlr)->registered) { 1394 + if (sa->registered) { 1477 1395 printk("cciss%d: SCSI subsystem already engaged.\n", ctlr); 1478 1396 spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); 1479 1397 return ENXIO; 1480 1398 } 1399 + sa->registered = 1; 1481 1400 spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); 1482 1401 cciss_update_non_disk_devices(ctlr, -1); 1483 - cciss_register_scsi(ctlr); 1402 + cciss_scsi_detect(ctlr); 1484 1403 return 0; 1485 1404 } 1486 1405 ··· 1574 1493 /* If no tape support, then these become defined out of existence */ 1575 1494 1576 1495 #define cciss_scsi_setup(cntl_num) 1577 - #define cciss_unregister_scsi(ctlr) 1578 - #define cciss_register_scsi(ctlr) 1579 1496 1580 1497 #endif /* CONFIG_CISS_SCSI_TAPE */