diff options
| author | Ching Huang <ching2048@areca.com.tw> | 2018-03-15 02:33:36 -0400 |
|---|---|---|
| committer | Martin K. Petersen <martin.petersen@oracle.com> | 2018-03-21 18:46:30 -0400 |
| commit | c4c1adb3490ea4b8b13da2dae8d563350ded4988 (patch) | |
| tree | b8e901e5d59318bbdd27f2aa1e819195cb30a738 | |
| parent | 50b08240de61fcae54f6b35a25198209ac13c947 (diff) | |
scsi: arcmsr: Handle adapter removed due to thunderbolt cable disconnection.
Handle adapter removed due to thunderbolt cable disconnection.
Signed-off-by: Ching Huang <ching2048@areca.com.tw>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
| -rw-r--r-- | drivers/scsi/arcmsr/arcmsr_hba.c | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c index 75e828bd30e3..2f52c53e4faa 100644 --- a/drivers/scsi/arcmsr/arcmsr_hba.c +++ b/drivers/scsi/arcmsr/arcmsr_hba.c | |||
| @@ -1446,12 +1446,80 @@ static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb) | |||
| 1446 | } | 1446 | } |
| 1447 | } | 1447 | } |
| 1448 | 1448 | ||
| 1449 | static void arcmsr_remove_scsi_devices(struct AdapterControlBlock *acb) | ||
| 1450 | { | ||
| 1451 | char *acb_dev_map = (char *)acb->device_map; | ||
| 1452 | int target, lun, i; | ||
| 1453 | struct scsi_device *psdev; | ||
| 1454 | struct CommandControlBlock *ccb; | ||
| 1455 | char temp; | ||
| 1456 | |||
| 1457 | for (i = 0; i < acb->maxFreeCCB; i++) { | ||
| 1458 | ccb = acb->pccb_pool[i]; | ||
| 1459 | if (ccb->startdone == ARCMSR_CCB_START) { | ||
| 1460 | ccb->pcmd->result = DID_NO_CONNECT << 16; | ||
| 1461 | arcmsr_pci_unmap_dma(ccb); | ||
| 1462 | ccb->pcmd->scsi_done(ccb->pcmd); | ||
| 1463 | } | ||
| 1464 | } | ||
| 1465 | for (target = 0; target < ARCMSR_MAX_TARGETID; target++) { | ||
| 1466 | temp = *acb_dev_map; | ||
| 1467 | if (temp) { | ||
| 1468 | for (lun = 0; lun < ARCMSR_MAX_TARGETLUN; lun++) { | ||
| 1469 | if (temp & 1) { | ||
| 1470 | psdev = scsi_device_lookup(acb->host, | ||
| 1471 | 0, target, lun); | ||
| 1472 | if (psdev != NULL) { | ||
| 1473 | scsi_remove_device(psdev); | ||
| 1474 | scsi_device_put(psdev); | ||
| 1475 | } | ||
| 1476 | } | ||
| 1477 | temp >>= 1; | ||
| 1478 | } | ||
| 1479 | *acb_dev_map = 0; | ||
| 1480 | } | ||
| 1481 | acb_dev_map++; | ||
| 1482 | } | ||
| 1483 | } | ||
| 1484 | |||
| 1485 | static void arcmsr_free_pcidev(struct AdapterControlBlock *acb) | ||
| 1486 | { | ||
| 1487 | struct pci_dev *pdev; | ||
| 1488 | struct Scsi_Host *host; | ||
| 1489 | |||
| 1490 | host = acb->host; | ||
| 1491 | arcmsr_free_sysfs_attr(acb); | ||
| 1492 | scsi_remove_host(host); | ||
| 1493 | flush_work(&acb->arcmsr_do_message_isr_bh); | ||
| 1494 | del_timer_sync(&acb->eternal_timer); | ||
| 1495 | if (set_date_time) | ||
| 1496 | del_timer_sync(&acb->refresh_timer); | ||
| 1497 | pdev = acb->pdev; | ||
| 1498 | arcmsr_free_irq(pdev, acb); | ||
| 1499 | arcmsr_free_ccb_pool(acb); | ||
| 1500 | arcmsr_free_mu(acb); | ||
| 1501 | arcmsr_unmap_pciregion(acb); | ||
| 1502 | pci_release_regions(pdev); | ||
| 1503 | scsi_host_put(host); | ||
| 1504 | pci_disable_device(pdev); | ||
| 1505 | } | ||
| 1506 | |||
| 1449 | static void arcmsr_remove(struct pci_dev *pdev) | 1507 | static void arcmsr_remove(struct pci_dev *pdev) |
| 1450 | { | 1508 | { |
| 1451 | struct Scsi_Host *host = pci_get_drvdata(pdev); | 1509 | struct Scsi_Host *host = pci_get_drvdata(pdev); |
| 1452 | struct AdapterControlBlock *acb = | 1510 | struct AdapterControlBlock *acb = |
| 1453 | (struct AdapterControlBlock *) host->hostdata; | 1511 | (struct AdapterControlBlock *) host->hostdata; |
| 1454 | int poll_count = 0; | 1512 | int poll_count = 0; |
| 1513 | uint16_t dev_id; | ||
| 1514 | |||
| 1515 | pci_read_config_word(pdev, PCI_DEVICE_ID, &dev_id); | ||
| 1516 | if (dev_id == 0xffff) { | ||
| 1517 | acb->acb_flags &= ~ACB_F_IOP_INITED; | ||
| 1518 | acb->acb_flags |= ACB_F_ADAPTER_REMOVED; | ||
| 1519 | arcmsr_remove_scsi_devices(acb); | ||
| 1520 | arcmsr_free_pcidev(acb); | ||
| 1521 | return; | ||
| 1522 | } | ||
| 1455 | arcmsr_free_sysfs_attr(acb); | 1523 | arcmsr_free_sysfs_attr(acb); |
| 1456 | scsi_remove_host(host); | 1524 | scsi_remove_host(host); |
| 1457 | flush_work(&acb->arcmsr_do_message_isr_bh); | 1525 | flush_work(&acb->arcmsr_do_message_isr_bh); |
| @@ -1499,6 +1567,8 @@ static void arcmsr_shutdown(struct pci_dev *pdev) | |||
| 1499 | struct Scsi_Host *host = pci_get_drvdata(pdev); | 1567 | struct Scsi_Host *host = pci_get_drvdata(pdev); |
| 1500 | struct AdapterControlBlock *acb = | 1568 | struct AdapterControlBlock *acb = |
| 1501 | (struct AdapterControlBlock *)host->hostdata; | 1569 | (struct AdapterControlBlock *)host->hostdata; |
| 1570 | if (acb->acb_flags & ACB_F_ADAPTER_REMOVED) | ||
| 1571 | return; | ||
| 1502 | del_timer_sync(&acb->eternal_timer); | 1572 | del_timer_sync(&acb->eternal_timer); |
| 1503 | if (set_date_time) | 1573 | if (set_date_time) |
| 1504 | del_timer_sync(&acb->refresh_timer); | 1574 | del_timer_sync(&acb->refresh_timer); |
| @@ -2931,6 +3001,12 @@ static int arcmsr_queue_command_lck(struct scsi_cmnd *cmd, | |||
| 2931 | struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata; | 3001 | struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata; |
| 2932 | struct CommandControlBlock *ccb; | 3002 | struct CommandControlBlock *ccb; |
| 2933 | int target = cmd->device->id; | 3003 | int target = cmd->device->id; |
| 3004 | |||
| 3005 | if (acb->acb_flags & ACB_F_ADAPTER_REMOVED) { | ||
| 3006 | cmd->result = (DID_NO_CONNECT << 16); | ||
| 3007 | cmd->scsi_done(cmd); | ||
| 3008 | return 0; | ||
| 3009 | } | ||
| 2934 | cmd->scsi_done = done; | 3010 | cmd->scsi_done = done; |
| 2935 | cmd->host_scribble = NULL; | 3011 | cmd->host_scribble = NULL; |
| 2936 | cmd->result = 0; | 3012 | cmd->result = 0; |
| @@ -4177,6 +4253,8 @@ static int arcmsr_bus_reset(struct scsi_cmnd *cmd) | |||
| 4177 | int retry_count = 0; | 4253 | int retry_count = 0; |
| 4178 | int rtn = FAILED; | 4254 | int rtn = FAILED; |
| 4179 | acb = (struct AdapterControlBlock *) cmd->device->host->hostdata; | 4255 | acb = (struct AdapterControlBlock *) cmd->device->host->hostdata; |
| 4256 | if (acb->acb_flags & ACB_F_ADAPTER_REMOVED) | ||
| 4257 | return SUCCESS; | ||
| 4180 | pr_notice("arcmsr: executing bus reset eh.....num_resets = %d," | 4258 | pr_notice("arcmsr: executing bus reset eh.....num_resets = %d," |
| 4181 | " num_aborts = %d \n", acb->num_resets, acb->num_aborts); | 4259 | " num_aborts = %d \n", acb->num_resets, acb->num_aborts); |
| 4182 | acb->num_resets++; | 4260 | acb->num_resets++; |
| @@ -4243,6 +4321,8 @@ static int arcmsr_abort(struct scsi_cmnd *cmd) | |||
| 4243 | int rtn = FAILED; | 4321 | int rtn = FAILED; |
| 4244 | uint32_t intmask_org; | 4322 | uint32_t intmask_org; |
| 4245 | 4323 | ||
| 4324 | if (acb->acb_flags & ACB_F_ADAPTER_REMOVED) | ||
| 4325 | return SUCCESS; | ||
| 4246 | printk(KERN_NOTICE | 4326 | printk(KERN_NOTICE |
| 4247 | "arcmsr%d: abort device command of scsi id = %d lun = %d\n", | 4327 | "arcmsr%d: abort device command of scsi id = %d lun = %d\n", |
| 4248 | acb->host->host_no, cmd->device->id, (u32)cmd->device->lun); | 4328 | acb->host->host_no, cmd->device->id, (u32)cmd->device->lun); |
