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 113 Hot plugging of SCSI tape drives is supported, with some caveats. 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: 117 118 echo "rescan" > /proc/scsi/cciss0/1 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 122 driver to make note of any new or removed sequential access devices 123 or medium changers. The driver will output messages indicating what 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. 136 137 Note that the naming convention of the /proc filesystem entries 138 contains a number in addition to the driver name. (E.g. "cciss0"
··· 112 113 Hot plugging of SCSI tape drives is supported, with some caveats. 114 The cciss driver must be informed that changes to the SCSI bus 115 + have been made. This may be done via the /proc filesystem. 116 + For example: 117 118 echo "rescan" > /proc/scsi/cciss0/1 119 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 driver to make note of any new or removed sequential access devices 123 or medium changers. The driver will output messages indicating what 124 devices have been added or removed and the controller, bus, target and 125 + lun used to address the device. It then notifies the SCSI mid layer 126 + of these changes. 127 128 Note that the naming convention of the /proc filesystem entries 129 contains a number in addition to the driver name. (E.g. "cciss0"
+118 -39
drivers/block/cciss_scsi.c
··· 358 } 359 return (!found); 360 } 361 362 static int 363 cciss_scsi_add_entry(int ctlr, int hostno, 364 - unsigned char *scsi3addr, int devtype) 365 { 366 /* assumes hba[ctlr]->scsi_ctlr->lock is held */ 367 int n = ccissscsi[ctlr].ndevices; ··· 380 sd = &ccissscsi[ctlr].dev[n]; 381 if (find_bus_target_lun(ctlr, &sd->bus, &sd->target, &sd->lun) != 0) 382 return -1; 383 memcpy(&sd->scsi3addr[0], scsi3addr, 8); 384 sd->devtype = devtype; 385 ccissscsi[ctlr].ndevices++; ··· 401 } 402 403 static void 404 - cciss_scsi_remove_entry(int ctlr, int hostno, int entry) 405 { 406 /* assumes hba[ctlr]->scsi_ctlr->lock is held */ 407 int i; ··· 410 411 if (entry < 0 || entry >= CCISS_MAX_SCSI_DEVS_PER_HBA) return; 412 sd = ccissscsi[ctlr].dev[entry]; 413 for (i=entry;i<ccissscsi[ctlr].ndevices-1;i++) 414 ccissscsi[ctlr].dev[i] = ccissscsi[ctlr].dev[i+1]; 415 ccissscsi[ctlr].ndevices--; ··· 433 (a)[1] == (b)[1] && \ 434 (a)[0] == (b)[0]) 435 436 static int 437 adjust_cciss_scsi_table(int ctlr, int hostno, 438 struct cciss_scsi_dev_t sd[], int nsds) ··· 465 int i,j, found, changes=0; 466 struct cciss_scsi_dev_t *csd; 467 unsigned long flags; 468 469 CPQ_TAPE_LOCK(ctlr, flags); 470 471 /* find any devices in ccissscsi[] that are not in 472 sd[] and remove them from ccissscsi[] */ 473 474 i = 0; 475 while(i<ccissscsi[ctlr].ndevices) { 476 csd = &ccissscsi[ctlr].dev[i]; 477 found=0; ··· 511 /* printk("cciss%d: %s device c%db%dt%dl%d removed.\n", 512 ctlr, scsi_device_type(csd->devtype), hostno, 513 csd->bus, csd->target, csd->lun); */ 514 - cciss_scsi_remove_entry(ctlr, hostno, i); 515 - /* note, i not incremented */ 516 } 517 else if (found == 1) { /* device is different kind */ 518 changes++; ··· 521 "(device type now %s).\n", 522 ctlr, hostno, csd->bus, csd->target, csd->lun, 523 scsi_device_type(csd->devtype)); 524 csd->devtype = sd[j].devtype; 525 - i++; /* so just move along. */ 526 } else /* device is same as it ever was, */ 527 i++; /* so just move along. */ 528 } ··· 553 if (!found) { 554 changes++; 555 if (cciss_scsi_add_entry(ctlr, hostno, 556 - &sd[i].scsi3addr[0], sd[i].devtype) != 0) 557 break; 558 } else if (found == 1) { 559 /* should never happen... */ ··· 567 } 568 CPQ_TAPE_UNLOCK(ctlr, flags); 569 570 - if (!changes) 571 - printk("cciss%d: No device changes detected.\n", ctlr); 572 573 return 0; 574 } 575 ··· 1462 } 1463 1464 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 cciss_engage_scsi(int ctlr) 1492 { 1493 struct cciss_scsi_adapter_data_t *sa; ··· 1472 sa = (struct cciss_scsi_adapter_data_t *) hba[ctlr]->scsi_ctlr; 1473 stk = &sa->cmd_stack; 1474 1475 - if (((struct cciss_scsi_adapter_data_t *) 1476 - hba[ctlr]->scsi_ctlr)->registered) { 1477 printk("cciss%d: SCSI subsystem already engaged.\n", ctlr); 1478 spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); 1479 return ENXIO; 1480 } 1481 spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); 1482 cciss_update_non_disk_devices(ctlr, -1); 1483 - cciss_register_scsi(ctlr); 1484 return 0; 1485 } 1486 ··· 1574 /* If no tape support, then these become defined out of existence */ 1575 1576 #define cciss_scsi_setup(cntl_num) 1577 - #define cciss_unregister_scsi(ctlr) 1578 - #define cciss_register_scsi(ctlr) 1579 1580 #endif /* CONFIG_CISS_SCSI_TAPE */
··· 358 } 359 return (!found); 360 } 361 + struct scsi2map { 362 + char scsi3addr[8]; 363 + int bus, target, lun; 364 + }; 365 366 static int 367 cciss_scsi_add_entry(int ctlr, int hostno, 368 + unsigned char *scsi3addr, int devtype, 369 + struct scsi2map *added, int *nadded) 370 { 371 /* assumes hba[ctlr]->scsi_ctlr->lock is held */ 372 int n = ccissscsi[ctlr].ndevices; ··· 375 sd = &ccissscsi[ctlr].dev[n]; 376 if (find_bus_target_lun(ctlr, &sd->bus, &sd->target, &sd->lun) != 0) 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 + 384 memcpy(&sd->scsi3addr[0], scsi3addr, 8); 385 sd->devtype = devtype; 386 ccissscsi[ctlr].ndevices++; ··· 390 } 391 392 static void 393 + cciss_scsi_remove_entry(int ctlr, int hostno, int entry, 394 + struct scsi2map *removed, int *nremoved) 395 { 396 /* assumes hba[ctlr]->scsi_ctlr->lock is held */ 397 int i; ··· 398 399 if (entry < 0 || entry >= CCISS_MAX_SCSI_DEVS_PER_HBA) return; 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)++; 405 for (i=entry;i<ccissscsi[ctlr].ndevices-1;i++) 406 ccissscsi[ctlr].dev[i] = ccissscsi[ctlr].dev[i+1]; 407 ccissscsi[ctlr].ndevices--; ··· 417 (a)[1] == (b)[1] && \ 418 (a)[0] == (b)[0]) 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 + 440 static int 441 adjust_cciss_scsi_table(int ctlr, int hostno, 442 struct cciss_scsi_dev_t sd[], int nsds) ··· 429 int i,j, found, changes=0; 430 struct cciss_scsi_dev_t *csd; 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 + } 446 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; 452 453 /* find any devices in ccissscsi[] that are not in 454 sd[] and remove them from ccissscsi[] */ 455 456 i = 0; 457 + nremoved = 0; 458 + nadded = 0; 459 while(i<ccissscsi[ctlr].ndevices) { 460 csd = &ccissscsi[ctlr].dev[i]; 461 found=0; ··· 455 /* printk("cciss%d: %s device c%db%dt%dl%d removed.\n", 456 ctlr, scsi_device_type(csd->devtype), hostno, 457 csd->bus, csd->target, csd->lun); */ 458 + cciss_scsi_remove_entry(ctlr, hostno, i, 459 + removed, &nremoved); 460 + /* remove ^^^, hence i not incremented */ 461 } 462 else if (found == 1) { /* device is different kind */ 463 changes++; ··· 464 "(device type now %s).\n", 465 ctlr, hostno, csd->bus, csd->target, csd->lun, 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(); 475 csd->devtype = sd[j].devtype; 476 } else /* device is same as it ever was, */ 477 i++; /* so just move along. */ 478 } ··· 489 if (!found) { 490 changes++; 491 if (cciss_scsi_add_entry(ctlr, hostno, 492 + 493 + &sd[i].scsi3addr[0], sd[i].devtype, 494 + added, &nadded) != 0) 495 break; 496 } else if (found == 1) { 497 /* should never happen... */ ··· 501 } 502 CPQ_TAPE_UNLOCK(ctlr, flags); 503 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; 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); 548 return 0; 549 } 550 ··· 1355 } 1356 1357 static int 1358 cciss_engage_scsi(int ctlr) 1359 { 1360 struct cciss_scsi_adapter_data_t *sa; ··· 1391 sa = (struct cciss_scsi_adapter_data_t *) hba[ctlr]->scsi_ctlr; 1392 stk = &sa->cmd_stack; 1393 1394 + if (sa->registered) { 1395 printk("cciss%d: SCSI subsystem already engaged.\n", ctlr); 1396 spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); 1397 return ENXIO; 1398 } 1399 + sa->registered = 1; 1400 spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); 1401 cciss_update_non_disk_devices(ctlr, -1); 1402 + cciss_scsi_detect(ctlr); 1403 return 0; 1404 } 1405 ··· 1493 /* If no tape support, then these become defined out of existence */ 1494 1495 #define cciss_scsi_setup(cntl_num) 1496 1497 #endif /* CONFIG_CISS_SCSI_TAPE */