diff options
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_isr.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_isr.c | 94 |
1 files changed, 79 insertions, 15 deletions
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index ce42288049b5..6f67a9d4998b 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c | |||
@@ -5,6 +5,7 @@ | |||
5 | * See LICENSE.qla2xxx for copyright and licensing details. | 5 | * See LICENSE.qla2xxx for copyright and licensing details. |
6 | */ | 6 | */ |
7 | #include "qla_def.h" | 7 | #include "qla_def.h" |
8 | #include "qla_target.h" | ||
8 | 9 | ||
9 | #include <linux/delay.h> | 10 | #include <linux/delay.h> |
10 | #include <linux/slab.h> | 11 | #include <linux/slab.h> |
@@ -309,6 +310,28 @@ qla81xx_idc_event(scsi_qla_host_t *vha, uint16_t aen, uint16_t descr) | |||
309 | "IDC failed to post ACK.\n"); | 310 | "IDC failed to post ACK.\n"); |
310 | } | 311 | } |
311 | 312 | ||
313 | #define LS_UNKNOWN 2 | ||
314 | char * | ||
315 | qla2x00_get_link_speed_str(struct qla_hw_data *ha) | ||
316 | { | ||
317 | static char *link_speeds[] = {"1", "2", "?", "4", "8", "16", "10"}; | ||
318 | char *link_speed; | ||
319 | int fw_speed = ha->link_data_rate; | ||
320 | |||
321 | if (IS_QLA2100(ha) || IS_QLA2200(ha)) | ||
322 | link_speed = link_speeds[0]; | ||
323 | else if (fw_speed == 0x13) | ||
324 | link_speed = link_speeds[6]; | ||
325 | else { | ||
326 | link_speed = link_speeds[LS_UNKNOWN]; | ||
327 | if (fw_speed < 6) | ||
328 | link_speed = | ||
329 | link_speeds[fw_speed]; | ||
330 | } | ||
331 | |||
332 | return link_speed; | ||
333 | } | ||
334 | |||
312 | /** | 335 | /** |
313 | * qla2x00_async_event() - Process aynchronous events. | 336 | * qla2x00_async_event() - Process aynchronous events. |
314 | * @ha: SCSI driver HA context | 337 | * @ha: SCSI driver HA context |
@@ -317,9 +340,6 @@ qla81xx_idc_event(scsi_qla_host_t *vha, uint16_t aen, uint16_t descr) | |||
317 | void | 340 | void |
318 | qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb) | 341 | qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb) |
319 | { | 342 | { |
320 | #define LS_UNKNOWN 2 | ||
321 | static char *link_speeds[] = { "1", "2", "?", "4", "8", "16", "10" }; | ||
322 | char *link_speed; | ||
323 | uint16_t handle_cnt; | 343 | uint16_t handle_cnt; |
324 | uint16_t cnt, mbx; | 344 | uint16_t cnt, mbx; |
325 | uint32_t handles[5]; | 345 | uint32_t handles[5]; |
@@ -454,8 +474,8 @@ skip_rio: | |||
454 | case MBA_WAKEUP_THRES: /* Request Queue Wake-up */ | 474 | case MBA_WAKEUP_THRES: /* Request Queue Wake-up */ |
455 | ql_dbg(ql_dbg_async, vha, 0x5008, | 475 | ql_dbg(ql_dbg_async, vha, 0x5008, |
456 | "Asynchronous WAKEUP_THRES.\n"); | 476 | "Asynchronous WAKEUP_THRES.\n"); |
457 | break; | ||
458 | 477 | ||
478 | break; | ||
459 | case MBA_LIP_OCCURRED: /* Loop Initialization Procedure */ | 479 | case MBA_LIP_OCCURRED: /* Loop Initialization Procedure */ |
460 | ql_dbg(ql_dbg_async, vha, 0x5009, | 480 | ql_dbg(ql_dbg_async, vha, 0x5009, |
461 | "LIP occurred (%x).\n", mb[1]); | 481 | "LIP occurred (%x).\n", mb[1]); |
@@ -479,20 +499,14 @@ skip_rio: | |||
479 | break; | 499 | break; |
480 | 500 | ||
481 | case MBA_LOOP_UP: /* Loop Up Event */ | 501 | case MBA_LOOP_UP: /* Loop Up Event */ |
482 | if (IS_QLA2100(ha) || IS_QLA2200(ha)) { | 502 | if (IS_QLA2100(ha) || IS_QLA2200(ha)) |
483 | link_speed = link_speeds[0]; | ||
484 | ha->link_data_rate = PORT_SPEED_1GB; | 503 | ha->link_data_rate = PORT_SPEED_1GB; |
485 | } else { | 504 | else |
486 | link_speed = link_speeds[LS_UNKNOWN]; | ||
487 | if (mb[1] < 6) | ||
488 | link_speed = link_speeds[mb[1]]; | ||
489 | else if (mb[1] == 0x13) | ||
490 | link_speed = link_speeds[6]; | ||
491 | ha->link_data_rate = mb[1]; | 505 | ha->link_data_rate = mb[1]; |
492 | } | ||
493 | 506 | ||
494 | ql_dbg(ql_dbg_async, vha, 0x500a, | 507 | ql_dbg(ql_dbg_async, vha, 0x500a, |
495 | "LOOP UP detected (%s Gbps).\n", link_speed); | 508 | "LOOP UP detected (%s Gbps).\n", |
509 | qla2x00_get_link_speed_str(ha)); | ||
496 | 510 | ||
497 | vha->flags.management_server_logged_in = 0; | 511 | vha->flags.management_server_logged_in = 0; |
498 | qla2x00_post_aen_work(vha, FCH_EVT_LINKUP, ha->link_data_rate); | 512 | qla2x00_post_aen_work(vha, FCH_EVT_LINKUP, ha->link_data_rate); |
@@ -638,6 +652,8 @@ skip_rio: | |||
638 | ql_dbg(ql_dbg_async, vha, 0x5010, | 652 | ql_dbg(ql_dbg_async, vha, 0x5010, |
639 | "Port unavailable %04x %04x %04x.\n", | 653 | "Port unavailable %04x %04x %04x.\n", |
640 | mb[1], mb[2], mb[3]); | 654 | mb[1], mb[2], mb[3]); |
655 | ql_log(ql_log_warn, vha, 0x505e, | ||
656 | "Link is offline.\n"); | ||
641 | 657 | ||
642 | if (atomic_read(&vha->loop_state) != LOOP_DOWN) { | 658 | if (atomic_read(&vha->loop_state) != LOOP_DOWN) { |
643 | atomic_set(&vha->loop_state, LOOP_DOWN); | 659 | atomic_set(&vha->loop_state, LOOP_DOWN); |
@@ -670,12 +686,17 @@ skip_rio: | |||
670 | ql_dbg(ql_dbg_async, vha, 0x5011, | 686 | ql_dbg(ql_dbg_async, vha, 0x5011, |
671 | "Asynchronous PORT UPDATE ignored %04x/%04x/%04x.\n", | 687 | "Asynchronous PORT UPDATE ignored %04x/%04x/%04x.\n", |
672 | mb[1], mb[2], mb[3]); | 688 | mb[1], mb[2], mb[3]); |
689 | |||
690 | qlt_async_event(mb[0], vha, mb); | ||
673 | break; | 691 | break; |
674 | } | 692 | } |
675 | 693 | ||
676 | ql_dbg(ql_dbg_async, vha, 0x5012, | 694 | ql_dbg(ql_dbg_async, vha, 0x5012, |
677 | "Port database changed %04x %04x %04x.\n", | 695 | "Port database changed %04x %04x %04x.\n", |
678 | mb[1], mb[2], mb[3]); | 696 | mb[1], mb[2], mb[3]); |
697 | ql_log(ql_log_warn, vha, 0x505f, | ||
698 | "Link is operational (%s Gbps).\n", | ||
699 | qla2x00_get_link_speed_str(ha)); | ||
679 | 700 | ||
680 | /* | 701 | /* |
681 | * Mark all devices as missing so we will login again. | 702 | * Mark all devices as missing so we will login again. |
@@ -684,8 +705,13 @@ skip_rio: | |||
684 | 705 | ||
685 | qla2x00_mark_all_devices_lost(vha, 1); | 706 | qla2x00_mark_all_devices_lost(vha, 1); |
686 | 707 | ||
708 | if (vha->vp_idx == 0 && !qla_ini_mode_enabled(vha)) | ||
709 | set_bit(SCR_PENDING, &vha->dpc_flags); | ||
710 | |||
687 | set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); | 711 | set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); |
688 | set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags); | 712 | set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags); |
713 | |||
714 | qlt_async_event(mb[0], vha, mb); | ||
689 | break; | 715 | break; |
690 | 716 | ||
691 | case MBA_RSCN_UPDATE: /* State Change Registration */ | 717 | case MBA_RSCN_UPDATE: /* State Change Registration */ |
@@ -807,6 +833,8 @@ skip_rio: | |||
807 | mb[0], mb[1], mb[2], mb[3]); | 833 | mb[0], mb[1], mb[2], mb[3]); |
808 | } | 834 | } |
809 | 835 | ||
836 | qlt_async_event(mb[0], vha, mb); | ||
837 | |||
810 | if (!vha->vp_idx && ha->num_vhosts) | 838 | if (!vha->vp_idx && ha->num_vhosts) |
811 | qla2x00_alert_all_vps(rsp, mb); | 839 | qla2x00_alert_all_vps(rsp, mb); |
812 | } | 840 | } |
@@ -1172,6 +1200,9 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req, | |||
1172 | } else if (iop[0] & BIT_5) | 1200 | } else if (iop[0] & BIT_5) |
1173 | fcport->port_type = FCT_INITIATOR; | 1201 | fcport->port_type = FCT_INITIATOR; |
1174 | 1202 | ||
1203 | if (iop[0] & BIT_7) | ||
1204 | fcport->flags |= FCF_CONF_COMP_SUPPORTED; | ||
1205 | |||
1175 | if (logio->io_parameter[7] || logio->io_parameter[8]) | 1206 | if (logio->io_parameter[7] || logio->io_parameter[8]) |
1176 | fcport->supported_classes |= FC_COS_CLASS2; | 1207 | fcport->supported_classes |= FC_COS_CLASS2; |
1177 | if (logio->io_parameter[9] || logio->io_parameter[10]) | 1208 | if (logio->io_parameter[9] || logio->io_parameter[10]) |
@@ -1986,6 +2017,9 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha, | |||
1986 | 2017 | ||
1987 | if (pkt->entry_status != 0) { | 2018 | if (pkt->entry_status != 0) { |
1988 | qla2x00_error_entry(vha, rsp, (sts_entry_t *) pkt); | 2019 | qla2x00_error_entry(vha, rsp, (sts_entry_t *) pkt); |
2020 | |||
2021 | (void)qlt_24xx_process_response_error(vha, pkt); | ||
2022 | |||
1989 | ((response_t *)pkt)->signature = RESPONSE_PROCESSED; | 2023 | ((response_t *)pkt)->signature = RESPONSE_PROCESSED; |
1990 | wmb(); | 2024 | wmb(); |
1991 | continue; | 2025 | continue; |
@@ -2016,6 +2050,14 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha, | |||
2016 | case ELS_IOCB_TYPE: | 2050 | case ELS_IOCB_TYPE: |
2017 | qla24xx_els_ct_entry(vha, rsp->req, pkt, ELS_IOCB_TYPE); | 2051 | qla24xx_els_ct_entry(vha, rsp->req, pkt, ELS_IOCB_TYPE); |
2018 | break; | 2052 | break; |
2053 | case ABTS_RECV_24XX: | ||
2054 | /* ensure that the ATIO queue is empty */ | ||
2055 | qlt_24xx_process_atio_queue(vha); | ||
2056 | case ABTS_RESP_24XX: | ||
2057 | case CTIO_TYPE7: | ||
2058 | case NOTIFY_ACK_TYPE: | ||
2059 | qlt_response_pkt_all_vps(vha, (response_t *)pkt); | ||
2060 | break; | ||
2019 | case MARKER_TYPE: | 2061 | case MARKER_TYPE: |
2020 | /* Do nothing in this case, this check is to prevent it | 2062 | /* Do nothing in this case, this check is to prevent it |
2021 | * from falling into default case | 2063 | * from falling into default case |
@@ -2168,6 +2210,13 @@ qla24xx_intr_handler(int irq, void *dev_id) | |||
2168 | case 0x14: | 2210 | case 0x14: |
2169 | qla24xx_process_response_queue(vha, rsp); | 2211 | qla24xx_process_response_queue(vha, rsp); |
2170 | break; | 2212 | break; |
2213 | case 0x1C: /* ATIO queue updated */ | ||
2214 | qlt_24xx_process_atio_queue(vha); | ||
2215 | break; | ||
2216 | case 0x1D: /* ATIO and response queues updated */ | ||
2217 | qlt_24xx_process_atio_queue(vha); | ||
2218 | qla24xx_process_response_queue(vha, rsp); | ||
2219 | break; | ||
2171 | default: | 2220 | default: |
2172 | ql_dbg(ql_dbg_async, vha, 0x504f, | 2221 | ql_dbg(ql_dbg_async, vha, 0x504f, |
2173 | "Unrecognized interrupt type (%d).\n", stat * 0xff); | 2222 | "Unrecognized interrupt type (%d).\n", stat * 0xff); |
@@ -2312,6 +2361,13 @@ qla24xx_msix_default(int irq, void *dev_id) | |||
2312 | case 0x14: | 2361 | case 0x14: |
2313 | qla24xx_process_response_queue(vha, rsp); | 2362 | qla24xx_process_response_queue(vha, rsp); |
2314 | break; | 2363 | break; |
2364 | case 0x1C: /* ATIO queue updated */ | ||
2365 | qlt_24xx_process_atio_queue(vha); | ||
2366 | break; | ||
2367 | case 0x1D: /* ATIO and response queues updated */ | ||
2368 | qlt_24xx_process_atio_queue(vha); | ||
2369 | qla24xx_process_response_queue(vha, rsp); | ||
2370 | break; | ||
2315 | default: | 2371 | default: |
2316 | ql_dbg(ql_dbg_async, vha, 0x5051, | 2372 | ql_dbg(ql_dbg_async, vha, 0x5051, |
2317 | "Unrecognized interrupt type (%d).\n", stat & 0xff); | 2373 | "Unrecognized interrupt type (%d).\n", stat & 0xff); |
@@ -2564,7 +2620,15 @@ void | |||
2564 | qla2x00_free_irqs(scsi_qla_host_t *vha) | 2620 | qla2x00_free_irqs(scsi_qla_host_t *vha) |
2565 | { | 2621 | { |
2566 | struct qla_hw_data *ha = vha->hw; | 2622 | struct qla_hw_data *ha = vha->hw; |
2567 | struct rsp_que *rsp = ha->rsp_q_map[0]; | 2623 | struct rsp_que *rsp; |
2624 | |||
2625 | /* | ||
2626 | * We need to check that ha->rsp_q_map is valid in case we are called | ||
2627 | * from a probe failure context. | ||
2628 | */ | ||
2629 | if (!ha->rsp_q_map || !ha->rsp_q_map[0]) | ||
2630 | return; | ||
2631 | rsp = ha->rsp_q_map[0]; | ||
2568 | 2632 | ||
2569 | if (ha->flags.msix_enabled) | 2633 | if (ha->flags.msix_enabled) |
2570 | qla24xx_disable_msix(ha); | 2634 | qla24xx_disable_msix(ha); |