diff options
author | Anirban Chakraborty <anirban.chakraborty@qlogic.com> | 2008-12-18 13:06:15 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-12-29 12:24:35 -0500 |
commit | 17d98630a4f2a38537618503ad0c7ec97ba461ca (patch) | |
tree | 27deaa971e7b3a95a56a0ba5cf4c92e12853a775 /drivers/scsi/qla2xxx/qla_os.c | |
parent | 20c09df7eb9c92a40e0ecf654b6e8f14c8583b9e (diff) |
[SCSI] qla2xxx: changes in multiq code
Following changes have been made:
1. Scan outstanding commands only in the queue where it is submitted
2. Update queue registers directly in the fast path
3. Queue specific BAR is remapped only for multiq capable adapters
Signed-off-by: Anirban Chakraborty <anirban.chakraborty@qlogic.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
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 9142025db3d8..8ea927788b3f 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"); |