aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/qla2xxx/qla_bsg.c79
-rw-r--r--drivers/scsi/qla2xxx/qla_bsg.h2
-rw-r--r--drivers/scsi/qla2xxx/qla_dbg.c5
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h1
-rw-r--r--drivers/scsi/qla2xxx/qla_gbl.h2
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c10
-rw-r--r--drivers/scsi/qla2xxx/qla_isr.c27
-rw-r--r--drivers/scsi/qla2xxx/qla_nx.c2
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c23
9 files changed, 87 insertions, 64 deletions
diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c
index 6da13e26ccac..581592fc63e7 100644
--- a/drivers/scsi/qla2xxx/qla_bsg.c
+++ b/drivers/scsi/qla2xxx/qla_bsg.c
@@ -530,13 +530,13 @@ done_unmap_sg:
530done: 530done:
531 return rval; 531 return rval;
532} 532}
533 533/*
534/* Set the port configuration to enable the 534 * Set the port configuration to enable the internal or external loopback
535 * internal loopback on ISP81XX 535 * depending on the loopback mode.
536 */ 536 */
537static inline int 537static inline int
538qla81xx_set_internal_loopback(scsi_qla_host_t *vha, uint16_t *config, 538qla81xx_set_loopback_mode(scsi_qla_host_t *vha, uint16_t *config,
539 uint16_t *new_config) 539 uint16_t *new_config, uint16_t mode)
540{ 540{
541 int ret = 0; 541 int ret = 0;
542 int rval = 0; 542 int rval = 0;
@@ -545,8 +545,14 @@ qla81xx_set_internal_loopback(scsi_qla_host_t *vha, uint16_t *config,
545 if (!IS_QLA81XX(ha) && !IS_QLA8031(ha)) 545 if (!IS_QLA81XX(ha) && !IS_QLA8031(ha))
546 goto done_set_internal; 546 goto done_set_internal;
547 547
548 new_config[0] = config[0] | (ENABLE_INTERNAL_LOOPBACK << 1); 548 if (mode == INTERNAL_LOOPBACK)
549 memcpy(&new_config[1], &config[1], sizeof(uint16_t) * 3) ; 549 new_config[0] = config[0] | (ENABLE_INTERNAL_LOOPBACK << 1);
550 else if (mode == EXTERNAL_LOOPBACK)
551 new_config[0] = config[0] | (ENABLE_EXTERNAL_LOOPBACK << 1);
552 ql_dbg(ql_dbg_user, vha, 0x70be,
553 "new_config[0]=%02x\n", (new_config[0] & INTERNAL_LOOPBACK_MASK));
554
555 memcpy(&new_config[1], &config[1], sizeof(uint16_t) * 3);
550 556
551 ha->notify_dcbx_comp = 1; 557 ha->notify_dcbx_comp = 1;
552 ret = qla81xx_set_port_config(vha, new_config); 558 ret = qla81xx_set_port_config(vha, new_config);
@@ -572,11 +578,9 @@ done_set_internal:
572 return rval; 578 return rval;
573} 579}
574 580
575/* Set the port configuration to disable the 581/* Disable loopback mode */
576 * internal loopback on ISP81XX
577 */
578static inline int 582static inline int
579qla81xx_reset_internal_loopback(scsi_qla_host_t *vha, uint16_t *config, 583qla81xx_reset_loopback_mode(scsi_qla_host_t *vha, uint16_t *config,
580 int wait) 584 int wait)
581{ 585{
582 int ret = 0; 586 int ret = 0;
@@ -589,8 +593,12 @@ qla81xx_reset_internal_loopback(scsi_qla_host_t *vha, uint16_t *config,
589 593
590 memset(new_config, 0 , sizeof(new_config)); 594 memset(new_config, 0 , sizeof(new_config));
591 if ((config[0] & INTERNAL_LOOPBACK_MASK) >> 1 == 595 if ((config[0] & INTERNAL_LOOPBACK_MASK) >> 1 ==
592 ENABLE_INTERNAL_LOOPBACK) { 596 ENABLE_INTERNAL_LOOPBACK ||
597 (config[0] & INTERNAL_LOOPBACK_MASK) >> 1 ==
598 ENABLE_EXTERNAL_LOOPBACK) {
593 new_config[0] = config[0] & ~INTERNAL_LOOPBACK_MASK; 599 new_config[0] = config[0] & ~INTERNAL_LOOPBACK_MASK;
600 ql_dbg(ql_dbg_user, vha, 0x70bf, "new_config[0]=%02x\n",
601 (new_config[0] & INTERNAL_LOOPBACK_MASK));
594 memcpy(&new_config[1], &config[1], sizeof(uint16_t) * 3) ; 602 memcpy(&new_config[1], &config[1], sizeof(uint16_t) * 3) ;
595 603
596 ha->notify_dcbx_comp = wait; 604 ha->notify_dcbx_comp = wait;
@@ -707,7 +715,8 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
707 715
708 elreq.options = bsg_job->request->rqst_data.h_vendor.vendor_cmd[1]; 716 elreq.options = bsg_job->request->rqst_data.h_vendor.vendor_cmd[1];
709 717
710 if ((ha->current_topology == ISP_CFG_F || 718 if (atomic_read(&vha->loop_state) == LOOP_READY &&
719 (ha->current_topology == ISP_CFG_F ||
711 ((IS_QLA81XX(ha) || IS_QLA8031(ha)) && 720 ((IS_QLA81XX(ha) || IS_QLA8031(ha)) &&
712 le32_to_cpu(*(uint32_t *)req_data) == ELS_OPCODE_BYTE 721 le32_to_cpu(*(uint32_t *)req_data) == ELS_OPCODE_BYTE
713 && req_data_len == MAX_ELS_FRAME_PAYLOAD)) && 722 && req_data_len == MAX_ELS_FRAME_PAYLOAD)) &&
@@ -729,30 +738,24 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
729 goto done_free_dma_req; 738 goto done_free_dma_req;
730 } 739 }
731 740
732 if (elreq.options != EXTERNAL_LOOPBACK) { 741 ql_dbg(ql_dbg_user, vha, 0x70c0,
733 ql_dbg(ql_dbg_user, vha, 0x7020, 742 "elreq.options=%04x\n", elreq.options);
734 "Internal: current port config = %x\n", 743
735 config[0]); 744 if (elreq.options == EXTERNAL_LOOPBACK)
736 if (qla81xx_set_internal_loopback(vha, config, 745 if (IS_QLA8031(ha))
737 new_config)) { 746 rval = qla81xx_set_loopback_mode(vha,
738 ql_log(ql_log_warn, vha, 0x7024, 747 config, new_config, elreq.options);
739 "Internal loopback failed.\n"); 748 else
740 bsg_job->reply->result = 749 rval = qla81xx_reset_loopback_mode(vha,
741 (DID_ERROR << 16); 750 config, 1);
742 rval = -EPERM; 751 else
743 goto done_free_dma_req; 752 rval = qla81xx_set_loopback_mode(vha, config,
744 } 753 new_config, elreq.options);
745 } else { 754
746 /* For external loopback to work 755 if (rval) {
747 * ensure internal loopback is disabled 756 bsg_job->reply->result = (DID_ERROR << 16);
748 */ 757 rval = -EPERM;
749 if (qla81xx_reset_internal_loopback(vha, 758 goto done_free_dma_req;
750 config, 1)) {
751 bsg_job->reply->result =
752 (DID_ERROR << 16);
753 rval = -EPERM;
754 goto done_free_dma_req;
755 }
756 } 759 }
757 760
758 type = "FC_BSG_HST_VENDOR_LOOPBACK"; 761 type = "FC_BSG_HST_VENDOR_LOOPBACK";
@@ -766,7 +769,7 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
766 /* Revert back to original port config 769 /* Revert back to original port config
767 * Also clear internal loopback 770 * Also clear internal loopback
768 */ 771 */
769 qla81xx_reset_internal_loopback(vha, 772 qla81xx_reset_loopback_mode(vha,
770 new_config, 0); 773 new_config, 0);
771 } 774 }
772 775
diff --git a/drivers/scsi/qla2xxx/qla_bsg.h b/drivers/scsi/qla2xxx/qla_bsg.h
index 1875ee10e589..cd63ec79abcf 100644
--- a/drivers/scsi/qla2xxx/qla_bsg.h
+++ b/drivers/scsi/qla2xxx/qla_bsg.h
@@ -50,8 +50,10 @@
50#define INT_DEF_LB_ECHO_CMD 1 50#define INT_DEF_LB_ECHO_CMD 1
51 51
52/* Loopback related definations */ 52/* Loopback related definations */
53#define INTERNAL_LOOPBACK 0xF1
53#define EXTERNAL_LOOPBACK 0xF2 54#define EXTERNAL_LOOPBACK 0xF2
54#define ENABLE_INTERNAL_LOOPBACK 0x02 55#define ENABLE_INTERNAL_LOOPBACK 0x02
56#define ENABLE_EXTERNAL_LOOPBACK 0x04
55#define INTERNAL_LOOPBACK_MASK 0x000E 57#define INTERNAL_LOOPBACK_MASK 0x000E
56#define MAX_ELS_FRAME_PAYLOAD 252 58#define MAX_ELS_FRAME_PAYLOAD 252
57#define ELS_OPCODE_BYTE 0x10 59#define ELS_OPCODE_BYTE 0x10
diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c
index 6012805e0690..647ddfaf16f8 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.c
+++ b/drivers/scsi/qla2xxx/qla_dbg.c
@@ -18,7 +18,7 @@
18 * | Device Discovery | 0x2087 | 0x2020-0x2022 | 18 * | Device Discovery | 0x2087 | 0x2020-0x2022 |
19 * | Queue Command and IO tracing | 0x3030 | 0x3006,0x3008 | 19 * | Queue Command and IO tracing | 0x3030 | 0x3006,0x3008 |
20 * | | | 0x302d-0x302e | 20 * | | | 0x302d-0x302e |
21 * | DPC Thread | 0x401c | 0x4002,0x4013 | 21 * | DPC Thread | 0x401d | 0x4002,0x4013 |
22 * | Async Events | 0x5071 | 0x502b-0x502f | 22 * | Async Events | 0x5071 | 0x502b-0x502f |
23 * | | | 0x5047,0x5052 | 23 * | | | 0x5047,0x5052 |
24 * | Timer Routines | 0x6011 | | 24 * | Timer Routines | 0x6011 | |
@@ -29,12 +29,11 @@
29 * | | | 0x70a5,0x70a6, | 29 * | | | 0x70a5,0x70a6, |
30 * | | | 0x70a8,0x70ab, | 30 * | | | 0x70a8,0x70ab, |
31 * | | | 0x70ad-0x70ae | 31 * | | | 0x70ad-0x70ae |
32 * | | | 0x70be-70c0 |
33 * | Task Management | 0x803c | 0x8025-0x8026 | 32 * | Task Management | 0x803c | 0x8025-0x8026 |
34 * | | | 0x800b,0x8039 | 33 * | | | 0x800b,0x8039 |
35 * | AER/EEH | 0x9011 | | 34 * | AER/EEH | 0x9011 | |
36 * | Virtual Port | 0xa007 | | 35 * | Virtual Port | 0xa007 | |
37 * | ISP82XX Specific | 0xb084 | 0xb002 | 36 * | ISP82XX Specific | 0xb084 | 0xb002,0xb024 |
38 * | | | 0xb082,0xb083 | 37 * | | | 0xb082,0xb083 |
39 * | MultiQ | 0xc00c | | 38 * | MultiQ | 0xc00c | |
40 * | Misc | 0xd010 | | 39 * | Misc | 0xd010 | |
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 874c1cd483e0..d7520082f93d 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -799,6 +799,7 @@ typedef struct {
799#define MBC_SEND_RNFT_ELS 0x5e /* Send RNFT ELS request */ 799#define MBC_SEND_RNFT_ELS 0x5e /* Send RNFT ELS request */
800#define MBC_GET_LINK_PRIV_STATS 0x6d /* Get link & private data. */ 800#define MBC_GET_LINK_PRIV_STATS 0x6d /* Get link & private data. */
801#define MBC_SET_VENDOR_ID 0x76 /* Set Vendor ID. */ 801#define MBC_SET_VENDOR_ID 0x76 /* Set Vendor ID. */
802#define MBC_PORT_RESET 0x120 /* Port Reset */
802#define MBC_SET_PORT_CONFIG 0x122 /* Set port configuration */ 803#define MBC_SET_PORT_CONFIG 0x122 /* Set port configuration */
803#define MBC_GET_PORT_CONFIG 0x123 /* Get port configuration */ 804#define MBC_GET_PORT_CONFIG 0x123 /* Get port configuration */
804 805
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index b808b8e47d45..8d77e5251af3 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -48,7 +48,7 @@ extern void qla2x00_update_fcports(scsi_qla_host_t *);
48 48
49extern int qla2x00_abort_isp(scsi_qla_host_t *); 49extern int qla2x00_abort_isp(scsi_qla_host_t *);
50extern void qla2x00_abort_isp_cleanup(scsi_qla_host_t *); 50extern void qla2x00_abort_isp_cleanup(scsi_qla_host_t *);
51extern void qla82xx_quiescent_state_cleanup(scsi_qla_host_t *); 51extern void qla2x00_quiesce_io(scsi_qla_host_t *);
52 52
53extern void qla2x00_update_fcport(scsi_qla_host_t *, fc_port_t *); 53extern void qla2x00_update_fcport(scsi_qla_host_t *, fc_port_t *);
54 54
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 0ea15b781adf..37eeaa84e62a 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -4165,7 +4165,7 @@ qla2xxx_mctp_dump(scsi_qla_host_t *vha)
4165} 4165}
4166 4166
4167/* 4167/*
4168* qla82xx_quiescent_state_cleanup 4168* qla2x00_quiesce_io
4169* Description: This function will block the new I/Os 4169* Description: This function will block the new I/Os
4170* Its not aborting any I/Os as context 4170* Its not aborting any I/Os as context
4171* is not destroyed during quiescence 4171* is not destroyed during quiescence
@@ -4173,20 +4173,20 @@ qla2xxx_mctp_dump(scsi_qla_host_t *vha)
4173* return : void 4173* return : void
4174*/ 4174*/
4175void 4175void
4176qla82xx_quiescent_state_cleanup(scsi_qla_host_t *vha) 4176qla2x00_quiesce_io(scsi_qla_host_t *vha)
4177{ 4177{
4178 struct qla_hw_data *ha = vha->hw; 4178 struct qla_hw_data *ha = vha->hw;
4179 struct scsi_qla_host *vp; 4179 struct scsi_qla_host *vp;
4180 4180
4181 ql_dbg(ql_dbg_p3p, vha, 0xb002, 4181 ql_dbg(ql_dbg_dpc, vha, 0x401d,
4182 "Performing ISP error recovery - ha=%p.\n", ha); 4182 "Quiescing I/O - ha=%p.\n", ha);
4183 4183
4184 atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME); 4184 atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME);
4185 if (atomic_read(&vha->loop_state) != LOOP_DOWN) { 4185 if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
4186 atomic_set(&vha->loop_state, LOOP_DOWN); 4186 atomic_set(&vha->loop_state, LOOP_DOWN);
4187 qla2x00_mark_all_devices_lost(vha, 0); 4187 qla2x00_mark_all_devices_lost(vha, 0);
4188 list_for_each_entry(vp, &ha->vp_list, list) 4188 list_for_each_entry(vp, &ha->vp_list, list)
4189 qla2x00_mark_all_devices_lost(vha, 0); 4189 qla2x00_mark_all_devices_lost(vp, 0);
4190 } else { 4190 } else {
4191 if (!atomic_read(&vha->loop_down_timer)) 4191 if (!atomic_read(&vha->loop_down_timer))
4192 atomic_set(&vha->loop_down_timer, 4192 atomic_set(&vha->loop_down_timer,
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index 1222e937a5fe..2b05af1838f4 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -295,14 +295,16 @@ qla81xx_idc_event(scsi_qla_host_t *vha, uint16_t aen, uint16_t descr)
295 event[aen & 0xff], mb[0], mb[1], mb[2], mb[3], 295 event[aen & 0xff], mb[0], mb[1], mb[2], mb[3],
296 mb[4], mb[5], mb[6]); 296 mb[4], mb[5], mb[6]);
297 297
298 /* Acknowledgement needed? [Notify && non-zero timeout]. */ 298 if (IS_QLA81XX(vha->hw)) {
299 timeout = (descr >> 8) & 0xf; 299 /* Acknowledgement needed? [Notify && non-zero timeout]. */
300 if (aen != MBA_IDC_NOTIFY || !timeout) 300 timeout = (descr >> 8) & 0xf;
301 return; 301 if (aen != MBA_IDC_NOTIFY || !timeout)
302 return;
302 303
303 ql_dbg(ql_dbg_async, vha, 0x5022, 304 ql_dbg(ql_dbg_async, vha, 0x5022,
304 "%lu Inter-Driver Communication %s -- ACK timeout=%d.\n", 305 "%lu Inter-Driver Communication %s -- ACK timeout=%d.\n",
305 vha->host_no, event[aen & 0xff], timeout); 306 vha->host_no, event[aen & 0xff], timeout);
307 }
306 308
307 rval = qla2x00_post_idc_ack_work(vha, mb); 309 rval = qla2x00_post_idc_ack_work(vha, mb);
308 if (rval != QLA_SUCCESS) 310 if (rval != QLA_SUCCESS)
@@ -982,8 +984,17 @@ skip_rio:
982 "FCF Configuration Error -- %04x %04x %04x.\n", 984 "FCF Configuration Error -- %04x %04x %04x.\n",
983 mb[1], mb[2], mb[3]); 985 mb[1], mb[2], mb[3]);
984 break; 986 break;
985 case MBA_IDC_COMPLETE:
986 case MBA_IDC_NOTIFY: 987 case MBA_IDC_NOTIFY:
988 /* See if we need to quiesce any I/O */
989 if (IS_QLA8031(vha->hw))
990 if ((mb[2] & 0x7fff) == MBC_PORT_RESET ||
991 (mb[2] & 0x7fff) == MBC_SET_PORT_CONFIG) {
992 set_bit(ISP_QUIESCE_NEEDED, &vha->dpc_flags);
993 /* Ack that we have quiesced I/O */
994 qla81xx_idc_event(vha, mb[0], mb[1]);
995 qla2xxx_wake_dpc(vha);
996 }
997 case MBA_IDC_COMPLETE:
987 case MBA_IDC_TIME_EXT: 998 case MBA_IDC_TIME_EXT:
988 if (IS_QLA81XX(vha->hw)) 999 if (IS_QLA81XX(vha->hw))
989 qla81xx_idc_event(vha, mb[0], mb[1]); 1000 qla81xx_idc_event(vha, mb[0], mb[1]);
diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c
index 75cdf200f453..9f4dcf5c8e4a 100644
--- a/drivers/scsi/qla2xxx/qla_nx.c
+++ b/drivers/scsi/qla2xxx/qla_nx.c
@@ -2939,7 +2939,7 @@ qla82xx_need_qsnt_handler(scsi_qla_host_t *vha)
2939 2939
2940 if (vha->flags.online) { 2940 if (vha->flags.online) {
2941 /*Block any further I/O and wait for pending cmnds to complete*/ 2941 /*Block any further I/O and wait for pending cmnds to complete*/
2942 qla82xx_quiescent_state_cleanup(vha); 2942 qla2x00_quiesce_io(vha);
2943 } 2943 }
2944 2944
2945 /* Set the quiescence ready bit */ 2945 /* Set the quiescence ready bit */
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 6250e5761d35..e68fe1281645 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -4513,14 +4513,21 @@ qla2x00_do_dpc(void *data)
4513 if (test_bit(ISP_QUIESCE_NEEDED, &base_vha->dpc_flags)) { 4513 if (test_bit(ISP_QUIESCE_NEEDED, &base_vha->dpc_flags)) {
4514 ql_dbg(ql_dbg_dpc, base_vha, 0x4009, 4514 ql_dbg(ql_dbg_dpc, base_vha, 0x4009,
4515 "Quiescence mode scheduled.\n"); 4515 "Quiescence mode scheduled.\n");
4516 qla82xx_device_state_handler(base_vha); 4516 if (IS_QLA82XX(ha)) {
4517 clear_bit(ISP_QUIESCE_NEEDED, &base_vha->dpc_flags); 4517 qla82xx_device_state_handler(base_vha);
4518 if (!ha->flags.quiesce_owner) { 4518 clear_bit(ISP_QUIESCE_NEEDED,
4519 qla2x00_perform_loop_resync(base_vha); 4519 &base_vha->dpc_flags);
4520 4520 if (!ha->flags.quiesce_owner) {
4521 qla82xx_idc_lock(ha); 4521 qla2x00_perform_loop_resync(base_vha);
4522 qla82xx_clear_qsnt_ready(base_vha); 4522
4523 qla82xx_idc_unlock(ha); 4523 qla82xx_idc_lock(ha);
4524 qla82xx_clear_qsnt_ready(base_vha);
4525 qla82xx_idc_unlock(ha);
4526 }
4527 } else {
4528 clear_bit(ISP_QUIESCE_NEEDED,
4529 &base_vha->dpc_flags);
4530 qla2x00_quiesce_io(base_vha);
4524 } 4531 }
4525 ql_dbg(ql_dbg_dpc, base_vha, 0x400a, 4532 ql_dbg(ql_dbg_dpc, base_vha, 0x400a,
4526 "Quiescence mode end.\n"); 4533 "Quiescence mode end.\n");