mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-10 07:10:27 +00:00
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>
This commit is contained in:
parent
50b08240de
commit
c4c1adb349
@ -1446,12 +1446,80 @@ static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb)
|
||||
}
|
||||
}
|
||||
|
||||
static void arcmsr_remove_scsi_devices(struct AdapterControlBlock *acb)
|
||||
{
|
||||
char *acb_dev_map = (char *)acb->device_map;
|
||||
int target, lun, i;
|
||||
struct scsi_device *psdev;
|
||||
struct CommandControlBlock *ccb;
|
||||
char temp;
|
||||
|
||||
for (i = 0; i < acb->maxFreeCCB; i++) {
|
||||
ccb = acb->pccb_pool[i];
|
||||
if (ccb->startdone == ARCMSR_CCB_START) {
|
||||
ccb->pcmd->result = DID_NO_CONNECT << 16;
|
||||
arcmsr_pci_unmap_dma(ccb);
|
||||
ccb->pcmd->scsi_done(ccb->pcmd);
|
||||
}
|
||||
}
|
||||
for (target = 0; target < ARCMSR_MAX_TARGETID; target++) {
|
||||
temp = *acb_dev_map;
|
||||
if (temp) {
|
||||
for (lun = 0; lun < ARCMSR_MAX_TARGETLUN; lun++) {
|
||||
if (temp & 1) {
|
||||
psdev = scsi_device_lookup(acb->host,
|
||||
0, target, lun);
|
||||
if (psdev != NULL) {
|
||||
scsi_remove_device(psdev);
|
||||
scsi_device_put(psdev);
|
||||
}
|
||||
}
|
||||
temp >>= 1;
|
||||
}
|
||||
*acb_dev_map = 0;
|
||||
}
|
||||
acb_dev_map++;
|
||||
}
|
||||
}
|
||||
|
||||
static void arcmsr_free_pcidev(struct AdapterControlBlock *acb)
|
||||
{
|
||||
struct pci_dev *pdev;
|
||||
struct Scsi_Host *host;
|
||||
|
||||
host = acb->host;
|
||||
arcmsr_free_sysfs_attr(acb);
|
||||
scsi_remove_host(host);
|
||||
flush_work(&acb->arcmsr_do_message_isr_bh);
|
||||
del_timer_sync(&acb->eternal_timer);
|
||||
if (set_date_time)
|
||||
del_timer_sync(&acb->refresh_timer);
|
||||
pdev = acb->pdev;
|
||||
arcmsr_free_irq(pdev, acb);
|
||||
arcmsr_free_ccb_pool(acb);
|
||||
arcmsr_free_mu(acb);
|
||||
arcmsr_unmap_pciregion(acb);
|
||||
pci_release_regions(pdev);
|
||||
scsi_host_put(host);
|
||||
pci_disable_device(pdev);
|
||||
}
|
||||
|
||||
static void arcmsr_remove(struct pci_dev *pdev)
|
||||
{
|
||||
struct Scsi_Host *host = pci_get_drvdata(pdev);
|
||||
struct AdapterControlBlock *acb =
|
||||
(struct AdapterControlBlock *) host->hostdata;
|
||||
int poll_count = 0;
|
||||
uint16_t dev_id;
|
||||
|
||||
pci_read_config_word(pdev, PCI_DEVICE_ID, &dev_id);
|
||||
if (dev_id == 0xffff) {
|
||||
acb->acb_flags &= ~ACB_F_IOP_INITED;
|
||||
acb->acb_flags |= ACB_F_ADAPTER_REMOVED;
|
||||
arcmsr_remove_scsi_devices(acb);
|
||||
arcmsr_free_pcidev(acb);
|
||||
return;
|
||||
}
|
||||
arcmsr_free_sysfs_attr(acb);
|
||||
scsi_remove_host(host);
|
||||
flush_work(&acb->arcmsr_do_message_isr_bh);
|
||||
@ -1499,6 +1567,8 @@ static void arcmsr_shutdown(struct pci_dev *pdev)
|
||||
struct Scsi_Host *host = pci_get_drvdata(pdev);
|
||||
struct AdapterControlBlock *acb =
|
||||
(struct AdapterControlBlock *)host->hostdata;
|
||||
if (acb->acb_flags & ACB_F_ADAPTER_REMOVED)
|
||||
return;
|
||||
del_timer_sync(&acb->eternal_timer);
|
||||
if (set_date_time)
|
||||
del_timer_sync(&acb->refresh_timer);
|
||||
@ -2931,6 +3001,12 @@ static int arcmsr_queue_command_lck(struct scsi_cmnd *cmd,
|
||||
struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
|
||||
struct CommandControlBlock *ccb;
|
||||
int target = cmd->device->id;
|
||||
|
||||
if (acb->acb_flags & ACB_F_ADAPTER_REMOVED) {
|
||||
cmd->result = (DID_NO_CONNECT << 16);
|
||||
cmd->scsi_done(cmd);
|
||||
return 0;
|
||||
}
|
||||
cmd->scsi_done = done;
|
||||
cmd->host_scribble = NULL;
|
||||
cmd->result = 0;
|
||||
@ -4177,6 +4253,8 @@ static int arcmsr_bus_reset(struct scsi_cmnd *cmd)
|
||||
int retry_count = 0;
|
||||
int rtn = FAILED;
|
||||
acb = (struct AdapterControlBlock *) cmd->device->host->hostdata;
|
||||
if (acb->acb_flags & ACB_F_ADAPTER_REMOVED)
|
||||
return SUCCESS;
|
||||
pr_notice("arcmsr: executing bus reset eh.....num_resets = %d,"
|
||||
" num_aborts = %d \n", acb->num_resets, acb->num_aborts);
|
||||
acb->num_resets++;
|
||||
@ -4243,6 +4321,8 @@ static int arcmsr_abort(struct scsi_cmnd *cmd)
|
||||
int rtn = FAILED;
|
||||
uint32_t intmask_org;
|
||||
|
||||
if (acb->acb_flags & ACB_F_ADAPTER_REMOVED)
|
||||
return SUCCESS;
|
||||
printk(KERN_NOTICE
|
||||
"arcmsr%d: abort device command of scsi id = %d lun = %d\n",
|
||||
acb->host->host_no, cmd->device->id, (u32)cmd->device->lun);
|
||||
|
Loading…
x
Reference in New Issue
Block a user