aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChing Huang <ching2048@areca.com.tw>2018-03-15 02:33:36 -0400
committerMartin K. Petersen <martin.petersen@oracle.com>2018-03-21 18:46:30 -0400
commitc4c1adb3490ea4b8b13da2dae8d563350ded4988 (patch)
treeb8e901e5d59318bbdd27f2aa1e819195cb30a738
parent50b08240de61fcae54f6b35a25198209ac13c947 (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.c80
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
1449static 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
1485static 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
1449static void arcmsr_remove(struct pci_dev *pdev) 1507static 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);