diff options
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_isr.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_isr.c | 109 |
1 files changed, 92 insertions, 17 deletions
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index f79844ce7122..6f67a9d4998b 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -5,6 +5,7 @@ * See LICENSE.qla2xxx for copyright and licensing details. */ #include "qla_def.h" +#include "qla_target.h" #include <linux/delay.h> #include <linux/slab.h> @@ -309,6 +310,28 @@ qla81xx_idc_event(scsi_qla_host_t *vha, uint16_t aen, uint16_t descr) "IDC failed to post ACK.\n"); } +#define LS_UNKNOWN 2 +char * +qla2x00_get_link_speed_str(struct qla_hw_data *ha) +{ + static char *link_speeds[] = {"1", "2", "?", "4", "8", "16", "10"}; + char *link_speed; + int fw_speed = ha->link_data_rate; + + if (IS_QLA2100(ha) || IS_QLA2200(ha)) + link_speed = link_speeds[0]; + else if (fw_speed == 0x13) + link_speed = link_speeds[6]; + else { + link_speed = link_speeds[LS_UNKNOWN]; + if (fw_speed < 6) + link_speed = + link_speeds[fw_speed]; + } + + return link_speed; +} + /** * qla2x00_async_event() - Process aynchronous events. * @ha: SCSI driver HA context @@ -317,9 +340,6 @@ qla81xx_idc_event(scsi_qla_host_t *vha, uint16_t aen, uint16_t descr) void qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb) { -#define LS_UNKNOWN 2 - static char *link_speeds[] = { "1", "2", "?", "4", "8", "16", "10" }; - char *link_speed; uint16_t handle_cnt; uint16_t cnt, mbx; uint32_t handles[5]; @@ -454,8 +474,8 @@ skip_rio: case MBA_WAKEUP_THRES: /* Request Queue Wake-up */ ql_dbg(ql_dbg_async, vha, 0x5008, "Asynchronous WAKEUP_THRES.\n"); - break; + break; case MBA_LIP_OCCURRED: /* Loop Initialization Procedure */ ql_dbg(ql_dbg_async, vha, 0x5009, "LIP occurred (%x).\n", mb[1]); @@ -479,20 +499,14 @@ skip_rio: break; case MBA_LOOP_UP: /* Loop Up Event */ - if (IS_QLA2100(ha) || IS_QLA2200(ha)) { - link_speed = link_speeds[0]; + if (IS_QLA2100(ha) || IS_QLA2200(ha)) ha->link_data_rate = PORT_SPEED_1GB; - } else { - link_speed = link_speeds[LS_UNKNOWN]; - if (mb[1] < 6) - link_speed = link_speeds[mb[1]]; - else if (mb[1] == 0x13) - link_speed = link_speeds[6]; + else ha->link_data_rate = mb[1]; - } ql_dbg(ql_dbg_async, vha, 0x500a, - "LOOP UP detected (%s Gbps).\n", link_speed); + "LOOP UP detected (%s Gbps).\n", + qla2x00_get_link_speed_str(ha)); vha->flags.management_server_logged_in = 0; qla2x00_post_aen_work(vha, FCH_EVT_LINKUP, ha->link_data_rate); @@ -638,6 +652,8 @@ skip_rio: ql_dbg(ql_dbg_async, vha, 0x5010, "Port unavailable %04x %04x %04x.\n", mb[1], mb[2], mb[3]); + ql_log(ql_log_warn, vha, 0x505e, + "Link is offline.\n"); if (atomic_read(&vha->loop_state) != LOOP_DOWN) { atomic_set(&vha->loop_state, LOOP_DOWN); @@ -670,12 +686,17 @@ skip_rio: ql_dbg(ql_dbg_async, vha, 0x5011, "Asynchronous PORT UPDATE ignored %04x/%04x/%04x.\n", mb[1], mb[2], mb[3]); + + qlt_async_event(mb[0], vha, mb); break; } ql_dbg(ql_dbg_async, vha, 0x5012, "Port database changed %04x %04x %04x.\n", mb[1], mb[2], mb[3]); + ql_log(ql_log_warn, vha, 0x505f, + "Link is operational (%s Gbps).\n", + qla2x00_get_link_speed_str(ha)); /* * Mark all devices as missing so we will login again. @@ -684,8 +705,13 @@ skip_rio: qla2x00_mark_all_devices_lost(vha, 1); + if (vha->vp_idx == 0 && !qla_ini_mode_enabled(vha)) + set_bit(SCR_PENDING, &vha->dpc_flags); + set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags); + + qlt_async_event(mb[0], vha, mb); break; case MBA_RSCN_UPDATE: /* State Change Registration */ @@ -807,6 +833,8 @@ skip_rio: mb[0], mb[1], mb[2], mb[3]); } + qlt_async_event(mb[0], vha, mb); + if (!vha->vp_idx && ha->num_vhosts) qla2x00_alert_all_vps(rsp, mb); } @@ -1172,6 +1200,9 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req, } else if (iop[0] & BIT_5) fcport->port_type = FCT_INITIATOR; + if (iop[0] & BIT_7) + fcport->flags |= FCF_CONF_COMP_SUPPORTED; + if (logio->io_parameter[7] || logio->io_parameter[8]) fcport->supported_classes |= FC_COS_CLASS2; if (logio->io_parameter[9] || logio->io_parameter[10]) @@ -1715,13 +1746,24 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) res = DID_ERROR << 16; break; } - } else { + } else if (lscsi_status != SAM_STAT_TASK_SET_FULL && + lscsi_status != SAM_STAT_BUSY) { + /* + * scsi status of task set and busy are considered to be + * task not completed. + */ + ql_dbg(ql_dbg_io, fcport->vha, 0x301f, "Dropped frame(s) detected (0x%x " - "of 0x%x bytes).\n", resid, scsi_bufflen(cp)); + "of 0x%x bytes).\n", resid, + scsi_bufflen(cp)); res = DID_ERROR << 16 | lscsi_status; goto check_scsi_status; + } else { + ql_dbg(ql_dbg_io, fcport->vha, 0x3030, + "scsi_status: 0x%x, lscsi_status: 0x%x\n", + scsi_status, lscsi_status); } res = DID_OK << 16 | lscsi_status; @@ -1975,6 +2017,9 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha, if (pkt->entry_status != 0) { qla2x00_error_entry(vha, rsp, (sts_entry_t *) pkt); + + (void)qlt_24xx_process_response_error(vha, pkt); + ((response_t *)pkt)->signature = RESPONSE_PROCESSED; wmb(); continue; @@ -2005,6 +2050,14 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha, case ELS_IOCB_TYPE: qla24xx_els_ct_entry(vha, rsp->req, pkt, ELS_IOCB_TYPE); break; + case ABTS_RECV_24XX: + /* ensure that the ATIO queue is empty */ + qlt_24xx_process_atio_queue(vha); + case ABTS_RESP_24XX: + case CTIO_TYPE7: + case NOTIFY_ACK_TYPE: + qlt_response_pkt_all_vps(vha, (response_t *)pkt); + break; case MARKER_TYPE: /* Do nothing in this case, this check is to prevent it * from falling into default case @@ -2157,6 +2210,13 @@ qla24xx_intr_handler(int irq, void *dev_id) case 0x14: qla24xx_process_response_queue(vha, rsp); break; + case 0x1C: /* ATIO queue updated */ + qlt_24xx_process_atio_queue(vha); + break; + case 0x1D: /* ATIO and response queues updated */ + qlt_24xx_process_atio_queue(vha); + qla24xx_process_response_queue(vha, rsp); + break; default: ql_dbg(ql_dbg_async, vha, 0x504f, "Unrecognized interrupt type (%d).\n", stat * 0xff); @@ -2301,6 +2361,13 @@ qla24xx_msix_default(int irq, void *dev_id) case 0x14: qla24xx_process_response_queue(vha, rsp); break; + case 0x1C: /* ATIO queue updated */ + qlt_24xx_process_atio_queue(vha); + break; + case 0x1D: /* ATIO and response queues updated */ + qlt_24xx_process_atio_queue(vha); + qla24xx_process_response_queue(vha, rsp); + break; default: ql_dbg(ql_dbg_async, vha, 0x5051, "Unrecognized interrupt type (%d).\n", stat & 0xff); @@ -2553,7 +2620,15 @@ void qla2x00_free_irqs(scsi_qla_host_t *vha) { struct qla_hw_data *ha = vha->hw; - struct rsp_que *rsp = ha->rsp_q_map[0]; + struct rsp_que *rsp; + + /* + * We need to check that ha->rsp_q_map is valid in case we are called + * from a probe failure context. + */ + if (!ha->rsp_q_map || !ha->rsp_q_map[0]) + return; + rsp = ha->rsp_q_map[0]; if (ha->flags.msix_enabled) qla24xx_disable_msix(ha); |