aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/cciss.txt21
-rw-r--r--drivers/block/cciss_scsi.c157
2 files changed, 124 insertions, 54 deletions
diff --git a/Documentation/cciss.txt b/Documentation/cciss.txt
index 63e59b8847c5..8244c6442faa 100644
--- a/Documentation/cciss.txt
+++ b/Documentation/cciss.txt
@@ -112,27 +112,18 @@ Hot plug support for SCSI tape drives
112 112
113Hot plugging of SCSI tape drives is supported, with some caveats. 113Hot plugging of SCSI tape drives is supported, with some caveats.
114The cciss driver must be informed that changes to the SCSI bus 114The cciss driver must be informed that changes to the SCSI bus
115have been made, in addition to and prior to informing the SCSI 115have been made. This may be done via the /proc filesystem.
116mid layer. This may be done via the /proc filesystem. For example: 116For example:
117 117
118 echo "rescan" > /proc/scsi/cciss0/1 118 echo "rescan" > /proc/scsi/cciss0/1
119 119
120This causes the adapter to query the adapter about changes to the 120This causes the driver to query the adapter about changes to the
121physical SCSI buses and/or fibre channel arbitrated loop and the 121physical SCSI buses and/or fibre channel arbitrated loop and the
122driver to make note of any new or removed sequential access devices 122driver to make note of any new or removed sequential access devices
123or medium changers. The driver will output messages indicating what 123or medium changers. The driver will output messages indicating what
124devices have been added or removed and the controller, bus, target and 124devices have been added or removed and the controller, bus, target and
125lun used to address the device. Once this is done, the SCSI mid layer 125lun used to address the device. It then notifies the SCSI mid layer
126can be informed of changes to the virtual SCSI bus which the driver 126of these changes.
127presents to it in the usual way. For example:
128
129 echo scsi add-single-device 3 2 1 0 > /proc/scsi/scsi
130
131to add a device on controller 3, bus 2, target 1, lun 0. Note that
132the driver makes an effort to preserve the devices positions
133in the virtual SCSI bus, so if you are only moving tape drives
134around on the same adapter and not adding or removing tape drives
135from the adapter, informing the SCSI mid layer may not be necessary.
136 127
137Note that the naming convention of the /proc filesystem entries 128Note that the naming convention of the /proc filesystem entries
138contains a number in addition to the driver name. (E.g. "cciss0" 129contains a number in addition to the driver name. (E.g. "cciss0"
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c
index e4bf9a11ca0d..c673ff14126a 100644
--- a/drivers/block/cciss_scsi.c
+++ b/drivers/block/cciss_scsi.c
@@ -358,10 +358,15 @@ find_bus_target_lun(int ctlr, int *bus, int *target, int *lun)
358 } 358 }
359 return (!found); 359 return (!found);
360} 360}
361struct scsi2map {
362 char scsi3addr[8];
363 int bus, target, lun;
364};
361 365
362static int 366static int
363cciss_scsi_add_entry(int ctlr, int hostno, 367cciss_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 /* assumes hba[ctlr]->scsi_ctlr->lock is held */ 371 /* assumes hba[ctlr]->scsi_ctlr->lock is held */
367 int n = ccissscsi[ctlr].ndevices; 372 int n = ccissscsi[ctlr].ndevices;
@@ -375,6 +380,12 @@ cciss_scsi_add_entry(int ctlr, int hostno,
375 sd = &ccissscsi[ctlr].dev[n]; 380 sd = &ccissscsi[ctlr].dev[n];
376 if (find_bus_target_lun(ctlr, &sd->bus, &sd->target, &sd->lun) != 0) 381 if (find_bus_target_lun(ctlr, &sd->bus, &sd->target, &sd->lun) != 0)
377 return -1; 382 return -1;
383
384 added[*nadded].bus = sd->bus;
385 added[*nadded].target = sd->target;
386 added[*nadded].lun = sd->lun;
387 (*nadded)++;
388
378 memcpy(&sd->scsi3addr[0], scsi3addr, 8); 389 memcpy(&sd->scsi3addr[0], scsi3addr, 8);
379 sd->devtype = devtype; 390 sd->devtype = devtype;
380 ccissscsi[ctlr].ndevices++; 391 ccissscsi[ctlr].ndevices++;
@@ -390,7 +401,8 @@ cciss_scsi_add_entry(int ctlr, int hostno,
390} 401}
391 402
392static void 403static void
393cciss_scsi_remove_entry(int ctlr, int hostno, int entry) 404cciss_scsi_remove_entry(int ctlr, int hostno, int entry,
405 struct scsi2map *removed, int *nremoved)
394{ 406{
395 /* assumes hba[ctlr]->scsi_ctlr->lock is held */ 407 /* assumes hba[ctlr]->scsi_ctlr->lock is held */
396 int i; 408 int i;
@@ -398,6 +410,10 @@ cciss_scsi_remove_entry(int ctlr, int hostno, int entry)
398 410
399 if (entry < 0 || entry >= CCISS_MAX_SCSI_DEVS_PER_HBA) return; 411 if (entry < 0 || entry >= CCISS_MAX_SCSI_DEVS_PER_HBA) return;
400 sd = ccissscsi[ctlr].dev[entry]; 412 sd = ccissscsi[ctlr].dev[entry];
413 removed[*nremoved].bus = sd.bus;
414 removed[*nremoved].target = sd.target;
415 removed[*nremoved].lun = sd.lun;
416 (*nremoved)++;
401 for (i=entry;i<ccissscsi[ctlr].ndevices-1;i++) 417 for (i=entry;i<ccissscsi[ctlr].ndevices-1;i++)
402 ccissscsi[ctlr].dev[i] = ccissscsi[ctlr].dev[i+1]; 418 ccissscsi[ctlr].dev[i] = ccissscsi[ctlr].dev[i+1];
403 ccissscsi[ctlr].ndevices--; 419 ccissscsi[ctlr].ndevices--;
@@ -417,6 +433,26 @@ cciss_scsi_remove_entry(int ctlr, int hostno, int entry)
417 (a)[1] == (b)[1] && \ 433 (a)[1] == (b)[1] && \
418 (a)[0] == (b)[0]) 434 (a)[0] == (b)[0])
419 435
436static void fixup_botched_add(int ctlr, char *scsi3addr)
437{
438 /* called when scsi_add_device fails in order to re-adjust */
439 /* ccissscsi[] to match the mid layer's view. */
440 unsigned long flags;
441 int i, j;
442 CPQ_TAPE_LOCK(ctlr, flags);
443 for (i = 0; i < ccissscsi[ctlr].ndevices; i++) {
444 if (memcmp(scsi3addr,
445 ccissscsi[ctlr].dev[i].scsi3addr, 8) == 0) {
446 for (j = i; j < ccissscsi[ctlr].ndevices-1; j++)
447 ccissscsi[ctlr].dev[j] =
448 ccissscsi[ctlr].dev[j+1];
449 ccissscsi[ctlr].ndevices--;
450 break;
451 }
452 }
453 CPQ_TAPE_UNLOCK(ctlr, flags);
454}
455
420static int 456static int
421adjust_cciss_scsi_table(int ctlr, int hostno, 457adjust_cciss_scsi_table(int ctlr, int hostno,
422 struct cciss_scsi_dev_t sd[], int nsds) 458 struct cciss_scsi_dev_t sd[], int nsds)
@@ -429,13 +465,33 @@ adjust_cciss_scsi_table(int ctlr, int hostno,
429 int i,j, found, changes=0; 465 int i,j, found, changes=0;
430 struct cciss_scsi_dev_t *csd; 466 struct cciss_scsi_dev_t *csd;
431 unsigned long flags; 467 unsigned long flags;
468 struct scsi2map *added, *removed;
469 int nadded, nremoved;
470 struct Scsi_Host *sh = NULL;
471
472 added = kzalloc(sizeof(*added) * CCISS_MAX_SCSI_DEVS_PER_HBA,
473 GFP_KERNEL);
474 removed = kzalloc(sizeof(*removed) * CCISS_MAX_SCSI_DEVS_PER_HBA,
475 GFP_KERNEL);
476
477 if (!added || !removed) {
478 printk(KERN_WARNING "cciss%d: Out of memory in "
479 "adjust_cciss_scsi_table\n", ctlr);
480 goto free_and_out;
481 }
432 482
433 CPQ_TAPE_LOCK(ctlr, flags); 483 CPQ_TAPE_LOCK(ctlr, flags);
434 484
485 if (hostno != -1) /* if it's not the first time... */
486 sh = ((struct cciss_scsi_adapter_data_t *)
487 hba[ctlr]->scsi_ctlr)->scsi_host;
488
435 /* find any devices in ccissscsi[] that are not in 489 /* find any devices in ccissscsi[] that are not in
436 sd[] and remove them from ccissscsi[] */ 490 sd[] and remove them from ccissscsi[] */
437 491
438 i = 0; 492 i = 0;
493 nremoved = 0;
494 nadded = 0;
439 while(i<ccissscsi[ctlr].ndevices) { 495 while(i<ccissscsi[ctlr].ndevices) {
440 csd = &ccissscsi[ctlr].dev[i]; 496 csd = &ccissscsi[ctlr].dev[i];
441 found=0; 497 found=0;
@@ -455,8 +511,9 @@ adjust_cciss_scsi_table(int ctlr, int hostno,
455 /* printk("cciss%d: %s device c%db%dt%dl%d removed.\n", 511 /* printk("cciss%d: %s device c%db%dt%dl%d removed.\n",
456 ctlr, scsi_device_type(csd->devtype), hostno, 512 ctlr, scsi_device_type(csd->devtype), hostno,
457 csd->bus, csd->target, csd->lun); */ 513 csd->bus, csd->target, csd->lun); */
458 cciss_scsi_remove_entry(ctlr, hostno, i); 514 cciss_scsi_remove_entry(ctlr, hostno, i,
459 /* note, i not incremented */ 515 removed, &nremoved);
516 /* remove ^^^, hence i not incremented */
460 } 517 }
461 else if (found == 1) { /* device is different kind */ 518 else if (found == 1) { /* device is different kind */
462 changes++; 519 changes++;
@@ -464,8 +521,15 @@ adjust_cciss_scsi_table(int ctlr, int hostno,
464 "(device type now %s).\n", 521 "(device type now %s).\n",
465 ctlr, hostno, csd->bus, csd->target, csd->lun, 522 ctlr, hostno, csd->bus, csd->target, csd->lun,
466 scsi_device_type(csd->devtype)); 523 scsi_device_type(csd->devtype));
524 cciss_scsi_remove_entry(ctlr, hostno, i,
525 removed, &nremoved);
526 /* remove ^^^, hence i not incremented */
527 if (cciss_scsi_add_entry(ctlr, hostno,
528 &sd[j].scsi3addr[0], sd[j].devtype,
529 added, &nadded) != 0)
530 /* we just removed one, so add can't fail. */
531 BUG();
467 csd->devtype = sd[j].devtype; 532 csd->devtype = sd[j].devtype;
468 i++; /* so just move along. */
469 } else /* device is same as it ever was, */ 533 } else /* device is same as it ever was, */
470 i++; /* so just move along. */ 534 i++; /* so just move along. */
471 } 535 }
@@ -489,7 +553,9 @@ adjust_cciss_scsi_table(int ctlr, int hostno,
489 if (!found) { 553 if (!found) {
490 changes++; 554 changes++;
491 if (cciss_scsi_add_entry(ctlr, hostno, 555 if (cciss_scsi_add_entry(ctlr, hostno,
492 &sd[i].scsi3addr[0], sd[i].devtype) != 0) 556
557 &sd[i].scsi3addr[0], sd[i].devtype,
558 added, &nadded) != 0)
493 break; 559 break;
494 } else if (found == 1) { 560 } else if (found == 1) {
495 /* should never happen... */ 561 /* should never happen... */
@@ -501,9 +567,50 @@ adjust_cciss_scsi_table(int ctlr, int hostno,
501 } 567 }
502 CPQ_TAPE_UNLOCK(ctlr, flags); 568 CPQ_TAPE_UNLOCK(ctlr, flags);
503 569
504 if (!changes) 570 /* Don't notify scsi mid layer of any changes the first time through */
505 printk("cciss%d: No device changes detected.\n", ctlr); 571 /* (or if there are no changes) scsi_scan_host will do it later the */
572 /* first time through. */
573 if (hostno == -1 || !changes)
574 goto free_and_out;
575
576 /* Notify scsi mid layer of any removed devices */
577 for (i = 0; i < nremoved; i++) {
578 struct scsi_device *sdev =
579 scsi_device_lookup(sh, removed[i].bus,
580 removed[i].target, removed[i].lun);
581 if (sdev != NULL) {
582 scsi_remove_device(sdev);
583 scsi_device_put(sdev);
584 } else {
585 /* We don't expect to get here. */
586 /* future cmds to this device will get selection */
587 /* timeout as if the device was gone. */
588 printk(KERN_WARNING "cciss%d: didn't find "
589 "c%db%dt%dl%d\n for removal.",
590 ctlr, hostno, removed[i].bus,
591 removed[i].target, removed[i].lun);
592 }
593 }
594
595 /* Notify scsi mid layer of any added devices */
596 for (i = 0; i < nadded; i++) {
597 int rc;
598 rc = scsi_add_device(sh, added[i].bus,
599 added[i].target, added[i].lun);
600 if (rc == 0)
601 continue;
602 printk(KERN_WARNING "cciss%d: scsi_add_device "
603 "c%db%dt%dl%d failed, device not added.\n",
604 ctlr, hostno,
605 added[i].bus, added[i].target, added[i].lun);
606 /* now we have to remove it from ccissscsi, */
607 /* since it didn't get added to scsi mid layer */
608 fixup_botched_add(ctlr, added[i].scsi3addr);
609 }
506 610
611free_and_out:
612 kfree(added);
613 kfree(removed);
507 return 0; 614 return 0;
508} 615}
509 616
@@ -1355,32 +1462,6 @@ cciss_unregister_scsi(int ctlr)
1355} 1462}
1356 1463
1357static int 1464static int
1358cciss_register_scsi(int ctlr)
1359{
1360 unsigned long flags;
1361
1362 CPQ_TAPE_LOCK(ctlr, flags);
1363
1364 /* Since this is really a block driver, the SCSI core may not be
1365 initialized at init time, in which case, calling scsi_register_host
1366 would hang. Instead, we do it later, via /proc filesystem
1367 and rc scripts, when we know SCSI core is good to go. */
1368
1369 /* Only register if SCSI devices are detected. */
1370 if (ccissscsi[ctlr].ndevices != 0) {
1371 ((struct cciss_scsi_adapter_data_t *)
1372 hba[ctlr]->scsi_ctlr)->registered = 1;
1373 CPQ_TAPE_UNLOCK(ctlr, flags);
1374 return cciss_scsi_detect(ctlr);
1375 }
1376 CPQ_TAPE_UNLOCK(ctlr, flags);
1377 printk(KERN_INFO
1378 "cciss%d: No appropriate SCSI device detected, "
1379 "SCSI subsystem not engaged.\n", ctlr);
1380 return 0;
1381}
1382
1383static int
1384cciss_engage_scsi(int ctlr) 1465cciss_engage_scsi(int ctlr)
1385{ 1466{
1386 struct cciss_scsi_adapter_data_t *sa; 1467 struct cciss_scsi_adapter_data_t *sa;
@@ -1391,15 +1472,15 @@ cciss_engage_scsi(int ctlr)
1391 sa = (struct cciss_scsi_adapter_data_t *) hba[ctlr]->scsi_ctlr; 1472 sa = (struct cciss_scsi_adapter_data_t *) hba[ctlr]->scsi_ctlr;
1392 stk = &sa->cmd_stack; 1473 stk = &sa->cmd_stack;
1393 1474
1394 if (((struct cciss_scsi_adapter_data_t *) 1475 if (sa->registered) {
1395 hba[ctlr]->scsi_ctlr)->registered) {
1396 printk("cciss%d: SCSI subsystem already engaged.\n", ctlr); 1476 printk("cciss%d: SCSI subsystem already engaged.\n", ctlr);
1397 spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); 1477 spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
1398 return ENXIO; 1478 return ENXIO;
1399 } 1479 }
1480 sa->registered = 1;
1400 spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); 1481 spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
1401 cciss_update_non_disk_devices(ctlr, -1); 1482 cciss_update_non_disk_devices(ctlr, -1);
1402 cciss_register_scsi(ctlr); 1483 cciss_scsi_detect(ctlr);
1403 return 0; 1484 return 0;
1404} 1485}
1405 1486
@@ -1493,7 +1574,5 @@ static int cciss_eh_abort_handler(struct scsi_cmnd *scsicmd)
1493/* If no tape support, then these become defined out of existence */ 1574/* If no tape support, then these become defined out of existence */
1494 1575
1495#define cciss_scsi_setup(cntl_num) 1576#define cciss_scsi_setup(cntl_num)
1496#define cciss_unregister_scsi(ctlr)
1497#define cciss_register_scsi(ctlr)
1498 1577
1499#endif /* CONFIG_CISS_SCSI_TAPE */ 1578#endif /* CONFIG_CISS_SCSI_TAPE */