diff options
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_isr.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_isr.c | 437 |
1 files changed, 389 insertions, 48 deletions
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 6f67a9d4998b..5733811ce8e7 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * QLogic Fibre Channel HBA Driver | 2 | * QLogic Fibre Channel HBA Driver |
3 | * Copyright (c) 2003-2011 QLogic Corporation | 3 | * Copyright (c) 2003-2012 QLogic Corporation |
4 | * | 4 | * |
5 | * See LICENSE.qla2xxx for copyright and licensing details. | 5 | * See LICENSE.qla2xxx for copyright and licensing details. |
6 | */ | 6 | */ |
@@ -294,6 +294,11 @@ qla81xx_idc_event(scsi_qla_host_t *vha, uint16_t aen, uint16_t descr) | |||
294 | "%04x %04x %04x %04x %04x %04x %04x.\n", | 294 | "%04x %04x %04x %04x %04x %04x %04x.\n", |
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 | if ((aen == MBA_IDC_COMPLETE && mb[1] >> 15)) { | ||
298 | vha->hw->flags.idc_compl_status = 1; | ||
299 | if (vha->hw->notify_dcbx_comp) | ||
300 | complete(&vha->hw->dcbx_comp); | ||
301 | } | ||
297 | 302 | ||
298 | /* Acknowledgement needed? [Notify && non-zero timeout]. */ | 303 | /* Acknowledgement needed? [Notify && non-zero timeout]. */ |
299 | timeout = (descr >> 8) & 0xf; | 304 | timeout = (descr >> 8) & 0xf; |
@@ -332,6 +337,166 @@ qla2x00_get_link_speed_str(struct qla_hw_data *ha) | |||
332 | return link_speed; | 337 | return link_speed; |
333 | } | 338 | } |
334 | 339 | ||
340 | void | ||
341 | qla83xx_handle_8200_aen(scsi_qla_host_t *vha, uint16_t *mb) | ||
342 | { | ||
343 | struct qla_hw_data *ha = vha->hw; | ||
344 | |||
345 | /* | ||
346 | * 8200 AEN Interpretation: | ||
347 | * mb[0] = AEN code | ||
348 | * mb[1] = AEN Reason code | ||
349 | * mb[2] = LSW of Peg-Halt Status-1 Register | ||
350 | * mb[6] = MSW of Peg-Halt Status-1 Register | ||
351 | * mb[3] = LSW of Peg-Halt Status-2 register | ||
352 | * mb[7] = MSW of Peg-Halt Status-2 register | ||
353 | * mb[4] = IDC Device-State Register value | ||
354 | * mb[5] = IDC Driver-Presence Register value | ||
355 | */ | ||
356 | ql_dbg(ql_dbg_async, vha, 0x506b, "AEN Code: mb[0] = 0x%x AEN reason: " | ||
357 | "mb[1] = 0x%x PH-status1: mb[2] = 0x%x PH-status1: mb[6] = 0x%x.\n", | ||
358 | mb[0], mb[1], mb[2], mb[6]); | ||
359 | ql_dbg(ql_dbg_async, vha, 0x506c, "PH-status2: mb[3] = 0x%x " | ||
360 | "PH-status2: mb[7] = 0x%x Device-State: mb[4] = 0x%x " | ||
361 | "Drv-Presence: mb[5] = 0x%x.\n", mb[3], mb[7], mb[4], mb[5]); | ||
362 | |||
363 | if (mb[1] & (IDC_PEG_HALT_STATUS_CHANGE | IDC_NIC_FW_REPORTED_FAILURE | | ||
364 | IDC_HEARTBEAT_FAILURE)) { | ||
365 | ha->flags.nic_core_hung = 1; | ||
366 | ql_log(ql_log_warn, vha, 0x5060, | ||
367 | "83XX: F/W Error Reported: Check if reset required.\n"); | ||
368 | |||
369 | if (mb[1] & IDC_PEG_HALT_STATUS_CHANGE) { | ||
370 | uint32_t protocol_engine_id, fw_err_code, err_level; | ||
371 | |||
372 | /* | ||
373 | * IDC_PEG_HALT_STATUS_CHANGE interpretation: | ||
374 | * - PEG-Halt Status-1 Register: | ||
375 | * (LSW = mb[2], MSW = mb[6]) | ||
376 | * Bits 0-7 = protocol-engine ID | ||
377 | * Bits 8-28 = f/w error code | ||
378 | * Bits 29-31 = Error-level | ||
379 | * Error-level 0x1 = Non-Fatal error | ||
380 | * Error-level 0x2 = Recoverable Fatal error | ||
381 | * Error-level 0x4 = UnRecoverable Fatal error | ||
382 | * - PEG-Halt Status-2 Register: | ||
383 | * (LSW = mb[3], MSW = mb[7]) | ||
384 | */ | ||
385 | protocol_engine_id = (mb[2] & 0xff); | ||
386 | fw_err_code = (((mb[2] & 0xff00) >> 8) | | ||
387 | ((mb[6] & 0x1fff) << 8)); | ||
388 | err_level = ((mb[6] & 0xe000) >> 13); | ||
389 | ql_log(ql_log_warn, vha, 0x5061, "PegHalt Status-1 " | ||
390 | "Register: protocol_engine_id=0x%x " | ||
391 | "fw_err_code=0x%x err_level=0x%x.\n", | ||
392 | protocol_engine_id, fw_err_code, err_level); | ||
393 | ql_log(ql_log_warn, vha, 0x5062, "PegHalt Status-2 " | ||
394 | "Register: 0x%x%x.\n", mb[7], mb[3]); | ||
395 | if (err_level == ERR_LEVEL_NON_FATAL) { | ||
396 | ql_log(ql_log_warn, vha, 0x5063, | ||
397 | "Not a fatal error, f/w has recovered " | ||
398 | "iteself.\n"); | ||
399 | } else if (err_level == ERR_LEVEL_RECOVERABLE_FATAL) { | ||
400 | ql_log(ql_log_fatal, vha, 0x5064, | ||
401 | "Recoverable Fatal error: Chip reset " | ||
402 | "required.\n"); | ||
403 | qla83xx_schedule_work(vha, | ||
404 | QLA83XX_NIC_CORE_RESET); | ||
405 | } else if (err_level == ERR_LEVEL_UNRECOVERABLE_FATAL) { | ||
406 | ql_log(ql_log_fatal, vha, 0x5065, | ||
407 | "Unrecoverable Fatal error: Set FAILED " | ||
408 | "state, reboot required.\n"); | ||
409 | qla83xx_schedule_work(vha, | ||
410 | QLA83XX_NIC_CORE_UNRECOVERABLE); | ||
411 | } | ||
412 | } | ||
413 | |||
414 | if (mb[1] & IDC_NIC_FW_REPORTED_FAILURE) { | ||
415 | uint16_t peg_fw_state, nw_interface_link_up; | ||
416 | uint16_t nw_interface_signal_detect, sfp_status; | ||
417 | uint16_t htbt_counter, htbt_monitor_enable; | ||
418 | uint16_t sfp_additonal_info, sfp_multirate; | ||
419 | uint16_t sfp_tx_fault, link_speed, dcbx_status; | ||
420 | |||
421 | /* | ||
422 | * IDC_NIC_FW_REPORTED_FAILURE interpretation: | ||
423 | * - PEG-to-FC Status Register: | ||
424 | * (LSW = mb[2], MSW = mb[6]) | ||
425 | * Bits 0-7 = Peg-Firmware state | ||
426 | * Bit 8 = N/W Interface Link-up | ||
427 | * Bit 9 = N/W Interface signal detected | ||
428 | * Bits 10-11 = SFP Status | ||
429 | * SFP Status 0x0 = SFP+ transceiver not expected | ||
430 | * SFP Status 0x1 = SFP+ transceiver not present | ||
431 | * SFP Status 0x2 = SFP+ transceiver invalid | ||
432 | * SFP Status 0x3 = SFP+ transceiver present and | ||
433 | * valid | ||
434 | * Bits 12-14 = Heartbeat Counter | ||
435 | * Bit 15 = Heartbeat Monitor Enable | ||
436 | * Bits 16-17 = SFP Additional Info | ||
437 | * SFP info 0x0 = Unregocnized transceiver for | ||
438 | * Ethernet | ||
439 | * SFP info 0x1 = SFP+ brand validation failed | ||
440 | * SFP info 0x2 = SFP+ speed validation failed | ||
441 | * SFP info 0x3 = SFP+ access error | ||
442 | * Bit 18 = SFP Multirate | ||
443 | * Bit 19 = SFP Tx Fault | ||
444 | * Bits 20-22 = Link Speed | ||
445 | * Bits 23-27 = Reserved | ||
446 | * Bits 28-30 = DCBX Status | ||
447 | * DCBX Status 0x0 = DCBX Disabled | ||
448 | * DCBX Status 0x1 = DCBX Enabled | ||
449 | * DCBX Status 0x2 = DCBX Exchange error | ||
450 | * Bit 31 = Reserved | ||
451 | */ | ||
452 | peg_fw_state = (mb[2] & 0x00ff); | ||
453 | nw_interface_link_up = ((mb[2] & 0x0100) >> 8); | ||
454 | nw_interface_signal_detect = ((mb[2] & 0x0200) >> 9); | ||
455 | sfp_status = ((mb[2] & 0x0c00) >> 10); | ||
456 | htbt_counter = ((mb[2] & 0x7000) >> 12); | ||
457 | htbt_monitor_enable = ((mb[2] & 0x8000) >> 15); | ||
458 | sfp_additonal_info = (mb[6] & 0x0003); | ||
459 | sfp_multirate = ((mb[6] & 0x0004) >> 2); | ||
460 | sfp_tx_fault = ((mb[6] & 0x0008) >> 3); | ||
461 | link_speed = ((mb[6] & 0x0070) >> 4); | ||
462 | dcbx_status = ((mb[6] & 0x7000) >> 12); | ||
463 | |||
464 | ql_log(ql_log_warn, vha, 0x5066, | ||
465 | "Peg-to-Fc Status Register:\n" | ||
466 | "peg_fw_state=0x%x, nw_interface_link_up=0x%x, " | ||
467 | "nw_interface_signal_detect=0x%x" | ||
468 | "\nsfp_statis=0x%x.\n ", peg_fw_state, | ||
469 | nw_interface_link_up, nw_interface_signal_detect, | ||
470 | sfp_status); | ||
471 | ql_log(ql_log_warn, vha, 0x5067, | ||
472 | "htbt_counter=0x%x, htbt_monitor_enable=0x%x, " | ||
473 | "sfp_additonal_info=0x%x, sfp_multirate=0x%x.\n ", | ||
474 | htbt_counter, htbt_monitor_enable, | ||
475 | sfp_additonal_info, sfp_multirate); | ||
476 | ql_log(ql_log_warn, vha, 0x5068, | ||
477 | "sfp_tx_fault=0x%x, link_state=0x%x, " | ||
478 | "dcbx_status=0x%x.\n", sfp_tx_fault, link_speed, | ||
479 | dcbx_status); | ||
480 | |||
481 | qla83xx_schedule_work(vha, QLA83XX_NIC_CORE_RESET); | ||
482 | } | ||
483 | |||
484 | if (mb[1] & IDC_HEARTBEAT_FAILURE) { | ||
485 | ql_log(ql_log_warn, vha, 0x5069, | ||
486 | "Heartbeat Failure encountered, chip reset " | ||
487 | "required.\n"); | ||
488 | |||
489 | qla83xx_schedule_work(vha, QLA83XX_NIC_CORE_RESET); | ||
490 | } | ||
491 | } | ||
492 | |||
493 | if (mb[1] & IDC_DEVICE_STATE_CHANGE) { | ||
494 | ql_log(ql_log_info, vha, 0x506a, | ||
495 | "IDC Device-State changed = 0x%x.\n", mb[4]); | ||
496 | qla83xx_schedule_work(vha, MBA_IDC_AEN); | ||
497 | } | ||
498 | } | ||
499 | |||
335 | /** | 500 | /** |
336 | * qla2x00_async_event() - Process aynchronous events. | 501 | * qla2x00_async_event() - Process aynchronous events. |
337 | * @ha: SCSI driver HA context | 502 | * @ha: SCSI driver HA context |
@@ -681,8 +846,7 @@ skip_rio: | |||
681 | * it. Otherwise ignore it and Wait for RSCN to come in. | 846 | * it. Otherwise ignore it and Wait for RSCN to come in. |
682 | */ | 847 | */ |
683 | atomic_set(&vha->loop_down_timer, 0); | 848 | atomic_set(&vha->loop_down_timer, 0); |
684 | if (atomic_read(&vha->loop_state) != LOOP_DOWN && | 849 | if (mb[1] != 0xffff || (mb[2] != 0x6 && mb[2] != 0x4)) { |
685 | atomic_read(&vha->loop_state) != LOOP_DEAD) { | ||
686 | ql_dbg(ql_dbg_async, vha, 0x5011, | 850 | ql_dbg(ql_dbg_async, vha, 0x5011, |
687 | "Asynchronous PORT UPDATE ignored %04x/%04x/%04x.\n", | 851 | "Asynchronous PORT UPDATE ignored %04x/%04x/%04x.\n", |
688 | mb[1], mb[2], mb[3]); | 852 | mb[1], mb[2], mb[3]); |
@@ -822,11 +986,28 @@ skip_rio: | |||
822 | "FCF Configuration Error -- %04x %04x %04x.\n", | 986 | "FCF Configuration Error -- %04x %04x %04x.\n", |
823 | mb[1], mb[2], mb[3]); | 987 | mb[1], mb[2], mb[3]); |
824 | break; | 988 | break; |
825 | case MBA_IDC_COMPLETE: | ||
826 | case MBA_IDC_NOTIFY: | 989 | case MBA_IDC_NOTIFY: |
990 | /* See if we need to quiesce any I/O */ | ||
991 | if (IS_QLA8031(vha->hw)) | ||
992 | if ((mb[2] & 0x7fff) == MBC_PORT_RESET || | ||
993 | (mb[2] & 0x7fff) == MBC_SET_PORT_CONFIG) { | ||
994 | set_bit(ISP_QUIESCE_NEEDED, &vha->dpc_flags); | ||
995 | qla2xxx_wake_dpc(vha); | ||
996 | } | ||
997 | case MBA_IDC_COMPLETE: | ||
827 | case MBA_IDC_TIME_EXT: | 998 | case MBA_IDC_TIME_EXT: |
828 | qla81xx_idc_event(vha, mb[0], mb[1]); | 999 | if (IS_QLA81XX(vha->hw) || IS_QLA8031(vha->hw)) |
1000 | qla81xx_idc_event(vha, mb[0], mb[1]); | ||
829 | break; | 1001 | break; |
1002 | |||
1003 | case MBA_IDC_AEN: | ||
1004 | mb[4] = RD_REG_WORD(®24->mailbox4); | ||
1005 | mb[5] = RD_REG_WORD(®24->mailbox5); | ||
1006 | mb[6] = RD_REG_WORD(®24->mailbox6); | ||
1007 | mb[7] = RD_REG_WORD(®24->mailbox7); | ||
1008 | qla83xx_handle_8200_aen(vha, mb); | ||
1009 | break; | ||
1010 | |||
830 | default: | 1011 | default: |
831 | ql_dbg(ql_dbg_async, vha, 0x5057, | 1012 | ql_dbg(ql_dbg_async, vha, 0x5057, |
832 | "Unknown AEN:%04x %04x %04x %04x\n", | 1013 | "Unknown AEN:%04x %04x %04x %04x\n", |
@@ -1414,7 +1595,7 @@ qla2x00_handle_sense(srb_t *sp, uint8_t *sense_data, uint32_t par_sense_len, | |||
1414 | 1595 | ||
1415 | struct scsi_dif_tuple { | 1596 | struct scsi_dif_tuple { |
1416 | __be16 guard; /* Checksum */ | 1597 | __be16 guard; /* Checksum */ |
1417 | __be16 app_tag; /* APPL identifer */ | 1598 | __be16 app_tag; /* APPL identifier */ |
1418 | __be32 ref_tag; /* Target LBA or indirect LBA */ | 1599 | __be32 ref_tag; /* Target LBA or indirect LBA */ |
1419 | }; | 1600 | }; |
1420 | 1601 | ||
@@ -1546,6 +1727,149 @@ qla2x00_handle_dif_error(srb_t *sp, struct sts_entry_24xx *sts24) | |||
1546 | return 1; | 1727 | return 1; |
1547 | } | 1728 | } |
1548 | 1729 | ||
1730 | static void | ||
1731 | qla25xx_process_bidir_status_iocb(scsi_qla_host_t *vha, void *pkt, | ||
1732 | struct req_que *req, uint32_t index) | ||
1733 | { | ||
1734 | struct qla_hw_data *ha = vha->hw; | ||
1735 | srb_t *sp; | ||
1736 | uint16_t comp_status; | ||
1737 | uint16_t scsi_status; | ||
1738 | uint16_t thread_id; | ||
1739 | uint32_t rval = EXT_STATUS_OK; | ||
1740 | struct fc_bsg_job *bsg_job = NULL; | ||
1741 | sts_entry_t *sts; | ||
1742 | struct sts_entry_24xx *sts24; | ||
1743 | sts = (sts_entry_t *) pkt; | ||
1744 | sts24 = (struct sts_entry_24xx *) pkt; | ||
1745 | |||
1746 | /* Validate handle. */ | ||
1747 | if (index >= MAX_OUTSTANDING_COMMANDS) { | ||
1748 | ql_log(ql_log_warn, vha, 0x70af, | ||
1749 | "Invalid SCSI completion handle 0x%x.\n", index); | ||
1750 | set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); | ||
1751 | return; | ||
1752 | } | ||
1753 | |||
1754 | sp = req->outstanding_cmds[index]; | ||
1755 | if (sp) { | ||
1756 | /* Free outstanding command slot. */ | ||
1757 | req->outstanding_cmds[index] = NULL; | ||
1758 | bsg_job = sp->u.bsg_job; | ||
1759 | } else { | ||
1760 | ql_log(ql_log_warn, vha, 0x70b0, | ||
1761 | "Req:%d: Invalid ISP SCSI completion handle(0x%x)\n", | ||
1762 | req->id, index); | ||
1763 | |||
1764 | set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); | ||
1765 | return; | ||
1766 | } | ||
1767 | |||
1768 | if (IS_FWI2_CAPABLE(ha)) { | ||
1769 | comp_status = le16_to_cpu(sts24->comp_status); | ||
1770 | scsi_status = le16_to_cpu(sts24->scsi_status) & SS_MASK; | ||
1771 | } else { | ||
1772 | comp_status = le16_to_cpu(sts->comp_status); | ||
1773 | scsi_status = le16_to_cpu(sts->scsi_status) & SS_MASK; | ||
1774 | } | ||
1775 | |||
1776 | thread_id = bsg_job->request->rqst_data.h_vendor.vendor_cmd[1]; | ||
1777 | switch (comp_status) { | ||
1778 | case CS_COMPLETE: | ||
1779 | if (scsi_status == 0) { | ||
1780 | bsg_job->reply->reply_payload_rcv_len = | ||
1781 | bsg_job->reply_payload.payload_len; | ||
1782 | rval = EXT_STATUS_OK; | ||
1783 | } | ||
1784 | goto done; | ||
1785 | |||
1786 | case CS_DATA_OVERRUN: | ||
1787 | ql_dbg(ql_dbg_user, vha, 0x70b1, | ||
1788 | "Command completed with date overrun thread_id=%d\n", | ||
1789 | thread_id); | ||
1790 | rval = EXT_STATUS_DATA_OVERRUN; | ||
1791 | break; | ||
1792 | |||
1793 | case CS_DATA_UNDERRUN: | ||
1794 | ql_dbg(ql_dbg_user, vha, 0x70b2, | ||
1795 | "Command completed with date underrun thread_id=%d\n", | ||
1796 | thread_id); | ||
1797 | rval = EXT_STATUS_DATA_UNDERRUN; | ||
1798 | break; | ||
1799 | case CS_BIDIR_RD_OVERRUN: | ||
1800 | ql_dbg(ql_dbg_user, vha, 0x70b3, | ||
1801 | "Command completed with read data overrun thread_id=%d\n", | ||
1802 | thread_id); | ||
1803 | rval = EXT_STATUS_DATA_OVERRUN; | ||
1804 | break; | ||
1805 | |||
1806 | case CS_BIDIR_RD_WR_OVERRUN: | ||
1807 | ql_dbg(ql_dbg_user, vha, 0x70b4, | ||
1808 | "Command completed with read and write data overrun " | ||
1809 | "thread_id=%d\n", thread_id); | ||
1810 | rval = EXT_STATUS_DATA_OVERRUN; | ||
1811 | break; | ||
1812 | |||
1813 | case CS_BIDIR_RD_OVERRUN_WR_UNDERRUN: | ||
1814 | ql_dbg(ql_dbg_user, vha, 0x70b5, | ||
1815 | "Command completed with read data over and write data " | ||
1816 | "underrun thread_id=%d\n", thread_id); | ||
1817 | rval = EXT_STATUS_DATA_OVERRUN; | ||
1818 | break; | ||
1819 | |||
1820 | case CS_BIDIR_RD_UNDERRUN: | ||
1821 | ql_dbg(ql_dbg_user, vha, 0x70b6, | ||
1822 | "Command completed with read data data underrun " | ||
1823 | "thread_id=%d\n", thread_id); | ||
1824 | rval = EXT_STATUS_DATA_UNDERRUN; | ||
1825 | break; | ||
1826 | |||
1827 | case CS_BIDIR_RD_UNDERRUN_WR_OVERRUN: | ||
1828 | ql_dbg(ql_dbg_user, vha, 0x70b7, | ||
1829 | "Command completed with read data under and write data " | ||
1830 | "overrun thread_id=%d\n", thread_id); | ||
1831 | rval = EXT_STATUS_DATA_UNDERRUN; | ||
1832 | break; | ||
1833 | |||
1834 | case CS_BIDIR_RD_WR_UNDERRUN: | ||
1835 | ql_dbg(ql_dbg_user, vha, 0x70b8, | ||
1836 | "Command completed with read and write data underrun " | ||
1837 | "thread_id=%d\n", thread_id); | ||
1838 | rval = EXT_STATUS_DATA_UNDERRUN; | ||
1839 | break; | ||
1840 | |||
1841 | case CS_BIDIR_DMA: | ||
1842 | ql_dbg(ql_dbg_user, vha, 0x70b9, | ||
1843 | "Command completed with data DMA error thread_id=%d\n", | ||
1844 | thread_id); | ||
1845 | rval = EXT_STATUS_DMA_ERR; | ||
1846 | break; | ||
1847 | |||
1848 | case CS_TIMEOUT: | ||
1849 | ql_dbg(ql_dbg_user, vha, 0x70ba, | ||
1850 | "Command completed with timeout thread_id=%d\n", | ||
1851 | thread_id); | ||
1852 | rval = EXT_STATUS_TIMEOUT; | ||
1853 | break; | ||
1854 | default: | ||
1855 | ql_dbg(ql_dbg_user, vha, 0x70bb, | ||
1856 | "Command completed with completion status=0x%x " | ||
1857 | "thread_id=%d\n", comp_status, thread_id); | ||
1858 | rval = EXT_STATUS_ERR; | ||
1859 | break; | ||
1860 | } | ||
1861 | bsg_job->reply->reply_payload_rcv_len = 0; | ||
1862 | |||
1863 | done: | ||
1864 | /* Return the vendor specific reply to API */ | ||
1865 | bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] = rval; | ||
1866 | bsg_job->reply_len = sizeof(struct fc_bsg_reply); | ||
1867 | /* Always return DID_OK, bsg will send the vendor specific response | ||
1868 | * in this case only */ | ||
1869 | sp->done(vha, sp, (DID_OK << 6)); | ||
1870 | |||
1871 | } | ||
1872 | |||
1549 | /** | 1873 | /** |
1550 | * qla2x00_status_entry() - Process a Status IOCB entry. | 1874 | * qla2x00_status_entry() - Process a Status IOCB entry. |
1551 | * @ha: SCSI driver HA context | 1875 | * @ha: SCSI driver HA context |
@@ -1573,12 +1897,14 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) | |||
1573 | struct req_que *req; | 1897 | struct req_que *req; |
1574 | int logit = 1; | 1898 | int logit = 1; |
1575 | int res = 0; | 1899 | int res = 0; |
1900 | uint16_t state_flags = 0; | ||
1576 | 1901 | ||
1577 | sts = (sts_entry_t *) pkt; | 1902 | sts = (sts_entry_t *) pkt; |
1578 | sts24 = (struct sts_entry_24xx *) pkt; | 1903 | sts24 = (struct sts_entry_24xx *) pkt; |
1579 | if (IS_FWI2_CAPABLE(ha)) { | 1904 | if (IS_FWI2_CAPABLE(ha)) { |
1580 | comp_status = le16_to_cpu(sts24->comp_status); | 1905 | comp_status = le16_to_cpu(sts24->comp_status); |
1581 | scsi_status = le16_to_cpu(sts24->scsi_status) & SS_MASK; | 1906 | scsi_status = le16_to_cpu(sts24->scsi_status) & SS_MASK; |
1907 | state_flags = le16_to_cpu(sts24->state_flags); | ||
1582 | } else { | 1908 | } else { |
1583 | comp_status = le16_to_cpu(sts->comp_status); | 1909 | comp_status = le16_to_cpu(sts->comp_status); |
1584 | scsi_status = le16_to_cpu(sts->scsi_status) & SS_MASK; | 1910 | scsi_status = le16_to_cpu(sts->scsi_status) & SS_MASK; |
@@ -1587,17 +1913,9 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) | |||
1587 | que = MSW(sts->handle); | 1913 | que = MSW(sts->handle); |
1588 | req = ha->req_q_map[que]; | 1914 | req = ha->req_q_map[que]; |
1589 | 1915 | ||
1590 | /* Fast path completion. */ | ||
1591 | if (comp_status == CS_COMPLETE && scsi_status == 0) { | ||
1592 | qla2x00_process_completed_request(vha, req, handle); | ||
1593 | |||
1594 | return; | ||
1595 | } | ||
1596 | |||
1597 | /* Validate handle. */ | 1916 | /* Validate handle. */ |
1598 | if (handle < MAX_OUTSTANDING_COMMANDS) { | 1917 | if (handle < MAX_OUTSTANDING_COMMANDS) { |
1599 | sp = req->outstanding_cmds[handle]; | 1918 | sp = req->outstanding_cmds[handle]; |
1600 | req->outstanding_cmds[handle] = NULL; | ||
1601 | } else | 1919 | } else |
1602 | sp = NULL; | 1920 | sp = NULL; |
1603 | 1921 | ||
@@ -1612,6 +1930,20 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) | |||
1612 | qla2xxx_wake_dpc(vha); | 1930 | qla2xxx_wake_dpc(vha); |
1613 | return; | 1931 | return; |
1614 | } | 1932 | } |
1933 | |||
1934 | if (unlikely((state_flags & BIT_1) && (sp->type == SRB_BIDI_CMD))) { | ||
1935 | qla25xx_process_bidir_status_iocb(vha, pkt, req, handle); | ||
1936 | return; | ||
1937 | } | ||
1938 | |||
1939 | /* Fast path completion. */ | ||
1940 | if (comp_status == CS_COMPLETE && scsi_status == 0) { | ||
1941 | qla2x00_process_completed_request(vha, req, handle); | ||
1942 | |||
1943 | return; | ||
1944 | } | ||
1945 | |||
1946 | req->outstanding_cmds[handle] = NULL; | ||
1615 | cp = GET_CMD_SP(sp); | 1947 | cp = GET_CMD_SP(sp); |
1616 | if (cp == NULL) { | 1948 | if (cp == NULL) { |
1617 | ql_dbg(ql_dbg_io, vha, 0x3018, | 1949 | ql_dbg(ql_dbg_io, vha, 0x3018, |
@@ -1830,7 +2162,21 @@ check_scsi_status: | |||
1830 | 2162 | ||
1831 | case CS_DIF_ERROR: | 2163 | case CS_DIF_ERROR: |
1832 | logit = qla2x00_handle_dif_error(sp, sts24); | 2164 | logit = qla2x00_handle_dif_error(sp, sts24); |
2165 | res = cp->result; | ||
1833 | break; | 2166 | break; |
2167 | |||
2168 | case CS_TRANSPORT: | ||
2169 | res = DID_ERROR << 16; | ||
2170 | |||
2171 | if (!IS_PI_SPLIT_DET_CAPABLE(ha)) | ||
2172 | break; | ||
2173 | |||
2174 | if (state_flags & BIT_4) | ||
2175 | scmd_printk(KERN_WARNING, cp, | ||
2176 | "Unsupported device '%s' found.\n", | ||
2177 | cp->device->vendor); | ||
2178 | break; | ||
2179 | |||
1834 | default: | 2180 | default: |
1835 | res = DID_ERROR << 16; | 2181 | res = DID_ERROR << 16; |
1836 | break; | 2182 | break; |
@@ -2150,7 +2496,7 @@ qla24xx_intr_handler(int irq, void *dev_id) | |||
2150 | unsigned long iter; | 2496 | unsigned long iter; |
2151 | uint32_t stat; | 2497 | uint32_t stat; |
2152 | uint32_t hccr; | 2498 | uint32_t hccr; |
2153 | uint16_t mb[4]; | 2499 | uint16_t mb[8]; |
2154 | struct rsp_que *rsp; | 2500 | struct rsp_que *rsp; |
2155 | unsigned long flags; | 2501 | unsigned long flags; |
2156 | 2502 | ||
@@ -2191,29 +2537,29 @@ qla24xx_intr_handler(int irq, void *dev_id) | |||
2191 | break; | 2537 | break; |
2192 | 2538 | ||
2193 | switch (stat & 0xff) { | 2539 | switch (stat & 0xff) { |
2194 | case 0x1: | 2540 | case INTR_ROM_MB_SUCCESS: |
2195 | case 0x2: | 2541 | case INTR_ROM_MB_FAILED: |
2196 | case 0x10: | 2542 | case INTR_MB_SUCCESS: |
2197 | case 0x11: | 2543 | case INTR_MB_FAILED: |
2198 | qla24xx_mbx_completion(vha, MSW(stat)); | 2544 | qla24xx_mbx_completion(vha, MSW(stat)); |
2199 | status |= MBX_INTERRUPT; | 2545 | status |= MBX_INTERRUPT; |
2200 | 2546 | ||
2201 | break; | 2547 | break; |
2202 | case 0x12: | 2548 | case INTR_ASYNC_EVENT: |
2203 | mb[0] = MSW(stat); | 2549 | mb[0] = MSW(stat); |
2204 | mb[1] = RD_REG_WORD(®->mailbox1); | 2550 | mb[1] = RD_REG_WORD(®->mailbox1); |
2205 | mb[2] = RD_REG_WORD(®->mailbox2); | 2551 | mb[2] = RD_REG_WORD(®->mailbox2); |
2206 | mb[3] = RD_REG_WORD(®->mailbox3); | 2552 | mb[3] = RD_REG_WORD(®->mailbox3); |
2207 | qla2x00_async_event(vha, rsp, mb); | 2553 | qla2x00_async_event(vha, rsp, mb); |
2208 | break; | 2554 | break; |
2209 | case 0x13: | 2555 | case INTR_RSP_QUE_UPDATE: |
2210 | case 0x14: | 2556 | case INTR_RSP_QUE_UPDATE_83XX: |
2211 | qla24xx_process_response_queue(vha, rsp); | 2557 | qla24xx_process_response_queue(vha, rsp); |
2212 | break; | 2558 | break; |
2213 | case 0x1C: /* ATIO queue updated */ | 2559 | case INTR_ATIO_QUE_UPDATE: |
2214 | qlt_24xx_process_atio_queue(vha); | 2560 | qlt_24xx_process_atio_queue(vha); |
2215 | break; | 2561 | break; |
2216 | case 0x1D: /* ATIO and response queues updated */ | 2562 | case INTR_ATIO_RSP_QUE_UPDATE: |
2217 | qlt_24xx_process_atio_queue(vha); | 2563 | qlt_24xx_process_atio_queue(vha); |
2218 | qla24xx_process_response_queue(vha, rsp); | 2564 | qla24xx_process_response_queue(vha, rsp); |
2219 | break; | 2565 | break; |
@@ -2224,6 +2570,8 @@ qla24xx_intr_handler(int irq, void *dev_id) | |||
2224 | } | 2570 | } |
2225 | WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); | 2571 | WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); |
2226 | RD_REG_DWORD_RELAXED(®->hccr); | 2572 | RD_REG_DWORD_RELAXED(®->hccr); |
2573 | if (unlikely(IS_QLA83XX(ha) && (ha->pdev->revision == 1))) | ||
2574 | ndelay(3500); | ||
2227 | } | 2575 | } |
2228 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 2576 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
2229 | 2577 | ||
@@ -2306,7 +2654,7 @@ qla24xx_msix_default(int irq, void *dev_id) | |||
2306 | int status; | 2654 | int status; |
2307 | uint32_t stat; | 2655 | uint32_t stat; |
2308 | uint32_t hccr; | 2656 | uint32_t hccr; |
2309 | uint16_t mb[4]; | 2657 | uint16_t mb[8]; |
2310 | unsigned long flags; | 2658 | unsigned long flags; |
2311 | 2659 | ||
2312 | rsp = (struct rsp_que *) dev_id; | 2660 | rsp = (struct rsp_que *) dev_id; |
@@ -2342,29 +2690,29 @@ qla24xx_msix_default(int irq, void *dev_id) | |||
2342 | break; | 2690 | break; |
2343 | 2691 | ||
2344 | switch (stat & 0xff) { | 2692 | switch (stat & 0xff) { |
2345 | case 0x1: | 2693 | case INTR_ROM_MB_SUCCESS: |
2346 | case 0x2: | 2694 | case INTR_ROM_MB_FAILED: |
2347 | case 0x10: | 2695 | case INTR_MB_SUCCESS: |
2348 | case 0x11: | 2696 | case INTR_MB_FAILED: |
2349 | qla24xx_mbx_completion(vha, MSW(stat)); | 2697 | qla24xx_mbx_completion(vha, MSW(stat)); |
2350 | status |= MBX_INTERRUPT; | 2698 | status |= MBX_INTERRUPT; |
2351 | 2699 | ||
2352 | break; | 2700 | break; |
2353 | case 0x12: | 2701 | case INTR_ASYNC_EVENT: |
2354 | mb[0] = MSW(stat); | 2702 | mb[0] = MSW(stat); |
2355 | mb[1] = RD_REG_WORD(®->mailbox1); | 2703 | mb[1] = RD_REG_WORD(®->mailbox1); |
2356 | mb[2] = RD_REG_WORD(®->mailbox2); | 2704 | mb[2] = RD_REG_WORD(®->mailbox2); |
2357 | mb[3] = RD_REG_WORD(®->mailbox3); | 2705 | mb[3] = RD_REG_WORD(®->mailbox3); |
2358 | qla2x00_async_event(vha, rsp, mb); | 2706 | qla2x00_async_event(vha, rsp, mb); |
2359 | break; | 2707 | break; |
2360 | case 0x13: | 2708 | case INTR_RSP_QUE_UPDATE: |
2361 | case 0x14: | 2709 | case INTR_RSP_QUE_UPDATE_83XX: |
2362 | qla24xx_process_response_queue(vha, rsp); | 2710 | qla24xx_process_response_queue(vha, rsp); |
2363 | break; | 2711 | break; |
2364 | case 0x1C: /* ATIO queue updated */ | 2712 | case INTR_ATIO_QUE_UPDATE: |
2365 | qlt_24xx_process_atio_queue(vha); | 2713 | qlt_24xx_process_atio_queue(vha); |
2366 | break; | 2714 | break; |
2367 | case 0x1D: /* ATIO and response queues updated */ | 2715 | case INTR_ATIO_RSP_QUE_UPDATE: |
2368 | qlt_24xx_process_atio_queue(vha); | 2716 | qlt_24xx_process_atio_queue(vha); |
2369 | qla24xx_process_response_queue(vha, rsp); | 2717 | qla24xx_process_response_queue(vha, rsp); |
2370 | break; | 2718 | break; |
@@ -2570,7 +2918,7 @@ qla2x00_request_irqs(struct qla_hw_data *ha, struct rsp_que *rsp) | |||
2570 | skip_msix: | 2918 | skip_msix: |
2571 | 2919 | ||
2572 | if (!IS_QLA24XX(ha) && !IS_QLA2532(ha) && !IS_QLA8432(ha) && | 2920 | if (!IS_QLA24XX(ha) && !IS_QLA2532(ha) && !IS_QLA8432(ha) && |
2573 | !IS_QLA8001(ha)) | 2921 | !IS_QLA8001(ha) && !IS_QLA82XX(ha)) |
2574 | goto skip_msi; | 2922 | goto skip_msi; |
2575 | 2923 | ||
2576 | ret = pci_enable_msi(ha->pdev); | 2924 | ret = pci_enable_msi(ha->pdev); |
@@ -2581,6 +2929,11 @@ skip_msix: | |||
2581 | } else | 2929 | } else |
2582 | ql_log(ql_log_warn, vha, 0x0039, | 2930 | ql_log(ql_log_warn, vha, 0x0039, |
2583 | "MSI-X; Falling back-to INTa mode -- %d.\n", ret); | 2931 | "MSI-X; Falling back-to INTa mode -- %d.\n", ret); |
2932 | |||
2933 | /* Skip INTx on ISP82xx. */ | ||
2934 | if (!ha->flags.msi_enabled && IS_QLA82XX(ha)) | ||
2935 | return QLA_FUNCTION_FAILED; | ||
2936 | |||
2584 | skip_msi: | 2937 | skip_msi: |
2585 | 2938 | ||
2586 | ret = request_irq(ha->pdev->irq, ha->isp_ops->intr_handler, | 2939 | ret = request_irq(ha->pdev->irq, ha->isp_ops->intr_handler, |
@@ -2595,21 +2948,9 @@ skip_msi: | |||
2595 | 2948 | ||
2596 | clear_risc_ints: | 2949 | clear_risc_ints: |
2597 | 2950 | ||
2598 | /* | ||
2599 | * FIXME: Noted that 8014s were being dropped during NK testing. | ||
2600 | * Timing deltas during MSI-X/INTa transitions? | ||
2601 | */ | ||
2602 | if (IS_QLA81XX(ha) || IS_QLA82XX(ha) || IS_QLA83XX(ha)) | ||
2603 | goto fail; | ||
2604 | spin_lock_irq(&ha->hardware_lock); | 2951 | spin_lock_irq(&ha->hardware_lock); |
2605 | if (IS_FWI2_CAPABLE(ha)) { | 2952 | if (!IS_FWI2_CAPABLE(ha)) |
2606 | WRT_REG_DWORD(®->isp24.hccr, HCCRX_CLR_HOST_INT); | ||
2607 | WRT_REG_DWORD(®->isp24.hccr, HCCRX_CLR_RISC_INT); | ||
2608 | } else { | ||
2609 | WRT_REG_WORD(®->isp.semaphore, 0); | 2953 | WRT_REG_WORD(®->isp.semaphore, 0); |
2610 | WRT_REG_WORD(®->isp.hccr, HCCR_CLR_RISC_INT); | ||
2611 | WRT_REG_WORD(®->isp.hccr, HCCR_CLR_HOST_INT); | ||
2612 | } | ||
2613 | spin_unlock_irq(&ha->hardware_lock); | 2954 | spin_unlock_irq(&ha->hardware_lock); |
2614 | 2955 | ||
2615 | fail: | 2956 | fail: |