aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/cciss_scsi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/block/cciss_scsi.c')
-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 */