summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCharles <charles.chiou@tw.promise.com>2016-02-22 07:04:25 -0500
committerMartin K. Petersen <martin.petersen@oracle.com>2016-02-23 21:27:02 -0500
commit45b42adbec68872529e4e24ba7570de367240818 (patch)
tree89b526877e14a340adf5dd38a68d0ee1b8db9388
parent1ec364e6a33a748c30411737b01257b1c976d297 (diff)
stex: Add hotplug support
1. Add hotplug support. Pegasus support surprise removal. To this end, I use return_abnormal_state function to return DID_NO_CONNECT for all commands which sent to driver. 2. Remove stex_hba_stop in stex_remove because we cannot send command to device after hotplug. 3. Add new device status: MU_STATE_STOP, MU_STATE_NOCONNECT, MU_STATE_STOP. MU_STATE_STOP is currently not referenced. MU_STATE_NOCONNECT represent that device is plugged out from the host. 4. Use return_abnormal_function() to substitute part of code in stex_do_reset. Signed-off-by: Charles Chiou <charles.chiou@tw.promise.com> Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-rw-r--r--drivers/scsi/stex.c53
1 files changed, 34 insertions, 19 deletions
diff --git a/drivers/scsi/stex.c b/drivers/scsi/stex.c
index 495d6322bb21..19946031fa9a 100644
--- a/drivers/scsi/stex.c
+++ b/drivers/scsi/stex.c
@@ -84,6 +84,8 @@ enum {
84 MU_STATE_STARTED = 2, 84 MU_STATE_STARTED = 2,
85 MU_STATE_RESETTING = 3, 85 MU_STATE_RESETTING = 3,
86 MU_STATE_FAILED = 4, 86 MU_STATE_FAILED = 4,
87 MU_STATE_STOP = 5,
88 MU_STATE_NOCONNECT = 6,
87 89
88 MU_MAX_DELAY = 120, 90 MU_MAX_DELAY = 120,
89 MU_HANDSHAKE_SIGNATURE = 0x55aaaa55, 91 MU_HANDSHAKE_SIGNATURE = 0x55aaaa55,
@@ -537,6 +539,27 @@ stex_ss_send_cmd(struct st_hba *hba, struct req_msg *req, u16 tag)
537 readl(hba->mmio_base + YH2I_REQ); /* flush */ 539 readl(hba->mmio_base + YH2I_REQ); /* flush */
538} 540}
539 541
542static void return_abnormal_state(struct st_hba *hba, int status)
543{
544 struct st_ccb *ccb;
545 unsigned long flags;
546 u16 tag;
547
548 spin_lock_irqsave(hba->host->host_lock, flags);
549 for (tag = 0; tag < hba->host->can_queue; tag++) {
550 ccb = &hba->ccb[tag];
551 if (ccb->req == NULL)
552 continue;
553 ccb->req = NULL;
554 if (ccb->cmd) {
555 scsi_dma_unmap(ccb->cmd);
556 ccb->cmd->result = status << 16;
557 ccb->cmd->scsi_done(ccb->cmd);
558 ccb->cmd = NULL;
559 }
560 }
561 spin_unlock_irqrestore(hba->host->host_lock, flags);
562}
540static int 563static int
541stex_slave_config(struct scsi_device *sdev) 564stex_slave_config(struct scsi_device *sdev)
542{ 565{
@@ -560,8 +583,12 @@ stex_queuecommand_lck(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
560 id = cmd->device->id; 583 id = cmd->device->id;
561 lun = cmd->device->lun; 584 lun = cmd->device->lun;
562 hba = (struct st_hba *) &host->hostdata[0]; 585 hba = (struct st_hba *) &host->hostdata[0];
563 586 if (hba->mu_status == MU_STATE_NOCONNECT) {
564 if (unlikely(hba->mu_status == MU_STATE_RESETTING)) 587 cmd->result = DID_NO_CONNECT;
588 done(cmd);
589 return 0;
590 }
591 if (unlikely(hba->mu_status != MU_STATE_STARTED))
565 return SCSI_MLQUEUE_HOST_BUSY; 592 return SCSI_MLQUEUE_HOST_BUSY;
566 593
567 switch (cmd->cmnd[0]) { 594 switch (cmd->cmnd[0]) {
@@ -1260,10 +1287,8 @@ static void stex_ss_reset(struct st_hba *hba)
1260 1287
1261static int stex_do_reset(struct st_hba *hba) 1288static int stex_do_reset(struct st_hba *hba)
1262{ 1289{
1263 struct st_ccb *ccb;
1264 unsigned long flags; 1290 unsigned long flags;
1265 unsigned int mu_status = MU_STATE_RESETTING; 1291 unsigned int mu_status = MU_STATE_RESETTING;
1266 u16 tag;
1267 1292
1268 spin_lock_irqsave(hba->host->host_lock, flags); 1293 spin_lock_irqsave(hba->host->host_lock, flags);
1269 if (hba->mu_status == MU_STATE_STARTING) { 1294 if (hba->mu_status == MU_STATE_STARTING) {
@@ -1297,20 +1322,8 @@ static int stex_do_reset(struct st_hba *hba)
1297 else if (hba->cardtype == st_yel) 1322 else if (hba->cardtype == st_yel)
1298 stex_ss_reset(hba); 1323 stex_ss_reset(hba);
1299 1324
1300 spin_lock_irqsave(hba->host->host_lock, flags); 1325
1301 for (tag = 0; tag < hba->host->can_queue; tag++) { 1326 return_abnormal_state(hba, DID_RESET);
1302 ccb = &hba->ccb[tag];
1303 if (ccb->req == NULL)
1304 continue;
1305 ccb->req = NULL;
1306 if (ccb->cmd) {
1307 scsi_dma_unmap(ccb->cmd);
1308 ccb->cmd->result = DID_RESET << 16;
1309 ccb->cmd->scsi_done(ccb->cmd);
1310 ccb->cmd = NULL;
1311 }
1312 }
1313 spin_unlock_irqrestore(hba->host->host_lock, flags);
1314 1327
1315 if (stex_handshake(hba) == 0) 1328 if (stex_handshake(hba) == 0)
1316 return 0; 1329 return 0;
@@ -1771,9 +1784,11 @@ static void stex_remove(struct pci_dev *pdev)
1771{ 1784{
1772 struct st_hba *hba = pci_get_drvdata(pdev); 1785 struct st_hba *hba = pci_get_drvdata(pdev);
1773 1786
1787 hba->mu_status = MU_STATE_NOCONNECT;
1788 return_abnormal_state(hba, DID_NO_CONNECT);
1774 scsi_remove_host(hba->host); 1789 scsi_remove_host(hba->host);
1775 1790
1776 stex_hba_stop(hba); 1791 scsi_block_requests(hba->host);
1777 1792
1778 stex_hba_free(hba); 1793 stex_hba_free(hba);
1779 1794