diff options
author | Charles <charles.chiou@tw.promise.com> | 2016-02-22 07:04:25 -0500 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2016-02-23 21:27:02 -0500 |
commit | 45b42adbec68872529e4e24ba7570de367240818 (patch) | |
tree | 89b526877e14a340adf5dd38a68d0ee1b8db9388 | |
parent | 1ec364e6a33a748c30411737b01257b1c976d297 (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.c | 53 |
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 | ||
542 | static 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 | } | ||
540 | static int | 563 | static int |
541 | stex_slave_config(struct scsi_device *sdev) | 564 | stex_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 | ||
1261 | static int stex_do_reset(struct st_hba *hba) | 1288 | static 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 | ||