diff options
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_os.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_os.c | 112 |
1 files changed, 39 insertions, 73 deletions
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 7aec93f9d423..c58c9d97b041 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c | |||
@@ -1,20 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * QLOGIC LINUX SOFTWARE | 2 | * QLogic Fibre Channel HBA Driver |
3 | * | 3 | * Copyright (c) 2003-2005 QLogic Corporation |
4 | * QLogic ISP2x00 device driver for Linux 2.6.x | ||
5 | * Copyright (C) 2003-2005 QLogic Corporation | ||
6 | * (www.qlogic.com) | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2, or (at your option) any | ||
11 | * later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | 4 | * |
5 | * See LICENSE.qla2xxx for copyright and licensing details. | ||
18 | */ | 6 | */ |
19 | #include "qla_def.h" | 7 | #include "qla_def.h" |
20 | 8 | ||
@@ -61,19 +49,6 @@ MODULE_PARM_DESC(ql2xplogiabsentdevice, | |||
61 | "a Fabric scan. This is needed for several broken switches." | 49 | "a Fabric scan. This is needed for several broken switches." |
62 | "Default is 0 - no PLOGI. 1 - perfom PLOGI."); | 50 | "Default is 0 - no PLOGI. 1 - perfom PLOGI."); |
63 | 51 | ||
64 | int ql2xenablezio = 0; | ||
65 | module_param(ql2xenablezio, int, S_IRUGO|S_IRUSR); | ||
66 | MODULE_PARM_DESC(ql2xenablezio, | ||
67 | "Option to enable ZIO:If 1 then enable it otherwise" | ||
68 | " use the default set in the NVRAM." | ||
69 | " Default is 0 : disabled"); | ||
70 | |||
71 | int ql2xintrdelaytimer = 10; | ||
72 | module_param(ql2xintrdelaytimer, int, S_IRUGO|S_IRUSR); | ||
73 | MODULE_PARM_DESC(ql2xintrdelaytimer, | ||
74 | "ZIO: Waiting time for Firmware before it generates an " | ||
75 | "interrupt to the host to notify completion of request."); | ||
76 | |||
77 | int ql2xloginretrycount = 0; | 52 | int ql2xloginretrycount = 0; |
78 | module_param(ql2xloginretrycount, int, S_IRUGO|S_IRUSR); | 53 | module_param(ql2xloginretrycount, int, S_IRUGO|S_IRUSR); |
79 | MODULE_PARM_DESC(ql2xloginretrycount, | 54 | MODULE_PARM_DESC(ql2xloginretrycount, |
@@ -373,11 +348,13 @@ qla2x00_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) | |||
373 | { | 348 | { |
374 | scsi_qla_host_t *ha = to_qla_host(cmd->device->host); | 349 | scsi_qla_host_t *ha = to_qla_host(cmd->device->host); |
375 | fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; | 350 | fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; |
351 | struct fc_rport *rport = starget_to_rport(scsi_target(cmd->device)); | ||
376 | srb_t *sp; | 352 | srb_t *sp; |
377 | int rval; | 353 | int rval; |
378 | 354 | ||
379 | if (!fcport) { | 355 | rval = fc_remote_port_chkready(rport); |
380 | cmd->result = DID_NO_CONNECT << 16; | 356 | if (rval) { |
357 | cmd->result = rval; | ||
381 | goto qc_fail_command; | 358 | goto qc_fail_command; |
382 | } | 359 | } |
383 | 360 | ||
@@ -400,16 +377,6 @@ qla2x00_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) | |||
400 | if (rval != QLA_SUCCESS) | 377 | if (rval != QLA_SUCCESS) |
401 | goto qc_host_busy_free_sp; | 378 | goto qc_host_busy_free_sp; |
402 | 379 | ||
403 | /* Manage unprocessed RIO/ZIO commands in response queue. */ | ||
404 | if (ha->flags.online && ha->flags.process_response_queue && | ||
405 | ha->response_ring_ptr->signature != RESPONSE_PROCESSED) { | ||
406 | unsigned long flags; | ||
407 | |||
408 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
409 | qla2x00_process_response_queue(ha); | ||
410 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
411 | } | ||
412 | |||
413 | spin_lock_irq(ha->host->host_lock); | 380 | spin_lock_irq(ha->host->host_lock); |
414 | 381 | ||
415 | return 0; | 382 | return 0; |
@@ -436,11 +403,13 @@ qla24xx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) | |||
436 | { | 403 | { |
437 | scsi_qla_host_t *ha = to_qla_host(cmd->device->host); | 404 | scsi_qla_host_t *ha = to_qla_host(cmd->device->host); |
438 | fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; | 405 | fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; |
406 | struct fc_rport *rport = starget_to_rport(scsi_target(cmd->device)); | ||
439 | srb_t *sp; | 407 | srb_t *sp; |
440 | int rval; | 408 | int rval; |
441 | 409 | ||
442 | if (!fcport) { | 410 | rval = fc_remote_port_chkready(rport); |
443 | cmd->result = DID_NO_CONNECT << 16; | 411 | if (rval) { |
412 | cmd->result = rval; | ||
444 | goto qc24_fail_command; | 413 | goto qc24_fail_command; |
445 | } | 414 | } |
446 | 415 | ||
@@ -797,29 +766,19 @@ qla2xxx_eh_device_reset(struct scsi_cmnd *cmd) | |||
797 | goto eh_dev_reset_done; | 766 | goto eh_dev_reset_done; |
798 | } | 767 | } |
799 | 768 | ||
800 | /* | 769 | /* Flush outstanding commands. */ |
801 | * If we are coming down the EH path, wait for all commands to | 770 | if (qla2x00_eh_wait_for_pending_target_commands(ha, id)) |
802 | * complete for the device. | 771 | ret = FAILED; |
803 | */ | 772 | if (ret == FAILED) { |
804 | if (cmd->device->host->eh_active) { | 773 | DEBUG3(printk("%s(%ld): failed while waiting for commands\n", |
805 | if (qla2x00_eh_wait_for_pending_target_commands(ha, id)) | 774 | __func__, ha->host_no)); |
806 | ret = FAILED; | 775 | qla_printk(KERN_INFO, ha, |
807 | 776 | "%s: failed while waiting for commands\n", __func__); | |
808 | if (ret == FAILED) { | 777 | } else |
809 | DEBUG3(printk("%s(%ld): failed while waiting for " | 778 | qla_printk(KERN_INFO, ha, |
810 | "commands\n", __func__, ha->host_no)); | 779 | "scsi(%ld:%d:%d): DEVICE RESET SUCCEEDED.\n", ha->host_no, |
811 | qla_printk(KERN_INFO, ha, | 780 | id, lun); |
812 | "%s: failed while waiting for commands\n", | 781 | eh_dev_reset_done: |
813 | __func__); | ||
814 | |||
815 | goto eh_dev_reset_done; | ||
816 | } | ||
817 | } | ||
818 | |||
819 | qla_printk(KERN_INFO, ha, | ||
820 | "scsi(%ld:%d:%d): DEVICE RESET SUCCEEDED.\n", ha->host_no, id, lun); | ||
821 | |||
822 | eh_dev_reset_done: | ||
823 | return ret; | 782 | return ret; |
824 | } | 783 | } |
825 | 784 | ||
@@ -921,10 +880,9 @@ qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd) | |||
921 | if (ret == FAILED) | 880 | if (ret == FAILED) |
922 | goto eh_bus_reset_done; | 881 | goto eh_bus_reset_done; |
923 | 882 | ||
924 | /* Waiting for our command in done_queue to be returned to OS.*/ | 883 | /* Flush outstanding commands. */ |
925 | if (cmd->device->host->eh_active) | 884 | if (!qla2x00_eh_wait_for_pending_commands(ha)) |
926 | if (!qla2x00_eh_wait_for_pending_commands(ha)) | 885 | ret = FAILED; |
927 | ret = FAILED; | ||
928 | 886 | ||
929 | eh_bus_reset_done: | 887 | eh_bus_reset_done: |
930 | qla_printk(KERN_INFO, ha, "%s: reset %s\n", __func__, | 888 | qla_printk(KERN_INFO, ha, "%s: reset %s\n", __func__, |
@@ -1087,10 +1045,10 @@ qla2xxx_slave_alloc(struct scsi_device *sdev) | |||
1087 | { | 1045 | { |
1088 | struct fc_rport *rport = starget_to_rport(scsi_target(sdev)); | 1046 | struct fc_rport *rport = starget_to_rport(scsi_target(sdev)); |
1089 | 1047 | ||
1090 | if (!rport) | 1048 | if (!rport || fc_remote_port_chkready(rport)) |
1091 | return -ENXIO; | 1049 | return -ENXIO; |
1092 | 1050 | ||
1093 | sdev->hostdata = rport->dd_data; | 1051 | sdev->hostdata = *(fc_port_t **)rport->dd_data; |
1094 | 1052 | ||
1095 | return 0; | 1053 | return 0; |
1096 | } | 1054 | } |
@@ -1682,7 +1640,8 @@ void qla2x00_mark_device_lost(scsi_qla_host_t *ha, fc_port_t *fcport, | |||
1682 | int do_login) | 1640 | int do_login) |
1683 | { | 1641 | { |
1684 | if (atomic_read(&fcport->state) == FCS_ONLINE && fcport->rport) | 1642 | if (atomic_read(&fcport->state) == FCS_ONLINE && fcport->rport) |
1685 | fc_remote_port_block(fcport->rport); | 1643 | schedule_work(&fcport->rport_del_work); |
1644 | |||
1686 | /* | 1645 | /* |
1687 | * We may need to retry the login, so don't change the state of the | 1646 | * We may need to retry the login, so don't change the state of the |
1688 | * port but do the retries. | 1647 | * port but do the retries. |
@@ -1743,7 +1702,7 @@ qla2x00_mark_all_devices_lost(scsi_qla_host_t *ha) | |||
1743 | if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD) | 1702 | if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD) |
1744 | continue; | 1703 | continue; |
1745 | if (atomic_read(&fcport->state) == FCS_ONLINE && fcport->rport) | 1704 | if (atomic_read(&fcport->state) == FCS_ONLINE && fcport->rport) |
1746 | fc_remote_port_block(fcport->rport); | 1705 | schedule_work(&fcport->rport_del_work); |
1747 | atomic_set(&fcport->state, FCS_DEVICE_LOST); | 1706 | atomic_set(&fcport->state, FCS_DEVICE_LOST); |
1748 | } | 1707 | } |
1749 | } | 1708 | } |
@@ -2187,6 +2146,12 @@ qla2x00_do_dpc(void *data) | |||
2187 | ha->host_no)); | 2146 | ha->host_no)); |
2188 | } | 2147 | } |
2189 | 2148 | ||
2149 | if (test_and_clear_bit(LOOP_RESET_NEEDED, &ha->dpc_flags)) { | ||
2150 | DEBUG(printk("scsi(%ld): dpc: sched loop_reset()\n", | ||
2151 | ha->host_no)); | ||
2152 | qla2x00_loop_reset(ha); | ||
2153 | } | ||
2154 | |||
2190 | if (test_and_clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags) && | 2155 | if (test_and_clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags) && |
2191 | (!(test_and_set_bit(RESET_ACTIVE, &ha->dpc_flags)))) { | 2156 | (!(test_and_set_bit(RESET_ACTIVE, &ha->dpc_flags)))) { |
2192 | 2157 | ||
@@ -2488,6 +2453,7 @@ qla2x00_timer(scsi_qla_host_t *ha) | |||
2488 | /* Schedule the DPC routine if needed */ | 2453 | /* Schedule the DPC routine if needed */ |
2489 | if ((test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags) || | 2454 | if ((test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags) || |
2490 | test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags) || | 2455 | test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags) || |
2456 | test_bit(LOOP_RESET_NEEDED, &ha->dpc_flags) || | ||
2491 | start_dpc || | 2457 | start_dpc || |
2492 | test_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags) || | 2458 | test_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags) || |
2493 | test_bit(RESET_MARKER_NEEDED, &ha->dpc_flags) || | 2459 | test_bit(RESET_MARKER_NEEDED, &ha->dpc_flags) || |