diff options
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_os.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_os.c | 176 |
1 files changed, 98 insertions, 78 deletions
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 9142025db3d..8ea927788b3 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c | |||
@@ -441,6 +441,7 @@ qla2x00_get_new_sp(scsi_qla_host_t *vha, fc_port_t *fcport, | |||
441 | sp->vha = vha; | 441 | sp->vha = vha; |
442 | sp->fcport = fcport; | 442 | sp->fcport = fcport; |
443 | sp->cmd = cmd; | 443 | sp->cmd = cmd; |
444 | sp->que = ha->req_q_map[0]; | ||
444 | sp->flags = 0; | 445 | sp->flags = 0; |
445 | CMD_SP(cmd) = (void *)sp; | 446 | CMD_SP(cmd) = (void *)sp; |
446 | cmd->scsi_done = done; | 447 | cmd->scsi_done = done; |
@@ -775,13 +776,14 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) | |||
775 | { | 776 | { |
776 | scsi_qla_host_t *vha = shost_priv(cmd->device->host); | 777 | scsi_qla_host_t *vha = shost_priv(cmd->device->host); |
777 | srb_t *sp; | 778 | srb_t *sp; |
778 | int ret, i, que; | 779 | int ret, i; |
779 | unsigned int id, lun; | 780 | unsigned int id, lun; |
780 | unsigned long serial; | 781 | unsigned long serial; |
781 | unsigned long flags; | 782 | unsigned long flags; |
782 | int wait = 0; | 783 | int wait = 0; |
783 | struct qla_hw_data *ha = vha->hw; | 784 | struct qla_hw_data *ha = vha->hw; |
784 | struct req_que *req; | 785 | struct req_que *req; |
786 | srb_t *spt; | ||
785 | 787 | ||
786 | qla2x00_block_error_handler(cmd); | 788 | qla2x00_block_error_handler(cmd); |
787 | 789 | ||
@@ -793,37 +795,36 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) | |||
793 | id = cmd->device->id; | 795 | id = cmd->device->id; |
794 | lun = cmd->device->lun; | 796 | lun = cmd->device->lun; |
795 | serial = cmd->serial_number; | 797 | serial = cmd->serial_number; |
798 | spt = (srb_t *) CMD_SP(cmd); | ||
799 | if (!spt) | ||
800 | return SUCCESS; | ||
801 | req = spt->que; | ||
796 | 802 | ||
797 | /* Check active list for command command. */ | 803 | /* Check active list for command command. */ |
798 | spin_lock_irqsave(&ha->hardware_lock, flags); | 804 | spin_lock_irqsave(&ha->hardware_lock, flags); |
799 | for (que = 0; que < QLA_MAX_HOST_QUES; que++) { | 805 | for (i = 1; i < MAX_OUTSTANDING_COMMANDS; i++) { |
800 | req = ha->req_q_map[vha->req_ques[que]]; | 806 | sp = req->outstanding_cmds[i]; |
801 | if (!req) | ||
802 | continue; | ||
803 | for (i = 1; i < MAX_OUTSTANDING_COMMANDS; i++) { | ||
804 | sp = req->outstanding_cmds[i]; | ||
805 | 807 | ||
806 | if (sp == NULL) | 808 | if (sp == NULL) |
807 | continue; | 809 | continue; |
808 | 810 | ||
809 | if (sp->cmd != cmd) | 811 | if (sp->cmd != cmd) |
810 | continue; | 812 | continue; |
811 | 813 | ||
812 | DEBUG2(printk("%s(%ld): aborting sp %p from RISC." | 814 | DEBUG2(printk("%s(%ld): aborting sp %p from RISC." |
813 | " pid=%ld.\n", __func__, vha->host_no, sp, serial)); | 815 | " pid=%ld.\n", __func__, vha->host_no, sp, serial)); |
814 | 816 | ||
815 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 817 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
816 | if (ha->isp_ops->abort_command(vha, sp, req)) { | 818 | if (ha->isp_ops->abort_command(vha, sp, req)) { |
817 | DEBUG2(printk("%s(%ld): abort_command " | 819 | DEBUG2(printk("%s(%ld): abort_command " |
818 | "mbx failed.\n", __func__, vha->host_no)); | 820 | "mbx failed.\n", __func__, vha->host_no)); |
819 | } else { | 821 | } else { |
820 | DEBUG3(printk("%s(%ld): abort_command " | 822 | DEBUG3(printk("%s(%ld): abort_command " |
821 | "mbx success.\n", __func__, vha->host_no)); | 823 | "mbx success.\n", __func__, vha->host_no)); |
822 | wait = 1; | 824 | wait = 1; |
823 | } | ||
824 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
825 | break; | ||
826 | } | 825 | } |
826 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
827 | break; | ||
827 | } | 828 | } |
828 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 829 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
829 | 830 | ||
@@ -852,48 +853,46 @@ enum nexus_wait_type { | |||
852 | 853 | ||
853 | static int | 854 | static int |
854 | qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *vha, unsigned int t, | 855 | qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *vha, unsigned int t, |
855 | unsigned int l, enum nexus_wait_type type) | 856 | unsigned int l, srb_t *sp, enum nexus_wait_type type) |
856 | { | 857 | { |
857 | int cnt, match, status, que; | 858 | int cnt, match, status; |
858 | srb_t *sp; | ||
859 | unsigned long flags; | 859 | unsigned long flags; |
860 | struct qla_hw_data *ha = vha->hw; | 860 | struct qla_hw_data *ha = vha->hw; |
861 | struct req_que *req; | 861 | struct req_que *req; |
862 | 862 | ||
863 | status = QLA_SUCCESS; | 863 | status = QLA_SUCCESS; |
864 | if (!sp) | ||
865 | return status; | ||
866 | |||
864 | spin_lock_irqsave(&ha->hardware_lock, flags); | 867 | spin_lock_irqsave(&ha->hardware_lock, flags); |
865 | for (que = 0; que < QLA_MAX_HOST_QUES; que++) { | 868 | req = sp->que; |
866 | req = ha->req_q_map[vha->req_ques[que]]; | 869 | for (cnt = 1; status == QLA_SUCCESS && |
867 | if (!req) | 870 | cnt < MAX_OUTSTANDING_COMMANDS; cnt++) { |
871 | sp = req->outstanding_cmds[cnt]; | ||
872 | if (!sp) | ||
868 | continue; | 873 | continue; |
869 | for (cnt = 1; status == QLA_SUCCESS && | ||
870 | cnt < MAX_OUTSTANDING_COMMANDS; cnt++) { | ||
871 | sp = req->outstanding_cmds[cnt]; | ||
872 | if (!sp) | ||
873 | continue; | ||
874 | |||
875 | if (vha->vp_idx != sp->fcport->vha->vp_idx) | ||
876 | continue; | ||
877 | match = 0; | ||
878 | switch (type) { | ||
879 | case WAIT_HOST: | ||
880 | match = 1; | ||
881 | break; | ||
882 | case WAIT_TARGET: | ||
883 | match = sp->cmd->device->id == t; | ||
884 | break; | ||
885 | case WAIT_LUN: | ||
886 | match = (sp->cmd->device->id == t && | ||
887 | sp->cmd->device->lun == l); | ||
888 | break; | ||
889 | } | ||
890 | if (!match) | ||
891 | continue; | ||
892 | 874 | ||
893 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 875 | if (vha->vp_idx != sp->fcport->vha->vp_idx) |
894 | status = qla2x00_eh_wait_on_command(sp->cmd); | 876 | continue; |
895 | spin_lock_irqsave(&ha->hardware_lock, flags); | 877 | match = 0; |
878 | switch (type) { | ||
879 | case WAIT_HOST: | ||
880 | match = 1; | ||
881 | break; | ||
882 | case WAIT_TARGET: | ||
883 | match = sp->cmd->device->id == t; | ||
884 | break; | ||
885 | case WAIT_LUN: | ||
886 | match = (sp->cmd->device->id == t && | ||
887 | sp->cmd->device->lun == l); | ||
888 | break; | ||
896 | } | 889 | } |
890 | if (!match) | ||
891 | continue; | ||
892 | |||
893 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
894 | status = qla2x00_eh_wait_on_command(sp->cmd); | ||
895 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
897 | } | 896 | } |
898 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 897 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
899 | 898 | ||
@@ -934,7 +933,7 @@ __qla2xxx_eh_generic_reset(char *name, enum nexus_wait_type type, | |||
934 | goto eh_reset_failed; | 933 | goto eh_reset_failed; |
935 | err = 3; | 934 | err = 3; |
936 | if (qla2x00_eh_wait_for_pending_commands(vha, cmd->device->id, | 935 | if (qla2x00_eh_wait_for_pending_commands(vha, cmd->device->id, |
937 | cmd->device->lun, type) != QLA_SUCCESS) | 936 | cmd->device->lun, (srb_t *) CMD_SP(cmd), type) != QLA_SUCCESS) |
938 | goto eh_reset_failed; | 937 | goto eh_reset_failed; |
939 | 938 | ||
940 | qla_printk(KERN_INFO, vha->hw, "scsi(%ld:%d:%d): %s RESET SUCCEEDED.\n", | 939 | qla_printk(KERN_INFO, vha->hw, "scsi(%ld:%d:%d): %s RESET SUCCEEDED.\n", |
@@ -992,6 +991,7 @@ qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd) | |||
992 | int ret = FAILED; | 991 | int ret = FAILED; |
993 | unsigned int id, lun; | 992 | unsigned int id, lun; |
994 | unsigned long serial; | 993 | unsigned long serial; |
994 | srb_t *sp = (srb_t *) CMD_SP(cmd); | ||
995 | 995 | ||
996 | qla2x00_block_error_handler(cmd); | 996 | qla2x00_block_error_handler(cmd); |
997 | 997 | ||
@@ -1018,7 +1018,7 @@ qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd) | |||
1018 | goto eh_bus_reset_done; | 1018 | goto eh_bus_reset_done; |
1019 | 1019 | ||
1020 | /* Flush outstanding commands. */ | 1020 | /* Flush outstanding commands. */ |
1021 | if (qla2x00_eh_wait_for_pending_commands(vha, 0, 0, WAIT_HOST) != | 1021 | if (qla2x00_eh_wait_for_pending_commands(vha, 0, 0, sp, WAIT_HOST) != |
1022 | QLA_SUCCESS) | 1022 | QLA_SUCCESS) |
1023 | ret = FAILED; | 1023 | ret = FAILED; |
1024 | 1024 | ||
@@ -1053,6 +1053,7 @@ qla2xxx_eh_host_reset(struct scsi_cmnd *cmd) | |||
1053 | int ret = FAILED; | 1053 | int ret = FAILED; |
1054 | unsigned int id, lun; | 1054 | unsigned int id, lun; |
1055 | unsigned long serial; | 1055 | unsigned long serial; |
1056 | srb_t *sp = (srb_t *) CMD_SP(cmd); | ||
1056 | scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev); | 1057 | scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev); |
1057 | 1058 | ||
1058 | qla2x00_block_error_handler(cmd); | 1059 | qla2x00_block_error_handler(cmd); |
@@ -1096,7 +1097,7 @@ qla2xxx_eh_host_reset(struct scsi_cmnd *cmd) | |||
1096 | } | 1097 | } |
1097 | 1098 | ||
1098 | /* Waiting for command to be returned to OS.*/ | 1099 | /* Waiting for command to be returned to OS.*/ |
1099 | if (qla2x00_eh_wait_for_pending_commands(vha, 0, 0, WAIT_HOST) == | 1100 | if (qla2x00_eh_wait_for_pending_commands(vha, 0, 0, sp, WAIT_HOST) == |
1100 | QLA_SUCCESS) | 1101 | QLA_SUCCESS) |
1101 | ret = SUCCESS; | 1102 | ret = SUCCESS; |
1102 | 1103 | ||
@@ -1368,6 +1369,9 @@ static struct isp_operations qla2100_isp_ops = { | |||
1368 | .write_optrom = qla2x00_write_optrom_data, | 1369 | .write_optrom = qla2x00_write_optrom_data, |
1369 | .get_flash_version = qla2x00_get_flash_version, | 1370 | .get_flash_version = qla2x00_get_flash_version, |
1370 | .start_scsi = qla2x00_start_scsi, | 1371 | .start_scsi = qla2x00_start_scsi, |
1372 | .wrt_req_reg = NULL, | ||
1373 | .wrt_rsp_reg = NULL, | ||
1374 | .rd_req_reg = NULL, | ||
1371 | }; | 1375 | }; |
1372 | 1376 | ||
1373 | static struct isp_operations qla2300_isp_ops = { | 1377 | static struct isp_operations qla2300_isp_ops = { |
@@ -1403,6 +1407,9 @@ static struct isp_operations qla2300_isp_ops = { | |||
1403 | .write_optrom = qla2x00_write_optrom_data, | 1407 | .write_optrom = qla2x00_write_optrom_data, |
1404 | .get_flash_version = qla2x00_get_flash_version, | 1408 | .get_flash_version = qla2x00_get_flash_version, |
1405 | .start_scsi = qla2x00_start_scsi, | 1409 | .start_scsi = qla2x00_start_scsi, |
1410 | .wrt_req_reg = NULL, | ||
1411 | .wrt_rsp_reg = NULL, | ||
1412 | .rd_req_reg = NULL, | ||
1406 | }; | 1413 | }; |
1407 | 1414 | ||
1408 | static struct isp_operations qla24xx_isp_ops = { | 1415 | static struct isp_operations qla24xx_isp_ops = { |
@@ -1438,6 +1445,9 @@ static struct isp_operations qla24xx_isp_ops = { | |||
1438 | .write_optrom = qla24xx_write_optrom_data, | 1445 | .write_optrom = qla24xx_write_optrom_data, |
1439 | .get_flash_version = qla24xx_get_flash_version, | 1446 | .get_flash_version = qla24xx_get_flash_version, |
1440 | .start_scsi = qla24xx_start_scsi, | 1447 | .start_scsi = qla24xx_start_scsi, |
1448 | .wrt_req_reg = qla24xx_wrt_req_reg, | ||
1449 | .wrt_rsp_reg = qla24xx_wrt_rsp_reg, | ||
1450 | .rd_req_reg = qla24xx_rd_req_reg, | ||
1441 | }; | 1451 | }; |
1442 | 1452 | ||
1443 | static struct isp_operations qla25xx_isp_ops = { | 1453 | static struct isp_operations qla25xx_isp_ops = { |
@@ -1473,6 +1483,9 @@ static struct isp_operations qla25xx_isp_ops = { | |||
1473 | .write_optrom = qla24xx_write_optrom_data, | 1483 | .write_optrom = qla24xx_write_optrom_data, |
1474 | .get_flash_version = qla24xx_get_flash_version, | 1484 | .get_flash_version = qla24xx_get_flash_version, |
1475 | .start_scsi = qla24xx_start_scsi, | 1485 | .start_scsi = qla24xx_start_scsi, |
1486 | .wrt_req_reg = qla24xx_wrt_req_reg, | ||
1487 | .wrt_rsp_reg = qla24xx_wrt_rsp_reg, | ||
1488 | .rd_req_reg = qla24xx_rd_req_reg, | ||
1476 | }; | 1489 | }; |
1477 | 1490 | ||
1478 | static inline void | 1491 | static inline void |
@@ -1616,26 +1629,27 @@ skip_pio: | |||
1616 | 1629 | ||
1617 | /* Determine queue resources */ | 1630 | /* Determine queue resources */ |
1618 | ha->max_queues = 1; | 1631 | ha->max_queues = 1; |
1619 | if (ql2xmaxqueues > 1) { | 1632 | if (ql2xmaxqueues <= 1 || !IS_QLA25XX(ha)) |
1620 | ha->mqiobase = ioremap(pci_resource_start(ha->pdev, 3), | 1633 | goto mqiobase_exit; |
1621 | pci_resource_len(ha->pdev, 3)); | 1634 | ha->mqiobase = ioremap(pci_resource_start(ha->pdev, 3), |
1622 | if (ha->mqiobase) { | 1635 | pci_resource_len(ha->pdev, 3)); |
1623 | /* Read MSIX vector size of the board */ | 1636 | if (ha->mqiobase) { |
1624 | pci_read_config_word(ha->pdev, QLA_PCI_MSIX_CONTROL, | 1637 | /* Read MSIX vector size of the board */ |
1625 | &msix); | 1638 | pci_read_config_word(ha->pdev, QLA_PCI_MSIX_CONTROL, &msix); |
1626 | ha->msix_count = msix; | 1639 | ha->msix_count = msix; |
1627 | /* Max queues are bounded by available msix vectors */ | 1640 | /* Max queues are bounded by available msix vectors */ |
1628 | /* queue 0 uses two msix vectors */ | 1641 | /* queue 0 uses two msix vectors */ |
1629 | if (ha->msix_count - 1 < ql2xmaxqueues) | 1642 | if (ha->msix_count - 1 < ql2xmaxqueues) |
1630 | ha->max_queues = ha->msix_count - 1; | 1643 | ha->max_queues = ha->msix_count - 1; |
1631 | else if (ql2xmaxqueues > QLA_MQ_SIZE) | 1644 | else if (ql2xmaxqueues > QLA_MQ_SIZE) |
1632 | ha->max_queues = QLA_MQ_SIZE; | 1645 | ha->max_queues = QLA_MQ_SIZE; |
1633 | else | 1646 | else |
1634 | ha->max_queues = ql2xmaxqueues; | 1647 | ha->max_queues = ql2xmaxqueues; |
1635 | qla_printk(KERN_INFO, ha, | 1648 | qla_printk(KERN_INFO, ha, |
1636 | "MSI-X vector count: %d\n", msix); | 1649 | "MSI-X vector count: %d\n", msix); |
1637 | } | ||
1638 | } | 1650 | } |
1651 | |||
1652 | mqiobase_exit: | ||
1639 | ha->msix_count = ha->max_queues + 1; | 1653 | ha->msix_count = ha->max_queues + 1; |
1640 | return (0); | 1654 | return (0); |
1641 | 1655 | ||
@@ -1852,6 +1866,12 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1852 | ha->rsp_q_map[0] = rsp; | 1866 | ha->rsp_q_map[0] = rsp; |
1853 | ha->req_q_map[0] = req; | 1867 | ha->req_q_map[0] = req; |
1854 | 1868 | ||
1869 | if (ha->mqenable) { | ||
1870 | ha->isp_ops->wrt_req_reg = qla25xx_wrt_req_reg; | ||
1871 | ha->isp_ops->wrt_rsp_reg = qla25xx_wrt_rsp_reg; | ||
1872 | ha->isp_ops->rd_req_reg = qla25xx_rd_req_reg; | ||
1873 | } | ||
1874 | |||
1855 | if (qla2x00_initialize_adapter(base_vha)) { | 1875 | if (qla2x00_initialize_adapter(base_vha)) { |
1856 | qla_printk(KERN_WARNING, ha, | 1876 | qla_printk(KERN_WARNING, ha, |
1857 | "Failed to initialize adapter\n"); | 1877 | "Failed to initialize adapter\n"); |