aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block
diff options
context:
space:
mode:
authorMike Miller <mike.miller@hp.com>2008-08-04 05:54:53 -0400
committerJens Axboe <jens.axboe@oracle.com>2008-08-06 06:30:04 -0400
commitf4a93bcda74edfe6977dcf296ed8c86119638871 (patch)
tree866f59740b737e23254160dea1bdc527292c76ce /drivers/block
parenteece695f8bf9d1aacf3a119ab8e21db31948e40b (diff)
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>
Diffstat (limited to 'drivers/block')
-rw-r--r--drivers/block/cciss_scsi.c157
1 files changed, 118 insertions, 39 deletions
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 */