diff options
Diffstat (limited to 'drivers/scsi/qla2xxx')
-rw-r--r-- | drivers/scsi/qla2xxx/Makefile | 3 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_attr.c | 772 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_bsg.c | 1212 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_bsg.h | 135 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_dbg.c | 61 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_dbg.h | 10 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_def.h | 343 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_fw.h | 106 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_gbl.h | 126 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_gs.c | 2 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_init.c | 724 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_inline.h | 21 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_iocb.c | 879 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_isr.c | 540 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_mbx.c | 266 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_nx.c | 3636 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_nx.h | 889 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_os.c | 543 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_sup.c | 149 |
19 files changed, 9140 insertions, 1277 deletions
diff --git a/drivers/scsi/qla2xxx/Makefile b/drivers/scsi/qla2xxx/Makefile index c51fd1f86639..5df782f4a097 100644 --- a/drivers/scsi/qla2xxx/Makefile +++ b/drivers/scsi/qla2xxx/Makefile | |||
@@ -1,4 +1,5 @@ | |||
1 | qla2xxx-y := qla_os.o qla_init.o qla_mbx.o qla_iocb.o qla_isr.o qla_gs.o \ | 1 | qla2xxx-y := qla_os.o qla_init.o qla_mbx.o qla_iocb.o qla_isr.o qla_gs.o \ |
2 | qla_dbg.o qla_sup.o qla_attr.o qla_mid.o qla_dfs.o | 2 | qla_dbg.o qla_sup.o qla_attr.o qla_mid.o qla_dfs.o qla_bsg.o \ |
3 | qla_nx.o | ||
3 | 4 | ||
4 | obj-$(CONFIG_SCSI_QLA_FC) += qla2xxx.o | 5 | obj-$(CONFIG_SCSI_QLA_FC) += qla2xxx.o |
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 1c7ef55966fb..3b708606b932 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c | |||
@@ -12,9 +12,7 @@ | |||
12 | #include <linux/delay.h> | 12 | #include <linux/delay.h> |
13 | 13 | ||
14 | static int qla24xx_vport_disable(struct fc_vport *, bool); | 14 | static int qla24xx_vport_disable(struct fc_vport *, bool); |
15 | static int qla84xx_reset(scsi_qla_host_t *, struct msg_echo_lb *, struct fc_bsg_job *); | 15 | |
16 | int qla84xx_reset_chip(scsi_qla_host_t *, uint16_t, uint16_t *); | ||
17 | static int qla84xx_mgmt_cmd(scsi_qla_host_t *, struct msg_echo_lb *, struct fc_bsg_job *); | ||
18 | /* SYSFS attributes --------------------------------------------------------- */ | 16 | /* SYSFS attributes --------------------------------------------------------- */ |
19 | 17 | ||
20 | static ssize_t | 18 | static ssize_t |
@@ -43,6 +41,12 @@ qla2x00_sysfs_write_fw_dump(struct kobject *kobj, | |||
43 | struct qla_hw_data *ha = vha->hw; | 41 | struct qla_hw_data *ha = vha->hw; |
44 | int reading; | 42 | int reading; |
45 | 43 | ||
44 | if (IS_QLA82XX(ha)) { | ||
45 | DEBUG2(qla_printk(KERN_INFO, ha, | ||
46 | "Firmware dump not supported for ISP82xx\n")); | ||
47 | return count; | ||
48 | } | ||
49 | |||
46 | if (off != 0) | 50 | if (off != 0) |
47 | return (0); | 51 | return (0); |
48 | 52 | ||
@@ -277,6 +281,12 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj, | |||
277 | return count; | 281 | return count; |
278 | } | 282 | } |
279 | 283 | ||
284 | if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) { | ||
285 | qla_printk(KERN_WARNING, ha, | ||
286 | "HBA not online, failing NVRAM update.\n"); | ||
287 | return -EAGAIN; | ||
288 | } | ||
289 | |||
280 | DEBUG2(qla_printk(KERN_INFO, ha, | 290 | DEBUG2(qla_printk(KERN_INFO, ha, |
281 | "Reading flash region -- 0x%x/0x%x.\n", | 291 | "Reading flash region -- 0x%x/0x%x.\n", |
282 | ha->optrom_region_start, ha->optrom_region_size)); | 292 | ha->optrom_region_start, ha->optrom_region_size)); |
@@ -315,8 +325,8 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj, | |||
315 | else if (start == (ha->flt_region_boot * 4) || | 325 | else if (start == (ha->flt_region_boot * 4) || |
316 | start == (ha->flt_region_fw * 4)) | 326 | start == (ha->flt_region_fw * 4)) |
317 | valid = 1; | 327 | valid = 1; |
318 | else if (IS_QLA25XX(ha) || IS_QLA81XX(ha)) | 328 | else if (IS_QLA25XX(ha) || IS_QLA8XXX_TYPE(ha)) |
319 | valid = 1; | 329 | valid = 1; |
320 | if (!valid) { | 330 | if (!valid) { |
321 | qla_printk(KERN_WARNING, ha, | 331 | qla_printk(KERN_WARNING, ha, |
322 | "Invalid start region 0x%x/0x%x.\n", start, size); | 332 | "Invalid start region 0x%x/0x%x.\n", start, size); |
@@ -519,6 +529,7 @@ qla2x00_sysfs_write_reset(struct kobject *kobj, | |||
519 | struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj, | 529 | struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj, |
520 | struct device, kobj))); | 530 | struct device, kobj))); |
521 | struct qla_hw_data *ha = vha->hw; | 531 | struct qla_hw_data *ha = vha->hw; |
532 | struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev); | ||
522 | int type; | 533 | int type; |
523 | 534 | ||
524 | if (off != 0) | 535 | if (off != 0) |
@@ -553,6 +564,20 @@ qla2x00_sysfs_write_reset(struct kobject *kobj, | |||
553 | "MPI reset failed on (%ld).\n", vha->host_no); | 564 | "MPI reset failed on (%ld).\n", vha->host_no); |
554 | scsi_unblock_requests(vha->host); | 565 | scsi_unblock_requests(vha->host); |
555 | break; | 566 | break; |
567 | case 0x2025e: | ||
568 | if (!IS_QLA82XX(ha) || vha != base_vha) { | ||
569 | qla_printk(KERN_INFO, ha, | ||
570 | "FCoE ctx reset not supported for host%ld.\n", | ||
571 | vha->host_no); | ||
572 | return count; | ||
573 | } | ||
574 | |||
575 | qla_printk(KERN_INFO, ha, | ||
576 | "Issuing FCoE CTX reset on host%ld.\n", vha->host_no); | ||
577 | set_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags); | ||
578 | qla2xxx_wake_dpc(vha); | ||
579 | qla2x00_wait_for_fcoe_ctx_reset(vha); | ||
580 | break; | ||
556 | } | 581 | } |
557 | return count; | 582 | return count; |
558 | } | 583 | } |
@@ -838,7 +863,7 @@ qla2x00_alloc_sysfs_attr(scsi_qla_host_t *vha) | |||
838 | continue; | 863 | continue; |
839 | if (iter->is4GBp_only == 2 && !IS_QLA25XX(vha->hw)) | 864 | if (iter->is4GBp_only == 2 && !IS_QLA25XX(vha->hw)) |
840 | continue; | 865 | continue; |
841 | if (iter->is4GBp_only == 3 && !IS_QLA81XX(vha->hw)) | 866 | if (iter->is4GBp_only == 3 && !(IS_QLA8XXX_TYPE(vha->hw))) |
842 | continue; | 867 | continue; |
843 | 868 | ||
844 | ret = sysfs_create_bin_file(&host->shost_gendev.kobj, | 869 | ret = sysfs_create_bin_file(&host->shost_gendev.kobj, |
@@ -862,7 +887,7 @@ qla2x00_free_sysfs_attr(scsi_qla_host_t *vha) | |||
862 | continue; | 887 | continue; |
863 | if (iter->is4GBp_only == 2 && !IS_QLA25XX(ha)) | 888 | if (iter->is4GBp_only == 2 && !IS_QLA25XX(ha)) |
864 | continue; | 889 | continue; |
865 | if (iter->is4GBp_only == 3 && !IS_QLA81XX(ha)) | 890 | if (iter->is4GBp_only == 3 && !!(IS_QLA8XXX_TYPE(vha->hw))) |
866 | continue; | 891 | continue; |
867 | 892 | ||
868 | sysfs_remove_bin_file(&host->shost_gendev.kobj, | 893 | sysfs_remove_bin_file(&host->shost_gendev.kobj, |
@@ -968,7 +993,8 @@ qla2x00_link_state_show(struct device *dev, struct device_attribute *attr, | |||
968 | int len = 0; | 993 | int len = 0; |
969 | 994 | ||
970 | if (atomic_read(&vha->loop_state) == LOOP_DOWN || | 995 | if (atomic_read(&vha->loop_state) == LOOP_DOWN || |
971 | atomic_read(&vha->loop_state) == LOOP_DEAD) | 996 | atomic_read(&vha->loop_state) == LOOP_DEAD || |
997 | vha->device_flags & DFLG_NO_CABLE) | ||
972 | len = snprintf(buf, PAGE_SIZE, "Link Down\n"); | 998 | len = snprintf(buf, PAGE_SIZE, "Link Down\n"); |
973 | else if (atomic_read(&vha->loop_state) != LOOP_READY || | 999 | else if (atomic_read(&vha->loop_state) != LOOP_READY || |
974 | test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) || | 1000 | test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) || |
@@ -1179,15 +1205,15 @@ qla24xx_84xx_fw_version_show(struct device *dev, | |||
1179 | scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); | 1205 | scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); |
1180 | struct qla_hw_data *ha = vha->hw; | 1206 | struct qla_hw_data *ha = vha->hw; |
1181 | 1207 | ||
1182 | if (IS_QLA84XX(ha) && ha->cs84xx) { | 1208 | if (!IS_QLA84XX(ha)) |
1183 | if (ha->cs84xx->op_fw_version == 0) { | 1209 | return snprintf(buf, PAGE_SIZE, "\n"); |
1184 | rval = qla84xx_verify_chip(vha, status); | 1210 | |
1185 | } | 1211 | if (ha->cs84xx && ha->cs84xx->op_fw_version == 0) |
1212 | rval = qla84xx_verify_chip(vha, status); | ||
1186 | 1213 | ||
1187 | if ((rval == QLA_SUCCESS) && (status[0] == 0)) | 1214 | if ((rval == QLA_SUCCESS) && (status[0] == 0)) |
1188 | return snprintf(buf, PAGE_SIZE, "%u\n", | 1215 | return snprintf(buf, PAGE_SIZE, "%u\n", |
1189 | (uint32_t)ha->cs84xx->op_fw_version); | 1216 | (uint32_t)ha->cs84xx->op_fw_version); |
1190 | } | ||
1191 | 1217 | ||
1192 | return snprintf(buf, PAGE_SIZE, "\n"); | 1218 | return snprintf(buf, PAGE_SIZE, "\n"); |
1193 | } | 1219 | } |
@@ -1237,7 +1263,7 @@ qla2x00_vlan_id_show(struct device *dev, struct device_attribute *attr, | |||
1237 | { | 1263 | { |
1238 | scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); | 1264 | scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); |
1239 | 1265 | ||
1240 | if (!IS_QLA81XX(vha->hw)) | 1266 | if (!IS_QLA8XXX_TYPE(vha->hw)) |
1241 | return snprintf(buf, PAGE_SIZE, "\n"); | 1267 | return snprintf(buf, PAGE_SIZE, "\n"); |
1242 | 1268 | ||
1243 | return snprintf(buf, PAGE_SIZE, "%d\n", vha->fcoe_vlan_id); | 1269 | return snprintf(buf, PAGE_SIZE, "%d\n", vha->fcoe_vlan_id); |
@@ -1249,7 +1275,7 @@ qla2x00_vn_port_mac_address_show(struct device *dev, | |||
1249 | { | 1275 | { |
1250 | scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); | 1276 | scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); |
1251 | 1277 | ||
1252 | if (!IS_QLA81XX(vha->hw)) | 1278 | if (!IS_QLA8XXX_TYPE(vha->hw)) |
1253 | return snprintf(buf, PAGE_SIZE, "\n"); | 1279 | return snprintf(buf, PAGE_SIZE, "\n"); |
1254 | 1280 | ||
1255 | return snprintf(buf, PAGE_SIZE, "%02x:%02x:%02x:%02x:%02x:%02x\n", | 1281 | return snprintf(buf, PAGE_SIZE, "%02x:%02x:%02x:%02x:%02x:%02x\n", |
@@ -1706,6 +1732,22 @@ qla24xx_vport_create(struct fc_vport *fc_vport, bool disable) | |||
1706 | fc_vport_set_state(fc_vport, FC_VPORT_LINKDOWN); | 1732 | fc_vport_set_state(fc_vport, FC_VPORT_LINKDOWN); |
1707 | } | 1733 | } |
1708 | 1734 | ||
1735 | if (IS_QLA25XX(ha) && ql2xenabledif) { | ||
1736 | if (ha->fw_attributes & BIT_4) { | ||
1737 | vha->flags.difdix_supported = 1; | ||
1738 | DEBUG18(qla_printk(KERN_INFO, ha, | ||
1739 | "Registering for DIF/DIX type 1 and 3" | ||
1740 | " protection.\n")); | ||
1741 | scsi_host_set_prot(vha->host, | ||
1742 | SHOST_DIF_TYPE1_PROTECTION | ||
1743 | | SHOST_DIF_TYPE3_PROTECTION | ||
1744 | | SHOST_DIX_TYPE1_PROTECTION | ||
1745 | | SHOST_DIX_TYPE3_PROTECTION); | ||
1746 | scsi_host_set_guard(vha->host, SHOST_DIX_GUARD_CRC); | ||
1747 | } else | ||
1748 | vha->flags.difdix_supported = 0; | ||
1749 | } | ||
1750 | |||
1709 | if (scsi_add_host_with_dma(vha->host, &fc_vport->dev, | 1751 | if (scsi_add_host_with_dma(vha->host, &fc_vport->dev, |
1710 | &ha->pdev->dev)) { | 1752 | &ha->pdev->dev)) { |
1711 | DEBUG15(printk("scsi(%ld): scsi_add_host failure for VP[%d].\n", | 1753 | DEBUG15(printk("scsi(%ld): scsi_add_host failure for VP[%d].\n", |
@@ -1825,582 +1867,6 @@ qla24xx_vport_disable(struct fc_vport *fc_vport, bool disable) | |||
1825 | return 0; | 1867 | return 0; |
1826 | } | 1868 | } |
1827 | 1869 | ||
1828 | /* BSG support for ELS/CT pass through */ | ||
1829 | inline srb_t * | ||
1830 | qla2x00_get_ctx_bsg_sp(scsi_qla_host_t *vha, fc_port_t *fcport, size_t size) | ||
1831 | { | ||
1832 | srb_t *sp; | ||
1833 | struct qla_hw_data *ha = vha->hw; | ||
1834 | struct srb_bsg_ctx *ctx; | ||
1835 | |||
1836 | sp = mempool_alloc(ha->srb_mempool, GFP_KERNEL); | ||
1837 | if (!sp) | ||
1838 | goto done; | ||
1839 | ctx = kzalloc(size, GFP_KERNEL); | ||
1840 | if (!ctx) { | ||
1841 | mempool_free(sp, ha->srb_mempool); | ||
1842 | goto done; | ||
1843 | } | ||
1844 | |||
1845 | memset(sp, 0, sizeof(*sp)); | ||
1846 | sp->fcport = fcport; | ||
1847 | sp->ctx = ctx; | ||
1848 | done: | ||
1849 | return sp; | ||
1850 | } | ||
1851 | |||
1852 | static int | ||
1853 | qla2x00_process_els(struct fc_bsg_job *bsg_job) | ||
1854 | { | ||
1855 | struct fc_rport *rport; | ||
1856 | fc_port_t *fcport; | ||
1857 | struct Scsi_Host *host; | ||
1858 | scsi_qla_host_t *vha; | ||
1859 | struct qla_hw_data *ha; | ||
1860 | srb_t *sp; | ||
1861 | const char *type; | ||
1862 | int req_sg_cnt, rsp_sg_cnt; | ||
1863 | int rval = (DRIVER_ERROR << 16); | ||
1864 | uint16_t nextlid = 0; | ||
1865 | struct srb_bsg *els; | ||
1866 | |||
1867 | /* Multiple SG's are not supported for ELS requests */ | ||
1868 | if (bsg_job->request_payload.sg_cnt > 1 || | ||
1869 | bsg_job->reply_payload.sg_cnt > 1) { | ||
1870 | DEBUG2(printk(KERN_INFO | ||
1871 | "multiple SG's are not supported for ELS requests" | ||
1872 | " [request_sg_cnt: %x reply_sg_cnt: %x]\n", | ||
1873 | bsg_job->request_payload.sg_cnt, | ||
1874 | bsg_job->reply_payload.sg_cnt)); | ||
1875 | rval = -EPERM; | ||
1876 | goto done; | ||
1877 | } | ||
1878 | |||
1879 | /* ELS request for rport */ | ||
1880 | if (bsg_job->request->msgcode == FC_BSG_RPT_ELS) { | ||
1881 | rport = bsg_job->rport; | ||
1882 | fcport = *(fc_port_t **) rport->dd_data; | ||
1883 | host = rport_to_shost(rport); | ||
1884 | vha = shost_priv(host); | ||
1885 | ha = vha->hw; | ||
1886 | type = "FC_BSG_RPT_ELS"; | ||
1887 | |||
1888 | /* make sure the rport is logged in, | ||
1889 | * if not perform fabric login | ||
1890 | */ | ||
1891 | if (qla2x00_fabric_login(vha, fcport, &nextlid)) { | ||
1892 | DEBUG2(qla_printk(KERN_WARNING, ha, | ||
1893 | "failed to login port %06X for ELS passthru\n", | ||
1894 | fcport->d_id.b24)); | ||
1895 | rval = -EIO; | ||
1896 | goto done; | ||
1897 | } | ||
1898 | } else { | ||
1899 | host = bsg_job->shost; | ||
1900 | vha = shost_priv(host); | ||
1901 | ha = vha->hw; | ||
1902 | type = "FC_BSG_HST_ELS_NOLOGIN"; | ||
1903 | |||
1904 | /* Allocate a dummy fcport structure, since functions | ||
1905 | * preparing the IOCB and mailbox command retrieves port | ||
1906 | * specific information from fcport structure. For Host based | ||
1907 | * ELS commands there will be no fcport structure allocated | ||
1908 | */ | ||
1909 | fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL); | ||
1910 | if (!fcport) { | ||
1911 | rval = -ENOMEM; | ||
1912 | goto done; | ||
1913 | } | ||
1914 | |||
1915 | /* Initialize all required fields of fcport */ | ||
1916 | fcport->vha = vha; | ||
1917 | fcport->vp_idx = vha->vp_idx; | ||
1918 | fcport->d_id.b.al_pa = | ||
1919 | bsg_job->request->rqst_data.h_els.port_id[0]; | ||
1920 | fcport->d_id.b.area = | ||
1921 | bsg_job->request->rqst_data.h_els.port_id[1]; | ||
1922 | fcport->d_id.b.domain = | ||
1923 | bsg_job->request->rqst_data.h_els.port_id[2]; | ||
1924 | fcport->loop_id = | ||
1925 | (fcport->d_id.b.al_pa == 0xFD) ? | ||
1926 | NPH_FABRIC_CONTROLLER : NPH_F_PORT; | ||
1927 | } | ||
1928 | |||
1929 | if (!vha->flags.online) { | ||
1930 | DEBUG2(qla_printk(KERN_WARNING, ha, | ||
1931 | "host not online\n")); | ||
1932 | rval = -EIO; | ||
1933 | goto done; | ||
1934 | } | ||
1935 | |||
1936 | req_sg_cnt = | ||
1937 | dma_map_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list, | ||
1938 | bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE); | ||
1939 | if (!req_sg_cnt) { | ||
1940 | rval = -ENOMEM; | ||
1941 | goto done_free_fcport; | ||
1942 | } | ||
1943 | rsp_sg_cnt = dma_map_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list, | ||
1944 | bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE); | ||
1945 | if (!rsp_sg_cnt) { | ||
1946 | rval = -ENOMEM; | ||
1947 | goto done_free_fcport; | ||
1948 | } | ||
1949 | |||
1950 | if ((req_sg_cnt != bsg_job->request_payload.sg_cnt) || | ||
1951 | (rsp_sg_cnt != bsg_job->reply_payload.sg_cnt)) | ||
1952 | { | ||
1953 | DEBUG2(printk(KERN_INFO | ||
1954 | "dma mapping resulted in different sg counts \ | ||
1955 | [request_sg_cnt: %x dma_request_sg_cnt: %x\ | ||
1956 | reply_sg_cnt: %x dma_reply_sg_cnt: %x]\n", | ||
1957 | bsg_job->request_payload.sg_cnt, req_sg_cnt, | ||
1958 | bsg_job->reply_payload.sg_cnt, rsp_sg_cnt)); | ||
1959 | rval = -EAGAIN; | ||
1960 | goto done_unmap_sg; | ||
1961 | } | ||
1962 | |||
1963 | /* Alloc SRB structure */ | ||
1964 | sp = qla2x00_get_ctx_bsg_sp(vha, fcport, sizeof(struct srb_bsg)); | ||
1965 | if (!sp) { | ||
1966 | rval = -ENOMEM; | ||
1967 | goto done_unmap_sg; | ||
1968 | } | ||
1969 | |||
1970 | els = sp->ctx; | ||
1971 | els->ctx.type = | ||
1972 | (bsg_job->request->msgcode == FC_BSG_RPT_ELS ? | ||
1973 | SRB_ELS_CMD_RPT : SRB_ELS_CMD_HST); | ||
1974 | els->bsg_job = bsg_job; | ||
1975 | |||
1976 | DEBUG2(qla_printk(KERN_INFO, ha, | ||
1977 | "scsi(%ld:%x): bsg rqst type: %s els type: %x - loop-id=%x " | ||
1978 | "portid=%02x%02x%02x.\n", vha->host_no, sp->handle, type, | ||
1979 | bsg_job->request->rqst_data.h_els.command_code, | ||
1980 | fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area, | ||
1981 | fcport->d_id.b.al_pa)); | ||
1982 | |||
1983 | rval = qla2x00_start_sp(sp); | ||
1984 | if (rval != QLA_SUCCESS) { | ||
1985 | kfree(sp->ctx); | ||
1986 | mempool_free(sp, ha->srb_mempool); | ||
1987 | rval = -EIO; | ||
1988 | goto done_unmap_sg; | ||
1989 | } | ||
1990 | return rval; | ||
1991 | |||
1992 | done_unmap_sg: | ||
1993 | dma_unmap_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list, | ||
1994 | bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE); | ||
1995 | dma_unmap_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list, | ||
1996 | bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE); | ||
1997 | goto done_free_fcport; | ||
1998 | |||
1999 | done_free_fcport: | ||
2000 | if (bsg_job->request->msgcode == FC_BSG_HST_ELS_NOLOGIN) | ||
2001 | kfree(fcport); | ||
2002 | done: | ||
2003 | return rval; | ||
2004 | } | ||
2005 | |||
2006 | static int | ||
2007 | qla2x00_process_ct(struct fc_bsg_job *bsg_job) | ||
2008 | { | ||
2009 | srb_t *sp; | ||
2010 | struct Scsi_Host *host = bsg_job->shost; | ||
2011 | scsi_qla_host_t *vha = shost_priv(host); | ||
2012 | struct qla_hw_data *ha = vha->hw; | ||
2013 | int rval = (DRIVER_ERROR << 16); | ||
2014 | int req_sg_cnt, rsp_sg_cnt; | ||
2015 | uint16_t loop_id; | ||
2016 | struct fc_port *fcport; | ||
2017 | char *type = "FC_BSG_HST_CT"; | ||
2018 | struct srb_bsg *ct; | ||
2019 | |||
2020 | /* pass through is supported only for ISP 4Gb or higher */ | ||
2021 | if (!IS_FWI2_CAPABLE(ha)) { | ||
2022 | DEBUG2(qla_printk(KERN_INFO, ha, | ||
2023 | "scsi(%ld):Firmware is not capable to support FC " | ||
2024 | "CT pass thru\n", vha->host_no)); | ||
2025 | rval = -EPERM; | ||
2026 | goto done; | ||
2027 | } | ||
2028 | |||
2029 | req_sg_cnt = | ||
2030 | dma_map_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list, | ||
2031 | bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE); | ||
2032 | if (!req_sg_cnt) { | ||
2033 | rval = -ENOMEM; | ||
2034 | goto done; | ||
2035 | } | ||
2036 | |||
2037 | rsp_sg_cnt = dma_map_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list, | ||
2038 | bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE); | ||
2039 | if (!rsp_sg_cnt) { | ||
2040 | rval = -ENOMEM; | ||
2041 | goto done; | ||
2042 | } | ||
2043 | |||
2044 | if ((req_sg_cnt != bsg_job->request_payload.sg_cnt) || | ||
2045 | (rsp_sg_cnt != bsg_job->reply_payload.sg_cnt)) | ||
2046 | { | ||
2047 | DEBUG2(qla_printk(KERN_WARNING, ha, | ||
2048 | "dma mapping resulted in different sg counts \ | ||
2049 | [request_sg_cnt: %x dma_request_sg_cnt: %x\ | ||
2050 | reply_sg_cnt: %x dma_reply_sg_cnt: %x]\n", | ||
2051 | bsg_job->request_payload.sg_cnt, req_sg_cnt, | ||
2052 | bsg_job->reply_payload.sg_cnt, rsp_sg_cnt)); | ||
2053 | rval = -EAGAIN; | ||
2054 | goto done_unmap_sg; | ||
2055 | } | ||
2056 | |||
2057 | if (!vha->flags.online) { | ||
2058 | DEBUG2(qla_printk(KERN_WARNING, ha, | ||
2059 | "host not online\n")); | ||
2060 | rval = -EIO; | ||
2061 | goto done_unmap_sg; | ||
2062 | } | ||
2063 | |||
2064 | loop_id = | ||
2065 | (bsg_job->request->rqst_data.h_ct.preamble_word1 & 0xFF000000) | ||
2066 | >> 24; | ||
2067 | switch (loop_id) { | ||
2068 | case 0xFC: | ||
2069 | loop_id = cpu_to_le16(NPH_SNS); | ||
2070 | break; | ||
2071 | case 0xFA: | ||
2072 | loop_id = vha->mgmt_svr_loop_id; | ||
2073 | break; | ||
2074 | default: | ||
2075 | DEBUG2(qla_printk(KERN_INFO, ha, | ||
2076 | "Unknown loop id: %x\n", loop_id)); | ||
2077 | rval = -EINVAL; | ||
2078 | goto done_unmap_sg; | ||
2079 | } | ||
2080 | |||
2081 | /* Allocate a dummy fcport structure, since functions preparing the | ||
2082 | * IOCB and mailbox command retrieves port specific information | ||
2083 | * from fcport structure. For Host based ELS commands there will be | ||
2084 | * no fcport structure allocated | ||
2085 | */ | ||
2086 | fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL); | ||
2087 | if (!fcport) | ||
2088 | { | ||
2089 | rval = -ENOMEM; | ||
2090 | goto done_unmap_sg; | ||
2091 | } | ||
2092 | |||
2093 | /* Initialize all required fields of fcport */ | ||
2094 | fcport->vha = vha; | ||
2095 | fcport->vp_idx = vha->vp_idx; | ||
2096 | fcport->d_id.b.al_pa = bsg_job->request->rqst_data.h_ct.port_id[0]; | ||
2097 | fcport->d_id.b.area = bsg_job->request->rqst_data.h_ct.port_id[1]; | ||
2098 | fcport->d_id.b.domain = bsg_job->request->rqst_data.h_ct.port_id[2]; | ||
2099 | fcport->loop_id = loop_id; | ||
2100 | |||
2101 | /* Alloc SRB structure */ | ||
2102 | sp = qla2x00_get_ctx_bsg_sp(vha, fcport, sizeof(struct srb_bsg)); | ||
2103 | if (!sp) { | ||
2104 | rval = -ENOMEM; | ||
2105 | goto done_free_fcport; | ||
2106 | } | ||
2107 | |||
2108 | ct = sp->ctx; | ||
2109 | ct->ctx.type = SRB_CT_CMD; | ||
2110 | ct->bsg_job = bsg_job; | ||
2111 | |||
2112 | DEBUG2(qla_printk(KERN_INFO, ha, | ||
2113 | "scsi(%ld:%x): bsg rqst type: %s els type: %x - loop-id=%x " | ||
2114 | "portid=%02x%02x%02x.\n", vha->host_no, sp->handle, type, | ||
2115 | (bsg_job->request->rqst_data.h_ct.preamble_word2 >> 16), | ||
2116 | fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area, | ||
2117 | fcport->d_id.b.al_pa)); | ||
2118 | |||
2119 | rval = qla2x00_start_sp(sp); | ||
2120 | if (rval != QLA_SUCCESS) { | ||
2121 | kfree(sp->ctx); | ||
2122 | mempool_free(sp, ha->srb_mempool); | ||
2123 | rval = -EIO; | ||
2124 | goto done_free_fcport; | ||
2125 | } | ||
2126 | return rval; | ||
2127 | |||
2128 | done_free_fcport: | ||
2129 | kfree(fcport); | ||
2130 | done_unmap_sg: | ||
2131 | dma_unmap_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list, | ||
2132 | bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE); | ||
2133 | dma_unmap_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list, | ||
2134 | bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE); | ||
2135 | done: | ||
2136 | return rval; | ||
2137 | } | ||
2138 | |||
2139 | static int | ||
2140 | qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job) | ||
2141 | { | ||
2142 | struct Scsi_Host *host = bsg_job->shost; | ||
2143 | scsi_qla_host_t *vha = shost_priv(host); | ||
2144 | struct qla_hw_data *ha = vha->hw; | ||
2145 | int rval; | ||
2146 | uint8_t command_sent; | ||
2147 | uint32_t vendor_cmd; | ||
2148 | char *type; | ||
2149 | struct msg_echo_lb elreq; | ||
2150 | uint16_t response[MAILBOX_REGISTER_COUNT]; | ||
2151 | uint8_t* fw_sts_ptr; | ||
2152 | uint8_t *req_data; | ||
2153 | dma_addr_t req_data_dma; | ||
2154 | uint32_t req_data_len; | ||
2155 | uint8_t *rsp_data; | ||
2156 | dma_addr_t rsp_data_dma; | ||
2157 | uint32_t rsp_data_len; | ||
2158 | |||
2159 | if (test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) || | ||
2160 | test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) || | ||
2161 | test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) { | ||
2162 | rval = -EBUSY; | ||
2163 | goto done; | ||
2164 | } | ||
2165 | |||
2166 | if (!vha->flags.online) { | ||
2167 | DEBUG2(qla_printk(KERN_WARNING, ha, | ||
2168 | "host not online\n")); | ||
2169 | rval = -EIO; | ||
2170 | goto done; | ||
2171 | } | ||
2172 | |||
2173 | elreq.req_sg_cnt = | ||
2174 | dma_map_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list, | ||
2175 | bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE); | ||
2176 | if (!elreq.req_sg_cnt) { | ||
2177 | rval = -ENOMEM; | ||
2178 | goto done; | ||
2179 | } | ||
2180 | elreq.rsp_sg_cnt = | ||
2181 | dma_map_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list, | ||
2182 | bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE); | ||
2183 | if (!elreq.rsp_sg_cnt) { | ||
2184 | rval = -ENOMEM; | ||
2185 | goto done; | ||
2186 | } | ||
2187 | |||
2188 | if ((elreq.req_sg_cnt != bsg_job->request_payload.sg_cnt) || | ||
2189 | (elreq.rsp_sg_cnt != bsg_job->reply_payload.sg_cnt)) | ||
2190 | { | ||
2191 | DEBUG2(printk(KERN_INFO | ||
2192 | "dma mapping resulted in different sg counts \ | ||
2193 | [request_sg_cnt: %x dma_request_sg_cnt: %x\ | ||
2194 | reply_sg_cnt: %x dma_reply_sg_cnt: %x]\n", | ||
2195 | bsg_job->request_payload.sg_cnt, elreq.req_sg_cnt, | ||
2196 | bsg_job->reply_payload.sg_cnt, elreq.rsp_sg_cnt)); | ||
2197 | rval = -EAGAIN; | ||
2198 | goto done_unmap_sg; | ||
2199 | } | ||
2200 | req_data_len = rsp_data_len = bsg_job->request_payload.payload_len; | ||
2201 | req_data = dma_alloc_coherent(&ha->pdev->dev, req_data_len, | ||
2202 | &req_data_dma, GFP_KERNEL); | ||
2203 | |||
2204 | rsp_data = dma_alloc_coherent(&ha->pdev->dev, rsp_data_len, | ||
2205 | &rsp_data_dma, GFP_KERNEL); | ||
2206 | |||
2207 | /* Copy the request buffer in req_data now */ | ||
2208 | sg_copy_to_buffer(bsg_job->request_payload.sg_list, | ||
2209 | bsg_job->request_payload.sg_cnt, req_data, | ||
2210 | req_data_len); | ||
2211 | |||
2212 | elreq.send_dma = req_data_dma; | ||
2213 | elreq.rcv_dma = rsp_data_dma; | ||
2214 | elreq.transfer_size = req_data_len; | ||
2215 | |||
2216 | /* Vendor cmd : loopback or ECHO diagnostic | ||
2217 | * Options: | ||
2218 | * Loopback : Either internal or external loopback | ||
2219 | * ECHO: ECHO ELS or Vendor specific FC4 link data | ||
2220 | */ | ||
2221 | vendor_cmd = bsg_job->request->rqst_data.h_vendor.vendor_cmd[0]; | ||
2222 | elreq.options = | ||
2223 | *(((uint32_t *)bsg_job->request->rqst_data.h_vendor.vendor_cmd) | ||
2224 | + 1); | ||
2225 | |||
2226 | switch (bsg_job->request->rqst_data.h_vendor.vendor_cmd[0]) { | ||
2227 | case QL_VND_LOOPBACK: | ||
2228 | if (ha->current_topology != ISP_CFG_F) { | ||
2229 | type = "FC_BSG_HST_VENDOR_LOOPBACK"; | ||
2230 | |||
2231 | DEBUG2(qla_printk(KERN_INFO, ha, | ||
2232 | "scsi(%ld) bsg rqst type: %s vendor rqst type: %x options: %x.\n", | ||
2233 | vha->host_no, type, vendor_cmd, elreq.options)); | ||
2234 | |||
2235 | command_sent = INT_DEF_LB_LOOPBACK_CMD; | ||
2236 | rval = qla2x00_loopback_test(vha, &elreq, response); | ||
2237 | if (IS_QLA81XX(ha)) { | ||
2238 | if (response[0] == MBS_COMMAND_ERROR && response[1] == MBS_LB_RESET) { | ||
2239 | DEBUG2(printk(KERN_ERR "%s(%ld): ABORTing " | ||
2240 | "ISP\n", __func__, vha->host_no)); | ||
2241 | set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); | ||
2242 | qla2xxx_wake_dpc(vha); | ||
2243 | } | ||
2244 | } | ||
2245 | } else { | ||
2246 | type = "FC_BSG_HST_VENDOR_ECHO_DIAG"; | ||
2247 | DEBUG2(qla_printk(KERN_INFO, ha, | ||
2248 | "scsi(%ld) bsg rqst type: %s vendor rqst type: %x options: %x.\n", | ||
2249 | vha->host_no, type, vendor_cmd, elreq.options)); | ||
2250 | |||
2251 | command_sent = INT_DEF_LB_ECHO_CMD; | ||
2252 | rval = qla2x00_echo_test(vha, &elreq, response); | ||
2253 | } | ||
2254 | break; | ||
2255 | case QLA84_RESET: | ||
2256 | if (!IS_QLA84XX(vha->hw)) { | ||
2257 | rval = -EINVAL; | ||
2258 | DEBUG16(printk( | ||
2259 | "%s(%ld): 8xxx exiting.\n", | ||
2260 | __func__, vha->host_no)); | ||
2261 | return rval; | ||
2262 | } | ||
2263 | rval = qla84xx_reset(vha, &elreq, bsg_job); | ||
2264 | break; | ||
2265 | case QLA84_MGMT_CMD: | ||
2266 | if (!IS_QLA84XX(vha->hw)) { | ||
2267 | rval = -EINVAL; | ||
2268 | DEBUG16(printk( | ||
2269 | "%s(%ld): 8xxx exiting.\n", | ||
2270 | __func__, vha->host_no)); | ||
2271 | return rval; | ||
2272 | } | ||
2273 | rval = qla84xx_mgmt_cmd(vha, &elreq, bsg_job); | ||
2274 | break; | ||
2275 | default: | ||
2276 | rval = -ENOSYS; | ||
2277 | } | ||
2278 | |||
2279 | if (rval != QLA_SUCCESS) { | ||
2280 | DEBUG2(qla_printk(KERN_WARNING, ha, | ||
2281 | "scsi(%ld) Vendor request %s failed\n", vha->host_no, type)); | ||
2282 | rval = 0; | ||
2283 | bsg_job->reply->result = (DID_ERROR << 16); | ||
2284 | bsg_job->reply->reply_payload_rcv_len = 0; | ||
2285 | fw_sts_ptr = ((uint8_t*)bsg_job->req->sense) + sizeof(struct fc_bsg_reply); | ||
2286 | memcpy( fw_sts_ptr, response, sizeof(response)); | ||
2287 | fw_sts_ptr += sizeof(response); | ||
2288 | *fw_sts_ptr = command_sent; | ||
2289 | } else { | ||
2290 | DEBUG2(qla_printk(KERN_WARNING, ha, | ||
2291 | "scsi(%ld) Vendor request %s completed\n", vha->host_no, type)); | ||
2292 | rval = bsg_job->reply->result = 0; | ||
2293 | bsg_job->reply_len = sizeof(struct fc_bsg_reply) + sizeof(response) + sizeof(uint8_t); | ||
2294 | bsg_job->reply->reply_payload_rcv_len = bsg_job->reply_payload.payload_len; | ||
2295 | fw_sts_ptr = ((uint8_t*)bsg_job->req->sense) + sizeof(struct fc_bsg_reply); | ||
2296 | memcpy(fw_sts_ptr, response, sizeof(response)); | ||
2297 | fw_sts_ptr += sizeof(response); | ||
2298 | *fw_sts_ptr = command_sent; | ||
2299 | sg_copy_from_buffer(bsg_job->reply_payload.sg_list, | ||
2300 | bsg_job->reply_payload.sg_cnt, rsp_data, | ||
2301 | rsp_data_len); | ||
2302 | } | ||
2303 | bsg_job->job_done(bsg_job); | ||
2304 | |||
2305 | done_unmap_sg: | ||
2306 | |||
2307 | if(req_data) | ||
2308 | dma_free_coherent(&ha->pdev->dev, req_data_len, | ||
2309 | req_data, req_data_dma); | ||
2310 | dma_unmap_sg(&ha->pdev->dev, | ||
2311 | bsg_job->request_payload.sg_list, | ||
2312 | bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE); | ||
2313 | dma_unmap_sg(&ha->pdev->dev, | ||
2314 | bsg_job->reply_payload.sg_list, | ||
2315 | bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE); | ||
2316 | |||
2317 | done: | ||
2318 | return rval; | ||
2319 | } | ||
2320 | |||
2321 | static int | ||
2322 | qla24xx_bsg_request(struct fc_bsg_job *bsg_job) | ||
2323 | { | ||
2324 | int ret = -EINVAL; | ||
2325 | |||
2326 | switch (bsg_job->request->msgcode) { | ||
2327 | case FC_BSG_RPT_ELS: | ||
2328 | case FC_BSG_HST_ELS_NOLOGIN: | ||
2329 | ret = qla2x00_process_els(bsg_job); | ||
2330 | break; | ||
2331 | case FC_BSG_HST_CT: | ||
2332 | ret = qla2x00_process_ct(bsg_job); | ||
2333 | break; | ||
2334 | case FC_BSG_HST_VENDOR: | ||
2335 | ret = qla2x00_process_vendor_specific(bsg_job); | ||
2336 | break; | ||
2337 | case FC_BSG_HST_ADD_RPORT: | ||
2338 | case FC_BSG_HST_DEL_RPORT: | ||
2339 | case FC_BSG_RPT_CT: | ||
2340 | default: | ||
2341 | DEBUG2(printk("qla2xxx: unsupported BSG request\n")); | ||
2342 | break; | ||
2343 | } | ||
2344 | return ret; | ||
2345 | } | ||
2346 | |||
2347 | static int | ||
2348 | qla24xx_bsg_timeout(struct fc_bsg_job *bsg_job) | ||
2349 | { | ||
2350 | scsi_qla_host_t *vha = shost_priv(bsg_job->shost); | ||
2351 | struct qla_hw_data *ha = vha->hw; | ||
2352 | srb_t *sp; | ||
2353 | int cnt, que; | ||
2354 | unsigned long flags; | ||
2355 | struct req_que *req; | ||
2356 | struct srb_bsg *sp_bsg; | ||
2357 | |||
2358 | /* find the bsg job from the active list of commands */ | ||
2359 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
2360 | for (que = 0; que < ha->max_req_queues; que++) { | ||
2361 | req = ha->req_q_map[que]; | ||
2362 | if (!req) | ||
2363 | continue; | ||
2364 | |||
2365 | for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++ ) { | ||
2366 | sp = req->outstanding_cmds[cnt]; | ||
2367 | |||
2368 | if (sp) { | ||
2369 | sp_bsg = (struct srb_bsg*)sp->ctx; | ||
2370 | |||
2371 | if (((sp_bsg->ctx.type == SRB_CT_CMD) || | ||
2372 | (sp_bsg->ctx.type == SRB_ELS_CMD_RPT) | ||
2373 | || ( sp_bsg->ctx.type == SRB_ELS_CMD_HST)) && | ||
2374 | (sp_bsg->bsg_job == bsg_job)) { | ||
2375 | if (ha->isp_ops->abort_command(sp)) { | ||
2376 | DEBUG2(qla_printk(KERN_INFO, ha, | ||
2377 | "scsi(%ld): mbx abort_command failed\n", vha->host_no)); | ||
2378 | bsg_job->req->errors = bsg_job->reply->result = -EIO; | ||
2379 | } else { | ||
2380 | DEBUG2(qla_printk(KERN_INFO, ha, | ||
2381 | "scsi(%ld): mbx abort_command success\n", vha->host_no)); | ||
2382 | bsg_job->req->errors = bsg_job->reply->result = 0; | ||
2383 | } | ||
2384 | goto done; | ||
2385 | } | ||
2386 | } | ||
2387 | } | ||
2388 | } | ||
2389 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
2390 | DEBUG2(qla_printk(KERN_INFO, ha, | ||
2391 | "scsi(%ld) SRB not found to abort\n", vha->host_no)); | ||
2392 | bsg_job->req->errors = bsg_job->reply->result = -ENXIO; | ||
2393 | return 0; | ||
2394 | |||
2395 | done: | ||
2396 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
2397 | if (bsg_job->request->msgcode == FC_BSG_HST_CT) | ||
2398 | kfree(sp->fcport); | ||
2399 | kfree(sp->ctx); | ||
2400 | mempool_free(sp, ha->srb_mempool); | ||
2401 | return 0; | ||
2402 | } | ||
2403 | |||
2404 | struct fc_function_template qla2xxx_transport_functions = { | 1870 | struct fc_function_template qla2xxx_transport_functions = { |
2405 | 1871 | ||
2406 | .show_host_node_name = 1, | 1872 | .show_host_node_name = 1, |
@@ -2502,7 +1968,7 @@ qla2x00_init_host_attr(scsi_qla_host_t *vha) | |||
2502 | fc_host_max_npiv_vports(vha->host) = ha->max_npiv_vports; | 1968 | fc_host_max_npiv_vports(vha->host) = ha->max_npiv_vports; |
2503 | fc_host_npiv_vports_inuse(vha->host) = ha->cur_vport_count; | 1969 | fc_host_npiv_vports_inuse(vha->host) = ha->cur_vport_count; |
2504 | 1970 | ||
2505 | if (IS_QLA81XX(ha)) | 1971 | if (IS_QLA8XXX_TYPE(ha)) |
2506 | speed = FC_PORTSPEED_10GBIT; | 1972 | speed = FC_PORTSPEED_10GBIT; |
2507 | else if (IS_QLA25XX(ha)) | 1973 | else if (IS_QLA25XX(ha)) |
2508 | speed = FC_PORTSPEED_8GBIT | FC_PORTSPEED_4GBIT | | 1974 | speed = FC_PORTSPEED_8GBIT | FC_PORTSPEED_4GBIT | |
@@ -2516,125 +1982,3 @@ qla2x00_init_host_attr(scsi_qla_host_t *vha) | |||
2516 | speed = FC_PORTSPEED_1GBIT; | 1982 | speed = FC_PORTSPEED_1GBIT; |
2517 | fc_host_supported_speeds(vha->host) = speed; | 1983 | fc_host_supported_speeds(vha->host) = speed; |
2518 | } | 1984 | } |
2519 | static int | ||
2520 | qla84xx_reset(scsi_qla_host_t *ha, struct msg_echo_lb *mreq, struct fc_bsg_job *bsg_job) | ||
2521 | { | ||
2522 | int ret = 0; | ||
2523 | int cmd; | ||
2524 | uint16_t cmd_status; | ||
2525 | |||
2526 | DEBUG16(printk("%s(%ld): entered.\n", __func__, ha->host_no)); | ||
2527 | |||
2528 | cmd = (*((bsg_job->request->rqst_data.h_vendor.vendor_cmd) + 2)) | ||
2529 | == A84_RESET_FLAG_ENABLE_DIAG_FW ? | ||
2530 | A84_ISSUE_RESET_DIAG_FW : A84_ISSUE_RESET_OP_FW; | ||
2531 | ret = qla84xx_reset_chip(ha, cmd == A84_ISSUE_RESET_DIAG_FW, | ||
2532 | &cmd_status); | ||
2533 | return ret; | ||
2534 | } | ||
2535 | |||
2536 | static int | ||
2537 | qla84xx_mgmt_cmd(scsi_qla_host_t *ha, struct msg_echo_lb *mreq, struct fc_bsg_job *bsg_job) | ||
2538 | { | ||
2539 | struct access_chip_84xx *mn; | ||
2540 | dma_addr_t mn_dma, mgmt_dma; | ||
2541 | void *mgmt_b = NULL; | ||
2542 | int ret = 0; | ||
2543 | int rsp_hdr_len, len = 0; | ||
2544 | struct qla84_msg_mgmt *ql84_mgmt; | ||
2545 | |||
2546 | ql84_mgmt = (struct qla84_msg_mgmt *) vmalloc(sizeof(struct qla84_msg_mgmt)); | ||
2547 | ql84_mgmt->cmd = | ||
2548 | *((uint16_t *)(bsg_job->request->rqst_data.h_vendor.vendor_cmd + 2)); | ||
2549 | ql84_mgmt->mgmtp.u.mem.start_addr = | ||
2550 | *((uint32_t *)(bsg_job->request->rqst_data.h_vendor.vendor_cmd + 3)); | ||
2551 | ql84_mgmt->len = | ||
2552 | *((uint32_t *)(bsg_job->request->rqst_data.h_vendor.vendor_cmd + 4)); | ||
2553 | ql84_mgmt->mgmtp.u.config.id = | ||
2554 | *((uint32_t *)(bsg_job->request->rqst_data.h_vendor.vendor_cmd + 5)); | ||
2555 | ql84_mgmt->mgmtp.u.config.param0 = | ||
2556 | *((uint32_t *)(bsg_job->request->rqst_data.h_vendor.vendor_cmd + 6)); | ||
2557 | ql84_mgmt->mgmtp.u.config.param1 = | ||
2558 | *((uint32_t *)(bsg_job->request->rqst_data.h_vendor.vendor_cmd + 7)); | ||
2559 | ql84_mgmt->mgmtp.u.info.type = | ||
2560 | *((uint32_t *)(bsg_job->request->rqst_data.h_vendor.vendor_cmd + 8)); | ||
2561 | ql84_mgmt->mgmtp.u.info.context = | ||
2562 | *((uint32_t *)(bsg_job->request->rqst_data.h_vendor.vendor_cmd + 9)); | ||
2563 | |||
2564 | rsp_hdr_len = bsg_job->request_payload.payload_len; | ||
2565 | |||
2566 | mn = dma_pool_alloc(ha->hw->s_dma_pool, GFP_KERNEL, &mn_dma); | ||
2567 | if (mn == NULL) { | ||
2568 | DEBUG2(printk(KERN_ERR "%s: dma alloc for fw buffer " | ||
2569 | "failed%lu\n", __func__, ha->host_no)); | ||
2570 | return -ENOMEM; | ||
2571 | } | ||
2572 | |||
2573 | memset(mn, 0, sizeof (struct access_chip_84xx)); | ||
2574 | |||
2575 | mn->entry_type = ACCESS_CHIP_IOCB_TYPE; | ||
2576 | mn->entry_count = 1; | ||
2577 | |||
2578 | switch (ql84_mgmt->cmd) { | ||
2579 | case QLA84_MGMT_READ_MEM: | ||
2580 | mn->options = cpu_to_le16(ACO_DUMP_MEMORY); | ||
2581 | mn->parameter1 = cpu_to_le32(ql84_mgmt->mgmtp.u.mem.start_addr); | ||
2582 | break; | ||
2583 | case QLA84_MGMT_WRITE_MEM: | ||
2584 | mn->options = cpu_to_le16(ACO_LOAD_MEMORY); | ||
2585 | mn->parameter1 = cpu_to_le32(ql84_mgmt->mgmtp.u.mem.start_addr); | ||
2586 | break; | ||
2587 | case QLA84_MGMT_CHNG_CONFIG: | ||
2588 | mn->options = cpu_to_le16(ACO_CHANGE_CONFIG_PARAM); | ||
2589 | mn->parameter1 = cpu_to_le32(ql84_mgmt->mgmtp.u.config.id); | ||
2590 | mn->parameter2 = cpu_to_le32(ql84_mgmt->mgmtp.u.config.param0); | ||
2591 | mn->parameter3 = cpu_to_le32(ql84_mgmt->mgmtp.u.config.param1); | ||
2592 | break; | ||
2593 | case QLA84_MGMT_GET_INFO: | ||
2594 | mn->options = cpu_to_le16(ACO_REQUEST_INFO); | ||
2595 | mn->parameter1 = cpu_to_le32(ql84_mgmt->mgmtp.u.info.type); | ||
2596 | mn->parameter2 = cpu_to_le32(ql84_mgmt->mgmtp.u.info.context); | ||
2597 | break; | ||
2598 | default: | ||
2599 | ret = -EIO; | ||
2600 | goto exit_mgmt0; | ||
2601 | } | ||
2602 | |||
2603 | if ((len == ql84_mgmt->len) && | ||
2604 | ql84_mgmt->cmd != QLA84_MGMT_CHNG_CONFIG) { | ||
2605 | mgmt_b = dma_alloc_coherent(&ha->hw->pdev->dev, len, | ||
2606 | &mgmt_dma, GFP_KERNEL); | ||
2607 | if (mgmt_b == NULL) { | ||
2608 | DEBUG2(printk(KERN_ERR "%s: dma alloc mgmt_b " | ||
2609 | "failed%lu\n", __func__, ha->host_no)); | ||
2610 | ret = -ENOMEM; | ||
2611 | goto exit_mgmt0; | ||
2612 | } | ||
2613 | mn->total_byte_cnt = cpu_to_le32(ql84_mgmt->len); | ||
2614 | mn->dseg_count = cpu_to_le16(1); | ||
2615 | mn->dseg_address[0] = cpu_to_le32(LSD(mgmt_dma)); | ||
2616 | mn->dseg_address[1] = cpu_to_le32(MSD(mgmt_dma)); | ||
2617 | mn->dseg_length = cpu_to_le32(len); | ||
2618 | |||
2619 | if (ql84_mgmt->cmd == QLA84_MGMT_WRITE_MEM) { | ||
2620 | memcpy(mgmt_b, ql84_mgmt->payload, len); | ||
2621 | } | ||
2622 | } | ||
2623 | |||
2624 | ret = qla2x00_issue_iocb(ha, mn, mn_dma, 0); | ||
2625 | if ((ret != QLA_SUCCESS) || (ql84_mgmt->cmd == QLA84_MGMT_WRITE_MEM) | ||
2626 | || (ql84_mgmt->cmd == QLA84_MGMT_CHNG_CONFIG)) { | ||
2627 | if (ret != QLA_SUCCESS) | ||
2628 | DEBUG2(printk(KERN_ERR "%s(%lu): failed\n", | ||
2629 | __func__, ha->host_no)); | ||
2630 | } else if ((ql84_mgmt->cmd == QLA84_MGMT_READ_MEM) || | ||
2631 | (ql84_mgmt->cmd == QLA84_MGMT_GET_INFO)) { | ||
2632 | } | ||
2633 | |||
2634 | if (mgmt_b) | ||
2635 | dma_free_coherent(&ha->hw->pdev->dev, len, mgmt_b, mgmt_dma); | ||
2636 | |||
2637 | exit_mgmt0: | ||
2638 | dma_pool_free(ha->hw->s_dma_pool, mn, mn_dma); | ||
2639 | return ret; | ||
2640 | } | ||
diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c new file mode 100644 index 000000000000..b905dfe5ea61 --- /dev/null +++ b/drivers/scsi/qla2xxx/qla_bsg.c | |||
@@ -0,0 +1,1212 @@ | |||
1 | /* | ||
2 | * QLogic Fibre Channel HBA Driver | ||
3 | * Copyright (c) 2003-2008 QLogic Corporation | ||
4 | * | ||
5 | * See LICENSE.qla2xxx for copyright and licensing details. | ||
6 | */ | ||
7 | #include "qla_def.h" | ||
8 | |||
9 | #include <linux/kthread.h> | ||
10 | #include <linux/vmalloc.h> | ||
11 | #include <linux/delay.h> | ||
12 | |||
13 | /* BSG support for ELS/CT pass through */ | ||
14 | inline srb_t * | ||
15 | qla2x00_get_ctx_bsg_sp(scsi_qla_host_t *vha, fc_port_t *fcport, size_t size) | ||
16 | { | ||
17 | srb_t *sp; | ||
18 | struct qla_hw_data *ha = vha->hw; | ||
19 | struct srb_ctx *ctx; | ||
20 | |||
21 | sp = mempool_alloc(ha->srb_mempool, GFP_KERNEL); | ||
22 | if (!sp) | ||
23 | goto done; | ||
24 | ctx = kzalloc(size, GFP_KERNEL); | ||
25 | if (!ctx) { | ||
26 | mempool_free(sp, ha->srb_mempool); | ||
27 | sp = NULL; | ||
28 | goto done; | ||
29 | } | ||
30 | |||
31 | memset(sp, 0, sizeof(*sp)); | ||
32 | sp->fcport = fcport; | ||
33 | sp->ctx = ctx; | ||
34 | done: | ||
35 | return sp; | ||
36 | } | ||
37 | |||
38 | int | ||
39 | qla24xx_fcp_prio_cfg_valid(struct qla_fcp_prio_cfg *pri_cfg, uint8_t flag) | ||
40 | { | ||
41 | int i, ret, num_valid; | ||
42 | uint8_t *bcode; | ||
43 | struct qla_fcp_prio_entry *pri_entry; | ||
44 | |||
45 | ret = 1; | ||
46 | num_valid = 0; | ||
47 | bcode = (uint8_t *)pri_cfg; | ||
48 | |||
49 | if (bcode[0x0] != 'H' || bcode[0x1] != 'Q' || bcode[0x2] != 'O' || | ||
50 | bcode[0x3] != 'S') { | ||
51 | return 0; | ||
52 | } | ||
53 | if (flag != 1) | ||
54 | return ret; | ||
55 | |||
56 | pri_entry = &pri_cfg->entry[0]; | ||
57 | for (i = 0; i < pri_cfg->num_entries; i++) { | ||
58 | if (pri_entry->flags & FCP_PRIO_ENTRY_TAG_VALID) | ||
59 | num_valid++; | ||
60 | pri_entry++; | ||
61 | } | ||
62 | |||
63 | if (num_valid == 0) | ||
64 | ret = 0; | ||
65 | |||
66 | return ret; | ||
67 | } | ||
68 | |||
69 | static int | ||
70 | qla24xx_proc_fcp_prio_cfg_cmd(struct fc_bsg_job *bsg_job) | ||
71 | { | ||
72 | struct Scsi_Host *host = bsg_job->shost; | ||
73 | scsi_qla_host_t *vha = shost_priv(host); | ||
74 | struct qla_hw_data *ha = vha->hw; | ||
75 | int ret = 0; | ||
76 | uint32_t len; | ||
77 | uint32_t oper; | ||
78 | |||
79 | bsg_job->reply->reply_payload_rcv_len = 0; | ||
80 | |||
81 | if (test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) || | ||
82 | test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) || | ||
83 | test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) { | ||
84 | ret = -EBUSY; | ||
85 | goto exit_fcp_prio_cfg; | ||
86 | } | ||
87 | |||
88 | /* Get the sub command */ | ||
89 | oper = bsg_job->request->rqst_data.h_vendor.vendor_cmd[1]; | ||
90 | |||
91 | /* Only set config is allowed if config memory is not allocated */ | ||
92 | if (!ha->fcp_prio_cfg && (oper != QLFC_FCP_PRIO_SET_CONFIG)) { | ||
93 | ret = -EINVAL; | ||
94 | goto exit_fcp_prio_cfg; | ||
95 | } | ||
96 | switch (oper) { | ||
97 | case QLFC_FCP_PRIO_DISABLE: | ||
98 | if (ha->flags.fcp_prio_enabled) { | ||
99 | ha->flags.fcp_prio_enabled = 0; | ||
100 | ha->fcp_prio_cfg->attributes &= | ||
101 | ~FCP_PRIO_ATTR_ENABLE; | ||
102 | qla24xx_update_all_fcp_prio(vha); | ||
103 | bsg_job->reply->result = DID_OK; | ||
104 | } else { | ||
105 | ret = -EINVAL; | ||
106 | bsg_job->reply->result = (DID_ERROR << 16); | ||
107 | goto exit_fcp_prio_cfg; | ||
108 | } | ||
109 | break; | ||
110 | |||
111 | case QLFC_FCP_PRIO_ENABLE: | ||
112 | if (!ha->flags.fcp_prio_enabled) { | ||
113 | if (ha->fcp_prio_cfg) { | ||
114 | ha->flags.fcp_prio_enabled = 1; | ||
115 | ha->fcp_prio_cfg->attributes |= | ||
116 | FCP_PRIO_ATTR_ENABLE; | ||
117 | qla24xx_update_all_fcp_prio(vha); | ||
118 | bsg_job->reply->result = DID_OK; | ||
119 | } else { | ||
120 | ret = -EINVAL; | ||
121 | bsg_job->reply->result = (DID_ERROR << 16); | ||
122 | goto exit_fcp_prio_cfg; | ||
123 | } | ||
124 | } | ||
125 | break; | ||
126 | |||
127 | case QLFC_FCP_PRIO_GET_CONFIG: | ||
128 | len = bsg_job->reply_payload.payload_len; | ||
129 | if (!len || len > FCP_PRIO_CFG_SIZE) { | ||
130 | ret = -EINVAL; | ||
131 | bsg_job->reply->result = (DID_ERROR << 16); | ||
132 | goto exit_fcp_prio_cfg; | ||
133 | } | ||
134 | |||
135 | bsg_job->reply->result = DID_OK; | ||
136 | bsg_job->reply->reply_payload_rcv_len = | ||
137 | sg_copy_from_buffer( | ||
138 | bsg_job->reply_payload.sg_list, | ||
139 | bsg_job->reply_payload.sg_cnt, ha->fcp_prio_cfg, | ||
140 | len); | ||
141 | |||
142 | break; | ||
143 | |||
144 | case QLFC_FCP_PRIO_SET_CONFIG: | ||
145 | len = bsg_job->request_payload.payload_len; | ||
146 | if (!len || len > FCP_PRIO_CFG_SIZE) { | ||
147 | bsg_job->reply->result = (DID_ERROR << 16); | ||
148 | ret = -EINVAL; | ||
149 | goto exit_fcp_prio_cfg; | ||
150 | } | ||
151 | |||
152 | if (!ha->fcp_prio_cfg) { | ||
153 | ha->fcp_prio_cfg = vmalloc(FCP_PRIO_CFG_SIZE); | ||
154 | if (!ha->fcp_prio_cfg) { | ||
155 | qla_printk(KERN_WARNING, ha, | ||
156 | "Unable to allocate memory " | ||
157 | "for fcp prio config data (%x).\n", | ||
158 | FCP_PRIO_CFG_SIZE); | ||
159 | bsg_job->reply->result = (DID_ERROR << 16); | ||
160 | ret = -ENOMEM; | ||
161 | goto exit_fcp_prio_cfg; | ||
162 | } | ||
163 | } | ||
164 | |||
165 | memset(ha->fcp_prio_cfg, 0, FCP_PRIO_CFG_SIZE); | ||
166 | sg_copy_to_buffer(bsg_job->request_payload.sg_list, | ||
167 | bsg_job->request_payload.sg_cnt, ha->fcp_prio_cfg, | ||
168 | FCP_PRIO_CFG_SIZE); | ||
169 | |||
170 | /* validate fcp priority data */ | ||
171 | if (!qla24xx_fcp_prio_cfg_valid( | ||
172 | (struct qla_fcp_prio_cfg *) | ||
173 | ha->fcp_prio_cfg, 1)) { | ||
174 | bsg_job->reply->result = (DID_ERROR << 16); | ||
175 | ret = -EINVAL; | ||
176 | /* If buffer was invalidatic int | ||
177 | * fcp_prio_cfg is of no use | ||
178 | */ | ||
179 | vfree(ha->fcp_prio_cfg); | ||
180 | ha->fcp_prio_cfg = NULL; | ||
181 | goto exit_fcp_prio_cfg; | ||
182 | } | ||
183 | |||
184 | ha->flags.fcp_prio_enabled = 0; | ||
185 | if (ha->fcp_prio_cfg->attributes & FCP_PRIO_ATTR_ENABLE) | ||
186 | ha->flags.fcp_prio_enabled = 1; | ||
187 | qla24xx_update_all_fcp_prio(vha); | ||
188 | bsg_job->reply->result = DID_OK; | ||
189 | break; | ||
190 | default: | ||
191 | ret = -EINVAL; | ||
192 | break; | ||
193 | } | ||
194 | exit_fcp_prio_cfg: | ||
195 | bsg_job->job_done(bsg_job); | ||
196 | return ret; | ||
197 | } | ||
198 | static int | ||
199 | qla2x00_process_els(struct fc_bsg_job *bsg_job) | ||
200 | { | ||
201 | struct fc_rport *rport; | ||
202 | fc_port_t *fcport; | ||
203 | struct Scsi_Host *host; | ||
204 | scsi_qla_host_t *vha; | ||
205 | struct qla_hw_data *ha; | ||
206 | srb_t *sp; | ||
207 | const char *type; | ||
208 | int req_sg_cnt, rsp_sg_cnt; | ||
209 | int rval = (DRIVER_ERROR << 16); | ||
210 | uint16_t nextlid = 0; | ||
211 | struct srb_ctx *els; | ||
212 | |||
213 | /* Multiple SG's are not supported for ELS requests */ | ||
214 | if (bsg_job->request_payload.sg_cnt > 1 || | ||
215 | bsg_job->reply_payload.sg_cnt > 1) { | ||
216 | DEBUG2(printk(KERN_INFO | ||
217 | "multiple SG's are not supported for ELS requests" | ||
218 | " [request_sg_cnt: %x reply_sg_cnt: %x]\n", | ||
219 | bsg_job->request_payload.sg_cnt, | ||
220 | bsg_job->reply_payload.sg_cnt)); | ||
221 | rval = -EPERM; | ||
222 | goto done; | ||
223 | } | ||
224 | |||
225 | /* ELS request for rport */ | ||
226 | if (bsg_job->request->msgcode == FC_BSG_RPT_ELS) { | ||
227 | rport = bsg_job->rport; | ||
228 | fcport = *(fc_port_t **) rport->dd_data; | ||
229 | host = rport_to_shost(rport); | ||
230 | vha = shost_priv(host); | ||
231 | ha = vha->hw; | ||
232 | type = "FC_BSG_RPT_ELS"; | ||
233 | |||
234 | /* make sure the rport is logged in, | ||
235 | * if not perform fabric login | ||
236 | */ | ||
237 | if (qla2x00_fabric_login(vha, fcport, &nextlid)) { | ||
238 | DEBUG2(qla_printk(KERN_WARNING, ha, | ||
239 | "failed to login port %06X for ELS passthru\n", | ||
240 | fcport->d_id.b24)); | ||
241 | rval = -EIO; | ||
242 | goto done; | ||
243 | } | ||
244 | } else { | ||
245 | host = bsg_job->shost; | ||
246 | vha = shost_priv(host); | ||
247 | ha = vha->hw; | ||
248 | type = "FC_BSG_HST_ELS_NOLOGIN"; | ||
249 | |||
250 | /* Allocate a dummy fcport structure, since functions | ||
251 | * preparing the IOCB and mailbox command retrieves port | ||
252 | * specific information from fcport structure. For Host based | ||
253 | * ELS commands there will be no fcport structure allocated | ||
254 | */ | ||
255 | fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL); | ||
256 | if (!fcport) { | ||
257 | rval = -ENOMEM; | ||
258 | goto done; | ||
259 | } | ||
260 | |||
261 | /* Initialize all required fields of fcport */ | ||
262 | fcport->vha = vha; | ||
263 | fcport->vp_idx = vha->vp_idx; | ||
264 | fcport->d_id.b.al_pa = | ||
265 | bsg_job->request->rqst_data.h_els.port_id[0]; | ||
266 | fcport->d_id.b.area = | ||
267 | bsg_job->request->rqst_data.h_els.port_id[1]; | ||
268 | fcport->d_id.b.domain = | ||
269 | bsg_job->request->rqst_data.h_els.port_id[2]; | ||
270 | fcport->loop_id = | ||
271 | (fcport->d_id.b.al_pa == 0xFD) ? | ||
272 | NPH_FABRIC_CONTROLLER : NPH_F_PORT; | ||
273 | } | ||
274 | |||
275 | if (!vha->flags.online) { | ||
276 | DEBUG2(qla_printk(KERN_WARNING, ha, | ||
277 | "host not online\n")); | ||
278 | rval = -EIO; | ||
279 | goto done; | ||
280 | } | ||
281 | |||
282 | req_sg_cnt = | ||
283 | dma_map_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list, | ||
284 | bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE); | ||
285 | if (!req_sg_cnt) { | ||
286 | rval = -ENOMEM; | ||
287 | goto done_free_fcport; | ||
288 | } | ||
289 | |||
290 | rsp_sg_cnt = dma_map_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list, | ||
291 | bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE); | ||
292 | if (!rsp_sg_cnt) { | ||
293 | rval = -ENOMEM; | ||
294 | goto done_free_fcport; | ||
295 | } | ||
296 | |||
297 | if ((req_sg_cnt != bsg_job->request_payload.sg_cnt) || | ||
298 | (rsp_sg_cnt != bsg_job->reply_payload.sg_cnt)) { | ||
299 | DEBUG2(printk(KERN_INFO | ||
300 | "dma mapping resulted in different sg counts \ | ||
301 | [request_sg_cnt: %x dma_request_sg_cnt: %x\ | ||
302 | reply_sg_cnt: %x dma_reply_sg_cnt: %x]\n", | ||
303 | bsg_job->request_payload.sg_cnt, req_sg_cnt, | ||
304 | bsg_job->reply_payload.sg_cnt, rsp_sg_cnt)); | ||
305 | rval = -EAGAIN; | ||
306 | goto done_unmap_sg; | ||
307 | } | ||
308 | |||
309 | /* Alloc SRB structure */ | ||
310 | sp = qla2x00_get_ctx_bsg_sp(vha, fcport, sizeof(struct srb_ctx)); | ||
311 | if (!sp) { | ||
312 | rval = -ENOMEM; | ||
313 | goto done_unmap_sg; | ||
314 | } | ||
315 | |||
316 | els = sp->ctx; | ||
317 | els->type = | ||
318 | (bsg_job->request->msgcode == FC_BSG_RPT_ELS ? | ||
319 | SRB_ELS_CMD_RPT : SRB_ELS_CMD_HST); | ||
320 | els->name = | ||
321 | (bsg_job->request->msgcode == FC_BSG_RPT_ELS ? | ||
322 | "bsg_els_rpt" : "bsg_els_hst"); | ||
323 | els->u.bsg_job = bsg_job; | ||
324 | |||
325 | DEBUG2(qla_printk(KERN_INFO, ha, | ||
326 | "scsi(%ld:%x): bsg rqst type: %s els type: %x - loop-id=%x " | ||
327 | "portid=%02x%02x%02x.\n", vha->host_no, sp->handle, type, | ||
328 | bsg_job->request->rqst_data.h_els.command_code, | ||
329 | fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area, | ||
330 | fcport->d_id.b.al_pa)); | ||
331 | |||
332 | rval = qla2x00_start_sp(sp); | ||
333 | if (rval != QLA_SUCCESS) { | ||
334 | kfree(sp->ctx); | ||
335 | mempool_free(sp, ha->srb_mempool); | ||
336 | rval = -EIO; | ||
337 | goto done_unmap_sg; | ||
338 | } | ||
339 | return rval; | ||
340 | |||
341 | done_unmap_sg: | ||
342 | dma_unmap_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list, | ||
343 | bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE); | ||
344 | dma_unmap_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list, | ||
345 | bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE); | ||
346 | goto done_free_fcport; | ||
347 | |||
348 | done_free_fcport: | ||
349 | if (bsg_job->request->msgcode == FC_BSG_HST_ELS_NOLOGIN) | ||
350 | kfree(fcport); | ||
351 | done: | ||
352 | return rval; | ||
353 | } | ||
354 | |||
355 | static int | ||
356 | qla2x00_process_ct(struct fc_bsg_job *bsg_job) | ||
357 | { | ||
358 | srb_t *sp; | ||
359 | struct Scsi_Host *host = bsg_job->shost; | ||
360 | scsi_qla_host_t *vha = shost_priv(host); | ||
361 | struct qla_hw_data *ha = vha->hw; | ||
362 | int rval = (DRIVER_ERROR << 16); | ||
363 | int req_sg_cnt, rsp_sg_cnt; | ||
364 | uint16_t loop_id; | ||
365 | struct fc_port *fcport; | ||
366 | char *type = "FC_BSG_HST_CT"; | ||
367 | struct srb_ctx *ct; | ||
368 | |||
369 | /* pass through is supported only for ISP 4Gb or higher */ | ||
370 | if (!IS_FWI2_CAPABLE(ha)) { | ||
371 | DEBUG2(qla_printk(KERN_INFO, ha, | ||
372 | "scsi(%ld):Firmware is not capable to support FC " | ||
373 | "CT pass thru\n", vha->host_no)); | ||
374 | rval = -EPERM; | ||
375 | goto done; | ||
376 | } | ||
377 | |||
378 | req_sg_cnt = | ||
379 | dma_map_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list, | ||
380 | bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE); | ||
381 | if (!req_sg_cnt) { | ||
382 | rval = -ENOMEM; | ||
383 | goto done; | ||
384 | } | ||
385 | |||
386 | rsp_sg_cnt = dma_map_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list, | ||
387 | bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE); | ||
388 | if (!rsp_sg_cnt) { | ||
389 | rval = -ENOMEM; | ||
390 | goto done; | ||
391 | } | ||
392 | |||
393 | if ((req_sg_cnt != bsg_job->request_payload.sg_cnt) || | ||
394 | (rsp_sg_cnt != bsg_job->reply_payload.sg_cnt)) { | ||
395 | DEBUG2(qla_printk(KERN_WARNING, ha, | ||
396 | "[request_sg_cnt: %x dma_request_sg_cnt: %x\ | ||
397 | reply_sg_cnt: %x dma_reply_sg_cnt: %x]\n", | ||
398 | bsg_job->request_payload.sg_cnt, req_sg_cnt, | ||
399 | bsg_job->reply_payload.sg_cnt, rsp_sg_cnt)); | ||
400 | rval = -EAGAIN; | ||
401 | goto done_unmap_sg; | ||
402 | } | ||
403 | |||
404 | if (!vha->flags.online) { | ||
405 | DEBUG2(qla_printk(KERN_WARNING, ha, | ||
406 | "host not online\n")); | ||
407 | rval = -EIO; | ||
408 | goto done_unmap_sg; | ||
409 | } | ||
410 | |||
411 | loop_id = | ||
412 | (bsg_job->request->rqst_data.h_ct.preamble_word1 & 0xFF000000) | ||
413 | >> 24; | ||
414 | switch (loop_id) { | ||
415 | case 0xFC: | ||
416 | loop_id = cpu_to_le16(NPH_SNS); | ||
417 | break; | ||
418 | case 0xFA: | ||
419 | loop_id = vha->mgmt_svr_loop_id; | ||
420 | break; | ||
421 | default: | ||
422 | DEBUG2(qla_printk(KERN_INFO, ha, | ||
423 | "Unknown loop id: %x\n", loop_id)); | ||
424 | rval = -EINVAL; | ||
425 | goto done_unmap_sg; | ||
426 | } | ||
427 | |||
428 | /* Allocate a dummy fcport structure, since functions preparing the | ||
429 | * IOCB and mailbox command retrieves port specific information | ||
430 | * from fcport structure. For Host based ELS commands there will be | ||
431 | * no fcport structure allocated | ||
432 | */ | ||
433 | fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL); | ||
434 | if (!fcport) { | ||
435 | rval = -ENOMEM; | ||
436 | goto done_unmap_sg; | ||
437 | } | ||
438 | |||
439 | /* Initialize all required fields of fcport */ | ||
440 | fcport->vha = vha; | ||
441 | fcport->vp_idx = vha->vp_idx; | ||
442 | fcport->d_id.b.al_pa = bsg_job->request->rqst_data.h_ct.port_id[0]; | ||
443 | fcport->d_id.b.area = bsg_job->request->rqst_data.h_ct.port_id[1]; | ||
444 | fcport->d_id.b.domain = bsg_job->request->rqst_data.h_ct.port_id[2]; | ||
445 | fcport->loop_id = loop_id; | ||
446 | |||
447 | /* Alloc SRB structure */ | ||
448 | sp = qla2x00_get_ctx_bsg_sp(vha, fcport, sizeof(struct srb_ctx)); | ||
449 | if (!sp) { | ||
450 | rval = -ENOMEM; | ||
451 | goto done_free_fcport; | ||
452 | } | ||
453 | |||
454 | ct = sp->ctx; | ||
455 | ct->type = SRB_CT_CMD; | ||
456 | ct->name = "bsg_ct"; | ||
457 | ct->u.bsg_job = bsg_job; | ||
458 | |||
459 | DEBUG2(qla_printk(KERN_INFO, ha, | ||
460 | "scsi(%ld:%x): bsg rqst type: %s els type: %x - loop-id=%x " | ||
461 | "portid=%02x%02x%02x.\n", vha->host_no, sp->handle, type, | ||
462 | (bsg_job->request->rqst_data.h_ct.preamble_word2 >> 16), | ||
463 | fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area, | ||
464 | fcport->d_id.b.al_pa)); | ||
465 | |||
466 | rval = qla2x00_start_sp(sp); | ||
467 | if (rval != QLA_SUCCESS) { | ||
468 | kfree(sp->ctx); | ||
469 | mempool_free(sp, ha->srb_mempool); | ||
470 | rval = -EIO; | ||
471 | goto done_free_fcport; | ||
472 | } | ||
473 | return rval; | ||
474 | |||
475 | done_free_fcport: | ||
476 | kfree(fcport); | ||
477 | done_unmap_sg: | ||
478 | dma_unmap_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list, | ||
479 | bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE); | ||
480 | dma_unmap_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list, | ||
481 | bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE); | ||
482 | done: | ||
483 | return rval; | ||
484 | } | ||
485 | |||
486 | static int | ||
487 | qla2x00_process_loopback(struct fc_bsg_job *bsg_job) | ||
488 | { | ||
489 | struct Scsi_Host *host = bsg_job->shost; | ||
490 | scsi_qla_host_t *vha = shost_priv(host); | ||
491 | struct qla_hw_data *ha = vha->hw; | ||
492 | int rval; | ||
493 | uint8_t command_sent; | ||
494 | char *type; | ||
495 | struct msg_echo_lb elreq; | ||
496 | uint16_t response[MAILBOX_REGISTER_COUNT]; | ||
497 | uint8_t *fw_sts_ptr; | ||
498 | uint8_t *req_data = NULL; | ||
499 | dma_addr_t req_data_dma; | ||
500 | uint32_t req_data_len; | ||
501 | uint8_t *rsp_data = NULL; | ||
502 | dma_addr_t rsp_data_dma; | ||
503 | uint32_t rsp_data_len; | ||
504 | |||
505 | if (test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) || | ||
506 | test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) || | ||
507 | test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) | ||
508 | return -EBUSY; | ||
509 | |||
510 | if (!vha->flags.online) { | ||
511 | DEBUG2(qla_printk(KERN_WARNING, ha, "host not online\n")); | ||
512 | return -EIO; | ||
513 | } | ||
514 | |||
515 | elreq.req_sg_cnt = dma_map_sg(&ha->pdev->dev, | ||
516 | bsg_job->request_payload.sg_list, bsg_job->request_payload.sg_cnt, | ||
517 | DMA_TO_DEVICE); | ||
518 | |||
519 | if (!elreq.req_sg_cnt) | ||
520 | return -ENOMEM; | ||
521 | |||
522 | elreq.rsp_sg_cnt = dma_map_sg(&ha->pdev->dev, | ||
523 | bsg_job->reply_payload.sg_list, bsg_job->reply_payload.sg_cnt, | ||
524 | DMA_FROM_DEVICE); | ||
525 | |||
526 | if (!elreq.rsp_sg_cnt) { | ||
527 | rval = -ENOMEM; | ||
528 | goto done_unmap_req_sg; | ||
529 | } | ||
530 | |||
531 | if ((elreq.req_sg_cnt != bsg_job->request_payload.sg_cnt) || | ||
532 | (elreq.rsp_sg_cnt != bsg_job->reply_payload.sg_cnt)) { | ||
533 | DEBUG2(printk(KERN_INFO | ||
534 | "dma mapping resulted in different sg counts " | ||
535 | "[request_sg_cnt: %x dma_request_sg_cnt: %x " | ||
536 | "reply_sg_cnt: %x dma_reply_sg_cnt: %x]\n", | ||
537 | bsg_job->request_payload.sg_cnt, elreq.req_sg_cnt, | ||
538 | bsg_job->reply_payload.sg_cnt, elreq.rsp_sg_cnt)); | ||
539 | rval = -EAGAIN; | ||
540 | goto done_unmap_sg; | ||
541 | } | ||
542 | req_data_len = rsp_data_len = bsg_job->request_payload.payload_len; | ||
543 | req_data = dma_alloc_coherent(&ha->pdev->dev, req_data_len, | ||
544 | &req_data_dma, GFP_KERNEL); | ||
545 | if (!req_data) { | ||
546 | DEBUG2(printk(KERN_ERR "%s: dma alloc for req_data " | ||
547 | "failed for host=%lu\n", __func__, vha->host_no)); | ||
548 | rval = -ENOMEM; | ||
549 | goto done_unmap_sg; | ||
550 | } | ||
551 | |||
552 | rsp_data = dma_alloc_coherent(&ha->pdev->dev, rsp_data_len, | ||
553 | &rsp_data_dma, GFP_KERNEL); | ||
554 | if (!rsp_data) { | ||
555 | DEBUG2(printk(KERN_ERR "%s: dma alloc for rsp_data " | ||
556 | "failed for host=%lu\n", __func__, vha->host_no)); | ||
557 | rval = -ENOMEM; | ||
558 | goto done_free_dma_req; | ||
559 | } | ||
560 | |||
561 | /* Copy the request buffer in req_data now */ | ||
562 | sg_copy_to_buffer(bsg_job->request_payload.sg_list, | ||
563 | bsg_job->request_payload.sg_cnt, req_data, req_data_len); | ||
564 | |||
565 | elreq.send_dma = req_data_dma; | ||
566 | elreq.rcv_dma = rsp_data_dma; | ||
567 | elreq.transfer_size = req_data_len; | ||
568 | |||
569 | elreq.options = bsg_job->request->rqst_data.h_vendor.vendor_cmd[1]; | ||
570 | |||
571 | if (ha->current_topology != ISP_CFG_F) { | ||
572 | type = "FC_BSG_HST_VENDOR_LOOPBACK"; | ||
573 | DEBUG2(qla_printk(KERN_INFO, ha, | ||
574 | "scsi(%ld) bsg rqst type: %s\n", | ||
575 | vha->host_no, type)); | ||
576 | |||
577 | command_sent = INT_DEF_LB_LOOPBACK_CMD; | ||
578 | rval = qla2x00_loopback_test(vha, &elreq, response); | ||
579 | if (IS_QLA81XX(ha)) { | ||
580 | if (response[0] == MBS_COMMAND_ERROR && | ||
581 | response[1] == MBS_LB_RESET) { | ||
582 | DEBUG2(printk(KERN_ERR "%s(%ld): ABORTing " | ||
583 | "ISP\n", __func__, vha->host_no)); | ||
584 | set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); | ||
585 | qla2xxx_wake_dpc(vha); | ||
586 | } | ||
587 | } | ||
588 | } else { | ||
589 | type = "FC_BSG_HST_VENDOR_ECHO_DIAG"; | ||
590 | DEBUG2(qla_printk(KERN_INFO, ha, | ||
591 | "scsi(%ld) bsg rqst type: %s\n", vha->host_no, type)); | ||
592 | command_sent = INT_DEF_LB_ECHO_CMD; | ||
593 | rval = qla2x00_echo_test(vha, &elreq, response); | ||
594 | } | ||
595 | |||
596 | if (rval) { | ||
597 | DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld) Vendor " | ||
598 | "request %s failed\n", vha->host_no, type)); | ||
599 | |||
600 | fw_sts_ptr = ((uint8_t *)bsg_job->req->sense) + | ||
601 | sizeof(struct fc_bsg_reply); | ||
602 | |||
603 | memcpy(fw_sts_ptr, response, sizeof(response)); | ||
604 | fw_sts_ptr += sizeof(response); | ||
605 | *fw_sts_ptr = command_sent; | ||
606 | rval = 0; | ||
607 | bsg_job->reply->reply_payload_rcv_len = 0; | ||
608 | bsg_job->reply->result = (DID_ERROR << 16); | ||
609 | } else { | ||
610 | DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld) Vendor " | ||
611 | "request %s completed\n", vha->host_no, type)); | ||
612 | |||
613 | bsg_job->reply_len = sizeof(struct fc_bsg_reply) + | ||
614 | sizeof(response) + sizeof(uint8_t); | ||
615 | bsg_job->reply->reply_payload_rcv_len = | ||
616 | bsg_job->reply_payload.payload_len; | ||
617 | fw_sts_ptr = ((uint8_t *)bsg_job->req->sense) + | ||
618 | sizeof(struct fc_bsg_reply); | ||
619 | memcpy(fw_sts_ptr, response, sizeof(response)); | ||
620 | fw_sts_ptr += sizeof(response); | ||
621 | *fw_sts_ptr = command_sent; | ||
622 | bsg_job->reply->result = DID_OK; | ||
623 | sg_copy_from_buffer(bsg_job->reply_payload.sg_list, | ||
624 | bsg_job->reply_payload.sg_cnt, rsp_data, | ||
625 | rsp_data_len); | ||
626 | } | ||
627 | bsg_job->job_done(bsg_job); | ||
628 | |||
629 | dma_free_coherent(&ha->pdev->dev, rsp_data_len, | ||
630 | rsp_data, rsp_data_dma); | ||
631 | done_free_dma_req: | ||
632 | dma_free_coherent(&ha->pdev->dev, req_data_len, | ||
633 | req_data, req_data_dma); | ||
634 | done_unmap_sg: | ||
635 | dma_unmap_sg(&ha->pdev->dev, | ||
636 | bsg_job->reply_payload.sg_list, | ||
637 | bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE); | ||
638 | done_unmap_req_sg: | ||
639 | dma_unmap_sg(&ha->pdev->dev, | ||
640 | bsg_job->request_payload.sg_list, | ||
641 | bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE); | ||
642 | return rval; | ||
643 | } | ||
644 | |||
645 | static int | ||
646 | qla84xx_reset(struct fc_bsg_job *bsg_job) | ||
647 | { | ||
648 | struct Scsi_Host *host = bsg_job->shost; | ||
649 | scsi_qla_host_t *vha = shost_priv(host); | ||
650 | struct qla_hw_data *ha = vha->hw; | ||
651 | int rval = 0; | ||
652 | uint32_t flag; | ||
653 | |||
654 | if (test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) || | ||
655 | test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) || | ||
656 | test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) | ||
657 | return -EBUSY; | ||
658 | |||
659 | if (!IS_QLA84XX(ha)) { | ||
660 | DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld): Not 84xx, " | ||
661 | "exiting.\n", vha->host_no)); | ||
662 | return -EINVAL; | ||
663 | } | ||
664 | |||
665 | flag = bsg_job->request->rqst_data.h_vendor.vendor_cmd[1]; | ||
666 | |||
667 | rval = qla84xx_reset_chip(vha, flag == A84_ISSUE_RESET_DIAG_FW); | ||
668 | |||
669 | if (rval) { | ||
670 | DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld) Vendor " | ||
671 | "request 84xx reset failed\n", vha->host_no)); | ||
672 | rval = bsg_job->reply->reply_payload_rcv_len = 0; | ||
673 | bsg_job->reply->result = (DID_ERROR << 16); | ||
674 | |||
675 | } else { | ||
676 | DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld) Vendor " | ||
677 | "request 84xx reset completed\n", vha->host_no)); | ||
678 | bsg_job->reply->result = DID_OK; | ||
679 | } | ||
680 | |||
681 | bsg_job->job_done(bsg_job); | ||
682 | return rval; | ||
683 | } | ||
684 | |||
685 | static int | ||
686 | qla84xx_updatefw(struct fc_bsg_job *bsg_job) | ||
687 | { | ||
688 | struct Scsi_Host *host = bsg_job->shost; | ||
689 | scsi_qla_host_t *vha = shost_priv(host); | ||
690 | struct qla_hw_data *ha = vha->hw; | ||
691 | struct verify_chip_entry_84xx *mn = NULL; | ||
692 | dma_addr_t mn_dma, fw_dma; | ||
693 | void *fw_buf = NULL; | ||
694 | int rval = 0; | ||
695 | uint32_t sg_cnt; | ||
696 | uint32_t data_len; | ||
697 | uint16_t options; | ||
698 | uint32_t flag; | ||
699 | uint32_t fw_ver; | ||
700 | |||
701 | if (test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) || | ||
702 | test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) || | ||
703 | test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) | ||
704 | return -EBUSY; | ||
705 | |||
706 | if (!IS_QLA84XX(ha)) { | ||
707 | DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld): Not 84xx, " | ||
708 | "exiting.\n", vha->host_no)); | ||
709 | return -EINVAL; | ||
710 | } | ||
711 | |||
712 | sg_cnt = dma_map_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list, | ||
713 | bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE); | ||
714 | if (!sg_cnt) | ||
715 | return -ENOMEM; | ||
716 | |||
717 | if (sg_cnt != bsg_job->request_payload.sg_cnt) { | ||
718 | DEBUG2(printk(KERN_INFO | ||
719 | "dma mapping resulted in different sg counts " | ||
720 | "request_sg_cnt: %x dma_request_sg_cnt: %x ", | ||
721 | bsg_job->request_payload.sg_cnt, sg_cnt)); | ||
722 | rval = -EAGAIN; | ||
723 | goto done_unmap_sg; | ||
724 | } | ||
725 | |||
726 | data_len = bsg_job->request_payload.payload_len; | ||
727 | fw_buf = dma_alloc_coherent(&ha->pdev->dev, data_len, | ||
728 | &fw_dma, GFP_KERNEL); | ||
729 | if (!fw_buf) { | ||
730 | DEBUG2(printk(KERN_ERR "%s: dma alloc for fw_buf " | ||
731 | "failed for host=%lu\n", __func__, vha->host_no)); | ||
732 | rval = -ENOMEM; | ||
733 | goto done_unmap_sg; | ||
734 | } | ||
735 | |||
736 | sg_copy_to_buffer(bsg_job->request_payload.sg_list, | ||
737 | bsg_job->request_payload.sg_cnt, fw_buf, data_len); | ||
738 | |||
739 | mn = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &mn_dma); | ||
740 | if (!mn) { | ||
741 | DEBUG2(printk(KERN_ERR "%s: dma alloc for fw buffer " | ||
742 | "failed for host=%lu\n", __func__, vha->host_no)); | ||
743 | rval = -ENOMEM; | ||
744 | goto done_free_fw_buf; | ||
745 | } | ||
746 | |||
747 | flag = bsg_job->request->rqst_data.h_vendor.vendor_cmd[1]; | ||
748 | fw_ver = le32_to_cpu(*((uint32_t *)((uint32_t *)fw_buf + 2))); | ||
749 | |||
750 | memset(mn, 0, sizeof(struct access_chip_84xx)); | ||
751 | mn->entry_type = VERIFY_CHIP_IOCB_TYPE; | ||
752 | mn->entry_count = 1; | ||
753 | |||
754 | options = VCO_FORCE_UPDATE | VCO_END_OF_DATA; | ||
755 | if (flag == A84_ISSUE_UPDATE_DIAGFW_CMD) | ||
756 | options |= VCO_DIAG_FW; | ||
757 | |||
758 | mn->options = cpu_to_le16(options); | ||
759 | mn->fw_ver = cpu_to_le32(fw_ver); | ||
760 | mn->fw_size = cpu_to_le32(data_len); | ||
761 | mn->fw_seq_size = cpu_to_le32(data_len); | ||
762 | mn->dseg_address[0] = cpu_to_le32(LSD(fw_dma)); | ||
763 | mn->dseg_address[1] = cpu_to_le32(MSD(fw_dma)); | ||
764 | mn->dseg_length = cpu_to_le32(data_len); | ||
765 | mn->data_seg_cnt = cpu_to_le16(1); | ||
766 | |||
767 | rval = qla2x00_issue_iocb_timeout(vha, mn, mn_dma, 0, 120); | ||
768 | |||
769 | if (rval) { | ||
770 | DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld) Vendor " | ||
771 | "request 84xx updatefw failed\n", vha->host_no)); | ||
772 | |||
773 | rval = bsg_job->reply->reply_payload_rcv_len = 0; | ||
774 | bsg_job->reply->result = (DID_ERROR << 16); | ||
775 | |||
776 | } else { | ||
777 | DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld) Vendor " | ||
778 | "request 84xx updatefw completed\n", vha->host_no)); | ||
779 | |||
780 | bsg_job->reply_len = sizeof(struct fc_bsg_reply); | ||
781 | bsg_job->reply->result = DID_OK; | ||
782 | } | ||
783 | |||
784 | bsg_job->job_done(bsg_job); | ||
785 | dma_pool_free(ha->s_dma_pool, mn, mn_dma); | ||
786 | |||
787 | done_free_fw_buf: | ||
788 | dma_free_coherent(&ha->pdev->dev, data_len, fw_buf, fw_dma); | ||
789 | |||
790 | done_unmap_sg: | ||
791 | dma_unmap_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list, | ||
792 | bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE); | ||
793 | |||
794 | return rval; | ||
795 | } | ||
796 | |||
797 | static int | ||
798 | qla84xx_mgmt_cmd(struct fc_bsg_job *bsg_job) | ||
799 | { | ||
800 | struct Scsi_Host *host = bsg_job->shost; | ||
801 | scsi_qla_host_t *vha = shost_priv(host); | ||
802 | struct qla_hw_data *ha = vha->hw; | ||
803 | struct access_chip_84xx *mn = NULL; | ||
804 | dma_addr_t mn_dma, mgmt_dma; | ||
805 | void *mgmt_b = NULL; | ||
806 | int rval = 0; | ||
807 | struct qla_bsg_a84_mgmt *ql84_mgmt; | ||
808 | uint32_t sg_cnt; | ||
809 | uint32_t data_len = 0; | ||
810 | uint32_t dma_direction = DMA_NONE; | ||
811 | |||
812 | if (test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) || | ||
813 | test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) || | ||
814 | test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) | ||
815 | return -EBUSY; | ||
816 | |||
817 | if (!IS_QLA84XX(ha)) { | ||
818 | DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld): Not 84xx, " | ||
819 | "exiting.\n", vha->host_no)); | ||
820 | return -EINVAL; | ||
821 | } | ||
822 | |||
823 | ql84_mgmt = (struct qla_bsg_a84_mgmt *)((char *)bsg_job->request + | ||
824 | sizeof(struct fc_bsg_request)); | ||
825 | if (!ql84_mgmt) { | ||
826 | DEBUG2(printk("%s(%ld): mgmt header not provided, exiting.\n", | ||
827 | __func__, vha->host_no)); | ||
828 | return -EINVAL; | ||
829 | } | ||
830 | |||
831 | mn = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &mn_dma); | ||
832 | if (!mn) { | ||
833 | DEBUG2(printk(KERN_ERR "%s: dma alloc for fw buffer " | ||
834 | "failed for host=%lu\n", __func__, vha->host_no)); | ||
835 | return -ENOMEM; | ||
836 | } | ||
837 | |||
838 | memset(mn, 0, sizeof(struct access_chip_84xx)); | ||
839 | mn->entry_type = ACCESS_CHIP_IOCB_TYPE; | ||
840 | mn->entry_count = 1; | ||
841 | |||
842 | switch (ql84_mgmt->mgmt.cmd) { | ||
843 | case QLA84_MGMT_READ_MEM: | ||
844 | case QLA84_MGMT_GET_INFO: | ||
845 | sg_cnt = dma_map_sg(&ha->pdev->dev, | ||
846 | bsg_job->reply_payload.sg_list, | ||
847 | bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE); | ||
848 | if (!sg_cnt) { | ||
849 | rval = -ENOMEM; | ||
850 | goto exit_mgmt; | ||
851 | } | ||
852 | |||
853 | dma_direction = DMA_FROM_DEVICE; | ||
854 | |||
855 | if (sg_cnt != bsg_job->reply_payload.sg_cnt) { | ||
856 | DEBUG2(printk(KERN_INFO | ||
857 | "dma mapping resulted in different sg counts " | ||
858 | "reply_sg_cnt: %x dma_reply_sg_cnt: %x\n", | ||
859 | bsg_job->reply_payload.sg_cnt, sg_cnt)); | ||
860 | rval = -EAGAIN; | ||
861 | goto done_unmap_sg; | ||
862 | } | ||
863 | |||
864 | data_len = bsg_job->reply_payload.payload_len; | ||
865 | |||
866 | mgmt_b = dma_alloc_coherent(&ha->pdev->dev, data_len, | ||
867 | &mgmt_dma, GFP_KERNEL); | ||
868 | if (!mgmt_b) { | ||
869 | DEBUG2(printk(KERN_ERR "%s: dma alloc for mgmt_b " | ||
870 | "failed for host=%lu\n", | ||
871 | __func__, vha->host_no)); | ||
872 | rval = -ENOMEM; | ||
873 | goto done_unmap_sg; | ||
874 | } | ||
875 | |||
876 | if (ql84_mgmt->mgmt.cmd == QLA84_MGMT_READ_MEM) { | ||
877 | mn->options = cpu_to_le16(ACO_DUMP_MEMORY); | ||
878 | mn->parameter1 = | ||
879 | cpu_to_le32( | ||
880 | ql84_mgmt->mgmt.mgmtp.u.mem.start_addr); | ||
881 | |||
882 | } else if (ql84_mgmt->mgmt.cmd == QLA84_MGMT_GET_INFO) { | ||
883 | mn->options = cpu_to_le16(ACO_REQUEST_INFO); | ||
884 | mn->parameter1 = | ||
885 | cpu_to_le32(ql84_mgmt->mgmt.mgmtp.u.info.type); | ||
886 | |||
887 | mn->parameter2 = | ||
888 | cpu_to_le32( | ||
889 | ql84_mgmt->mgmt.mgmtp.u.info.context); | ||
890 | } | ||
891 | break; | ||
892 | |||
893 | case QLA84_MGMT_WRITE_MEM: | ||
894 | sg_cnt = dma_map_sg(&ha->pdev->dev, | ||
895 | bsg_job->request_payload.sg_list, | ||
896 | bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE); | ||
897 | |||
898 | if (!sg_cnt) { | ||
899 | rval = -ENOMEM; | ||
900 | goto exit_mgmt; | ||
901 | } | ||
902 | |||
903 | dma_direction = DMA_TO_DEVICE; | ||
904 | |||
905 | if (sg_cnt != bsg_job->request_payload.sg_cnt) { | ||
906 | DEBUG2(printk(KERN_INFO | ||
907 | "dma mapping resulted in different sg counts " | ||
908 | "request_sg_cnt: %x dma_request_sg_cnt: %x ", | ||
909 | bsg_job->request_payload.sg_cnt, sg_cnt)); | ||
910 | rval = -EAGAIN; | ||
911 | goto done_unmap_sg; | ||
912 | } | ||
913 | |||
914 | data_len = bsg_job->request_payload.payload_len; | ||
915 | mgmt_b = dma_alloc_coherent(&ha->pdev->dev, data_len, | ||
916 | &mgmt_dma, GFP_KERNEL); | ||
917 | if (!mgmt_b) { | ||
918 | DEBUG2(printk(KERN_ERR "%s: dma alloc for mgmt_b " | ||
919 | "failed for host=%lu\n", | ||
920 | __func__, vha->host_no)); | ||
921 | rval = -ENOMEM; | ||
922 | goto done_unmap_sg; | ||
923 | } | ||
924 | |||
925 | sg_copy_to_buffer(bsg_job->request_payload.sg_list, | ||
926 | bsg_job->request_payload.sg_cnt, mgmt_b, data_len); | ||
927 | |||
928 | mn->options = cpu_to_le16(ACO_LOAD_MEMORY); | ||
929 | mn->parameter1 = | ||
930 | cpu_to_le32(ql84_mgmt->mgmt.mgmtp.u.mem.start_addr); | ||
931 | break; | ||
932 | |||
933 | case QLA84_MGMT_CHNG_CONFIG: | ||
934 | mn->options = cpu_to_le16(ACO_CHANGE_CONFIG_PARAM); | ||
935 | mn->parameter1 = | ||
936 | cpu_to_le32(ql84_mgmt->mgmt.mgmtp.u.config.id); | ||
937 | |||
938 | mn->parameter2 = | ||
939 | cpu_to_le32(ql84_mgmt->mgmt.mgmtp.u.config.param0); | ||
940 | |||
941 | mn->parameter3 = | ||
942 | cpu_to_le32(ql84_mgmt->mgmt.mgmtp.u.config.param1); | ||
943 | break; | ||
944 | |||
945 | default: | ||
946 | rval = -EIO; | ||
947 | goto exit_mgmt; | ||
948 | } | ||
949 | |||
950 | if (ql84_mgmt->mgmt.cmd != QLA84_MGMT_CHNG_CONFIG) { | ||
951 | mn->total_byte_cnt = cpu_to_le32(ql84_mgmt->mgmt.len); | ||
952 | mn->dseg_count = cpu_to_le16(1); | ||
953 | mn->dseg_address[0] = cpu_to_le32(LSD(mgmt_dma)); | ||
954 | mn->dseg_address[1] = cpu_to_le32(MSD(mgmt_dma)); | ||
955 | mn->dseg_length = cpu_to_le32(ql84_mgmt->mgmt.len); | ||
956 | } | ||
957 | |||
958 | rval = qla2x00_issue_iocb(vha, mn, mn_dma, 0); | ||
959 | |||
960 | if (rval) { | ||
961 | DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld) Vendor " | ||
962 | "request 84xx mgmt failed\n", vha->host_no)); | ||
963 | |||
964 | rval = bsg_job->reply->reply_payload_rcv_len = 0; | ||
965 | bsg_job->reply->result = (DID_ERROR << 16); | ||
966 | |||
967 | } else { | ||
968 | DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld) Vendor " | ||
969 | "request 84xx mgmt completed\n", vha->host_no)); | ||
970 | |||
971 | bsg_job->reply_len = sizeof(struct fc_bsg_reply); | ||
972 | bsg_job->reply->result = DID_OK; | ||
973 | |||
974 | if ((ql84_mgmt->mgmt.cmd == QLA84_MGMT_READ_MEM) || | ||
975 | (ql84_mgmt->mgmt.cmd == QLA84_MGMT_GET_INFO)) { | ||
976 | bsg_job->reply->reply_payload_rcv_len = | ||
977 | bsg_job->reply_payload.payload_len; | ||
978 | |||
979 | sg_copy_from_buffer(bsg_job->reply_payload.sg_list, | ||
980 | bsg_job->reply_payload.sg_cnt, mgmt_b, | ||
981 | data_len); | ||
982 | } | ||
983 | } | ||
984 | |||
985 | bsg_job->job_done(bsg_job); | ||
986 | |||
987 | done_unmap_sg: | ||
988 | if (mgmt_b) | ||
989 | dma_free_coherent(&ha->pdev->dev, data_len, mgmt_b, mgmt_dma); | ||
990 | |||
991 | if (dma_direction == DMA_TO_DEVICE) | ||
992 | dma_unmap_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list, | ||
993 | bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE); | ||
994 | else if (dma_direction == DMA_FROM_DEVICE) | ||
995 | dma_unmap_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list, | ||
996 | bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE); | ||
997 | |||
998 | exit_mgmt: | ||
999 | dma_pool_free(ha->s_dma_pool, mn, mn_dma); | ||
1000 | |||
1001 | return rval; | ||
1002 | } | ||
1003 | |||
1004 | static int | ||
1005 | qla24xx_iidma(struct fc_bsg_job *bsg_job) | ||
1006 | { | ||
1007 | struct Scsi_Host *host = bsg_job->shost; | ||
1008 | scsi_qla_host_t *vha = shost_priv(host); | ||
1009 | struct qla_hw_data *ha = vha->hw; | ||
1010 | int rval = 0; | ||
1011 | struct qla_port_param *port_param = NULL; | ||
1012 | fc_port_t *fcport = NULL; | ||
1013 | uint16_t mb[MAILBOX_REGISTER_COUNT]; | ||
1014 | uint8_t *rsp_ptr = NULL; | ||
1015 | |||
1016 | bsg_job->reply->reply_payload_rcv_len = 0; | ||
1017 | |||
1018 | if (test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) || | ||
1019 | test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) || | ||
1020 | test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) | ||
1021 | return -EBUSY; | ||
1022 | |||
1023 | if (!IS_IIDMA_CAPABLE(vha->hw)) { | ||
1024 | DEBUG2(qla_printk(KERN_WARNING, ha, "%s(%lu): iiDMA not " | ||
1025 | "supported\n", __func__, vha->host_no)); | ||
1026 | return -EINVAL; | ||
1027 | } | ||
1028 | |||
1029 | port_param = (struct qla_port_param *)((char *)bsg_job->request + | ||
1030 | sizeof(struct fc_bsg_request)); | ||
1031 | if (!port_param) { | ||
1032 | DEBUG2(printk("%s(%ld): port_param header not provided, " | ||
1033 | "exiting.\n", __func__, vha->host_no)); | ||
1034 | return -EINVAL; | ||
1035 | } | ||
1036 | |||
1037 | if (port_param->fc_scsi_addr.dest_type != EXT_DEF_TYPE_WWPN) { | ||
1038 | DEBUG2(printk(KERN_ERR "%s(%ld): Invalid destination type\n", | ||
1039 | __func__, vha->host_no)); | ||
1040 | return -EINVAL; | ||
1041 | } | ||
1042 | |||
1043 | list_for_each_entry(fcport, &vha->vp_fcports, list) { | ||
1044 | if (fcport->port_type != FCT_TARGET) | ||
1045 | continue; | ||
1046 | |||
1047 | if (memcmp(port_param->fc_scsi_addr.dest_addr.wwpn, | ||
1048 | fcport->port_name, sizeof(fcport->port_name))) | ||
1049 | continue; | ||
1050 | break; | ||
1051 | } | ||
1052 | |||
1053 | if (!fcport) { | ||
1054 | DEBUG2(printk(KERN_ERR "%s(%ld): Failed to find port\n", | ||
1055 | __func__, vha->host_no)); | ||
1056 | return -EINVAL; | ||
1057 | } | ||
1058 | |||
1059 | if (port_param->mode) | ||
1060 | rval = qla2x00_set_idma_speed(vha, fcport->loop_id, | ||
1061 | port_param->speed, mb); | ||
1062 | else | ||
1063 | rval = qla2x00_get_idma_speed(vha, fcport->loop_id, | ||
1064 | &port_param->speed, mb); | ||
1065 | |||
1066 | if (rval) { | ||
1067 | DEBUG16(printk(KERN_ERR "scsi(%ld): iIDMA cmd failed for " | ||
1068 | "%02x%02x%02x%02x%02x%02x%02x%02x -- " | ||
1069 | "%04x %x %04x %04x.\n", | ||
1070 | vha->host_no, fcport->port_name[0], | ||
1071 | fcport->port_name[1], | ||
1072 | fcport->port_name[2], fcport->port_name[3], | ||
1073 | fcport->port_name[4], fcport->port_name[5], | ||
1074 | fcport->port_name[6], fcport->port_name[7], rval, | ||
1075 | fcport->fp_speed, mb[0], mb[1])); | ||
1076 | rval = 0; | ||
1077 | bsg_job->reply->result = (DID_ERROR << 16); | ||
1078 | |||
1079 | } else { | ||
1080 | if (!port_param->mode) { | ||
1081 | bsg_job->reply_len = sizeof(struct fc_bsg_reply) + | ||
1082 | sizeof(struct qla_port_param); | ||
1083 | |||
1084 | rsp_ptr = ((uint8_t *)bsg_job->reply) + | ||
1085 | sizeof(struct fc_bsg_reply); | ||
1086 | |||
1087 | memcpy(rsp_ptr, port_param, | ||
1088 | sizeof(struct qla_port_param)); | ||
1089 | } | ||
1090 | |||
1091 | bsg_job->reply->result = DID_OK; | ||
1092 | } | ||
1093 | |||
1094 | bsg_job->job_done(bsg_job); | ||
1095 | return rval; | ||
1096 | } | ||
1097 | |||
1098 | static int | ||
1099 | qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job) | ||
1100 | { | ||
1101 | switch (bsg_job->request->rqst_data.h_vendor.vendor_cmd[0]) { | ||
1102 | case QL_VND_LOOPBACK: | ||
1103 | return qla2x00_process_loopback(bsg_job); | ||
1104 | |||
1105 | case QL_VND_A84_RESET: | ||
1106 | return qla84xx_reset(bsg_job); | ||
1107 | |||
1108 | case QL_VND_A84_UPDATE_FW: | ||
1109 | return qla84xx_updatefw(bsg_job); | ||
1110 | |||
1111 | case QL_VND_A84_MGMT_CMD: | ||
1112 | return qla84xx_mgmt_cmd(bsg_job); | ||
1113 | |||
1114 | case QL_VND_IIDMA: | ||
1115 | return qla24xx_iidma(bsg_job); | ||
1116 | |||
1117 | case QL_VND_FCP_PRIO_CFG_CMD: | ||
1118 | return qla24xx_proc_fcp_prio_cfg_cmd(bsg_job); | ||
1119 | |||
1120 | default: | ||
1121 | bsg_job->reply->result = (DID_ERROR << 16); | ||
1122 | bsg_job->job_done(bsg_job); | ||
1123 | return -ENOSYS; | ||
1124 | } | ||
1125 | } | ||
1126 | |||
1127 | int | ||
1128 | qla24xx_bsg_request(struct fc_bsg_job *bsg_job) | ||
1129 | { | ||
1130 | int ret = -EINVAL; | ||
1131 | |||
1132 | switch (bsg_job->request->msgcode) { | ||
1133 | case FC_BSG_RPT_ELS: | ||
1134 | case FC_BSG_HST_ELS_NOLOGIN: | ||
1135 | ret = qla2x00_process_els(bsg_job); | ||
1136 | break; | ||
1137 | case FC_BSG_HST_CT: | ||
1138 | ret = qla2x00_process_ct(bsg_job); | ||
1139 | break; | ||
1140 | case FC_BSG_HST_VENDOR: | ||
1141 | ret = qla2x00_process_vendor_specific(bsg_job); | ||
1142 | break; | ||
1143 | case FC_BSG_HST_ADD_RPORT: | ||
1144 | case FC_BSG_HST_DEL_RPORT: | ||
1145 | case FC_BSG_RPT_CT: | ||
1146 | default: | ||
1147 | DEBUG2(printk("qla2xxx: unsupported BSG request\n")); | ||
1148 | break; | ||
1149 | } | ||
1150 | return ret; | ||
1151 | } | ||
1152 | |||
1153 | int | ||
1154 | qla24xx_bsg_timeout(struct fc_bsg_job *bsg_job) | ||
1155 | { | ||
1156 | scsi_qla_host_t *vha = shost_priv(bsg_job->shost); | ||
1157 | struct qla_hw_data *ha = vha->hw; | ||
1158 | srb_t *sp; | ||
1159 | int cnt, que; | ||
1160 | unsigned long flags; | ||
1161 | struct req_que *req; | ||
1162 | struct srb_ctx *sp_bsg; | ||
1163 | |||
1164 | /* find the bsg job from the active list of commands */ | ||
1165 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
1166 | for (que = 0; que < ha->max_req_queues; que++) { | ||
1167 | req = ha->req_q_map[que]; | ||
1168 | if (!req) | ||
1169 | continue; | ||
1170 | |||
1171 | for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) { | ||
1172 | sp = req->outstanding_cmds[cnt]; | ||
1173 | if (sp) { | ||
1174 | sp_bsg = sp->ctx; | ||
1175 | |||
1176 | if (((sp_bsg->type == SRB_CT_CMD) || | ||
1177 | (sp_bsg->type == SRB_ELS_CMD_HST)) | ||
1178 | && (sp_bsg->u.bsg_job == bsg_job)) { | ||
1179 | if (ha->isp_ops->abort_command(sp)) { | ||
1180 | DEBUG2(qla_printk(KERN_INFO, ha, | ||
1181 | "scsi(%ld): mbx " | ||
1182 | "abort_command failed\n", | ||
1183 | vha->host_no)); | ||
1184 | bsg_job->req->errors = | ||
1185 | bsg_job->reply->result = -EIO; | ||
1186 | } else { | ||
1187 | DEBUG2(qla_printk(KERN_INFO, ha, | ||
1188 | "scsi(%ld): mbx " | ||
1189 | "abort_command success\n", | ||
1190 | vha->host_no)); | ||
1191 | bsg_job->req->errors = | ||
1192 | bsg_job->reply->result = 0; | ||
1193 | } | ||
1194 | goto done; | ||
1195 | } | ||
1196 | } | ||
1197 | } | ||
1198 | } | ||
1199 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
1200 | DEBUG2(qla_printk(KERN_INFO, ha, | ||
1201 | "scsi(%ld) SRB not found to abort\n", vha->host_no)); | ||
1202 | bsg_job->req->errors = bsg_job->reply->result = -ENXIO; | ||
1203 | return 0; | ||
1204 | |||
1205 | done: | ||
1206 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
1207 | if (bsg_job->request->msgcode == FC_BSG_HST_CT) | ||
1208 | kfree(sp->fcport); | ||
1209 | kfree(sp->ctx); | ||
1210 | mempool_free(sp, ha->srb_mempool); | ||
1211 | return 0; | ||
1212 | } | ||
diff --git a/drivers/scsi/qla2xxx/qla_bsg.h b/drivers/scsi/qla2xxx/qla_bsg.h new file mode 100644 index 000000000000..76ed92dd2ef2 --- /dev/null +++ b/drivers/scsi/qla2xxx/qla_bsg.h | |||
@@ -0,0 +1,135 @@ | |||
1 | /* | ||
2 | * QLogic Fibre Channel HBA Driver | ||
3 | * Copyright (c) 2003-2008 QLogic Corporation | ||
4 | * | ||
5 | * See LICENSE.qla2xxx for copyright and licensing details. | ||
6 | */ | ||
7 | #ifndef __QLA_BSG_H | ||
8 | #define __QLA_BSG_H | ||
9 | |||
10 | /* BSG Vendor specific commands */ | ||
11 | #define QL_VND_LOOPBACK 0x01 | ||
12 | #define QL_VND_A84_RESET 0x02 | ||
13 | #define QL_VND_A84_UPDATE_FW 0x03 | ||
14 | #define QL_VND_A84_MGMT_CMD 0x04 | ||
15 | #define QL_VND_IIDMA 0x05 | ||
16 | #define QL_VND_FCP_PRIO_CFG_CMD 0x06 | ||
17 | |||
18 | /* BSG definations for interpreting CommandSent field */ | ||
19 | #define INT_DEF_LB_LOOPBACK_CMD 0 | ||
20 | #define INT_DEF_LB_ECHO_CMD 1 | ||
21 | |||
22 | /* BSG Vendor specific definations */ | ||
23 | #define A84_ISSUE_WRITE_TYPE_CMD 0 | ||
24 | #define A84_ISSUE_READ_TYPE_CMD 1 | ||
25 | #define A84_CLEANUP_CMD 2 | ||
26 | #define A84_ISSUE_RESET_OP_FW 3 | ||
27 | #define A84_ISSUE_RESET_DIAG_FW 4 | ||
28 | #define A84_ISSUE_UPDATE_OPFW_CMD 5 | ||
29 | #define A84_ISSUE_UPDATE_DIAGFW_CMD 6 | ||
30 | |||
31 | struct qla84_mgmt_param { | ||
32 | union { | ||
33 | struct { | ||
34 | uint32_t start_addr; | ||
35 | } mem; /* for QLA84_MGMT_READ/WRITE_MEM */ | ||
36 | struct { | ||
37 | uint32_t id; | ||
38 | #define QLA84_MGMT_CONFIG_ID_UIF 1 | ||
39 | #define QLA84_MGMT_CONFIG_ID_FCOE_COS 2 | ||
40 | #define QLA84_MGMT_CONFIG_ID_PAUSE 3 | ||
41 | #define QLA84_MGMT_CONFIG_ID_TIMEOUTS 4 | ||
42 | |||
43 | uint32_t param0; | ||
44 | uint32_t param1; | ||
45 | } config; /* for QLA84_MGMT_CHNG_CONFIG */ | ||
46 | |||
47 | struct { | ||
48 | uint32_t type; | ||
49 | #define QLA84_MGMT_INFO_CONFIG_LOG_DATA 1 /* Get Config Log Data */ | ||
50 | #define QLA84_MGMT_INFO_LOG_DATA 2 /* Get Log Data */ | ||
51 | #define QLA84_MGMT_INFO_PORT_STAT 3 /* Get Port Statistics */ | ||
52 | #define QLA84_MGMT_INFO_LIF_STAT 4 /* Get LIF Statistics */ | ||
53 | #define QLA84_MGMT_INFO_ASIC_STAT 5 /* Get ASIC Statistics */ | ||
54 | #define QLA84_MGMT_INFO_CONFIG_PARAMS 6 /* Get Config Parameters */ | ||
55 | #define QLA84_MGMT_INFO_PANIC_LOG 7 /* Get Panic Log */ | ||
56 | |||
57 | uint32_t context; | ||
58 | /* | ||
59 | * context definitions for QLA84_MGMT_INFO_CONFIG_LOG_DATA | ||
60 | */ | ||
61 | #define IC_LOG_DATA_LOG_ID_DEBUG_LOG 0 | ||
62 | #define IC_LOG_DATA_LOG_ID_LEARN_LOG 1 | ||
63 | #define IC_LOG_DATA_LOG_ID_FC_ACL_INGRESS_LOG 2 | ||
64 | #define IC_LOG_DATA_LOG_ID_FC_ACL_EGRESS_LOG 3 | ||
65 | #define IC_LOG_DATA_LOG_ID_ETHERNET_ACL_INGRESS_LOG 4 | ||
66 | #define IC_LOG_DATA_LOG_ID_ETHERNET_ACL_EGRESS_LOG 5 | ||
67 | #define IC_LOG_DATA_LOG_ID_MESSAGE_TRANSMIT_LOG 6 | ||
68 | #define IC_LOG_DATA_LOG_ID_MESSAGE_RECEIVE_LOG 7 | ||
69 | #define IC_LOG_DATA_LOG_ID_LINK_EVENT_LOG 8 | ||
70 | #define IC_LOG_DATA_LOG_ID_DCX_LOG 9 | ||
71 | |||
72 | /* | ||
73 | * context definitions for QLA84_MGMT_INFO_PORT_STAT | ||
74 | */ | ||
75 | #define IC_PORT_STATISTICS_PORT_NUMBER_ETHERNET_PORT0 0 | ||
76 | #define IC_PORT_STATISTICS_PORT_NUMBER_ETHERNET_PORT1 1 | ||
77 | #define IC_PORT_STATISTICS_PORT_NUMBER_NSL_PORT0 2 | ||
78 | #define IC_PORT_STATISTICS_PORT_NUMBER_NSL_PORT1 3 | ||
79 | #define IC_PORT_STATISTICS_PORT_NUMBER_FC_PORT0 4 | ||
80 | #define IC_PORT_STATISTICS_PORT_NUMBER_FC_PORT1 5 | ||
81 | |||
82 | |||
83 | /* | ||
84 | * context definitions for QLA84_MGMT_INFO_LIF_STAT | ||
85 | */ | ||
86 | #define IC_LIF_STATISTICS_LIF_NUMBER_ETHERNET_PORT0 0 | ||
87 | #define IC_LIF_STATISTICS_LIF_NUMBER_ETHERNET_PORT1 1 | ||
88 | #define IC_LIF_STATISTICS_LIF_NUMBER_FC_PORT0 2 | ||
89 | #define IC_LIF_STATISTICS_LIF_NUMBER_FC_PORT1 3 | ||
90 | #define IC_LIF_STATISTICS_LIF_NUMBER_CPU 6 | ||
91 | |||
92 | } info; /* for QLA84_MGMT_GET_INFO */ | ||
93 | } u; | ||
94 | }; | ||
95 | |||
96 | struct qla84_msg_mgmt { | ||
97 | uint16_t cmd; | ||
98 | #define QLA84_MGMT_READ_MEM 0x00 | ||
99 | #define QLA84_MGMT_WRITE_MEM 0x01 | ||
100 | #define QLA84_MGMT_CHNG_CONFIG 0x02 | ||
101 | #define QLA84_MGMT_GET_INFO 0x03 | ||
102 | uint16_t rsrvd; | ||
103 | struct qla84_mgmt_param mgmtp;/* parameters for cmd */ | ||
104 | uint32_t len; /* bytes in payload following this struct */ | ||
105 | uint8_t payload[0]; /* payload for cmd */ | ||
106 | }; | ||
107 | |||
108 | struct qla_bsg_a84_mgmt { | ||
109 | struct qla84_msg_mgmt mgmt; | ||
110 | } __attribute__ ((packed)); | ||
111 | |||
112 | struct qla_scsi_addr { | ||
113 | uint16_t bus; | ||
114 | uint16_t target; | ||
115 | } __attribute__ ((packed)); | ||
116 | |||
117 | struct qla_ext_dest_addr { | ||
118 | union { | ||
119 | uint8_t wwnn[8]; | ||
120 | uint8_t wwpn[8]; | ||
121 | uint8_t id[4]; | ||
122 | struct qla_scsi_addr scsi_addr; | ||
123 | } dest_addr; | ||
124 | uint16_t dest_type; | ||
125 | #define EXT_DEF_TYPE_WWPN 2 | ||
126 | uint16_t lun; | ||
127 | uint16_t padding[2]; | ||
128 | } __attribute__ ((packed)); | ||
129 | |||
130 | struct qla_port_param { | ||
131 | struct qla_ext_dest_addr fc_scsi_addr; | ||
132 | uint16_t mode; | ||
133 | uint16_t speed; | ||
134 | } __attribute__ ((packed)); | ||
135 | #endif | ||
diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index cb2eca4c26d8..2afc8a362f2c 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c | |||
@@ -769,6 +769,9 @@ qla24xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) | |||
769 | void *nxt; | 769 | void *nxt; |
770 | struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev); | 770 | struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev); |
771 | 771 | ||
772 | if (IS_QLA82XX(ha)) | ||
773 | return; | ||
774 | |||
772 | risc_address = ext_mem_cnt = 0; | 775 | risc_address = ext_mem_cnt = 0; |
773 | flags = 0; | 776 | flags = 0; |
774 | 777 | ||
@@ -1660,4 +1663,62 @@ qla2x00_dump_buffer(uint8_t * b, uint32_t size) | |||
1660 | printk("\n"); | 1663 | printk("\n"); |
1661 | } | 1664 | } |
1662 | 1665 | ||
1666 | void | ||
1667 | qla2x00_dump_buffer_zipped(uint8_t *b, uint32_t size) | ||
1668 | { | ||
1669 | uint32_t cnt; | ||
1670 | uint8_t c; | ||
1671 | uint8_t last16[16], cur16[16]; | ||
1672 | uint32_t lc = 0, num_same16 = 0, j; | ||
1673 | |||
1674 | printk(KERN_DEBUG " 0 1 2 3 4 5 6 7 8 9 " | ||
1675 | "Ah Bh Ch Dh Eh Fh\n"); | ||
1676 | printk(KERN_DEBUG "----------------------------------------" | ||
1677 | "----------------------\n"); | ||
1678 | |||
1679 | for (cnt = 0; cnt < size;) { | ||
1680 | c = *b++; | ||
1663 | 1681 | ||
1682 | cur16[lc++] = c; | ||
1683 | |||
1684 | cnt++; | ||
1685 | if (cnt % 16) | ||
1686 | continue; | ||
1687 | |||
1688 | /* We have 16 now */ | ||
1689 | lc = 0; | ||
1690 | if (num_same16 == 0) { | ||
1691 | memcpy(last16, cur16, 16); | ||
1692 | num_same16++; | ||
1693 | continue; | ||
1694 | } | ||
1695 | if (memcmp(cur16, last16, 16) == 0) { | ||
1696 | num_same16++; | ||
1697 | continue; | ||
1698 | } | ||
1699 | for (j = 0; j < 16; j++) | ||
1700 | printk(KERN_DEBUG "%02x ", (uint32_t)last16[j]); | ||
1701 | printk(KERN_DEBUG "\n"); | ||
1702 | |||
1703 | if (num_same16 > 1) | ||
1704 | printk(KERN_DEBUG "> prev pattern repeats (%u)" | ||
1705 | "more times\n", num_same16-1); | ||
1706 | memcpy(last16, cur16, 16); | ||
1707 | num_same16 = 1; | ||
1708 | } | ||
1709 | |||
1710 | if (num_same16) { | ||
1711 | for (j = 0; j < 16; j++) | ||
1712 | printk(KERN_DEBUG "%02x ", (uint32_t)last16[j]); | ||
1713 | printk(KERN_DEBUG "\n"); | ||
1714 | |||
1715 | if (num_same16 > 1) | ||
1716 | printk(KERN_DEBUG "> prev pattern repeats (%u)" | ||
1717 | "more times\n", num_same16-1); | ||
1718 | } | ||
1719 | if (lc) { | ||
1720 | for (j = 0; j < lc; j++) | ||
1721 | printk(KERN_DEBUG "%02x ", (uint32_t)cur16[j]); | ||
1722 | printk(KERN_DEBUG "\n"); | ||
1723 | } | ||
1724 | } | ||
diff --git a/drivers/scsi/qla2xxx/qla_dbg.h b/drivers/scsi/qla2xxx/qla_dbg.h index d6d9c86cb058..916c81f3f55d 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.h +++ b/drivers/scsi/qla2xxx/qla_dbg.h | |||
@@ -27,6 +27,9 @@ | |||
27 | /* #define QL_DEBUG_LEVEL_15 */ /* Output NPIV trace msgs */ | 27 | /* #define QL_DEBUG_LEVEL_15 */ /* Output NPIV trace msgs */ |
28 | /* #define QL_DEBUG_LEVEL_16 */ /* Output ISP84XX trace msgs */ | 28 | /* #define QL_DEBUG_LEVEL_16 */ /* Output ISP84XX trace msgs */ |
29 | /* #define QL_DEBUG_LEVEL_17 */ /* Output EEH trace messages */ | 29 | /* #define QL_DEBUG_LEVEL_17 */ /* Output EEH trace messages */ |
30 | /* #define QL_DEBUG_LEVEL_18 */ /* Output T10 CRC trace messages */ | ||
31 | |||
32 | /* #define QL_PRINTK_BUF */ /* Captures printk to buffer */ | ||
30 | 33 | ||
31 | /* | 34 | /* |
32 | * Macros use for debugging the driver. | 35 | * Macros use for debugging the driver. |
@@ -139,6 +142,13 @@ | |||
139 | #define DEBUG17(x) do {} while (0) | 142 | #define DEBUG17(x) do {} while (0) |
140 | #endif | 143 | #endif |
141 | 144 | ||
145 | #if defined(QL_DEBUG_LEVEL_18) | ||
146 | #define DEBUG18(x) do {if (ql2xextended_error_logging) x; } while (0) | ||
147 | #else | ||
148 | #define DEBUG18(x) do {} while (0) | ||
149 | #endif | ||
150 | |||
151 | |||
142 | /* | 152 | /* |
143 | * Firmware Dump structure definition | 153 | * Firmware Dump structure definition |
144 | */ | 154 | */ |
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index afa95614aaf8..839610909018 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h | |||
@@ -33,7 +33,10 @@ | |||
33 | #include <scsi/scsi_transport_fc.h> | 33 | #include <scsi/scsi_transport_fc.h> |
34 | #include <scsi/scsi_bsg_fc.h> | 34 | #include <scsi/scsi_bsg_fc.h> |
35 | 35 | ||
36 | #define QLA2XXX_DRIVER_NAME "qla2xxx" | 36 | #include "qla_bsg.h" |
37 | #include "qla_nx.h" | ||
38 | #define QLA2XXX_DRIVER_NAME "qla2xxx" | ||
39 | #define QLA2XXX_APIDEV "ql2xapidev" | ||
37 | 40 | ||
38 | /* | 41 | /* |
39 | * We have MAILBOX_REGISTER_COUNT sized arrays in a few places, | 42 | * We have MAILBOX_REGISTER_COUNT sized arrays in a few places, |
@@ -186,6 +189,16 @@ | |||
186 | struct req_que; | 189 | struct req_que; |
187 | 190 | ||
188 | /* | 191 | /* |
192 | * (sd.h is not exported, hence local inclusion) | ||
193 | * Data Integrity Field tuple. | ||
194 | */ | ||
195 | struct sd_dif_tuple { | ||
196 | __be16 guard_tag; /* Checksum */ | ||
197 | __be16 app_tag; /* Opaque storage */ | ||
198 | __be32 ref_tag; /* Target LBA or indirect LBA */ | ||
199 | }; | ||
200 | |||
201 | /* | ||
189 | * SCSI Request Block | 202 | * SCSI Request Block |
190 | */ | 203 | */ |
191 | typedef struct srb { | 204 | typedef struct srb { |
@@ -205,40 +218,73 @@ typedef struct srb { | |||
205 | /* | 218 | /* |
206 | * SRB flag definitions | 219 | * SRB flag definitions |
207 | */ | 220 | */ |
208 | #define SRB_DMA_VALID BIT_0 /* Command sent to ISP */ | 221 | #define SRB_DMA_VALID BIT_0 /* Command sent to ISP */ |
222 | #define SRB_FCP_CMND_DMA_VALID BIT_12 /* DIF: DSD List valid */ | ||
223 | #define SRB_CRC_CTX_DMA_VALID BIT_2 /* DIF: context DMA valid */ | ||
224 | #define SRB_CRC_PROT_DMA_VALID BIT_4 /* DIF: prot DMA valid */ | ||
225 | #define SRB_CRC_CTX_DSD_VALID BIT_5 /* DIF: dsd_list valid */ | ||
226 | |||
227 | /* To identify if a srb is of T10-CRC type. @sp => srb_t pointer */ | ||
228 | #define IS_PROT_IO(sp) (sp->flags & SRB_CRC_CTX_DSD_VALID) | ||
209 | 229 | ||
210 | /* | 230 | /* |
211 | * SRB extensions. | 231 | * SRB extensions. |
212 | */ | 232 | */ |
213 | struct srb_ctx { | 233 | struct srb_iocb { |
214 | #define SRB_LOGIN_CMD 1 | 234 | union { |
215 | #define SRB_LOGOUT_CMD 2 | 235 | struct { |
216 | uint16_t type; | 236 | uint16_t flags; |
217 | struct timer_list timer; | ||
218 | |||
219 | void (*free)(srb_t *sp); | ||
220 | void (*timeout)(srb_t *sp); | ||
221 | }; | ||
222 | |||
223 | struct srb_logio { | ||
224 | struct srb_ctx ctx; | ||
225 | |||
226 | #define SRB_LOGIN_RETRIED BIT_0 | 237 | #define SRB_LOGIN_RETRIED BIT_0 |
227 | #define SRB_LOGIN_COND_PLOGI BIT_1 | 238 | #define SRB_LOGIN_COND_PLOGI BIT_1 |
228 | #define SRB_LOGIN_SKIP_PRLI BIT_2 | 239 | #define SRB_LOGIN_SKIP_PRLI BIT_2 |
229 | uint16_t flags; | 240 | uint16_t data[2]; |
241 | } logio; | ||
242 | struct { | ||
243 | /* | ||
244 | * Values for flags field below are as | ||
245 | * defined in tsk_mgmt_entry struct | ||
246 | * for control_flags field in qla_fw.h. | ||
247 | */ | ||
248 | uint32_t flags; | ||
249 | uint32_t lun; | ||
250 | uint32_t data; | ||
251 | } tmf; | ||
252 | struct { | ||
253 | /* | ||
254 | * values for modif field below are as | ||
255 | * defined in mrk_entry_24xx struct | ||
256 | * for the modifier field in qla_fw.h. | ||
257 | */ | ||
258 | uint8_t modif; | ||
259 | uint16_t lun; | ||
260 | uint32_t data; | ||
261 | } marker; | ||
262 | } u; | ||
263 | |||
264 | struct timer_list timer; | ||
265 | |||
266 | void (*done)(srb_t *); | ||
267 | void (*free)(srb_t *); | ||
268 | void (*timeout)(srb_t *); | ||
230 | }; | 269 | }; |
231 | 270 | ||
232 | struct srb_bsg_ctx { | 271 | /* Values for srb_ctx type */ |
272 | #define SRB_LOGIN_CMD 1 | ||
273 | #define SRB_LOGOUT_CMD 2 | ||
233 | #define SRB_ELS_CMD_RPT 3 | 274 | #define SRB_ELS_CMD_RPT 3 |
234 | #define SRB_ELS_CMD_HST 4 | 275 | #define SRB_ELS_CMD_HST 4 |
235 | #define SRB_CT_CMD 5 | 276 | #define SRB_CT_CMD 5 |
236 | uint16_t type; | 277 | #define SRB_ADISC_CMD 6 |
237 | }; | 278 | #define SRB_TM_CMD 7 |
279 | #define SRB_MARKER_CMD 8 | ||
238 | 280 | ||
239 | struct srb_bsg { | 281 | struct srb_ctx { |
240 | struct srb_bsg_ctx ctx; | 282 | uint16_t type; |
241 | struct fc_bsg_job *bsg_job; | 283 | char *name; |
284 | union { | ||
285 | struct srb_iocb *iocb_cmd; | ||
286 | struct fc_bsg_job *bsg_job; | ||
287 | } u; | ||
242 | }; | 288 | }; |
243 | 289 | ||
244 | struct msg_echo_lb { | 290 | struct msg_echo_lb { |
@@ -416,6 +462,7 @@ typedef union { | |||
416 | struct device_reg_2xxx isp; | 462 | struct device_reg_2xxx isp; |
417 | struct device_reg_24xx isp24; | 463 | struct device_reg_24xx isp24; |
418 | struct device_reg_25xxmq isp25mq; | 464 | struct device_reg_25xxmq isp25mq; |
465 | struct device_reg_82xx isp82; | ||
419 | } device_reg_t; | 466 | } device_reg_t; |
420 | 467 | ||
421 | #define ISP_REQ_Q_IN(ha, reg) \ | 468 | #define ISP_REQ_Q_IN(ha, reg) \ |
@@ -1299,6 +1346,66 @@ typedef struct { | |||
1299 | uint32_t dseg_4_length; /* Data segment 4 length. */ | 1346 | uint32_t dseg_4_length; /* Data segment 4 length. */ |
1300 | } cont_a64_entry_t; | 1347 | } cont_a64_entry_t; |
1301 | 1348 | ||
1349 | #define PO_MODE_DIF_INSERT 0 | ||
1350 | #define PO_MODE_DIF_REMOVE BIT_0 | ||
1351 | #define PO_MODE_DIF_PASS BIT_1 | ||
1352 | #define PO_MODE_DIF_REPLACE (BIT_0 + BIT_1) | ||
1353 | #define PO_ENABLE_DIF_BUNDLING BIT_8 | ||
1354 | #define PO_ENABLE_INCR_GUARD_SEED BIT_3 | ||
1355 | #define PO_DISABLE_INCR_REF_TAG BIT_5 | ||
1356 | #define PO_DISABLE_GUARD_CHECK BIT_4 | ||
1357 | /* | ||
1358 | * ISP queue - 64-Bit addressing, continuation crc entry structure definition. | ||
1359 | */ | ||
1360 | struct crc_context { | ||
1361 | uint32_t handle; /* System handle. */ | ||
1362 | uint32_t ref_tag; | ||
1363 | uint16_t app_tag; | ||
1364 | uint8_t ref_tag_mask[4]; /* Validation/Replacement Mask*/ | ||
1365 | uint8_t app_tag_mask[2]; /* Validation/Replacement Mask*/ | ||
1366 | uint16_t guard_seed; /* Initial Guard Seed */ | ||
1367 | uint16_t prot_opts; /* Requested Data Protection Mode */ | ||
1368 | uint16_t blk_size; /* Data size in bytes */ | ||
1369 | uint16_t runt_blk_guard; /* Guard value for runt block (tape | ||
1370 | * only) */ | ||
1371 | uint32_t byte_count; /* Total byte count/ total data | ||
1372 | * transfer count */ | ||
1373 | union { | ||
1374 | struct { | ||
1375 | uint32_t reserved_1; | ||
1376 | uint16_t reserved_2; | ||
1377 | uint16_t reserved_3; | ||
1378 | uint32_t reserved_4; | ||
1379 | uint32_t data_address[2]; | ||
1380 | uint32_t data_length; | ||
1381 | uint32_t reserved_5[2]; | ||
1382 | uint32_t reserved_6; | ||
1383 | } nobundling; | ||
1384 | struct { | ||
1385 | uint32_t dif_byte_count; /* Total DIF byte | ||
1386 | * count */ | ||
1387 | uint16_t reserved_1; | ||
1388 | uint16_t dseg_count; /* Data segment count */ | ||
1389 | uint32_t reserved_2; | ||
1390 | uint32_t data_address[2]; | ||
1391 | uint32_t data_length; | ||
1392 | uint32_t dif_address[2]; | ||
1393 | uint32_t dif_length; /* Data segment 0 | ||
1394 | * length */ | ||
1395 | } bundling; | ||
1396 | } u; | ||
1397 | |||
1398 | struct fcp_cmnd fcp_cmnd; | ||
1399 | dma_addr_t crc_ctx_dma; | ||
1400 | /* List of DMA context transfers */ | ||
1401 | struct list_head dsd_list; | ||
1402 | |||
1403 | /* This structure should not exceed 512 bytes */ | ||
1404 | }; | ||
1405 | |||
1406 | #define CRC_CONTEXT_LEN_FW (offsetof(struct crc_context, fcp_cmnd.lun)) | ||
1407 | #define CRC_CONTEXT_FCPCMND_OFF (offsetof(struct crc_context, fcp_cmnd.lun)) | ||
1408 | |||
1302 | /* | 1409 | /* |
1303 | * ISP queue - status entry structure definition. | 1410 | * ISP queue - status entry structure definition. |
1304 | */ | 1411 | */ |
@@ -1359,6 +1466,7 @@ typedef struct { | |||
1359 | #define CS_ABORTED 0x5 /* System aborted command. */ | 1466 | #define CS_ABORTED 0x5 /* System aborted command. */ |
1360 | #define CS_TIMEOUT 0x6 /* Timeout error. */ | 1467 | #define CS_TIMEOUT 0x6 /* Timeout error. */ |
1361 | #define CS_DATA_OVERRUN 0x7 /* Data overrun. */ | 1468 | #define CS_DATA_OVERRUN 0x7 /* Data overrun. */ |
1469 | #define CS_DIF_ERROR 0xC /* DIF error detected */ | ||
1362 | 1470 | ||
1363 | #define CS_DATA_UNDERRUN 0x15 /* Data Underrun. */ | 1471 | #define CS_DATA_UNDERRUN 0x15 /* Data Underrun. */ |
1364 | #define CS_QUEUE_FULL 0x1C /* Queue Full. */ | 1472 | #define CS_QUEUE_FULL 0x1C /* Queue Full. */ |
@@ -1579,6 +1687,8 @@ typedef struct fc_port { | |||
1579 | uint16_t loop_id; | 1687 | uint16_t loop_id; |
1580 | uint16_t old_loop_id; | 1688 | uint16_t old_loop_id; |
1581 | 1689 | ||
1690 | uint8_t fcp_prio; | ||
1691 | |||
1582 | uint8_t fabric_port_name[WWN_SIZE]; | 1692 | uint8_t fabric_port_name[WWN_SIZE]; |
1583 | uint16_t fp_speed; | 1693 | uint16_t fp_speed; |
1584 | 1694 | ||
@@ -1611,6 +1721,7 @@ typedef struct fc_port { | |||
1611 | #define FCF_FABRIC_DEVICE BIT_0 | 1721 | #define FCF_FABRIC_DEVICE BIT_0 |
1612 | #define FCF_LOGIN_NEEDED BIT_1 | 1722 | #define FCF_LOGIN_NEEDED BIT_1 |
1613 | #define FCF_FCP2_DEVICE BIT_2 | 1723 | #define FCF_FCP2_DEVICE BIT_2 |
1724 | #define FCF_ASYNC_SENT BIT_3 | ||
1614 | 1725 | ||
1615 | /* No loop ID flag. */ | 1726 | /* No loop ID flag. */ |
1616 | #define FC_NO_LOOP_ID 0x1000 | 1727 | #define FC_NO_LOOP_ID 0x1000 |
@@ -2109,6 +2220,7 @@ struct isp_operations { | |||
2109 | 2220 | ||
2110 | int (*get_flash_version) (struct scsi_qla_host *, void *); | 2221 | int (*get_flash_version) (struct scsi_qla_host *, void *); |
2111 | int (*start_scsi) (srb_t *); | 2222 | int (*start_scsi) (srb_t *); |
2223 | int (*abort_isp) (struct scsi_qla_host *); | ||
2112 | }; | 2224 | }; |
2113 | 2225 | ||
2114 | /* MSI-X Support *************************************************************/ | 2226 | /* MSI-X Support *************************************************************/ |
@@ -2143,6 +2255,8 @@ enum qla_work_type { | |||
2143 | QLA_EVT_ASYNC_LOGIN_DONE, | 2255 | QLA_EVT_ASYNC_LOGIN_DONE, |
2144 | QLA_EVT_ASYNC_LOGOUT, | 2256 | QLA_EVT_ASYNC_LOGOUT, |
2145 | QLA_EVT_ASYNC_LOGOUT_DONE, | 2257 | QLA_EVT_ASYNC_LOGOUT_DONE, |
2258 | QLA_EVT_ASYNC_ADISC, | ||
2259 | QLA_EVT_ASYNC_ADISC_DONE, | ||
2146 | QLA_EVT_UEVENT, | 2260 | QLA_EVT_UEVENT, |
2147 | }; | 2261 | }; |
2148 | 2262 | ||
@@ -2295,6 +2409,7 @@ struct qla_hw_data { | |||
2295 | uint32_t eeh_busy :1; | 2409 | uint32_t eeh_busy :1; |
2296 | uint32_t cpu_affinity_enabled :1; | 2410 | uint32_t cpu_affinity_enabled :1; |
2297 | uint32_t disable_msix_handshake :1; | 2411 | uint32_t disable_msix_handshake :1; |
2412 | uint32_t fcp_prio_enabled :1; | ||
2298 | } flags; | 2413 | } flags; |
2299 | 2414 | ||
2300 | /* This spinlock is used to protect "io transactions", you must | 2415 | /* This spinlock is used to protect "io transactions", you must |
@@ -2382,7 +2497,8 @@ struct qla_hw_data { | |||
2382 | #define DT_ISP2532 BIT_11 | 2497 | #define DT_ISP2532 BIT_11 |
2383 | #define DT_ISP8432 BIT_12 | 2498 | #define DT_ISP8432 BIT_12 |
2384 | #define DT_ISP8001 BIT_13 | 2499 | #define DT_ISP8001 BIT_13 |
2385 | #define DT_ISP_LAST (DT_ISP8001 << 1) | 2500 | #define DT_ISP8021 BIT_14 |
2501 | #define DT_ISP_LAST (DT_ISP8021 << 1) | ||
2386 | 2502 | ||
2387 | #define DT_IIDMA BIT_26 | 2503 | #define DT_IIDMA BIT_26 |
2388 | #define DT_FWI2 BIT_27 | 2504 | #define DT_FWI2 BIT_27 |
@@ -2405,6 +2521,7 @@ struct qla_hw_data { | |||
2405 | #define IS_QLA2532(ha) (DT_MASK(ha) & DT_ISP2532) | 2521 | #define IS_QLA2532(ha) (DT_MASK(ha) & DT_ISP2532) |
2406 | #define IS_QLA8432(ha) (DT_MASK(ha) & DT_ISP8432) | 2522 | #define IS_QLA8432(ha) (DT_MASK(ha) & DT_ISP8432) |
2407 | #define IS_QLA8001(ha) (DT_MASK(ha) & DT_ISP8001) | 2523 | #define IS_QLA8001(ha) (DT_MASK(ha) & DT_ISP8001) |
2524 | #define IS_QLA82XX(ha) (DT_MASK(ha) & DT_ISP8021) | ||
2408 | 2525 | ||
2409 | #define IS_QLA23XX(ha) (IS_QLA2300(ha) || IS_QLA2312(ha) || IS_QLA2322(ha) || \ | 2526 | #define IS_QLA23XX(ha) (IS_QLA2300(ha) || IS_QLA2312(ha) || IS_QLA2322(ha) || \ |
2410 | IS_QLA6312(ha) || IS_QLA6322(ha)) | 2527 | IS_QLA6312(ha) || IS_QLA6322(ha)) |
@@ -2415,8 +2532,10 @@ struct qla_hw_data { | |||
2415 | #define IS_QLA24XX_TYPE(ha) (IS_QLA24XX(ha) || IS_QLA54XX(ha) || \ | 2532 | #define IS_QLA24XX_TYPE(ha) (IS_QLA24XX(ha) || IS_QLA54XX(ha) || \ |
2416 | IS_QLA84XX(ha)) | 2533 | IS_QLA84XX(ha)) |
2417 | #define IS_QLA81XX(ha) (IS_QLA8001(ha)) | 2534 | #define IS_QLA81XX(ha) (IS_QLA8001(ha)) |
2535 | #define IS_QLA8XXX_TYPE(ha) (IS_QLA81XX(ha) || IS_QLA82XX(ha)) | ||
2418 | #define IS_QLA2XXX_MIDTYPE(ha) (IS_QLA24XX(ha) || IS_QLA84XX(ha) || \ | 2536 | #define IS_QLA2XXX_MIDTYPE(ha) (IS_QLA24XX(ha) || IS_QLA84XX(ha) || \ |
2419 | IS_QLA25XX(ha) || IS_QLA81XX(ha)) | 2537 | IS_QLA25XX(ha) || IS_QLA81XX(ha) || \ |
2538 | IS_QLA82XX(ha)) | ||
2420 | #define IS_MSIX_NACK_CAPABLE(ha) (IS_QLA81XX(ha)) | 2539 | #define IS_MSIX_NACK_CAPABLE(ha) (IS_QLA81XX(ha)) |
2421 | #define IS_NOPOLLING_TYPE(ha) ((IS_QLA25XX(ha) || IS_QLA81XX(ha)) && \ | 2540 | #define IS_NOPOLLING_TYPE(ha) ((IS_QLA25XX(ha) || IS_QLA81XX(ha)) && \ |
2422 | (ha)->flags.msix_enabled) | 2541 | (ha)->flags.msix_enabled) |
@@ -2496,6 +2615,9 @@ struct qla_hw_data { | |||
2496 | dma_addr_t ex_init_cb_dma; | 2615 | dma_addr_t ex_init_cb_dma; |
2497 | struct ex_init_cb_81xx *ex_init_cb; | 2616 | struct ex_init_cb_81xx *ex_init_cb; |
2498 | 2617 | ||
2618 | void *async_pd; | ||
2619 | dma_addr_t async_pd_dma; | ||
2620 | |||
2499 | /* These are used by mailbox operations. */ | 2621 | /* These are used by mailbox operations. */ |
2500 | volatile uint16_t mailbox_out[MAILBOX_REGISTER_COUNT]; | 2622 | volatile uint16_t mailbox_out[MAILBOX_REGISTER_COUNT]; |
2501 | 2623 | ||
@@ -2598,6 +2720,8 @@ struct qla_hw_data { | |||
2598 | uint32_t flt_region_nvram; | 2720 | uint32_t flt_region_nvram; |
2599 | uint32_t flt_region_npiv_conf; | 2721 | uint32_t flt_region_npiv_conf; |
2600 | uint32_t flt_region_gold_fw; | 2722 | uint32_t flt_region_gold_fw; |
2723 | uint32_t flt_region_fcp_prio; | ||
2724 | uint32_t flt_region_bootload; | ||
2601 | 2725 | ||
2602 | /* Needed for BEACON */ | 2726 | /* Needed for BEACON */ |
2603 | uint16_t beacon_blink_led; | 2727 | uint16_t beacon_blink_led; |
@@ -2626,6 +2750,39 @@ struct qla_hw_data { | |||
2626 | struct isp_operations *isp_ops; | 2750 | struct isp_operations *isp_ops; |
2627 | struct workqueue_struct *wq; | 2751 | struct workqueue_struct *wq; |
2628 | struct qlfc_fw fw_buf; | 2752 | struct qlfc_fw fw_buf; |
2753 | |||
2754 | /* FCP_CMND priority support */ | ||
2755 | struct qla_fcp_prio_cfg *fcp_prio_cfg; | ||
2756 | |||
2757 | struct dma_pool *dl_dma_pool; | ||
2758 | #define DSD_LIST_DMA_POOL_SIZE 512 | ||
2759 | |||
2760 | struct dma_pool *fcp_cmnd_dma_pool; | ||
2761 | mempool_t *ctx_mempool; | ||
2762 | #define FCP_CMND_DMA_POOL_SIZE 512 | ||
2763 | |||
2764 | unsigned long nx_pcibase; /* Base I/O address */ | ||
2765 | uint8_t *nxdb_rd_ptr; /* Doorbell read pointer */ | ||
2766 | unsigned long nxdb_wr_ptr; /* Door bell write pointer */ | ||
2767 | |||
2768 | uint32_t crb_win; | ||
2769 | uint32_t curr_window; | ||
2770 | uint32_t ddr_mn_window; | ||
2771 | unsigned long mn_win_crb; | ||
2772 | unsigned long ms_win_crb; | ||
2773 | int qdr_sn_window; | ||
2774 | uint32_t nx_dev_init_timeout; | ||
2775 | uint32_t nx_reset_timeout; | ||
2776 | rwlock_t hw_lock; | ||
2777 | uint16_t portnum; /* port number */ | ||
2778 | int link_width; | ||
2779 | struct fw_blob *hablob; | ||
2780 | struct qla82xx_legacy_intr_set nx_legacy_intr; | ||
2781 | |||
2782 | uint16_t gbl_dsd_inuse; | ||
2783 | uint16_t gbl_dsd_avail; | ||
2784 | struct list_head gbl_dsd_list; | ||
2785 | #define NUM_DSD_CHAIN 4096 | ||
2629 | }; | 2786 | }; |
2630 | 2787 | ||
2631 | /* | 2788 | /* |
@@ -2650,6 +2807,7 @@ typedef struct scsi_qla_host { | |||
2650 | 2807 | ||
2651 | uint32_t management_server_logged_in :1; | 2808 | uint32_t management_server_logged_in :1; |
2652 | uint32_t process_response_queue :1; | 2809 | uint32_t process_response_queue :1; |
2810 | uint32_t difdix_supported:1; | ||
2653 | } flags; | 2811 | } flags; |
2654 | 2812 | ||
2655 | atomic_t loop_state; | 2813 | atomic_t loop_state; |
@@ -2678,10 +2836,13 @@ typedef struct scsi_qla_host { | |||
2678 | #define VP_DPC_NEEDED 14 /* wake up for VP dpc handling */ | 2836 | #define VP_DPC_NEEDED 14 /* wake up for VP dpc handling */ |
2679 | #define UNLOADING 15 | 2837 | #define UNLOADING 15 |
2680 | #define NPIV_CONFIG_NEEDED 16 | 2838 | #define NPIV_CONFIG_NEEDED 16 |
2839 | #define ISP_UNRECOVERABLE 17 | ||
2840 | #define FCOE_CTX_RESET_NEEDED 18 /* Initiate FCoE context reset */ | ||
2681 | 2841 | ||
2682 | uint32_t device_flags; | 2842 | uint32_t device_flags; |
2683 | #define SWITCH_FOUND BIT_0 | 2843 | #define SWITCH_FOUND BIT_0 |
2684 | #define DFLG_NO_CABLE BIT_1 | 2844 | #define DFLG_NO_CABLE BIT_1 |
2845 | #define DFLG_DEV_FAILED BIT_5 | ||
2685 | 2846 | ||
2686 | /* ISP configuration data. */ | 2847 | /* ISP configuration data. */ |
2687 | uint16_t loop_id; /* Host adapter loop id */ | 2848 | uint16_t loop_id; /* Host adapter loop id */ |
@@ -2739,6 +2900,8 @@ typedef struct scsi_qla_host { | |||
2739 | #define VP_ERR_ADAP_NORESOURCES 5 | 2900 | #define VP_ERR_ADAP_NORESOURCES 5 |
2740 | struct qla_hw_data *hw; | 2901 | struct qla_hw_data *hw; |
2741 | struct req_que *req; | 2902 | struct req_que *req; |
2903 | int fw_heartbeat_counter; | ||
2904 | int seconds_since_last_heartbeat; | ||
2742 | } scsi_qla_host_t; | 2905 | } scsi_qla_host_t; |
2743 | 2906 | ||
2744 | /* | 2907 | /* |
@@ -2791,134 +2954,16 @@ typedef struct scsi_qla_host { | |||
2791 | #define OPTROM_SIZE_24XX 0x100000 | 2954 | #define OPTROM_SIZE_24XX 0x100000 |
2792 | #define OPTROM_SIZE_25XX 0x200000 | 2955 | #define OPTROM_SIZE_25XX 0x200000 |
2793 | #define OPTROM_SIZE_81XX 0x400000 | 2956 | #define OPTROM_SIZE_81XX 0x400000 |
2957 | #define OPTROM_SIZE_82XX 0x800000 | ||
2958 | |||
2959 | #define OPTROM_BURST_SIZE 0x1000 | ||
2960 | #define OPTROM_BURST_DWORDS (OPTROM_BURST_SIZE / 4) | ||
2961 | |||
2962 | #define QLA_DSDS_PER_IOCB 37 | ||
2794 | 2963 | ||
2795 | #include "qla_gbl.h" | 2964 | #include "qla_gbl.h" |
2796 | #include "qla_dbg.h" | 2965 | #include "qla_dbg.h" |
2797 | #include "qla_inline.h" | 2966 | #include "qla_inline.h" |
2798 | 2967 | ||
2799 | #define CMD_SP(Cmnd) ((Cmnd)->SCp.ptr) | 2968 | #define CMD_SP(Cmnd) ((Cmnd)->SCp.ptr) |
2800 | |||
2801 | /* | ||
2802 | * BSG Vendor specific commands | ||
2803 | */ | ||
2804 | |||
2805 | #define QL_VND_LOOPBACK 0x01 | ||
2806 | #define QLA84_RESET 0x02 | ||
2807 | #define QLA84_UPDATE_FW 0x03 | ||
2808 | #define QLA84_MGMT_CMD 0x04 | ||
2809 | |||
2810 | /* BSG definations for interpreting CommandSent field */ | ||
2811 | #define INT_DEF_LB_LOOPBACK_CMD 0 | ||
2812 | #define INT_DEF_LB_ECHO_CMD 1 | ||
2813 | |||
2814 | /* BSG Vendor specific definations */ | ||
2815 | typedef struct _A84_RESET { | ||
2816 | uint16_t Flags; | ||
2817 | uint16_t Reserved; | ||
2818 | #define A84_RESET_FLAG_ENABLE_DIAG_FW 1 | ||
2819 | } __attribute__((packed)) A84_RESET, *PA84_RESET; | ||
2820 | |||
2821 | #define A84_ISSUE_WRITE_TYPE_CMD 0 | ||
2822 | #define A84_ISSUE_READ_TYPE_CMD 1 | ||
2823 | #define A84_CLEANUP_CMD 2 | ||
2824 | #define A84_ISSUE_RESET_OP_FW 3 | ||
2825 | #define A84_ISSUE_RESET_DIAG_FW 4 | ||
2826 | #define A84_ISSUE_UPDATE_OPFW_CMD 5 | ||
2827 | #define A84_ISSUE_UPDATE_DIAGFW_CMD 6 | ||
2828 | |||
2829 | struct qla84_mgmt_param { | ||
2830 | union { | ||
2831 | struct { | ||
2832 | uint32_t start_addr; | ||
2833 | } mem; /* for QLA84_MGMT_READ/WRITE_MEM */ | ||
2834 | struct { | ||
2835 | uint32_t id; | ||
2836 | #define QLA84_MGMT_CONFIG_ID_UIF 1 | ||
2837 | #define QLA84_MGMT_CONFIG_ID_FCOE_COS 2 | ||
2838 | #define QLA84_MGMT_CONFIG_ID_PAUSE 3 | ||
2839 | #define QLA84_MGMT_CONFIG_ID_TIMEOUTS 4 | ||
2840 | |||
2841 | uint32_t param0; | ||
2842 | uint32_t param1; | ||
2843 | } config; /* for QLA84_MGMT_CHNG_CONFIG */ | ||
2844 | |||
2845 | struct { | ||
2846 | uint32_t type; | ||
2847 | #define QLA84_MGMT_INFO_CONFIG_LOG_DATA 1 /* Get Config Log Data */ | ||
2848 | #define QLA84_MGMT_INFO_LOG_DATA 2 /* Get Log Data */ | ||
2849 | #define QLA84_MGMT_INFO_PORT_STAT 3 /* Get Port Statistics */ | ||
2850 | #define QLA84_MGMT_INFO_LIF_STAT 4 /* Get LIF Statistics */ | ||
2851 | #define QLA84_MGMT_INFO_ASIC_STAT 5 /* Get ASIC Statistics */ | ||
2852 | #define QLA84_MGMT_INFO_CONFIG_PARAMS 6 /* Get Config Parameters */ | ||
2853 | #define QLA84_MGMT_INFO_PANIC_LOG 7 /* Get Panic Log */ | ||
2854 | |||
2855 | uint32_t context; | ||
2856 | /* | ||
2857 | * context definitions for QLA84_MGMT_INFO_CONFIG_LOG_DATA | ||
2858 | */ | ||
2859 | #define IC_LOG_DATA_LOG_ID_DEBUG_LOG 0 | ||
2860 | #define IC_LOG_DATA_LOG_ID_LEARN_LOG 1 | ||
2861 | #define IC_LOG_DATA_LOG_ID_FC_ACL_INGRESS_LOG 2 | ||
2862 | #define IC_LOG_DATA_LOG_ID_FC_ACL_EGRESS_LOG 3 | ||
2863 | #define IC_LOG_DATA_LOG_ID_ETHERNET_ACL_INGRESS_LOG 4 | ||
2864 | #define IC_LOG_DATA_LOG_ID_ETHERNET_ACL_EGRESS_LOG 5 | ||
2865 | #define IC_LOG_DATA_LOG_ID_MESSAGE_TRANSMIT_LOG 6 | ||
2866 | #define IC_LOG_DATA_LOG_ID_MESSAGE_RECEIVE_LOG 7 | ||
2867 | #define IC_LOG_DATA_LOG_ID_LINK_EVENT_LOG 8 | ||
2868 | #define IC_LOG_DATA_LOG_ID_DCX_LOG 9 | ||
2869 | |||
2870 | /* | ||
2871 | * context definitions for QLA84_MGMT_INFO_PORT_STAT | ||
2872 | */ | ||
2873 | #define IC_PORT_STATISTICS_PORT_NUMBER_ETHERNET_PORT0 0 | ||
2874 | #define IC_PORT_STATISTICS_PORT_NUMBER_ETHERNET_PORT1 1 | ||
2875 | #define IC_PORT_STATISTICS_PORT_NUMBER_NSL_PORT0 2 | ||
2876 | #define IC_PORT_STATISTICS_PORT_NUMBER_NSL_PORT1 3 | ||
2877 | #define IC_PORT_STATISTICS_PORT_NUMBER_FC_PORT0 4 | ||
2878 | #define IC_PORT_STATISTICS_PORT_NUMBER_FC_PORT1 5 | ||
2879 | |||
2880 | |||
2881 | /* | ||
2882 | * context definitions for QLA84_MGMT_INFO_LIF_STAT | ||
2883 | */ | ||
2884 | #define IC_LIF_STATISTICS_LIF_NUMBER_ETHERNET_PORT0 0 | ||
2885 | #define IC_LIF_STATISTICS_LIF_NUMBER_ETHERNET_PORT1 1 | ||
2886 | #define IC_LIF_STATISTICS_LIF_NUMBER_FC_PORT0 2 | ||
2887 | #define IC_LIF_STATISTICS_LIF_NUMBER_FC_PORT1 3 | ||
2888 | #define IC_LIF_STATISTICS_LIF_NUMBER_CPU 6 | ||
2889 | |||
2890 | } info; /* for QLA84_MGMT_GET_INFO */ | ||
2891 | } u; | ||
2892 | }; | ||
2893 | |||
2894 | struct qla84_msg_mgmt { | ||
2895 | uint16_t cmd; | ||
2896 | #define QLA84_MGMT_READ_MEM 0x00 | ||
2897 | #define QLA84_MGMT_WRITE_MEM 0x01 | ||
2898 | #define QLA84_MGMT_CHNG_CONFIG 0x02 | ||
2899 | #define QLA84_MGMT_GET_INFO 0x03 | ||
2900 | uint16_t rsrvd; | ||
2901 | struct qla84_mgmt_param mgmtp;/* parameters for cmd */ | ||
2902 | uint32_t len; /* bytes in payload following this struct */ | ||
2903 | uint8_t payload[0]; /* payload for cmd */ | ||
2904 | }; | ||
2905 | |||
2906 | struct msg_update_fw { | ||
2907 | /* | ||
2908 | * diag_fw = 0 operational fw | ||
2909 | * otherwise diagnostic fw | ||
2910 | * offset, len, fw_len are present to overcome the current limitation | ||
2911 | * of 128Kb xfer size. The fw is sent in smaller chunks. Each chunk | ||
2912 | * specifies the byte "offset" where it fits in the fw buffer. The | ||
2913 | * number of bytes in each chunk is specified in "len". "fw_len" | ||
2914 | * is the total size of fw. The first chunk should start at offset = 0. | ||
2915 | * When offset+len == fw_len, the fw is written to the HBA. | ||
2916 | */ | ||
2917 | uint32_t diag_fw; | ||
2918 | uint32_t offset;/* start offset */ | ||
2919 | uint32_t len; /* num bytes in cur xfer */ | ||
2920 | uint32_t fw_len; /* size of fw in bytes */ | ||
2921 | uint8_t fw_bytes[0]; | ||
2922 | }; | ||
2923 | |||
2924 | #endif | 2969 | #endif |
diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h index 42c5587cc50c..93f833960147 100644 --- a/drivers/scsi/qla2xxx/qla_fw.h +++ b/drivers/scsi/qla2xxx/qla_fw.h | |||
@@ -400,6 +400,7 @@ struct cmd_type_6 { | |||
400 | struct scsi_lun lun; /* FCP LUN (BE). */ | 400 | struct scsi_lun lun; /* FCP LUN (BE). */ |
401 | 401 | ||
402 | uint16_t control_flags; /* Control flags. */ | 402 | uint16_t control_flags; /* Control flags. */ |
403 | #define CF_DIF_SEG_DESCR_ENABLE BIT_3 | ||
403 | #define CF_DATA_SEG_DESCR_ENABLE BIT_2 | 404 | #define CF_DATA_SEG_DESCR_ENABLE BIT_2 |
404 | #define CF_READ_DATA BIT_1 | 405 | #define CF_READ_DATA BIT_1 |
405 | #define CF_WRITE_DATA BIT_0 | 406 | #define CF_WRITE_DATA BIT_0 |
@@ -466,6 +467,43 @@ struct cmd_type_7 { | |||
466 | uint32_t dseg_0_len; /* Data segment 0 length. */ | 467 | uint32_t dseg_0_len; /* Data segment 0 length. */ |
467 | }; | 468 | }; |
468 | 469 | ||
470 | #define COMMAND_TYPE_CRC_2 0x6A /* Command Type CRC_2 (Type 6) | ||
471 | * (T10-DIF) */ | ||
472 | struct cmd_type_crc_2 { | ||
473 | uint8_t entry_type; /* Entry type. */ | ||
474 | uint8_t entry_count; /* Entry count. */ | ||
475 | uint8_t sys_define; /* System defined. */ | ||
476 | uint8_t entry_status; /* Entry Status. */ | ||
477 | |||
478 | uint32_t handle; /* System handle. */ | ||
479 | |||
480 | uint16_t nport_handle; /* N_PORT handle. */ | ||
481 | uint16_t timeout; /* Command timeout. */ | ||
482 | |||
483 | uint16_t dseg_count; /* Data segment count. */ | ||
484 | |||
485 | uint16_t fcp_rsp_dseg_len; /* FCP_RSP DSD length. */ | ||
486 | |||
487 | struct scsi_lun lun; /* FCP LUN (BE). */ | ||
488 | |||
489 | uint16_t control_flags; /* Control flags. */ | ||
490 | |||
491 | uint16_t fcp_cmnd_dseg_len; /* Data segment length. */ | ||
492 | uint32_t fcp_cmnd_dseg_address[2]; /* Data segment address. */ | ||
493 | |||
494 | uint32_t fcp_rsp_dseg_address[2]; /* Data segment address. */ | ||
495 | |||
496 | uint32_t byte_count; /* Total byte count. */ | ||
497 | |||
498 | uint8_t port_id[3]; /* PortID of destination port. */ | ||
499 | uint8_t vp_index; | ||
500 | |||
501 | uint32_t crc_context_address[2]; /* Data segment address. */ | ||
502 | uint16_t crc_context_len; /* Data segment length. */ | ||
503 | uint16_t reserved_1; /* MUST be set to 0. */ | ||
504 | }; | ||
505 | |||
506 | |||
469 | /* | 507 | /* |
470 | * ISP queue - status entry structure definition. | 508 | * ISP queue - status entry structure definition. |
471 | */ | 509 | */ |
@@ -496,10 +534,17 @@ struct sts_entry_24xx { | |||
496 | 534 | ||
497 | uint32_t sense_len; /* FCP SENSE length. */ | 535 | uint32_t sense_len; /* FCP SENSE length. */ |
498 | uint32_t rsp_data_len; /* FCP response data length. */ | 536 | uint32_t rsp_data_len; /* FCP response data length. */ |
499 | |||
500 | uint8_t data[28]; /* FCP response/sense information. */ | 537 | uint8_t data[28]; /* FCP response/sense information. */ |
538 | /* | ||
539 | * If DIF Error is set in comp_status, these additional fields are | ||
540 | * defined: | ||
541 | * &data[10] : uint8_t report_runt_bg[2]; - computed guard | ||
542 | * &data[12] : uint8_t actual_dif[8]; - DIF Data recieved | ||
543 | * &data[20] : uint8_t expected_dif[8]; - DIF Data computed | ||
544 | */ | ||
501 | }; | 545 | }; |
502 | 546 | ||
547 | |||
503 | /* | 548 | /* |
504 | * Status entry completion status | 549 | * Status entry completion status |
505 | */ | 550 | */ |
@@ -841,6 +886,8 @@ struct device_reg_24xx { | |||
841 | #define FA_HW_EVENT_ENTRY_SIZE 4 | 886 | #define FA_HW_EVENT_ENTRY_SIZE 4 |
842 | #define FA_NPIV_CONF0_ADDR 0x5C000 | 887 | #define FA_NPIV_CONF0_ADDR 0x5C000 |
843 | #define FA_NPIV_CONF1_ADDR 0x5D000 | 888 | #define FA_NPIV_CONF1_ADDR 0x5D000 |
889 | #define FA_FCP_PRIO0_ADDR 0x10000 | ||
890 | #define FA_FCP_PRIO1_ADDR 0x12000 | ||
844 | 891 | ||
845 | /* | 892 | /* |
846 | * Flash Error Log Event Codes. | 893 | * Flash Error Log Event Codes. |
@@ -1274,6 +1321,8 @@ struct qla_flt_header { | |||
1274 | #define FLT_REG_NPIV_CONF_0 0x29 | 1321 | #define FLT_REG_NPIV_CONF_0 0x29 |
1275 | #define FLT_REG_NPIV_CONF_1 0x2a | 1322 | #define FLT_REG_NPIV_CONF_1 0x2a |
1276 | #define FLT_REG_GOLD_FW 0x2f | 1323 | #define FLT_REG_GOLD_FW 0x2f |
1324 | #define FLT_REG_FCP_PRIO_0 0x87 | ||
1325 | #define FLT_REG_FCP_PRIO_1 0x88 | ||
1277 | 1326 | ||
1278 | struct qla_flt_region { | 1327 | struct qla_flt_region { |
1279 | uint32_t code; | 1328 | uint32_t code; |
@@ -1750,6 +1799,61 @@ struct ex_init_cb_81xx { | |||
1750 | #define FARX_ACCESS_FLASH_CONF_81XX 0x7FFD0000 | 1799 | #define FARX_ACCESS_FLASH_CONF_81XX 0x7FFD0000 |
1751 | #define FARX_ACCESS_FLASH_DATA_81XX 0x7F800000 | 1800 | #define FARX_ACCESS_FLASH_DATA_81XX 0x7F800000 |
1752 | 1801 | ||
1802 | /* FCP priority config defines *************************************/ | ||
1803 | /* operations */ | ||
1804 | #define QLFC_FCP_PRIO_DISABLE 0x0 | ||
1805 | #define QLFC_FCP_PRIO_ENABLE 0x1 | ||
1806 | #define QLFC_FCP_PRIO_GET_CONFIG 0x2 | ||
1807 | #define QLFC_FCP_PRIO_SET_CONFIG 0x3 | ||
1808 | |||
1809 | struct qla_fcp_prio_entry { | ||
1810 | uint16_t flags; /* Describes parameter(s) in FCP */ | ||
1811 | /* priority entry that are valid */ | ||
1812 | #define FCP_PRIO_ENTRY_VALID 0x1 | ||
1813 | #define FCP_PRIO_ENTRY_TAG_VALID 0x2 | ||
1814 | #define FCP_PRIO_ENTRY_SPID_VALID 0x4 | ||
1815 | #define FCP_PRIO_ENTRY_DPID_VALID 0x8 | ||
1816 | #define FCP_PRIO_ENTRY_LUNB_VALID 0x10 | ||
1817 | #define FCP_PRIO_ENTRY_LUNE_VALID 0x20 | ||
1818 | #define FCP_PRIO_ENTRY_SWWN_VALID 0x40 | ||
1819 | #define FCP_PRIO_ENTRY_DWWN_VALID 0x80 | ||
1820 | uint8_t tag; /* Priority value */ | ||
1821 | uint8_t reserved; /* Reserved for future use */ | ||
1822 | uint32_t src_pid; /* Src port id. high order byte */ | ||
1823 | /* unused; -1 (wild card) */ | ||
1824 | uint32_t dst_pid; /* Src port id. high order byte */ | ||
1825 | /* unused; -1 (wild card) */ | ||
1826 | uint16_t lun_beg; /* 1st lun num of lun range. */ | ||
1827 | /* -1 (wild card) */ | ||
1828 | uint16_t lun_end; /* 2nd lun num of lun range. */ | ||
1829 | /* -1 (wild card) */ | ||
1830 | uint8_t src_wwpn[8]; /* Source WWPN: -1 (wild card) */ | ||
1831 | uint8_t dst_wwpn[8]; /* Destination WWPN: -1 (wild card) */ | ||
1832 | }; | ||
1833 | |||
1834 | struct qla_fcp_prio_cfg { | ||
1835 | uint8_t signature[4]; /* "HQOS" signature of config data */ | ||
1836 | uint16_t version; /* 1: Initial version */ | ||
1837 | uint16_t length; /* config data size in num bytes */ | ||
1838 | uint16_t checksum; /* config data bytes checksum */ | ||
1839 | uint16_t num_entries; /* Number of entries */ | ||
1840 | uint16_t size_of_entry; /* Size of each entry in num bytes */ | ||
1841 | uint8_t attributes; /* enable/disable, persistence */ | ||
1842 | #define FCP_PRIO_ATTR_DISABLE 0x0 | ||
1843 | #define FCP_PRIO_ATTR_ENABLE 0x1 | ||
1844 | #define FCP_PRIO_ATTR_PERSIST 0x2 | ||
1845 | uint8_t reserved; /* Reserved for future use */ | ||
1846 | #define FCP_PRIO_CFG_HDR_SIZE 0x10 | ||
1847 | struct qla_fcp_prio_entry entry[1]; /* fcp priority entries */ | ||
1848 | #define FCP_PRIO_CFG_ENTRY_SIZE 0x20 | ||
1849 | }; | ||
1850 | |||
1851 | #define FCP_PRIO_CFG_SIZE (32*1024) /* fcp prio data per port*/ | ||
1852 | |||
1853 | /* 25XX Support ****************************************************/ | ||
1854 | #define FA_FCP_PRIO0_ADDR_25 0x3C000 | ||
1855 | #define FA_FCP_PRIO1_ADDR_25 0x3E000 | ||
1856 | |||
1753 | /* 81XX Flash locations -- occupies second 2MB region. */ | 1857 | /* 81XX Flash locations -- occupies second 2MB region. */ |
1754 | #define FA_BOOT_CODE_ADDR_81 0x80000 | 1858 | #define FA_BOOT_CODE_ADDR_81 0x80000 |
1755 | #define FA_RISC_CODE_ADDR_81 0xA0000 | 1859 | #define FA_RISC_CODE_ADDR_81 0xA0000 |
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 3a89bc514e2b..8217c3bcbc2e 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h | |||
@@ -44,6 +44,7 @@ extern int qla2x00_local_device_login(scsi_qla_host_t *, fc_port_t *); | |||
44 | extern void qla2x00_update_fcports(scsi_qla_host_t *); | 44 | extern void qla2x00_update_fcports(scsi_qla_host_t *); |
45 | 45 | ||
46 | extern int qla2x00_abort_isp(scsi_qla_host_t *); | 46 | extern int qla2x00_abort_isp(scsi_qla_host_t *); |
47 | extern void qla2x00_abort_isp_cleanup(scsi_qla_host_t *); | ||
47 | 48 | ||
48 | extern void qla2x00_update_fcport(scsi_qla_host_t *, fc_port_t *); | 49 | extern void qla2x00_update_fcport(scsi_qla_host_t *, fc_port_t *); |
49 | 50 | ||
@@ -55,10 +56,20 @@ extern void qla84xx_put_chip(struct scsi_qla_host *); | |||
55 | extern int qla2x00_async_login(struct scsi_qla_host *, fc_port_t *, | 56 | extern int qla2x00_async_login(struct scsi_qla_host *, fc_port_t *, |
56 | uint16_t *); | 57 | uint16_t *); |
57 | extern int qla2x00_async_logout(struct scsi_qla_host *, fc_port_t *); | 58 | extern int qla2x00_async_logout(struct scsi_qla_host *, fc_port_t *); |
58 | extern int qla2x00_async_login_done(struct scsi_qla_host *, fc_port_t *, | 59 | extern int qla2x00_async_adisc(struct scsi_qla_host *, fc_port_t *, |
59 | uint16_t *); | 60 | uint16_t *); |
60 | extern int qla2x00_async_logout_done(struct scsi_qla_host *, fc_port_t *, | 61 | extern int qla2x00_async_tm_cmd(fc_port_t *, uint32_t, uint32_t, uint32_t); |
62 | extern int qla2x00_async_marker(fc_port_t *, uint16_t, uint8_t); | ||
63 | extern void qla2x00_async_login_done(struct scsi_qla_host *, fc_port_t *, | ||
61 | uint16_t *); | 64 | uint16_t *); |
65 | extern void qla2x00_async_logout_done(struct scsi_qla_host *, fc_port_t *, | ||
66 | uint16_t *); | ||
67 | extern void qla2x00_async_adisc_done(struct scsi_qla_host *, fc_port_t *, | ||
68 | uint16_t *); | ||
69 | extern void qla2x00_async_tm_cmd_done(struct scsi_qla_host *, fc_port_t *, | ||
70 | struct srb_iocb *); | ||
71 | extern void qla2x00_async_marker_done(struct scsi_qla_host *, fc_port_t *, | ||
72 | struct srb_iocb *); | ||
62 | 73 | ||
63 | extern fc_port_t * | 74 | extern fc_port_t * |
64 | qla2x00_alloc_fcport(scsi_qla_host_t *, gfp_t ); | 75 | qla2x00_alloc_fcport(scsi_qla_host_t *, gfp_t ); |
@@ -79,6 +90,13 @@ extern int ql2xmaxqueues; | |||
79 | extern int ql2xmultique_tag; | 90 | extern int ql2xmultique_tag; |
80 | extern int ql2xfwloadbin; | 91 | extern int ql2xfwloadbin; |
81 | extern int ql2xetsenable; | 92 | extern int ql2xetsenable; |
93 | extern int ql2xshiftctondsd; | ||
94 | extern int ql2xdbwr; | ||
95 | extern int ql2xdontresethba; | ||
96 | extern int ql2xasynctmfenable; | ||
97 | extern int ql2xenabledif; | ||
98 | extern int ql2xenablehba_err_chk; | ||
99 | extern int ql2xtargetreset; | ||
82 | 100 | ||
83 | extern int qla2x00_loop_reset(scsi_qla_host_t *); | 101 | extern int qla2x00_loop_reset(scsi_qla_host_t *); |
84 | extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int); | 102 | extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int); |
@@ -93,6 +111,10 @@ extern int qla2x00_post_async_logout_work(struct scsi_qla_host *, fc_port_t *, | |||
93 | uint16_t *); | 111 | uint16_t *); |
94 | extern int qla2x00_post_async_logout_done_work(struct scsi_qla_host *, | 112 | extern int qla2x00_post_async_logout_done_work(struct scsi_qla_host *, |
95 | fc_port_t *, uint16_t *); | 113 | fc_port_t *, uint16_t *); |
114 | extern int qla2x00_post_async_adisc_work(struct scsi_qla_host *, fc_port_t *, | ||
115 | uint16_t *); | ||
116 | extern int qla2x00_post_async_adisc_done_work(struct scsi_qla_host *, | ||
117 | fc_port_t *, uint16_t *); | ||
96 | extern int qla2x00_post_uevent_work(struct scsi_qla_host *, u32); | 118 | extern int qla2x00_post_uevent_work(struct scsi_qla_host *, u32); |
97 | 119 | ||
98 | extern int qla81xx_restart_mpi_firmware(scsi_qla_host_t *); | 120 | extern int qla81xx_restart_mpi_firmware(scsi_qla_host_t *); |
@@ -135,6 +157,7 @@ extern struct fw_blob *qla2x00_request_firmware(scsi_qla_host_t *); | |||
135 | 157 | ||
136 | extern int qla2x00_wait_for_hba_online(scsi_qla_host_t *); | 158 | extern int qla2x00_wait_for_hba_online(scsi_qla_host_t *); |
137 | extern int qla2x00_wait_for_chip_reset(scsi_qla_host_t *); | 159 | extern int qla2x00_wait_for_chip_reset(scsi_qla_host_t *); |
160 | extern int qla2x00_wait_for_fcoe_ctx_reset(scsi_qla_host_t *); | ||
138 | 161 | ||
139 | extern void qla2xxx_wake_dpc(struct scsi_qla_host *); | 162 | extern void qla2xxx_wake_dpc(struct scsi_qla_host *); |
140 | extern void qla2x00_alert_all_vps(struct rsp_que *, uint16_t *); | 163 | extern void qla2x00_alert_all_vps(struct rsp_que *, uint16_t *); |
@@ -157,6 +180,10 @@ int __qla2x00_marker(struct scsi_qla_host *, struct req_que *, struct rsp_que *, | |||
157 | uint16_t, uint16_t, uint8_t); | 180 | uint16_t, uint16_t, uint8_t); |
158 | extern int qla2x00_start_sp(srb_t *); | 181 | extern int qla2x00_start_sp(srb_t *); |
159 | extern void qla2x00_ctx_sp_free(srb_t *); | 182 | extern void qla2x00_ctx_sp_free(srb_t *); |
183 | extern uint16_t qla24xx_calc_iocbs(uint16_t); | ||
184 | extern void qla24xx_build_scsi_iocbs(srb_t *, struct cmd_type_7 *, uint16_t); | ||
185 | extern int qla24xx_dif_start_scsi(srb_t *); | ||
186 | |||
160 | 187 | ||
161 | /* | 188 | /* |
162 | * Global Function Prototypes in qla_mbx.c source file. | 189 | * Global Function Prototypes in qla_mbx.c source file. |
@@ -328,6 +355,9 @@ extern int | |||
328 | qla2x00_write_ram_word(scsi_qla_host_t *, uint32_t, uint32_t); | 355 | qla2x00_write_ram_word(scsi_qla_host_t *, uint32_t, uint32_t); |
329 | 356 | ||
330 | extern int qla2x00_get_data_rate(scsi_qla_host_t *); | 357 | extern int qla2x00_get_data_rate(scsi_qla_host_t *); |
358 | extern int qla24xx_set_fcp_prio(scsi_qla_host_t *, uint16_t, uint16_t, | ||
359 | uint16_t *); | ||
360 | |||
331 | /* | 361 | /* |
332 | * Global Function Prototypes in qla_isr.c source file. | 362 | * Global Function Prototypes in qla_isr.c source file. |
333 | */ | 363 | */ |
@@ -340,6 +370,7 @@ qla24xx_process_response_queue(struct scsi_qla_host *, struct rsp_que *); | |||
340 | extern int qla2x00_request_irqs(struct qla_hw_data *, struct rsp_que *); | 370 | extern int qla2x00_request_irqs(struct qla_hw_data *, struct rsp_que *); |
341 | extern void qla2x00_free_irqs(scsi_qla_host_t *); | 371 | extern void qla2x00_free_irqs(scsi_qla_host_t *); |
342 | 372 | ||
373 | extern int qla2x00_get_data_rate(scsi_qla_host_t *); | ||
343 | /* | 374 | /* |
344 | * Global Function Prototypes in qla_sup.c source file. | 375 | * Global Function Prototypes in qla_sup.c source file. |
345 | */ | 376 | */ |
@@ -384,6 +415,7 @@ extern int qla2xxx_get_flash_info(scsi_qla_host_t *); | |||
384 | extern int qla2xxx_get_vpd_field(scsi_qla_host_t *, char *, char *, size_t); | 415 | extern int qla2xxx_get_vpd_field(scsi_qla_host_t *, char *, char *, size_t); |
385 | 416 | ||
386 | extern void qla2xxx_flash_npiv_conf(scsi_qla_host_t *); | 417 | extern void qla2xxx_flash_npiv_conf(scsi_qla_host_t *); |
418 | extern int qla24xx_read_fcp_prio_cfg(scsi_qla_host_t *); | ||
387 | 419 | ||
388 | /* | 420 | /* |
389 | * Global Function Prototypes in qla_dbg.c source file. | 421 | * Global Function Prototypes in qla_dbg.c source file. |
@@ -395,6 +427,7 @@ extern void qla25xx_fw_dump(scsi_qla_host_t *, int); | |||
395 | extern void qla81xx_fw_dump(scsi_qla_host_t *, int); | 427 | extern void qla81xx_fw_dump(scsi_qla_host_t *, int); |
396 | extern void qla2x00_dump_regs(scsi_qla_host_t *); | 428 | extern void qla2x00_dump_regs(scsi_qla_host_t *); |
397 | extern void qla2x00_dump_buffer(uint8_t *, uint32_t); | 429 | extern void qla2x00_dump_buffer(uint8_t *, uint32_t); |
430 | extern void qla2x00_dump_buffer_zipped(uint8_t *, uint32_t); | ||
398 | 431 | ||
399 | /* | 432 | /* |
400 | * Global Function Prototypes in qla_gs.c source file. | 433 | * Global Function Prototypes in qla_gs.c source file. |
@@ -430,7 +463,10 @@ extern void qla2x00_init_host_attr(scsi_qla_host_t *); | |||
430 | extern void qla2x00_alloc_sysfs_attr(scsi_qla_host_t *); | 463 | extern void qla2x00_alloc_sysfs_attr(scsi_qla_host_t *); |
431 | extern void qla2x00_free_sysfs_attr(scsi_qla_host_t *); | 464 | extern void qla2x00_free_sysfs_attr(scsi_qla_host_t *); |
432 | extern int qla2x00_loopback_test(scsi_qla_host_t *, struct msg_echo_lb *, uint16_t *); | 465 | extern int qla2x00_loopback_test(scsi_qla_host_t *, struct msg_echo_lb *, uint16_t *); |
433 | extern int qla2x00_echo_test(scsi_qla_host_t *, struct msg_echo_lb *, uint16_t *); | 466 | extern int qla2x00_echo_test(scsi_qla_host_t *, |
467 | struct msg_echo_lb *, uint16_t *); | ||
468 | extern int qla24xx_update_all_fcp_prio(scsi_qla_host_t *); | ||
469 | extern int qla24xx_fcp_prio_cfg_valid(struct qla_fcp_prio_cfg *, uint8_t); | ||
434 | 470 | ||
435 | /* | 471 | /* |
436 | * Global Function Prototypes in qla_dfs.c source file. | 472 | * Global Function Prototypes in qla_dfs.c source file. |
@@ -459,4 +495,88 @@ extern void qla25xx_wrt_req_reg(struct qla_hw_data *, uint16_t, uint16_t); | |||
459 | extern void qla25xx_wrt_rsp_reg(struct qla_hw_data *, uint16_t, uint16_t); | 495 | extern void qla25xx_wrt_rsp_reg(struct qla_hw_data *, uint16_t, uint16_t); |
460 | extern void qla24xx_wrt_rsp_reg(struct qla_hw_data *, uint16_t, uint16_t); | 496 | extern void qla24xx_wrt_rsp_reg(struct qla_hw_data *, uint16_t, uint16_t); |
461 | 497 | ||
498 | /* qla82xx related functions */ | ||
499 | |||
500 | /* PCI related functions */ | ||
501 | extern int qla82xx_pci_config(struct scsi_qla_host *); | ||
502 | extern int qla82xx_pci_mem_read_2M(struct qla_hw_data *, u64, void *, int); | ||
503 | extern int qla82xx_pci_mem_write_2M(struct qla_hw_data *, u64, void *, int); | ||
504 | extern char *qla82xx_pci_info_str(struct scsi_qla_host *, char *); | ||
505 | extern int qla82xx_pci_region_offset(struct pci_dev *, int); | ||
506 | extern int qla82xx_pci_region_len(struct pci_dev *, int); | ||
507 | extern int qla82xx_iospace_config(struct qla_hw_data *); | ||
508 | |||
509 | /* Initialization related functions */ | ||
510 | extern void qla82xx_reset_chip(struct scsi_qla_host *); | ||
511 | extern void qla82xx_config_rings(struct scsi_qla_host *); | ||
512 | extern int qla82xx_nvram_config(struct scsi_qla_host *); | ||
513 | extern int qla82xx_pinit_from_rom(scsi_qla_host_t *); | ||
514 | extern int qla82xx_load_firmware(scsi_qla_host_t *); | ||
515 | extern int qla82xx_reset_hw(scsi_qla_host_t *); | ||
516 | extern int qla82xx_load_risc_blob(scsi_qla_host_t *, uint32_t *); | ||
517 | extern void qla82xx_watchdog(scsi_qla_host_t *); | ||
518 | |||
519 | /* Firmware and flash related functions */ | ||
520 | extern int qla82xx_load_risc(scsi_qla_host_t *, uint32_t *); | ||
521 | extern uint8_t *qla82xx_read_optrom_data(struct scsi_qla_host *, uint8_t *, | ||
522 | uint32_t, uint32_t); | ||
523 | extern int qla82xx_write_optrom_data(struct scsi_qla_host *, uint8_t *, | ||
524 | uint32_t, uint32_t); | ||
525 | |||
526 | /* Mailbox related functions */ | ||
527 | extern int qla82xx_abort_isp(scsi_qla_host_t *); | ||
528 | extern int qla82xx_restart_isp(scsi_qla_host_t *); | ||
529 | |||
530 | /* IOCB related functions */ | ||
531 | extern int qla82xx_start_scsi(srb_t *); | ||
532 | |||
533 | /* Interrupt related */ | ||
534 | extern irqreturn_t qla82xx_intr_handler(int, void *); | ||
535 | extern irqreturn_t qla82xx_msi_handler(int, void *); | ||
536 | extern irqreturn_t qla82xx_msix_default(int, void *); | ||
537 | extern irqreturn_t qla82xx_msix_rsp_q(int, void *); | ||
538 | extern void qla82xx_enable_intrs(struct qla_hw_data *); | ||
539 | extern void qla82xx_disable_intrs(struct qla_hw_data *); | ||
540 | extern void qla82xx_mbx_completion(scsi_qla_host_t *, uint16_t); | ||
541 | extern void qla82xx_poll(int, void *); | ||
542 | extern void qla82xx_init_flags(struct qla_hw_data *); | ||
543 | |||
544 | /* ISP 8021 hardware related */ | ||
545 | extern int qla82xx_crb_win_lock(struct qla_hw_data *); | ||
546 | extern void qla82xx_crb_win_unlock(struct qla_hw_data *); | ||
547 | extern int qla82xx_pci_get_crb_addr_2M(struct qla_hw_data *, ulong *); | ||
548 | extern int qla82xx_wr_32(struct qla_hw_data *, ulong, u32); | ||
549 | extern int qla82xx_rd_32(struct qla_hw_data *, ulong); | ||
550 | extern int qla82xx_rdmem(struct qla_hw_data *, u64, void *, int); | ||
551 | extern int qla82xx_wrmem(struct qla_hw_data *, u64, void *, int); | ||
552 | extern int qla82xx_check_for_bad_spd(struct qla_hw_data *); | ||
553 | extern int qla82xx_load_fw(scsi_qla_host_t *); | ||
554 | extern int qla82xx_rom_lock(struct qla_hw_data *); | ||
555 | extern void qla82xx_rom_unlock(struct qla_hw_data *); | ||
556 | extern int qla82xx_rom_fast_read(struct qla_hw_data *, int , int *); | ||
557 | extern int qla82xx_do_rom_fast_read(struct qla_hw_data *, int, int *); | ||
558 | extern unsigned long qla82xx_decode_crb_addr(unsigned long); | ||
559 | |||
560 | /* ISP 8021 IDC */ | ||
561 | extern void qla82xx_clear_drv_active(struct qla_hw_data *); | ||
562 | extern int qla82xx_idc_lock(struct qla_hw_data *); | ||
563 | extern void qla82xx_idc_unlock(struct qla_hw_data *); | ||
564 | extern int qla82xx_device_state_handler(scsi_qla_host_t *); | ||
565 | |||
566 | extern void qla2x00_set_model_info(scsi_qla_host_t *, uint8_t *, | ||
567 | size_t, char *); | ||
568 | extern int qla82xx_mbx_intr_enable(scsi_qla_host_t *); | ||
569 | extern int qla82xx_mbx_intr_disable(scsi_qla_host_t *); | ||
570 | extern void qla82xx_start_iocbs(srb_t *); | ||
571 | extern int qla82xx_fcoe_ctx_reset(scsi_qla_host_t *); | ||
572 | extern void qla82xx_wait_for_pending_commands(scsi_qla_host_t *); | ||
573 | |||
574 | /* BSG related functions */ | ||
575 | extern int qla24xx_bsg_request(struct fc_bsg_job *); | ||
576 | extern int qla24xx_bsg_timeout(struct fc_bsg_job *); | ||
577 | extern int qla84xx_reset_chip(scsi_qla_host_t *, uint16_t); | ||
578 | extern int qla2x00_issue_iocb_timeout(scsi_qla_host_t *, void *, | ||
579 | dma_addr_t, size_t, uint32_t); | ||
580 | extern int qla2x00_get_idma_speed(scsi_qla_host_t *, uint16_t, | ||
581 | uint16_t *, uint16_t *); | ||
462 | #endif /* _QLA_GBL_H */ | 582 | #endif /* _QLA_GBL_H */ |
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index 4647015eba63..872c55f049a5 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c | |||
@@ -1535,7 +1535,7 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *vha) | |||
1535 | eiter = (struct ct_fdmi_port_attr *) (entries + size); | 1535 | eiter = (struct ct_fdmi_port_attr *) (entries + size); |
1536 | eiter->type = __constant_cpu_to_be16(FDMI_PORT_SUPPORT_SPEED); | 1536 | eiter->type = __constant_cpu_to_be16(FDMI_PORT_SUPPORT_SPEED); |
1537 | eiter->len = __constant_cpu_to_be16(4 + 4); | 1537 | eiter->len = __constant_cpu_to_be16(4 + 4); |
1538 | if (IS_QLA81XX(ha)) | 1538 | if (IS_QLA8XXX_TYPE(ha)) |
1539 | eiter->a.sup_speed = __constant_cpu_to_be32( | 1539 | eiter->a.sup_speed = __constant_cpu_to_be32( |
1540 | FDMI_PORT_SPEED_10GB); | 1540 | FDMI_PORT_SPEED_10GB); |
1541 | else if (IS_QLA25XX(ha)) | 1541 | else if (IS_QLA25XX(ha)) |
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 4229bb483c5e..ab2cc71994c2 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c | |||
@@ -48,6 +48,7 @@ qla2x00_ctx_sp_timeout(unsigned long __data) | |||
48 | { | 48 | { |
49 | srb_t *sp = (srb_t *)__data; | 49 | srb_t *sp = (srb_t *)__data; |
50 | struct srb_ctx *ctx; | 50 | struct srb_ctx *ctx; |
51 | struct srb_iocb *iocb; | ||
51 | fc_port_t *fcport = sp->fcport; | 52 | fc_port_t *fcport = sp->fcport; |
52 | struct qla_hw_data *ha = fcport->vha->hw; | 53 | struct qla_hw_data *ha = fcport->vha->hw; |
53 | struct req_que *req; | 54 | struct req_que *req; |
@@ -57,17 +58,21 @@ qla2x00_ctx_sp_timeout(unsigned long __data) | |||
57 | req = ha->req_q_map[0]; | 58 | req = ha->req_q_map[0]; |
58 | req->outstanding_cmds[sp->handle] = NULL; | 59 | req->outstanding_cmds[sp->handle] = NULL; |
59 | ctx = sp->ctx; | 60 | ctx = sp->ctx; |
60 | ctx->timeout(sp); | 61 | iocb = ctx->u.iocb_cmd; |
62 | iocb->timeout(sp); | ||
61 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 63 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
62 | 64 | ||
63 | ctx->free(sp); | 65 | iocb->free(sp); |
64 | } | 66 | } |
65 | 67 | ||
66 | void | 68 | void |
67 | qla2x00_ctx_sp_free(srb_t *sp) | 69 | qla2x00_ctx_sp_free(srb_t *sp) |
68 | { | 70 | { |
69 | struct srb_ctx *ctx = sp->ctx; | 71 | struct srb_ctx *ctx = sp->ctx; |
72 | struct srb_iocb *iocb = ctx->u.iocb_cmd; | ||
70 | 73 | ||
74 | del_timer_sync(&iocb->timer); | ||
75 | kfree(iocb); | ||
71 | kfree(ctx); | 76 | kfree(ctx); |
72 | mempool_free(sp, sp->fcport->vha->hw->srb_mempool); | 77 | mempool_free(sp, sp->fcport->vha->hw->srb_mempool); |
73 | } | 78 | } |
@@ -79,6 +84,7 @@ qla2x00_get_ctx_sp(scsi_qla_host_t *vha, fc_port_t *fcport, size_t size, | |||
79 | srb_t *sp; | 84 | srb_t *sp; |
80 | struct qla_hw_data *ha = vha->hw; | 85 | struct qla_hw_data *ha = vha->hw; |
81 | struct srb_ctx *ctx; | 86 | struct srb_ctx *ctx; |
87 | struct srb_iocb *iocb; | ||
82 | 88 | ||
83 | sp = mempool_alloc(ha->srb_mempool, GFP_KERNEL); | 89 | sp = mempool_alloc(ha->srb_mempool, GFP_KERNEL); |
84 | if (!sp) | 90 | if (!sp) |
@@ -86,21 +92,30 @@ qla2x00_get_ctx_sp(scsi_qla_host_t *vha, fc_port_t *fcport, size_t size, | |||
86 | ctx = kzalloc(size, GFP_KERNEL); | 92 | ctx = kzalloc(size, GFP_KERNEL); |
87 | if (!ctx) { | 93 | if (!ctx) { |
88 | mempool_free(sp, ha->srb_mempool); | 94 | mempool_free(sp, ha->srb_mempool); |
95 | sp = NULL; | ||
96 | goto done; | ||
97 | } | ||
98 | iocb = kzalloc(sizeof(struct srb_iocb), GFP_KERNEL); | ||
99 | if (!iocb) { | ||
100 | mempool_free(sp, ha->srb_mempool); | ||
101 | sp = NULL; | ||
102 | kfree(ctx); | ||
89 | goto done; | 103 | goto done; |
90 | } | 104 | } |
91 | 105 | ||
92 | memset(sp, 0, sizeof(*sp)); | 106 | memset(sp, 0, sizeof(*sp)); |
93 | sp->fcport = fcport; | 107 | sp->fcport = fcport; |
94 | sp->ctx = ctx; | 108 | sp->ctx = ctx; |
95 | ctx->free = qla2x00_ctx_sp_free; | 109 | ctx->u.iocb_cmd = iocb; |
110 | iocb->free = qla2x00_ctx_sp_free; | ||
96 | 111 | ||
97 | init_timer(&ctx->timer); | 112 | init_timer(&iocb->timer); |
98 | if (!tmo) | 113 | if (!tmo) |
99 | goto done; | 114 | goto done; |
100 | ctx->timer.expires = jiffies + tmo * HZ; | 115 | iocb->timer.expires = jiffies + tmo * HZ; |
101 | ctx->timer.data = (unsigned long)sp; | 116 | iocb->timer.data = (unsigned long)sp; |
102 | ctx->timer.function = qla2x00_ctx_sp_timeout; | 117 | iocb->timer.function = qla2x00_ctx_sp_timeout; |
103 | add_timer(&ctx->timer); | 118 | add_timer(&iocb->timer); |
104 | done: | 119 | done: |
105 | return sp; | 120 | return sp; |
106 | } | 121 | } |
@@ -110,41 +125,56 @@ done: | |||
110 | #define ELS_TMO_2_RATOV(ha) ((ha)->r_a_tov / 10 * 2) | 125 | #define ELS_TMO_2_RATOV(ha) ((ha)->r_a_tov / 10 * 2) |
111 | 126 | ||
112 | static void | 127 | static void |
113 | qla2x00_async_logio_timeout(srb_t *sp) | 128 | qla2x00_async_iocb_timeout(srb_t *sp) |
114 | { | 129 | { |
115 | fc_port_t *fcport = sp->fcport; | 130 | fc_port_t *fcport = sp->fcport; |
116 | struct srb_logio *lio = sp->ctx; | 131 | struct srb_ctx *ctx = sp->ctx; |
117 | 132 | ||
118 | DEBUG2(printk(KERN_WARNING | 133 | DEBUG2(printk(KERN_WARNING |
119 | "scsi(%ld:%x): Async-%s timeout.\n", | 134 | "scsi(%ld:%x): Async-%s timeout.\n", |
120 | fcport->vha->host_no, sp->handle, | 135 | fcport->vha->host_no, sp->handle, ctx->name)); |
121 | lio->ctx.type == SRB_LOGIN_CMD ? "login": "logout")); | ||
122 | 136 | ||
123 | if (lio->ctx.type == SRB_LOGIN_CMD) | 137 | fcport->flags &= ~FCF_ASYNC_SENT; |
138 | if (ctx->type == SRB_LOGIN_CMD) | ||
124 | qla2x00_post_async_logout_work(fcport->vha, fcport, NULL); | 139 | qla2x00_post_async_logout_work(fcport->vha, fcport, NULL); |
125 | } | 140 | } |
126 | 141 | ||
142 | static void | ||
143 | qla2x00_async_login_ctx_done(srb_t *sp) | ||
144 | { | ||
145 | struct srb_ctx *ctx = sp->ctx; | ||
146 | struct srb_iocb *lio = ctx->u.iocb_cmd; | ||
147 | |||
148 | qla2x00_post_async_login_done_work(sp->fcport->vha, sp->fcport, | ||
149 | lio->u.logio.data); | ||
150 | lio->free(sp); | ||
151 | } | ||
152 | |||
127 | int | 153 | int |
128 | qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport, | 154 | qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport, |
129 | uint16_t *data) | 155 | uint16_t *data) |
130 | { | 156 | { |
131 | struct qla_hw_data *ha = vha->hw; | 157 | struct qla_hw_data *ha = vha->hw; |
132 | srb_t *sp; | 158 | srb_t *sp; |
133 | struct srb_logio *lio; | 159 | struct srb_ctx *ctx; |
160 | struct srb_iocb *lio; | ||
134 | int rval; | 161 | int rval; |
135 | 162 | ||
136 | rval = QLA_FUNCTION_FAILED; | 163 | rval = QLA_FUNCTION_FAILED; |
137 | sp = qla2x00_get_ctx_sp(vha, fcport, sizeof(struct srb_logio), | 164 | sp = qla2x00_get_ctx_sp(vha, fcport, sizeof(struct srb_ctx), |
138 | ELS_TMO_2_RATOV(ha) + 2); | 165 | ELS_TMO_2_RATOV(ha) + 2); |
139 | if (!sp) | 166 | if (!sp) |
140 | goto done; | 167 | goto done; |
141 | 168 | ||
142 | lio = sp->ctx; | 169 | ctx = sp->ctx; |
143 | lio->ctx.type = SRB_LOGIN_CMD; | 170 | ctx->type = SRB_LOGIN_CMD; |
144 | lio->ctx.timeout = qla2x00_async_logio_timeout; | 171 | ctx->name = "login"; |
145 | lio->flags |= SRB_LOGIN_COND_PLOGI; | 172 | lio = ctx->u.iocb_cmd; |
173 | lio->timeout = qla2x00_async_iocb_timeout; | ||
174 | lio->done = qla2x00_async_login_ctx_done; | ||
175 | lio->u.logio.flags |= SRB_LOGIN_COND_PLOGI; | ||
146 | if (data[1] & QLA_LOGIO_LOGIN_RETRIED) | 176 | if (data[1] & QLA_LOGIO_LOGIN_RETRIED) |
147 | lio->flags |= SRB_LOGIN_RETRIED; | 177 | lio->u.logio.flags |= SRB_LOGIN_RETRIED; |
148 | rval = qla2x00_start_sp(sp); | 178 | rval = qla2x00_start_sp(sp); |
149 | if (rval != QLA_SUCCESS) | 179 | if (rval != QLA_SUCCESS) |
150 | goto done_free_sp; | 180 | goto done_free_sp; |
@@ -157,29 +187,43 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport, | |||
157 | return rval; | 187 | return rval; |
158 | 188 | ||
159 | done_free_sp: | 189 | done_free_sp: |
160 | del_timer_sync(&lio->ctx.timer); | 190 | lio->free(sp); |
161 | lio->ctx.free(sp); | ||
162 | done: | 191 | done: |
163 | return rval; | 192 | return rval; |
164 | } | 193 | } |
165 | 194 | ||
195 | static void | ||
196 | qla2x00_async_logout_ctx_done(srb_t *sp) | ||
197 | { | ||
198 | struct srb_ctx *ctx = sp->ctx; | ||
199 | struct srb_iocb *lio = ctx->u.iocb_cmd; | ||
200 | |||
201 | qla2x00_post_async_logout_done_work(sp->fcport->vha, sp->fcport, | ||
202 | lio->u.logio.data); | ||
203 | lio->free(sp); | ||
204 | } | ||
205 | |||
166 | int | 206 | int |
167 | qla2x00_async_logout(struct scsi_qla_host *vha, fc_port_t *fcport) | 207 | qla2x00_async_logout(struct scsi_qla_host *vha, fc_port_t *fcport) |
168 | { | 208 | { |
169 | struct qla_hw_data *ha = vha->hw; | 209 | struct qla_hw_data *ha = vha->hw; |
170 | srb_t *sp; | 210 | srb_t *sp; |
171 | struct srb_logio *lio; | 211 | struct srb_ctx *ctx; |
212 | struct srb_iocb *lio; | ||
172 | int rval; | 213 | int rval; |
173 | 214 | ||
174 | rval = QLA_FUNCTION_FAILED; | 215 | rval = QLA_FUNCTION_FAILED; |
175 | sp = qla2x00_get_ctx_sp(vha, fcport, sizeof(struct srb_logio), | 216 | sp = qla2x00_get_ctx_sp(vha, fcport, sizeof(struct srb_ctx), |
176 | ELS_TMO_2_RATOV(ha) + 2); | 217 | ELS_TMO_2_RATOV(ha) + 2); |
177 | if (!sp) | 218 | if (!sp) |
178 | goto done; | 219 | goto done; |
179 | 220 | ||
180 | lio = sp->ctx; | 221 | ctx = sp->ctx; |
181 | lio->ctx.type = SRB_LOGOUT_CMD; | 222 | ctx->type = SRB_LOGOUT_CMD; |
182 | lio->ctx.timeout = qla2x00_async_logio_timeout; | 223 | ctx->name = "logout"; |
224 | lio = ctx->u.iocb_cmd; | ||
225 | lio->timeout = qla2x00_async_iocb_timeout; | ||
226 | lio->done = qla2x00_async_logout_ctx_done; | ||
183 | rval = qla2x00_start_sp(sp); | 227 | rval = qla2x00_start_sp(sp); |
184 | if (rval != QLA_SUCCESS) | 228 | if (rval != QLA_SUCCESS) |
185 | goto done_free_sp; | 229 | goto done_free_sp; |
@@ -191,30 +235,186 @@ qla2x00_async_logout(struct scsi_qla_host *vha, fc_port_t *fcport) | |||
191 | return rval; | 235 | return rval; |
192 | 236 | ||
193 | done_free_sp: | 237 | done_free_sp: |
194 | del_timer_sync(&lio->ctx.timer); | 238 | lio->free(sp); |
195 | lio->ctx.free(sp); | ||
196 | done: | 239 | done: |
197 | return rval; | 240 | return rval; |
198 | } | 241 | } |
199 | 242 | ||
243 | static void | ||
244 | qla2x00_async_adisc_ctx_done(srb_t *sp) | ||
245 | { | ||
246 | struct srb_ctx *ctx = sp->ctx; | ||
247 | struct srb_iocb *lio = ctx->u.iocb_cmd; | ||
248 | |||
249 | qla2x00_post_async_adisc_done_work(sp->fcport->vha, sp->fcport, | ||
250 | lio->u.logio.data); | ||
251 | lio->free(sp); | ||
252 | } | ||
253 | |||
200 | int | 254 | int |
255 | qla2x00_async_adisc(struct scsi_qla_host *vha, fc_port_t *fcport, | ||
256 | uint16_t *data) | ||
257 | { | ||
258 | struct qla_hw_data *ha = vha->hw; | ||
259 | srb_t *sp; | ||
260 | struct srb_ctx *ctx; | ||
261 | struct srb_iocb *lio; | ||
262 | int rval; | ||
263 | |||
264 | rval = QLA_FUNCTION_FAILED; | ||
265 | sp = qla2x00_get_ctx_sp(vha, fcport, sizeof(struct srb_ctx), | ||
266 | ELS_TMO_2_RATOV(ha) + 2); | ||
267 | if (!sp) | ||
268 | goto done; | ||
269 | |||
270 | ctx = sp->ctx; | ||
271 | ctx->type = SRB_ADISC_CMD; | ||
272 | ctx->name = "adisc"; | ||
273 | lio = ctx->u.iocb_cmd; | ||
274 | lio->timeout = qla2x00_async_iocb_timeout; | ||
275 | lio->done = qla2x00_async_adisc_ctx_done; | ||
276 | if (data[1] & QLA_LOGIO_LOGIN_RETRIED) | ||
277 | lio->u.logio.flags |= SRB_LOGIN_RETRIED; | ||
278 | rval = qla2x00_start_sp(sp); | ||
279 | if (rval != QLA_SUCCESS) | ||
280 | goto done_free_sp; | ||
281 | |||
282 | DEBUG2(printk(KERN_DEBUG | ||
283 | "scsi(%ld:%x): Async-adisc - loop-id=%x portid=%02x%02x%02x.\n", | ||
284 | fcport->vha->host_no, sp->handle, fcport->loop_id, | ||
285 | fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa)); | ||
286 | |||
287 | return rval; | ||
288 | |||
289 | done_free_sp: | ||
290 | lio->free(sp); | ||
291 | done: | ||
292 | return rval; | ||
293 | } | ||
294 | |||
295 | static void | ||
296 | qla2x00_async_tm_cmd_ctx_done(srb_t *sp) | ||
297 | { | ||
298 | struct srb_ctx *ctx = sp->ctx; | ||
299 | struct srb_iocb *iocb = (struct srb_iocb *)ctx->u.iocb_cmd; | ||
300 | |||
301 | qla2x00_async_tm_cmd_done(sp->fcport->vha, sp->fcport, iocb); | ||
302 | iocb->free(sp); | ||
303 | } | ||
304 | |||
305 | int | ||
306 | qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun, | ||
307 | uint32_t tag) | ||
308 | { | ||
309 | struct scsi_qla_host *vha = fcport->vha; | ||
310 | struct qla_hw_data *ha = vha->hw; | ||
311 | srb_t *sp; | ||
312 | struct srb_ctx *ctx; | ||
313 | struct srb_iocb *tcf; | ||
314 | int rval; | ||
315 | |||
316 | rval = QLA_FUNCTION_FAILED; | ||
317 | sp = qla2x00_get_ctx_sp(vha, fcport, sizeof(struct srb_ctx), | ||
318 | ELS_TMO_2_RATOV(ha) + 2); | ||
319 | if (!sp) | ||
320 | goto done; | ||
321 | |||
322 | ctx = sp->ctx; | ||
323 | ctx->type = SRB_TM_CMD; | ||
324 | ctx->name = "tmf"; | ||
325 | tcf = ctx->u.iocb_cmd; | ||
326 | tcf->u.tmf.flags = flags; | ||
327 | tcf->u.tmf.lun = lun; | ||
328 | tcf->u.tmf.data = tag; | ||
329 | tcf->timeout = qla2x00_async_iocb_timeout; | ||
330 | tcf->done = qla2x00_async_tm_cmd_ctx_done; | ||
331 | |||
332 | rval = qla2x00_start_sp(sp); | ||
333 | if (rval != QLA_SUCCESS) | ||
334 | goto done_free_sp; | ||
335 | |||
336 | DEBUG2(printk(KERN_DEBUG | ||
337 | "scsi(%ld:%x): Async-tmf - loop-id=%x portid=%02x%02x%02x.\n", | ||
338 | fcport->vha->host_no, sp->handle, fcport->loop_id, | ||
339 | fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa)); | ||
340 | |||
341 | return rval; | ||
342 | |||
343 | done_free_sp: | ||
344 | tcf->free(sp); | ||
345 | done: | ||
346 | return rval; | ||
347 | } | ||
348 | |||
349 | static void | ||
350 | qla2x00_async_marker_ctx_done(srb_t *sp) | ||
351 | { | ||
352 | struct srb_ctx *ctx = sp->ctx; | ||
353 | struct srb_iocb *iocb = (struct srb_iocb *)ctx->u.iocb_cmd; | ||
354 | |||
355 | qla2x00_async_marker_done(sp->fcport->vha, sp->fcport, iocb); | ||
356 | iocb->free(sp); | ||
357 | } | ||
358 | |||
359 | int | ||
360 | qla2x00_async_marker(fc_port_t *fcport, uint16_t lun, uint8_t modif) | ||
361 | { | ||
362 | struct scsi_qla_host *vha = fcport->vha; | ||
363 | srb_t *sp; | ||
364 | struct srb_ctx *ctx; | ||
365 | struct srb_iocb *mrk; | ||
366 | int rval; | ||
367 | |||
368 | rval = QLA_FUNCTION_FAILED; | ||
369 | sp = qla2x00_get_ctx_sp(vha, fcport, sizeof(struct srb_ctx), 0); | ||
370 | if (!sp) | ||
371 | goto done; | ||
372 | |||
373 | ctx = sp->ctx; | ||
374 | ctx->type = SRB_MARKER_CMD; | ||
375 | ctx->name = "marker"; | ||
376 | mrk = ctx->u.iocb_cmd; | ||
377 | mrk->u.marker.lun = lun; | ||
378 | mrk->u.marker.modif = modif; | ||
379 | mrk->timeout = qla2x00_async_iocb_timeout; | ||
380 | mrk->done = qla2x00_async_marker_ctx_done; | ||
381 | |||
382 | rval = qla2x00_start_sp(sp); | ||
383 | if (rval != QLA_SUCCESS) | ||
384 | goto done_free_sp; | ||
385 | |||
386 | DEBUG2(printk(KERN_DEBUG | ||
387 | "scsi(%ld:%x): Async-marker - loop-id=%x " | ||
388 | "portid=%02x%02x%02x.\n", | ||
389 | fcport->vha->host_no, sp->handle, fcport->loop_id, | ||
390 | fcport->d_id.b.domain, fcport->d_id.b.area, | ||
391 | fcport->d_id.b.al_pa)); | ||
392 | |||
393 | return rval; | ||
394 | |||
395 | done_free_sp: | ||
396 | mrk->free(sp); | ||
397 | done: | ||
398 | return rval; | ||
399 | } | ||
400 | |||
401 | void | ||
201 | qla2x00_async_login_done(struct scsi_qla_host *vha, fc_port_t *fcport, | 402 | qla2x00_async_login_done(struct scsi_qla_host *vha, fc_port_t *fcport, |
202 | uint16_t *data) | 403 | uint16_t *data) |
203 | { | 404 | { |
204 | int rval; | 405 | int rval; |
205 | uint8_t opts = 0; | ||
206 | 406 | ||
207 | switch (data[0]) { | 407 | switch (data[0]) { |
208 | case MBS_COMMAND_COMPLETE: | 408 | case MBS_COMMAND_COMPLETE: |
209 | if (fcport->flags & FCF_FCP2_DEVICE) | 409 | if (fcport->flags & FCF_FCP2_DEVICE) { |
210 | opts |= BIT_1; | 410 | fcport->flags |= FCF_ASYNC_SENT; |
211 | rval = qla2x00_get_port_database(vha, fcport, opts); | 411 | qla2x00_post_async_adisc_work(vha, fcport, data); |
212 | if (rval != QLA_SUCCESS) | 412 | break; |
213 | qla2x00_mark_device_lost(vha, fcport, 1, 0); | 413 | } |
214 | else | 414 | qla2x00_update_fcport(vha, fcport); |
215 | qla2x00_update_fcport(vha, fcport); | ||
216 | break; | 415 | break; |
217 | case MBS_COMMAND_ERROR: | 416 | case MBS_COMMAND_ERROR: |
417 | fcport->flags &= ~FCF_ASYNC_SENT; | ||
218 | if (data[1] & QLA_LOGIO_LOGIN_RETRIED) | 418 | if (data[1] & QLA_LOGIO_LOGIN_RETRIED) |
219 | set_bit(RELOGIN_NEEDED, &vha->dpc_flags); | 419 | set_bit(RELOGIN_NEEDED, &vha->dpc_flags); |
220 | else | 420 | else |
@@ -228,21 +428,84 @@ qla2x00_async_login_done(struct scsi_qla_host *vha, fc_port_t *fcport, | |||
228 | fcport->loop_id++; | 428 | fcport->loop_id++; |
229 | rval = qla2x00_find_new_loop_id(vha, fcport); | 429 | rval = qla2x00_find_new_loop_id(vha, fcport); |
230 | if (rval != QLA_SUCCESS) { | 430 | if (rval != QLA_SUCCESS) { |
431 | fcport->flags &= ~FCF_ASYNC_SENT; | ||
231 | qla2x00_mark_device_lost(vha, fcport, 1, 0); | 432 | qla2x00_mark_device_lost(vha, fcport, 1, 0); |
232 | break; | 433 | break; |
233 | } | 434 | } |
234 | qla2x00_post_async_login_work(vha, fcport, NULL); | 435 | qla2x00_post_async_login_work(vha, fcport, NULL); |
235 | break; | 436 | break; |
236 | } | 437 | } |
237 | return QLA_SUCCESS; | 438 | return; |
238 | } | 439 | } |
239 | 440 | ||
240 | int | 441 | void |
241 | qla2x00_async_logout_done(struct scsi_qla_host *vha, fc_port_t *fcport, | 442 | qla2x00_async_logout_done(struct scsi_qla_host *vha, fc_port_t *fcport, |
242 | uint16_t *data) | 443 | uint16_t *data) |
243 | { | 444 | { |
244 | qla2x00_mark_device_lost(vha, fcport, 1, 0); | 445 | qla2x00_mark_device_lost(vha, fcport, 1, 0); |
245 | return QLA_SUCCESS; | 446 | return; |
447 | } | ||
448 | |||
449 | void | ||
450 | qla2x00_async_adisc_done(struct scsi_qla_host *vha, fc_port_t *fcport, | ||
451 | uint16_t *data) | ||
452 | { | ||
453 | if (data[0] == MBS_COMMAND_COMPLETE) { | ||
454 | qla2x00_update_fcport(vha, fcport); | ||
455 | |||
456 | return; | ||
457 | } | ||
458 | |||
459 | /* Retry login. */ | ||
460 | fcport->flags &= ~FCF_ASYNC_SENT; | ||
461 | if (data[1] & QLA_LOGIO_LOGIN_RETRIED) | ||
462 | set_bit(RELOGIN_NEEDED, &vha->dpc_flags); | ||
463 | else | ||
464 | qla2x00_mark_device_lost(vha, fcport, 1, 0); | ||
465 | |||
466 | return; | ||
467 | } | ||
468 | |||
469 | void | ||
470 | qla2x00_async_tm_cmd_done(struct scsi_qla_host *vha, fc_port_t *fcport, | ||
471 | struct srb_iocb *iocb) | ||
472 | { | ||
473 | int rval; | ||
474 | uint32_t flags; | ||
475 | uint16_t lun; | ||
476 | |||
477 | flags = iocb->u.tmf.flags; | ||
478 | lun = (uint16_t)iocb->u.tmf.lun; | ||
479 | |||
480 | /* Issue Marker IOCB */ | ||
481 | rval = qla2x00_async_marker(fcport, lun, | ||
482 | flags == TCF_LUN_RESET ? MK_SYNC_ID_LUN : MK_SYNC_ID); | ||
483 | |||
484 | if ((rval != QLA_SUCCESS) || iocb->u.tmf.data) { | ||
485 | DEBUG2_3_11(printk(KERN_WARNING | ||
486 | "%s(%ld): TM IOCB failed (%x).\n", | ||
487 | __func__, vha->host_no, rval)); | ||
488 | } | ||
489 | |||
490 | return; | ||
491 | } | ||
492 | |||
493 | void | ||
494 | qla2x00_async_marker_done(struct scsi_qla_host *vha, fc_port_t *fcport, | ||
495 | struct srb_iocb *iocb) | ||
496 | { | ||
497 | /* | ||
498 | * Currently we dont have any specific post response processing | ||
499 | * for this IOCB. We'll just return success or failed | ||
500 | * depending on whether the IOCB command succeeded or failed. | ||
501 | */ | ||
502 | if (iocb->u.tmf.data) { | ||
503 | DEBUG2_3_11(printk(KERN_WARNING | ||
504 | "%s(%ld): Marker IOCB failed (%x).\n", | ||
505 | __func__, vha->host_no, iocb->u.tmf.data)); | ||
506 | } | ||
507 | |||
508 | return; | ||
246 | } | 509 | } |
247 | 510 | ||
248 | /****************************************************************************/ | 511 | /****************************************************************************/ |
@@ -328,6 +591,7 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha) | |||
328 | if (rval) | 591 | if (rval) |
329 | return (rval); | 592 | return (rval); |
330 | } | 593 | } |
594 | |||
331 | if (IS_QLA84XX(ha)) { | 595 | if (IS_QLA84XX(ha)) { |
332 | ha->cs84xx = qla84xx_get_chip(vha); | 596 | ha->cs84xx = qla84xx_get_chip(vha); |
333 | if (!ha->cs84xx) { | 597 | if (!ha->cs84xx) { |
@@ -340,7 +604,7 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha) | |||
340 | ha->flags.chip_reset_done = 1; | 604 | ha->flags.chip_reset_done = 1; |
341 | 605 | ||
342 | if (rval == QLA_SUCCESS && IS_QLA84XX(ha)) { | 606 | if (rval == QLA_SUCCESS && IS_QLA84XX(ha)) { |
343 | /* Issue verify 84xx FW IOCB to complete 84xx initialization */ | 607 | /* Issue verify 84xx FW IOCB to complete 84xx initialization */ |
344 | rval = qla84xx_init_chip(vha); | 608 | rval = qla84xx_init_chip(vha); |
345 | if (rval != QLA_SUCCESS) { | 609 | if (rval != QLA_SUCCESS) { |
346 | qla_printk(KERN_ERR, ha, | 610 | qla_printk(KERN_ERR, ha, |
@@ -349,6 +613,12 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha) | |||
349 | } | 613 | } |
350 | } | 614 | } |
351 | 615 | ||
616 | if (IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha)) { | ||
617 | if (qla24xx_read_fcp_prio_cfg(vha)) | ||
618 | qla_printk(KERN_ERR, ha, | ||
619 | "Unable to read FCP priority data.\n"); | ||
620 | } | ||
621 | |||
352 | return (rval); | 622 | return (rval); |
353 | } | 623 | } |
354 | 624 | ||
@@ -955,6 +1225,9 @@ qla24xx_chip_diag(scsi_qla_host_t *vha) | |||
955 | struct qla_hw_data *ha = vha->hw; | 1225 | struct qla_hw_data *ha = vha->hw; |
956 | struct req_que *req = ha->req_q_map[0]; | 1226 | struct req_que *req = ha->req_q_map[0]; |
957 | 1227 | ||
1228 | if (IS_QLA82XX(ha)) | ||
1229 | return QLA_SUCCESS; | ||
1230 | |||
958 | ha->fw_transfer_size = REQUEST_ENTRY_SIZE * req->length; | 1231 | ha->fw_transfer_size = REQUEST_ENTRY_SIZE * req->length; |
959 | 1232 | ||
960 | rval = qla2x00_mbx_reg_test(vha); | 1233 | rval = qla2x00_mbx_reg_test(vha); |
@@ -1177,6 +1450,12 @@ qla2x00_setup_chip(scsi_qla_host_t *vha) | |||
1177 | unsigned long flags; | 1450 | unsigned long flags; |
1178 | uint16_t fw_major_version; | 1451 | uint16_t fw_major_version; |
1179 | 1452 | ||
1453 | if (IS_QLA82XX(ha)) { | ||
1454 | rval = ha->isp_ops->load_risc(vha, &srisc_address); | ||
1455 | if (rval == QLA_SUCCESS) | ||
1456 | goto enable_82xx_npiv; | ||
1457 | } | ||
1458 | |||
1180 | if (!IS_FWI2_CAPABLE(ha) && !IS_QLA2100(ha) && !IS_QLA2200(ha)) { | 1459 | if (!IS_FWI2_CAPABLE(ha) && !IS_QLA2100(ha) && !IS_QLA2200(ha)) { |
1181 | /* Disable SRAM, Instruction RAM and GP RAM parity. */ | 1460 | /* Disable SRAM, Instruction RAM and GP RAM parity. */ |
1182 | spin_lock_irqsave(&ha->hardware_lock, flags); | 1461 | spin_lock_irqsave(&ha->hardware_lock, flags); |
@@ -1202,6 +1481,7 @@ qla2x00_setup_chip(scsi_qla_host_t *vha) | |||
1202 | rval = qla2x00_execute_fw(vha, srisc_address); | 1481 | rval = qla2x00_execute_fw(vha, srisc_address); |
1203 | /* Retrieve firmware information. */ | 1482 | /* Retrieve firmware information. */ |
1204 | if (rval == QLA_SUCCESS) { | 1483 | if (rval == QLA_SUCCESS) { |
1484 | enable_82xx_npiv: | ||
1205 | fw_major_version = ha->fw_major_version; | 1485 | fw_major_version = ha->fw_major_version; |
1206 | rval = qla2x00_get_fw_version(vha, | 1486 | rval = qla2x00_get_fw_version(vha, |
1207 | &ha->fw_major_version, | 1487 | &ha->fw_major_version, |
@@ -1226,8 +1506,10 @@ qla2x00_setup_chip(scsi_qla_host_t *vha) | |||
1226 | &ha->fw_xcb_count, NULL, NULL, | 1506 | &ha->fw_xcb_count, NULL, NULL, |
1227 | &ha->max_npiv_vports, NULL); | 1507 | &ha->max_npiv_vports, NULL); |
1228 | 1508 | ||
1229 | if (!fw_major_version && ql2xallocfwdump) | 1509 | if (!fw_major_version && ql2xallocfwdump) { |
1230 | qla2x00_alloc_fw_dump(vha); | 1510 | if (!IS_QLA82XX(ha)) |
1511 | qla2x00_alloc_fw_dump(vha); | ||
1512 | } | ||
1231 | } | 1513 | } |
1232 | } else { | 1514 | } else { |
1233 | DEBUG2(printk(KERN_INFO | 1515 | DEBUG2(printk(KERN_INFO |
@@ -1384,6 +1666,9 @@ qla24xx_update_fw_options(scsi_qla_host_t *vha) | |||
1384 | int rval; | 1666 | int rval; |
1385 | struct qla_hw_data *ha = vha->hw; | 1667 | struct qla_hw_data *ha = vha->hw; |
1386 | 1668 | ||
1669 | if (IS_QLA82XX(ha)) | ||
1670 | return; | ||
1671 | |||
1387 | /* Update Serial Link options. */ | 1672 | /* Update Serial Link options. */ |
1388 | if ((le16_to_cpu(ha->fw_seriallink_options24[0]) & BIT_0) == 0) | 1673 | if ((le16_to_cpu(ha->fw_seriallink_options24[0]) & BIT_0) == 0) |
1389 | return; | 1674 | return; |
@@ -1818,7 +2103,7 @@ qla2x00_configure_hba(scsi_qla_host_t *vha) | |||
1818 | return(rval); | 2103 | return(rval); |
1819 | } | 2104 | } |
1820 | 2105 | ||
1821 | static inline void | 2106 | inline void |
1822 | qla2x00_set_model_info(scsi_qla_host_t *vha, uint8_t *model, size_t len, | 2107 | qla2x00_set_model_info(scsi_qla_host_t *vha, uint8_t *model, size_t len, |
1823 | char *def) | 2108 | char *def) |
1824 | { | 2109 | { |
@@ -1826,7 +2111,7 @@ qla2x00_set_model_info(scsi_qla_host_t *vha, uint8_t *model, size_t len, | |||
1826 | uint16_t index; | 2111 | uint16_t index; |
1827 | struct qla_hw_data *ha = vha->hw; | 2112 | struct qla_hw_data *ha = vha->hw; |
1828 | int use_tbl = !IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha) && | 2113 | int use_tbl = !IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha) && |
1829 | !IS_QLA81XX(ha); | 2114 | !IS_QLA8XXX_TYPE(ha); |
1830 | 2115 | ||
1831 | if (memcmp(model, BINZERO, len) != 0) { | 2116 | if (memcmp(model, BINZERO, len) != 0) { |
1832 | strncpy(ha->model_number, model, len); | 2117 | strncpy(ha->model_number, model, len); |
@@ -2017,6 +2302,7 @@ qla2x00_nvram_config(scsi_qla_host_t *vha) | |||
2017 | if (IS_QLA23XX(ha)) { | 2302 | if (IS_QLA23XX(ha)) { |
2018 | nv->firmware_options[0] |= BIT_2; | 2303 | nv->firmware_options[0] |= BIT_2; |
2019 | nv->firmware_options[0] &= ~BIT_3; | 2304 | nv->firmware_options[0] &= ~BIT_3; |
2305 | nv->firmware_options[0] &= ~BIT_6; | ||
2020 | nv->add_firmware_options[1] |= BIT_5 | BIT_4; | 2306 | nv->add_firmware_options[1] |= BIT_5 | BIT_4; |
2021 | 2307 | ||
2022 | if (IS_QLA2300(ha)) { | 2308 | if (IS_QLA2300(ha)) { |
@@ -2635,7 +2921,7 @@ qla2x00_update_fcport(scsi_qla_host_t *vha, fc_port_t *fcport) | |||
2635 | PORT_RETRY_TIME; | 2921 | PORT_RETRY_TIME; |
2636 | atomic_set(&fcport->port_down_timer, ha->port_down_retry_count * | 2922 | atomic_set(&fcport->port_down_timer, ha->port_down_retry_count * |
2637 | PORT_RETRY_TIME); | 2923 | PORT_RETRY_TIME); |
2638 | fcport->flags &= ~FCF_LOGIN_NEEDED; | 2924 | fcport->flags &= ~(FCF_LOGIN_NEEDED | FCF_ASYNC_SENT); |
2639 | 2925 | ||
2640 | qla2x00_iidma_fcport(vha, fcport); | 2926 | qla2x00_iidma_fcport(vha, fcport); |
2641 | 2927 | ||
@@ -2864,7 +3150,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha, | |||
2864 | sw_info_t *swl; | 3150 | sw_info_t *swl; |
2865 | int swl_idx; | 3151 | int swl_idx; |
2866 | int first_dev, last_dev; | 3152 | int first_dev, last_dev; |
2867 | port_id_t wrap, nxt_d_id; | 3153 | port_id_t wrap = {}, nxt_d_id; |
2868 | struct qla_hw_data *ha = vha->hw; | 3154 | struct qla_hw_data *ha = vha->hw; |
2869 | struct scsi_qla_host *vp, *base_vha = pci_get_drvdata(ha->pdev); | 3155 | struct scsi_qla_host *vp, *base_vha = pci_get_drvdata(ha->pdev); |
2870 | struct scsi_qla_host *tvp; | 3156 | struct scsi_qla_host *tvp; |
@@ -3167,7 +3453,7 @@ qla2x00_device_resync(scsi_qla_host_t *vha) | |||
3167 | uint32_t rscn_entry; | 3453 | uint32_t rscn_entry; |
3168 | uint8_t rscn_out_iter; | 3454 | uint8_t rscn_out_iter; |
3169 | uint8_t format; | 3455 | uint8_t format; |
3170 | port_id_t d_id; | 3456 | port_id_t d_id = {}; |
3171 | 3457 | ||
3172 | rval = QLA_RSCNS_HANDLED; | 3458 | rval = QLA_RSCNS_HANDLED; |
3173 | 3459 | ||
@@ -3281,11 +3567,15 @@ qla2x00_fabric_dev_login(scsi_qla_host_t *vha, fc_port_t *fcport, | |||
3281 | retry = 0; | 3567 | retry = 0; |
3282 | 3568 | ||
3283 | if (IS_ALOGIO_CAPABLE(ha)) { | 3569 | if (IS_ALOGIO_CAPABLE(ha)) { |
3570 | if (fcport->flags & FCF_ASYNC_SENT) | ||
3571 | return rval; | ||
3572 | fcport->flags |= FCF_ASYNC_SENT; | ||
3284 | rval = qla2x00_post_async_login_work(vha, fcport, NULL); | 3573 | rval = qla2x00_post_async_login_work(vha, fcport, NULL); |
3285 | if (!rval) | 3574 | if (!rval) |
3286 | return rval; | 3575 | return rval; |
3287 | } | 3576 | } |
3288 | 3577 | ||
3578 | fcport->flags &= ~FCF_ASYNC_SENT; | ||
3289 | rval = qla2x00_fabric_login(vha, fcport, next_loopid); | 3579 | rval = qla2x00_fabric_login(vha, fcport, next_loopid); |
3290 | if (rval == QLA_SUCCESS) { | 3580 | if (rval == QLA_SUCCESS) { |
3291 | /* Send an ADISC to FCP2 devices.*/ | 3581 | /* Send an ADISC to FCP2 devices.*/ |
@@ -3546,6 +3836,45 @@ qla2x00_update_fcports(scsi_qla_host_t *base_vha) | |||
3546 | qla2x00_rport_del(fcport); | 3836 | qla2x00_rport_del(fcport); |
3547 | } | 3837 | } |
3548 | 3838 | ||
3839 | void | ||
3840 | qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha) | ||
3841 | { | ||
3842 | struct qla_hw_data *ha = vha->hw; | ||
3843 | struct scsi_qla_host *vp, *base_vha = pci_get_drvdata(ha->pdev); | ||
3844 | struct scsi_qla_host *tvp; | ||
3845 | |||
3846 | vha->flags.online = 0; | ||
3847 | ha->flags.chip_reset_done = 0; | ||
3848 | clear_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); | ||
3849 | ha->qla_stats.total_isp_aborts++; | ||
3850 | |||
3851 | qla_printk(KERN_INFO, ha, | ||
3852 | "Performing ISP error recovery - ha= %p.\n", ha); | ||
3853 | |||
3854 | /* Chip reset does not apply to 82XX */ | ||
3855 | if (!IS_QLA82XX(ha)) | ||
3856 | ha->isp_ops->reset_chip(vha); | ||
3857 | |||
3858 | atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME); | ||
3859 | if (atomic_read(&vha->loop_state) != LOOP_DOWN) { | ||
3860 | atomic_set(&vha->loop_state, LOOP_DOWN); | ||
3861 | qla2x00_mark_all_devices_lost(vha, 0); | ||
3862 | list_for_each_entry_safe(vp, tvp, &base_vha->hw->vp_list, list) | ||
3863 | qla2x00_mark_all_devices_lost(vp, 0); | ||
3864 | } else { | ||
3865 | if (!atomic_read(&vha->loop_down_timer)) | ||
3866 | atomic_set(&vha->loop_down_timer, | ||
3867 | LOOP_DOWN_TIME); | ||
3868 | } | ||
3869 | |||
3870 | /* Make sure for ISP 82XX IO DMA is complete */ | ||
3871 | if (IS_QLA82XX(ha)) | ||
3872 | qla82xx_wait_for_pending_commands(vha); | ||
3873 | |||
3874 | /* Requeue all commands in outstanding command list. */ | ||
3875 | qla2x00_abort_all_cmds(vha, DID_RESET << 16); | ||
3876 | } | ||
3877 | |||
3549 | /* | 3878 | /* |
3550 | * qla2x00_abort_isp | 3879 | * qla2x00_abort_isp |
3551 | * Resets ISP and aborts all outstanding commands. | 3880 | * Resets ISP and aborts all outstanding commands. |
@@ -3567,27 +3896,7 @@ qla2x00_abort_isp(scsi_qla_host_t *vha) | |||
3567 | struct req_que *req = ha->req_q_map[0]; | 3896 | struct req_que *req = ha->req_q_map[0]; |
3568 | 3897 | ||
3569 | if (vha->flags.online) { | 3898 | if (vha->flags.online) { |
3570 | vha->flags.online = 0; | 3899 | qla2x00_abort_isp_cleanup(vha); |
3571 | ha->flags.chip_reset_done = 0; | ||
3572 | clear_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); | ||
3573 | ha->qla_stats.total_isp_aborts++; | ||
3574 | |||
3575 | qla_printk(KERN_INFO, ha, | ||
3576 | "Performing ISP error recovery - ha= %p.\n", ha); | ||
3577 | ha->isp_ops->reset_chip(vha); | ||
3578 | |||
3579 | atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME); | ||
3580 | if (atomic_read(&vha->loop_state) != LOOP_DOWN) { | ||
3581 | atomic_set(&vha->loop_state, LOOP_DOWN); | ||
3582 | qla2x00_mark_all_devices_lost(vha, 0); | ||
3583 | } else { | ||
3584 | if (!atomic_read(&vha->loop_down_timer)) | ||
3585 | atomic_set(&vha->loop_down_timer, | ||
3586 | LOOP_DOWN_TIME); | ||
3587 | } | ||
3588 | |||
3589 | /* Requeue all commands in outstanding command list. */ | ||
3590 | qla2x00_abort_all_cmds(vha, DID_RESET << 16); | ||
3591 | 3900 | ||
3592 | if (unlikely(pci_channel_offline(ha->pdev) && | 3901 | if (unlikely(pci_channel_offline(ha->pdev) && |
3593 | ha->flags.pci_channel_io_perm_failure)) { | 3902 | ha->flags.pci_channel_io_perm_failure)) { |
@@ -3843,6 +4152,9 @@ qla24xx_reset_adapter(scsi_qla_host_t *vha) | |||
3843 | struct qla_hw_data *ha = vha->hw; | 4152 | struct qla_hw_data *ha = vha->hw; |
3844 | struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; | 4153 | struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; |
3845 | 4154 | ||
4155 | if (IS_QLA82XX(ha)) | ||
4156 | return; | ||
4157 | |||
3846 | vha->flags.online = 0; | 4158 | vha->flags.online = 0; |
3847 | ha->isp_ops->disable_intrs(ha); | 4159 | ha->isp_ops->disable_intrs(ha); |
3848 | 4160 | ||
@@ -3906,6 +4218,8 @@ qla24xx_nvram_config(scsi_qla_host_t *vha) | |||
3906 | } | 4218 | } |
3907 | ha->nvram_size = sizeof(struct nvram_24xx); | 4219 | ha->nvram_size = sizeof(struct nvram_24xx); |
3908 | ha->vpd_size = FA_NVRAM_VPD_SIZE; | 4220 | ha->vpd_size = FA_NVRAM_VPD_SIZE; |
4221 | if (IS_QLA82XX(ha)) | ||
4222 | ha->vpd_size = FA_VPD_SIZE_82XX; | ||
3909 | 4223 | ||
3910 | /* Get VPD data into cache */ | 4224 | /* Get VPD data into cache */ |
3911 | ha->vpd = ha->nvram + VPD_OFFSET; | 4225 | ha->vpd = ha->nvram + VPD_OFFSET; |
@@ -4769,7 +5083,7 @@ qla81xx_nvram_config(scsi_qla_host_t *vha) | |||
4769 | * Setup driver NVRAM options. | 5083 | * Setup driver NVRAM options. |
4770 | */ | 5084 | */ |
4771 | qla2x00_set_model_info(vha, nv->model_name, sizeof(nv->model_name), | 5085 | qla2x00_set_model_info(vha, nv->model_name, sizeof(nv->model_name), |
4772 | "QLE81XX"); | 5086 | "QLE8XXX"); |
4773 | 5087 | ||
4774 | /* Use alternate WWN? */ | 5088 | /* Use alternate WWN? */ |
4775 | if (nv->host_p & __constant_cpu_to_le32(BIT_15)) { | 5089 | if (nv->host_p & __constant_cpu_to_le32(BIT_15)) { |
@@ -4892,6 +5206,114 @@ qla81xx_nvram_config(scsi_qla_host_t *vha) | |||
4892 | return (rval); | 5206 | return (rval); |
4893 | } | 5207 | } |
4894 | 5208 | ||
5209 | int | ||
5210 | qla82xx_restart_isp(scsi_qla_host_t *vha) | ||
5211 | { | ||
5212 | int status, rval; | ||
5213 | uint32_t wait_time; | ||
5214 | struct qla_hw_data *ha = vha->hw; | ||
5215 | struct req_que *req = ha->req_q_map[0]; | ||
5216 | struct rsp_que *rsp = ha->rsp_q_map[0]; | ||
5217 | struct scsi_qla_host *vp; | ||
5218 | struct scsi_qla_host *tvp; | ||
5219 | |||
5220 | status = qla2x00_init_rings(vha); | ||
5221 | if (!status) { | ||
5222 | clear_bit(RESET_MARKER_NEEDED, &vha->dpc_flags); | ||
5223 | ha->flags.chip_reset_done = 1; | ||
5224 | |||
5225 | status = qla2x00_fw_ready(vha); | ||
5226 | if (!status) { | ||
5227 | qla_printk(KERN_INFO, ha, | ||
5228 | "%s(): Start configure loop, " | ||
5229 | "status = %d\n", __func__, status); | ||
5230 | |||
5231 | /* Issue a marker after FW becomes ready. */ | ||
5232 | qla2x00_marker(vha, req, rsp, 0, 0, MK_SYNC_ALL); | ||
5233 | |||
5234 | vha->flags.online = 1; | ||
5235 | /* Wait at most MAX_TARGET RSCNs for a stable link. */ | ||
5236 | wait_time = 256; | ||
5237 | do { | ||
5238 | clear_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); | ||
5239 | qla2x00_configure_loop(vha); | ||
5240 | wait_time--; | ||
5241 | } while (!atomic_read(&vha->loop_down_timer) && | ||
5242 | !(test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags)) && | ||
5243 | wait_time && | ||
5244 | (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))); | ||
5245 | } | ||
5246 | |||
5247 | /* if no cable then assume it's good */ | ||
5248 | if ((vha->device_flags & DFLG_NO_CABLE)) | ||
5249 | status = 0; | ||
5250 | |||
5251 | qla_printk(KERN_INFO, ha, | ||
5252 | "%s(): Configure loop done, status = 0x%x\n", | ||
5253 | __func__, status); | ||
5254 | } | ||
5255 | |||
5256 | if (!status) { | ||
5257 | clear_bit(RESET_MARKER_NEEDED, &vha->dpc_flags); | ||
5258 | |||
5259 | if (!atomic_read(&vha->loop_down_timer)) { | ||
5260 | /* | ||
5261 | * Issue marker command only when we are going | ||
5262 | * to start the I/O . | ||
5263 | */ | ||
5264 | vha->marker_needed = 1; | ||
5265 | } | ||
5266 | |||
5267 | vha->flags.online = 1; | ||
5268 | |||
5269 | ha->isp_ops->enable_intrs(ha); | ||
5270 | |||
5271 | ha->isp_abort_cnt = 0; | ||
5272 | clear_bit(ISP_ABORT_RETRY, &vha->dpc_flags); | ||
5273 | |||
5274 | if (ha->fce) { | ||
5275 | ha->flags.fce_enabled = 1; | ||
5276 | memset(ha->fce, 0, | ||
5277 | fce_calc_size(ha->fce_bufs)); | ||
5278 | rval = qla2x00_enable_fce_trace(vha, | ||
5279 | ha->fce_dma, ha->fce_bufs, ha->fce_mb, | ||
5280 | &ha->fce_bufs); | ||
5281 | if (rval) { | ||
5282 | qla_printk(KERN_WARNING, ha, | ||
5283 | "Unable to reinitialize FCE " | ||
5284 | "(%d).\n", rval); | ||
5285 | ha->flags.fce_enabled = 0; | ||
5286 | } | ||
5287 | } | ||
5288 | |||
5289 | if (ha->eft) { | ||
5290 | memset(ha->eft, 0, EFT_SIZE); | ||
5291 | rval = qla2x00_enable_eft_trace(vha, | ||
5292 | ha->eft_dma, EFT_NUM_BUFFERS); | ||
5293 | if (rval) { | ||
5294 | qla_printk(KERN_WARNING, ha, | ||
5295 | "Unable to reinitialize EFT " | ||
5296 | "(%d).\n", rval); | ||
5297 | } | ||
5298 | } | ||
5299 | } | ||
5300 | |||
5301 | if (!status) { | ||
5302 | DEBUG(printk(KERN_INFO | ||
5303 | "qla82xx_restart_isp(%ld): succeeded.\n", | ||
5304 | vha->host_no)); | ||
5305 | list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) { | ||
5306 | if (vp->vp_idx) | ||
5307 | qla2x00_vp_abort_isp(vp); | ||
5308 | } | ||
5309 | } else { | ||
5310 | qla_printk(KERN_INFO, ha, | ||
5311 | "qla82xx_restart_isp: **** FAILED ****\n"); | ||
5312 | } | ||
5313 | |||
5314 | return status; | ||
5315 | } | ||
5316 | |||
4895 | void | 5317 | void |
4896 | qla81xx_update_fw_options(scsi_qla_host_t *vha) | 5318 | qla81xx_update_fw_options(scsi_qla_host_t *vha) |
4897 | { | 5319 | { |
@@ -4905,3 +5327,165 @@ qla81xx_update_fw_options(scsi_qla_host_t *vha) | |||
4905 | ha->fw_options[2] |= BIT_9; | 5327 | ha->fw_options[2] |= BIT_9; |
4906 | qla2x00_set_fw_options(vha, ha->fw_options); | 5328 | qla2x00_set_fw_options(vha, ha->fw_options); |
4907 | } | 5329 | } |
5330 | |||
5331 | /* | ||
5332 | * qla24xx_get_fcp_prio | ||
5333 | * Gets the fcp cmd priority value for the logged in port. | ||
5334 | * Looks for a match of the port descriptors within | ||
5335 | * each of the fcp prio config entries. If a match is found, | ||
5336 | * the tag (priority) value is returned. | ||
5337 | * | ||
5338 | * Input: | ||
5339 | * ha = adapter block po | ||
5340 | * fcport = port structure pointer. | ||
5341 | * | ||
5342 | * Return: | ||
5343 | * non-zero (if found) | ||
5344 | * 0 (if not found) | ||
5345 | * | ||
5346 | * Context: | ||
5347 | * Kernel context | ||
5348 | */ | ||
5349 | uint8_t | ||
5350 | qla24xx_get_fcp_prio(scsi_qla_host_t *vha, fc_port_t *fcport) | ||
5351 | { | ||
5352 | int i, entries; | ||
5353 | uint8_t pid_match, wwn_match; | ||
5354 | uint8_t priority; | ||
5355 | uint32_t pid1, pid2; | ||
5356 | uint64_t wwn1, wwn2; | ||
5357 | struct qla_fcp_prio_entry *pri_entry; | ||
5358 | struct qla_hw_data *ha = vha->hw; | ||
5359 | |||
5360 | if (!ha->fcp_prio_cfg || !ha->flags.fcp_prio_enabled) | ||
5361 | return 0; | ||
5362 | |||
5363 | priority = 0; | ||
5364 | entries = ha->fcp_prio_cfg->num_entries; | ||
5365 | pri_entry = &ha->fcp_prio_cfg->entry[0]; | ||
5366 | |||
5367 | for (i = 0; i < entries; i++) { | ||
5368 | pid_match = wwn_match = 0; | ||
5369 | |||
5370 | if (!(pri_entry->flags & FCP_PRIO_ENTRY_VALID)) { | ||
5371 | pri_entry++; | ||
5372 | continue; | ||
5373 | } | ||
5374 | |||
5375 | /* check source pid for a match */ | ||
5376 | if (pri_entry->flags & FCP_PRIO_ENTRY_SPID_VALID) { | ||
5377 | pid1 = pri_entry->src_pid & INVALID_PORT_ID; | ||
5378 | pid2 = vha->d_id.b24 & INVALID_PORT_ID; | ||
5379 | if (pid1 == INVALID_PORT_ID) | ||
5380 | pid_match++; | ||
5381 | else if (pid1 == pid2) | ||
5382 | pid_match++; | ||
5383 | } | ||
5384 | |||
5385 | /* check destination pid for a match */ | ||
5386 | if (pri_entry->flags & FCP_PRIO_ENTRY_DPID_VALID) { | ||
5387 | pid1 = pri_entry->dst_pid & INVALID_PORT_ID; | ||
5388 | pid2 = fcport->d_id.b24 & INVALID_PORT_ID; | ||
5389 | if (pid1 == INVALID_PORT_ID) | ||
5390 | pid_match++; | ||
5391 | else if (pid1 == pid2) | ||
5392 | pid_match++; | ||
5393 | } | ||
5394 | |||
5395 | /* check source WWN for a match */ | ||
5396 | if (pri_entry->flags & FCP_PRIO_ENTRY_SWWN_VALID) { | ||
5397 | wwn1 = wwn_to_u64(vha->port_name); | ||
5398 | wwn2 = wwn_to_u64(pri_entry->src_wwpn); | ||
5399 | if (wwn2 == (uint64_t)-1) | ||
5400 | wwn_match++; | ||
5401 | else if (wwn1 == wwn2) | ||
5402 | wwn_match++; | ||
5403 | } | ||
5404 | |||
5405 | /* check destination WWN for a match */ | ||
5406 | if (pri_entry->flags & FCP_PRIO_ENTRY_DWWN_VALID) { | ||
5407 | wwn1 = wwn_to_u64(fcport->port_name); | ||
5408 | wwn2 = wwn_to_u64(pri_entry->dst_wwpn); | ||
5409 | if (wwn2 == (uint64_t)-1) | ||
5410 | wwn_match++; | ||
5411 | else if (wwn1 == wwn2) | ||
5412 | wwn_match++; | ||
5413 | } | ||
5414 | |||
5415 | if (pid_match == 2 || wwn_match == 2) { | ||
5416 | /* Found a matching entry */ | ||
5417 | if (pri_entry->flags & FCP_PRIO_ENTRY_TAG_VALID) | ||
5418 | priority = pri_entry->tag; | ||
5419 | break; | ||
5420 | } | ||
5421 | |||
5422 | pri_entry++; | ||
5423 | } | ||
5424 | |||
5425 | return priority; | ||
5426 | } | ||
5427 | |||
5428 | /* | ||
5429 | * qla24xx_update_fcport_fcp_prio | ||
5430 | * Activates fcp priority for the logged in fc port | ||
5431 | * | ||
5432 | * Input: | ||
5433 | * ha = adapter block pointer. | ||
5434 | * fcp = port structure pointer. | ||
5435 | * | ||
5436 | * Return: | ||
5437 | * QLA_SUCCESS or QLA_FUNCTION_FAILED | ||
5438 | * | ||
5439 | * Context: | ||
5440 | * Kernel context. | ||
5441 | */ | ||
5442 | int | ||
5443 | qla24xx_update_fcport_fcp_prio(scsi_qla_host_t *ha, fc_port_t *fcport) | ||
5444 | { | ||
5445 | int ret; | ||
5446 | uint8_t priority; | ||
5447 | uint16_t mb[5]; | ||
5448 | |||
5449 | if (atomic_read(&fcport->state) == FCS_UNCONFIGURED || | ||
5450 | fcport->port_type != FCT_TARGET || | ||
5451 | fcport->loop_id == FC_NO_LOOP_ID) | ||
5452 | return QLA_FUNCTION_FAILED; | ||
5453 | |||
5454 | priority = qla24xx_get_fcp_prio(ha, fcport); | ||
5455 | ret = qla24xx_set_fcp_prio(ha, fcport->loop_id, priority, mb); | ||
5456 | if (ret == QLA_SUCCESS) | ||
5457 | fcport->fcp_prio = priority; | ||
5458 | else | ||
5459 | DEBUG2(printk(KERN_WARNING | ||
5460 | "scsi(%ld): Unable to activate fcp priority, " | ||
5461 | " ret=0x%x\n", ha->host_no, ret)); | ||
5462 | |||
5463 | return ret; | ||
5464 | } | ||
5465 | |||
5466 | /* | ||
5467 | * qla24xx_update_all_fcp_prio | ||
5468 | * Activates fcp priority for all the logged in ports | ||
5469 | * | ||
5470 | * Input: | ||
5471 | * ha = adapter block pointer. | ||
5472 | * | ||
5473 | * Return: | ||
5474 | * QLA_SUCCESS or QLA_FUNCTION_FAILED | ||
5475 | * | ||
5476 | * Context: | ||
5477 | * Kernel context. | ||
5478 | */ | ||
5479 | int | ||
5480 | qla24xx_update_all_fcp_prio(scsi_qla_host_t *vha) | ||
5481 | { | ||
5482 | int ret; | ||
5483 | fc_port_t *fcport; | ||
5484 | |||
5485 | ret = QLA_FUNCTION_FAILED; | ||
5486 | /* We need to set priority for all logged in ports */ | ||
5487 | list_for_each_entry(fcport, &vha->vp_fcports, list) | ||
5488 | ret = qla24xx_update_fcport_fcp_prio(vha, fcport); | ||
5489 | |||
5490 | return ret; | ||
5491 | } | ||
diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h index 5e0a7095c9f2..84c2fea154d2 100644 --- a/drivers/scsi/qla2xxx/qla_inline.h +++ b/drivers/scsi/qla2xxx/qla_inline.h | |||
@@ -37,7 +37,10 @@ qla2x00_poll(struct rsp_que *rsp) | |||
37 | unsigned long flags; | 37 | unsigned long flags; |
38 | struct qla_hw_data *ha = rsp->hw; | 38 | struct qla_hw_data *ha = rsp->hw; |
39 | local_irq_save(flags); | 39 | local_irq_save(flags); |
40 | ha->isp_ops->intr_handler(0, rsp); | 40 | if (IS_QLA82XX(ha)) |
41 | qla82xx_poll(0, rsp); | ||
42 | else | ||
43 | ha->isp_ops->intr_handler(0, rsp); | ||
41 | local_irq_restore(flags); | 44 | local_irq_restore(flags); |
42 | } | 45 | } |
43 | 46 | ||
@@ -64,3 +67,19 @@ qla2x00_is_reserved_id(scsi_qla_host_t *vha, uint16_t loop_id) | |||
64 | return ((loop_id > ha->max_loop_id && loop_id < SNS_FIRST_LOOP_ID) || | 67 | return ((loop_id > ha->max_loop_id && loop_id < SNS_FIRST_LOOP_ID) || |
65 | loop_id == MANAGEMENT_SERVER || loop_id == BROADCAST); | 68 | loop_id == MANAGEMENT_SERVER || loop_id == BROADCAST); |
66 | } | 69 | } |
70 | |||
71 | static inline void | ||
72 | qla2x00_clean_dsd_pool(struct qla_hw_data *ha, srb_t *sp) | ||
73 | { | ||
74 | struct dsd_dma *dsd_ptr, *tdsd_ptr; | ||
75 | |||
76 | /* clean up allocated prev pool */ | ||
77 | list_for_each_entry_safe(dsd_ptr, tdsd_ptr, | ||
78 | &((struct crc_context *)sp->ctx)->dsd_list, list) { | ||
79 | dma_pool_free(ha->dl_dma_pool, dsd_ptr->dsd_addr, | ||
80 | dsd_ptr->dsd_list_dma); | ||
81 | list_del(&dsd_ptr->list); | ||
82 | kfree(dsd_ptr); | ||
83 | } | ||
84 | INIT_LIST_HEAD(&((struct crc_context *)sp->ctx)->dsd_list); | ||
85 | } | ||
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index 8299a9891bfe..8ef945365412 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c | |||
@@ -145,7 +145,49 @@ qla2x00_prep_cont_type1_iocb(scsi_qla_host_t *vha) | |||
145 | return (cont_pkt); | 145 | return (cont_pkt); |
146 | } | 146 | } |
147 | 147 | ||
148 | /** | 148 | static inline int |
149 | qla24xx_configure_prot_mode(srb_t *sp, uint16_t *fw_prot_opts) | ||
150 | { | ||
151 | uint8_t guard = scsi_host_get_guard(sp->cmd->device->host); | ||
152 | |||
153 | /* We only support T10 DIF right now */ | ||
154 | if (guard != SHOST_DIX_GUARD_CRC) { | ||
155 | DEBUG2(printk(KERN_ERR "Unsupported guard: %d\n", guard)); | ||
156 | return 0; | ||
157 | } | ||
158 | |||
159 | /* We always use DIFF Bundling for best performance */ | ||
160 | *fw_prot_opts = 0; | ||
161 | |||
162 | /* Translate SCSI opcode to a protection opcode */ | ||
163 | switch (scsi_get_prot_op(sp->cmd)) { | ||
164 | case SCSI_PROT_READ_STRIP: | ||
165 | *fw_prot_opts |= PO_MODE_DIF_REMOVE; | ||
166 | break; | ||
167 | case SCSI_PROT_WRITE_INSERT: | ||
168 | *fw_prot_opts |= PO_MODE_DIF_INSERT; | ||
169 | break; | ||
170 | case SCSI_PROT_READ_INSERT: | ||
171 | *fw_prot_opts |= PO_MODE_DIF_INSERT; | ||
172 | break; | ||
173 | case SCSI_PROT_WRITE_STRIP: | ||
174 | *fw_prot_opts |= PO_MODE_DIF_REMOVE; | ||
175 | break; | ||
176 | case SCSI_PROT_READ_PASS: | ||
177 | *fw_prot_opts |= PO_MODE_DIF_PASS; | ||
178 | break; | ||
179 | case SCSI_PROT_WRITE_PASS: | ||
180 | *fw_prot_opts |= PO_MODE_DIF_PASS; | ||
181 | break; | ||
182 | default: /* Normal Request */ | ||
183 | *fw_prot_opts |= PO_MODE_DIF_PASS; | ||
184 | break; | ||
185 | } | ||
186 | |||
187 | return scsi_prot_sg_count(sp->cmd); | ||
188 | } | ||
189 | |||
190 | /* | ||
149 | * qla2x00_build_scsi_iocbs_32() - Build IOCB command utilizing 32bit | 191 | * qla2x00_build_scsi_iocbs_32() - Build IOCB command utilizing 32bit |
150 | * capable IOCB types. | 192 | * capable IOCB types. |
151 | * | 193 | * |
@@ -506,7 +548,10 @@ qla2x00_req_pkt(struct scsi_qla_host *vha, struct req_que *req, | |||
506 | cnt = (uint16_t) | 548 | cnt = (uint16_t) |
507 | RD_REG_DWORD(®->isp25mq.req_q_out); | 549 | RD_REG_DWORD(®->isp25mq.req_q_out); |
508 | else { | 550 | else { |
509 | if (IS_FWI2_CAPABLE(ha)) | 551 | if (IS_QLA82XX(ha)) |
552 | cnt = (uint16_t)RD_REG_DWORD( | ||
553 | ®->isp82.req_q_out); | ||
554 | else if (IS_FWI2_CAPABLE(ha)) | ||
510 | cnt = (uint16_t)RD_REG_DWORD( | 555 | cnt = (uint16_t)RD_REG_DWORD( |
511 | ®->isp24.req_q_out); | 556 | ®->isp24.req_q_out); |
512 | else | 557 | else |
@@ -579,11 +624,29 @@ qla2x00_isp_cmd(struct scsi_qla_host *vha, struct req_que *req) | |||
579 | req->ring_ptr++; | 624 | req->ring_ptr++; |
580 | 625 | ||
581 | /* Set chip new ring index. */ | 626 | /* Set chip new ring index. */ |
582 | if (ha->mqenable) { | 627 | if (IS_QLA82XX(ha)) { |
628 | uint32_t dbval = 0x04 | (ha->portnum << 5); | ||
629 | |||
630 | /* write, read and verify logic */ | ||
631 | dbval = dbval | (req->id << 8) | (req->ring_index << 16); | ||
632 | if (ql2xdbwr) | ||
633 | qla82xx_wr_32(ha, ha->nxdb_wr_ptr, dbval); | ||
634 | else { | ||
635 | WRT_REG_DWORD( | ||
636 | (unsigned long __iomem *)ha->nxdb_wr_ptr, | ||
637 | dbval); | ||
638 | wmb(); | ||
639 | while (RD_REG_DWORD(ha->nxdb_rd_ptr) != dbval) { | ||
640 | WRT_REG_DWORD((unsigned long __iomem *) | ||
641 | ha->nxdb_wr_ptr, dbval); | ||
642 | wmb(); | ||
643 | } | ||
644 | } | ||
645 | } else if (ha->mqenable) { | ||
646 | /* Set chip new ring index. */ | ||
583 | WRT_REG_DWORD(®->isp25mq.req_q_in, req->ring_index); | 647 | WRT_REG_DWORD(®->isp25mq.req_q_in, req->ring_index); |
584 | RD_REG_DWORD(&ioreg->hccr); | 648 | RD_REG_DWORD(&ioreg->hccr); |
585 | } | 649 | } else { |
586 | else { | ||
587 | if (IS_FWI2_CAPABLE(ha)) { | 650 | if (IS_FWI2_CAPABLE(ha)) { |
588 | WRT_REG_DWORD(®->isp24.req_q_in, req->ring_index); | 651 | WRT_REG_DWORD(®->isp24.req_q_in, req->ring_index); |
589 | RD_REG_DWORD_RELAXED(®->isp24.req_q_in); | 652 | RD_REG_DWORD_RELAXED(®->isp24.req_q_in); |
@@ -604,7 +667,7 @@ qla2x00_isp_cmd(struct scsi_qla_host *vha, struct req_que *req) | |||
604 | * | 667 | * |
605 | * Returns the number of IOCB entries needed to store @dsds. | 668 | * Returns the number of IOCB entries needed to store @dsds. |
606 | */ | 669 | */ |
607 | static inline uint16_t | 670 | inline uint16_t |
608 | qla24xx_calc_iocbs(uint16_t dsds) | 671 | qla24xx_calc_iocbs(uint16_t dsds) |
609 | { | 672 | { |
610 | uint16_t iocbs; | 673 | uint16_t iocbs; |
@@ -615,6 +678,8 @@ qla24xx_calc_iocbs(uint16_t dsds) | |||
615 | if ((dsds - 1) % 5) | 678 | if ((dsds - 1) % 5) |
616 | iocbs++; | 679 | iocbs++; |
617 | } | 680 | } |
681 | DEBUG3(printk(KERN_DEBUG "%s(): Required PKT(s) = %d\n", | ||
682 | __func__, iocbs)); | ||
618 | return iocbs; | 683 | return iocbs; |
619 | } | 684 | } |
620 | 685 | ||
@@ -626,7 +691,7 @@ qla24xx_calc_iocbs(uint16_t dsds) | |||
626 | * @cmd_pkt: Command type 3 IOCB | 691 | * @cmd_pkt: Command type 3 IOCB |
627 | * @tot_dsds: Total number of segments to transfer | 692 | * @tot_dsds: Total number of segments to transfer |
628 | */ | 693 | */ |
629 | static inline void | 694 | inline void |
630 | qla24xx_build_scsi_iocbs(srb_t *sp, struct cmd_type_7 *cmd_pkt, | 695 | qla24xx_build_scsi_iocbs(srb_t *sp, struct cmd_type_7 *cmd_pkt, |
631 | uint16_t tot_dsds) | 696 | uint16_t tot_dsds) |
632 | { | 697 | { |
@@ -695,6 +760,453 @@ qla24xx_build_scsi_iocbs(srb_t *sp, struct cmd_type_7 *cmd_pkt, | |||
695 | } | 760 | } |
696 | } | 761 | } |
697 | 762 | ||
763 | struct fw_dif_context { | ||
764 | uint32_t ref_tag; | ||
765 | uint16_t app_tag; | ||
766 | uint8_t ref_tag_mask[4]; /* Validation/Replacement Mask*/ | ||
767 | uint8_t app_tag_mask[2]; /* Validation/Replacement Mask*/ | ||
768 | }; | ||
769 | |||
770 | /* | ||
771 | * qla24xx_set_t10dif_tags_from_cmd - Extract Ref and App tags from SCSI command | ||
772 | * | ||
773 | */ | ||
774 | static inline void | ||
775 | qla24xx_set_t10dif_tags(struct scsi_cmnd *cmd, struct fw_dif_context *pkt, | ||
776 | unsigned int protcnt) | ||
777 | { | ||
778 | struct sd_dif_tuple *spt; | ||
779 | unsigned char op = scsi_get_prot_op(cmd); | ||
780 | |||
781 | switch (scsi_get_prot_type(cmd)) { | ||
782 | /* For TYPE 0 protection: no checking */ | ||
783 | case SCSI_PROT_DIF_TYPE0: | ||
784 | pkt->ref_tag_mask[0] = 0x00; | ||
785 | pkt->ref_tag_mask[1] = 0x00; | ||
786 | pkt->ref_tag_mask[2] = 0x00; | ||
787 | pkt->ref_tag_mask[3] = 0x00; | ||
788 | break; | ||
789 | |||
790 | /* | ||
791 | * For TYPE 2 protection: 16 bit GUARD + 32 bit REF tag has to | ||
792 | * match LBA in CDB + N | ||
793 | */ | ||
794 | case SCSI_PROT_DIF_TYPE2: | ||
795 | break; | ||
796 | |||
797 | /* For Type 3 protection: 16 bit GUARD only */ | ||
798 | case SCSI_PROT_DIF_TYPE3: | ||
799 | pkt->ref_tag_mask[0] = pkt->ref_tag_mask[1] = | ||
800 | pkt->ref_tag_mask[2] = pkt->ref_tag_mask[3] = | ||
801 | 0x00; | ||
802 | break; | ||
803 | |||
804 | /* | ||
805 | * For TYpe 1 protection: 16 bit GUARD tag, 32 bit REF tag, and | ||
806 | * 16 bit app tag. | ||
807 | */ | ||
808 | case SCSI_PROT_DIF_TYPE1: | ||
809 | if (!ql2xenablehba_err_chk) | ||
810 | break; | ||
811 | |||
812 | if (protcnt && (op == SCSI_PROT_WRITE_STRIP || | ||
813 | op == SCSI_PROT_WRITE_PASS)) { | ||
814 | spt = page_address(sg_page(scsi_prot_sglist(cmd))) + | ||
815 | scsi_prot_sglist(cmd)[0].offset; | ||
816 | DEBUG18(printk(KERN_DEBUG | ||
817 | "%s(): LBA from user %p, lba = 0x%x\n", | ||
818 | __func__, spt, (int)spt->ref_tag)); | ||
819 | pkt->ref_tag = swab32(spt->ref_tag); | ||
820 | pkt->app_tag_mask[0] = 0x0; | ||
821 | pkt->app_tag_mask[1] = 0x0; | ||
822 | } else { | ||
823 | pkt->ref_tag = cpu_to_le32((uint32_t) | ||
824 | (0xffffffff & scsi_get_lba(cmd))); | ||
825 | pkt->app_tag = __constant_cpu_to_le16(0); | ||
826 | pkt->app_tag_mask[0] = 0x0; | ||
827 | pkt->app_tag_mask[1] = 0x0; | ||
828 | } | ||
829 | /* enable ALL bytes of the ref tag */ | ||
830 | pkt->ref_tag_mask[0] = 0xff; | ||
831 | pkt->ref_tag_mask[1] = 0xff; | ||
832 | pkt->ref_tag_mask[2] = 0xff; | ||
833 | pkt->ref_tag_mask[3] = 0xff; | ||
834 | break; | ||
835 | } | ||
836 | |||
837 | DEBUG18(printk(KERN_DEBUG | ||
838 | "%s(): Setting protection Tags: (BIG) ref tag = 0x%x," | ||
839 | " app tag = 0x%x, prot SG count %d , cmd lba 0x%x," | ||
840 | " prot_type=%u\n", __func__, pkt->ref_tag, pkt->app_tag, protcnt, | ||
841 | (int)scsi_get_lba(cmd), scsi_get_prot_type(cmd))); | ||
842 | } | ||
843 | |||
844 | |||
845 | static int | ||
846 | qla24xx_walk_and_build_sglist(struct qla_hw_data *ha, srb_t *sp, uint32_t *dsd, | ||
847 | uint16_t tot_dsds) | ||
848 | { | ||
849 | void *next_dsd; | ||
850 | uint8_t avail_dsds = 0; | ||
851 | uint32_t dsd_list_len; | ||
852 | struct dsd_dma *dsd_ptr; | ||
853 | struct scatterlist *sg; | ||
854 | uint32_t *cur_dsd = dsd; | ||
855 | int i; | ||
856 | uint16_t used_dsds = tot_dsds; | ||
857 | |||
858 | uint8_t *cp; | ||
859 | |||
860 | scsi_for_each_sg(sp->cmd, sg, tot_dsds, i) { | ||
861 | dma_addr_t sle_dma; | ||
862 | |||
863 | /* Allocate additional continuation packets? */ | ||
864 | if (avail_dsds == 0) { | ||
865 | avail_dsds = (used_dsds > QLA_DSDS_PER_IOCB) ? | ||
866 | QLA_DSDS_PER_IOCB : used_dsds; | ||
867 | dsd_list_len = (avail_dsds + 1) * 12; | ||
868 | used_dsds -= avail_dsds; | ||
869 | |||
870 | /* allocate tracking DS */ | ||
871 | dsd_ptr = kzalloc(sizeof(struct dsd_dma), GFP_ATOMIC); | ||
872 | if (!dsd_ptr) | ||
873 | return 1; | ||
874 | |||
875 | /* allocate new list */ | ||
876 | dsd_ptr->dsd_addr = next_dsd = | ||
877 | dma_pool_alloc(ha->dl_dma_pool, GFP_ATOMIC, | ||
878 | &dsd_ptr->dsd_list_dma); | ||
879 | |||
880 | if (!next_dsd) { | ||
881 | /* | ||
882 | * Need to cleanup only this dsd_ptr, rest | ||
883 | * will be done by sp_free_dma() | ||
884 | */ | ||
885 | kfree(dsd_ptr); | ||
886 | return 1; | ||
887 | } | ||
888 | |||
889 | list_add_tail(&dsd_ptr->list, | ||
890 | &((struct crc_context *)sp->ctx)->dsd_list); | ||
891 | |||
892 | sp->flags |= SRB_CRC_CTX_DSD_VALID; | ||
893 | |||
894 | /* add new list to cmd iocb or last list */ | ||
895 | *cur_dsd++ = cpu_to_le32(LSD(dsd_ptr->dsd_list_dma)); | ||
896 | *cur_dsd++ = cpu_to_le32(MSD(dsd_ptr->dsd_list_dma)); | ||
897 | *cur_dsd++ = dsd_list_len; | ||
898 | cur_dsd = (uint32_t *)next_dsd; | ||
899 | } | ||
900 | sle_dma = sg_dma_address(sg); | ||
901 | DEBUG18(printk("%s(): %p, sg entry %d - addr =0x%x 0x%x," | ||
902 | " len =%d\n", __func__ , cur_dsd, i, LSD(sle_dma), | ||
903 | MSD(sle_dma), sg_dma_len(sg))); | ||
904 | *cur_dsd++ = cpu_to_le32(LSD(sle_dma)); | ||
905 | *cur_dsd++ = cpu_to_le32(MSD(sle_dma)); | ||
906 | *cur_dsd++ = cpu_to_le32(sg_dma_len(sg)); | ||
907 | avail_dsds--; | ||
908 | |||
909 | if (scsi_get_prot_op(sp->cmd) == SCSI_PROT_WRITE_PASS) { | ||
910 | cp = page_address(sg_page(sg)) + sg->offset; | ||
911 | DEBUG18(printk("%s(): User Data buffer= %p:\n", | ||
912 | __func__ , cp)); | ||
913 | } | ||
914 | } | ||
915 | /* Null termination */ | ||
916 | *cur_dsd++ = 0; | ||
917 | *cur_dsd++ = 0; | ||
918 | *cur_dsd++ = 0; | ||
919 | return 0; | ||
920 | } | ||
921 | |||
922 | static int | ||
923 | qla24xx_walk_and_build_prot_sglist(struct qla_hw_data *ha, srb_t *sp, | ||
924 | uint32_t *dsd, | ||
925 | uint16_t tot_dsds) | ||
926 | { | ||
927 | void *next_dsd; | ||
928 | uint8_t avail_dsds = 0; | ||
929 | uint32_t dsd_list_len; | ||
930 | struct dsd_dma *dsd_ptr; | ||
931 | struct scatterlist *sg; | ||
932 | int i; | ||
933 | struct scsi_cmnd *cmd; | ||
934 | uint32_t *cur_dsd = dsd; | ||
935 | uint16_t used_dsds = tot_dsds; | ||
936 | |||
937 | uint8_t *cp; | ||
938 | |||
939 | |||
940 | cmd = sp->cmd; | ||
941 | scsi_for_each_prot_sg(cmd, sg, tot_dsds, i) { | ||
942 | dma_addr_t sle_dma; | ||
943 | |||
944 | /* Allocate additional continuation packets? */ | ||
945 | if (avail_dsds == 0) { | ||
946 | avail_dsds = (used_dsds > QLA_DSDS_PER_IOCB) ? | ||
947 | QLA_DSDS_PER_IOCB : used_dsds; | ||
948 | dsd_list_len = (avail_dsds + 1) * 12; | ||
949 | used_dsds -= avail_dsds; | ||
950 | |||
951 | /* allocate tracking DS */ | ||
952 | dsd_ptr = kzalloc(sizeof(struct dsd_dma), GFP_ATOMIC); | ||
953 | if (!dsd_ptr) | ||
954 | return 1; | ||
955 | |||
956 | /* allocate new list */ | ||
957 | dsd_ptr->dsd_addr = next_dsd = | ||
958 | dma_pool_alloc(ha->dl_dma_pool, GFP_ATOMIC, | ||
959 | &dsd_ptr->dsd_list_dma); | ||
960 | |||
961 | if (!next_dsd) { | ||
962 | /* | ||
963 | * Need to cleanup only this dsd_ptr, rest | ||
964 | * will be done by sp_free_dma() | ||
965 | */ | ||
966 | kfree(dsd_ptr); | ||
967 | return 1; | ||
968 | } | ||
969 | |||
970 | list_add_tail(&dsd_ptr->list, | ||
971 | &((struct crc_context *)sp->ctx)->dsd_list); | ||
972 | |||
973 | sp->flags |= SRB_CRC_CTX_DSD_VALID; | ||
974 | |||
975 | /* add new list to cmd iocb or last list */ | ||
976 | *cur_dsd++ = cpu_to_le32(LSD(dsd_ptr->dsd_list_dma)); | ||
977 | *cur_dsd++ = cpu_to_le32(MSD(dsd_ptr->dsd_list_dma)); | ||
978 | *cur_dsd++ = dsd_list_len; | ||
979 | cur_dsd = (uint32_t *)next_dsd; | ||
980 | } | ||
981 | sle_dma = sg_dma_address(sg); | ||
982 | if (scsi_get_prot_op(sp->cmd) == SCSI_PROT_WRITE_PASS) { | ||
983 | DEBUG18(printk(KERN_DEBUG | ||
984 | "%s(): %p, sg entry %d - addr =0x%x" | ||
985 | "0x%x, len =%d\n", __func__ , cur_dsd, i, | ||
986 | LSD(sle_dma), MSD(sle_dma), sg_dma_len(sg))); | ||
987 | } | ||
988 | *cur_dsd++ = cpu_to_le32(LSD(sle_dma)); | ||
989 | *cur_dsd++ = cpu_to_le32(MSD(sle_dma)); | ||
990 | *cur_dsd++ = cpu_to_le32(sg_dma_len(sg)); | ||
991 | |||
992 | if (scsi_get_prot_op(sp->cmd) == SCSI_PROT_WRITE_PASS) { | ||
993 | cp = page_address(sg_page(sg)) + sg->offset; | ||
994 | DEBUG18(printk("%s(): Protection Data buffer = %p:\n", | ||
995 | __func__ , cp)); | ||
996 | } | ||
997 | avail_dsds--; | ||
998 | } | ||
999 | /* Null termination */ | ||
1000 | *cur_dsd++ = 0; | ||
1001 | *cur_dsd++ = 0; | ||
1002 | *cur_dsd++ = 0; | ||
1003 | return 0; | ||
1004 | } | ||
1005 | |||
1006 | /** | ||
1007 | * qla24xx_build_scsi_crc_2_iocbs() - Build IOCB command utilizing Command | ||
1008 | * Type 6 IOCB types. | ||
1009 | * | ||
1010 | * @sp: SRB command to process | ||
1011 | * @cmd_pkt: Command type 3 IOCB | ||
1012 | * @tot_dsds: Total number of segments to transfer | ||
1013 | */ | ||
1014 | static inline int | ||
1015 | qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt, | ||
1016 | uint16_t tot_dsds, uint16_t tot_prot_dsds, uint16_t fw_prot_opts) | ||
1017 | { | ||
1018 | uint32_t *cur_dsd, *fcp_dl; | ||
1019 | scsi_qla_host_t *vha; | ||
1020 | struct scsi_cmnd *cmd; | ||
1021 | struct scatterlist *cur_seg; | ||
1022 | int sgc; | ||
1023 | uint32_t total_bytes; | ||
1024 | uint32_t data_bytes; | ||
1025 | uint32_t dif_bytes; | ||
1026 | uint8_t bundling = 1; | ||
1027 | uint16_t blk_size; | ||
1028 | uint8_t *clr_ptr; | ||
1029 | struct crc_context *crc_ctx_pkt = NULL; | ||
1030 | struct qla_hw_data *ha; | ||
1031 | uint8_t additional_fcpcdb_len; | ||
1032 | uint16_t fcp_cmnd_len; | ||
1033 | struct fcp_cmnd *fcp_cmnd; | ||
1034 | dma_addr_t crc_ctx_dma; | ||
1035 | |||
1036 | cmd = sp->cmd; | ||
1037 | |||
1038 | sgc = 0; | ||
1039 | /* Update entry type to indicate Command Type CRC_2 IOCB */ | ||
1040 | *((uint32_t *)(&cmd_pkt->entry_type)) = | ||
1041 | __constant_cpu_to_le32(COMMAND_TYPE_CRC_2); | ||
1042 | |||
1043 | /* No data transfer */ | ||
1044 | data_bytes = scsi_bufflen(cmd); | ||
1045 | if (!data_bytes || cmd->sc_data_direction == DMA_NONE) { | ||
1046 | DEBUG18(printk(KERN_INFO "%s: Zero data bytes or DMA-NONE %d\n", | ||
1047 | __func__, data_bytes)); | ||
1048 | cmd_pkt->byte_count = __constant_cpu_to_le32(0); | ||
1049 | return QLA_SUCCESS; | ||
1050 | } | ||
1051 | |||
1052 | vha = sp->fcport->vha; | ||
1053 | ha = vha->hw; | ||
1054 | |||
1055 | DEBUG18(printk(KERN_DEBUG | ||
1056 | "%s(%ld): Executing cmd sp %p, pid=%ld, prot_op=%u.\n", __func__, | ||
1057 | vha->host_no, sp, cmd->serial_number, scsi_get_prot_op(sp->cmd))); | ||
1058 | |||
1059 | cmd_pkt->vp_index = sp->fcport->vp_idx; | ||
1060 | |||
1061 | /* Set transfer direction */ | ||
1062 | if (cmd->sc_data_direction == DMA_TO_DEVICE) { | ||
1063 | cmd_pkt->control_flags = | ||
1064 | __constant_cpu_to_le16(CF_WRITE_DATA); | ||
1065 | } else if (cmd->sc_data_direction == DMA_FROM_DEVICE) { | ||
1066 | cmd_pkt->control_flags = | ||
1067 | __constant_cpu_to_le16(CF_READ_DATA); | ||
1068 | } | ||
1069 | |||
1070 | tot_prot_dsds = scsi_prot_sg_count(cmd); | ||
1071 | if (!tot_prot_dsds) | ||
1072 | bundling = 0; | ||
1073 | |||
1074 | /* Allocate CRC context from global pool */ | ||
1075 | crc_ctx_pkt = sp->ctx = dma_pool_alloc(ha->dl_dma_pool, | ||
1076 | GFP_ATOMIC, &crc_ctx_dma); | ||
1077 | |||
1078 | if (!crc_ctx_pkt) | ||
1079 | goto crc_queuing_error; | ||
1080 | |||
1081 | /* Zero out CTX area. */ | ||
1082 | clr_ptr = (uint8_t *)crc_ctx_pkt; | ||
1083 | memset(clr_ptr, 0, sizeof(*crc_ctx_pkt)); | ||
1084 | |||
1085 | crc_ctx_pkt->crc_ctx_dma = crc_ctx_dma; | ||
1086 | |||
1087 | sp->flags |= SRB_CRC_CTX_DMA_VALID; | ||
1088 | |||
1089 | /* Set handle */ | ||
1090 | crc_ctx_pkt->handle = cmd_pkt->handle; | ||
1091 | |||
1092 | INIT_LIST_HEAD(&crc_ctx_pkt->dsd_list); | ||
1093 | |||
1094 | qla24xx_set_t10dif_tags(cmd, (struct fw_dif_context *) | ||
1095 | &crc_ctx_pkt->ref_tag, tot_prot_dsds); | ||
1096 | |||
1097 | cmd_pkt->crc_context_address[0] = cpu_to_le32(LSD(crc_ctx_dma)); | ||
1098 | cmd_pkt->crc_context_address[1] = cpu_to_le32(MSD(crc_ctx_dma)); | ||
1099 | cmd_pkt->crc_context_len = CRC_CONTEXT_LEN_FW; | ||
1100 | |||
1101 | /* Determine SCSI command length -- align to 4 byte boundary */ | ||
1102 | if (cmd->cmd_len > 16) { | ||
1103 | DEBUG18(printk(KERN_INFO "%s(): **** SCSI CMD > 16\n", | ||
1104 | __func__)); | ||
1105 | additional_fcpcdb_len = cmd->cmd_len - 16; | ||
1106 | if ((cmd->cmd_len % 4) != 0) { | ||
1107 | /* SCSI cmd > 16 bytes must be multiple of 4 */ | ||
1108 | goto crc_queuing_error; | ||
1109 | } | ||
1110 | fcp_cmnd_len = 12 + cmd->cmd_len + 4; | ||
1111 | } else { | ||
1112 | additional_fcpcdb_len = 0; | ||
1113 | fcp_cmnd_len = 12 + 16 + 4; | ||
1114 | } | ||
1115 | |||
1116 | fcp_cmnd = &crc_ctx_pkt->fcp_cmnd; | ||
1117 | |||
1118 | fcp_cmnd->additional_cdb_len = additional_fcpcdb_len; | ||
1119 | if (cmd->sc_data_direction == DMA_TO_DEVICE) | ||
1120 | fcp_cmnd->additional_cdb_len |= 1; | ||
1121 | else if (cmd->sc_data_direction == DMA_FROM_DEVICE) | ||
1122 | fcp_cmnd->additional_cdb_len |= 2; | ||
1123 | |||
1124 | int_to_scsilun(sp->cmd->device->lun, &fcp_cmnd->lun); | ||
1125 | memcpy(fcp_cmnd->cdb, cmd->cmnd, cmd->cmd_len); | ||
1126 | cmd_pkt->fcp_cmnd_dseg_len = cpu_to_le16(fcp_cmnd_len); | ||
1127 | cmd_pkt->fcp_cmnd_dseg_address[0] = cpu_to_le32( | ||
1128 | LSD(crc_ctx_dma + CRC_CONTEXT_FCPCMND_OFF)); | ||
1129 | cmd_pkt->fcp_cmnd_dseg_address[1] = cpu_to_le32( | ||
1130 | MSD(crc_ctx_dma + CRC_CONTEXT_FCPCMND_OFF)); | ||
1131 | fcp_cmnd->task_attribute = 0; | ||
1132 | fcp_cmnd->task_managment = 0; | ||
1133 | |||
1134 | cmd_pkt->fcp_rsp_dseg_len = 0; /* Let response come in status iocb */ | ||
1135 | |||
1136 | DEBUG18(printk(KERN_INFO "%s(%ld): Total SG(s) Entries %d, Data" | ||
1137 | "entries %d, data bytes %d, Protection entries %d\n", | ||
1138 | __func__, vha->host_no, tot_dsds, (tot_dsds-tot_prot_dsds), | ||
1139 | data_bytes, tot_prot_dsds)); | ||
1140 | |||
1141 | /* Compute dif len and adjust data len to incude protection */ | ||
1142 | total_bytes = data_bytes; | ||
1143 | dif_bytes = 0; | ||
1144 | blk_size = cmd->device->sector_size; | ||
1145 | if (scsi_get_prot_type(cmd) == SCSI_PROT_DIF_TYPE1) { | ||
1146 | dif_bytes = (data_bytes / blk_size) * 8; | ||
1147 | total_bytes += dif_bytes; | ||
1148 | } | ||
1149 | |||
1150 | if (!ql2xenablehba_err_chk) | ||
1151 | fw_prot_opts |= 0x10; /* Disable Guard tag checking */ | ||
1152 | |||
1153 | if (!bundling) { | ||
1154 | cur_dsd = (uint32_t *) &crc_ctx_pkt->u.nobundling.data_address; | ||
1155 | } else { | ||
1156 | /* | ||
1157 | * Configure Bundling if we need to fetch interlaving | ||
1158 | * protection PCI accesses | ||
1159 | */ | ||
1160 | fw_prot_opts |= PO_ENABLE_DIF_BUNDLING; | ||
1161 | crc_ctx_pkt->u.bundling.dif_byte_count = cpu_to_le32(dif_bytes); | ||
1162 | crc_ctx_pkt->u.bundling.dseg_count = cpu_to_le16(tot_dsds - | ||
1163 | tot_prot_dsds); | ||
1164 | cur_dsd = (uint32_t *) &crc_ctx_pkt->u.bundling.data_address; | ||
1165 | } | ||
1166 | |||
1167 | /* Finish the common fields of CRC pkt */ | ||
1168 | crc_ctx_pkt->blk_size = cpu_to_le16(blk_size); | ||
1169 | crc_ctx_pkt->prot_opts = cpu_to_le16(fw_prot_opts); | ||
1170 | crc_ctx_pkt->byte_count = cpu_to_le32(data_bytes); | ||
1171 | crc_ctx_pkt->guard_seed = __constant_cpu_to_le16(0); | ||
1172 | /* Fibre channel byte count */ | ||
1173 | cmd_pkt->byte_count = cpu_to_le32(total_bytes); | ||
1174 | fcp_dl = (uint32_t *)(crc_ctx_pkt->fcp_cmnd.cdb + 16 + | ||
1175 | additional_fcpcdb_len); | ||
1176 | *fcp_dl = htonl(total_bytes); | ||
1177 | |||
1178 | DEBUG18(printk(KERN_INFO "%s(%ld): dif bytes = 0x%x (%d), total bytes" | ||
1179 | " = 0x%x (%d), dat block size =0x%x (%d)\n", __func__, | ||
1180 | vha->host_no, dif_bytes, dif_bytes, total_bytes, total_bytes, | ||
1181 | crc_ctx_pkt->blk_size, crc_ctx_pkt->blk_size)); | ||
1182 | |||
1183 | /* Walks data segments */ | ||
1184 | |||
1185 | cmd_pkt->control_flags |= | ||
1186 | __constant_cpu_to_le16(CF_DATA_SEG_DESCR_ENABLE); | ||
1187 | if (qla24xx_walk_and_build_sglist(ha, sp, cur_dsd, | ||
1188 | (tot_dsds - tot_prot_dsds))) | ||
1189 | goto crc_queuing_error; | ||
1190 | |||
1191 | if (bundling && tot_prot_dsds) { | ||
1192 | /* Walks dif segments */ | ||
1193 | cur_seg = scsi_prot_sglist(cmd); | ||
1194 | cmd_pkt->control_flags |= | ||
1195 | __constant_cpu_to_le16(CF_DIF_SEG_DESCR_ENABLE); | ||
1196 | cur_dsd = (uint32_t *) &crc_ctx_pkt->u.bundling.dif_address; | ||
1197 | if (qla24xx_walk_and_build_prot_sglist(ha, sp, cur_dsd, | ||
1198 | tot_prot_dsds)) | ||
1199 | goto crc_queuing_error; | ||
1200 | } | ||
1201 | return QLA_SUCCESS; | ||
1202 | |||
1203 | crc_queuing_error: | ||
1204 | DEBUG18(qla_printk(KERN_INFO, ha, | ||
1205 | "CMD sent FAILED crc_q error:sp = %p\n", sp)); | ||
1206 | /* Cleanup will be performed by the caller */ | ||
1207 | |||
1208 | return QLA_FUNCTION_FAILED; | ||
1209 | } | ||
698 | 1210 | ||
699 | /** | 1211 | /** |
700 | * qla24xx_start_scsi() - Send a SCSI command to the ISP | 1212 | * qla24xx_start_scsi() - Send a SCSI command to the ISP |
@@ -848,6 +1360,191 @@ queuing_error: | |||
848 | return QLA_FUNCTION_FAILED; | 1360 | return QLA_FUNCTION_FAILED; |
849 | } | 1361 | } |
850 | 1362 | ||
1363 | |||
1364 | /** | ||
1365 | * qla24xx_dif_start_scsi() - Send a SCSI command to the ISP | ||
1366 | * @sp: command to send to the ISP | ||
1367 | * | ||
1368 | * Returns non-zero if a failure occurred, else zero. | ||
1369 | */ | ||
1370 | int | ||
1371 | qla24xx_dif_start_scsi(srb_t *sp) | ||
1372 | { | ||
1373 | int nseg; | ||
1374 | unsigned long flags; | ||
1375 | uint32_t *clr_ptr; | ||
1376 | uint32_t index; | ||
1377 | uint32_t handle; | ||
1378 | uint16_t cnt; | ||
1379 | uint16_t req_cnt = 0; | ||
1380 | uint16_t tot_dsds; | ||
1381 | uint16_t tot_prot_dsds; | ||
1382 | uint16_t fw_prot_opts = 0; | ||
1383 | struct req_que *req = NULL; | ||
1384 | struct rsp_que *rsp = NULL; | ||
1385 | struct scsi_cmnd *cmd = sp->cmd; | ||
1386 | struct scsi_qla_host *vha = sp->fcport->vha; | ||
1387 | struct qla_hw_data *ha = vha->hw; | ||
1388 | struct cmd_type_crc_2 *cmd_pkt; | ||
1389 | uint32_t status = 0; | ||
1390 | |||
1391 | #define QDSS_GOT_Q_SPACE BIT_0 | ||
1392 | |||
1393 | /* Only process protection in this routine */ | ||
1394 | if (scsi_get_prot_op(cmd) == SCSI_PROT_NORMAL) | ||
1395 | return qla24xx_start_scsi(sp); | ||
1396 | |||
1397 | /* Setup device pointers. */ | ||
1398 | |||
1399 | qla25xx_set_que(sp, &rsp); | ||
1400 | req = vha->req; | ||
1401 | |||
1402 | /* So we know we haven't pci_map'ed anything yet */ | ||
1403 | tot_dsds = 0; | ||
1404 | |||
1405 | /* Send marker if required */ | ||
1406 | if (vha->marker_needed != 0) { | ||
1407 | if (qla2x00_marker(vha, req, rsp, 0, 0, MK_SYNC_ALL) != | ||
1408 | QLA_SUCCESS) | ||
1409 | return QLA_FUNCTION_FAILED; | ||
1410 | vha->marker_needed = 0; | ||
1411 | } | ||
1412 | |||
1413 | /* Acquire ring specific lock */ | ||
1414 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
1415 | |||
1416 | /* Check for room in outstanding command list. */ | ||
1417 | handle = req->current_outstanding_cmd; | ||
1418 | for (index = 1; index < MAX_OUTSTANDING_COMMANDS; index++) { | ||
1419 | handle++; | ||
1420 | if (handle == MAX_OUTSTANDING_COMMANDS) | ||
1421 | handle = 1; | ||
1422 | if (!req->outstanding_cmds[handle]) | ||
1423 | break; | ||
1424 | } | ||
1425 | |||
1426 | if (index == MAX_OUTSTANDING_COMMANDS) | ||
1427 | goto queuing_error; | ||
1428 | |||
1429 | /* Compute number of required data segments */ | ||
1430 | /* Map the sg table so we have an accurate count of sg entries needed */ | ||
1431 | if (scsi_sg_count(cmd)) { | ||
1432 | nseg = dma_map_sg(&ha->pdev->dev, scsi_sglist(cmd), | ||
1433 | scsi_sg_count(cmd), cmd->sc_data_direction); | ||
1434 | if (unlikely(!nseg)) | ||
1435 | goto queuing_error; | ||
1436 | else | ||
1437 | sp->flags |= SRB_DMA_VALID; | ||
1438 | } else | ||
1439 | nseg = 0; | ||
1440 | |||
1441 | /* number of required data segments */ | ||
1442 | tot_dsds = nseg; | ||
1443 | |||
1444 | /* Compute number of required protection segments */ | ||
1445 | if (qla24xx_configure_prot_mode(sp, &fw_prot_opts)) { | ||
1446 | nseg = dma_map_sg(&ha->pdev->dev, scsi_prot_sglist(cmd), | ||
1447 | scsi_prot_sg_count(cmd), cmd->sc_data_direction); | ||
1448 | if (unlikely(!nseg)) | ||
1449 | goto queuing_error; | ||
1450 | else | ||
1451 | sp->flags |= SRB_CRC_PROT_DMA_VALID; | ||
1452 | } else { | ||
1453 | nseg = 0; | ||
1454 | } | ||
1455 | |||
1456 | req_cnt = 1; | ||
1457 | /* Total Data and protection sg segment(s) */ | ||
1458 | tot_prot_dsds = nseg; | ||
1459 | tot_dsds += nseg; | ||
1460 | if (req->cnt < (req_cnt + 2)) { | ||
1461 | cnt = RD_REG_DWORD_RELAXED(req->req_q_out); | ||
1462 | |||
1463 | if (req->ring_index < cnt) | ||
1464 | req->cnt = cnt - req->ring_index; | ||
1465 | else | ||
1466 | req->cnt = req->length - | ||
1467 | (req->ring_index - cnt); | ||
1468 | } | ||
1469 | |||
1470 | if (req->cnt < (req_cnt + 2)) | ||
1471 | goto queuing_error; | ||
1472 | |||
1473 | status |= QDSS_GOT_Q_SPACE; | ||
1474 | |||
1475 | /* Build header part of command packet (excluding the OPCODE). */ | ||
1476 | req->current_outstanding_cmd = handle; | ||
1477 | req->outstanding_cmds[handle] = sp; | ||
1478 | sp->cmd->host_scribble = (unsigned char *)(unsigned long)handle; | ||
1479 | req->cnt -= req_cnt; | ||
1480 | |||
1481 | /* Fill-in common area */ | ||
1482 | cmd_pkt = (struct cmd_type_crc_2 *)req->ring_ptr; | ||
1483 | cmd_pkt->handle = MAKE_HANDLE(req->id, handle); | ||
1484 | |||
1485 | clr_ptr = (uint32_t *)cmd_pkt + 2; | ||
1486 | memset(clr_ptr, 0, REQUEST_ENTRY_SIZE - 8); | ||
1487 | |||
1488 | /* Set NPORT-ID and LUN number*/ | ||
1489 | cmd_pkt->nport_handle = cpu_to_le16(sp->fcport->loop_id); | ||
1490 | cmd_pkt->port_id[0] = sp->fcport->d_id.b.al_pa; | ||
1491 | cmd_pkt->port_id[1] = sp->fcport->d_id.b.area; | ||
1492 | cmd_pkt->port_id[2] = sp->fcport->d_id.b.domain; | ||
1493 | |||
1494 | int_to_scsilun(sp->cmd->device->lun, &cmd_pkt->lun); | ||
1495 | host_to_fcp_swap((uint8_t *)&cmd_pkt->lun, sizeof(cmd_pkt->lun)); | ||
1496 | |||
1497 | /* Total Data and protection segment(s) */ | ||
1498 | cmd_pkt->dseg_count = cpu_to_le16(tot_dsds); | ||
1499 | |||
1500 | /* Build IOCB segments and adjust for data protection segments */ | ||
1501 | if (qla24xx_build_scsi_crc_2_iocbs(sp, (struct cmd_type_crc_2 *) | ||
1502 | req->ring_ptr, tot_dsds, tot_prot_dsds, fw_prot_opts) != | ||
1503 | QLA_SUCCESS) | ||
1504 | goto queuing_error; | ||
1505 | |||
1506 | cmd_pkt->entry_count = (uint8_t)req_cnt; | ||
1507 | /* Specify response queue number where completion should happen */ | ||
1508 | cmd_pkt->entry_status = (uint8_t) rsp->id; | ||
1509 | cmd_pkt->timeout = __constant_cpu_to_le16(0); | ||
1510 | wmb(); | ||
1511 | |||
1512 | /* Adjust ring index. */ | ||
1513 | req->ring_index++; | ||
1514 | if (req->ring_index == req->length) { | ||
1515 | req->ring_index = 0; | ||
1516 | req->ring_ptr = req->ring; | ||
1517 | } else | ||
1518 | req->ring_ptr++; | ||
1519 | |||
1520 | /* Set chip new ring index. */ | ||
1521 | WRT_REG_DWORD(req->req_q_in, req->ring_index); | ||
1522 | RD_REG_DWORD_RELAXED(&ha->iobase->isp24.hccr); | ||
1523 | |||
1524 | /* Manage unprocessed RIO/ZIO commands in response queue. */ | ||
1525 | if (vha->flags.process_response_queue && | ||
1526 | rsp->ring_ptr->signature != RESPONSE_PROCESSED) | ||
1527 | qla24xx_process_response_queue(vha, rsp); | ||
1528 | |||
1529 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
1530 | |||
1531 | return QLA_SUCCESS; | ||
1532 | |||
1533 | queuing_error: | ||
1534 | if (status & QDSS_GOT_Q_SPACE) { | ||
1535 | req->outstanding_cmds[handle] = NULL; | ||
1536 | req->cnt += req_cnt; | ||
1537 | } | ||
1538 | /* Cleanup will be performed by the caller (queuecommand) */ | ||
1539 | |||
1540 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
1541 | |||
1542 | DEBUG18(qla_printk(KERN_INFO, ha, | ||
1543 | "CMD sent FAILED SCSI prot_op:%02x\n", scsi_get_prot_op(cmd))); | ||
1544 | return QLA_FUNCTION_FAILED; | ||
1545 | } | ||
1546 | |||
1547 | |||
851 | static void qla25xx_set_que(srb_t *sp, struct rsp_que **rsp) | 1548 | static void qla25xx_set_que(srb_t *sp, struct rsp_que **rsp) |
852 | { | 1549 | { |
853 | struct scsi_cmnd *cmd = sp->cmd; | 1550 | struct scsi_cmnd *cmd = sp->cmd; |
@@ -931,37 +1628,45 @@ qla2x00_start_iocbs(srb_t *sp) | |||
931 | device_reg_t __iomem *reg = ISP_QUE_REG(ha, req->id); | 1628 | device_reg_t __iomem *reg = ISP_QUE_REG(ha, req->id); |
932 | struct device_reg_2xxx __iomem *ioreg = &ha->iobase->isp; | 1629 | struct device_reg_2xxx __iomem *ioreg = &ha->iobase->isp; |
933 | 1630 | ||
934 | /* Adjust ring index. */ | 1631 | if (IS_QLA82XX(ha)) { |
935 | req->ring_index++; | 1632 | qla82xx_start_iocbs(sp); |
936 | if (req->ring_index == req->length) { | ||
937 | req->ring_index = 0; | ||
938 | req->ring_ptr = req->ring; | ||
939 | } else | ||
940 | req->ring_ptr++; | ||
941 | |||
942 | /* Set chip new ring index. */ | ||
943 | if (ha->mqenable) { | ||
944 | WRT_REG_DWORD(®->isp25mq.req_q_in, req->ring_index); | ||
945 | RD_REG_DWORD(&ioreg->hccr); | ||
946 | } else if (IS_FWI2_CAPABLE(ha)) { | ||
947 | WRT_REG_DWORD(®->isp24.req_q_in, req->ring_index); | ||
948 | RD_REG_DWORD_RELAXED(®->isp24.req_q_in); | ||
949 | } else { | 1633 | } else { |
950 | WRT_REG_WORD(ISP_REQ_Q_IN(ha, ®->isp), req->ring_index); | 1634 | /* Adjust ring index. */ |
951 | RD_REG_WORD_RELAXED(ISP_REQ_Q_IN(ha, ®->isp)); | 1635 | req->ring_index++; |
1636 | if (req->ring_index == req->length) { | ||
1637 | req->ring_index = 0; | ||
1638 | req->ring_ptr = req->ring; | ||
1639 | } else | ||
1640 | req->ring_ptr++; | ||
1641 | |||
1642 | /* Set chip new ring index. */ | ||
1643 | if (ha->mqenable) { | ||
1644 | WRT_REG_DWORD(®->isp25mq.req_q_in, req->ring_index); | ||
1645 | RD_REG_DWORD(&ioreg->hccr); | ||
1646 | } else if (IS_QLA82XX(ha)) { | ||
1647 | qla82xx_start_iocbs(sp); | ||
1648 | } else if (IS_FWI2_CAPABLE(ha)) { | ||
1649 | WRT_REG_DWORD(®->isp24.req_q_in, req->ring_index); | ||
1650 | RD_REG_DWORD_RELAXED(®->isp24.req_q_in); | ||
1651 | } else { | ||
1652 | WRT_REG_WORD(ISP_REQ_Q_IN(ha, ®->isp), | ||
1653 | req->ring_index); | ||
1654 | RD_REG_WORD_RELAXED(ISP_REQ_Q_IN(ha, ®->isp)); | ||
1655 | } | ||
952 | } | 1656 | } |
953 | } | 1657 | } |
954 | 1658 | ||
955 | static void | 1659 | static void |
956 | qla24xx_login_iocb(srb_t *sp, struct logio_entry_24xx *logio) | 1660 | qla24xx_login_iocb(srb_t *sp, struct logio_entry_24xx *logio) |
957 | { | 1661 | { |
958 | struct srb_logio *lio = sp->ctx; | 1662 | struct srb_ctx *ctx = sp->ctx; |
1663 | struct srb_iocb *lio = ctx->u.iocb_cmd; | ||
959 | 1664 | ||
960 | logio->entry_type = LOGINOUT_PORT_IOCB_TYPE; | 1665 | logio->entry_type = LOGINOUT_PORT_IOCB_TYPE; |
961 | logio->control_flags = cpu_to_le16(LCF_COMMAND_PLOGI); | 1666 | logio->control_flags = cpu_to_le16(LCF_COMMAND_PLOGI); |
962 | if (lio->flags & SRB_LOGIN_COND_PLOGI) | 1667 | if (lio->u.logio.flags & SRB_LOGIN_COND_PLOGI) |
963 | logio->control_flags |= cpu_to_le16(LCF_COND_PLOGI); | 1668 | logio->control_flags |= cpu_to_le16(LCF_COND_PLOGI); |
964 | if (lio->flags & SRB_LOGIN_SKIP_PRLI) | 1669 | if (lio->u.logio.flags & SRB_LOGIN_SKIP_PRLI) |
965 | logio->control_flags |= cpu_to_le16(LCF_SKIP_PRLI); | 1670 | logio->control_flags |= cpu_to_le16(LCF_SKIP_PRLI); |
966 | logio->nport_handle = cpu_to_le16(sp->fcport->loop_id); | 1671 | logio->nport_handle = cpu_to_le16(sp->fcport->loop_id); |
967 | logio->port_id[0] = sp->fcport->d_id.b.al_pa; | 1672 | logio->port_id[0] = sp->fcport->d_id.b.al_pa; |
@@ -974,14 +1679,15 @@ static void | |||
974 | qla2x00_login_iocb(srb_t *sp, struct mbx_entry *mbx) | 1679 | qla2x00_login_iocb(srb_t *sp, struct mbx_entry *mbx) |
975 | { | 1680 | { |
976 | struct qla_hw_data *ha = sp->fcport->vha->hw; | 1681 | struct qla_hw_data *ha = sp->fcport->vha->hw; |
977 | struct srb_logio *lio = sp->ctx; | 1682 | struct srb_ctx *ctx = sp->ctx; |
1683 | struct srb_iocb *lio = ctx->u.iocb_cmd; | ||
978 | uint16_t opts; | 1684 | uint16_t opts; |
979 | 1685 | ||
980 | mbx->entry_type = MBX_IOCB_TYPE;; | 1686 | mbx->entry_type = MBX_IOCB_TYPE;; |
981 | SET_TARGET_ID(ha, mbx->loop_id, sp->fcport->loop_id); | 1687 | SET_TARGET_ID(ha, mbx->loop_id, sp->fcport->loop_id); |
982 | mbx->mb0 = cpu_to_le16(MBC_LOGIN_FABRIC_PORT); | 1688 | mbx->mb0 = cpu_to_le16(MBC_LOGIN_FABRIC_PORT); |
983 | opts = lio->flags & SRB_LOGIN_COND_PLOGI ? BIT_0: 0; | 1689 | opts = lio->u.logio.flags & SRB_LOGIN_COND_PLOGI ? BIT_0 : 0; |
984 | opts |= lio->flags & SRB_LOGIN_SKIP_PRLI ? BIT_1: 0; | 1690 | opts |= lio->u.logio.flags & SRB_LOGIN_SKIP_PRLI ? BIT_1 : 0; |
985 | if (HAS_EXTENDED_IDS(ha)) { | 1691 | if (HAS_EXTENDED_IDS(ha)) { |
986 | mbx->mb1 = cpu_to_le16(sp->fcport->loop_id); | 1692 | mbx->mb1 = cpu_to_le16(sp->fcport->loop_id); |
987 | mbx->mb10 = cpu_to_le16(opts); | 1693 | mbx->mb10 = cpu_to_le16(opts); |
@@ -1026,9 +1732,97 @@ qla2x00_logout_iocb(srb_t *sp, struct mbx_entry *mbx) | |||
1026 | } | 1732 | } |
1027 | 1733 | ||
1028 | static void | 1734 | static void |
1735 | qla24xx_adisc_iocb(srb_t *sp, struct logio_entry_24xx *logio) | ||
1736 | { | ||
1737 | logio->entry_type = LOGINOUT_PORT_IOCB_TYPE; | ||
1738 | logio->control_flags = cpu_to_le16(LCF_COMMAND_ADISC); | ||
1739 | logio->nport_handle = cpu_to_le16(sp->fcport->loop_id); | ||
1740 | logio->vp_index = sp->fcport->vp_idx; | ||
1741 | } | ||
1742 | |||
1743 | static void | ||
1744 | qla2x00_adisc_iocb(srb_t *sp, struct mbx_entry *mbx) | ||
1745 | { | ||
1746 | struct qla_hw_data *ha = sp->fcport->vha->hw; | ||
1747 | |||
1748 | mbx->entry_type = MBX_IOCB_TYPE; | ||
1749 | SET_TARGET_ID(ha, mbx->loop_id, sp->fcport->loop_id); | ||
1750 | mbx->mb0 = cpu_to_le16(MBC_GET_PORT_DATABASE); | ||
1751 | if (HAS_EXTENDED_IDS(ha)) { | ||
1752 | mbx->mb1 = cpu_to_le16(sp->fcport->loop_id); | ||
1753 | mbx->mb10 = cpu_to_le16(BIT_0); | ||
1754 | } else { | ||
1755 | mbx->mb1 = cpu_to_le16((sp->fcport->loop_id << 8) | BIT_0); | ||
1756 | } | ||
1757 | mbx->mb2 = cpu_to_le16(MSW(ha->async_pd_dma)); | ||
1758 | mbx->mb3 = cpu_to_le16(LSW(ha->async_pd_dma)); | ||
1759 | mbx->mb6 = cpu_to_le16(MSW(MSD(ha->async_pd_dma))); | ||
1760 | mbx->mb7 = cpu_to_le16(LSW(MSD(ha->async_pd_dma))); | ||
1761 | mbx->mb9 = cpu_to_le16(sp->fcport->vp_idx); | ||
1762 | } | ||
1763 | |||
1764 | static void | ||
1765 | qla24xx_tm_iocb(srb_t *sp, struct tsk_mgmt_entry *tsk) | ||
1766 | { | ||
1767 | uint32_t flags; | ||
1768 | unsigned int lun; | ||
1769 | struct fc_port *fcport = sp->fcport; | ||
1770 | scsi_qla_host_t *vha = fcport->vha; | ||
1771 | struct qla_hw_data *ha = vha->hw; | ||
1772 | struct srb_ctx *ctx = sp->ctx; | ||
1773 | struct srb_iocb *iocb = ctx->u.iocb_cmd; | ||
1774 | struct req_que *req = vha->req; | ||
1775 | |||
1776 | flags = iocb->u.tmf.flags; | ||
1777 | lun = iocb->u.tmf.lun; | ||
1778 | |||
1779 | tsk->entry_type = TSK_MGMT_IOCB_TYPE; | ||
1780 | tsk->entry_count = 1; | ||
1781 | tsk->handle = MAKE_HANDLE(req->id, tsk->handle); | ||
1782 | tsk->nport_handle = cpu_to_le16(fcport->loop_id); | ||
1783 | tsk->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2); | ||
1784 | tsk->control_flags = cpu_to_le32(flags); | ||
1785 | tsk->port_id[0] = fcport->d_id.b.al_pa; | ||
1786 | tsk->port_id[1] = fcport->d_id.b.area; | ||
1787 | tsk->port_id[2] = fcport->d_id.b.domain; | ||
1788 | tsk->vp_index = fcport->vp_idx; | ||
1789 | |||
1790 | if (flags == TCF_LUN_RESET) { | ||
1791 | int_to_scsilun(lun, &tsk->lun); | ||
1792 | host_to_fcp_swap((uint8_t *)&tsk->lun, | ||
1793 | sizeof(tsk->lun)); | ||
1794 | } | ||
1795 | } | ||
1796 | |||
1797 | static void | ||
1798 | qla24xx_marker_iocb(srb_t *sp, struct mrk_entry_24xx *mrk) | ||
1799 | { | ||
1800 | uint16_t lun; | ||
1801 | uint8_t modif; | ||
1802 | struct fc_port *fcport = sp->fcport; | ||
1803 | scsi_qla_host_t *vha = fcport->vha; | ||
1804 | struct srb_ctx *ctx = sp->ctx; | ||
1805 | struct srb_iocb *iocb = ctx->u.iocb_cmd; | ||
1806 | struct req_que *req = vha->req; | ||
1807 | |||
1808 | lun = iocb->u.marker.lun; | ||
1809 | modif = iocb->u.marker.modif; | ||
1810 | mrk->entry_type = MARKER_TYPE; | ||
1811 | mrk->modifier = modif; | ||
1812 | if (modif != MK_SYNC_ALL) { | ||
1813 | mrk->nport_handle = cpu_to_le16(fcport->loop_id); | ||
1814 | mrk->lun[1] = LSB(lun); | ||
1815 | mrk->lun[2] = MSB(lun); | ||
1816 | host_to_fcp_swap(mrk->lun, sizeof(mrk->lun)); | ||
1817 | mrk->vp_index = vha->vp_idx; | ||
1818 | mrk->handle = MAKE_HANDLE(req->id, mrk->handle); | ||
1819 | } | ||
1820 | } | ||
1821 | |||
1822 | static void | ||
1029 | qla24xx_els_iocb(srb_t *sp, struct els_entry_24xx *els_iocb) | 1823 | qla24xx_els_iocb(srb_t *sp, struct els_entry_24xx *els_iocb) |
1030 | { | 1824 | { |
1031 | struct fc_bsg_job *bsg_job = ((struct srb_bsg*)sp->ctx)->bsg_job; | 1825 | struct fc_bsg_job *bsg_job = ((struct srb_ctx *)sp->ctx)->u.bsg_job; |
1032 | 1826 | ||
1033 | els_iocb->entry_type = ELS_IOCB_TYPE; | 1827 | els_iocb->entry_type = ELS_IOCB_TYPE; |
1034 | els_iocb->entry_count = 1; | 1828 | els_iocb->entry_count = 1; |
@@ -1041,8 +1835,10 @@ qla24xx_els_iocb(srb_t *sp, struct els_entry_24xx *els_iocb) | |||
1041 | els_iocb->sof_type = EST_SOFI3; | 1835 | els_iocb->sof_type = EST_SOFI3; |
1042 | els_iocb->rx_dsd_count = __constant_cpu_to_le16(bsg_job->reply_payload.sg_cnt); | 1836 | els_iocb->rx_dsd_count = __constant_cpu_to_le16(bsg_job->reply_payload.sg_cnt); |
1043 | 1837 | ||
1044 | els_iocb->opcode =(((struct srb_bsg*)sp->ctx)->ctx.type == SRB_ELS_CMD_RPT) ? | 1838 | els_iocb->opcode = |
1045 | bsg_job->request->rqst_data.r_els.els_code : bsg_job->request->rqst_data.h_els.command_code; | 1839 | (((struct srb_ctx *)sp->ctx)->type == SRB_ELS_CMD_RPT) ? |
1840 | bsg_job->request->rqst_data.r_els.els_code : | ||
1841 | bsg_job->request->rqst_data.h_els.command_code; | ||
1046 | els_iocb->port_id[0] = sp->fcport->d_id.b.al_pa; | 1842 | els_iocb->port_id[0] = sp->fcport->d_id.b.al_pa; |
1047 | els_iocb->port_id[1] = sp->fcport->d_id.b.area; | 1843 | els_iocb->port_id[1] = sp->fcport->d_id.b.area; |
1048 | els_iocb->port_id[2] = sp->fcport->d_id.b.domain; | 1844 | els_iocb->port_id[2] = sp->fcport->d_id.b.domain; |
@@ -1076,7 +1872,7 @@ qla24xx_ct_iocb(srb_t *sp, struct ct_entry_24xx *ct_iocb) | |||
1076 | int index; | 1872 | int index; |
1077 | uint16_t tot_dsds; | 1873 | uint16_t tot_dsds; |
1078 | scsi_qla_host_t *vha = sp->fcport->vha; | 1874 | scsi_qla_host_t *vha = sp->fcport->vha; |
1079 | struct fc_bsg_job *bsg_job = ((struct srb_bsg*)sp->ctx)->bsg_job; | 1875 | struct fc_bsg_job *bsg_job = ((struct srb_ctx *)sp->ctx)->u.bsg_job; |
1080 | int loop_iterartion = 0; | 1876 | int loop_iterartion = 0; |
1081 | int cont_iocb_prsnt = 0; | 1877 | int cont_iocb_prsnt = 0; |
1082 | int entry_count = 1; | 1878 | int entry_count = 1; |
@@ -1157,12 +1953,12 @@ qla2x00_start_sp(srb_t *sp) | |||
1157 | switch (ctx->type) { | 1953 | switch (ctx->type) { |
1158 | case SRB_LOGIN_CMD: | 1954 | case SRB_LOGIN_CMD: |
1159 | IS_FWI2_CAPABLE(ha) ? | 1955 | IS_FWI2_CAPABLE(ha) ? |
1160 | qla24xx_login_iocb(sp, pkt): | 1956 | qla24xx_login_iocb(sp, pkt) : |
1161 | qla2x00_login_iocb(sp, pkt); | 1957 | qla2x00_login_iocb(sp, pkt); |
1162 | break; | 1958 | break; |
1163 | case SRB_LOGOUT_CMD: | 1959 | case SRB_LOGOUT_CMD: |
1164 | IS_FWI2_CAPABLE(ha) ? | 1960 | IS_FWI2_CAPABLE(ha) ? |
1165 | qla24xx_logout_iocb(sp, pkt): | 1961 | qla24xx_logout_iocb(sp, pkt) : |
1166 | qla2x00_logout_iocb(sp, pkt); | 1962 | qla2x00_logout_iocb(sp, pkt); |
1167 | break; | 1963 | break; |
1168 | case SRB_ELS_CMD_RPT: | 1964 | case SRB_ELS_CMD_RPT: |
@@ -1172,6 +1968,17 @@ qla2x00_start_sp(srb_t *sp) | |||
1172 | case SRB_CT_CMD: | 1968 | case SRB_CT_CMD: |
1173 | qla24xx_ct_iocb(sp, pkt); | 1969 | qla24xx_ct_iocb(sp, pkt); |
1174 | break; | 1970 | break; |
1971 | case SRB_ADISC_CMD: | ||
1972 | IS_FWI2_CAPABLE(ha) ? | ||
1973 | qla24xx_adisc_iocb(sp, pkt) : | ||
1974 | qla2x00_adisc_iocb(sp, pkt); | ||
1975 | break; | ||
1976 | case SRB_TM_CMD: | ||
1977 | qla24xx_tm_iocb(sp, pkt); | ||
1978 | break; | ||
1979 | case SRB_MARKER_CMD: | ||
1980 | qla24xx_marker_iocb(sp, pkt); | ||
1981 | break; | ||
1175 | default: | 1982 | default: |
1176 | break; | 1983 | break; |
1177 | } | 1984 | } |
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index db539b0c3dae..be3d8bed2ecf 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/slab.h> | 10 | #include <linux/slab.h> |
11 | #include <scsi/scsi_tcq.h> | 11 | #include <scsi/scsi_tcq.h> |
12 | #include <scsi/scsi_bsg_fc.h> | 12 | #include <scsi/scsi_bsg_fc.h> |
13 | #include <scsi/scsi_eh.h> | ||
13 | 14 | ||
14 | static void qla2x00_mbx_completion(scsi_qla_host_t *, uint16_t); | 15 | static void qla2x00_mbx_completion(scsi_qla_host_t *, uint16_t); |
15 | static void qla2x00_process_completed_request(struct scsi_qla_host *, | 16 | static void qla2x00_process_completed_request(struct scsi_qla_host *, |
@@ -326,7 +327,7 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb) | |||
326 | 327 | ||
327 | /* Setup to process RIO completion. */ | 328 | /* Setup to process RIO completion. */ |
328 | handle_cnt = 0; | 329 | handle_cnt = 0; |
329 | if (IS_QLA81XX(ha)) | 330 | if (IS_QLA8XXX_TYPE(ha)) |
330 | goto skip_rio; | 331 | goto skip_rio; |
331 | switch (mb[0]) { | 332 | switch (mb[0]) { |
332 | case MBA_SCSI_COMPLETION: | 333 | case MBA_SCSI_COMPLETION: |
@@ -544,7 +545,7 @@ skip_rio: | |||
544 | if (IS_QLA2100(ha)) | 545 | if (IS_QLA2100(ha)) |
545 | break; | 546 | break; |
546 | 547 | ||
547 | if (IS_QLA81XX(ha)) | 548 | if (IS_QLA8XXX_TYPE(ha)) |
548 | DEBUG2(printk("scsi(%ld): DCBX Completed -- %04x %04x " | 549 | DEBUG2(printk("scsi(%ld): DCBX Completed -- %04x %04x " |
549 | "%04x\n", vha->host_no, mb[1], mb[2], mb[3])); | 550 | "%04x\n", vha->host_no, mb[1], mb[2], mb[3])); |
550 | else | 551 | else |
@@ -845,7 +846,7 @@ qla2x00_process_completed_request(struct scsi_qla_host *vha, | |||
845 | qla2x00_sp_compl(ha, sp); | 846 | qla2x00_sp_compl(ha, sp); |
846 | } else { | 847 | } else { |
847 | DEBUG2(printk("scsi(%ld) Req:%d: Invalid ISP SCSI completion" | 848 | DEBUG2(printk("scsi(%ld) Req:%d: Invalid ISP SCSI completion" |
848 | " handle(%d)\n", vha->host_no, req->id, index)); | 849 | " handle(0x%x)\n", vha->host_no, req->id, index)); |
849 | qla_printk(KERN_WARNING, ha, | 850 | qla_printk(KERN_WARNING, ha, |
850 | "Invalid ISP SCSI completion handle\n"); | 851 | "Invalid ISP SCSI completion handle\n"); |
851 | 852 | ||
@@ -895,36 +896,26 @@ qla2x00_mbx_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, | |||
895 | { | 896 | { |
896 | const char func[] = "MBX-IOCB"; | 897 | const char func[] = "MBX-IOCB"; |
897 | const char *type; | 898 | const char *type; |
898 | struct qla_hw_data *ha = vha->hw; | ||
899 | fc_port_t *fcport; | 899 | fc_port_t *fcport; |
900 | srb_t *sp; | 900 | srb_t *sp; |
901 | struct srb_logio *lio; | 901 | struct srb_iocb *lio; |
902 | uint16_t data[2]; | 902 | struct srb_ctx *ctx; |
903 | uint16_t *data; | ||
904 | uint16_t status; | ||
903 | 905 | ||
904 | sp = qla2x00_get_sp_from_handle(vha, func, req, mbx); | 906 | sp = qla2x00_get_sp_from_handle(vha, func, req, mbx); |
905 | if (!sp) | 907 | if (!sp) |
906 | return; | 908 | return; |
907 | 909 | ||
908 | type = NULL; | 910 | ctx = sp->ctx; |
909 | lio = sp->ctx; | 911 | lio = ctx->u.iocb_cmd; |
910 | switch (lio->ctx.type) { | 912 | type = ctx->name; |
911 | case SRB_LOGIN_CMD: | ||
912 | type = "login"; | ||
913 | break; | ||
914 | case SRB_LOGOUT_CMD: | ||
915 | type = "logout"; | ||
916 | break; | ||
917 | default: | ||
918 | qla_printk(KERN_WARNING, ha, | ||
919 | "%s: Unrecognized SRB: (%p) type=%d.\n", func, sp, | ||
920 | lio->ctx.type); | ||
921 | return; | ||
922 | } | ||
923 | |||
924 | del_timer(&lio->ctx.timer); | ||
925 | fcport = sp->fcport; | 913 | fcport = sp->fcport; |
914 | data = lio->u.logio.data; | ||
926 | 915 | ||
927 | data[0] = data[1] = 0; | 916 | data[0] = MBS_COMMAND_ERROR; |
917 | data[1] = lio->u.logio.flags & SRB_LOGIN_RETRIED ? | ||
918 | QLA_LOGIO_LOGIN_RETRIED : 0; | ||
928 | if (mbx->entry_status) { | 919 | if (mbx->entry_status) { |
929 | DEBUG2(printk(KERN_WARNING | 920 | DEBUG2(printk(KERN_WARNING |
930 | "scsi(%ld:%x): Async-%s error entry - entry-status=%x " | 921 | "scsi(%ld:%x): Async-%s error entry - entry-status=%x " |
@@ -935,23 +926,28 @@ qla2x00_mbx_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, | |||
935 | le16_to_cpu(mbx->status_flags))); | 926 | le16_to_cpu(mbx->status_flags))); |
936 | DEBUG2(qla2x00_dump_buffer((uint8_t *)mbx, sizeof(*mbx))); | 927 | DEBUG2(qla2x00_dump_buffer((uint8_t *)mbx, sizeof(*mbx))); |
937 | 928 | ||
938 | data[0] = MBS_COMMAND_ERROR; | 929 | goto logio_done; |
939 | data[1] = lio->flags & SRB_LOGIN_RETRIED ? | ||
940 | QLA_LOGIO_LOGIN_RETRIED: 0; | ||
941 | goto done_post_logio_done_work; | ||
942 | } | 930 | } |
943 | 931 | ||
944 | if (!mbx->status && le16_to_cpu(mbx->mb0) == MBS_COMMAND_COMPLETE) { | 932 | status = le16_to_cpu(mbx->status); |
933 | if (status == 0x30 && ctx->type == SRB_LOGIN_CMD && | ||
934 | le16_to_cpu(mbx->mb0) == MBS_COMMAND_COMPLETE) | ||
935 | status = 0; | ||
936 | if (!status && le16_to_cpu(mbx->mb0) == MBS_COMMAND_COMPLETE) { | ||
945 | DEBUG2(printk(KERN_DEBUG | 937 | DEBUG2(printk(KERN_DEBUG |
946 | "scsi(%ld:%x): Async-%s complete - mbx1=%x.\n", | 938 | "scsi(%ld:%x): Async-%s complete - mbx1=%x.\n", |
947 | fcport->vha->host_no, sp->handle, type, | 939 | fcport->vha->host_no, sp->handle, type, |
948 | le16_to_cpu(mbx->mb1))); | 940 | le16_to_cpu(mbx->mb1))); |
949 | 941 | ||
950 | data[0] = MBS_COMMAND_COMPLETE; | 942 | data[0] = MBS_COMMAND_COMPLETE; |
951 | if (lio->ctx.type == SRB_LOGIN_CMD && le16_to_cpu(mbx->mb1) & BIT_1) | 943 | if (ctx->type == SRB_LOGIN_CMD) { |
952 | fcport->flags |= FCF_FCP2_DEVICE; | 944 | fcport->port_type = FCT_TARGET; |
953 | 945 | if (le16_to_cpu(mbx->mb1) & BIT_0) | |
954 | goto done_post_logio_done_work; | 946 | fcport->port_type = FCT_INITIATOR; |
947 | if (le16_to_cpu(mbx->mb1) & BIT_1) | ||
948 | fcport->flags |= FCF_FCP2_DEVICE; | ||
949 | } | ||
950 | goto logio_done; | ||
955 | } | 951 | } |
956 | 952 | ||
957 | data[0] = le16_to_cpu(mbx->mb0); | 953 | data[0] = le16_to_cpu(mbx->mb0); |
@@ -963,25 +959,19 @@ qla2x00_mbx_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, | |||
963 | break; | 959 | break; |
964 | default: | 960 | default: |
965 | data[0] = MBS_COMMAND_ERROR; | 961 | data[0] = MBS_COMMAND_ERROR; |
966 | data[1] = lio->flags & SRB_LOGIN_RETRIED ? | ||
967 | QLA_LOGIO_LOGIN_RETRIED: 0; | ||
968 | break; | 962 | break; |
969 | } | 963 | } |
970 | 964 | ||
971 | DEBUG2(printk(KERN_WARNING | 965 | DEBUG2(printk(KERN_WARNING |
972 | "scsi(%ld:%x): Async-%s failed - status=%x mb0=%x mb1=%x mb2=%x " | 966 | "scsi(%ld:%x): Async-%s failed - status=%x mb0=%x mb1=%x mb2=%x " |
973 | "mb6=%x mb7=%x.\n", | 967 | "mb6=%x mb7=%x.\n", |
974 | fcport->vha->host_no, sp->handle, type, le16_to_cpu(mbx->status), | 968 | fcport->vha->host_no, sp->handle, type, status, |
975 | le16_to_cpu(mbx->mb0), le16_to_cpu(mbx->mb1), | 969 | le16_to_cpu(mbx->mb0), le16_to_cpu(mbx->mb1), |
976 | le16_to_cpu(mbx->mb2), le16_to_cpu(mbx->mb6), | 970 | le16_to_cpu(mbx->mb2), le16_to_cpu(mbx->mb6), |
977 | le16_to_cpu(mbx->mb7))); | 971 | le16_to_cpu(mbx->mb7))); |
978 | 972 | ||
979 | done_post_logio_done_work: | 973 | logio_done: |
980 | lio->ctx.type == SRB_LOGIN_CMD ? | 974 | lio->done(sp); |
981 | qla2x00_post_async_login_done_work(fcport->vha, fcport, data): | ||
982 | qla2x00_post_async_logout_done_work(fcport->vha, fcport, data); | ||
983 | |||
984 | lio->ctx.free(sp); | ||
985 | } | 975 | } |
986 | 976 | ||
987 | static void | 977 | static void |
@@ -992,7 +982,7 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req, | |||
992 | const char *type; | 982 | const char *type; |
993 | struct qla_hw_data *ha = vha->hw; | 983 | struct qla_hw_data *ha = vha->hw; |
994 | srb_t *sp; | 984 | srb_t *sp; |
995 | struct srb_bsg *sp_bsg; | 985 | struct srb_ctx *sp_bsg; |
996 | struct fc_bsg_job *bsg_job; | 986 | struct fc_bsg_job *bsg_job; |
997 | uint16_t comp_status; | 987 | uint16_t comp_status; |
998 | uint32_t fw_status[3]; | 988 | uint32_t fw_status[3]; |
@@ -1001,11 +991,11 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req, | |||
1001 | sp = qla2x00_get_sp_from_handle(vha, func, req, pkt); | 991 | sp = qla2x00_get_sp_from_handle(vha, func, req, pkt); |
1002 | if (!sp) | 992 | if (!sp) |
1003 | return; | 993 | return; |
1004 | sp_bsg = (struct srb_bsg*)sp->ctx; | 994 | sp_bsg = sp->ctx; |
1005 | bsg_job = sp_bsg->bsg_job; | 995 | bsg_job = sp_bsg->u.bsg_job; |
1006 | 996 | ||
1007 | type = NULL; | 997 | type = NULL; |
1008 | switch (sp_bsg->ctx.type) { | 998 | switch (sp_bsg->type) { |
1009 | case SRB_ELS_CMD_RPT: | 999 | case SRB_ELS_CMD_RPT: |
1010 | case SRB_ELS_CMD_HST: | 1000 | case SRB_ELS_CMD_HST: |
1011 | type = "els"; | 1001 | type = "els"; |
@@ -1016,7 +1006,7 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req, | |||
1016 | default: | 1006 | default: |
1017 | qla_printk(KERN_WARNING, ha, | 1007 | qla_printk(KERN_WARNING, ha, |
1018 | "%s: Unrecognized SRB: (%p) type=%d.\n", func, sp, | 1008 | "%s: Unrecognized SRB: (%p) type=%d.\n", func, sp, |
1019 | sp_bsg->ctx.type); | 1009 | sp_bsg->type); |
1020 | return; | 1010 | return; |
1021 | } | 1011 | } |
1022 | 1012 | ||
@@ -1070,8 +1060,8 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req, | |||
1070 | dma_unmap_sg(&ha->pdev->dev, | 1060 | dma_unmap_sg(&ha->pdev->dev, |
1071 | bsg_job->reply_payload.sg_list, | 1061 | bsg_job->reply_payload.sg_list, |
1072 | bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE); | 1062 | bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE); |
1073 | if ((sp_bsg->ctx.type == SRB_ELS_CMD_HST) || | 1063 | if ((sp_bsg->type == SRB_ELS_CMD_HST) || |
1074 | (sp_bsg->ctx.type == SRB_CT_CMD)) | 1064 | (sp_bsg->type == SRB_CT_CMD)) |
1075 | kfree(sp->fcport); | 1065 | kfree(sp->fcport); |
1076 | kfree(sp->ctx); | 1066 | kfree(sp->ctx); |
1077 | mempool_free(sp, ha->srb_mempool); | 1067 | mempool_free(sp, ha->srb_mempool); |
@@ -1084,37 +1074,26 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req, | |||
1084 | { | 1074 | { |
1085 | const char func[] = "LOGIO-IOCB"; | 1075 | const char func[] = "LOGIO-IOCB"; |
1086 | const char *type; | 1076 | const char *type; |
1087 | struct qla_hw_data *ha = vha->hw; | ||
1088 | fc_port_t *fcport; | 1077 | fc_port_t *fcport; |
1089 | srb_t *sp; | 1078 | srb_t *sp; |
1090 | struct srb_logio *lio; | 1079 | struct srb_iocb *lio; |
1091 | uint16_t data[2]; | 1080 | struct srb_ctx *ctx; |
1081 | uint16_t *data; | ||
1092 | uint32_t iop[2]; | 1082 | uint32_t iop[2]; |
1093 | 1083 | ||
1094 | sp = qla2x00_get_sp_from_handle(vha, func, req, logio); | 1084 | sp = qla2x00_get_sp_from_handle(vha, func, req, logio); |
1095 | if (!sp) | 1085 | if (!sp) |
1096 | return; | 1086 | return; |
1097 | 1087 | ||
1098 | type = NULL; | 1088 | ctx = sp->ctx; |
1099 | lio = sp->ctx; | 1089 | lio = ctx->u.iocb_cmd; |
1100 | switch (lio->ctx.type) { | 1090 | type = ctx->name; |
1101 | case SRB_LOGIN_CMD: | ||
1102 | type = "login"; | ||
1103 | break; | ||
1104 | case SRB_LOGOUT_CMD: | ||
1105 | type = "logout"; | ||
1106 | break; | ||
1107 | default: | ||
1108 | qla_printk(KERN_WARNING, ha, | ||
1109 | "%s: Unrecognized SRB: (%p) type=%d.\n", func, sp, | ||
1110 | lio->ctx.type); | ||
1111 | return; | ||
1112 | } | ||
1113 | |||
1114 | del_timer(&lio->ctx.timer); | ||
1115 | fcport = sp->fcport; | 1091 | fcport = sp->fcport; |
1092 | data = lio->u.logio.data; | ||
1116 | 1093 | ||
1117 | data[0] = data[1] = 0; | 1094 | data[0] = MBS_COMMAND_ERROR; |
1095 | data[1] = lio->u.logio.flags & SRB_LOGIN_RETRIED ? | ||
1096 | QLA_LOGIO_LOGIN_RETRIED : 0; | ||
1118 | if (logio->entry_status) { | 1097 | if (logio->entry_status) { |
1119 | DEBUG2(printk(KERN_WARNING | 1098 | DEBUG2(printk(KERN_WARNING |
1120 | "scsi(%ld:%x): Async-%s error entry - entry-status=%x.\n", | 1099 | "scsi(%ld:%x): Async-%s error entry - entry-status=%x.\n", |
@@ -1122,10 +1101,7 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req, | |||
1122 | logio->entry_status)); | 1101 | logio->entry_status)); |
1123 | DEBUG2(qla2x00_dump_buffer((uint8_t *)logio, sizeof(*logio))); | 1102 | DEBUG2(qla2x00_dump_buffer((uint8_t *)logio, sizeof(*logio))); |
1124 | 1103 | ||
1125 | data[0] = MBS_COMMAND_ERROR; | 1104 | goto logio_done; |
1126 | data[1] = lio->flags & SRB_LOGIN_RETRIED ? | ||
1127 | QLA_LOGIO_LOGIN_RETRIED: 0; | ||
1128 | goto done_post_logio_done_work; | ||
1129 | } | 1105 | } |
1130 | 1106 | ||
1131 | if (le16_to_cpu(logio->comp_status) == CS_COMPLETE) { | 1107 | if (le16_to_cpu(logio->comp_status) == CS_COMPLETE) { |
@@ -1135,8 +1111,8 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req, | |||
1135 | le32_to_cpu(logio->io_parameter[0]))); | 1111 | le32_to_cpu(logio->io_parameter[0]))); |
1136 | 1112 | ||
1137 | data[0] = MBS_COMMAND_COMPLETE; | 1113 | data[0] = MBS_COMMAND_COMPLETE; |
1138 | if (lio->ctx.type == SRB_LOGOUT_CMD) | 1114 | if (ctx->type != SRB_LOGIN_CMD) |
1139 | goto done_post_logio_done_work; | 1115 | goto logio_done; |
1140 | 1116 | ||
1141 | iop[0] = le32_to_cpu(logio->io_parameter[0]); | 1117 | iop[0] = le32_to_cpu(logio->io_parameter[0]); |
1142 | if (iop[0] & BIT_4) { | 1118 | if (iop[0] & BIT_4) { |
@@ -1151,7 +1127,7 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req, | |||
1151 | if (logio->io_parameter[9] || logio->io_parameter[10]) | 1127 | if (logio->io_parameter[9] || logio->io_parameter[10]) |
1152 | fcport->supported_classes |= FC_COS_CLASS3; | 1128 | fcport->supported_classes |= FC_COS_CLASS3; |
1153 | 1129 | ||
1154 | goto done_post_logio_done_work; | 1130 | goto logio_done; |
1155 | } | 1131 | } |
1156 | 1132 | ||
1157 | iop[0] = le32_to_cpu(logio->io_parameter[0]); | 1133 | iop[0] = le32_to_cpu(logio->io_parameter[0]); |
@@ -1172,8 +1148,6 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req, | |||
1172 | /* Fall through. */ | 1148 | /* Fall through. */ |
1173 | default: | 1149 | default: |
1174 | data[0] = MBS_COMMAND_ERROR; | 1150 | data[0] = MBS_COMMAND_ERROR; |
1175 | data[1] = lio->flags & SRB_LOGIN_RETRIED ? | ||
1176 | QLA_LOGIO_LOGIN_RETRIED: 0; | ||
1177 | break; | 1151 | break; |
1178 | } | 1152 | } |
1179 | 1153 | ||
@@ -1184,12 +1158,101 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req, | |||
1184 | le32_to_cpu(logio->io_parameter[0]), | 1158 | le32_to_cpu(logio->io_parameter[0]), |
1185 | le32_to_cpu(logio->io_parameter[1]))); | 1159 | le32_to_cpu(logio->io_parameter[1]))); |
1186 | 1160 | ||
1187 | done_post_logio_done_work: | 1161 | logio_done: |
1188 | lio->ctx.type == SRB_LOGIN_CMD ? | 1162 | lio->done(sp); |
1189 | qla2x00_post_async_login_done_work(fcport->vha, fcport, data): | 1163 | } |
1190 | qla2x00_post_async_logout_done_work(fcport->vha, fcport, data); | ||
1191 | 1164 | ||
1192 | lio->ctx.free(sp); | 1165 | static void |
1166 | qla24xx_tm_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, | ||
1167 | struct tsk_mgmt_entry *tsk) | ||
1168 | { | ||
1169 | const char func[] = "TMF-IOCB"; | ||
1170 | const char *type; | ||
1171 | fc_port_t *fcport; | ||
1172 | srb_t *sp; | ||
1173 | struct srb_iocb *iocb; | ||
1174 | struct srb_ctx *ctx; | ||
1175 | struct sts_entry_24xx *sts = (struct sts_entry_24xx *)tsk; | ||
1176 | int error = 1; | ||
1177 | |||
1178 | sp = qla2x00_get_sp_from_handle(vha, func, req, tsk); | ||
1179 | if (!sp) | ||
1180 | return; | ||
1181 | |||
1182 | ctx = sp->ctx; | ||
1183 | iocb = ctx->u.iocb_cmd; | ||
1184 | type = ctx->name; | ||
1185 | fcport = sp->fcport; | ||
1186 | |||
1187 | if (sts->entry_status) { | ||
1188 | DEBUG2(printk(KERN_WARNING | ||
1189 | "scsi(%ld:%x): Async-%s error - entry-status(%x).\n", | ||
1190 | fcport->vha->host_no, sp->handle, type, | ||
1191 | sts->entry_status)); | ||
1192 | } else if (sts->comp_status != __constant_cpu_to_le16(CS_COMPLETE)) { | ||
1193 | DEBUG2(printk(KERN_WARNING | ||
1194 | "scsi(%ld:%x): Async-%s error - completion status(%x).\n", | ||
1195 | fcport->vha->host_no, sp->handle, type, | ||
1196 | sts->comp_status)); | ||
1197 | } else if (!(le16_to_cpu(sts->scsi_status) & | ||
1198 | SS_RESPONSE_INFO_LEN_VALID)) { | ||
1199 | DEBUG2(printk(KERN_WARNING | ||
1200 | "scsi(%ld:%x): Async-%s error - no response info(%x).\n", | ||
1201 | fcport->vha->host_no, sp->handle, type, | ||
1202 | sts->scsi_status)); | ||
1203 | } else if (le32_to_cpu(sts->rsp_data_len) < 4) { | ||
1204 | DEBUG2(printk(KERN_WARNING | ||
1205 | "scsi(%ld:%x): Async-%s error - not enough response(%d).\n", | ||
1206 | fcport->vha->host_no, sp->handle, type, | ||
1207 | sts->rsp_data_len)); | ||
1208 | } else if (sts->data[3]) { | ||
1209 | DEBUG2(printk(KERN_WARNING | ||
1210 | "scsi(%ld:%x): Async-%s error - response(%x).\n", | ||
1211 | fcport->vha->host_no, sp->handle, type, | ||
1212 | sts->data[3])); | ||
1213 | } else { | ||
1214 | error = 0; | ||
1215 | } | ||
1216 | |||
1217 | if (error) { | ||
1218 | iocb->u.tmf.data = error; | ||
1219 | DEBUG2(qla2x00_dump_buffer((uint8_t *)sts, sizeof(*sts))); | ||
1220 | } | ||
1221 | |||
1222 | iocb->done(sp); | ||
1223 | } | ||
1224 | |||
1225 | static void | ||
1226 | qla24xx_marker_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, | ||
1227 | struct mrk_entry_24xx *mrk) | ||
1228 | { | ||
1229 | const char func[] = "MRK-IOCB"; | ||
1230 | const char *type; | ||
1231 | fc_port_t *fcport; | ||
1232 | srb_t *sp; | ||
1233 | struct srb_iocb *iocb; | ||
1234 | struct srb_ctx *ctx; | ||
1235 | struct sts_entry_24xx *sts = (struct sts_entry_24xx *)mrk; | ||
1236 | |||
1237 | sp = qla2x00_get_sp_from_handle(vha, func, req, mrk); | ||
1238 | if (!sp) | ||
1239 | return; | ||
1240 | |||
1241 | ctx = sp->ctx; | ||
1242 | iocb = ctx->u.iocb_cmd; | ||
1243 | type = ctx->name; | ||
1244 | fcport = sp->fcport; | ||
1245 | |||
1246 | if (sts->entry_status) { | ||
1247 | iocb->u.marker.data = 1; | ||
1248 | DEBUG2(printk(KERN_WARNING | ||
1249 | "scsi(%ld:%x): Async-%s error entry - entry-status=%x.\n", | ||
1250 | fcport->vha->host_no, sp->handle, type, | ||
1251 | sts->entry_status)); | ||
1252 | DEBUG2(qla2x00_dump_buffer((uint8_t *)mrk, sizeof(*sts))); | ||
1253 | } | ||
1254 | |||
1255 | iocb->done(sp); | ||
1193 | } | 1256 | } |
1194 | 1257 | ||
1195 | /** | 1258 | /** |
@@ -1256,6 +1319,7 @@ qla2x00_process_response_queue(struct rsp_que *rsp) | |||
1256 | case MBX_IOCB_TYPE: | 1319 | case MBX_IOCB_TYPE: |
1257 | qla2x00_mbx_iocb_entry(vha, rsp->req, | 1320 | qla2x00_mbx_iocb_entry(vha, rsp->req, |
1258 | (struct mbx_entry *)pkt); | 1321 | (struct mbx_entry *)pkt); |
1322 | break; | ||
1259 | default: | 1323 | default: |
1260 | /* Type Not Supported. */ | 1324 | /* Type Not Supported. */ |
1261 | DEBUG4(printk(KERN_WARNING | 1325 | DEBUG4(printk(KERN_WARNING |
@@ -1301,6 +1365,78 @@ qla2x00_handle_sense(srb_t *sp, uint8_t *sense_data, uint32_t sense_len, | |||
1301 | DEBUG5(qla2x00_dump_buffer(cp->sense_buffer, sense_len)); | 1365 | DEBUG5(qla2x00_dump_buffer(cp->sense_buffer, sense_len)); |
1302 | } | 1366 | } |
1303 | 1367 | ||
1368 | struct scsi_dif_tuple { | ||
1369 | __be16 guard; /* Checksum */ | ||
1370 | __be16 app_tag; /* APPL identifer */ | ||
1371 | __be32 ref_tag; /* Target LBA or indirect LBA */ | ||
1372 | }; | ||
1373 | |||
1374 | /* | ||
1375 | * Checks the guard or meta-data for the type of error | ||
1376 | * detected by the HBA. In case of errors, we set the | ||
1377 | * ASC/ASCQ fields in the sense buffer with ILLEGAL_REQUEST | ||
1378 | * to indicate to the kernel that the HBA detected error. | ||
1379 | */ | ||
1380 | static inline void | ||
1381 | qla2x00_handle_dif_error(srb_t *sp, struct sts_entry_24xx *sts24) | ||
1382 | { | ||
1383 | struct scsi_cmnd *cmd = sp->cmd; | ||
1384 | struct scsi_dif_tuple *ep = | ||
1385 | (struct scsi_dif_tuple *)&sts24->data[20]; | ||
1386 | struct scsi_dif_tuple *ap = | ||
1387 | (struct scsi_dif_tuple *)&sts24->data[12]; | ||
1388 | uint32_t e_ref_tag, a_ref_tag; | ||
1389 | uint16_t e_app_tag, a_app_tag; | ||
1390 | uint16_t e_guard, a_guard; | ||
1391 | |||
1392 | e_ref_tag = be32_to_cpu(ep->ref_tag); | ||
1393 | a_ref_tag = be32_to_cpu(ap->ref_tag); | ||
1394 | e_app_tag = be16_to_cpu(ep->app_tag); | ||
1395 | a_app_tag = be16_to_cpu(ap->app_tag); | ||
1396 | e_guard = be16_to_cpu(ep->guard); | ||
1397 | a_guard = be16_to_cpu(ap->guard); | ||
1398 | |||
1399 | DEBUG18(printk(KERN_DEBUG | ||
1400 | "%s(): iocb(s) %p Returned STATUS\n", __func__, sts24)); | ||
1401 | |||
1402 | DEBUG18(printk(KERN_ERR "DIF ERROR in cmd 0x%x lba 0x%llx act ref" | ||
1403 | " tag=0x%x, exp ref_tag=0x%x, act app tag=0x%x, exp app" | ||
1404 | " tag=0x%x, act guard=0x%x, exp guard=0x%x\n", | ||
1405 | cmd->cmnd[0], (u64)scsi_get_lba(cmd), a_ref_tag, e_ref_tag, | ||
1406 | a_app_tag, e_app_tag, a_guard, e_guard)); | ||
1407 | |||
1408 | |||
1409 | /* check guard */ | ||
1410 | if (e_guard != a_guard) { | ||
1411 | scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST, | ||
1412 | 0x10, 0x1); | ||
1413 | set_driver_byte(cmd, DRIVER_SENSE); | ||
1414 | set_host_byte(cmd, DID_ABORT); | ||
1415 | cmd->result |= SAM_STAT_CHECK_CONDITION << 1; | ||
1416 | return; | ||
1417 | } | ||
1418 | |||
1419 | /* check appl tag */ | ||
1420 | if (e_app_tag != a_app_tag) { | ||
1421 | scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST, | ||
1422 | 0x10, 0x2); | ||
1423 | set_driver_byte(cmd, DRIVER_SENSE); | ||
1424 | set_host_byte(cmd, DID_ABORT); | ||
1425 | cmd->result |= SAM_STAT_CHECK_CONDITION << 1; | ||
1426 | return; | ||
1427 | } | ||
1428 | |||
1429 | /* check ref tag */ | ||
1430 | if (e_ref_tag != a_ref_tag) { | ||
1431 | scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST, | ||
1432 | 0x10, 0x3); | ||
1433 | set_driver_byte(cmd, DRIVER_SENSE); | ||
1434 | set_host_byte(cmd, DID_ABORT); | ||
1435 | cmd->result |= SAM_STAT_CHECK_CONDITION << 1; | ||
1436 | return; | ||
1437 | } | ||
1438 | } | ||
1439 | |||
1304 | /** | 1440 | /** |
1305 | * qla2x00_status_entry() - Process a Status IOCB entry. | 1441 | * qla2x00_status_entry() - Process a Status IOCB entry. |
1306 | * @ha: SCSI driver HA context | 1442 | * @ha: SCSI driver HA context |
@@ -1316,6 +1452,7 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) | |||
1316 | struct sts_entry_24xx *sts24; | 1452 | struct sts_entry_24xx *sts24; |
1317 | uint16_t comp_status; | 1453 | uint16_t comp_status; |
1318 | uint16_t scsi_status; | 1454 | uint16_t scsi_status; |
1455 | uint16_t ox_id; | ||
1319 | uint8_t lscsi_status; | 1456 | uint8_t lscsi_status; |
1320 | int32_t resid; | 1457 | int32_t resid; |
1321 | uint32_t sense_len, rsp_info_len, resid_len, fw_resid_len; | 1458 | uint32_t sense_len, rsp_info_len, resid_len, fw_resid_len; |
@@ -1324,6 +1461,7 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) | |||
1324 | uint32_t handle; | 1461 | uint32_t handle; |
1325 | uint16_t que; | 1462 | uint16_t que; |
1326 | struct req_que *req; | 1463 | struct req_que *req; |
1464 | int logit = 1; | ||
1327 | 1465 | ||
1328 | sts = (sts_entry_t *) pkt; | 1466 | sts = (sts_entry_t *) pkt; |
1329 | sts24 = (struct sts_entry_24xx *) pkt; | 1467 | sts24 = (struct sts_entry_24xx *) pkt; |
@@ -1337,6 +1475,7 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) | |||
1337 | handle = (uint32_t) LSW(sts->handle); | 1475 | handle = (uint32_t) LSW(sts->handle); |
1338 | que = MSW(sts->handle); | 1476 | que = MSW(sts->handle); |
1339 | req = ha->req_q_map[que]; | 1477 | req = ha->req_q_map[que]; |
1478 | |||
1340 | /* Fast path completion. */ | 1479 | /* Fast path completion. */ |
1341 | if (comp_status == CS_COMPLETE && scsi_status == 0) { | 1480 | if (comp_status == CS_COMPLETE && scsi_status == 0) { |
1342 | qla2x00_process_completed_request(vha, req, handle); | 1481 | qla2x00_process_completed_request(vha, req, handle); |
@@ -1352,9 +1491,9 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) | |||
1352 | sp = NULL; | 1491 | sp = NULL; |
1353 | 1492 | ||
1354 | if (sp == NULL) { | 1493 | if (sp == NULL) { |
1355 | DEBUG2(printk("scsi(%ld): Status Entry invalid handle.\n", | 1494 | qla_printk(KERN_WARNING, ha, |
1356 | vha->host_no)); | 1495 | "scsi(%ld): Invalid status handle (0x%x).\n", vha->host_no, |
1357 | qla_printk(KERN_WARNING, ha, "Status Entry invalid handle.\n"); | 1496 | sts->handle); |
1358 | 1497 | ||
1359 | set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); | 1498 | set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); |
1360 | qla2xxx_wake_dpc(vha); | 1499 | qla2xxx_wake_dpc(vha); |
@@ -1362,10 +1501,9 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) | |||
1362 | } | 1501 | } |
1363 | cp = sp->cmd; | 1502 | cp = sp->cmd; |
1364 | if (cp == NULL) { | 1503 | if (cp == NULL) { |
1365 | DEBUG2(printk("scsi(%ld): Command already returned back to OS " | ||
1366 | "pkt->handle=%d sp=%p.\n", vha->host_no, handle, sp)); | ||
1367 | qla_printk(KERN_WARNING, ha, | 1504 | qla_printk(KERN_WARNING, ha, |
1368 | "Command is NULL: already returned to OS (sp=%p)\n", sp); | 1505 | "scsi(%ld): Command already returned (0x%x/%p).\n", |
1506 | vha->host_no, sts->handle, sp); | ||
1369 | 1507 | ||
1370 | return; | 1508 | return; |
1371 | } | 1509 | } |
@@ -1374,6 +1512,7 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) | |||
1374 | 1512 | ||
1375 | fcport = sp->fcport; | 1513 | fcport = sp->fcport; |
1376 | 1514 | ||
1515 | ox_id = 0; | ||
1377 | sense_len = rsp_info_len = resid_len = fw_resid_len = 0; | 1516 | sense_len = rsp_info_len = resid_len = fw_resid_len = 0; |
1378 | if (IS_FWI2_CAPABLE(ha)) { | 1517 | if (IS_FWI2_CAPABLE(ha)) { |
1379 | if (scsi_status & SS_SENSE_LEN_VALID) | 1518 | if (scsi_status & SS_SENSE_LEN_VALID) |
@@ -1387,6 +1526,7 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) | |||
1387 | rsp_info = sts24->data; | 1526 | rsp_info = sts24->data; |
1388 | sense_data = sts24->data; | 1527 | sense_data = sts24->data; |
1389 | host_to_fcp_swap(sts24->data, sizeof(sts24->data)); | 1528 | host_to_fcp_swap(sts24->data, sizeof(sts24->data)); |
1529 | ox_id = le16_to_cpu(sts24->ox_id); | ||
1390 | } else { | 1530 | } else { |
1391 | if (scsi_status & SS_SENSE_LEN_VALID) | 1531 | if (scsi_status & SS_SENSE_LEN_VALID) |
1392 | sense_len = le16_to_cpu(sts->req_sense_length); | 1532 | sense_len = le16_to_cpu(sts->req_sense_length); |
@@ -1403,17 +1543,13 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) | |||
1403 | if (IS_FWI2_CAPABLE(ha)) | 1543 | if (IS_FWI2_CAPABLE(ha)) |
1404 | sense_data += rsp_info_len; | 1544 | sense_data += rsp_info_len; |
1405 | if (rsp_info_len > 3 && rsp_info[3]) { | 1545 | if (rsp_info_len > 3 && rsp_info[3]) { |
1406 | DEBUG2(printk("scsi(%ld:%d:%d:%d) FCP I/O protocol " | 1546 | DEBUG2(qla_printk(KERN_INFO, ha, |
1407 | "failure (%x/%02x%02x%02x%02x%02x%02x%02x%02x)..." | 1547 | "scsi(%ld:%d:%d): FCP I/O protocol failure " |
1408 | "retrying command\n", vha->host_no, | 1548 | "(0x%x/0x%x).\n", vha->host_no, cp->device->id, |
1409 | cp->device->channel, cp->device->id, | 1549 | cp->device->lun, rsp_info_len, rsp_info[3])); |
1410 | cp->device->lun, rsp_info_len, rsp_info[0], | ||
1411 | rsp_info[1], rsp_info[2], rsp_info[3], rsp_info[4], | ||
1412 | rsp_info[5], rsp_info[6], rsp_info[7])); | ||
1413 | 1550 | ||
1414 | cp->result = DID_BUS_BUSY << 16; | 1551 | cp->result = DID_BUS_BUSY << 16; |
1415 | qla2x00_sp_compl(ha, sp); | 1552 | goto out; |
1416 | return; | ||
1417 | } | 1553 | } |
1418 | } | 1554 | } |
1419 | 1555 | ||
@@ -1440,12 +1576,10 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) | |||
1440 | ((unsigned)(scsi_bufflen(cp) - resid) < | 1576 | ((unsigned)(scsi_bufflen(cp) - resid) < |
1441 | cp->underflow)) { | 1577 | cp->underflow)) { |
1442 | qla_printk(KERN_INFO, ha, | 1578 | qla_printk(KERN_INFO, ha, |
1443 | "scsi(%ld:%d:%d:%d): Mid-layer underflow " | 1579 | "scsi(%ld:%d:%d): Mid-layer underflow " |
1444 | "detected (%x of %x bytes)...returning " | 1580 | "detected (0x%x of 0x%x bytes).\n", |
1445 | "error status.\n", vha->host_no, | 1581 | vha->host_no, cp->device->id, |
1446 | cp->device->channel, cp->device->id, | 1582 | cp->device->lun, resid, scsi_bufflen(cp)); |
1447 | cp->device->lun, resid, | ||
1448 | scsi_bufflen(cp)); | ||
1449 | 1583 | ||
1450 | cp->result = DID_ERROR << 16; | 1584 | cp->result = DID_ERROR << 16; |
1451 | break; | 1585 | break; |
@@ -1454,12 +1588,12 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) | |||
1454 | cp->result = DID_OK << 16 | lscsi_status; | 1588 | cp->result = DID_OK << 16 | lscsi_status; |
1455 | 1589 | ||
1456 | if (lscsi_status == SAM_STAT_TASK_SET_FULL) { | 1590 | if (lscsi_status == SAM_STAT_TASK_SET_FULL) { |
1457 | DEBUG2(printk(KERN_INFO | 1591 | DEBUG2(qla_printk(KERN_INFO, ha, |
1458 | "scsi(%ld): QUEUE FULL status detected " | 1592 | "scsi(%ld:%d:%d) QUEUE FULL detected.\n", |
1459 | "0x%x-0x%x.\n", vha->host_no, comp_status, | 1593 | vha->host_no, cp->device->id, cp->device->lun)); |
1460 | scsi_status)); | ||
1461 | break; | 1594 | break; |
1462 | } | 1595 | } |
1596 | logit = 0; | ||
1463 | if (lscsi_status != SS_CHECK_CONDITION) | 1597 | if (lscsi_status != SS_CHECK_CONDITION) |
1464 | break; | 1598 | break; |
1465 | 1599 | ||
@@ -1471,23 +1605,14 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) | |||
1471 | break; | 1605 | break; |
1472 | 1606 | ||
1473 | case CS_DATA_UNDERRUN: | 1607 | case CS_DATA_UNDERRUN: |
1474 | DEBUG2(printk(KERN_INFO | ||
1475 | "scsi(%ld:%d:%d) UNDERRUN status detected 0x%x-0x%x. " | ||
1476 | "resid=0x%x fw_resid=0x%x cdb=0x%x os_underflow=0x%x\n", | ||
1477 | vha->host_no, cp->device->id, cp->device->lun, comp_status, | ||
1478 | scsi_status, resid_len, fw_resid_len, cp->cmnd[0], | ||
1479 | cp->underflow)); | ||
1480 | |||
1481 | /* Use F/W calculated residual length. */ | 1608 | /* Use F/W calculated residual length. */ |
1482 | resid = IS_FWI2_CAPABLE(ha) ? fw_resid_len : resid_len; | 1609 | resid = IS_FWI2_CAPABLE(ha) ? fw_resid_len : resid_len; |
1483 | scsi_set_resid(cp, resid); | 1610 | scsi_set_resid(cp, resid); |
1484 | if (scsi_status & SS_RESIDUAL_UNDER) { | 1611 | if (scsi_status & SS_RESIDUAL_UNDER) { |
1485 | if (IS_FWI2_CAPABLE(ha) && fw_resid_len != resid_len) { | 1612 | if (IS_FWI2_CAPABLE(ha) && fw_resid_len != resid_len) { |
1486 | DEBUG2(printk( | 1613 | DEBUG2(qla_printk(KERN_INFO, ha, |
1487 | "scsi(%ld:%d:%d:%d) Dropped frame(s) " | 1614 | "scsi(%ld:%d:%d) Dropped frame(s) detected " |
1488 | "detected (%x of %x bytes)...residual " | 1615 | "(0x%x of 0x%x bytes).\n", vha->host_no, |
1489 | "length mismatch...retrying command.\n", | ||
1490 | vha->host_no, cp->device->channel, | ||
1491 | cp->device->id, cp->device->lun, resid, | 1616 | cp->device->id, cp->device->lun, resid, |
1492 | scsi_bufflen(cp))); | 1617 | scsi_bufflen(cp))); |
1493 | 1618 | ||
@@ -1499,21 +1624,18 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) | |||
1499 | ((unsigned)(scsi_bufflen(cp) - resid) < | 1624 | ((unsigned)(scsi_bufflen(cp) - resid) < |
1500 | cp->underflow)) { | 1625 | cp->underflow)) { |
1501 | qla_printk(KERN_INFO, ha, | 1626 | qla_printk(KERN_INFO, ha, |
1502 | "scsi(%ld:%d:%d:%d): Mid-layer underflow " | 1627 | "scsi(%ld:%d:%d): Mid-layer underflow " |
1503 | "detected (%x of %x bytes)...returning " | 1628 | "detected (0x%x of 0x%x bytes).\n", |
1504 | "error status.\n", vha->host_no, | 1629 | vha->host_no, cp->device->id, |
1505 | cp->device->channel, cp->device->id, | ||
1506 | cp->device->lun, resid, scsi_bufflen(cp)); | 1630 | cp->device->lun, resid, scsi_bufflen(cp)); |
1507 | 1631 | ||
1508 | cp->result = DID_ERROR << 16; | 1632 | cp->result = DID_ERROR << 16; |
1509 | break; | 1633 | break; |
1510 | } | 1634 | } |
1511 | } else if (!lscsi_status) { | 1635 | } else if (!lscsi_status) { |
1512 | DEBUG2(printk( | 1636 | DEBUG2(qla_printk(KERN_INFO, ha, |
1513 | "scsi(%ld:%d:%d:%d) Dropped frame(s) detected " | 1637 | "scsi(%ld:%d:%d) Dropped frame(s) detected (0x%x " |
1514 | "(%x of %x bytes)...firmware reported underrun..." | 1638 | "of 0x%x bytes).\n", vha->host_no, cp->device->id, |
1515 | "retrying command.\n", vha->host_no, | ||
1516 | cp->device->channel, cp->device->id, | ||
1517 | cp->device->lun, resid, scsi_bufflen(cp))); | 1639 | cp->device->lun, resid, scsi_bufflen(cp))); |
1518 | 1640 | ||
1519 | cp->result = DID_ERROR << 16; | 1641 | cp->result = DID_ERROR << 16; |
@@ -1521,6 +1643,7 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) | |||
1521 | } | 1643 | } |
1522 | 1644 | ||
1523 | cp->result = DID_OK << 16 | lscsi_status; | 1645 | cp->result = DID_OK << 16 | lscsi_status; |
1646 | logit = 0; | ||
1524 | 1647 | ||
1525 | /* | 1648 | /* |
1526 | * Check to see if SCSI Status is non zero. If so report SCSI | 1649 | * Check to see if SCSI Status is non zero. If so report SCSI |
@@ -1528,10 +1651,11 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) | |||
1528 | */ | 1651 | */ |
1529 | if (lscsi_status != 0) { | 1652 | if (lscsi_status != 0) { |
1530 | if (lscsi_status == SAM_STAT_TASK_SET_FULL) { | 1653 | if (lscsi_status == SAM_STAT_TASK_SET_FULL) { |
1531 | DEBUG2(printk(KERN_INFO | 1654 | DEBUG2(qla_printk(KERN_INFO, ha, |
1532 | "scsi(%ld): QUEUE FULL status detected " | 1655 | "scsi(%ld:%d:%d) QUEUE FULL detected.\n", |
1533 | "0x%x-0x%x.\n", vha->host_no, comp_status, | 1656 | vha->host_no, cp->device->id, |
1534 | scsi_status)); | 1657 | cp->device->lun)); |
1658 | logit = 1; | ||
1535 | break; | 1659 | break; |
1536 | } | 1660 | } |
1537 | if (lscsi_status != SS_CHECK_CONDITION) | 1661 | if (lscsi_status != SS_CHECK_CONDITION) |
@@ -1545,109 +1669,60 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) | |||
1545 | } | 1669 | } |
1546 | break; | 1670 | break; |
1547 | 1671 | ||
1548 | case CS_DATA_OVERRUN: | ||
1549 | DEBUG2(printk(KERN_INFO | ||
1550 | "scsi(%ld:%d:%d): OVERRUN status detected 0x%x-0x%x\n", | ||
1551 | vha->host_no, cp->device->id, cp->device->lun, comp_status, | ||
1552 | scsi_status)); | ||
1553 | DEBUG2(printk(KERN_INFO | ||
1554 | "CDB: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", | ||
1555 | cp->cmnd[0], cp->cmnd[1], cp->cmnd[2], cp->cmnd[3], | ||
1556 | cp->cmnd[4], cp->cmnd[5])); | ||
1557 | DEBUG2(printk(KERN_INFO | ||
1558 | "PID=0x%lx req=0x%x xtra=0x%x -- returning DID_ERROR " | ||
1559 | "status!\n", | ||
1560 | cp->serial_number, scsi_bufflen(cp), resid_len)); | ||
1561 | |||
1562 | cp->result = DID_ERROR << 16; | ||
1563 | break; | ||
1564 | |||
1565 | case CS_PORT_LOGGED_OUT: | 1672 | case CS_PORT_LOGGED_OUT: |
1566 | case CS_PORT_CONFIG_CHG: | 1673 | case CS_PORT_CONFIG_CHG: |
1567 | case CS_PORT_BUSY: | 1674 | case CS_PORT_BUSY: |
1568 | case CS_INCOMPLETE: | 1675 | case CS_INCOMPLETE: |
1569 | case CS_PORT_UNAVAILABLE: | 1676 | case CS_PORT_UNAVAILABLE: |
1570 | /* | 1677 | case CS_TIMEOUT: |
1571 | * If the port is in Target Down state, return all IOs for this | ||
1572 | * Target with DID_NO_CONNECT ELSE Queue the IOs in the | ||
1573 | * retry_queue. | ||
1574 | */ | ||
1575 | DEBUG2(printk("scsi(%ld:%d:%d): status_entry: Port Down " | ||
1576 | "pid=%ld, compl status=0x%x, port state=0x%x\n", | ||
1577 | vha->host_no, cp->device->id, cp->device->lun, | ||
1578 | cp->serial_number, comp_status, | ||
1579 | atomic_read(&fcport->state))); | ||
1580 | |||
1581 | /* | 1678 | /* |
1582 | * We are going to have the fc class block the rport | 1679 | * We are going to have the fc class block the rport |
1583 | * while we try to recover so instruct the mid layer | 1680 | * while we try to recover so instruct the mid layer |
1584 | * to requeue until the class decides how to handle this. | 1681 | * to requeue until the class decides how to handle this. |
1585 | */ | 1682 | */ |
1586 | cp->result = DID_TRANSPORT_DISRUPTED << 16; | 1683 | cp->result = DID_TRANSPORT_DISRUPTED << 16; |
1684 | |||
1685 | if (comp_status == CS_TIMEOUT) { | ||
1686 | if (IS_FWI2_CAPABLE(ha)) | ||
1687 | break; | ||
1688 | else if ((le16_to_cpu(sts->status_flags) & | ||
1689 | SF_LOGOUT_SENT) == 0) | ||
1690 | break; | ||
1691 | } | ||
1692 | |||
1693 | DEBUG2(qla_printk(KERN_INFO, ha, | ||
1694 | "scsi(%ld:%d:%d) Port down status: port-state=0x%x\n", | ||
1695 | vha->host_no, cp->device->id, cp->device->lun, | ||
1696 | atomic_read(&fcport->state))); | ||
1697 | |||
1587 | if (atomic_read(&fcport->state) == FCS_ONLINE) | 1698 | if (atomic_read(&fcport->state) == FCS_ONLINE) |
1588 | qla2x00_mark_device_lost(fcport->vha, fcport, 1, 1); | 1699 | qla2x00_mark_device_lost(fcport->vha, fcport, 1, 1); |
1589 | break; | 1700 | break; |
1590 | 1701 | ||
1591 | case CS_RESET: | 1702 | case CS_RESET: |
1592 | DEBUG2(printk(KERN_INFO | ||
1593 | "scsi(%ld): RESET status detected 0x%x-0x%x.\n", | ||
1594 | vha->host_no, comp_status, scsi_status)); | ||
1595 | |||
1596 | cp->result = DID_RESET << 16; | ||
1597 | break; | ||
1598 | |||
1599 | case CS_ABORTED: | 1703 | case CS_ABORTED: |
1600 | /* | ||
1601 | * hv2.19.12 - DID_ABORT does not retry the request if we | ||
1602 | * aborted this request then abort otherwise it must be a | ||
1603 | * reset. | ||
1604 | */ | ||
1605 | DEBUG2(printk(KERN_INFO | ||
1606 | "scsi(%ld): ABORT status detected 0x%x-0x%x.\n", | ||
1607 | vha->host_no, comp_status, scsi_status)); | ||
1608 | |||
1609 | cp->result = DID_RESET << 16; | 1704 | cp->result = DID_RESET << 16; |
1610 | break; | 1705 | break; |
1611 | 1706 | ||
1612 | case CS_TIMEOUT: | 1707 | case CS_DIF_ERROR: |
1613 | /* | 1708 | qla2x00_handle_dif_error(sp, sts24); |
1614 | * We are going to have the fc class block the rport | ||
1615 | * while we try to recover so instruct the mid layer | ||
1616 | * to requeue until the class decides how to handle this. | ||
1617 | */ | ||
1618 | cp->result = DID_TRANSPORT_DISRUPTED << 16; | ||
1619 | |||
1620 | if (IS_FWI2_CAPABLE(ha)) { | ||
1621 | DEBUG2(printk(KERN_INFO | ||
1622 | "scsi(%ld:%d:%d:%d): TIMEOUT status detected " | ||
1623 | "0x%x-0x%x\n", vha->host_no, cp->device->channel, | ||
1624 | cp->device->id, cp->device->lun, comp_status, | ||
1625 | scsi_status)); | ||
1626 | break; | ||
1627 | } | ||
1628 | DEBUG2(printk(KERN_INFO | ||
1629 | "scsi(%ld:%d:%d:%d): TIMEOUT status detected 0x%x-0x%x " | ||
1630 | "sflags=%x.\n", vha->host_no, cp->device->channel, | ||
1631 | cp->device->id, cp->device->lun, comp_status, scsi_status, | ||
1632 | le16_to_cpu(sts->status_flags))); | ||
1633 | |||
1634 | /* Check to see if logout occurred. */ | ||
1635 | if ((le16_to_cpu(sts->status_flags) & SF_LOGOUT_SENT)) | ||
1636 | qla2x00_mark_device_lost(fcport->vha, fcport, 1, 1); | ||
1637 | break; | 1709 | break; |
1638 | |||
1639 | default: | 1710 | default: |
1640 | DEBUG3(printk("scsi(%ld): Error detected (unknown status) " | ||
1641 | "0x%x-0x%x.\n", vha->host_no, comp_status, scsi_status)); | ||
1642 | qla_printk(KERN_INFO, ha, | ||
1643 | "Unknown status detected 0x%x-0x%x.\n", | ||
1644 | comp_status, scsi_status); | ||
1645 | |||
1646 | cp->result = DID_ERROR << 16; | 1711 | cp->result = DID_ERROR << 16; |
1647 | break; | 1712 | break; |
1648 | } | 1713 | } |
1649 | 1714 | ||
1650 | /* Place command on done queue. */ | 1715 | out: |
1716 | if (logit) | ||
1717 | DEBUG2(qla_printk(KERN_INFO, ha, | ||
1718 | "scsi(%ld:%d:%d) FCP command status: 0x%x-0x%x (0x%x) " | ||
1719 | "oxid=0x%x ser=0x%lx cdb=%02x%02x%02x len=0x%x " | ||
1720 | "rsp_info=0x%x resid=0x%x fw_resid=0x%x\n", vha->host_no, | ||
1721 | cp->device->id, cp->device->lun, comp_status, scsi_status, | ||
1722 | cp->result, ox_id, cp->serial_number, cp->cmnd[0], | ||
1723 | cp->cmnd[1], cp->cmnd[2], scsi_bufflen(cp), rsp_info_len, | ||
1724 | resid_len, fw_resid_len)); | ||
1725 | |||
1651 | if (rsp->status_srb == NULL) | 1726 | if (rsp->status_srb == NULL) |
1652 | qla2x00_sp_compl(ha, sp); | 1727 | qla2x00_sp_compl(ha, sp); |
1653 | } | 1728 | } |
@@ -1806,6 +1881,7 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha, | |||
1806 | struct rsp_que *rsp) | 1881 | struct rsp_que *rsp) |
1807 | { | 1882 | { |
1808 | struct sts_entry_24xx *pkt; | 1883 | struct sts_entry_24xx *pkt; |
1884 | struct qla_hw_data *ha = vha->hw; | ||
1809 | 1885 | ||
1810 | if (!vha->flags.online) | 1886 | if (!vha->flags.online) |
1811 | return; | 1887 | return; |
@@ -1846,6 +1922,14 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha, | |||
1846 | qla24xx_logio_entry(vha, rsp->req, | 1922 | qla24xx_logio_entry(vha, rsp->req, |
1847 | (struct logio_entry_24xx *)pkt); | 1923 | (struct logio_entry_24xx *)pkt); |
1848 | break; | 1924 | break; |
1925 | case TSK_MGMT_IOCB_TYPE: | ||
1926 | qla24xx_tm_iocb_entry(vha, rsp->req, | ||
1927 | (struct tsk_mgmt_entry *)pkt); | ||
1928 | break; | ||
1929 | case MARKER_TYPE: | ||
1930 | qla24xx_marker_iocb_entry(vha, rsp->req, | ||
1931 | (struct mrk_entry_24xx *)pkt); | ||
1932 | break; | ||
1849 | case CT_IOCB_TYPE: | 1933 | case CT_IOCB_TYPE: |
1850 | qla24xx_els_ct_entry(vha, rsp->req, pkt, CT_IOCB_TYPE); | 1934 | qla24xx_els_ct_entry(vha, rsp->req, pkt, CT_IOCB_TYPE); |
1851 | clear_bit(MBX_INTERRUPT, &vha->hw->mbx_cmd_flags); | 1935 | clear_bit(MBX_INTERRUPT, &vha->hw->mbx_cmd_flags); |
@@ -1866,7 +1950,11 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha, | |||
1866 | } | 1950 | } |
1867 | 1951 | ||
1868 | /* Adjust ring index */ | 1952 | /* Adjust ring index */ |
1869 | WRT_REG_DWORD(rsp->rsp_q_out, rsp->ring_index); | 1953 | if (IS_QLA82XX(ha)) { |
1954 | struct device_reg_82xx __iomem *reg = &ha->iobase->isp82; | ||
1955 | WRT_REG_DWORD(®->rsp_q_out[0], rsp->ring_index); | ||
1956 | } else | ||
1957 | WRT_REG_DWORD(rsp->rsp_q_out, rsp->ring_index); | ||
1870 | } | 1958 | } |
1871 | 1959 | ||
1872 | static void | 1960 | static void |
@@ -2169,6 +2257,11 @@ static struct qla_init_msix_entry msix_entries[3] = { | |||
2169 | { "qla2xxx (multiq)", qla25xx_msix_rsp_q }, | 2257 | { "qla2xxx (multiq)", qla25xx_msix_rsp_q }, |
2170 | }; | 2258 | }; |
2171 | 2259 | ||
2260 | static struct qla_init_msix_entry qla82xx_msix_entries[2] = { | ||
2261 | { "qla2xxx (default)", qla82xx_msix_default }, | ||
2262 | { "qla2xxx (rsp_q)", qla82xx_msix_rsp_q }, | ||
2263 | }; | ||
2264 | |||
2172 | static void | 2265 | static void |
2173 | qla24xx_disable_msix(struct qla_hw_data *ha) | 2266 | qla24xx_disable_msix(struct qla_hw_data *ha) |
2174 | { | 2267 | { |
@@ -2195,7 +2288,7 @@ qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp) | |||
2195 | struct qla_msix_entry *qentry; | 2288 | struct qla_msix_entry *qentry; |
2196 | 2289 | ||
2197 | entries = kzalloc(sizeof(struct msix_entry) * ha->msix_count, | 2290 | entries = kzalloc(sizeof(struct msix_entry) * ha->msix_count, |
2198 | GFP_KERNEL); | 2291 | GFP_KERNEL); |
2199 | if (!entries) | 2292 | if (!entries) |
2200 | return -ENOMEM; | 2293 | return -ENOMEM; |
2201 | 2294 | ||
@@ -2240,8 +2333,15 @@ msix_failed: | |||
2240 | /* Enable MSI-X vectors for the base queue */ | 2333 | /* Enable MSI-X vectors for the base queue */ |
2241 | for (i = 0; i < 2; i++) { | 2334 | for (i = 0; i < 2; i++) { |
2242 | qentry = &ha->msix_entries[i]; | 2335 | qentry = &ha->msix_entries[i]; |
2243 | ret = request_irq(qentry->vector, msix_entries[i].handler, | 2336 | if (IS_QLA82XX(ha)) { |
2244 | 0, msix_entries[i].name, rsp); | 2337 | ret = request_irq(qentry->vector, |
2338 | qla82xx_msix_entries[i].handler, | ||
2339 | 0, qla82xx_msix_entries[i].name, rsp); | ||
2340 | } else { | ||
2341 | ret = request_irq(qentry->vector, | ||
2342 | msix_entries[i].handler, | ||
2343 | 0, msix_entries[i].name, rsp); | ||
2344 | } | ||
2245 | if (ret) { | 2345 | if (ret) { |
2246 | qla_printk(KERN_WARNING, ha, | 2346 | qla_printk(KERN_WARNING, ha, |
2247 | "MSI-X: Unable to register handler -- %x/%d.\n", | 2347 | "MSI-X: Unable to register handler -- %x/%d.\n", |
@@ -2272,7 +2372,7 @@ qla2x00_request_irqs(struct qla_hw_data *ha, struct rsp_que *rsp) | |||
2272 | 2372 | ||
2273 | /* If possible, enable MSI-X. */ | 2373 | /* If possible, enable MSI-X. */ |
2274 | if (!IS_QLA2432(ha) && !IS_QLA2532(ha) && | 2374 | if (!IS_QLA2432(ha) && !IS_QLA2532(ha) && |
2275 | !IS_QLA8432(ha) && !IS_QLA8001(ha)) | 2375 | !IS_QLA8432(ha) && !IS_QLA8XXX_TYPE(ha)) |
2276 | goto skip_msi; | 2376 | goto skip_msi; |
2277 | 2377 | ||
2278 | if (ha->pdev->subsystem_vendor == PCI_VENDOR_ID_HP && | 2378 | if (ha->pdev->subsystem_vendor == PCI_VENDOR_ID_HP && |
@@ -2302,7 +2402,7 @@ qla2x00_request_irqs(struct qla_hw_data *ha, struct rsp_que *rsp) | |||
2302 | goto clear_risc_ints; | 2402 | goto clear_risc_ints; |
2303 | } | 2403 | } |
2304 | qla_printk(KERN_WARNING, ha, | 2404 | qla_printk(KERN_WARNING, ha, |
2305 | "MSI-X: Falling back-to INTa mode -- %d.\n", ret); | 2405 | "MSI-X: Falling back-to MSI mode -- %d.\n", ret); |
2306 | skip_msix: | 2406 | skip_msix: |
2307 | 2407 | ||
2308 | if (!IS_QLA24XX(ha) && !IS_QLA2532(ha) && !IS_QLA8432(ha) && | 2408 | if (!IS_QLA24XX(ha) && !IS_QLA2532(ha) && !IS_QLA8432(ha) && |
@@ -2313,7 +2413,9 @@ skip_msix: | |||
2313 | if (!ret) { | 2413 | if (!ret) { |
2314 | DEBUG2(qla_printk(KERN_INFO, ha, "MSI: Enabled.\n")); | 2414 | DEBUG2(qla_printk(KERN_INFO, ha, "MSI: Enabled.\n")); |
2315 | ha->flags.msi_enabled = 1; | 2415 | ha->flags.msi_enabled = 1; |
2316 | } | 2416 | } else |
2417 | qla_printk(KERN_WARNING, ha, | ||
2418 | "MSI-X: Falling back-to INTa mode -- %d.\n", ret); | ||
2317 | skip_msi: | 2419 | skip_msi: |
2318 | 2420 | ||
2319 | ret = request_irq(ha->pdev->irq, ha->isp_ops->intr_handler, | 2421 | ret = request_irq(ha->pdev->irq, ha->isp_ops->intr_handler, |
@@ -2331,7 +2433,7 @@ clear_risc_ints: | |||
2331 | * FIXME: Noted that 8014s were being dropped during NK testing. | 2433 | * FIXME: Noted that 8014s were being dropped during NK testing. |
2332 | * Timing deltas during MSI-X/INTa transitions? | 2434 | * Timing deltas during MSI-X/INTa transitions? |
2333 | */ | 2435 | */ |
2334 | if (IS_QLA81XX(ha)) | 2436 | if (IS_QLA81XX(ha) || IS_QLA82XX(ha)) |
2335 | goto fail; | 2437 | goto fail; |
2336 | spin_lock_irq(&ha->hardware_lock); | 2438 | spin_lock_irq(&ha->hardware_lock); |
2337 | if (IS_FWI2_CAPABLE(ha)) { | 2439 | if (IS_FWI2_CAPABLE(ha)) { |
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 42eb7ffd5942..f3650d0434ca 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c | |||
@@ -49,6 +49,14 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) | |||
49 | if (ha->pdev->error_state > pci_channel_io_frozen) | 49 | if (ha->pdev->error_state > pci_channel_io_frozen) |
50 | return QLA_FUNCTION_TIMEOUT; | 50 | return QLA_FUNCTION_TIMEOUT; |
51 | 51 | ||
52 | if (vha->device_flags & DFLG_DEV_FAILED) { | ||
53 | DEBUG2_3_11(qla_printk(KERN_WARNING, ha, | ||
54 | "%s(%ld): Device in failed state, " | ||
55 | "timeout MBX Exiting.\n", | ||
56 | __func__, base_vha->host_no)); | ||
57 | return QLA_FUNCTION_TIMEOUT; | ||
58 | } | ||
59 | |||
52 | reg = ha->iobase; | 60 | reg = ha->iobase; |
53 | io_lock_on = base_vha->flags.init_done; | 61 | io_lock_on = base_vha->flags.init_done; |
54 | 62 | ||
@@ -85,7 +93,9 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) | |||
85 | spin_lock_irqsave(&ha->hardware_lock, flags); | 93 | spin_lock_irqsave(&ha->hardware_lock, flags); |
86 | 94 | ||
87 | /* Load mailbox registers. */ | 95 | /* Load mailbox registers. */ |
88 | if (IS_FWI2_CAPABLE(ha)) | 96 | if (IS_QLA82XX(ha)) |
97 | optr = (uint16_t __iomem *)®->isp82.mailbox_in[0]; | ||
98 | else if (IS_FWI2_CAPABLE(ha) && !IS_QLA82XX(ha)) | ||
89 | optr = (uint16_t __iomem *)®->isp24.mailbox0; | 99 | optr = (uint16_t __iomem *)®->isp24.mailbox0; |
90 | else | 100 | else |
91 | optr = (uint16_t __iomem *)MAILBOX_REG(ha, ®->isp, 0); | 101 | optr = (uint16_t __iomem *)MAILBOX_REG(ha, ®->isp, 0); |
@@ -133,7 +143,18 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) | |||
133 | if ((!abort_active && io_lock_on) || IS_NOPOLLING_TYPE(ha)) { | 143 | if ((!abort_active && io_lock_on) || IS_NOPOLLING_TYPE(ha)) { |
134 | set_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags); | 144 | set_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags); |
135 | 145 | ||
136 | if (IS_FWI2_CAPABLE(ha)) | 146 | if (IS_QLA82XX(ha)) { |
147 | if (RD_REG_DWORD(®->isp82.hint) & | ||
148 | HINT_MBX_INT_PENDING) { | ||
149 | spin_unlock_irqrestore(&ha->hardware_lock, | ||
150 | flags); | ||
151 | DEBUG2_3_11(printk(KERN_INFO | ||
152 | "%s(%ld): Pending Mailbox timeout. " | ||
153 | "Exiting.\n", __func__, base_vha->host_no)); | ||
154 | return QLA_FUNCTION_TIMEOUT; | ||
155 | } | ||
156 | WRT_REG_DWORD(®->isp82.hint, HINT_MBX_INT_PENDING); | ||
157 | } else if (IS_FWI2_CAPABLE(ha)) | ||
137 | WRT_REG_DWORD(®->isp24.hccr, HCCRX_SET_HOST_INT); | 158 | WRT_REG_DWORD(®->isp24.hccr, HCCRX_SET_HOST_INT); |
138 | else | 159 | else |
139 | WRT_REG_WORD(®->isp.hccr, HCCR_SET_HOST_INT); | 160 | WRT_REG_WORD(®->isp.hccr, HCCR_SET_HOST_INT); |
@@ -147,7 +168,18 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) | |||
147 | DEBUG3_11(printk("%s(%ld): cmd=%x POLLING MODE.\n", __func__, | 168 | DEBUG3_11(printk("%s(%ld): cmd=%x POLLING MODE.\n", __func__, |
148 | base_vha->host_no, command)); | 169 | base_vha->host_no, command)); |
149 | 170 | ||
150 | if (IS_FWI2_CAPABLE(ha)) | 171 | if (IS_QLA82XX(ha)) { |
172 | if (RD_REG_DWORD(®->isp82.hint) & | ||
173 | HINT_MBX_INT_PENDING) { | ||
174 | spin_unlock_irqrestore(&ha->hardware_lock, | ||
175 | flags); | ||
176 | DEBUG2_3_11(printk(KERN_INFO | ||
177 | "%s(%ld): Pending Mailbox timeout. " | ||
178 | "Exiting.\n", __func__, base_vha->host_no)); | ||
179 | return QLA_FUNCTION_TIMEOUT; | ||
180 | } | ||
181 | WRT_REG_DWORD(®->isp82.hint, HINT_MBX_INT_PENDING); | ||
182 | } else if (IS_FWI2_CAPABLE(ha)) | ||
151 | WRT_REG_DWORD(®->isp24.hccr, HCCRX_SET_HOST_INT); | 183 | WRT_REG_DWORD(®->isp24.hccr, HCCRX_SET_HOST_INT); |
152 | else | 184 | else |
153 | WRT_REG_WORD(®->isp.hccr, HCCR_SET_HOST_INT); | 185 | WRT_REG_WORD(®->isp.hccr, HCCR_SET_HOST_INT); |
@@ -264,7 +296,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) | |||
264 | 296 | ||
265 | set_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags); | 297 | set_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags); |
266 | clear_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags); | 298 | clear_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags); |
267 | if (qla2x00_abort_isp(base_vha)) { | 299 | if (ha->isp_ops->abort_isp(base_vha)) { |
268 | /* Failed. retry later. */ | 300 | /* Failed. retry later. */ |
269 | set_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags); | 301 | set_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags); |
270 | } | 302 | } |
@@ -711,7 +743,7 @@ qla2x00_verify_checksum(scsi_qla_host_t *vha, uint32_t risc_addr) | |||
711 | * Context: | 743 | * Context: |
712 | * Kernel context. | 744 | * Kernel context. |
713 | */ | 745 | */ |
714 | static int | 746 | int |
715 | qla2x00_issue_iocb_timeout(scsi_qla_host_t *vha, void *buffer, | 747 | qla2x00_issue_iocb_timeout(scsi_qla_host_t *vha, void *buffer, |
716 | dma_addr_t phys_addr, size_t size, uint32_t tov) | 748 | dma_addr_t phys_addr, size_t size, uint32_t tov) |
717 | { | 749 | { |
@@ -952,7 +984,7 @@ qla2x00_get_adapter_id(scsi_qla_host_t *vha, uint16_t *id, uint8_t *al_pa, | |||
952 | mcp->mb[9] = vha->vp_idx; | 984 | mcp->mb[9] = vha->vp_idx; |
953 | mcp->out_mb = MBX_9|MBX_0; | 985 | mcp->out_mb = MBX_9|MBX_0; |
954 | mcp->in_mb = MBX_9|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; | 986 | mcp->in_mb = MBX_9|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; |
955 | if (IS_QLA81XX(vha->hw)) | 987 | if (IS_QLA8XXX_TYPE(vha->hw)) |
956 | mcp->in_mb |= MBX_13|MBX_12|MBX_11|MBX_10; | 988 | mcp->in_mb |= MBX_13|MBX_12|MBX_11|MBX_10; |
957 | mcp->tov = MBX_TOV_SECONDS; | 989 | mcp->tov = MBX_TOV_SECONDS; |
958 | mcp->flags = 0; | 990 | mcp->flags = 0; |
@@ -978,7 +1010,7 @@ qla2x00_get_adapter_id(scsi_qla_host_t *vha, uint16_t *id, uint8_t *al_pa, | |||
978 | DEBUG11(printk("qla2x00_get_adapter_id(%ld): done.\n", | 1010 | DEBUG11(printk("qla2x00_get_adapter_id(%ld): done.\n", |
979 | vha->host_no)); | 1011 | vha->host_no)); |
980 | 1012 | ||
981 | if (IS_QLA81XX(vha->hw)) { | 1013 | if (IS_QLA8XXX_TYPE(vha->hw)) { |
982 | vha->fcoe_vlan_id = mcp->mb[9] & 0xfff; | 1014 | vha->fcoe_vlan_id = mcp->mb[9] & 0xfff; |
983 | vha->fcoe_fcf_idx = mcp->mb[10]; | 1015 | vha->fcoe_fcf_idx = mcp->mb[10]; |
984 | vha->fcoe_vn_port_mac[5] = mcp->mb[11] >> 8; | 1016 | vha->fcoe_vn_port_mac[5] = mcp->mb[11] >> 8; |
@@ -1076,6 +1108,10 @@ qla2x00_init_firmware(scsi_qla_host_t *vha, uint16_t size) | |||
1076 | DEBUG11(printk("qla2x00_init_firmware(%ld): entered.\n", | 1108 | DEBUG11(printk("qla2x00_init_firmware(%ld): entered.\n", |
1077 | vha->host_no)); | 1109 | vha->host_no)); |
1078 | 1110 | ||
1111 | if (IS_QLA82XX(ha) && ql2xdbwr) | ||
1112 | qla82xx_wr_32(ha, ha->nxdb_wr_ptr, | ||
1113 | (0x04 | (ha->portnum << 5) | (0 << 8) | (0 << 16))); | ||
1114 | |||
1079 | if (ha->flags.npiv_supported) | 1115 | if (ha->flags.npiv_supported) |
1080 | mcp->mb[0] = MBC_MID_INITIALIZE_FIRMWARE; | 1116 | mcp->mb[0] = MBC_MID_INITIALIZE_FIRMWARE; |
1081 | else | 1117 | else |
@@ -1408,7 +1444,7 @@ qla2x00_lip_reset(scsi_qla_host_t *vha) | |||
1408 | 1444 | ||
1409 | DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no)); | 1445 | DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no)); |
1410 | 1446 | ||
1411 | if (IS_QLA81XX(vha->hw)) { | 1447 | if (IS_QLA8XXX_TYPE(vha->hw)) { |
1412 | /* Logout across all FCFs. */ | 1448 | /* Logout across all FCFs. */ |
1413 | mcp->mb[0] = MBC_LIP_FULL_LOGIN; | 1449 | mcp->mb[0] = MBC_LIP_FULL_LOGIN; |
1414 | mcp->mb[1] = BIT_1; | 1450 | mcp->mb[1] = BIT_1; |
@@ -2428,12 +2464,22 @@ __qla24xx_issue_tmf(char *name, uint32_t type, struct fc_port *fcport, | |||
2428 | int | 2464 | int |
2429 | qla24xx_abort_target(struct fc_port *fcport, unsigned int l, int tag) | 2465 | qla24xx_abort_target(struct fc_port *fcport, unsigned int l, int tag) |
2430 | { | 2466 | { |
2467 | struct qla_hw_data *ha = fcport->vha->hw; | ||
2468 | |||
2469 | if ((ql2xasynctmfenable) && IS_FWI2_CAPABLE(ha)) | ||
2470 | return qla2x00_async_tm_cmd(fcport, TCF_TARGET_RESET, l, tag); | ||
2471 | |||
2431 | return __qla24xx_issue_tmf("Target", TCF_TARGET_RESET, fcport, l, tag); | 2472 | return __qla24xx_issue_tmf("Target", TCF_TARGET_RESET, fcport, l, tag); |
2432 | } | 2473 | } |
2433 | 2474 | ||
2434 | int | 2475 | int |
2435 | qla24xx_lun_reset(struct fc_port *fcport, unsigned int l, int tag) | 2476 | qla24xx_lun_reset(struct fc_port *fcport, unsigned int l, int tag) |
2436 | { | 2477 | { |
2478 | struct qla_hw_data *ha = fcport->vha->hw; | ||
2479 | |||
2480 | if ((ql2xasynctmfenable) && IS_FWI2_CAPABLE(ha)) | ||
2481 | return qla2x00_async_tm_cmd(fcport, TCF_LUN_RESET, l, tag); | ||
2482 | |||
2437 | return __qla24xx_issue_tmf("Lun", TCF_LUN_RESET, fcport, l, tag); | 2483 | return __qla24xx_issue_tmf("Lun", TCF_LUN_RESET, fcport, l, tag); |
2438 | } | 2484 | } |
2439 | 2485 | ||
@@ -2740,6 +2786,48 @@ qla2x00_read_sfp(scsi_qla_host_t *vha, dma_addr_t sfp_dma, uint16_t addr, | |||
2740 | } | 2786 | } |
2741 | 2787 | ||
2742 | int | 2788 | int |
2789 | qla2x00_get_idma_speed(scsi_qla_host_t *vha, uint16_t loop_id, | ||
2790 | uint16_t *port_speed, uint16_t *mb) | ||
2791 | { | ||
2792 | int rval; | ||
2793 | mbx_cmd_t mc; | ||
2794 | mbx_cmd_t *mcp = &mc; | ||
2795 | |||
2796 | if (!IS_IIDMA_CAPABLE(vha->hw)) | ||
2797 | return QLA_FUNCTION_FAILED; | ||
2798 | |||
2799 | DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no)); | ||
2800 | |||
2801 | mcp->mb[0] = MBC_PORT_PARAMS; | ||
2802 | mcp->mb[1] = loop_id; | ||
2803 | mcp->mb[2] = mcp->mb[3] = 0; | ||
2804 | mcp->mb[9] = vha->vp_idx; | ||
2805 | mcp->out_mb = MBX_9|MBX_3|MBX_2|MBX_1|MBX_0; | ||
2806 | mcp->in_mb = MBX_3|MBX_1|MBX_0; | ||
2807 | mcp->tov = MBX_TOV_SECONDS; | ||
2808 | mcp->flags = 0; | ||
2809 | rval = qla2x00_mailbox_command(vha, mcp); | ||
2810 | |||
2811 | /* Return mailbox statuses. */ | ||
2812 | if (mb != NULL) { | ||
2813 | mb[0] = mcp->mb[0]; | ||
2814 | mb[1] = mcp->mb[1]; | ||
2815 | mb[3] = mcp->mb[3]; | ||
2816 | } | ||
2817 | |||
2818 | if (rval != QLA_SUCCESS) { | ||
2819 | DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__, | ||
2820 | vha->host_no, rval)); | ||
2821 | } else { | ||
2822 | DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no)); | ||
2823 | if (port_speed) | ||
2824 | *port_speed = mcp->mb[3]; | ||
2825 | } | ||
2826 | |||
2827 | return rval; | ||
2828 | } | ||
2829 | |||
2830 | int | ||
2743 | qla2x00_set_idma_speed(scsi_qla_host_t *vha, uint16_t loop_id, | 2831 | qla2x00_set_idma_speed(scsi_qla_host_t *vha, uint16_t loop_id, |
2744 | uint16_t port_speed, uint16_t *mb) | 2832 | uint16_t port_speed, uint16_t *mb) |
2745 | { | 2833 | { |
@@ -2755,7 +2843,7 @@ qla2x00_set_idma_speed(scsi_qla_host_t *vha, uint16_t loop_id, | |||
2755 | mcp->mb[0] = MBC_PORT_PARAMS; | 2843 | mcp->mb[0] = MBC_PORT_PARAMS; |
2756 | mcp->mb[1] = loop_id; | 2844 | mcp->mb[1] = loop_id; |
2757 | mcp->mb[2] = BIT_0; | 2845 | mcp->mb[2] = BIT_0; |
2758 | if (IS_QLA81XX(vha->hw)) | 2846 | if (IS_QLA8XXX_TYPE(vha->hw)) |
2759 | mcp->mb[3] = port_speed & (BIT_5|BIT_4|BIT_3|BIT_2|BIT_1|BIT_0); | 2847 | mcp->mb[3] = port_speed & (BIT_5|BIT_4|BIT_3|BIT_2|BIT_1|BIT_0); |
2760 | else | 2848 | else |
2761 | mcp->mb[3] = port_speed & (BIT_2|BIT_1|BIT_0); | 2849 | mcp->mb[3] = port_speed & (BIT_2|BIT_1|BIT_0); |
@@ -3544,7 +3632,7 @@ qla2x00_get_xgmac_stats(scsi_qla_host_t *vha, dma_addr_t stats_dma, | |||
3544 | mbx_cmd_t mc; | 3632 | mbx_cmd_t mc; |
3545 | mbx_cmd_t *mcp = &mc; | 3633 | mbx_cmd_t *mcp = &mc; |
3546 | 3634 | ||
3547 | if (!IS_QLA81XX(vha->hw)) | 3635 | if (!IS_QLA8XXX_TYPE(vha->hw)) |
3548 | return QLA_FUNCTION_FAILED; | 3636 | return QLA_FUNCTION_FAILED; |
3549 | 3637 | ||
3550 | DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no)); | 3638 | DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no)); |
@@ -3582,7 +3670,7 @@ qla2x00_get_dcbx_params(scsi_qla_host_t *vha, dma_addr_t tlv_dma, | |||
3582 | mbx_cmd_t mc; | 3670 | mbx_cmd_t mc; |
3583 | mbx_cmd_t *mcp = &mc; | 3671 | mbx_cmd_t *mcp = &mc; |
3584 | 3672 | ||
3585 | if (!IS_QLA81XX(vha->hw)) | 3673 | if (!IS_QLA8XXX_TYPE(vha->hw)) |
3586 | return QLA_FUNCTION_FAILED; | 3674 | return QLA_FUNCTION_FAILED; |
3587 | 3675 | ||
3588 | DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no)); | 3676 | DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no)); |
@@ -3643,7 +3731,8 @@ qla2x00_read_ram_word(scsi_qla_host_t *vha, uint32_t risc_addr, uint32_t *data) | |||
3643 | } | 3731 | } |
3644 | 3732 | ||
3645 | int | 3733 | int |
3646 | qla2x00_loopback_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq, uint16_t *mresp) | 3734 | qla2x00_loopback_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq, |
3735 | uint16_t *mresp) | ||
3647 | { | 3736 | { |
3648 | int rval; | 3737 | int rval; |
3649 | mbx_cmd_t mc; | 3738 | mbx_cmd_t mc; |
@@ -3678,7 +3767,7 @@ qla2x00_loopback_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq, uint16_t * | |||
3678 | 3767 | ||
3679 | mcp->out_mb = MBX_21|MBX_20|MBX_19|MBX_18|MBX_17|MBX_16|MBX_15| | 3768 | mcp->out_mb = MBX_21|MBX_20|MBX_19|MBX_18|MBX_17|MBX_16|MBX_15| |
3680 | MBX_14|MBX_13|MBX_12|MBX_11|MBX_10|MBX_7|MBX_6|MBX_1|MBX_0; | 3769 | MBX_14|MBX_13|MBX_12|MBX_11|MBX_10|MBX_7|MBX_6|MBX_1|MBX_0; |
3681 | if (IS_QLA81XX(vha->hw)) | 3770 | if (IS_QLA8XXX_TYPE(vha->hw)) |
3682 | mcp->out_mb |= MBX_2; | 3771 | mcp->out_mb |= MBX_2; |
3683 | mcp->in_mb = MBX_19|MBX_18|MBX_3|MBX_2|MBX_1|MBX_0; | 3772 | mcp->in_mb = MBX_19|MBX_18|MBX_3|MBX_2|MBX_1|MBX_0; |
3684 | 3773 | ||
@@ -3690,9 +3779,11 @@ qla2x00_loopback_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq, uint16_t * | |||
3690 | 3779 | ||
3691 | if (rval != QLA_SUCCESS) { | 3780 | if (rval != QLA_SUCCESS) { |
3692 | DEBUG2(printk(KERN_WARNING | 3781 | DEBUG2(printk(KERN_WARNING |
3693 | "(%ld): failed=%x mb[0]=0x%x " | 3782 | "(%ld): failed=%x mb[0]=0x%x " |
3694 | "mb[1]=0x%x mb[2]=0x%x mb[3]=0x%x mb[18]=0x%x mb[19]=0x%x. \n", vha->host_no, rval, | 3783 | "mb[1]=0x%x mb[2]=0x%x mb[3]=0x%x mb[18]=0x%x " |
3695 | mcp->mb[0], mcp->mb[1], mcp->mb[2], mcp->mb[3], mcp->mb[18], mcp->mb[19])); | 3784 | "mb[19]=0x%x.\n", |
3785 | vha->host_no, rval, mcp->mb[0], mcp->mb[1], mcp->mb[2], | ||
3786 | mcp->mb[3], mcp->mb[18], mcp->mb[19])); | ||
3696 | } else { | 3787 | } else { |
3697 | DEBUG2(printk(KERN_WARNING | 3788 | DEBUG2(printk(KERN_WARNING |
3698 | "scsi(%ld): done.\n", vha->host_no)); | 3789 | "scsi(%ld): done.\n", vha->host_no)); |
@@ -3706,7 +3797,8 @@ qla2x00_loopback_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq, uint16_t * | |||
3706 | } | 3797 | } |
3707 | 3798 | ||
3708 | int | 3799 | int |
3709 | qla2x00_echo_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq, uint16_t *mresp) | 3800 | qla2x00_echo_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq, |
3801 | uint16_t *mresp) | ||
3710 | { | 3802 | { |
3711 | int rval; | 3803 | int rval; |
3712 | mbx_cmd_t mc; | 3804 | mbx_cmd_t mc; |
@@ -3718,9 +3810,10 @@ qla2x00_echo_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq, uint16_t *mres | |||
3718 | memset(mcp->mb, 0 , sizeof(mcp->mb)); | 3810 | memset(mcp->mb, 0 , sizeof(mcp->mb)); |
3719 | mcp->mb[0] = MBC_DIAGNOSTIC_ECHO; | 3811 | mcp->mb[0] = MBC_DIAGNOSTIC_ECHO; |
3720 | mcp->mb[1] = mreq->options | BIT_6; /* BIT_6 specifies 64bit address */ | 3812 | mcp->mb[1] = mreq->options | BIT_6; /* BIT_6 specifies 64bit address */ |
3721 | if (IS_QLA81XX(ha)) | 3813 | if (IS_QLA8XXX_TYPE(ha)) { |
3722 | mcp->mb[1] |= BIT_15; | 3814 | mcp->mb[1] |= BIT_15; |
3723 | mcp->mb[2] = IS_QLA81XX(ha) ? vha->fcoe_fcf_idx : 0; | 3815 | mcp->mb[2] = vha->fcoe_fcf_idx; |
3816 | } | ||
3724 | mcp->mb[16] = LSW(mreq->rcv_dma); | 3817 | mcp->mb[16] = LSW(mreq->rcv_dma); |
3725 | mcp->mb[17] = MSW(mreq->rcv_dma); | 3818 | mcp->mb[17] = MSW(mreq->rcv_dma); |
3726 | mcp->mb[6] = LSW(MSD(mreq->rcv_dma)); | 3819 | mcp->mb[6] = LSW(MSD(mreq->rcv_dma)); |
@@ -3735,13 +3828,13 @@ qla2x00_echo_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq, uint16_t *mres | |||
3735 | 3828 | ||
3736 | mcp->out_mb = MBX_21|MBX_20|MBX_17|MBX_16|MBX_15| | 3829 | mcp->out_mb = MBX_21|MBX_20|MBX_17|MBX_16|MBX_15| |
3737 | MBX_14|MBX_10|MBX_7|MBX_6|MBX_1|MBX_0; | 3830 | MBX_14|MBX_10|MBX_7|MBX_6|MBX_1|MBX_0; |
3738 | if (IS_QLA81XX(ha)) | 3831 | if (IS_QLA8XXX_TYPE(ha)) |
3739 | mcp->out_mb |= MBX_2; | 3832 | mcp->out_mb |= MBX_2; |
3740 | 3833 | ||
3741 | mcp->in_mb = MBX_0; | 3834 | mcp->in_mb = MBX_0; |
3742 | if (IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha) || IS_QLA81XX(ha)) | 3835 | if (IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha) || IS_QLA8XXX_TYPE(ha)) |
3743 | mcp->in_mb |= MBX_1; | 3836 | mcp->in_mb |= MBX_1; |
3744 | if (IS_QLA81XX(ha)) | 3837 | if (IS_QLA8XXX_TYPE(ha)) |
3745 | mcp->in_mb |= MBX_3; | 3838 | mcp->in_mb |= MBX_3; |
3746 | 3839 | ||
3747 | mcp->tov = MBX_TOV_SECONDS; | 3840 | mcp->tov = MBX_TOV_SECONDS; |
@@ -3764,8 +3857,7 @@ qla2x00_echo_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq, uint16_t *mres | |||
3764 | return rval; | 3857 | return rval; |
3765 | } | 3858 | } |
3766 | int | 3859 | int |
3767 | qla84xx_reset_chip(scsi_qla_host_t *ha, uint16_t enable_diagnostic, | 3860 | qla84xx_reset_chip(scsi_qla_host_t *ha, uint16_t enable_diagnostic) |
3768 | uint16_t *cmd_status) | ||
3769 | { | 3861 | { |
3770 | int rval; | 3862 | int rval; |
3771 | mbx_cmd_t mc; | 3863 | mbx_cmd_t mc; |
@@ -3782,8 +3874,6 @@ qla84xx_reset_chip(scsi_qla_host_t *ha, uint16_t enable_diagnostic, | |||
3782 | mcp->flags = MBX_DMA_OUT|MBX_DMA_IN|IOCTL_CMD; | 3874 | mcp->flags = MBX_DMA_OUT|MBX_DMA_IN|IOCTL_CMD; |
3783 | rval = qla2x00_mailbox_command(ha, mcp); | 3875 | rval = qla2x00_mailbox_command(ha, mcp); |
3784 | 3876 | ||
3785 | /* Return mailbox statuses. */ | ||
3786 | *cmd_status = mcp->mb[0]; | ||
3787 | if (rval != QLA_SUCCESS) | 3877 | if (rval != QLA_SUCCESS) |
3788 | DEBUG16(printk("%s(%ld): failed=%x.\n", __func__, ha->host_no, | 3878 | DEBUG16(printk("%s(%ld): failed=%x.\n", __func__, ha->host_no, |
3789 | rval)); | 3879 | rval)); |
@@ -3801,7 +3891,7 @@ qla2x00_write_ram_word(scsi_qla_host_t *vha, uint32_t risc_addr, uint32_t data) | |||
3801 | mbx_cmd_t *mcp = &mc; | 3891 | mbx_cmd_t *mcp = &mc; |
3802 | 3892 | ||
3803 | if (!IS_FWI2_CAPABLE(vha->hw)) | 3893 | if (!IS_FWI2_CAPABLE(vha->hw)) |
3804 | return QLA_FUNCTION_FAILED; | 3894 | return QLA_FUNCTION_FAILED; |
3805 | 3895 | ||
3806 | DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no)); | 3896 | DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no)); |
3807 | 3897 | ||
@@ -3836,7 +3926,8 @@ qla2x00_get_data_rate(scsi_qla_host_t *vha) | |||
3836 | if (!IS_FWI2_CAPABLE(ha)) | 3926 | if (!IS_FWI2_CAPABLE(ha)) |
3837 | return QLA_FUNCTION_FAILED; | 3927 | return QLA_FUNCTION_FAILED; |
3838 | 3928 | ||
3839 | DEBUG11(printk(KERN_INFO "%s(%ld): entered.\n", __func__, vha->host_no)); | 3929 | DEBUG11(qla_printk(KERN_INFO, ha, |
3930 | "%s(%ld): entered.\n", __func__, vha->host_no)); | ||
3840 | 3931 | ||
3841 | mcp->mb[0] = MBC_DATA_RATE; | 3932 | mcp->mb[0] = MBC_DATA_RATE; |
3842 | mcp->mb[1] = 0; | 3933 | mcp->mb[1] = 0; |
@@ -3857,3 +3948,122 @@ qla2x00_get_data_rate(scsi_qla_host_t *vha) | |||
3857 | 3948 | ||
3858 | return rval; | 3949 | return rval; |
3859 | } | 3950 | } |
3951 | |||
3952 | int | ||
3953 | qla24xx_set_fcp_prio(scsi_qla_host_t *vha, uint16_t loop_id, uint16_t priority, | ||
3954 | uint16_t *mb) | ||
3955 | { | ||
3956 | int rval; | ||
3957 | mbx_cmd_t mc; | ||
3958 | mbx_cmd_t *mcp = &mc; | ||
3959 | struct qla_hw_data *ha = vha->hw; | ||
3960 | |||
3961 | if (!IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha)) | ||
3962 | return QLA_FUNCTION_FAILED; | ||
3963 | |||
3964 | DEBUG11(printk(KERN_INFO | ||
3965 | "%s(%ld): entered.\n", __func__, ha->host_no)); | ||
3966 | |||
3967 | mcp->mb[0] = MBC_PORT_PARAMS; | ||
3968 | mcp->mb[1] = loop_id; | ||
3969 | if (ha->flags.fcp_prio_enabled) | ||
3970 | mcp->mb[2] = BIT_1; | ||
3971 | else | ||
3972 | mcp->mb[2] = BIT_2; | ||
3973 | mcp->mb[4] = priority & 0xf; | ||
3974 | mcp->mb[9] = vha->vp_idx; | ||
3975 | mcp->out_mb = MBX_9|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; | ||
3976 | mcp->in_mb = MBX_4|MBX_3|MBX_1|MBX_0; | ||
3977 | mcp->tov = 30; | ||
3978 | mcp->flags = 0; | ||
3979 | rval = qla2x00_mailbox_command(vha, mcp); | ||
3980 | if (mb != NULL) { | ||
3981 | mb[0] = mcp->mb[0]; | ||
3982 | mb[1] = mcp->mb[1]; | ||
3983 | mb[3] = mcp->mb[3]; | ||
3984 | mb[4] = mcp->mb[4]; | ||
3985 | } | ||
3986 | |||
3987 | if (rval != QLA_SUCCESS) { | ||
3988 | DEBUG2_3_11(printk(KERN_WARNING | ||
3989 | "%s(%ld): failed=%x.\n", __func__, | ||
3990 | vha->host_no, rval)); | ||
3991 | } else { | ||
3992 | DEBUG11(printk(KERN_INFO | ||
3993 | "%s(%ld): done.\n", __func__, vha->host_no)); | ||
3994 | } | ||
3995 | |||
3996 | return rval; | ||
3997 | } | ||
3998 | |||
3999 | int | ||
4000 | qla82xx_mbx_intr_enable(scsi_qla_host_t *vha) | ||
4001 | { | ||
4002 | int rval; | ||
4003 | struct qla_hw_data *ha = vha->hw; | ||
4004 | mbx_cmd_t mc; | ||
4005 | mbx_cmd_t *mcp = &mc; | ||
4006 | |||
4007 | if (!IS_FWI2_CAPABLE(ha)) | ||
4008 | return QLA_FUNCTION_FAILED; | ||
4009 | |||
4010 | DEBUG11(qla_printk(KERN_INFO, ha, | ||
4011 | "%s(%ld): entered.\n", __func__, vha->host_no)); | ||
4012 | |||
4013 | memset(mcp, 0, sizeof(mbx_cmd_t)); | ||
4014 | mcp->mb[0] = MBC_TOGGLE_INTR; | ||
4015 | mcp->mb[1] = 1; | ||
4016 | |||
4017 | mcp->out_mb = MBX_1|MBX_0; | ||
4018 | mcp->in_mb = MBX_0; | ||
4019 | mcp->tov = 30; | ||
4020 | mcp->flags = 0; | ||
4021 | |||
4022 | rval = qla2x00_mailbox_command(vha, mcp); | ||
4023 | if (rval != QLA_SUCCESS) { | ||
4024 | DEBUG2_3_11(qla_printk(KERN_WARNING, ha, | ||
4025 | "%s(%ld): failed=%x mb[0]=%x.\n", __func__, | ||
4026 | vha->host_no, rval, mcp->mb[0])); | ||
4027 | } else { | ||
4028 | DEBUG11(qla_printk(KERN_INFO, ha, | ||
4029 | "%s(%ld): done.\n", __func__, vha->host_no)); | ||
4030 | } | ||
4031 | |||
4032 | return rval; | ||
4033 | } | ||
4034 | |||
4035 | int | ||
4036 | qla82xx_mbx_intr_disable(scsi_qla_host_t *vha) | ||
4037 | { | ||
4038 | int rval; | ||
4039 | struct qla_hw_data *ha = vha->hw; | ||
4040 | mbx_cmd_t mc; | ||
4041 | mbx_cmd_t *mcp = &mc; | ||
4042 | |||
4043 | if (!IS_QLA82XX(ha)) | ||
4044 | return QLA_FUNCTION_FAILED; | ||
4045 | |||
4046 | DEBUG11(qla_printk(KERN_INFO, ha, | ||
4047 | "%s(%ld): entered.\n", __func__, vha->host_no)); | ||
4048 | |||
4049 | memset(mcp, 0, sizeof(mbx_cmd_t)); | ||
4050 | mcp->mb[0] = MBC_TOGGLE_INTR; | ||
4051 | mcp->mb[1] = 0; | ||
4052 | |||
4053 | mcp->out_mb = MBX_1|MBX_0; | ||
4054 | mcp->in_mb = MBX_0; | ||
4055 | mcp->tov = 30; | ||
4056 | mcp->flags = 0; | ||
4057 | |||
4058 | rval = qla2x00_mailbox_command(vha, mcp); | ||
4059 | if (rval != QLA_SUCCESS) { | ||
4060 | DEBUG2_3_11(qla_printk(KERN_WARNING, ha, | ||
4061 | "%s(%ld): failed=%x mb[0]=%x.\n", __func__, | ||
4062 | vha->host_no, rval, mcp->mb[0])); | ||
4063 | } else { | ||
4064 | DEBUG11(qla_printk(KERN_INFO, ha, | ||
4065 | "%s(%ld): done.\n", __func__, vha->host_no)); | ||
4066 | } | ||
4067 | |||
4068 | return rval; | ||
4069 | } | ||
diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c new file mode 100644 index 000000000000..ff562de0e8e7 --- /dev/null +++ b/drivers/scsi/qla2xxx/qla_nx.c | |||
@@ -0,0 +1,3636 @@ | |||
1 | /* | ||
2 | * QLogic Fibre Channel HBA Driver | ||
3 | * Copyright (c) 2003-2008 QLogic Corporation | ||
4 | * | ||
5 | * See LICENSE.qla2xxx for copyright and licensing details. | ||
6 | */ | ||
7 | #include "qla_def.h" | ||
8 | #include <linux/delay.h> | ||
9 | #include <linux/pci.h> | ||
10 | |||
11 | #define MASK(n) ((1ULL<<(n))-1) | ||
12 | #define MN_WIN(addr) (((addr & 0x1fc0000) >> 1) | \ | ||
13 | ((addr >> 25) & 0x3ff)) | ||
14 | #define OCM_WIN(addr) (((addr & 0x1ff0000) >> 1) | \ | ||
15 | ((addr >> 25) & 0x3ff)) | ||
16 | #define MS_WIN(addr) (addr & 0x0ffc0000) | ||
17 | #define QLA82XX_PCI_MN_2M (0) | ||
18 | #define QLA82XX_PCI_MS_2M (0x80000) | ||
19 | #define QLA82XX_PCI_OCM0_2M (0xc0000) | ||
20 | #define VALID_OCM_ADDR(addr) (((addr) & 0x3f800) != 0x3f800) | ||
21 | #define GET_MEM_OFFS_2M(addr) (addr & MASK(18)) | ||
22 | |||
23 | /* CRB window related */ | ||
24 | #define CRB_BLK(off) ((off >> 20) & 0x3f) | ||
25 | #define CRB_SUBBLK(off) ((off >> 16) & 0xf) | ||
26 | #define CRB_WINDOW_2M (0x130060) | ||
27 | #define QLA82XX_PCI_CAMQM_2M_END (0x04800800UL) | ||
28 | #define CRB_HI(off) ((qla82xx_crb_hub_agt[CRB_BLK(off)] << 20) | \ | ||
29 | ((off) & 0xf0000)) | ||
30 | #define QLA82XX_PCI_CAMQM_2M_BASE (0x000ff800UL) | ||
31 | #define CRB_INDIRECT_2M (0x1e0000UL) | ||
32 | |||
33 | #define MAX_CRB_XFORM 60 | ||
34 | static unsigned long crb_addr_xform[MAX_CRB_XFORM]; | ||
35 | int qla82xx_crb_table_initialized; | ||
36 | |||
37 | #define qla82xx_crb_addr_transform(name) \ | ||
38 | (crb_addr_xform[QLA82XX_HW_PX_MAP_CRB_##name] = \ | ||
39 | QLA82XX_HW_CRB_HUB_AGT_ADR_##name << 20) | ||
40 | |||
41 | static void qla82xx_crb_addr_transform_setup(void) | ||
42 | { | ||
43 | qla82xx_crb_addr_transform(XDMA); | ||
44 | qla82xx_crb_addr_transform(TIMR); | ||
45 | qla82xx_crb_addr_transform(SRE); | ||
46 | qla82xx_crb_addr_transform(SQN3); | ||
47 | qla82xx_crb_addr_transform(SQN2); | ||
48 | qla82xx_crb_addr_transform(SQN1); | ||
49 | qla82xx_crb_addr_transform(SQN0); | ||
50 | qla82xx_crb_addr_transform(SQS3); | ||
51 | qla82xx_crb_addr_transform(SQS2); | ||
52 | qla82xx_crb_addr_transform(SQS1); | ||
53 | qla82xx_crb_addr_transform(SQS0); | ||
54 | qla82xx_crb_addr_transform(RPMX7); | ||
55 | qla82xx_crb_addr_transform(RPMX6); | ||
56 | qla82xx_crb_addr_transform(RPMX5); | ||
57 | qla82xx_crb_addr_transform(RPMX4); | ||
58 | qla82xx_crb_addr_transform(RPMX3); | ||
59 | qla82xx_crb_addr_transform(RPMX2); | ||
60 | qla82xx_crb_addr_transform(RPMX1); | ||
61 | qla82xx_crb_addr_transform(RPMX0); | ||
62 | qla82xx_crb_addr_transform(ROMUSB); | ||
63 | qla82xx_crb_addr_transform(SN); | ||
64 | qla82xx_crb_addr_transform(QMN); | ||
65 | qla82xx_crb_addr_transform(QMS); | ||
66 | qla82xx_crb_addr_transform(PGNI); | ||
67 | qla82xx_crb_addr_transform(PGND); | ||
68 | qla82xx_crb_addr_transform(PGN3); | ||
69 | qla82xx_crb_addr_transform(PGN2); | ||
70 | qla82xx_crb_addr_transform(PGN1); | ||
71 | qla82xx_crb_addr_transform(PGN0); | ||
72 | qla82xx_crb_addr_transform(PGSI); | ||
73 | qla82xx_crb_addr_transform(PGSD); | ||
74 | qla82xx_crb_addr_transform(PGS3); | ||
75 | qla82xx_crb_addr_transform(PGS2); | ||
76 | qla82xx_crb_addr_transform(PGS1); | ||
77 | qla82xx_crb_addr_transform(PGS0); | ||
78 | qla82xx_crb_addr_transform(PS); | ||
79 | qla82xx_crb_addr_transform(PH); | ||
80 | qla82xx_crb_addr_transform(NIU); | ||
81 | qla82xx_crb_addr_transform(I2Q); | ||
82 | qla82xx_crb_addr_transform(EG); | ||
83 | qla82xx_crb_addr_transform(MN); | ||
84 | qla82xx_crb_addr_transform(MS); | ||
85 | qla82xx_crb_addr_transform(CAS2); | ||
86 | qla82xx_crb_addr_transform(CAS1); | ||
87 | qla82xx_crb_addr_transform(CAS0); | ||
88 | qla82xx_crb_addr_transform(CAM); | ||
89 | qla82xx_crb_addr_transform(C2C1); | ||
90 | qla82xx_crb_addr_transform(C2C0); | ||
91 | qla82xx_crb_addr_transform(SMB); | ||
92 | qla82xx_crb_addr_transform(OCM0); | ||
93 | /* | ||
94 | * Used only in P3 just define it for P2 also. | ||
95 | */ | ||
96 | qla82xx_crb_addr_transform(I2C0); | ||
97 | |||
98 | qla82xx_crb_table_initialized = 1; | ||
99 | } | ||
100 | |||
101 | struct crb_128M_2M_block_map crb_128M_2M_map[64] = { | ||
102 | {{{0, 0, 0, 0} } }, | ||
103 | {{{1, 0x0100000, 0x0102000, 0x120000}, | ||
104 | {1, 0x0110000, 0x0120000, 0x130000}, | ||
105 | {1, 0x0120000, 0x0122000, 0x124000}, | ||
106 | {1, 0x0130000, 0x0132000, 0x126000}, | ||
107 | {1, 0x0140000, 0x0142000, 0x128000}, | ||
108 | {1, 0x0150000, 0x0152000, 0x12a000}, | ||
109 | {1, 0x0160000, 0x0170000, 0x110000}, | ||
110 | {1, 0x0170000, 0x0172000, 0x12e000}, | ||
111 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
112 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
113 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
114 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
115 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
116 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
117 | {1, 0x01e0000, 0x01e0800, 0x122000}, | ||
118 | {0, 0x0000000, 0x0000000, 0x000000} } } , | ||
119 | {{{1, 0x0200000, 0x0210000, 0x180000} } }, | ||
120 | {{{0, 0, 0, 0} } }, | ||
121 | {{{1, 0x0400000, 0x0401000, 0x169000} } }, | ||
122 | {{{1, 0x0500000, 0x0510000, 0x140000} } }, | ||
123 | {{{1, 0x0600000, 0x0610000, 0x1c0000} } }, | ||
124 | {{{1, 0x0700000, 0x0704000, 0x1b8000} } }, | ||
125 | {{{1, 0x0800000, 0x0802000, 0x170000}, | ||
126 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
127 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
128 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
129 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
130 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
131 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
132 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
133 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
134 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
135 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
136 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
137 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
138 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
139 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
140 | {1, 0x08f0000, 0x08f2000, 0x172000} } }, | ||
141 | {{{1, 0x0900000, 0x0902000, 0x174000}, | ||
142 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
143 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
144 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
145 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
146 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
147 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
148 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
149 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
150 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
151 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
152 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
153 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
154 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
155 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
156 | {1, 0x09f0000, 0x09f2000, 0x176000} } }, | ||
157 | {{{0, 0x0a00000, 0x0a02000, 0x178000}, | ||
158 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
159 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
160 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
161 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
162 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
163 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
164 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
165 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
166 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
167 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
168 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
169 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
170 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
171 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
172 | {1, 0x0af0000, 0x0af2000, 0x17a000} } }, | ||
173 | {{{0, 0x0b00000, 0x0b02000, 0x17c000}, | ||
174 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
175 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
176 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
177 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
178 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
179 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
180 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
181 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
182 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
183 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
184 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
185 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
186 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
187 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
188 | {1, 0x0bf0000, 0x0bf2000, 0x17e000} } }, | ||
189 | {{{1, 0x0c00000, 0x0c04000, 0x1d4000} } }, | ||
190 | {{{1, 0x0d00000, 0x0d04000, 0x1a4000} } }, | ||
191 | {{{1, 0x0e00000, 0x0e04000, 0x1a0000} } }, | ||
192 | {{{1, 0x0f00000, 0x0f01000, 0x164000} } }, | ||
193 | {{{0, 0x1000000, 0x1004000, 0x1a8000} } }, | ||
194 | {{{1, 0x1100000, 0x1101000, 0x160000} } }, | ||
195 | {{{1, 0x1200000, 0x1201000, 0x161000} } }, | ||
196 | {{{1, 0x1300000, 0x1301000, 0x162000} } }, | ||
197 | {{{1, 0x1400000, 0x1401000, 0x163000} } }, | ||
198 | {{{1, 0x1500000, 0x1501000, 0x165000} } }, | ||
199 | {{{1, 0x1600000, 0x1601000, 0x166000} } }, | ||
200 | {{{0, 0, 0, 0} } }, | ||
201 | {{{0, 0, 0, 0} } }, | ||
202 | {{{0, 0, 0, 0} } }, | ||
203 | {{{0, 0, 0, 0} } }, | ||
204 | {{{0, 0, 0, 0} } }, | ||
205 | {{{0, 0, 0, 0} } }, | ||
206 | {{{1, 0x1d00000, 0x1d10000, 0x190000} } }, | ||
207 | {{{1, 0x1e00000, 0x1e01000, 0x16a000} } }, | ||
208 | {{{1, 0x1f00000, 0x1f10000, 0x150000} } }, | ||
209 | {{{0} } }, | ||
210 | {{{1, 0x2100000, 0x2102000, 0x120000}, | ||
211 | {1, 0x2110000, 0x2120000, 0x130000}, | ||
212 | {1, 0x2120000, 0x2122000, 0x124000}, | ||
213 | {1, 0x2130000, 0x2132000, 0x126000}, | ||
214 | {1, 0x2140000, 0x2142000, 0x128000}, | ||
215 | {1, 0x2150000, 0x2152000, 0x12a000}, | ||
216 | {1, 0x2160000, 0x2170000, 0x110000}, | ||
217 | {1, 0x2170000, 0x2172000, 0x12e000}, | ||
218 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
219 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
220 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
221 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
222 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
223 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
224 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
225 | {0, 0x0000000, 0x0000000, 0x000000} } }, | ||
226 | {{{1, 0x2200000, 0x2204000, 0x1b0000} } }, | ||
227 | {{{0} } }, | ||
228 | {{{0} } }, | ||
229 | {{{0} } }, | ||
230 | {{{0} } }, | ||
231 | {{{0} } }, | ||
232 | {{{1, 0x2800000, 0x2804000, 0x1a4000} } }, | ||
233 | {{{1, 0x2900000, 0x2901000, 0x16b000} } }, | ||
234 | {{{1, 0x2a00000, 0x2a00400, 0x1ac400} } }, | ||
235 | {{{1, 0x2b00000, 0x2b00400, 0x1ac800} } }, | ||
236 | {{{1, 0x2c00000, 0x2c00400, 0x1acc00} } }, | ||
237 | {{{1, 0x2d00000, 0x2d00400, 0x1ad000} } }, | ||
238 | {{{1, 0x2e00000, 0x2e00400, 0x1ad400} } }, | ||
239 | {{{1, 0x2f00000, 0x2f00400, 0x1ad800} } }, | ||
240 | {{{1, 0x3000000, 0x3000400, 0x1adc00} } }, | ||
241 | {{{0, 0x3100000, 0x3104000, 0x1a8000} } }, | ||
242 | {{{1, 0x3200000, 0x3204000, 0x1d4000} } }, | ||
243 | {{{1, 0x3300000, 0x3304000, 0x1a0000} } }, | ||
244 | {{{0} } }, | ||
245 | {{{1, 0x3500000, 0x3500400, 0x1ac000} } }, | ||
246 | {{{1, 0x3600000, 0x3600400, 0x1ae000} } }, | ||
247 | {{{1, 0x3700000, 0x3700400, 0x1ae400} } }, | ||
248 | {{{1, 0x3800000, 0x3804000, 0x1d0000} } }, | ||
249 | {{{1, 0x3900000, 0x3904000, 0x1b4000} } }, | ||
250 | {{{1, 0x3a00000, 0x3a04000, 0x1d8000} } }, | ||
251 | {{{0} } }, | ||
252 | {{{0} } }, | ||
253 | {{{1, 0x3d00000, 0x3d04000, 0x1dc000} } }, | ||
254 | {{{1, 0x3e00000, 0x3e01000, 0x167000} } }, | ||
255 | {{{1, 0x3f00000, 0x3f01000, 0x168000} } } | ||
256 | }; | ||
257 | |||
258 | /* | ||
259 | * top 12 bits of crb internal address (hub, agent) | ||
260 | */ | ||
261 | unsigned qla82xx_crb_hub_agt[64] = { | ||
262 | 0, | ||
263 | QLA82XX_HW_CRB_HUB_AGT_ADR_PS, | ||
264 | QLA82XX_HW_CRB_HUB_AGT_ADR_MN, | ||
265 | QLA82XX_HW_CRB_HUB_AGT_ADR_MS, | ||
266 | 0, | ||
267 | QLA82XX_HW_CRB_HUB_AGT_ADR_SRE, | ||
268 | QLA82XX_HW_CRB_HUB_AGT_ADR_NIU, | ||
269 | QLA82XX_HW_CRB_HUB_AGT_ADR_QMN, | ||
270 | QLA82XX_HW_CRB_HUB_AGT_ADR_SQN0, | ||
271 | QLA82XX_HW_CRB_HUB_AGT_ADR_SQN1, | ||
272 | QLA82XX_HW_CRB_HUB_AGT_ADR_SQN2, | ||
273 | QLA82XX_HW_CRB_HUB_AGT_ADR_SQN3, | ||
274 | QLA82XX_HW_CRB_HUB_AGT_ADR_I2Q, | ||
275 | QLA82XX_HW_CRB_HUB_AGT_ADR_TIMR, | ||
276 | QLA82XX_HW_CRB_HUB_AGT_ADR_ROMUSB, | ||
277 | QLA82XX_HW_CRB_HUB_AGT_ADR_PGN4, | ||
278 | QLA82XX_HW_CRB_HUB_AGT_ADR_XDMA, | ||
279 | QLA82XX_HW_CRB_HUB_AGT_ADR_PGN0, | ||
280 | QLA82XX_HW_CRB_HUB_AGT_ADR_PGN1, | ||
281 | QLA82XX_HW_CRB_HUB_AGT_ADR_PGN2, | ||
282 | QLA82XX_HW_CRB_HUB_AGT_ADR_PGN3, | ||
283 | QLA82XX_HW_CRB_HUB_AGT_ADR_PGND, | ||
284 | QLA82XX_HW_CRB_HUB_AGT_ADR_PGNI, | ||
285 | QLA82XX_HW_CRB_HUB_AGT_ADR_PGS0, | ||
286 | QLA82XX_HW_CRB_HUB_AGT_ADR_PGS1, | ||
287 | QLA82XX_HW_CRB_HUB_AGT_ADR_PGS2, | ||
288 | QLA82XX_HW_CRB_HUB_AGT_ADR_PGS3, | ||
289 | 0, | ||
290 | QLA82XX_HW_CRB_HUB_AGT_ADR_PGSI, | ||
291 | QLA82XX_HW_CRB_HUB_AGT_ADR_SN, | ||
292 | 0, | ||
293 | QLA82XX_HW_CRB_HUB_AGT_ADR_EG, | ||
294 | 0, | ||
295 | QLA82XX_HW_CRB_HUB_AGT_ADR_PS, | ||
296 | QLA82XX_HW_CRB_HUB_AGT_ADR_CAM, | ||
297 | 0, | ||
298 | 0, | ||
299 | 0, | ||
300 | 0, | ||
301 | 0, | ||
302 | QLA82XX_HW_CRB_HUB_AGT_ADR_TIMR, | ||
303 | 0, | ||
304 | QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX1, | ||
305 | QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX2, | ||
306 | QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX3, | ||
307 | QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX4, | ||
308 | QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX5, | ||
309 | QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX6, | ||
310 | QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX7, | ||
311 | QLA82XX_HW_CRB_HUB_AGT_ADR_XDMA, | ||
312 | QLA82XX_HW_CRB_HUB_AGT_ADR_I2Q, | ||
313 | QLA82XX_HW_CRB_HUB_AGT_ADR_ROMUSB, | ||
314 | 0, | ||
315 | QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX0, | ||
316 | QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX8, | ||
317 | QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX9, | ||
318 | QLA82XX_HW_CRB_HUB_AGT_ADR_OCM0, | ||
319 | 0, | ||
320 | QLA82XX_HW_CRB_HUB_AGT_ADR_SMB, | ||
321 | QLA82XX_HW_CRB_HUB_AGT_ADR_I2C0, | ||
322 | QLA82XX_HW_CRB_HUB_AGT_ADR_I2C1, | ||
323 | 0, | ||
324 | QLA82XX_HW_CRB_HUB_AGT_ADR_PGNC, | ||
325 | 0, | ||
326 | }; | ||
327 | |||
328 | /* Device states */ | ||
329 | char *qdev_state[] = { | ||
330 | "Unknown", | ||
331 | "Cold", | ||
332 | "Initializing", | ||
333 | "Ready", | ||
334 | "Need Reset", | ||
335 | "Need Quiescent", | ||
336 | "Failed", | ||
337 | "Quiescent", | ||
338 | }; | ||
339 | |||
340 | /* | ||
341 | * In: 'off' is offset from CRB space in 128M pci map | ||
342 | * Out: 'off' is 2M pci map addr | ||
343 | * side effect: lock crb window | ||
344 | */ | ||
345 | static void | ||
346 | qla82xx_pci_set_crbwindow_2M(struct qla_hw_data *ha, ulong *off) | ||
347 | { | ||
348 | u32 win_read; | ||
349 | |||
350 | ha->crb_win = CRB_HI(*off); | ||
351 | writel(ha->crb_win, | ||
352 | (void *)(CRB_WINDOW_2M + ha->nx_pcibase)); | ||
353 | |||
354 | /* Read back value to make sure write has gone through before trying | ||
355 | * to use it. | ||
356 | */ | ||
357 | win_read = RD_REG_DWORD((void *)(CRB_WINDOW_2M + ha->nx_pcibase)); | ||
358 | if (win_read != ha->crb_win) { | ||
359 | DEBUG2(qla_printk(KERN_INFO, ha, | ||
360 | "%s: Written crbwin (0x%x) != Read crbwin (0x%x), " | ||
361 | "off=0x%lx\n", __func__, ha->crb_win, win_read, *off)); | ||
362 | } | ||
363 | *off = (*off & MASK(16)) + CRB_INDIRECT_2M + ha->nx_pcibase; | ||
364 | } | ||
365 | |||
366 | static inline unsigned long | ||
367 | qla82xx_pci_set_crbwindow(struct qla_hw_data *ha, u64 off) | ||
368 | { | ||
369 | /* See if we are currently pointing to the region we want to use next */ | ||
370 | if ((off >= QLA82XX_CRB_PCIX_HOST) && (off < QLA82XX_CRB_DDR_NET)) { | ||
371 | /* No need to change window. PCIX and PCIEregs are in both | ||
372 | * regs are in both windows. | ||
373 | */ | ||
374 | return off; | ||
375 | } | ||
376 | |||
377 | if ((off >= QLA82XX_CRB_PCIX_HOST) && (off < QLA82XX_CRB_PCIX_HOST2)) { | ||
378 | /* We are in first CRB window */ | ||
379 | if (ha->curr_window != 0) | ||
380 | WARN_ON(1); | ||
381 | return off; | ||
382 | } | ||
383 | |||
384 | if ((off > QLA82XX_CRB_PCIX_HOST2) && (off < QLA82XX_CRB_MAX)) { | ||
385 | /* We are in second CRB window */ | ||
386 | off = off - QLA82XX_CRB_PCIX_HOST2 + QLA82XX_CRB_PCIX_HOST; | ||
387 | |||
388 | if (ha->curr_window != 1) | ||
389 | return off; | ||
390 | |||
391 | /* We are in the QM or direct access | ||
392 | * register region - do nothing | ||
393 | */ | ||
394 | if ((off >= QLA82XX_PCI_DIRECT_CRB) && | ||
395 | (off < QLA82XX_PCI_CAMQM_MAX)) | ||
396 | return off; | ||
397 | } | ||
398 | /* strange address given */ | ||
399 | qla_printk(KERN_WARNING, ha, | ||
400 | "%s: Warning: unm_nic_pci_set_crbwindow called with" | ||
401 | " an unknown address(%llx)\n", QLA2XXX_DRIVER_NAME, off); | ||
402 | return off; | ||
403 | } | ||
404 | |||
405 | int | ||
406 | qla82xx_wr_32(struct qla_hw_data *ha, ulong off, u32 data) | ||
407 | { | ||
408 | unsigned long flags = 0; | ||
409 | int rv; | ||
410 | |||
411 | rv = qla82xx_pci_get_crb_addr_2M(ha, &off); | ||
412 | |||
413 | BUG_ON(rv == -1); | ||
414 | |||
415 | if (rv == 1) { | ||
416 | write_lock_irqsave(&ha->hw_lock, flags); | ||
417 | qla82xx_crb_win_lock(ha); | ||
418 | qla82xx_pci_set_crbwindow_2M(ha, &off); | ||
419 | } | ||
420 | |||
421 | writel(data, (void __iomem *)off); | ||
422 | |||
423 | if (rv == 1) { | ||
424 | qla82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM7_UNLOCK)); | ||
425 | write_unlock_irqrestore(&ha->hw_lock, flags); | ||
426 | } | ||
427 | return 0; | ||
428 | } | ||
429 | |||
430 | int | ||
431 | qla82xx_rd_32(struct qla_hw_data *ha, ulong off) | ||
432 | { | ||
433 | unsigned long flags = 0; | ||
434 | int rv; | ||
435 | u32 data; | ||
436 | |||
437 | rv = qla82xx_pci_get_crb_addr_2M(ha, &off); | ||
438 | |||
439 | BUG_ON(rv == -1); | ||
440 | |||
441 | if (rv == 1) { | ||
442 | write_lock_irqsave(&ha->hw_lock, flags); | ||
443 | qla82xx_crb_win_lock(ha); | ||
444 | qla82xx_pci_set_crbwindow_2M(ha, &off); | ||
445 | } | ||
446 | data = RD_REG_DWORD((void __iomem *)off); | ||
447 | |||
448 | if (rv == 1) { | ||
449 | qla82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM7_UNLOCK)); | ||
450 | write_unlock_irqrestore(&ha->hw_lock, flags); | ||
451 | } | ||
452 | return data; | ||
453 | } | ||
454 | |||
455 | #define CRB_WIN_LOCK_TIMEOUT 100000000 | ||
456 | int qla82xx_crb_win_lock(struct qla_hw_data *ha) | ||
457 | { | ||
458 | int done = 0, timeout = 0; | ||
459 | |||
460 | while (!done) { | ||
461 | /* acquire semaphore3 from PCI HW block */ | ||
462 | done = qla82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM7_LOCK)); | ||
463 | if (done == 1) | ||
464 | break; | ||
465 | if (timeout >= CRB_WIN_LOCK_TIMEOUT) | ||
466 | return -1; | ||
467 | timeout++; | ||
468 | } | ||
469 | qla82xx_wr_32(ha, QLA82XX_CRB_WIN_LOCK_ID, ha->portnum); | ||
470 | return 0; | ||
471 | } | ||
472 | |||
473 | #define IDC_LOCK_TIMEOUT 100000000 | ||
474 | int qla82xx_idc_lock(struct qla_hw_data *ha) | ||
475 | { | ||
476 | int i; | ||
477 | int done = 0, timeout = 0; | ||
478 | |||
479 | while (!done) { | ||
480 | /* acquire semaphore5 from PCI HW block */ | ||
481 | done = qla82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM5_LOCK)); | ||
482 | if (done == 1) | ||
483 | break; | ||
484 | if (timeout >= IDC_LOCK_TIMEOUT) | ||
485 | return -1; | ||
486 | |||
487 | timeout++; | ||
488 | |||
489 | /* Yield CPU */ | ||
490 | if (!in_interrupt()) | ||
491 | schedule(); | ||
492 | else { | ||
493 | for (i = 0; i < 20; i++) | ||
494 | cpu_relax(); | ||
495 | } | ||
496 | } | ||
497 | |||
498 | return 0; | ||
499 | } | ||
500 | |||
501 | void qla82xx_idc_unlock(struct qla_hw_data *ha) | ||
502 | { | ||
503 | qla82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM5_UNLOCK)); | ||
504 | } | ||
505 | |||
506 | int | ||
507 | qla82xx_pci_get_crb_addr_2M(struct qla_hw_data *ha, ulong *off) | ||
508 | { | ||
509 | struct crb_128M_2M_sub_block_map *m; | ||
510 | |||
511 | if (*off >= QLA82XX_CRB_MAX) | ||
512 | return -1; | ||
513 | |||
514 | if (*off >= QLA82XX_PCI_CAMQM && (*off < QLA82XX_PCI_CAMQM_2M_END)) { | ||
515 | *off = (*off - QLA82XX_PCI_CAMQM) + | ||
516 | QLA82XX_PCI_CAMQM_2M_BASE + ha->nx_pcibase; | ||
517 | return 0; | ||
518 | } | ||
519 | |||
520 | if (*off < QLA82XX_PCI_CRBSPACE) | ||
521 | return -1; | ||
522 | |||
523 | *off -= QLA82XX_PCI_CRBSPACE; | ||
524 | |||
525 | /* Try direct map */ | ||
526 | m = &crb_128M_2M_map[CRB_BLK(*off)].sub_block[CRB_SUBBLK(*off)]; | ||
527 | |||
528 | if (m->valid && (m->start_128M <= *off) && (m->end_128M > *off)) { | ||
529 | *off = *off + m->start_2M - m->start_128M + ha->nx_pcibase; | ||
530 | return 0; | ||
531 | } | ||
532 | /* Not in direct map, use crb window */ | ||
533 | return 1; | ||
534 | } | ||
535 | |||
536 | /* PCI Windowing for DDR regions. */ | ||
537 | #define QLA82XX_ADDR_IN_RANGE(addr, low, high) \ | ||
538 | (((addr) <= (high)) && ((addr) >= (low))) | ||
539 | /* | ||
540 | * check memory access boundary. | ||
541 | * used by test agent. support ddr access only for now | ||
542 | */ | ||
543 | static unsigned long | ||
544 | qla82xx_pci_mem_bound_check(struct qla_hw_data *ha, | ||
545 | unsigned long long addr, int size) | ||
546 | { | ||
547 | if (!QLA82XX_ADDR_IN_RANGE(addr, QLA82XX_ADDR_DDR_NET, | ||
548 | QLA82XX_ADDR_DDR_NET_MAX) || | ||
549 | !QLA82XX_ADDR_IN_RANGE(addr + size - 1, QLA82XX_ADDR_DDR_NET, | ||
550 | QLA82XX_ADDR_DDR_NET_MAX) || | ||
551 | ((size != 1) && (size != 2) && (size != 4) && (size != 8))) | ||
552 | return 0; | ||
553 | else | ||
554 | return 1; | ||
555 | } | ||
556 | |||
557 | int qla82xx_pci_set_window_warning_count; | ||
558 | |||
559 | unsigned long | ||
560 | qla82xx_pci_set_window(struct qla_hw_data *ha, unsigned long long addr) | ||
561 | { | ||
562 | int window; | ||
563 | u32 win_read; | ||
564 | |||
565 | if (QLA82XX_ADDR_IN_RANGE(addr, QLA82XX_ADDR_DDR_NET, | ||
566 | QLA82XX_ADDR_DDR_NET_MAX)) { | ||
567 | /* DDR network side */ | ||
568 | window = MN_WIN(addr); | ||
569 | ha->ddr_mn_window = window; | ||
570 | qla82xx_wr_32(ha, | ||
571 | ha->mn_win_crb | QLA82XX_PCI_CRBSPACE, window); | ||
572 | win_read = qla82xx_rd_32(ha, | ||
573 | ha->mn_win_crb | QLA82XX_PCI_CRBSPACE); | ||
574 | if ((win_read << 17) != window) { | ||
575 | qla_printk(KERN_WARNING, ha, | ||
576 | "%s: Written MNwin (0x%x) != Read MNwin (0x%x)\n", | ||
577 | __func__, window, win_read); | ||
578 | } | ||
579 | addr = GET_MEM_OFFS_2M(addr) + QLA82XX_PCI_DDR_NET; | ||
580 | } else if (QLA82XX_ADDR_IN_RANGE(addr, QLA82XX_ADDR_OCM0, | ||
581 | QLA82XX_ADDR_OCM0_MAX)) { | ||
582 | unsigned int temp1; | ||
583 | if ((addr & 0x00ff800) == 0xff800) { | ||
584 | qla_printk(KERN_WARNING, ha, | ||
585 | "%s: QM access not handled.\n", __func__); | ||
586 | addr = -1UL; | ||
587 | } | ||
588 | window = OCM_WIN(addr); | ||
589 | ha->ddr_mn_window = window; | ||
590 | qla82xx_wr_32(ha, | ||
591 | ha->mn_win_crb | QLA82XX_PCI_CRBSPACE, window); | ||
592 | win_read = qla82xx_rd_32(ha, | ||
593 | ha->mn_win_crb | QLA82XX_PCI_CRBSPACE); | ||
594 | temp1 = ((window & 0x1FF) << 7) | | ||
595 | ((window & 0x0FFFE0000) >> 17); | ||
596 | if (win_read != temp1) { | ||
597 | qla_printk(KERN_WARNING, ha, | ||
598 | "%s: Written OCMwin (0x%x) != Read OCMwin (0x%x)\n", | ||
599 | __func__, temp1, win_read); | ||
600 | } | ||
601 | addr = GET_MEM_OFFS_2M(addr) + QLA82XX_PCI_OCM0_2M; | ||
602 | |||
603 | } else if (QLA82XX_ADDR_IN_RANGE(addr, QLA82XX_ADDR_QDR_NET, | ||
604 | QLA82XX_P3_ADDR_QDR_NET_MAX)) { | ||
605 | /* QDR network side */ | ||
606 | window = MS_WIN(addr); | ||
607 | ha->qdr_sn_window = window; | ||
608 | qla82xx_wr_32(ha, | ||
609 | ha->ms_win_crb | QLA82XX_PCI_CRBSPACE, window); | ||
610 | win_read = qla82xx_rd_32(ha, | ||
611 | ha->ms_win_crb | QLA82XX_PCI_CRBSPACE); | ||
612 | if (win_read != window) { | ||
613 | qla_printk(KERN_WARNING, ha, | ||
614 | "%s: Written MSwin (0x%x) != Read MSwin (0x%x)\n", | ||
615 | __func__, window, win_read); | ||
616 | } | ||
617 | addr = GET_MEM_OFFS_2M(addr) + QLA82XX_PCI_QDR_NET; | ||
618 | } else { | ||
619 | /* | ||
620 | * peg gdb frequently accesses memory that doesn't exist, | ||
621 | * this limits the chit chat so debugging isn't slowed down. | ||
622 | */ | ||
623 | if ((qla82xx_pci_set_window_warning_count++ < 8) || | ||
624 | (qla82xx_pci_set_window_warning_count%64 == 0)) { | ||
625 | qla_printk(KERN_WARNING, ha, | ||
626 | "%s: Warning:%s Unknown address range!\n", __func__, | ||
627 | QLA2XXX_DRIVER_NAME); | ||
628 | } | ||
629 | addr = -1UL; | ||
630 | } | ||
631 | return addr; | ||
632 | } | ||
633 | |||
634 | /* check if address is in the same windows as the previous access */ | ||
635 | static int qla82xx_pci_is_same_window(struct qla_hw_data *ha, | ||
636 | unsigned long long addr) | ||
637 | { | ||
638 | int window; | ||
639 | unsigned long long qdr_max; | ||
640 | |||
641 | qdr_max = QLA82XX_P3_ADDR_QDR_NET_MAX; | ||
642 | |||
643 | /* DDR network side */ | ||
644 | if (QLA82XX_ADDR_IN_RANGE(addr, QLA82XX_ADDR_DDR_NET, | ||
645 | QLA82XX_ADDR_DDR_NET_MAX)) | ||
646 | BUG(); | ||
647 | else if (QLA82XX_ADDR_IN_RANGE(addr, QLA82XX_ADDR_OCM0, | ||
648 | QLA82XX_ADDR_OCM0_MAX)) | ||
649 | return 1; | ||
650 | else if (QLA82XX_ADDR_IN_RANGE(addr, QLA82XX_ADDR_OCM1, | ||
651 | QLA82XX_ADDR_OCM1_MAX)) | ||
652 | return 1; | ||
653 | else if (QLA82XX_ADDR_IN_RANGE(addr, QLA82XX_ADDR_QDR_NET, qdr_max)) { | ||
654 | /* QDR network side */ | ||
655 | window = ((addr - QLA82XX_ADDR_QDR_NET) >> 22) & 0x3f; | ||
656 | if (ha->qdr_sn_window == window) | ||
657 | return 1; | ||
658 | } | ||
659 | return 0; | ||
660 | } | ||
661 | |||
662 | static int qla82xx_pci_mem_read_direct(struct qla_hw_data *ha, | ||
663 | u64 off, void *data, int size) | ||
664 | { | ||
665 | unsigned long flags; | ||
666 | void *addr = NULL; | ||
667 | int ret = 0; | ||
668 | u64 start; | ||
669 | uint8_t *mem_ptr = NULL; | ||
670 | unsigned long mem_base; | ||
671 | unsigned long mem_page; | ||
672 | |||
673 | write_lock_irqsave(&ha->hw_lock, flags); | ||
674 | |||
675 | /* | ||
676 | * If attempting to access unknown address or straddle hw windows, | ||
677 | * do not access. | ||
678 | */ | ||
679 | start = qla82xx_pci_set_window(ha, off); | ||
680 | if ((start == -1UL) || | ||
681 | (qla82xx_pci_is_same_window(ha, off + size - 1) == 0)) { | ||
682 | write_unlock_irqrestore(&ha->hw_lock, flags); | ||
683 | qla_printk(KERN_ERR, ha, | ||
684 | "%s out of bound pci memory access. " | ||
685 | "offset is 0x%llx\n", QLA2XXX_DRIVER_NAME, off); | ||
686 | return -1; | ||
687 | } | ||
688 | |||
689 | write_unlock_irqrestore(&ha->hw_lock, flags); | ||
690 | mem_base = pci_resource_start(ha->pdev, 0); | ||
691 | mem_page = start & PAGE_MASK; | ||
692 | /* Map two pages whenever user tries to access addresses in two | ||
693 | * consecutive pages. | ||
694 | */ | ||
695 | if (mem_page != ((start + size - 1) & PAGE_MASK)) | ||
696 | mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE * 2); | ||
697 | else | ||
698 | mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE); | ||
699 | if (mem_ptr == 0UL) { | ||
700 | *(u8 *)data = 0; | ||
701 | return -1; | ||
702 | } | ||
703 | addr = mem_ptr; | ||
704 | addr += start & (PAGE_SIZE - 1); | ||
705 | write_lock_irqsave(&ha->hw_lock, flags); | ||
706 | |||
707 | switch (size) { | ||
708 | case 1: | ||
709 | *(u8 *)data = readb(addr); | ||
710 | break; | ||
711 | case 2: | ||
712 | *(u16 *)data = readw(addr); | ||
713 | break; | ||
714 | case 4: | ||
715 | *(u32 *)data = readl(addr); | ||
716 | break; | ||
717 | case 8: | ||
718 | *(u64 *)data = readq(addr); | ||
719 | break; | ||
720 | default: | ||
721 | ret = -1; | ||
722 | break; | ||
723 | } | ||
724 | write_unlock_irqrestore(&ha->hw_lock, flags); | ||
725 | |||
726 | if (mem_ptr) | ||
727 | iounmap(mem_ptr); | ||
728 | return ret; | ||
729 | } | ||
730 | |||
731 | static int | ||
732 | qla82xx_pci_mem_write_direct(struct qla_hw_data *ha, | ||
733 | u64 off, void *data, int size) | ||
734 | { | ||
735 | unsigned long flags; | ||
736 | void *addr = NULL; | ||
737 | int ret = 0; | ||
738 | u64 start; | ||
739 | uint8_t *mem_ptr = NULL; | ||
740 | unsigned long mem_base; | ||
741 | unsigned long mem_page; | ||
742 | |||
743 | write_lock_irqsave(&ha->hw_lock, flags); | ||
744 | |||
745 | /* | ||
746 | * If attempting to access unknown address or straddle hw windows, | ||
747 | * do not access. | ||
748 | */ | ||
749 | start = qla82xx_pci_set_window(ha, off); | ||
750 | if ((start == -1UL) || | ||
751 | (qla82xx_pci_is_same_window(ha, off + size - 1) == 0)) { | ||
752 | write_unlock_irqrestore(&ha->hw_lock, flags); | ||
753 | qla_printk(KERN_ERR, ha, | ||
754 | "%s out of bound pci memory access. " | ||
755 | "offset is 0x%llx\n", QLA2XXX_DRIVER_NAME, off); | ||
756 | return -1; | ||
757 | } | ||
758 | |||
759 | write_unlock_irqrestore(&ha->hw_lock, flags); | ||
760 | mem_base = pci_resource_start(ha->pdev, 0); | ||
761 | mem_page = start & PAGE_MASK; | ||
762 | /* Map two pages whenever user tries to access addresses in two | ||
763 | * consecutive pages. | ||
764 | */ | ||
765 | if (mem_page != ((start + size - 1) & PAGE_MASK)) | ||
766 | mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE*2); | ||
767 | else | ||
768 | mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE); | ||
769 | if (mem_ptr == 0UL) | ||
770 | return -1; | ||
771 | |||
772 | addr = mem_ptr; | ||
773 | addr += start & (PAGE_SIZE - 1); | ||
774 | write_lock_irqsave(&ha->hw_lock, flags); | ||
775 | |||
776 | switch (size) { | ||
777 | case 1: | ||
778 | writeb(*(u8 *)data, addr); | ||
779 | break; | ||
780 | case 2: | ||
781 | writew(*(u16 *)data, addr); | ||
782 | break; | ||
783 | case 4: | ||
784 | writel(*(u32 *)data, addr); | ||
785 | break; | ||
786 | case 8: | ||
787 | writeq(*(u64 *)data, addr); | ||
788 | break; | ||
789 | default: | ||
790 | ret = -1; | ||
791 | break; | ||
792 | } | ||
793 | write_unlock_irqrestore(&ha->hw_lock, flags); | ||
794 | if (mem_ptr) | ||
795 | iounmap(mem_ptr); | ||
796 | return ret; | ||
797 | } | ||
798 | |||
799 | int | ||
800 | qla82xx_wrmem(struct qla_hw_data *ha, u64 off, void *data, int size) | ||
801 | { | ||
802 | int i, j, ret = 0, loop, sz[2], off0; | ||
803 | u32 temp; | ||
804 | u64 off8, mem_crb, tmpw, word[2] = {0, 0}; | ||
805 | #define MAX_CTL_CHECK 1000 | ||
806 | /* | ||
807 | * If not MN, go check for MS or invalid. | ||
808 | */ | ||
809 | if (off >= QLA82XX_ADDR_QDR_NET && off <= QLA82XX_P3_ADDR_QDR_NET_MAX) { | ||
810 | mem_crb = QLA82XX_CRB_QDR_NET; | ||
811 | } else { | ||
812 | mem_crb = QLA82XX_CRB_DDR_NET; | ||
813 | if (qla82xx_pci_mem_bound_check(ha, off, size) == 0) | ||
814 | return qla82xx_pci_mem_write_direct(ha, off, | ||
815 | data, size); | ||
816 | } | ||
817 | |||
818 | off8 = off & 0xfffffff8; | ||
819 | off0 = off & 0x7; | ||
820 | sz[0] = (size < (8 - off0)) ? size : (8 - off0); | ||
821 | sz[1] = size - sz[0]; | ||
822 | loop = ((off0 + size - 1) >> 3) + 1; | ||
823 | |||
824 | if ((size != 8) || (off0 != 0)) { | ||
825 | for (i = 0; i < loop; i++) { | ||
826 | if (qla82xx_rdmem(ha, off8 + (i << 3), &word[i], 8)) | ||
827 | return -1; | ||
828 | } | ||
829 | } | ||
830 | |||
831 | switch (size) { | ||
832 | case 1: | ||
833 | tmpw = *((u8 *)data); | ||
834 | break; | ||
835 | case 2: | ||
836 | tmpw = *((u16 *)data); | ||
837 | break; | ||
838 | case 4: | ||
839 | tmpw = *((u32 *)data); | ||
840 | break; | ||
841 | case 8: | ||
842 | default: | ||
843 | tmpw = *((u64 *)data); | ||
844 | break; | ||
845 | } | ||
846 | |||
847 | word[0] &= ~((~(~0ULL << (sz[0] * 8))) << (off0 * 8)); | ||
848 | word[0] |= tmpw << (off0 * 8); | ||
849 | |||
850 | if (loop == 2) { | ||
851 | word[1] &= ~(~0ULL << (sz[1] * 8)); | ||
852 | word[1] |= tmpw >> (sz[0] * 8); | ||
853 | } | ||
854 | |||
855 | for (i = 0; i < loop; i++) { | ||
856 | temp = off8 + (i << 3); | ||
857 | qla82xx_wr_32(ha, mem_crb+MIU_TEST_AGT_ADDR_LO, temp); | ||
858 | temp = 0; | ||
859 | qla82xx_wr_32(ha, mem_crb+MIU_TEST_AGT_ADDR_HI, temp); | ||
860 | temp = word[i] & 0xffffffff; | ||
861 | qla82xx_wr_32(ha, mem_crb+MIU_TEST_AGT_WRDATA_LO, temp); | ||
862 | temp = (word[i] >> 32) & 0xffffffff; | ||
863 | qla82xx_wr_32(ha, mem_crb+MIU_TEST_AGT_WRDATA_HI, temp); | ||
864 | temp = MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE; | ||
865 | qla82xx_wr_32(ha, mem_crb+MIU_TEST_AGT_CTRL, temp); | ||
866 | temp = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE; | ||
867 | qla82xx_wr_32(ha, mem_crb+MIU_TEST_AGT_CTRL, temp); | ||
868 | |||
869 | for (j = 0; j < MAX_CTL_CHECK; j++) { | ||
870 | temp = qla82xx_rd_32(ha, mem_crb + MIU_TEST_AGT_CTRL); | ||
871 | if ((temp & MIU_TA_CTL_BUSY) == 0) | ||
872 | break; | ||
873 | } | ||
874 | |||
875 | if (j >= MAX_CTL_CHECK) { | ||
876 | qla_printk(KERN_WARNING, ha, | ||
877 | "%s: Fail to write through agent\n", | ||
878 | QLA2XXX_DRIVER_NAME); | ||
879 | ret = -1; | ||
880 | break; | ||
881 | } | ||
882 | } | ||
883 | return ret; | ||
884 | } | ||
885 | |||
886 | int | ||
887 | qla82xx_rdmem(struct qla_hw_data *ha, u64 off, void *data, int size) | ||
888 | { | ||
889 | int i, j = 0, k, start, end, loop, sz[2], off0[2]; | ||
890 | u32 temp; | ||
891 | u64 off8, val, mem_crb, word[2] = {0, 0}; | ||
892 | #define MAX_CTL_CHECK 1000 | ||
893 | |||
894 | /* | ||
895 | * If not MN, go check for MS or invalid. | ||
896 | */ | ||
897 | if (off >= QLA82XX_ADDR_QDR_NET && off <= QLA82XX_P3_ADDR_QDR_NET_MAX) | ||
898 | mem_crb = QLA82XX_CRB_QDR_NET; | ||
899 | else { | ||
900 | mem_crb = QLA82XX_CRB_DDR_NET; | ||
901 | if (qla82xx_pci_mem_bound_check(ha, off, size) == 0) | ||
902 | return qla82xx_pci_mem_read_direct(ha, off, | ||
903 | data, size); | ||
904 | } | ||
905 | |||
906 | off8 = off & 0xfffffff8; | ||
907 | off0[0] = off & 0x7; | ||
908 | off0[1] = 0; | ||
909 | sz[0] = (size < (8 - off0[0])) ? size : (8 - off0[0]); | ||
910 | sz[1] = size - sz[0]; | ||
911 | loop = ((off0[0] + size - 1) >> 3) + 1; | ||
912 | |||
913 | for (i = 0; i < loop; i++) { | ||
914 | temp = off8 + (i << 3); | ||
915 | qla82xx_wr_32(ha, mem_crb + MIU_TEST_AGT_ADDR_LO, temp); | ||
916 | temp = 0; | ||
917 | qla82xx_wr_32(ha, mem_crb + MIU_TEST_AGT_ADDR_HI, temp); | ||
918 | temp = MIU_TA_CTL_ENABLE; | ||
919 | qla82xx_wr_32(ha, mem_crb + MIU_TEST_AGT_CTRL, temp); | ||
920 | temp = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE; | ||
921 | qla82xx_wr_32(ha, mem_crb + MIU_TEST_AGT_CTRL, temp); | ||
922 | |||
923 | for (j = 0; j < MAX_CTL_CHECK; j++) { | ||
924 | temp = qla82xx_rd_32(ha, mem_crb + MIU_TEST_AGT_CTRL); | ||
925 | if ((temp & MIU_TA_CTL_BUSY) == 0) | ||
926 | break; | ||
927 | } | ||
928 | |||
929 | if (j >= MAX_CTL_CHECK) { | ||
930 | qla_printk(KERN_INFO, ha, | ||
931 | "%s: Fail to read through agent\n", | ||
932 | QLA2XXX_DRIVER_NAME); | ||
933 | break; | ||
934 | } | ||
935 | |||
936 | start = off0[i] >> 2; | ||
937 | end = (off0[i] + sz[i] - 1) >> 2; | ||
938 | for (k = start; k <= end; k++) { | ||
939 | temp = qla82xx_rd_32(ha, | ||
940 | mem_crb + MIU_TEST_AGT_RDDATA(k)); | ||
941 | word[i] |= ((u64)temp << (32 * k)); | ||
942 | } | ||
943 | } | ||
944 | |||
945 | if (j >= MAX_CTL_CHECK) | ||
946 | return -1; | ||
947 | |||
948 | if (sz[0] == 8) { | ||
949 | val = word[0]; | ||
950 | } else { | ||
951 | val = ((word[0] >> (off0[0] * 8)) & (~(~0ULL << (sz[0] * 8)))) | | ||
952 | ((word[1] & (~(~0ULL << (sz[1] * 8)))) << (sz[0] * 8)); | ||
953 | } | ||
954 | |||
955 | switch (size) { | ||
956 | case 1: | ||
957 | *(u8 *)data = val; | ||
958 | break; | ||
959 | case 2: | ||
960 | *(u16 *)data = val; | ||
961 | break; | ||
962 | case 4: | ||
963 | *(u32 *)data = val; | ||
964 | break; | ||
965 | case 8: | ||
966 | *(u64 *)data = val; | ||
967 | break; | ||
968 | } | ||
969 | return 0; | ||
970 | } | ||
971 | |||
972 | #define MTU_FUDGE_FACTOR 100 | ||
973 | unsigned long qla82xx_decode_crb_addr(unsigned long addr) | ||
974 | { | ||
975 | int i; | ||
976 | unsigned long base_addr, offset, pci_base; | ||
977 | |||
978 | if (!qla82xx_crb_table_initialized) | ||
979 | qla82xx_crb_addr_transform_setup(); | ||
980 | |||
981 | pci_base = ADDR_ERROR; | ||
982 | base_addr = addr & 0xfff00000; | ||
983 | offset = addr & 0x000fffff; | ||
984 | |||
985 | for (i = 0; i < MAX_CRB_XFORM; i++) { | ||
986 | if (crb_addr_xform[i] == base_addr) { | ||
987 | pci_base = i << 20; | ||
988 | break; | ||
989 | } | ||
990 | } | ||
991 | if (pci_base == ADDR_ERROR) | ||
992 | return pci_base; | ||
993 | return pci_base + offset; | ||
994 | } | ||
995 | |||
996 | static long rom_max_timeout = 100; | ||
997 | static long qla82xx_rom_lock_timeout = 100; | ||
998 | |||
999 | int | ||
1000 | qla82xx_rom_lock(struct qla_hw_data *ha) | ||
1001 | { | ||
1002 | int done = 0, timeout = 0; | ||
1003 | |||
1004 | while (!done) { | ||
1005 | /* acquire semaphore2 from PCI HW block */ | ||
1006 | done = qla82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM2_LOCK)); | ||
1007 | if (done == 1) | ||
1008 | break; | ||
1009 | if (timeout >= qla82xx_rom_lock_timeout) | ||
1010 | return -1; | ||
1011 | timeout++; | ||
1012 | } | ||
1013 | qla82xx_wr_32(ha, QLA82XX_ROM_LOCK_ID, ROM_LOCK_DRIVER); | ||
1014 | return 0; | ||
1015 | } | ||
1016 | |||
1017 | int | ||
1018 | qla82xx_wait_rom_busy(struct qla_hw_data *ha) | ||
1019 | { | ||
1020 | long timeout = 0; | ||
1021 | long done = 0 ; | ||
1022 | |||
1023 | while (done == 0) { | ||
1024 | done = qla82xx_rd_32(ha, QLA82XX_ROMUSB_GLB_STATUS); | ||
1025 | done &= 4; | ||
1026 | timeout++; | ||
1027 | if (timeout >= rom_max_timeout) { | ||
1028 | DEBUG(qla_printk(KERN_INFO, ha, | ||
1029 | "%s: Timeout reached waiting for rom busy", | ||
1030 | QLA2XXX_DRIVER_NAME)); | ||
1031 | return -1; | ||
1032 | } | ||
1033 | } | ||
1034 | return 0; | ||
1035 | } | ||
1036 | |||
1037 | int | ||
1038 | qla82xx_wait_rom_done(struct qla_hw_data *ha) | ||
1039 | { | ||
1040 | long timeout = 0; | ||
1041 | long done = 0 ; | ||
1042 | |||
1043 | while (done == 0) { | ||
1044 | done = qla82xx_rd_32(ha, QLA82XX_ROMUSB_GLB_STATUS); | ||
1045 | done &= 2; | ||
1046 | timeout++; | ||
1047 | if (timeout >= rom_max_timeout) { | ||
1048 | DEBUG(qla_printk(KERN_INFO, ha, | ||
1049 | "%s: Timeout reached waiting for rom done", | ||
1050 | QLA2XXX_DRIVER_NAME)); | ||
1051 | return -1; | ||
1052 | } | ||
1053 | } | ||
1054 | return 0; | ||
1055 | } | ||
1056 | |||
1057 | int | ||
1058 | qla82xx_do_rom_fast_read(struct qla_hw_data *ha, int addr, int *valp) | ||
1059 | { | ||
1060 | qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_ADDRESS, addr); | ||
1061 | qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_DUMMY_BYTE_CNT, 0); | ||
1062 | qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_ABYTE_CNT, 3); | ||
1063 | qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_INSTR_OPCODE, 0xb); | ||
1064 | qla82xx_wait_rom_busy(ha); | ||
1065 | if (qla82xx_wait_rom_done(ha)) { | ||
1066 | qla_printk(KERN_WARNING, ha, | ||
1067 | "%s: Error waiting for rom done\n", | ||
1068 | QLA2XXX_DRIVER_NAME); | ||
1069 | return -1; | ||
1070 | } | ||
1071 | /* Reset abyte_cnt and dummy_byte_cnt */ | ||
1072 | qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_DUMMY_BYTE_CNT, 0); | ||
1073 | udelay(10); | ||
1074 | cond_resched(); | ||
1075 | qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_ABYTE_CNT, 0); | ||
1076 | *valp = qla82xx_rd_32(ha, QLA82XX_ROMUSB_ROM_RDATA); | ||
1077 | return 0; | ||
1078 | } | ||
1079 | |||
1080 | int | ||
1081 | qla82xx_rom_fast_read(struct qla_hw_data *ha, int addr, int *valp) | ||
1082 | { | ||
1083 | int ret, loops = 0; | ||
1084 | |||
1085 | while ((qla82xx_rom_lock(ha) != 0) && (loops < 50000)) { | ||
1086 | udelay(100); | ||
1087 | schedule(); | ||
1088 | loops++; | ||
1089 | } | ||
1090 | if (loops >= 50000) { | ||
1091 | qla_printk(KERN_INFO, ha, | ||
1092 | "%s: qla82xx_rom_lock failed\n", | ||
1093 | QLA2XXX_DRIVER_NAME); | ||
1094 | return -1; | ||
1095 | } | ||
1096 | ret = qla82xx_do_rom_fast_read(ha, addr, valp); | ||
1097 | qla82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM2_UNLOCK)); | ||
1098 | return ret; | ||
1099 | } | ||
1100 | |||
1101 | int | ||
1102 | qla82xx_read_status_reg(struct qla_hw_data *ha, uint32_t *val) | ||
1103 | { | ||
1104 | qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_INSTR_OPCODE, M25P_INSTR_RDSR); | ||
1105 | qla82xx_wait_rom_busy(ha); | ||
1106 | if (qla82xx_wait_rom_done(ha)) { | ||
1107 | qla_printk(KERN_WARNING, ha, | ||
1108 | "Error waiting for rom done\n"); | ||
1109 | return -1; | ||
1110 | } | ||
1111 | *val = qla82xx_rd_32(ha, QLA82XX_ROMUSB_ROM_RDATA); | ||
1112 | return 0; | ||
1113 | } | ||
1114 | |||
1115 | int | ||
1116 | qla82xx_flash_wait_write_finish(struct qla_hw_data *ha) | ||
1117 | { | ||
1118 | long timeout = 0; | ||
1119 | uint32_t done = 1 ; | ||
1120 | uint32_t val; | ||
1121 | int ret = 0; | ||
1122 | |||
1123 | qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_ABYTE_CNT, 0); | ||
1124 | while ((done != 0) && (ret == 0)) { | ||
1125 | ret = qla82xx_read_status_reg(ha, &val); | ||
1126 | done = val & 1; | ||
1127 | timeout++; | ||
1128 | udelay(10); | ||
1129 | cond_resched(); | ||
1130 | if (timeout >= 50000) { | ||
1131 | qla_printk(KERN_WARNING, ha, | ||
1132 | "Timeout reached waiting for write finish"); | ||
1133 | return -1; | ||
1134 | } | ||
1135 | } | ||
1136 | return ret; | ||
1137 | } | ||
1138 | |||
1139 | int | ||
1140 | qla82xx_flash_set_write_enable(struct qla_hw_data *ha) | ||
1141 | { | ||
1142 | uint32_t val; | ||
1143 | qla82xx_wait_rom_busy(ha); | ||
1144 | qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_ABYTE_CNT, 0); | ||
1145 | qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_INSTR_OPCODE, M25P_INSTR_WREN); | ||
1146 | qla82xx_wait_rom_busy(ha); | ||
1147 | if (qla82xx_wait_rom_done(ha)) | ||
1148 | return -1; | ||
1149 | if (qla82xx_read_status_reg(ha, &val) != 0) | ||
1150 | return -1; | ||
1151 | if ((val & 2) != 2) | ||
1152 | return -1; | ||
1153 | return 0; | ||
1154 | } | ||
1155 | |||
1156 | int | ||
1157 | qla82xx_write_status_reg(struct qla_hw_data *ha, uint32_t val) | ||
1158 | { | ||
1159 | if (qla82xx_flash_set_write_enable(ha)) | ||
1160 | return -1; | ||
1161 | qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_WDATA, val); | ||
1162 | qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_INSTR_OPCODE, 0x1); | ||
1163 | if (qla82xx_wait_rom_done(ha)) { | ||
1164 | qla_printk(KERN_WARNING, ha, | ||
1165 | "Error waiting for rom done\n"); | ||
1166 | return -1; | ||
1167 | } | ||
1168 | return qla82xx_flash_wait_write_finish(ha); | ||
1169 | } | ||
1170 | |||
1171 | int | ||
1172 | qla82xx_write_disable_flash(struct qla_hw_data *ha) | ||
1173 | { | ||
1174 | qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_INSTR_OPCODE, M25P_INSTR_WRDI); | ||
1175 | if (qla82xx_wait_rom_done(ha)) { | ||
1176 | qla_printk(KERN_WARNING, ha, | ||
1177 | "Error waiting for rom done\n"); | ||
1178 | return -1; | ||
1179 | } | ||
1180 | return 0; | ||
1181 | } | ||
1182 | |||
1183 | int | ||
1184 | ql82xx_rom_lock_d(struct qla_hw_data *ha) | ||
1185 | { | ||
1186 | int loops = 0; | ||
1187 | while ((qla82xx_rom_lock(ha) != 0) && (loops < 50000)) { | ||
1188 | udelay(100); | ||
1189 | cond_resched(); | ||
1190 | loops++; | ||
1191 | } | ||
1192 | if (loops >= 50000) { | ||
1193 | qla_printk(KERN_WARNING, ha, "ROM lock failed\n"); | ||
1194 | return -1; | ||
1195 | } | ||
1196 | return 0;; | ||
1197 | } | ||
1198 | |||
1199 | int | ||
1200 | qla82xx_write_flash_dword(struct qla_hw_data *ha, uint32_t flashaddr, | ||
1201 | uint32_t data) | ||
1202 | { | ||
1203 | int ret = 0; | ||
1204 | |||
1205 | ret = ql82xx_rom_lock_d(ha); | ||
1206 | if (ret < 0) { | ||
1207 | qla_printk(KERN_WARNING, ha, "ROM Lock failed\n"); | ||
1208 | return ret; | ||
1209 | } | ||
1210 | |||
1211 | if (qla82xx_flash_set_write_enable(ha)) | ||
1212 | goto done_write; | ||
1213 | |||
1214 | qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_WDATA, data); | ||
1215 | qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_ADDRESS, flashaddr); | ||
1216 | qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_ABYTE_CNT, 3); | ||
1217 | qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_INSTR_OPCODE, M25P_INSTR_PP); | ||
1218 | qla82xx_wait_rom_busy(ha); | ||
1219 | if (qla82xx_wait_rom_done(ha)) { | ||
1220 | qla_printk(KERN_WARNING, ha, | ||
1221 | "Error waiting for rom done\n"); | ||
1222 | ret = -1; | ||
1223 | goto done_write; | ||
1224 | } | ||
1225 | |||
1226 | ret = qla82xx_flash_wait_write_finish(ha); | ||
1227 | |||
1228 | done_write: | ||
1229 | qla82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM2_UNLOCK)); | ||
1230 | return ret; | ||
1231 | } | ||
1232 | |||
1233 | /* This routine does CRB initialize sequence | ||
1234 | * to put the ISP into operational state | ||
1235 | */ | ||
1236 | int qla82xx_pinit_from_rom(scsi_qla_host_t *vha) | ||
1237 | { | ||
1238 | int addr, val; | ||
1239 | int i ; | ||
1240 | struct crb_addr_pair *buf; | ||
1241 | unsigned long off; | ||
1242 | unsigned offset, n; | ||
1243 | struct qla_hw_data *ha = vha->hw; | ||
1244 | |||
1245 | struct crb_addr_pair { | ||
1246 | long addr; | ||
1247 | long data; | ||
1248 | }; | ||
1249 | |||
1250 | /* Halt all the indiviual PEGs and other blocks of the ISP */ | ||
1251 | qla82xx_rom_lock(ha); | ||
1252 | if (test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags)) | ||
1253 | /* don't reset CAM block on reset */ | ||
1254 | qla82xx_wr_32(ha, QLA82XX_ROMUSB_GLB_SW_RESET, 0xfeffffff); | ||
1255 | else | ||
1256 | qla82xx_wr_32(ha, QLA82XX_ROMUSB_GLB_SW_RESET, 0xffffffff); | ||
1257 | qla82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM2_UNLOCK)); | ||
1258 | |||
1259 | /* Read the signature value from the flash. | ||
1260 | * Offset 0: Contain signature (0xcafecafe) | ||
1261 | * Offset 4: Offset and number of addr/value pairs | ||
1262 | * that present in CRB initialize sequence | ||
1263 | */ | ||
1264 | if (qla82xx_rom_fast_read(ha, 0, &n) != 0 || n != 0xcafecafeUL || | ||
1265 | qla82xx_rom_fast_read(ha, 4, &n) != 0) { | ||
1266 | qla_printk(KERN_WARNING, ha, | ||
1267 | "[ERROR] Reading crb_init area: n: %08x\n", n); | ||
1268 | return -1; | ||
1269 | } | ||
1270 | |||
1271 | /* Offset in flash = lower 16 bits | ||
1272 | * Number of enteries = upper 16 bits | ||
1273 | */ | ||
1274 | offset = n & 0xffffU; | ||
1275 | n = (n >> 16) & 0xffffU; | ||
1276 | |||
1277 | /* number of addr/value pair should not exceed 1024 enteries */ | ||
1278 | if (n >= 1024) { | ||
1279 | qla_printk(KERN_WARNING, ha, | ||
1280 | "%s: %s:n=0x%x [ERROR] Card flash not initialized.\n", | ||
1281 | QLA2XXX_DRIVER_NAME, __func__, n); | ||
1282 | return -1; | ||
1283 | } | ||
1284 | |||
1285 | qla_printk(KERN_INFO, ha, | ||
1286 | "%s: %d CRB init values found in ROM.\n", QLA2XXX_DRIVER_NAME, n); | ||
1287 | |||
1288 | buf = kmalloc(n * sizeof(struct crb_addr_pair), GFP_KERNEL); | ||
1289 | if (buf == NULL) { | ||
1290 | qla_printk(KERN_WARNING, ha, | ||
1291 | "%s: [ERROR] Unable to malloc memory.\n", | ||
1292 | QLA2XXX_DRIVER_NAME); | ||
1293 | return -1; | ||
1294 | } | ||
1295 | |||
1296 | for (i = 0; i < n; i++) { | ||
1297 | if (qla82xx_rom_fast_read(ha, 8*i + 4*offset, &val) != 0 || | ||
1298 | qla82xx_rom_fast_read(ha, 8*i + 4*offset + 4, &addr) != 0) { | ||
1299 | kfree(buf); | ||
1300 | return -1; | ||
1301 | } | ||
1302 | |||
1303 | buf[i].addr = addr; | ||
1304 | buf[i].data = val; | ||
1305 | } | ||
1306 | |||
1307 | for (i = 0; i < n; i++) { | ||
1308 | /* Translate internal CRB initialization | ||
1309 | * address to PCI bus address | ||
1310 | */ | ||
1311 | off = qla82xx_decode_crb_addr((unsigned long)buf[i].addr) + | ||
1312 | QLA82XX_PCI_CRBSPACE; | ||
1313 | /* Not all CRB addr/value pair to be written, | ||
1314 | * some of them are skipped | ||
1315 | */ | ||
1316 | |||
1317 | /* skipping cold reboot MAGIC */ | ||
1318 | if (off == QLA82XX_CAM_RAM(0x1fc)) | ||
1319 | continue; | ||
1320 | |||
1321 | /* do not reset PCI */ | ||
1322 | if (off == (ROMUSB_GLB + 0xbc)) | ||
1323 | continue; | ||
1324 | |||
1325 | /* skip core clock, so that firmware can increase the clock */ | ||
1326 | if (off == (ROMUSB_GLB + 0xc8)) | ||
1327 | continue; | ||
1328 | |||
1329 | /* skip the function enable register */ | ||
1330 | if (off == QLA82XX_PCIE_REG(PCIE_SETUP_FUNCTION)) | ||
1331 | continue; | ||
1332 | |||
1333 | if (off == QLA82XX_PCIE_REG(PCIE_SETUP_FUNCTION2)) | ||
1334 | continue; | ||
1335 | |||
1336 | if ((off & 0x0ff00000) == QLA82XX_CRB_SMB) | ||
1337 | continue; | ||
1338 | |||
1339 | if ((off & 0x0ff00000) == QLA82XX_CRB_DDR_NET) | ||
1340 | continue; | ||
1341 | |||
1342 | if (off == ADDR_ERROR) { | ||
1343 | qla_printk(KERN_WARNING, ha, | ||
1344 | "%s: [ERROR] Unknown addr: 0x%08lx\n", | ||
1345 | QLA2XXX_DRIVER_NAME, buf[i].addr); | ||
1346 | continue; | ||
1347 | } | ||
1348 | |||
1349 | if (off == (QLA82XX_CRB_PEG_NET_1 + 0x18)) { | ||
1350 | if (!QLA82XX_IS_REVISION_P3PLUS(ha->chip_revision)) | ||
1351 | buf[i].data = 0x1020; | ||
1352 | } | ||
1353 | |||
1354 | qla82xx_wr_32(ha, off, buf[i].data); | ||
1355 | |||
1356 | /* ISP requires much bigger delay to settle down, | ||
1357 | * else crb_window returns 0xffffffff | ||
1358 | */ | ||
1359 | if (off == QLA82XX_ROMUSB_GLB_SW_RESET) | ||
1360 | msleep(1000); | ||
1361 | |||
1362 | /* ISP requires millisec delay between | ||
1363 | * successive CRB register updation | ||
1364 | */ | ||
1365 | msleep(1); | ||
1366 | } | ||
1367 | |||
1368 | kfree(buf); | ||
1369 | |||
1370 | /* Resetting the data and instruction cache */ | ||
1371 | qla82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_D+0xec, 0x1e); | ||
1372 | qla82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_D+0x4c, 8); | ||
1373 | qla82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_I+0x4c, 8); | ||
1374 | |||
1375 | /* Clear all protocol processing engines */ | ||
1376 | qla82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_0+0x8, 0); | ||
1377 | qla82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_0+0xc, 0); | ||
1378 | qla82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_1+0x8, 0); | ||
1379 | qla82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_1+0xc, 0); | ||
1380 | qla82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_2+0x8, 0); | ||
1381 | qla82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_2+0xc, 0); | ||
1382 | qla82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_3+0x8, 0); | ||
1383 | qla82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_3+0xc, 0); | ||
1384 | return 0; | ||
1385 | } | ||
1386 | |||
1387 | int qla82xx_check_for_bad_spd(struct qla_hw_data *ha) | ||
1388 | { | ||
1389 | u32 val = 0; | ||
1390 | val = qla82xx_rd_32(ha, BOOT_LOADER_DIMM_STATUS); | ||
1391 | val &= QLA82XX_BOOT_LOADER_MN_ISSUE; | ||
1392 | if (val & QLA82XX_PEG_TUNE_MN_SPD_ZEROED) { | ||
1393 | qla_printk(KERN_INFO, ha, | ||
1394 | "Memory DIMM SPD not programmed. " | ||
1395 | " Assumed valid.\n"); | ||
1396 | return 1; | ||
1397 | } else if (val) { | ||
1398 | qla_printk(KERN_INFO, ha, | ||
1399 | "Memory DIMM type incorrect.Info:%08X.\n", val); | ||
1400 | return 2; | ||
1401 | } | ||
1402 | return 0; | ||
1403 | } | ||
1404 | |||
1405 | int | ||
1406 | qla82xx_fw_load_from_flash(struct qla_hw_data *ha) | ||
1407 | { | ||
1408 | int i; | ||
1409 | long size = 0; | ||
1410 | long flashaddr = BOOTLD_START, memaddr = BOOTLD_START; | ||
1411 | u64 data; | ||
1412 | u32 high, low; | ||
1413 | size = (IMAGE_START - BOOTLD_START) / 8; | ||
1414 | |||
1415 | for (i = 0; i < size; i++) { | ||
1416 | if ((qla82xx_rom_fast_read(ha, flashaddr, (int *)&low)) || | ||
1417 | (qla82xx_rom_fast_read(ha, flashaddr + 4, (int *)&high))) { | ||
1418 | return -1; | ||
1419 | } | ||
1420 | data = ((u64)high << 32) | low ; | ||
1421 | qla82xx_pci_mem_write_2M(ha, memaddr, &data, 8); | ||
1422 | flashaddr += 8; | ||
1423 | memaddr += 8; | ||
1424 | |||
1425 | if (i % 0x1000 == 0) | ||
1426 | msleep(1); | ||
1427 | } | ||
1428 | udelay(100); | ||
1429 | read_lock(&ha->hw_lock); | ||
1430 | if (QLA82XX_IS_REVISION_P3PLUS(ha->chip_revision)) { | ||
1431 | qla82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_0 + 0x18, 0x1020); | ||
1432 | qla82xx_wr_32(ha, QLA82XX_ROMUSB_GLB_SW_RESET, 0x80001e); | ||
1433 | } else { | ||
1434 | qla82xx_wr_32(ha, QLA82XX_ROMUSB_GLB_SW_RESET, 0x80001d); | ||
1435 | } | ||
1436 | read_unlock(&ha->hw_lock); | ||
1437 | return 0; | ||
1438 | } | ||
1439 | |||
1440 | int | ||
1441 | qla82xx_pci_mem_read_2M(struct qla_hw_data *ha, | ||
1442 | u64 off, void *data, int size) | ||
1443 | { | ||
1444 | int i, j = 0, k, start, end, loop, sz[2], off0[2]; | ||
1445 | int shift_amount; | ||
1446 | uint32_t temp; | ||
1447 | uint64_t off8, val, mem_crb, word[2] = {0, 0}; | ||
1448 | |||
1449 | /* | ||
1450 | * If not MN, go check for MS or invalid. | ||
1451 | */ | ||
1452 | |||
1453 | if (off >= QLA82XX_ADDR_QDR_NET && off <= QLA82XX_P3_ADDR_QDR_NET_MAX) | ||
1454 | mem_crb = QLA82XX_CRB_QDR_NET; | ||
1455 | else { | ||
1456 | mem_crb = QLA82XX_CRB_DDR_NET; | ||
1457 | if (qla82xx_pci_mem_bound_check(ha, off, size) == 0) | ||
1458 | return qla82xx_pci_mem_read_direct(ha, | ||
1459 | off, data, size); | ||
1460 | } | ||
1461 | |||
1462 | if (QLA82XX_IS_REVISION_P3PLUS(ha->chip_revision)) { | ||
1463 | off8 = off & 0xfffffff0; | ||
1464 | off0[0] = off & 0xf; | ||
1465 | sz[0] = (size < (16 - off0[0])) ? size : (16 - off0[0]); | ||
1466 | shift_amount = 4; | ||
1467 | } else { | ||
1468 | off8 = off & 0xfffffff8; | ||
1469 | off0[0] = off & 0x7; | ||
1470 | sz[0] = (size < (8 - off0[0])) ? size : (8 - off0[0]); | ||
1471 | shift_amount = 4; | ||
1472 | } | ||
1473 | loop = ((off0[0] + size - 1) >> shift_amount) + 1; | ||
1474 | off0[1] = 0; | ||
1475 | sz[1] = size - sz[0]; | ||
1476 | |||
1477 | /* | ||
1478 | * don't lock here - write_wx gets the lock if each time | ||
1479 | * write_lock_irqsave(&adapter->adapter_lock, flags); | ||
1480 | * netxen_nic_pci_change_crbwindow_128M(adapter, 0); | ||
1481 | */ | ||
1482 | |||
1483 | for (i = 0; i < loop; i++) { | ||
1484 | temp = off8 + (i << shift_amount); | ||
1485 | qla82xx_wr_32(ha, mem_crb + MIU_TEST_AGT_ADDR_LO, temp); | ||
1486 | temp = 0; | ||
1487 | qla82xx_wr_32(ha, mem_crb + MIU_TEST_AGT_ADDR_HI, temp); | ||
1488 | temp = MIU_TA_CTL_ENABLE; | ||
1489 | qla82xx_wr_32(ha, mem_crb + MIU_TEST_AGT_CTRL, temp); | ||
1490 | temp = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE; | ||
1491 | qla82xx_wr_32(ha, mem_crb + MIU_TEST_AGT_CTRL, temp); | ||
1492 | |||
1493 | for (j = 0; j < MAX_CTL_CHECK; j++) { | ||
1494 | temp = qla82xx_rd_32(ha, mem_crb + MIU_TEST_AGT_CTRL); | ||
1495 | if ((temp & MIU_TA_CTL_BUSY) == 0) | ||
1496 | break; | ||
1497 | } | ||
1498 | |||
1499 | if (j >= MAX_CTL_CHECK) { | ||
1500 | if (printk_ratelimit()) | ||
1501 | dev_err(&ha->pdev->dev, | ||
1502 | "failed to read through agent\n"); | ||
1503 | break; | ||
1504 | } | ||
1505 | |||
1506 | start = off0[i] >> 2; | ||
1507 | end = (off0[i] + sz[i] - 1) >> 2; | ||
1508 | for (k = start; k <= end; k++) { | ||
1509 | temp = qla82xx_rd_32(ha, | ||
1510 | mem_crb + MIU_TEST_AGT_RDDATA(k)); | ||
1511 | word[i] |= ((uint64_t)temp << (32 * (k & 1))); | ||
1512 | } | ||
1513 | } | ||
1514 | |||
1515 | /* | ||
1516 | * netxen_nic_pci_change_crbwindow_128M(adapter, 1); | ||
1517 | * write_unlock_irqrestore(&adapter->adapter_lock, flags); | ||
1518 | */ | ||
1519 | |||
1520 | if (j >= MAX_CTL_CHECK) | ||
1521 | return -1; | ||
1522 | |||
1523 | if ((off0[0] & 7) == 0) { | ||
1524 | val = word[0]; | ||
1525 | } else { | ||
1526 | val = ((word[0] >> (off0[0] * 8)) & (~(~0ULL << (sz[0] * 8)))) | | ||
1527 | ((word[1] & (~(~0ULL << (sz[1] * 8)))) << (sz[0] * 8)); | ||
1528 | } | ||
1529 | |||
1530 | switch (size) { | ||
1531 | case 1: | ||
1532 | *(uint8_t *)data = val; | ||
1533 | break; | ||
1534 | case 2: | ||
1535 | *(uint16_t *)data = val; | ||
1536 | break; | ||
1537 | case 4: | ||
1538 | *(uint32_t *)data = val; | ||
1539 | break; | ||
1540 | case 8: | ||
1541 | *(uint64_t *)data = val; | ||
1542 | break; | ||
1543 | } | ||
1544 | return 0; | ||
1545 | } | ||
1546 | |||
1547 | int | ||
1548 | qla82xx_pci_mem_write_2M(struct qla_hw_data *ha, | ||
1549 | u64 off, void *data, int size) | ||
1550 | { | ||
1551 | int i, j, ret = 0, loop, sz[2], off0; | ||
1552 | int scale, shift_amount, p3p, startword; | ||
1553 | uint32_t temp; | ||
1554 | uint64_t off8, mem_crb, tmpw, word[2] = {0, 0}; | ||
1555 | |||
1556 | /* | ||
1557 | * If not MN, go check for MS or invalid. | ||
1558 | */ | ||
1559 | if (off >= QLA82XX_ADDR_QDR_NET && off <= QLA82XX_P3_ADDR_QDR_NET_MAX) | ||
1560 | mem_crb = QLA82XX_CRB_QDR_NET; | ||
1561 | else { | ||
1562 | mem_crb = QLA82XX_CRB_DDR_NET; | ||
1563 | if (qla82xx_pci_mem_bound_check(ha, off, size) == 0) | ||
1564 | return qla82xx_pci_mem_write_direct(ha, | ||
1565 | off, data, size); | ||
1566 | } | ||
1567 | |||
1568 | off0 = off & 0x7; | ||
1569 | sz[0] = (size < (8 - off0)) ? size : (8 - off0); | ||
1570 | sz[1] = size - sz[0]; | ||
1571 | |||
1572 | if (QLA82XX_IS_REVISION_P3PLUS(ha->chip_revision)) { | ||
1573 | off8 = off & 0xfffffff0; | ||
1574 | loop = (((off & 0xf) + size - 1) >> 4) + 1; | ||
1575 | shift_amount = 4; | ||
1576 | scale = 2; | ||
1577 | p3p = 1; | ||
1578 | startword = (off & 0xf)/8; | ||
1579 | } else { | ||
1580 | off8 = off & 0xfffffff8; | ||
1581 | loop = ((off0 + size - 1) >> 3) + 1; | ||
1582 | shift_amount = 3; | ||
1583 | scale = 1; | ||
1584 | p3p = 0; | ||
1585 | startword = 0; | ||
1586 | } | ||
1587 | |||
1588 | if (p3p || (size != 8) || (off0 != 0)) { | ||
1589 | for (i = 0; i < loop; i++) { | ||
1590 | if (qla82xx_pci_mem_read_2M(ha, off8 + | ||
1591 | (i << shift_amount), &word[i * scale], 8)) | ||
1592 | return -1; | ||
1593 | } | ||
1594 | } | ||
1595 | |||
1596 | switch (size) { | ||
1597 | case 1: | ||
1598 | tmpw = *((uint8_t *)data); | ||
1599 | break; | ||
1600 | case 2: | ||
1601 | tmpw = *((uint16_t *)data); | ||
1602 | break; | ||
1603 | case 4: | ||
1604 | tmpw = *((uint32_t *)data); | ||
1605 | break; | ||
1606 | case 8: | ||
1607 | default: | ||
1608 | tmpw = *((uint64_t *)data); | ||
1609 | break; | ||
1610 | } | ||
1611 | |||
1612 | if (QLA82XX_IS_REVISION_P3PLUS(ha->chip_revision)) { | ||
1613 | if (sz[0] == 8) { | ||
1614 | word[startword] = tmpw; | ||
1615 | } else { | ||
1616 | word[startword] &= | ||
1617 | ~((~(~0ULL << (sz[0] * 8))) << (off0 * 8)); | ||
1618 | word[startword] |= tmpw << (off0 * 8); | ||
1619 | } | ||
1620 | if (sz[1] != 0) { | ||
1621 | word[startword+1] &= ~(~0ULL << (sz[1] * 8)); | ||
1622 | word[startword+1] |= tmpw >> (sz[0] * 8); | ||
1623 | } | ||
1624 | } else { | ||
1625 | word[startword] &= ~((~(~0ULL << (sz[0] * 8))) << (off0 * 8)); | ||
1626 | word[startword] |= tmpw << (off0 * 8); | ||
1627 | |||
1628 | if (loop == 2) { | ||
1629 | word[1] &= ~(~0ULL << (sz[1] * 8)); | ||
1630 | word[1] |= tmpw >> (sz[0] * 8); | ||
1631 | } | ||
1632 | } | ||
1633 | |||
1634 | /* | ||
1635 | * don't lock here - write_wx gets the lock if each time | ||
1636 | * write_lock_irqsave(&adapter->adapter_lock, flags); | ||
1637 | * netxen_nic_pci_change_crbwindow_128M(adapter, 0); | ||
1638 | */ | ||
1639 | for (i = 0; i < loop; i++) { | ||
1640 | temp = off8 + (i << shift_amount); | ||
1641 | qla82xx_wr_32(ha, mem_crb+MIU_TEST_AGT_ADDR_LO, temp); | ||
1642 | temp = 0; | ||
1643 | qla82xx_wr_32(ha, mem_crb+MIU_TEST_AGT_ADDR_HI, temp); | ||
1644 | temp = word[i * scale] & 0xffffffff; | ||
1645 | qla82xx_wr_32(ha, mem_crb+MIU_TEST_AGT_WRDATA_LO, temp); | ||
1646 | temp = (word[i * scale] >> 32) & 0xffffffff; | ||
1647 | qla82xx_wr_32(ha, mem_crb+MIU_TEST_AGT_WRDATA_HI, temp); | ||
1648 | if (QLA82XX_IS_REVISION_P3PLUS(ha->chip_revision)) { | ||
1649 | temp = word[i*scale + 1] & 0xffffffff; | ||
1650 | qla82xx_wr_32(ha, mem_crb + | ||
1651 | MIU_TEST_AGT_WRDATA_UPPER_LO, temp); | ||
1652 | temp = (word[i*scale + 1] >> 32) & 0xffffffff; | ||
1653 | qla82xx_wr_32(ha, mem_crb + | ||
1654 | MIU_TEST_AGT_WRDATA_UPPER_HI, temp); | ||
1655 | } | ||
1656 | |||
1657 | temp = MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE; | ||
1658 | qla82xx_wr_32(ha, mem_crb + MIU_TEST_AGT_CTRL, temp); | ||
1659 | temp = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE; | ||
1660 | qla82xx_wr_32(ha, mem_crb + MIU_TEST_AGT_CTRL, temp); | ||
1661 | |||
1662 | for (j = 0; j < MAX_CTL_CHECK; j++) { | ||
1663 | temp = qla82xx_rd_32(ha, mem_crb + MIU_TEST_AGT_CTRL); | ||
1664 | if ((temp & MIU_TA_CTL_BUSY) == 0) | ||
1665 | break; | ||
1666 | } | ||
1667 | |||
1668 | if (j >= MAX_CTL_CHECK) { | ||
1669 | if (printk_ratelimit()) | ||
1670 | dev_err(&ha->pdev->dev, | ||
1671 | "failed to write through agent\n"); | ||
1672 | ret = -1; | ||
1673 | break; | ||
1674 | } | ||
1675 | } | ||
1676 | |||
1677 | return ret; | ||
1678 | } | ||
1679 | |||
1680 | /* PCI related functions */ | ||
1681 | char * | ||
1682 | qla82xx_pci_info_str(struct scsi_qla_host *vha, char *str) | ||
1683 | { | ||
1684 | int pcie_reg; | ||
1685 | struct qla_hw_data *ha = vha->hw; | ||
1686 | char lwstr[6]; | ||
1687 | uint16_t lnk; | ||
1688 | |||
1689 | pcie_reg = pci_find_capability(ha->pdev, PCI_CAP_ID_EXP); | ||
1690 | pci_read_config_word(ha->pdev, pcie_reg + PCI_EXP_LNKSTA, &lnk); | ||
1691 | ha->link_width = (lnk >> 4) & 0x3f; | ||
1692 | |||
1693 | strcpy(str, "PCIe ("); | ||
1694 | strcat(str, "2.5Gb/s "); | ||
1695 | snprintf(lwstr, sizeof(lwstr), "x%d)", ha->link_width); | ||
1696 | strcat(str, lwstr); | ||
1697 | return str; | ||
1698 | } | ||
1699 | |||
1700 | int qla82xx_pci_region_offset(struct pci_dev *pdev, int region) | ||
1701 | { | ||
1702 | unsigned long val = 0; | ||
1703 | u32 control; | ||
1704 | |||
1705 | switch (region) { | ||
1706 | case 0: | ||
1707 | val = 0; | ||
1708 | break; | ||
1709 | case 1: | ||
1710 | pci_read_config_dword(pdev, QLA82XX_PCI_REG_MSIX_TBL, &control); | ||
1711 | val = control + QLA82XX_MSIX_TBL_SPACE; | ||
1712 | break; | ||
1713 | } | ||
1714 | return val; | ||
1715 | } | ||
1716 | |||
1717 | int qla82xx_pci_region_len(struct pci_dev *pdev, int region) | ||
1718 | { | ||
1719 | unsigned long val = 0; | ||
1720 | u32 control; | ||
1721 | switch (region) { | ||
1722 | case 0: | ||
1723 | pci_read_config_dword(pdev, QLA82XX_PCI_REG_MSIX_TBL, &control); | ||
1724 | val = control; | ||
1725 | break; | ||
1726 | case 1: | ||
1727 | val = pci_resource_len(pdev, 0) - | ||
1728 | qla82xx_pci_region_offset(pdev, 1); | ||
1729 | break; | ||
1730 | } | ||
1731 | return val; | ||
1732 | } | ||
1733 | |||
1734 | int | ||
1735 | qla82xx_iospace_config(struct qla_hw_data *ha) | ||
1736 | { | ||
1737 | uint32_t len = 0; | ||
1738 | |||
1739 | if (pci_request_regions(ha->pdev, QLA2XXX_DRIVER_NAME)) { | ||
1740 | qla_printk(KERN_WARNING, ha, | ||
1741 | "Failed to reserve selected regions (%s)\n", | ||
1742 | pci_name(ha->pdev)); | ||
1743 | goto iospace_error_exit; | ||
1744 | } | ||
1745 | |||
1746 | /* Use MMIO operations for all accesses. */ | ||
1747 | if (!(pci_resource_flags(ha->pdev, 0) & IORESOURCE_MEM)) { | ||
1748 | qla_printk(KERN_ERR, ha, | ||
1749 | "region #0 not an MMIO resource (%s), aborting\n", | ||
1750 | pci_name(ha->pdev)); | ||
1751 | goto iospace_error_exit; | ||
1752 | } | ||
1753 | |||
1754 | len = pci_resource_len(ha->pdev, 0); | ||
1755 | ha->nx_pcibase = | ||
1756 | (unsigned long)ioremap(pci_resource_start(ha->pdev, 0), len); | ||
1757 | if (!ha->nx_pcibase) { | ||
1758 | qla_printk(KERN_ERR, ha, | ||
1759 | "cannot remap pcibase MMIO (%s), aborting\n", | ||
1760 | pci_name(ha->pdev)); | ||
1761 | pci_release_regions(ha->pdev); | ||
1762 | goto iospace_error_exit; | ||
1763 | } | ||
1764 | |||
1765 | /* Mapping of IO base pointer */ | ||
1766 | ha->iobase = (device_reg_t __iomem *)((uint8_t *)ha->nx_pcibase + | ||
1767 | 0xbc000 + (ha->pdev->devfn << 11)); | ||
1768 | |||
1769 | if (!ql2xdbwr) { | ||
1770 | ha->nxdb_wr_ptr = | ||
1771 | (unsigned long)ioremap((pci_resource_start(ha->pdev, 4) + | ||
1772 | (ha->pdev->devfn << 12)), 4); | ||
1773 | if (!ha->nxdb_wr_ptr) { | ||
1774 | qla_printk(KERN_ERR, ha, | ||
1775 | "cannot remap MMIO (%s), aborting\n", | ||
1776 | pci_name(ha->pdev)); | ||
1777 | pci_release_regions(ha->pdev); | ||
1778 | goto iospace_error_exit; | ||
1779 | } | ||
1780 | |||
1781 | /* Mapping of IO base pointer, | ||
1782 | * door bell read and write pointer | ||
1783 | */ | ||
1784 | ha->nxdb_rd_ptr = (uint8_t *) ha->nx_pcibase + (512 * 1024) + | ||
1785 | (ha->pdev->devfn * 8); | ||
1786 | } else { | ||
1787 | ha->nxdb_wr_ptr = (ha->pdev->devfn == 6 ? | ||
1788 | QLA82XX_CAMRAM_DB1 : | ||
1789 | QLA82XX_CAMRAM_DB2); | ||
1790 | } | ||
1791 | |||
1792 | ha->max_req_queues = ha->max_rsp_queues = 1; | ||
1793 | ha->msix_count = ha->max_rsp_queues + 1; | ||
1794 | return 0; | ||
1795 | |||
1796 | iospace_error_exit: | ||
1797 | return -ENOMEM; | ||
1798 | } | ||
1799 | |||
1800 | /* GS related functions */ | ||
1801 | |||
1802 | /* Initialization related functions */ | ||
1803 | |||
1804 | /** | ||
1805 | * qla82xx_pci_config() - Setup ISP82xx PCI configuration registers. | ||
1806 | * @ha: HA context | ||
1807 | * | ||
1808 | * Returns 0 on success. | ||
1809 | */ | ||
1810 | int | ||
1811 | qla82xx_pci_config(scsi_qla_host_t *vha) | ||
1812 | { | ||
1813 | struct qla_hw_data *ha = vha->hw; | ||
1814 | int ret; | ||
1815 | |||
1816 | pci_set_master(ha->pdev); | ||
1817 | ret = pci_set_mwi(ha->pdev); | ||
1818 | ha->chip_revision = ha->pdev->revision; | ||
1819 | return 0; | ||
1820 | } | ||
1821 | |||
1822 | /** | ||
1823 | * qla82xx_reset_chip() - Setup ISP82xx PCI configuration registers. | ||
1824 | * @ha: HA context | ||
1825 | * | ||
1826 | * Returns 0 on success. | ||
1827 | */ | ||
1828 | void | ||
1829 | qla82xx_reset_chip(scsi_qla_host_t *vha) | ||
1830 | { | ||
1831 | struct qla_hw_data *ha = vha->hw; | ||
1832 | ha->isp_ops->disable_intrs(ha); | ||
1833 | } | ||
1834 | |||
1835 | void qla82xx_config_rings(struct scsi_qla_host *vha) | ||
1836 | { | ||
1837 | struct qla_hw_data *ha = vha->hw; | ||
1838 | struct device_reg_82xx __iomem *reg = &ha->iobase->isp82; | ||
1839 | struct init_cb_81xx *icb; | ||
1840 | struct req_que *req = ha->req_q_map[0]; | ||
1841 | struct rsp_que *rsp = ha->rsp_q_map[0]; | ||
1842 | |||
1843 | /* Setup ring parameters in initialization control block. */ | ||
1844 | icb = (struct init_cb_81xx *)ha->init_cb; | ||
1845 | icb->request_q_outpointer = __constant_cpu_to_le16(0); | ||
1846 | icb->response_q_inpointer = __constant_cpu_to_le16(0); | ||
1847 | icb->request_q_length = cpu_to_le16(req->length); | ||
1848 | icb->response_q_length = cpu_to_le16(rsp->length); | ||
1849 | icb->request_q_address[0] = cpu_to_le32(LSD(req->dma)); | ||
1850 | icb->request_q_address[1] = cpu_to_le32(MSD(req->dma)); | ||
1851 | icb->response_q_address[0] = cpu_to_le32(LSD(rsp->dma)); | ||
1852 | icb->response_q_address[1] = cpu_to_le32(MSD(rsp->dma)); | ||
1853 | |||
1854 | icb->version = 1; | ||
1855 | icb->frame_payload_size = 2112; | ||
1856 | icb->execution_throttle = 8; | ||
1857 | icb->exchange_count = 128; | ||
1858 | icb->login_retry_count = 8; | ||
1859 | |||
1860 | WRT_REG_DWORD((unsigned long __iomem *)®->req_q_out[0], 0); | ||
1861 | WRT_REG_DWORD((unsigned long __iomem *)®->rsp_q_in[0], 0); | ||
1862 | WRT_REG_DWORD((unsigned long __iomem *)®->rsp_q_out[0], 0); | ||
1863 | } | ||
1864 | |||
1865 | void qla82xx_reset_adapter(struct scsi_qla_host *vha) | ||
1866 | { | ||
1867 | struct qla_hw_data *ha = vha->hw; | ||
1868 | vha->flags.online = 0; | ||
1869 | qla2x00_try_to_stop_firmware(vha); | ||
1870 | ha->isp_ops->disable_intrs(ha); | ||
1871 | } | ||
1872 | |||
1873 | int qla82xx_fw_load_from_blob(struct qla_hw_data *ha) | ||
1874 | { | ||
1875 | u64 *ptr64; | ||
1876 | u32 i, flashaddr, size; | ||
1877 | __le64 data; | ||
1878 | |||
1879 | size = (IMAGE_START - BOOTLD_START) / 8; | ||
1880 | |||
1881 | ptr64 = (u64 *)&ha->hablob->fw->data[BOOTLD_START]; | ||
1882 | flashaddr = BOOTLD_START; | ||
1883 | |||
1884 | for (i = 0; i < size; i++) { | ||
1885 | data = cpu_to_le64(ptr64[i]); | ||
1886 | qla82xx_pci_mem_write_2M(ha, flashaddr, &data, 8); | ||
1887 | flashaddr += 8; | ||
1888 | } | ||
1889 | |||
1890 | size = *(u32 *)&ha->hablob->fw->data[FW_SIZE_OFFSET]; | ||
1891 | size = (__force u32)cpu_to_le32(size) / 8; | ||
1892 | ptr64 = (u64 *)&ha->hablob->fw->data[IMAGE_START]; | ||
1893 | flashaddr = FLASH_ADDR_START; | ||
1894 | |||
1895 | for (i = 0; i < size; i++) { | ||
1896 | data = cpu_to_le64(ptr64[i]); | ||
1897 | |||
1898 | if (qla82xx_pci_mem_write_2M(ha, flashaddr, &data, 8)) | ||
1899 | return -EIO; | ||
1900 | flashaddr += 8; | ||
1901 | } | ||
1902 | |||
1903 | /* Write a magic value to CAMRAM register | ||
1904 | * at a specified offset to indicate | ||
1905 | * that all data is written and | ||
1906 | * ready for firmware to initialize. | ||
1907 | */ | ||
1908 | qla82xx_wr_32(ha, QLA82XX_CAM_RAM(0x1fc), 0x12345678); | ||
1909 | |||
1910 | if (QLA82XX_IS_REVISION_P3PLUS(ha->chip_revision)) { | ||
1911 | qla82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_0 + 0x18, 0x1020); | ||
1912 | qla82xx_wr_32(ha, QLA82XX_ROMUSB_GLB_SW_RESET, 0x80001e); | ||
1913 | } else | ||
1914 | qla82xx_wr_32(ha, QLA82XX_ROMUSB_GLB_SW_RESET, 0x80001d); | ||
1915 | return 0; | ||
1916 | } | ||
1917 | |||
1918 | int qla82xx_check_cmdpeg_state(struct qla_hw_data *ha) | ||
1919 | { | ||
1920 | u32 val = 0; | ||
1921 | int retries = 60; | ||
1922 | |||
1923 | do { | ||
1924 | read_lock(&ha->hw_lock); | ||
1925 | val = qla82xx_rd_32(ha, CRB_CMDPEG_STATE); | ||
1926 | read_unlock(&ha->hw_lock); | ||
1927 | |||
1928 | switch (val) { | ||
1929 | case PHAN_INITIALIZE_COMPLETE: | ||
1930 | case PHAN_INITIALIZE_ACK: | ||
1931 | return QLA_SUCCESS; | ||
1932 | case PHAN_INITIALIZE_FAILED: | ||
1933 | break; | ||
1934 | default: | ||
1935 | break; | ||
1936 | } | ||
1937 | qla_printk(KERN_WARNING, ha, | ||
1938 | "CRB_CMDPEG_STATE: 0x%x and retries: 0x%x\n", | ||
1939 | val, retries); | ||
1940 | |||
1941 | msleep(500); | ||
1942 | |||
1943 | } while (--retries); | ||
1944 | |||
1945 | qla_printk(KERN_INFO, ha, | ||
1946 | "Cmd Peg initialization failed: 0x%x.\n", val); | ||
1947 | |||
1948 | qla82xx_check_for_bad_spd(ha); | ||
1949 | val = qla82xx_rd_32(ha, QLA82XX_ROMUSB_GLB_PEGTUNE_DONE); | ||
1950 | read_lock(&ha->hw_lock); | ||
1951 | qla82xx_wr_32(ha, CRB_CMDPEG_STATE, PHAN_INITIALIZE_FAILED); | ||
1952 | read_unlock(&ha->hw_lock); | ||
1953 | return QLA_FUNCTION_FAILED; | ||
1954 | } | ||
1955 | |||
1956 | int qla82xx_check_rcvpeg_state(struct qla_hw_data *ha) | ||
1957 | { | ||
1958 | u32 val = 0; | ||
1959 | int retries = 60; | ||
1960 | |||
1961 | do { | ||
1962 | read_lock(&ha->hw_lock); | ||
1963 | val = qla82xx_rd_32(ha, CRB_RCVPEG_STATE); | ||
1964 | read_unlock(&ha->hw_lock); | ||
1965 | |||
1966 | switch (val) { | ||
1967 | case PHAN_INITIALIZE_COMPLETE: | ||
1968 | case PHAN_INITIALIZE_ACK: | ||
1969 | return QLA_SUCCESS; | ||
1970 | case PHAN_INITIALIZE_FAILED: | ||
1971 | break; | ||
1972 | default: | ||
1973 | break; | ||
1974 | } | ||
1975 | |||
1976 | qla_printk(KERN_WARNING, ha, | ||
1977 | "CRB_RCVPEG_STATE: 0x%x and retries: 0x%x\n", | ||
1978 | val, retries); | ||
1979 | |||
1980 | msleep(500); | ||
1981 | |||
1982 | } while (--retries); | ||
1983 | |||
1984 | qla_printk(KERN_INFO, ha, | ||
1985 | "Rcv Peg initialization failed: 0x%x.\n", val); | ||
1986 | read_lock(&ha->hw_lock); | ||
1987 | qla82xx_wr_32(ha, CRB_RCVPEG_STATE, PHAN_INITIALIZE_FAILED); | ||
1988 | read_unlock(&ha->hw_lock); | ||
1989 | return QLA_FUNCTION_FAILED; | ||
1990 | } | ||
1991 | |||
1992 | /* ISR related functions */ | ||
1993 | uint32_t qla82xx_isr_int_target_mask_enable[8] = { | ||
1994 | ISR_INT_TARGET_MASK, ISR_INT_TARGET_MASK_F1, | ||
1995 | ISR_INT_TARGET_MASK_F2, ISR_INT_TARGET_MASK_F3, | ||
1996 | ISR_INT_TARGET_MASK_F4, ISR_INT_TARGET_MASK_F5, | ||
1997 | ISR_INT_TARGET_MASK_F7, ISR_INT_TARGET_MASK_F7 | ||
1998 | }; | ||
1999 | |||
2000 | uint32_t qla82xx_isr_int_target_status[8] = { | ||
2001 | ISR_INT_TARGET_STATUS, ISR_INT_TARGET_STATUS_F1, | ||
2002 | ISR_INT_TARGET_STATUS_F2, ISR_INT_TARGET_STATUS_F3, | ||
2003 | ISR_INT_TARGET_STATUS_F4, ISR_INT_TARGET_STATUS_F5, | ||
2004 | ISR_INT_TARGET_STATUS_F7, ISR_INT_TARGET_STATUS_F7 | ||
2005 | }; | ||
2006 | |||
2007 | static struct qla82xx_legacy_intr_set legacy_intr[] = \ | ||
2008 | QLA82XX_LEGACY_INTR_CONFIG; | ||
2009 | |||
2010 | /* | ||
2011 | * qla82xx_mbx_completion() - Process mailbox command completions. | ||
2012 | * @ha: SCSI driver HA context | ||
2013 | * @mb0: Mailbox0 register | ||
2014 | */ | ||
2015 | void | ||
2016 | qla82xx_mbx_completion(scsi_qla_host_t *vha, uint16_t mb0) | ||
2017 | { | ||
2018 | uint16_t cnt; | ||
2019 | uint16_t __iomem *wptr; | ||
2020 | struct qla_hw_data *ha = vha->hw; | ||
2021 | struct device_reg_82xx __iomem *reg = &ha->iobase->isp82; | ||
2022 | wptr = (uint16_t __iomem *)®->mailbox_out[1]; | ||
2023 | |||
2024 | /* Load return mailbox registers. */ | ||
2025 | ha->flags.mbox_int = 1; | ||
2026 | ha->mailbox_out[0] = mb0; | ||
2027 | |||
2028 | for (cnt = 1; cnt < ha->mbx_count; cnt++) { | ||
2029 | ha->mailbox_out[cnt] = RD_REG_WORD(wptr); | ||
2030 | wptr++; | ||
2031 | } | ||
2032 | |||
2033 | if (ha->mcp) { | ||
2034 | DEBUG3_11(printk(KERN_INFO "%s(%ld): " | ||
2035 | "Got mailbox completion. cmd=%x.\n", | ||
2036 | __func__, vha->host_no, ha->mcp->mb[0])); | ||
2037 | } else { | ||
2038 | qla_printk(KERN_INFO, ha, | ||
2039 | "%s(%ld): MBX pointer ERROR!\n", | ||
2040 | __func__, vha->host_no); | ||
2041 | } | ||
2042 | } | ||
2043 | |||
2044 | /* | ||
2045 | * qla82xx_intr_handler() - Process interrupts for the ISP23xx and ISP63xx. | ||
2046 | * @irq: | ||
2047 | * @dev_id: SCSI driver HA context | ||
2048 | * @regs: | ||
2049 | * | ||
2050 | * Called by system whenever the host adapter generates an interrupt. | ||
2051 | * | ||
2052 | * Returns handled flag. | ||
2053 | */ | ||
2054 | irqreturn_t | ||
2055 | qla82xx_intr_handler(int irq, void *dev_id) | ||
2056 | { | ||
2057 | scsi_qla_host_t *vha; | ||
2058 | struct qla_hw_data *ha; | ||
2059 | struct rsp_que *rsp; | ||
2060 | struct device_reg_82xx __iomem *reg; | ||
2061 | int status = 0, status1 = 0; | ||
2062 | unsigned long flags; | ||
2063 | unsigned long iter; | ||
2064 | uint32_t stat; | ||
2065 | uint16_t mb[4]; | ||
2066 | |||
2067 | rsp = (struct rsp_que *) dev_id; | ||
2068 | if (!rsp) { | ||
2069 | printk(KERN_INFO | ||
2070 | "%s(): NULL response queue pointer\n", __func__); | ||
2071 | return IRQ_NONE; | ||
2072 | } | ||
2073 | ha = rsp->hw; | ||
2074 | |||
2075 | if (!ha->flags.msi_enabled) { | ||
2076 | status = qla82xx_rd_32(ha, ISR_INT_VECTOR); | ||
2077 | if (!(status & ha->nx_legacy_intr.int_vec_bit)) | ||
2078 | return IRQ_NONE; | ||
2079 | |||
2080 | status1 = qla82xx_rd_32(ha, ISR_INT_STATE_REG); | ||
2081 | if (!ISR_IS_LEGACY_INTR_TRIGGERED(status1)) | ||
2082 | return IRQ_NONE; | ||
2083 | } | ||
2084 | |||
2085 | /* clear the interrupt */ | ||
2086 | qla82xx_wr_32(ha, ha->nx_legacy_intr.tgt_status_reg, 0xffffffff); | ||
2087 | |||
2088 | /* read twice to ensure write is flushed */ | ||
2089 | qla82xx_rd_32(ha, ISR_INT_VECTOR); | ||
2090 | qla82xx_rd_32(ha, ISR_INT_VECTOR); | ||
2091 | |||
2092 | reg = &ha->iobase->isp82; | ||
2093 | |||
2094 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
2095 | vha = pci_get_drvdata(ha->pdev); | ||
2096 | for (iter = 1; iter--; ) { | ||
2097 | |||
2098 | if (RD_REG_DWORD(®->host_int)) { | ||
2099 | stat = RD_REG_DWORD(®->host_status); | ||
2100 | if ((stat & HSRX_RISC_INT) == 0) | ||
2101 | break; | ||
2102 | |||
2103 | switch (stat & 0xff) { | ||
2104 | case 0x1: | ||
2105 | case 0x2: | ||
2106 | case 0x10: | ||
2107 | case 0x11: | ||
2108 | qla82xx_mbx_completion(vha, MSW(stat)); | ||
2109 | status |= MBX_INTERRUPT; | ||
2110 | break; | ||
2111 | case 0x12: | ||
2112 | mb[0] = MSW(stat); | ||
2113 | mb[1] = RD_REG_WORD(®->mailbox_out[1]); | ||
2114 | mb[2] = RD_REG_WORD(®->mailbox_out[2]); | ||
2115 | mb[3] = RD_REG_WORD(®->mailbox_out[3]); | ||
2116 | qla2x00_async_event(vha, rsp, mb); | ||
2117 | break; | ||
2118 | case 0x13: | ||
2119 | qla24xx_process_response_queue(vha, rsp); | ||
2120 | break; | ||
2121 | default: | ||
2122 | DEBUG2(printk("scsi(%ld): " | ||
2123 | " Unrecognized interrupt type (%d).\n", | ||
2124 | vha->host_no, stat & 0xff)); | ||
2125 | break; | ||
2126 | } | ||
2127 | } | ||
2128 | WRT_REG_DWORD(®->host_int, 0); | ||
2129 | } | ||
2130 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
2131 | if (!ha->flags.msi_enabled) | ||
2132 | qla82xx_wr_32(ha, ha->nx_legacy_intr.tgt_mask_reg, 0xfbff); | ||
2133 | |||
2134 | #ifdef QL_DEBUG_LEVEL_17 | ||
2135 | if (!irq && ha->flags.eeh_busy) | ||
2136 | qla_printk(KERN_WARNING, ha, | ||
2137 | "isr: status %x, cmd_flags %lx, mbox_int %x, stat %x\n", | ||
2138 | status, ha->mbx_cmd_flags, ha->flags.mbox_int, stat); | ||
2139 | #endif | ||
2140 | |||
2141 | if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) && | ||
2142 | (status & MBX_INTERRUPT) && ha->flags.mbox_int) { | ||
2143 | set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); | ||
2144 | complete(&ha->mbx_intr_comp); | ||
2145 | } | ||
2146 | return IRQ_HANDLED; | ||
2147 | } | ||
2148 | |||
2149 | irqreturn_t | ||
2150 | qla82xx_msix_default(int irq, void *dev_id) | ||
2151 | { | ||
2152 | scsi_qla_host_t *vha; | ||
2153 | struct qla_hw_data *ha; | ||
2154 | struct rsp_que *rsp; | ||
2155 | struct device_reg_82xx __iomem *reg; | ||
2156 | int status = 0; | ||
2157 | unsigned long flags; | ||
2158 | uint32_t stat; | ||
2159 | uint16_t mb[4]; | ||
2160 | |||
2161 | rsp = (struct rsp_que *) dev_id; | ||
2162 | if (!rsp) { | ||
2163 | printk(KERN_INFO | ||
2164 | "%s(): NULL response queue pointer\n", __func__); | ||
2165 | return IRQ_NONE; | ||
2166 | } | ||
2167 | ha = rsp->hw; | ||
2168 | |||
2169 | reg = &ha->iobase->isp82; | ||
2170 | |||
2171 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
2172 | vha = pci_get_drvdata(ha->pdev); | ||
2173 | do { | ||
2174 | if (RD_REG_DWORD(®->host_int)) { | ||
2175 | stat = RD_REG_DWORD(®->host_status); | ||
2176 | if ((stat & HSRX_RISC_INT) == 0) | ||
2177 | break; | ||
2178 | |||
2179 | switch (stat & 0xff) { | ||
2180 | case 0x1: | ||
2181 | case 0x2: | ||
2182 | case 0x10: | ||
2183 | case 0x11: | ||
2184 | qla82xx_mbx_completion(vha, MSW(stat)); | ||
2185 | status |= MBX_INTERRUPT; | ||
2186 | break; | ||
2187 | case 0x12: | ||
2188 | mb[0] = MSW(stat); | ||
2189 | mb[1] = RD_REG_WORD(®->mailbox_out[1]); | ||
2190 | mb[2] = RD_REG_WORD(®->mailbox_out[2]); | ||
2191 | mb[3] = RD_REG_WORD(®->mailbox_out[3]); | ||
2192 | qla2x00_async_event(vha, rsp, mb); | ||
2193 | break; | ||
2194 | case 0x13: | ||
2195 | qla24xx_process_response_queue(vha, rsp); | ||
2196 | break; | ||
2197 | default: | ||
2198 | DEBUG2(printk("scsi(%ld): " | ||
2199 | " Unrecognized interrupt type (%d).\n", | ||
2200 | vha->host_no, stat & 0xff)); | ||
2201 | break; | ||
2202 | } | ||
2203 | } | ||
2204 | WRT_REG_DWORD(®->host_int, 0); | ||
2205 | } while (0); | ||
2206 | |||
2207 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
2208 | |||
2209 | #ifdef QL_DEBUG_LEVEL_17 | ||
2210 | if (!irq && ha->flags.eeh_busy) | ||
2211 | qla_printk(KERN_WARNING, ha, | ||
2212 | "isr: status %x, cmd_flags %lx, mbox_int %x, stat %x\n", | ||
2213 | status, ha->mbx_cmd_flags, ha->flags.mbox_int, stat); | ||
2214 | #endif | ||
2215 | |||
2216 | if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) && | ||
2217 | (status & MBX_INTERRUPT) && ha->flags.mbox_int) { | ||
2218 | set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); | ||
2219 | complete(&ha->mbx_intr_comp); | ||
2220 | } | ||
2221 | return IRQ_HANDLED; | ||
2222 | } | ||
2223 | |||
2224 | irqreturn_t | ||
2225 | qla82xx_msix_rsp_q(int irq, void *dev_id) | ||
2226 | { | ||
2227 | scsi_qla_host_t *vha; | ||
2228 | struct qla_hw_data *ha; | ||
2229 | struct rsp_que *rsp; | ||
2230 | struct device_reg_82xx __iomem *reg; | ||
2231 | |||
2232 | rsp = (struct rsp_que *) dev_id; | ||
2233 | if (!rsp) { | ||
2234 | printk(KERN_INFO | ||
2235 | "%s(): NULL response queue pointer\n", __func__); | ||
2236 | return IRQ_NONE; | ||
2237 | } | ||
2238 | |||
2239 | ha = rsp->hw; | ||
2240 | reg = &ha->iobase->isp82; | ||
2241 | spin_lock_irq(&ha->hardware_lock); | ||
2242 | vha = pci_get_drvdata(ha->pdev); | ||
2243 | qla24xx_process_response_queue(vha, rsp); | ||
2244 | WRT_REG_DWORD(®->host_int, 0); | ||
2245 | spin_unlock_irq(&ha->hardware_lock); | ||
2246 | return IRQ_HANDLED; | ||
2247 | } | ||
2248 | |||
2249 | void | ||
2250 | qla82xx_poll(int irq, void *dev_id) | ||
2251 | { | ||
2252 | scsi_qla_host_t *vha; | ||
2253 | struct qla_hw_data *ha; | ||
2254 | struct rsp_que *rsp; | ||
2255 | struct device_reg_82xx __iomem *reg; | ||
2256 | int status = 0; | ||
2257 | uint32_t stat; | ||
2258 | uint16_t mb[4]; | ||
2259 | unsigned long flags; | ||
2260 | |||
2261 | rsp = (struct rsp_que *) dev_id; | ||
2262 | if (!rsp) { | ||
2263 | printk(KERN_INFO | ||
2264 | "%s(): NULL response queue pointer\n", __func__); | ||
2265 | return; | ||
2266 | } | ||
2267 | ha = rsp->hw; | ||
2268 | |||
2269 | reg = &ha->iobase->isp82; | ||
2270 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
2271 | vha = pci_get_drvdata(ha->pdev); | ||
2272 | |||
2273 | if (RD_REG_DWORD(®->host_int)) { | ||
2274 | stat = RD_REG_DWORD(®->host_status); | ||
2275 | switch (stat & 0xff) { | ||
2276 | case 0x1: | ||
2277 | case 0x2: | ||
2278 | case 0x10: | ||
2279 | case 0x11: | ||
2280 | qla82xx_mbx_completion(vha, MSW(stat)); | ||
2281 | status |= MBX_INTERRUPT; | ||
2282 | break; | ||
2283 | case 0x12: | ||
2284 | mb[0] = MSW(stat); | ||
2285 | mb[1] = RD_REG_WORD(®->mailbox_out[1]); | ||
2286 | mb[2] = RD_REG_WORD(®->mailbox_out[2]); | ||
2287 | mb[3] = RD_REG_WORD(®->mailbox_out[3]); | ||
2288 | qla2x00_async_event(vha, rsp, mb); | ||
2289 | break; | ||
2290 | case 0x13: | ||
2291 | qla24xx_process_response_queue(vha, rsp); | ||
2292 | break; | ||
2293 | default: | ||
2294 | DEBUG2(printk("scsi(%ld): Unrecognized interrupt type " | ||
2295 | "(%d).\n", | ||
2296 | vha->host_no, stat & 0xff)); | ||
2297 | break; | ||
2298 | } | ||
2299 | } | ||
2300 | WRT_REG_DWORD(®->host_int, 0); | ||
2301 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
2302 | } | ||
2303 | |||
2304 | void | ||
2305 | qla82xx_enable_intrs(struct qla_hw_data *ha) | ||
2306 | { | ||
2307 | scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev); | ||
2308 | qla82xx_mbx_intr_enable(vha); | ||
2309 | spin_lock_irq(&ha->hardware_lock); | ||
2310 | qla82xx_wr_32(ha, ha->nx_legacy_intr.tgt_mask_reg, 0xfbff); | ||
2311 | spin_unlock_irq(&ha->hardware_lock); | ||
2312 | ha->interrupts_on = 1; | ||
2313 | } | ||
2314 | |||
2315 | void | ||
2316 | qla82xx_disable_intrs(struct qla_hw_data *ha) | ||
2317 | { | ||
2318 | scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev); | ||
2319 | qla82xx_mbx_intr_disable(vha); | ||
2320 | spin_lock_irq(&ha->hardware_lock); | ||
2321 | qla82xx_wr_32(ha, ha->nx_legacy_intr.tgt_mask_reg, 0x0400); | ||
2322 | spin_unlock_irq(&ha->hardware_lock); | ||
2323 | ha->interrupts_on = 0; | ||
2324 | } | ||
2325 | |||
2326 | void qla82xx_init_flags(struct qla_hw_data *ha) | ||
2327 | { | ||
2328 | struct qla82xx_legacy_intr_set *nx_legacy_intr; | ||
2329 | |||
2330 | /* ISP 8021 initializations */ | ||
2331 | rwlock_init(&ha->hw_lock); | ||
2332 | ha->qdr_sn_window = -1; | ||
2333 | ha->ddr_mn_window = -1; | ||
2334 | ha->curr_window = 255; | ||
2335 | ha->portnum = PCI_FUNC(ha->pdev->devfn); | ||
2336 | nx_legacy_intr = &legacy_intr[ha->portnum]; | ||
2337 | ha->nx_legacy_intr.int_vec_bit = nx_legacy_intr->int_vec_bit; | ||
2338 | ha->nx_legacy_intr.tgt_status_reg = nx_legacy_intr->tgt_status_reg; | ||
2339 | ha->nx_legacy_intr.tgt_mask_reg = nx_legacy_intr->tgt_mask_reg; | ||
2340 | ha->nx_legacy_intr.pci_int_reg = nx_legacy_intr->pci_int_reg; | ||
2341 | } | ||
2342 | |||
2343 | static inline void | ||
2344 | qla82xx_set_drv_active(scsi_qla_host_t *vha) | ||
2345 | { | ||
2346 | uint32_t drv_active; | ||
2347 | struct qla_hw_data *ha = vha->hw; | ||
2348 | |||
2349 | drv_active = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE); | ||
2350 | |||
2351 | /* If reset value is all FF's, initialize DRV_ACTIVE */ | ||
2352 | if (drv_active == 0xffffffff) { | ||
2353 | qla82xx_wr_32(ha, QLA82XX_CRB_DRV_ACTIVE, 0); | ||
2354 | drv_active = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE); | ||
2355 | } | ||
2356 | drv_active |= (1 << (ha->portnum * 4)); | ||
2357 | qla82xx_wr_32(ha, QLA82XX_CRB_DRV_ACTIVE, drv_active); | ||
2358 | } | ||
2359 | |||
2360 | inline void | ||
2361 | qla82xx_clear_drv_active(struct qla_hw_data *ha) | ||
2362 | { | ||
2363 | uint32_t drv_active; | ||
2364 | |||
2365 | drv_active = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE); | ||
2366 | drv_active &= ~(1 << (ha->portnum * 4)); | ||
2367 | qla82xx_wr_32(ha, QLA82XX_CRB_DRV_ACTIVE, drv_active); | ||
2368 | } | ||
2369 | |||
2370 | static inline int | ||
2371 | qla82xx_need_reset(struct qla_hw_data *ha) | ||
2372 | { | ||
2373 | uint32_t drv_state; | ||
2374 | int rval; | ||
2375 | |||
2376 | drv_state = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE); | ||
2377 | rval = drv_state & (1 << (ha->portnum * 4)); | ||
2378 | return rval; | ||
2379 | } | ||
2380 | |||
2381 | static inline void | ||
2382 | qla82xx_set_rst_ready(struct qla_hw_data *ha) | ||
2383 | { | ||
2384 | uint32_t drv_state; | ||
2385 | scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev); | ||
2386 | |||
2387 | drv_state = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE); | ||
2388 | |||
2389 | /* If reset value is all FF's, initialize DRV_STATE */ | ||
2390 | if (drv_state == 0xffffffff) { | ||
2391 | qla82xx_wr_32(ha, QLA82XX_CRB_DRV_STATE, 0); | ||
2392 | drv_state = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE); | ||
2393 | } | ||
2394 | drv_state |= (QLA82XX_DRVST_RST_RDY << (ha->portnum * 4)); | ||
2395 | qla_printk(KERN_INFO, ha, | ||
2396 | "%s(%ld):drv_state = 0x%x\n", | ||
2397 | __func__, vha->host_no, drv_state); | ||
2398 | qla82xx_wr_32(ha, QLA82XX_CRB_DRV_STATE, drv_state); | ||
2399 | } | ||
2400 | |||
2401 | static inline void | ||
2402 | qla82xx_clear_rst_ready(struct qla_hw_data *ha) | ||
2403 | { | ||
2404 | uint32_t drv_state; | ||
2405 | |||
2406 | drv_state = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE); | ||
2407 | drv_state &= ~(QLA82XX_DRVST_RST_RDY << (ha->portnum * 4)); | ||
2408 | qla82xx_wr_32(ha, QLA82XX_CRB_DRV_STATE, drv_state); | ||
2409 | } | ||
2410 | |||
2411 | static inline void | ||
2412 | qla82xx_set_qsnt_ready(struct qla_hw_data *ha) | ||
2413 | { | ||
2414 | uint32_t qsnt_state; | ||
2415 | |||
2416 | qsnt_state = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE); | ||
2417 | qsnt_state |= (QLA82XX_DRVST_QSNT_RDY << (ha->portnum * 4)); | ||
2418 | qla82xx_wr_32(ha, QLA82XX_CRB_DRV_STATE, qsnt_state); | ||
2419 | } | ||
2420 | |||
2421 | int qla82xx_load_fw(scsi_qla_host_t *vha) | ||
2422 | { | ||
2423 | int rst; | ||
2424 | struct fw_blob *blob; | ||
2425 | struct qla_hw_data *ha = vha->hw; | ||
2426 | |||
2427 | /* Put both the PEG CMD and RCV PEG to default state | ||
2428 | * of 0 before resetting the hardware | ||
2429 | */ | ||
2430 | qla82xx_wr_32(ha, CRB_CMDPEG_STATE, 0); | ||
2431 | qla82xx_wr_32(ha, CRB_RCVPEG_STATE, 0); | ||
2432 | |||
2433 | if (qla82xx_pinit_from_rom(vha) != QLA_SUCCESS) { | ||
2434 | qla_printk(KERN_ERR, ha, | ||
2435 | "%s: Error during CRB Initialization\n", __func__); | ||
2436 | return QLA_FUNCTION_FAILED; | ||
2437 | } | ||
2438 | udelay(500); | ||
2439 | |||
2440 | /* Bring QM and CAMRAM out of reset */ | ||
2441 | rst = qla82xx_rd_32(ha, QLA82XX_ROMUSB_GLB_SW_RESET); | ||
2442 | rst &= ~((1 << 28) | (1 << 24)); | ||
2443 | qla82xx_wr_32(ha, QLA82XX_ROMUSB_GLB_SW_RESET, rst); | ||
2444 | |||
2445 | /* | ||
2446 | * FW Load priority: | ||
2447 | * 1) Operational firmware residing in flash. | ||
2448 | * 2) Firmware via request-firmware interface (.bin file). | ||
2449 | */ | ||
2450 | if (ql2xfwloadbin == 2) | ||
2451 | goto try_blob_fw; | ||
2452 | |||
2453 | qla_printk(KERN_INFO, ha, | ||
2454 | "Attempting to load firmware from flash\n"); | ||
2455 | |||
2456 | if (qla82xx_fw_load_from_flash(ha) == QLA_SUCCESS) { | ||
2457 | qla_printk(KERN_ERR, ha, | ||
2458 | "Firmware loaded successfully from flash\n"); | ||
2459 | return QLA_SUCCESS; | ||
2460 | } | ||
2461 | try_blob_fw: | ||
2462 | qla_printk(KERN_INFO, ha, | ||
2463 | "Attempting to load firmware from blob\n"); | ||
2464 | |||
2465 | /* Load firmware blob. */ | ||
2466 | blob = ha->hablob = qla2x00_request_firmware(vha); | ||
2467 | if (!blob) { | ||
2468 | qla_printk(KERN_ERR, ha, | ||
2469 | "Firmware image not present.\n"); | ||
2470 | goto fw_load_failed; | ||
2471 | } | ||
2472 | |||
2473 | if (qla82xx_fw_load_from_blob(ha) == QLA_SUCCESS) { | ||
2474 | qla_printk(KERN_ERR, ha, | ||
2475 | "%s: Firmware loaded successfully " | ||
2476 | " from binary blob\n", __func__); | ||
2477 | return QLA_SUCCESS; | ||
2478 | } else { | ||
2479 | qla_printk(KERN_ERR, ha, | ||
2480 | "Firmware load failed from binary blob\n"); | ||
2481 | blob->fw = NULL; | ||
2482 | blob = NULL; | ||
2483 | goto fw_load_failed; | ||
2484 | } | ||
2485 | return QLA_SUCCESS; | ||
2486 | |||
2487 | fw_load_failed: | ||
2488 | return QLA_FUNCTION_FAILED; | ||
2489 | } | ||
2490 | |||
2491 | static int | ||
2492 | qla82xx_start_firmware(scsi_qla_host_t *vha) | ||
2493 | { | ||
2494 | int pcie_cap; | ||
2495 | uint16_t lnk; | ||
2496 | struct qla_hw_data *ha = vha->hw; | ||
2497 | |||
2498 | /* scrub dma mask expansion register */ | ||
2499 | qla82xx_wr_32(ha, CRB_DMA_SHIFT, 0x55555555); | ||
2500 | |||
2501 | /* Overwrite stale initialization register values */ | ||
2502 | qla82xx_wr_32(ha, QLA82XX_PEG_HALT_STATUS1, 0); | ||
2503 | qla82xx_wr_32(ha, QLA82XX_PEG_HALT_STATUS2, 0); | ||
2504 | |||
2505 | if (qla82xx_load_fw(vha) != QLA_SUCCESS) { | ||
2506 | qla_printk(KERN_INFO, ha, | ||
2507 | "%s: Error trying to start fw!\n", __func__); | ||
2508 | return QLA_FUNCTION_FAILED; | ||
2509 | } | ||
2510 | |||
2511 | /* Handshake with the card before we register the devices. */ | ||
2512 | if (qla82xx_check_cmdpeg_state(ha) != QLA_SUCCESS) { | ||
2513 | qla_printk(KERN_INFO, ha, | ||
2514 | "%s: Error during card handshake!\n", __func__); | ||
2515 | return QLA_FUNCTION_FAILED; | ||
2516 | } | ||
2517 | |||
2518 | /* Negotiated Link width */ | ||
2519 | pcie_cap = pci_find_capability(ha->pdev, PCI_CAP_ID_EXP); | ||
2520 | pci_read_config_word(ha->pdev, pcie_cap + PCI_EXP_LNKSTA, &lnk); | ||
2521 | ha->link_width = (lnk >> 4) & 0x3f; | ||
2522 | |||
2523 | /* Synchronize with Receive peg */ | ||
2524 | return qla82xx_check_rcvpeg_state(ha); | ||
2525 | } | ||
2526 | |||
2527 | static inline int | ||
2528 | qla2xx_build_scsi_type_6_iocbs(srb_t *sp, struct cmd_type_6 *cmd_pkt, | ||
2529 | uint16_t tot_dsds) | ||
2530 | { | ||
2531 | uint32_t *cur_dsd = NULL; | ||
2532 | scsi_qla_host_t *vha; | ||
2533 | struct qla_hw_data *ha; | ||
2534 | struct scsi_cmnd *cmd; | ||
2535 | struct scatterlist *cur_seg; | ||
2536 | uint32_t *dsd_seg; | ||
2537 | void *next_dsd; | ||
2538 | uint8_t avail_dsds; | ||
2539 | uint8_t first_iocb = 1; | ||
2540 | uint32_t dsd_list_len; | ||
2541 | struct dsd_dma *dsd_ptr; | ||
2542 | struct ct6_dsd *ctx; | ||
2543 | |||
2544 | cmd = sp->cmd; | ||
2545 | |||
2546 | /* Update entry type to indicate Command Type 3 IOCB */ | ||
2547 | *((uint32_t *)(&cmd_pkt->entry_type)) = | ||
2548 | __constant_cpu_to_le32(COMMAND_TYPE_6); | ||
2549 | |||
2550 | /* No data transfer */ | ||
2551 | if (!scsi_bufflen(cmd) || cmd->sc_data_direction == DMA_NONE) { | ||
2552 | cmd_pkt->byte_count = __constant_cpu_to_le32(0); | ||
2553 | return 0; | ||
2554 | } | ||
2555 | |||
2556 | vha = sp->fcport->vha; | ||
2557 | ha = vha->hw; | ||
2558 | |||
2559 | /* Set transfer direction */ | ||
2560 | if (cmd->sc_data_direction == DMA_TO_DEVICE) { | ||
2561 | cmd_pkt->control_flags = | ||
2562 | __constant_cpu_to_le16(CF_WRITE_DATA); | ||
2563 | ha->qla_stats.output_bytes += scsi_bufflen(cmd); | ||
2564 | } else if (cmd->sc_data_direction == DMA_FROM_DEVICE) { | ||
2565 | cmd_pkt->control_flags = | ||
2566 | __constant_cpu_to_le16(CF_READ_DATA); | ||
2567 | ha->qla_stats.input_bytes += scsi_bufflen(cmd); | ||
2568 | } | ||
2569 | |||
2570 | cur_seg = scsi_sglist(cmd); | ||
2571 | ctx = sp->ctx; | ||
2572 | |||
2573 | while (tot_dsds) { | ||
2574 | avail_dsds = (tot_dsds > QLA_DSDS_PER_IOCB) ? | ||
2575 | QLA_DSDS_PER_IOCB : tot_dsds; | ||
2576 | tot_dsds -= avail_dsds; | ||
2577 | dsd_list_len = (avail_dsds + 1) * QLA_DSD_SIZE; | ||
2578 | |||
2579 | dsd_ptr = list_first_entry(&ha->gbl_dsd_list, | ||
2580 | struct dsd_dma, list); | ||
2581 | next_dsd = dsd_ptr->dsd_addr; | ||
2582 | list_del(&dsd_ptr->list); | ||
2583 | ha->gbl_dsd_avail--; | ||
2584 | list_add_tail(&dsd_ptr->list, &ctx->dsd_list); | ||
2585 | ctx->dsd_use_cnt++; | ||
2586 | ha->gbl_dsd_inuse++; | ||
2587 | |||
2588 | if (first_iocb) { | ||
2589 | first_iocb = 0; | ||
2590 | dsd_seg = (uint32_t *)&cmd_pkt->fcp_data_dseg_address; | ||
2591 | *dsd_seg++ = cpu_to_le32(LSD(dsd_ptr->dsd_list_dma)); | ||
2592 | *dsd_seg++ = cpu_to_le32(MSD(dsd_ptr->dsd_list_dma)); | ||
2593 | *dsd_seg++ = dsd_list_len; | ||
2594 | } else { | ||
2595 | *cur_dsd++ = cpu_to_le32(LSD(dsd_ptr->dsd_list_dma)); | ||
2596 | *cur_dsd++ = cpu_to_le32(MSD(dsd_ptr->dsd_list_dma)); | ||
2597 | *cur_dsd++ = dsd_list_len; | ||
2598 | } | ||
2599 | cur_dsd = (uint32_t *)next_dsd; | ||
2600 | while (avail_dsds) { | ||
2601 | dma_addr_t sle_dma; | ||
2602 | |||
2603 | sle_dma = sg_dma_address(cur_seg); | ||
2604 | *cur_dsd++ = cpu_to_le32(LSD(sle_dma)); | ||
2605 | *cur_dsd++ = cpu_to_le32(MSD(sle_dma)); | ||
2606 | *cur_dsd++ = cpu_to_le32(sg_dma_len(cur_seg)); | ||
2607 | cur_seg++; | ||
2608 | avail_dsds--; | ||
2609 | } | ||
2610 | } | ||
2611 | |||
2612 | /* Null termination */ | ||
2613 | *cur_dsd++ = 0; | ||
2614 | *cur_dsd++ = 0; | ||
2615 | *cur_dsd++ = 0; | ||
2616 | cmd_pkt->control_flags |= CF_DATA_SEG_DESCR_ENABLE; | ||
2617 | return 0; | ||
2618 | } | ||
2619 | |||
2620 | /* | ||
2621 | * qla82xx_calc_dsd_lists() - Determine number of DSD list required | ||
2622 | * for Command Type 6. | ||
2623 | * | ||
2624 | * @dsds: number of data segment decriptors needed | ||
2625 | * | ||
2626 | * Returns the number of dsd list needed to store @dsds. | ||
2627 | */ | ||
2628 | inline uint16_t | ||
2629 | qla82xx_calc_dsd_lists(uint16_t dsds) | ||
2630 | { | ||
2631 | uint16_t dsd_lists = 0; | ||
2632 | |||
2633 | dsd_lists = (dsds/QLA_DSDS_PER_IOCB); | ||
2634 | if (dsds % QLA_DSDS_PER_IOCB) | ||
2635 | dsd_lists++; | ||
2636 | return dsd_lists; | ||
2637 | } | ||
2638 | |||
2639 | /* | ||
2640 | * qla82xx_start_scsi() - Send a SCSI command to the ISP | ||
2641 | * @sp: command to send to the ISP | ||
2642 | * | ||
2643 | * Returns non-zero if a failure occured, else zero. | ||
2644 | */ | ||
2645 | int | ||
2646 | qla82xx_start_scsi(srb_t *sp) | ||
2647 | { | ||
2648 | int ret, nseg; | ||
2649 | unsigned long flags; | ||
2650 | struct scsi_cmnd *cmd; | ||
2651 | uint32_t *clr_ptr; | ||
2652 | uint32_t index; | ||
2653 | uint32_t handle; | ||
2654 | uint16_t cnt; | ||
2655 | uint16_t req_cnt; | ||
2656 | uint16_t tot_dsds; | ||
2657 | struct device_reg_82xx __iomem *reg; | ||
2658 | uint32_t dbval; | ||
2659 | uint32_t *fcp_dl; | ||
2660 | uint8_t additional_cdb_len; | ||
2661 | struct ct6_dsd *ctx; | ||
2662 | struct scsi_qla_host *vha = sp->fcport->vha; | ||
2663 | struct qla_hw_data *ha = vha->hw; | ||
2664 | struct req_que *req = NULL; | ||
2665 | struct rsp_que *rsp = NULL; | ||
2666 | |||
2667 | /* Setup device pointers. */ | ||
2668 | ret = 0; | ||
2669 | reg = &ha->iobase->isp82; | ||
2670 | cmd = sp->cmd; | ||
2671 | req = vha->req; | ||
2672 | rsp = ha->rsp_q_map[0]; | ||
2673 | |||
2674 | /* So we know we haven't pci_map'ed anything yet */ | ||
2675 | tot_dsds = 0; | ||
2676 | |||
2677 | dbval = 0x04 | (ha->portnum << 5); | ||
2678 | |||
2679 | /* Send marker if required */ | ||
2680 | if (vha->marker_needed != 0) { | ||
2681 | if (qla2x00_marker(vha, req, | ||
2682 | rsp, 0, 0, MK_SYNC_ALL) != QLA_SUCCESS) | ||
2683 | return QLA_FUNCTION_FAILED; | ||
2684 | vha->marker_needed = 0; | ||
2685 | } | ||
2686 | |||
2687 | /* Acquire ring specific lock */ | ||
2688 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
2689 | |||
2690 | /* Check for room in outstanding command list. */ | ||
2691 | handle = req->current_outstanding_cmd; | ||
2692 | for (index = 1; index < MAX_OUTSTANDING_COMMANDS; index++) { | ||
2693 | handle++; | ||
2694 | if (handle == MAX_OUTSTANDING_COMMANDS) | ||
2695 | handle = 1; | ||
2696 | if (!req->outstanding_cmds[handle]) | ||
2697 | break; | ||
2698 | } | ||
2699 | if (index == MAX_OUTSTANDING_COMMANDS) | ||
2700 | goto queuing_error; | ||
2701 | |||
2702 | /* Map the sg table so we have an accurate count of sg entries needed */ | ||
2703 | if (scsi_sg_count(cmd)) { | ||
2704 | nseg = dma_map_sg(&ha->pdev->dev, scsi_sglist(cmd), | ||
2705 | scsi_sg_count(cmd), cmd->sc_data_direction); | ||
2706 | if (unlikely(!nseg)) | ||
2707 | goto queuing_error; | ||
2708 | } else | ||
2709 | nseg = 0; | ||
2710 | |||
2711 | tot_dsds = nseg; | ||
2712 | |||
2713 | if (tot_dsds > ql2xshiftctondsd) { | ||
2714 | struct cmd_type_6 *cmd_pkt; | ||
2715 | uint16_t more_dsd_lists = 0; | ||
2716 | struct dsd_dma *dsd_ptr; | ||
2717 | uint16_t i; | ||
2718 | |||
2719 | more_dsd_lists = qla82xx_calc_dsd_lists(tot_dsds); | ||
2720 | if ((more_dsd_lists + ha->gbl_dsd_inuse) >= NUM_DSD_CHAIN) | ||
2721 | goto queuing_error; | ||
2722 | |||
2723 | if (more_dsd_lists <= ha->gbl_dsd_avail) | ||
2724 | goto sufficient_dsds; | ||
2725 | else | ||
2726 | more_dsd_lists -= ha->gbl_dsd_avail; | ||
2727 | |||
2728 | for (i = 0; i < more_dsd_lists; i++) { | ||
2729 | dsd_ptr = kzalloc(sizeof(struct dsd_dma), GFP_ATOMIC); | ||
2730 | if (!dsd_ptr) | ||
2731 | goto queuing_error; | ||
2732 | |||
2733 | dsd_ptr->dsd_addr = dma_pool_alloc(ha->dl_dma_pool, | ||
2734 | GFP_ATOMIC, &dsd_ptr->dsd_list_dma); | ||
2735 | if (!dsd_ptr->dsd_addr) { | ||
2736 | kfree(dsd_ptr); | ||
2737 | goto queuing_error; | ||
2738 | } | ||
2739 | list_add_tail(&dsd_ptr->list, &ha->gbl_dsd_list); | ||
2740 | ha->gbl_dsd_avail++; | ||
2741 | } | ||
2742 | |||
2743 | sufficient_dsds: | ||
2744 | req_cnt = 1; | ||
2745 | |||
2746 | ctx = sp->ctx = mempool_alloc(ha->ctx_mempool, GFP_ATOMIC); | ||
2747 | if (!sp->ctx) { | ||
2748 | DEBUG(printk(KERN_INFO | ||
2749 | "%s(%ld): failed to allocate" | ||
2750 | " ctx.\n", __func__, vha->host_no)); | ||
2751 | goto queuing_error; | ||
2752 | } | ||
2753 | memset(ctx, 0, sizeof(struct ct6_dsd)); | ||
2754 | ctx->fcp_cmnd = dma_pool_alloc(ha->fcp_cmnd_dma_pool, | ||
2755 | GFP_ATOMIC, &ctx->fcp_cmnd_dma); | ||
2756 | if (!ctx->fcp_cmnd) { | ||
2757 | DEBUG2_3(printk("%s(%ld): failed to allocate" | ||
2758 | " fcp_cmnd.\n", __func__, vha->host_no)); | ||
2759 | goto queuing_error_fcp_cmnd; | ||
2760 | } | ||
2761 | |||
2762 | /* Initialize the DSD list and dma handle */ | ||
2763 | INIT_LIST_HEAD(&ctx->dsd_list); | ||
2764 | ctx->dsd_use_cnt = 0; | ||
2765 | |||
2766 | if (cmd->cmd_len > 16) { | ||
2767 | additional_cdb_len = cmd->cmd_len - 16; | ||
2768 | if ((cmd->cmd_len % 4) != 0) { | ||
2769 | /* SCSI command bigger than 16 bytes must be | ||
2770 | * multiple of 4 | ||
2771 | */ | ||
2772 | goto queuing_error_fcp_cmnd; | ||
2773 | } | ||
2774 | ctx->fcp_cmnd_len = 12 + cmd->cmd_len + 4; | ||
2775 | } else { | ||
2776 | additional_cdb_len = 0; | ||
2777 | ctx->fcp_cmnd_len = 12 + 16 + 4; | ||
2778 | } | ||
2779 | |||
2780 | cmd_pkt = (struct cmd_type_6 *)req->ring_ptr; | ||
2781 | cmd_pkt->handle = MAKE_HANDLE(req->id, handle); | ||
2782 | |||
2783 | /* Zero out remaining portion of packet. */ | ||
2784 | /* tagged queuing modifier -- default is TSK_SIMPLE (0). */ | ||
2785 | clr_ptr = (uint32_t *)cmd_pkt + 2; | ||
2786 | memset(clr_ptr, 0, REQUEST_ENTRY_SIZE - 8); | ||
2787 | cmd_pkt->dseg_count = cpu_to_le16(tot_dsds); | ||
2788 | |||
2789 | /* Set NPORT-ID and LUN number*/ | ||
2790 | cmd_pkt->nport_handle = cpu_to_le16(sp->fcport->loop_id); | ||
2791 | cmd_pkt->port_id[0] = sp->fcport->d_id.b.al_pa; | ||
2792 | cmd_pkt->port_id[1] = sp->fcport->d_id.b.area; | ||
2793 | cmd_pkt->port_id[2] = sp->fcport->d_id.b.domain; | ||
2794 | cmd_pkt->vp_index = sp->fcport->vp_idx; | ||
2795 | |||
2796 | /* Build IOCB segments */ | ||
2797 | if (qla2xx_build_scsi_type_6_iocbs(sp, cmd_pkt, tot_dsds)) | ||
2798 | goto queuing_error_fcp_cmnd; | ||
2799 | |||
2800 | int_to_scsilun(sp->cmd->device->lun, &cmd_pkt->lun); | ||
2801 | |||
2802 | /* build FCP_CMND IU */ | ||
2803 | memset(ctx->fcp_cmnd, 0, sizeof(struct fcp_cmnd)); | ||
2804 | int_to_scsilun(sp->cmd->device->lun, &ctx->fcp_cmnd->lun); | ||
2805 | ctx->fcp_cmnd->additional_cdb_len = additional_cdb_len; | ||
2806 | |||
2807 | if (cmd->sc_data_direction == DMA_TO_DEVICE) | ||
2808 | ctx->fcp_cmnd->additional_cdb_len |= 1; | ||
2809 | else if (cmd->sc_data_direction == DMA_FROM_DEVICE) | ||
2810 | ctx->fcp_cmnd->additional_cdb_len |= 2; | ||
2811 | |||
2812 | memcpy(ctx->fcp_cmnd->cdb, cmd->cmnd, cmd->cmd_len); | ||
2813 | |||
2814 | fcp_dl = (uint32_t *)(ctx->fcp_cmnd->cdb + 16 + | ||
2815 | additional_cdb_len); | ||
2816 | *fcp_dl = htonl((uint32_t)scsi_bufflen(cmd)); | ||
2817 | |||
2818 | cmd_pkt->fcp_cmnd_dseg_len = cpu_to_le16(ctx->fcp_cmnd_len); | ||
2819 | cmd_pkt->fcp_cmnd_dseg_address[0] = | ||
2820 | cpu_to_le32(LSD(ctx->fcp_cmnd_dma)); | ||
2821 | cmd_pkt->fcp_cmnd_dseg_address[1] = | ||
2822 | cpu_to_le32(MSD(ctx->fcp_cmnd_dma)); | ||
2823 | |||
2824 | sp->flags |= SRB_FCP_CMND_DMA_VALID; | ||
2825 | cmd_pkt->byte_count = cpu_to_le32((uint32_t)scsi_bufflen(cmd)); | ||
2826 | /* Set total data segment count. */ | ||
2827 | cmd_pkt->entry_count = (uint8_t)req_cnt; | ||
2828 | /* Specify response queue number where | ||
2829 | * completion should happen | ||
2830 | */ | ||
2831 | cmd_pkt->entry_status = (uint8_t) rsp->id; | ||
2832 | } else { | ||
2833 | struct cmd_type_7 *cmd_pkt; | ||
2834 | req_cnt = qla24xx_calc_iocbs(tot_dsds); | ||
2835 | if (req->cnt < (req_cnt + 2)) { | ||
2836 | cnt = (uint16_t)RD_REG_DWORD_RELAXED( | ||
2837 | ®->req_q_out[0]); | ||
2838 | if (req->ring_index < cnt) | ||
2839 | req->cnt = cnt - req->ring_index; | ||
2840 | else | ||
2841 | req->cnt = req->length - | ||
2842 | (req->ring_index - cnt); | ||
2843 | } | ||
2844 | if (req->cnt < (req_cnt + 2)) | ||
2845 | goto queuing_error; | ||
2846 | |||
2847 | cmd_pkt = (struct cmd_type_7 *)req->ring_ptr; | ||
2848 | cmd_pkt->handle = MAKE_HANDLE(req->id, handle); | ||
2849 | |||
2850 | /* Zero out remaining portion of packet. */ | ||
2851 | /* tagged queuing modifier -- default is TSK_SIMPLE (0).*/ | ||
2852 | clr_ptr = (uint32_t *)cmd_pkt + 2; | ||
2853 | memset(clr_ptr, 0, REQUEST_ENTRY_SIZE - 8); | ||
2854 | cmd_pkt->dseg_count = cpu_to_le16(tot_dsds); | ||
2855 | |||
2856 | /* Set NPORT-ID and LUN number*/ | ||
2857 | cmd_pkt->nport_handle = cpu_to_le16(sp->fcport->loop_id); | ||
2858 | cmd_pkt->port_id[0] = sp->fcport->d_id.b.al_pa; | ||
2859 | cmd_pkt->port_id[1] = sp->fcport->d_id.b.area; | ||
2860 | cmd_pkt->port_id[2] = sp->fcport->d_id.b.domain; | ||
2861 | cmd_pkt->vp_index = sp->fcport->vp_idx; | ||
2862 | |||
2863 | int_to_scsilun(sp->cmd->device->lun, &cmd_pkt->lun); | ||
2864 | host_to_fcp_swap((uint8_t *)&cmd_pkt->lun, | ||
2865 | sizeof(cmd_pkt->lun)); | ||
2866 | |||
2867 | /* Load SCSI command packet. */ | ||
2868 | memcpy(cmd_pkt->fcp_cdb, cmd->cmnd, cmd->cmd_len); | ||
2869 | host_to_fcp_swap(cmd_pkt->fcp_cdb, sizeof(cmd_pkt->fcp_cdb)); | ||
2870 | |||
2871 | cmd_pkt->byte_count = cpu_to_le32((uint32_t)scsi_bufflen(cmd)); | ||
2872 | |||
2873 | /* Build IOCB segments */ | ||
2874 | qla24xx_build_scsi_iocbs(sp, cmd_pkt, tot_dsds); | ||
2875 | |||
2876 | /* Set total data segment count. */ | ||
2877 | cmd_pkt->entry_count = (uint8_t)req_cnt; | ||
2878 | /* Specify response queue number where | ||
2879 | * completion should happen. | ||
2880 | */ | ||
2881 | cmd_pkt->entry_status = (uint8_t) rsp->id; | ||
2882 | |||
2883 | } | ||
2884 | /* Build command packet. */ | ||
2885 | req->current_outstanding_cmd = handle; | ||
2886 | req->outstanding_cmds[handle] = sp; | ||
2887 | sp->handle = handle; | ||
2888 | sp->cmd->host_scribble = (unsigned char *)(unsigned long)handle; | ||
2889 | req->cnt -= req_cnt; | ||
2890 | wmb(); | ||
2891 | |||
2892 | /* Adjust ring index. */ | ||
2893 | req->ring_index++; | ||
2894 | if (req->ring_index == req->length) { | ||
2895 | req->ring_index = 0; | ||
2896 | req->ring_ptr = req->ring; | ||
2897 | } else | ||
2898 | req->ring_ptr++; | ||
2899 | |||
2900 | sp->flags |= SRB_DMA_VALID; | ||
2901 | |||
2902 | /* Set chip new ring index. */ | ||
2903 | /* write, read and verify logic */ | ||
2904 | dbval = dbval | (req->id << 8) | (req->ring_index << 16); | ||
2905 | if (ql2xdbwr) | ||
2906 | qla82xx_wr_32(ha, ha->nxdb_wr_ptr, dbval); | ||
2907 | else { | ||
2908 | WRT_REG_DWORD( | ||
2909 | (unsigned long __iomem *)ha->nxdb_wr_ptr, | ||
2910 | dbval); | ||
2911 | wmb(); | ||
2912 | while (RD_REG_DWORD(ha->nxdb_rd_ptr) != dbval) { | ||
2913 | WRT_REG_DWORD( | ||
2914 | (unsigned long __iomem *)ha->nxdb_wr_ptr, | ||
2915 | dbval); | ||
2916 | wmb(); | ||
2917 | } | ||
2918 | } | ||
2919 | |||
2920 | /* Manage unprocessed RIO/ZIO commands in response queue. */ | ||
2921 | if (vha->flags.process_response_queue && | ||
2922 | rsp->ring_ptr->signature != RESPONSE_PROCESSED) | ||
2923 | qla24xx_process_response_queue(vha, rsp); | ||
2924 | |||
2925 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
2926 | return QLA_SUCCESS; | ||
2927 | |||
2928 | queuing_error_fcp_cmnd: | ||
2929 | dma_pool_free(ha->fcp_cmnd_dma_pool, ctx->fcp_cmnd, ctx->fcp_cmnd_dma); | ||
2930 | queuing_error: | ||
2931 | if (tot_dsds) | ||
2932 | scsi_dma_unmap(cmd); | ||
2933 | |||
2934 | if (sp->ctx) { | ||
2935 | mempool_free(sp->ctx, ha->ctx_mempool); | ||
2936 | sp->ctx = NULL; | ||
2937 | } | ||
2938 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
2939 | |||
2940 | return QLA_FUNCTION_FAILED; | ||
2941 | } | ||
2942 | |||
2943 | uint32_t * | ||
2944 | qla82xx_read_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr, | ||
2945 | uint32_t length) | ||
2946 | { | ||
2947 | uint32_t i; | ||
2948 | uint32_t val; | ||
2949 | struct qla_hw_data *ha = vha->hw; | ||
2950 | |||
2951 | /* Dword reads to flash. */ | ||
2952 | for (i = 0; i < length/4; i++, faddr += 4) { | ||
2953 | if (qla82xx_rom_fast_read(ha, faddr, &val)) { | ||
2954 | qla_printk(KERN_WARNING, ha, | ||
2955 | "Do ROM fast read failed\n"); | ||
2956 | goto done_read; | ||
2957 | } | ||
2958 | dwptr[i] = __constant_cpu_to_le32(val); | ||
2959 | } | ||
2960 | done_read: | ||
2961 | return dwptr; | ||
2962 | } | ||
2963 | |||
2964 | int | ||
2965 | qla82xx_unprotect_flash(struct qla_hw_data *ha) | ||
2966 | { | ||
2967 | int ret; | ||
2968 | uint32_t val; | ||
2969 | |||
2970 | ret = ql82xx_rom_lock_d(ha); | ||
2971 | if (ret < 0) { | ||
2972 | qla_printk(KERN_WARNING, ha, "ROM Lock failed\n"); | ||
2973 | return ret; | ||
2974 | } | ||
2975 | |||
2976 | ret = qla82xx_read_status_reg(ha, &val); | ||
2977 | if (ret < 0) | ||
2978 | goto done_unprotect; | ||
2979 | |||
2980 | val &= ~(0x7 << 2); | ||
2981 | ret = qla82xx_write_status_reg(ha, val); | ||
2982 | if (ret < 0) { | ||
2983 | val |= (0x7 << 2); | ||
2984 | qla82xx_write_status_reg(ha, val); | ||
2985 | } | ||
2986 | |||
2987 | if (qla82xx_write_disable_flash(ha) != 0) | ||
2988 | qla_printk(KERN_WARNING, ha, "Write disable failed\n"); | ||
2989 | |||
2990 | done_unprotect: | ||
2991 | qla82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM2_UNLOCK)); | ||
2992 | return ret; | ||
2993 | } | ||
2994 | |||
2995 | int | ||
2996 | qla82xx_protect_flash(struct qla_hw_data *ha) | ||
2997 | { | ||
2998 | int ret; | ||
2999 | uint32_t val; | ||
3000 | |||
3001 | ret = ql82xx_rom_lock_d(ha); | ||
3002 | if (ret < 0) { | ||
3003 | qla_printk(KERN_WARNING, ha, "ROM Lock failed\n"); | ||
3004 | return ret; | ||
3005 | } | ||
3006 | |||
3007 | ret = qla82xx_read_status_reg(ha, &val); | ||
3008 | if (ret < 0) | ||
3009 | goto done_protect; | ||
3010 | |||
3011 | val |= (0x7 << 2); | ||
3012 | /* LOCK all sectors */ | ||
3013 | ret = qla82xx_write_status_reg(ha, val); | ||
3014 | if (ret < 0) | ||
3015 | qla_printk(KERN_WARNING, ha, "Write status register failed\n"); | ||
3016 | |||
3017 | if (qla82xx_write_disable_flash(ha) != 0) | ||
3018 | qla_printk(KERN_WARNING, ha, "Write disable failed\n"); | ||
3019 | done_protect: | ||
3020 | qla82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM2_UNLOCK)); | ||
3021 | return ret; | ||
3022 | } | ||
3023 | |||
3024 | int | ||
3025 | qla82xx_erase_sector(struct qla_hw_data *ha, int addr) | ||
3026 | { | ||
3027 | int ret = 0; | ||
3028 | |||
3029 | ret = ql82xx_rom_lock_d(ha); | ||
3030 | if (ret < 0) { | ||
3031 | qla_printk(KERN_WARNING, ha, "ROM Lock failed\n"); | ||
3032 | return ret; | ||
3033 | } | ||
3034 | |||
3035 | qla82xx_flash_set_write_enable(ha); | ||
3036 | qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_ADDRESS, addr); | ||
3037 | qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_ABYTE_CNT, 3); | ||
3038 | qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_INSTR_OPCODE, M25P_INSTR_SE); | ||
3039 | |||
3040 | if (qla82xx_wait_rom_done(ha)) { | ||
3041 | qla_printk(KERN_WARNING, ha, | ||
3042 | "Error waiting for rom done\n"); | ||
3043 | ret = -1; | ||
3044 | goto done; | ||
3045 | } | ||
3046 | ret = qla82xx_flash_wait_write_finish(ha); | ||
3047 | done: | ||
3048 | qla82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM2_UNLOCK)); | ||
3049 | return ret; | ||
3050 | } | ||
3051 | |||
3052 | /* | ||
3053 | * Address and length are byte address | ||
3054 | */ | ||
3055 | uint8_t * | ||
3056 | qla82xx_read_optrom_data(struct scsi_qla_host *vha, uint8_t *buf, | ||
3057 | uint32_t offset, uint32_t length) | ||
3058 | { | ||
3059 | scsi_block_requests(vha->host); | ||
3060 | qla82xx_read_flash_data(vha, (uint32_t *)buf, offset, length); | ||
3061 | scsi_unblock_requests(vha->host); | ||
3062 | return buf; | ||
3063 | } | ||
3064 | |||
3065 | static int | ||
3066 | qla82xx_write_flash_data(struct scsi_qla_host *vha, uint32_t *dwptr, | ||
3067 | uint32_t faddr, uint32_t dwords) | ||
3068 | { | ||
3069 | int ret; | ||
3070 | uint32_t liter; | ||
3071 | uint32_t sec_mask, rest_addr; | ||
3072 | dma_addr_t optrom_dma; | ||
3073 | void *optrom = NULL; | ||
3074 | int page_mode = 0; | ||
3075 | struct qla_hw_data *ha = vha->hw; | ||
3076 | |||
3077 | ret = -1; | ||
3078 | |||
3079 | /* Prepare burst-capable write on supported ISPs. */ | ||
3080 | if (page_mode && !(faddr & 0xfff) && | ||
3081 | dwords > OPTROM_BURST_DWORDS) { | ||
3082 | optrom = dma_alloc_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE, | ||
3083 | &optrom_dma, GFP_KERNEL); | ||
3084 | if (!optrom) { | ||
3085 | qla_printk(KERN_DEBUG, ha, | ||
3086 | "Unable to allocate memory for optrom " | ||
3087 | "burst write (%x KB).\n", | ||
3088 | OPTROM_BURST_SIZE / 1024); | ||
3089 | } | ||
3090 | } | ||
3091 | |||
3092 | rest_addr = ha->fdt_block_size - 1; | ||
3093 | sec_mask = ~rest_addr; | ||
3094 | |||
3095 | ret = qla82xx_unprotect_flash(ha); | ||
3096 | if (ret) { | ||
3097 | qla_printk(KERN_WARNING, ha, | ||
3098 | "Unable to unprotect flash for update.\n"); | ||
3099 | goto write_done; | ||
3100 | } | ||
3101 | |||
3102 | for (liter = 0; liter < dwords; liter++, faddr += 4, dwptr++) { | ||
3103 | /* Are we at the beginning of a sector? */ | ||
3104 | if ((faddr & rest_addr) == 0) { | ||
3105 | |||
3106 | ret = qla82xx_erase_sector(ha, faddr); | ||
3107 | if (ret) { | ||
3108 | DEBUG9(qla_printk(KERN_ERR, ha, | ||
3109 | "Unable to erase sector: " | ||
3110 | "address=%x.\n", faddr)); | ||
3111 | break; | ||
3112 | } | ||
3113 | } | ||
3114 | |||
3115 | /* Go with burst-write. */ | ||
3116 | if (optrom && (liter + OPTROM_BURST_DWORDS) <= dwords) { | ||
3117 | /* Copy data to DMA'ble buffer. */ | ||
3118 | memcpy(optrom, dwptr, OPTROM_BURST_SIZE); | ||
3119 | |||
3120 | ret = qla2x00_load_ram(vha, optrom_dma, | ||
3121 | (ha->flash_data_off | faddr), | ||
3122 | OPTROM_BURST_DWORDS); | ||
3123 | if (ret != QLA_SUCCESS) { | ||
3124 | qla_printk(KERN_WARNING, ha, | ||
3125 | "Unable to burst-write optrom segment " | ||
3126 | "(%x/%x/%llx).\n", ret, | ||
3127 | (ha->flash_data_off | faddr), | ||
3128 | (unsigned long long)optrom_dma); | ||
3129 | qla_printk(KERN_WARNING, ha, | ||
3130 | "Reverting to slow-write.\n"); | ||
3131 | |||
3132 | dma_free_coherent(&ha->pdev->dev, | ||
3133 | OPTROM_BURST_SIZE, optrom, optrom_dma); | ||
3134 | optrom = NULL; | ||
3135 | } else { | ||
3136 | liter += OPTROM_BURST_DWORDS - 1; | ||
3137 | faddr += OPTROM_BURST_DWORDS - 1; | ||
3138 | dwptr += OPTROM_BURST_DWORDS - 1; | ||
3139 | continue; | ||
3140 | } | ||
3141 | } | ||
3142 | |||
3143 | ret = qla82xx_write_flash_dword(ha, faddr, | ||
3144 | cpu_to_le32(*dwptr)); | ||
3145 | if (ret) { | ||
3146 | DEBUG9(printk(KERN_DEBUG "%s(%ld) Unable to program" | ||
3147 | "flash address=%x data=%x.\n", __func__, | ||
3148 | ha->host_no, faddr, *dwptr)); | ||
3149 | break; | ||
3150 | } | ||
3151 | } | ||
3152 | |||
3153 | ret = qla82xx_protect_flash(ha); | ||
3154 | if (ret) | ||
3155 | qla_printk(KERN_WARNING, ha, | ||
3156 | "Unable to protect flash after update.\n"); | ||
3157 | write_done: | ||
3158 | if (optrom) | ||
3159 | dma_free_coherent(&ha->pdev->dev, | ||
3160 | OPTROM_BURST_SIZE, optrom, optrom_dma); | ||
3161 | return ret; | ||
3162 | } | ||
3163 | |||
3164 | int | ||
3165 | qla82xx_write_optrom_data(struct scsi_qla_host *vha, uint8_t *buf, | ||
3166 | uint32_t offset, uint32_t length) | ||
3167 | { | ||
3168 | int rval; | ||
3169 | |||
3170 | /* Suspend HBA. */ | ||
3171 | scsi_block_requests(vha->host); | ||
3172 | rval = qla82xx_write_flash_data(vha, (uint32_t *)buf, offset, | ||
3173 | length >> 2); | ||
3174 | scsi_unblock_requests(vha->host); | ||
3175 | |||
3176 | /* Convert return ISP82xx to generic */ | ||
3177 | if (rval) | ||
3178 | rval = QLA_FUNCTION_FAILED; | ||
3179 | else | ||
3180 | rval = QLA_SUCCESS; | ||
3181 | return rval; | ||
3182 | } | ||
3183 | |||
3184 | void | ||
3185 | qla82xx_start_iocbs(srb_t *sp) | ||
3186 | { | ||
3187 | struct qla_hw_data *ha = sp->fcport->vha->hw; | ||
3188 | struct req_que *req = ha->req_q_map[0]; | ||
3189 | struct device_reg_82xx __iomem *reg; | ||
3190 | uint32_t dbval; | ||
3191 | |||
3192 | /* Adjust ring index. */ | ||
3193 | req->ring_index++; | ||
3194 | if (req->ring_index == req->length) { | ||
3195 | req->ring_index = 0; | ||
3196 | req->ring_ptr = req->ring; | ||
3197 | } else | ||
3198 | req->ring_ptr++; | ||
3199 | |||
3200 | reg = &ha->iobase->isp82; | ||
3201 | dbval = 0x04 | (ha->portnum << 5); | ||
3202 | |||
3203 | dbval = dbval | (req->id << 8) | (req->ring_index << 16); | ||
3204 | WRT_REG_DWORD((unsigned long __iomem *)ha->nxdb_wr_ptr, dbval); | ||
3205 | wmb(); | ||
3206 | while (RD_REG_DWORD(ha->nxdb_rd_ptr) != dbval) { | ||
3207 | WRT_REG_DWORD((unsigned long __iomem *)ha->nxdb_wr_ptr, dbval); | ||
3208 | wmb(); | ||
3209 | } | ||
3210 | } | ||
3211 | |||
3212 | /* | ||
3213 | * qla82xx_device_bootstrap | ||
3214 | * Initialize device, set DEV_READY, start fw | ||
3215 | * | ||
3216 | * Note: | ||
3217 | * IDC lock must be held upon entry | ||
3218 | * | ||
3219 | * Return: | ||
3220 | * Success : 0 | ||
3221 | * Failed : 1 | ||
3222 | */ | ||
3223 | static int | ||
3224 | qla82xx_device_bootstrap(scsi_qla_host_t *vha) | ||
3225 | { | ||
3226 | int rval, i, timeout; | ||
3227 | uint32_t old_count, count; | ||
3228 | struct qla_hw_data *ha = vha->hw; | ||
3229 | |||
3230 | if (qla82xx_need_reset(ha)) | ||
3231 | goto dev_initialize; | ||
3232 | |||
3233 | old_count = qla82xx_rd_32(ha, QLA82XX_PEG_ALIVE_COUNTER); | ||
3234 | |||
3235 | for (i = 0; i < 10; i++) { | ||
3236 | timeout = msleep_interruptible(200); | ||
3237 | if (timeout) { | ||
3238 | qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, | ||
3239 | QLA82XX_DEV_FAILED); | ||
3240 | return QLA_FUNCTION_FAILED; | ||
3241 | } | ||
3242 | |||
3243 | count = qla82xx_rd_32(ha, QLA82XX_PEG_ALIVE_COUNTER); | ||
3244 | if (count != old_count) | ||
3245 | goto dev_ready; | ||
3246 | } | ||
3247 | |||
3248 | dev_initialize: | ||
3249 | /* set to DEV_INITIALIZING */ | ||
3250 | qla_printk(KERN_INFO, ha, "HW State: INITIALIZING\n"); | ||
3251 | qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA82XX_DEV_INITIALIZING); | ||
3252 | |||
3253 | /* Driver that sets device state to initializating sets IDC version */ | ||
3254 | qla82xx_wr_32(ha, QLA82XX_CRB_DRV_IDC_VERSION, QLA82XX_IDC_VERSION); | ||
3255 | |||
3256 | qla82xx_idc_unlock(ha); | ||
3257 | rval = qla82xx_start_firmware(vha); | ||
3258 | qla82xx_idc_lock(ha); | ||
3259 | |||
3260 | if (rval != QLA_SUCCESS) { | ||
3261 | qla_printk(KERN_INFO, ha, "HW State: FAILED\n"); | ||
3262 | qla82xx_clear_drv_active(ha); | ||
3263 | qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA82XX_DEV_FAILED); | ||
3264 | return rval; | ||
3265 | } | ||
3266 | |||
3267 | dev_ready: | ||
3268 | qla_printk(KERN_INFO, ha, "HW State: READY\n"); | ||
3269 | qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA82XX_DEV_READY); | ||
3270 | |||
3271 | return QLA_SUCCESS; | ||
3272 | } | ||
3273 | |||
3274 | static void | ||
3275 | qla82xx_dev_failed_handler(scsi_qla_host_t *vha) | ||
3276 | { | ||
3277 | struct qla_hw_data *ha = vha->hw; | ||
3278 | |||
3279 | /* Disable the board */ | ||
3280 | qla_printk(KERN_INFO, ha, "Disabling the board\n"); | ||
3281 | |||
3282 | /* Set DEV_FAILED flag to disable timer */ | ||
3283 | vha->device_flags |= DFLG_DEV_FAILED; | ||
3284 | qla2x00_abort_all_cmds(vha, DID_NO_CONNECT << 16); | ||
3285 | qla2x00_mark_all_devices_lost(vha, 0); | ||
3286 | vha->flags.online = 0; | ||
3287 | vha->flags.init_done = 0; | ||
3288 | } | ||
3289 | |||
3290 | /* | ||
3291 | * qla82xx_need_reset_handler | ||
3292 | * Code to start reset sequence | ||
3293 | * | ||
3294 | * Note: | ||
3295 | * IDC lock must be held upon entry | ||
3296 | * | ||
3297 | * Return: | ||
3298 | * Success : 0 | ||
3299 | * Failed : 1 | ||
3300 | */ | ||
3301 | static void | ||
3302 | qla82xx_need_reset_handler(scsi_qla_host_t *vha) | ||
3303 | { | ||
3304 | uint32_t dev_state, drv_state, drv_active; | ||
3305 | unsigned long reset_timeout; | ||
3306 | struct qla_hw_data *ha = vha->hw; | ||
3307 | struct req_que *req = ha->req_q_map[0]; | ||
3308 | |||
3309 | if (vha->flags.online) { | ||
3310 | qla82xx_idc_unlock(ha); | ||
3311 | qla2x00_abort_isp_cleanup(vha); | ||
3312 | ha->isp_ops->get_flash_version(vha, req->ring); | ||
3313 | ha->isp_ops->nvram_config(vha); | ||
3314 | qla82xx_idc_lock(ha); | ||
3315 | } | ||
3316 | |||
3317 | qla82xx_set_rst_ready(ha); | ||
3318 | |||
3319 | /* wait for 10 seconds for reset ack from all functions */ | ||
3320 | reset_timeout = jiffies + (ha->nx_reset_timeout * HZ); | ||
3321 | |||
3322 | drv_state = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE); | ||
3323 | drv_active = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE); | ||
3324 | |||
3325 | while (drv_state != drv_active) { | ||
3326 | if (time_after_eq(jiffies, reset_timeout)) { | ||
3327 | qla_printk(KERN_INFO, ha, | ||
3328 | "%s: RESET TIMEOUT!\n", QLA2XXX_DRIVER_NAME); | ||
3329 | break; | ||
3330 | } | ||
3331 | qla82xx_idc_unlock(ha); | ||
3332 | msleep(1000); | ||
3333 | qla82xx_idc_lock(ha); | ||
3334 | drv_state = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE); | ||
3335 | drv_active = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE); | ||
3336 | } | ||
3337 | |||
3338 | dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE); | ||
3339 | qla_printk(KERN_INFO, ha, "3:Device state is 0x%x = %s\n", dev_state, | ||
3340 | dev_state < MAX_STATES ? qdev_state[dev_state] : "Unknown"); | ||
3341 | |||
3342 | /* Force to DEV_COLD unless someone else is starting a reset */ | ||
3343 | if (dev_state != QLA82XX_DEV_INITIALIZING) { | ||
3344 | qla_printk(KERN_INFO, ha, "HW State: COLD/RE-INIT\n"); | ||
3345 | qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA82XX_DEV_COLD); | ||
3346 | } | ||
3347 | } | ||
3348 | |||
3349 | static void | ||
3350 | qla82xx_check_fw_alive(scsi_qla_host_t *vha) | ||
3351 | { | ||
3352 | uint32_t fw_heartbeat_counter, halt_status; | ||
3353 | struct qla_hw_data *ha = vha->hw; | ||
3354 | |||
3355 | fw_heartbeat_counter = qla82xx_rd_32(ha, QLA82XX_PEG_ALIVE_COUNTER); | ||
3356 | if (vha->fw_heartbeat_counter == fw_heartbeat_counter) { | ||
3357 | vha->seconds_since_last_heartbeat++; | ||
3358 | /* FW not alive after 2 seconds */ | ||
3359 | if (vha->seconds_since_last_heartbeat == 2) { | ||
3360 | vha->seconds_since_last_heartbeat = 0; | ||
3361 | halt_status = qla82xx_rd_32(ha, | ||
3362 | QLA82XX_PEG_HALT_STATUS1); | ||
3363 | if (halt_status & HALT_STATUS_UNRECOVERABLE) { | ||
3364 | set_bit(ISP_UNRECOVERABLE, &vha->dpc_flags); | ||
3365 | } else { | ||
3366 | qla_printk(KERN_INFO, ha, | ||
3367 | "scsi(%ld): %s - detect abort needed\n", | ||
3368 | vha->host_no, __func__); | ||
3369 | set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); | ||
3370 | } | ||
3371 | qla2xxx_wake_dpc(vha); | ||
3372 | } | ||
3373 | } | ||
3374 | vha->fw_heartbeat_counter = fw_heartbeat_counter; | ||
3375 | } | ||
3376 | |||
3377 | /* | ||
3378 | * qla82xx_device_state_handler | ||
3379 | * Main state handler | ||
3380 | * | ||
3381 | * Note: | ||
3382 | * IDC lock must be held upon entry | ||
3383 | * | ||
3384 | * Return: | ||
3385 | * Success : 0 | ||
3386 | * Failed : 1 | ||
3387 | */ | ||
3388 | int | ||
3389 | qla82xx_device_state_handler(scsi_qla_host_t *vha) | ||
3390 | { | ||
3391 | uint32_t dev_state; | ||
3392 | int rval = QLA_SUCCESS; | ||
3393 | unsigned long dev_init_timeout; | ||
3394 | struct qla_hw_data *ha = vha->hw; | ||
3395 | |||
3396 | qla82xx_idc_lock(ha); | ||
3397 | if (!vha->flags.init_done) | ||
3398 | qla82xx_set_drv_active(vha); | ||
3399 | |||
3400 | dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE); | ||
3401 | qla_printk(KERN_INFO, ha, "1:Device state is 0x%x = %s\n", dev_state, | ||
3402 | dev_state < MAX_STATES ? qdev_state[dev_state] : "Unknown"); | ||
3403 | |||
3404 | /* wait for 30 seconds for device to go ready */ | ||
3405 | dev_init_timeout = jiffies + (ha->nx_dev_init_timeout * HZ); | ||
3406 | |||
3407 | while (1) { | ||
3408 | |||
3409 | if (time_after_eq(jiffies, dev_init_timeout)) { | ||
3410 | DEBUG(qla_printk(KERN_INFO, ha, | ||
3411 | "%s: device init failed!\n", | ||
3412 | QLA2XXX_DRIVER_NAME)); | ||
3413 | rval = QLA_FUNCTION_FAILED; | ||
3414 | break; | ||
3415 | } | ||
3416 | dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE); | ||
3417 | qla_printk(KERN_INFO, ha, | ||
3418 | "2:Device state is 0x%x = %s\n", dev_state, | ||
3419 | dev_state < MAX_STATES ? | ||
3420 | qdev_state[dev_state] : "Unknown"); | ||
3421 | |||
3422 | switch (dev_state) { | ||
3423 | case QLA82XX_DEV_READY: | ||
3424 | goto exit; | ||
3425 | case QLA82XX_DEV_COLD: | ||
3426 | rval = qla82xx_device_bootstrap(vha); | ||
3427 | goto exit; | ||
3428 | case QLA82XX_DEV_INITIALIZING: | ||
3429 | qla82xx_idc_unlock(ha); | ||
3430 | msleep(1000); | ||
3431 | qla82xx_idc_lock(ha); | ||
3432 | break; | ||
3433 | case QLA82XX_DEV_NEED_RESET: | ||
3434 | if (!ql2xdontresethba) | ||
3435 | qla82xx_need_reset_handler(vha); | ||
3436 | break; | ||
3437 | case QLA82XX_DEV_NEED_QUIESCENT: | ||
3438 | qla82xx_set_qsnt_ready(ha); | ||
3439 | case QLA82XX_DEV_QUIESCENT: | ||
3440 | qla82xx_idc_unlock(ha); | ||
3441 | msleep(1000); | ||
3442 | qla82xx_idc_lock(ha); | ||
3443 | break; | ||
3444 | case QLA82XX_DEV_FAILED: | ||
3445 | qla82xx_dev_failed_handler(vha); | ||
3446 | rval = QLA_FUNCTION_FAILED; | ||
3447 | goto exit; | ||
3448 | default: | ||
3449 | qla82xx_idc_unlock(ha); | ||
3450 | msleep(1000); | ||
3451 | qla82xx_idc_lock(ha); | ||
3452 | } | ||
3453 | } | ||
3454 | exit: | ||
3455 | qla82xx_idc_unlock(ha); | ||
3456 | return rval; | ||
3457 | } | ||
3458 | |||
3459 | void qla82xx_watchdog(scsi_qla_host_t *vha) | ||
3460 | { | ||
3461 | uint32_t dev_state; | ||
3462 | struct qla_hw_data *ha = vha->hw; | ||
3463 | |||
3464 | dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE); | ||
3465 | |||
3466 | /* don't poll if reset is going on */ | ||
3467 | if (!(test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) || | ||
3468 | test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) || | ||
3469 | test_bit(ISP_ABORT_RETRY, &vha->dpc_flags))) { | ||
3470 | if (dev_state == QLA82XX_DEV_NEED_RESET) { | ||
3471 | qla_printk(KERN_WARNING, ha, | ||
3472 | "%s(): Adapter reset needed!\n", __func__); | ||
3473 | set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); | ||
3474 | qla2xxx_wake_dpc(vha); | ||
3475 | } else { | ||
3476 | qla82xx_check_fw_alive(vha); | ||
3477 | } | ||
3478 | } | ||
3479 | } | ||
3480 | |||
3481 | int qla82xx_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr) | ||
3482 | { | ||
3483 | int rval; | ||
3484 | rval = qla82xx_device_state_handler(vha); | ||
3485 | return rval; | ||
3486 | } | ||
3487 | |||
3488 | /* | ||
3489 | * qla82xx_abort_isp | ||
3490 | * Resets ISP and aborts all outstanding commands. | ||
3491 | * | ||
3492 | * Input: | ||
3493 | * ha = adapter block pointer. | ||
3494 | * | ||
3495 | * Returns: | ||
3496 | * 0 = success | ||
3497 | */ | ||
3498 | int | ||
3499 | qla82xx_abort_isp(scsi_qla_host_t *vha) | ||
3500 | { | ||
3501 | int rval; | ||
3502 | struct qla_hw_data *ha = vha->hw; | ||
3503 | uint32_t dev_state; | ||
3504 | |||
3505 | if (vha->device_flags & DFLG_DEV_FAILED) { | ||
3506 | qla_printk(KERN_WARNING, ha, | ||
3507 | "%s(%ld): Device in failed state, " | ||
3508 | "Exiting.\n", __func__, vha->host_no); | ||
3509 | return QLA_SUCCESS; | ||
3510 | } | ||
3511 | |||
3512 | qla82xx_idc_lock(ha); | ||
3513 | dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE); | ||
3514 | if (dev_state == QLA82XX_DEV_READY) { | ||
3515 | qla_printk(KERN_INFO, ha, "HW State: NEED RESET\n"); | ||
3516 | qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, | ||
3517 | QLA82XX_DEV_NEED_RESET); | ||
3518 | } else | ||
3519 | qla_printk(KERN_INFO, ha, "HW State: %s\n", | ||
3520 | dev_state < MAX_STATES ? | ||
3521 | qdev_state[dev_state] : "Unknown"); | ||
3522 | qla82xx_idc_unlock(ha); | ||
3523 | |||
3524 | rval = qla82xx_device_state_handler(vha); | ||
3525 | |||
3526 | qla82xx_idc_lock(ha); | ||
3527 | qla82xx_clear_rst_ready(ha); | ||
3528 | qla82xx_idc_unlock(ha); | ||
3529 | |||
3530 | if (rval == QLA_SUCCESS) | ||
3531 | qla82xx_restart_isp(vha); | ||
3532 | |||
3533 | if (rval) { | ||
3534 | vha->flags.online = 1; | ||
3535 | if (test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) { | ||
3536 | if (ha->isp_abort_cnt == 0) { | ||
3537 | qla_printk(KERN_WARNING, ha, | ||
3538 | "ISP error recovery failed - " | ||
3539 | "board disabled\n"); | ||
3540 | /* | ||
3541 | * The next call disables the board | ||
3542 | * completely. | ||
3543 | */ | ||
3544 | ha->isp_ops->reset_adapter(vha); | ||
3545 | vha->flags.online = 0; | ||
3546 | clear_bit(ISP_ABORT_RETRY, | ||
3547 | &vha->dpc_flags); | ||
3548 | rval = QLA_SUCCESS; | ||
3549 | } else { /* schedule another ISP abort */ | ||
3550 | ha->isp_abort_cnt--; | ||
3551 | DEBUG(qla_printk(KERN_INFO, ha, | ||
3552 | "qla%ld: ISP abort - retry remaining %d\n", | ||
3553 | vha->host_no, ha->isp_abort_cnt)); | ||
3554 | rval = QLA_FUNCTION_FAILED; | ||
3555 | } | ||
3556 | } else { | ||
3557 | ha->isp_abort_cnt = MAX_RETRIES_OF_ISP_ABORT; | ||
3558 | DEBUG(qla_printk(KERN_INFO, ha, | ||
3559 | "(%ld): ISP error recovery - retrying (%d) " | ||
3560 | "more times\n", vha->host_no, ha->isp_abort_cnt)); | ||
3561 | set_bit(ISP_ABORT_RETRY, &vha->dpc_flags); | ||
3562 | rval = QLA_FUNCTION_FAILED; | ||
3563 | } | ||
3564 | } | ||
3565 | return rval; | ||
3566 | } | ||
3567 | |||
3568 | /* | ||
3569 | * qla82xx_fcoe_ctx_reset | ||
3570 | * Perform a quick reset and aborts all outstanding commands. | ||
3571 | * This will only perform an FCoE context reset and avoids a full blown | ||
3572 | * chip reset. | ||
3573 | * | ||
3574 | * Input: | ||
3575 | * ha = adapter block pointer. | ||
3576 | * is_reset_path = flag for identifying the reset path. | ||
3577 | * | ||
3578 | * Returns: | ||
3579 | * 0 = success | ||
3580 | */ | ||
3581 | int qla82xx_fcoe_ctx_reset(scsi_qla_host_t *vha) | ||
3582 | { | ||
3583 | int rval = QLA_FUNCTION_FAILED; | ||
3584 | |||
3585 | if (vha->flags.online) { | ||
3586 | /* Abort all outstanding commands, so as to be requeued later */ | ||
3587 | qla2x00_abort_isp_cleanup(vha); | ||
3588 | } | ||
3589 | |||
3590 | /* Stop currently executing firmware. | ||
3591 | * This will destroy existing FCoE context at the F/W end. | ||
3592 | */ | ||
3593 | qla2x00_try_to_stop_firmware(vha); | ||
3594 | |||
3595 | /* Restart. Creates a new FCoE context on INIT_FIRMWARE. */ | ||
3596 | rval = qla82xx_restart_isp(vha); | ||
3597 | |||
3598 | return rval; | ||
3599 | } | ||
3600 | |||
3601 | /* | ||
3602 | * qla2x00_wait_for_fcoe_ctx_reset | ||
3603 | * Wait till the FCoE context is reset. | ||
3604 | * | ||
3605 | * Note: | ||
3606 | * Does context switching here. | ||
3607 | * Release SPIN_LOCK (if any) before calling this routine. | ||
3608 | * | ||
3609 | * Return: | ||
3610 | * Success (fcoe_ctx reset is done) : 0 | ||
3611 | * Failed (fcoe_ctx reset not completed within max loop timout ) : 1 | ||
3612 | */ | ||
3613 | int qla2x00_wait_for_fcoe_ctx_reset(scsi_qla_host_t *vha) | ||
3614 | { | ||
3615 | int status = QLA_FUNCTION_FAILED; | ||
3616 | unsigned long wait_reset; | ||
3617 | |||
3618 | wait_reset = jiffies + (MAX_LOOP_TIMEOUT * HZ); | ||
3619 | while ((test_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags) || | ||
3620 | test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags)) | ||
3621 | && time_before(jiffies, wait_reset)) { | ||
3622 | |||
3623 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
3624 | schedule_timeout(HZ); | ||
3625 | |||
3626 | if (!test_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags) && | ||
3627 | !test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags)) { | ||
3628 | status = QLA_SUCCESS; | ||
3629 | break; | ||
3630 | } | ||
3631 | } | ||
3632 | DEBUG2(printk(KERN_INFO | ||
3633 | "%s status=%d\n", __func__, status)); | ||
3634 | |||
3635 | return status; | ||
3636 | } | ||
diff --git a/drivers/scsi/qla2xxx/qla_nx.h b/drivers/scsi/qla2xxx/qla_nx.h new file mode 100644 index 000000000000..f8f99a5ea532 --- /dev/null +++ b/drivers/scsi/qla2xxx/qla_nx.h | |||
@@ -0,0 +1,889 @@ | |||
1 | /* | ||
2 | * QLogic Fibre Channel HBA Driver | ||
3 | * Copyright (c) 2003-2008 QLogic Corporation | ||
4 | * | ||
5 | * See LICENSE.qla2xxx for copyright and licensing details. | ||
6 | */ | ||
7 | #ifndef __QLA_NX_H | ||
8 | #define __QLA_NX_H | ||
9 | |||
10 | /* | ||
11 | * Following are the states of the Phantom. Phantom will set them and | ||
12 | * Host will read to check if the fields are correct. | ||
13 | */ | ||
14 | #define PHAN_INITIALIZE_FAILED 0xffff | ||
15 | #define PHAN_INITIALIZE_COMPLETE 0xff01 | ||
16 | |||
17 | /* Host writes the following to notify that it has done the init-handshake */ | ||
18 | #define PHAN_INITIALIZE_ACK 0xf00f | ||
19 | #define PHAN_PEG_RCV_INITIALIZED 0xff01 | ||
20 | |||
21 | /*CRB_RELATED*/ | ||
22 | #define QLA82XX_CRB_BASE QLA82XX_CAM_RAM(0x200) | ||
23 | #define QLA82XX_REG(X) (QLA82XX_CRB_BASE+(X)) | ||
24 | |||
25 | #define CRB_CMDPEG_STATE QLA82XX_REG(0x50) | ||
26 | #define CRB_RCVPEG_STATE QLA82XX_REG(0x13c) | ||
27 | #define BOOT_LOADER_DIMM_STATUS QLA82XX_REG(0x54) | ||
28 | #define CRB_DMA_SHIFT QLA82XX_REG(0xcc) | ||
29 | |||
30 | #define QLA82XX_HW_H0_CH_HUB_ADR 0x05 | ||
31 | #define QLA82XX_HW_H1_CH_HUB_ADR 0x0E | ||
32 | #define QLA82XX_HW_H2_CH_HUB_ADR 0x03 | ||
33 | #define QLA82XX_HW_H3_CH_HUB_ADR 0x01 | ||
34 | #define QLA82XX_HW_H4_CH_HUB_ADR 0x06 | ||
35 | #define QLA82XX_HW_H5_CH_HUB_ADR 0x07 | ||
36 | #define QLA82XX_HW_H6_CH_HUB_ADR 0x08 | ||
37 | |||
38 | /* Hub 0 */ | ||
39 | #define QLA82XX_HW_MN_CRB_AGT_ADR 0x15 | ||
40 | #define QLA82XX_HW_MS_CRB_AGT_ADR 0x25 | ||
41 | |||
42 | /* Hub 1 */ | ||
43 | #define QLA82XX_HW_PS_CRB_AGT_ADR 0x73 | ||
44 | #define QLA82XX_HW_QMS_CRB_AGT_ADR 0x00 | ||
45 | #define QLA82XX_HW_RPMX3_CRB_AGT_ADR 0x0b | ||
46 | #define QLA82XX_HW_SQGS0_CRB_AGT_ADR 0x01 | ||
47 | #define QLA82XX_HW_SQGS1_CRB_AGT_ADR 0x02 | ||
48 | #define QLA82XX_HW_SQGS2_CRB_AGT_ADR 0x03 | ||
49 | #define QLA82XX_HW_SQGS3_CRB_AGT_ADR 0x04 | ||
50 | #define QLA82XX_HW_C2C0_CRB_AGT_ADR 0x58 | ||
51 | #define QLA82XX_HW_C2C1_CRB_AGT_ADR 0x59 | ||
52 | #define QLA82XX_HW_C2C2_CRB_AGT_ADR 0x5a | ||
53 | #define QLA82XX_HW_RPMX2_CRB_AGT_ADR 0x0a | ||
54 | #define QLA82XX_HW_RPMX4_CRB_AGT_ADR 0x0c | ||
55 | #define QLA82XX_HW_RPMX7_CRB_AGT_ADR 0x0f | ||
56 | #define QLA82XX_HW_RPMX9_CRB_AGT_ADR 0x12 | ||
57 | #define QLA82XX_HW_SMB_CRB_AGT_ADR 0x18 | ||
58 | |||
59 | /* Hub 2 */ | ||
60 | #define QLA82XX_HW_NIU_CRB_AGT_ADR 0x31 | ||
61 | #define QLA82XX_HW_I2C0_CRB_AGT_ADR 0x19 | ||
62 | #define QLA82XX_HW_I2C1_CRB_AGT_ADR 0x29 | ||
63 | |||
64 | #define QLA82XX_HW_SN_CRB_AGT_ADR 0x10 | ||
65 | #define QLA82XX_HW_I2Q_CRB_AGT_ADR 0x20 | ||
66 | #define QLA82XX_HW_LPC_CRB_AGT_ADR 0x22 | ||
67 | #define QLA82XX_HW_ROMUSB_CRB_AGT_ADR 0x21 | ||
68 | #define QLA82XX_HW_QM_CRB_AGT_ADR 0x66 | ||
69 | #define QLA82XX_HW_SQG0_CRB_AGT_ADR 0x60 | ||
70 | #define QLA82XX_HW_SQG1_CRB_AGT_ADR 0x61 | ||
71 | #define QLA82XX_HW_SQG2_CRB_AGT_ADR 0x62 | ||
72 | #define QLA82XX_HW_SQG3_CRB_AGT_ADR 0x63 | ||
73 | #define QLA82XX_HW_RPMX1_CRB_AGT_ADR 0x09 | ||
74 | #define QLA82XX_HW_RPMX5_CRB_AGT_ADR 0x0d | ||
75 | #define QLA82XX_HW_RPMX6_CRB_AGT_ADR 0x0e | ||
76 | #define QLA82XX_HW_RPMX8_CRB_AGT_ADR 0x11 | ||
77 | |||
78 | /* Hub 3 */ | ||
79 | #define QLA82XX_HW_PH_CRB_AGT_ADR 0x1A | ||
80 | #define QLA82XX_HW_SRE_CRB_AGT_ADR 0x50 | ||
81 | #define QLA82XX_HW_EG_CRB_AGT_ADR 0x51 | ||
82 | #define QLA82XX_HW_RPMX0_CRB_AGT_ADR 0x08 | ||
83 | |||
84 | /* Hub 4 */ | ||
85 | #define QLA82XX_HW_PEGN0_CRB_AGT_ADR 0x40 | ||
86 | #define QLA82XX_HW_PEGN1_CRB_AGT_ADR 0x41 | ||
87 | #define QLA82XX_HW_PEGN2_CRB_AGT_ADR 0x42 | ||
88 | #define QLA82XX_HW_PEGN3_CRB_AGT_ADR 0x43 | ||
89 | #define QLA82XX_HW_PEGNI_CRB_AGT_ADR 0x44 | ||
90 | #define QLA82XX_HW_PEGND_CRB_AGT_ADR 0x45 | ||
91 | #define QLA82XX_HW_PEGNC_CRB_AGT_ADR 0x46 | ||
92 | #define QLA82XX_HW_PEGR0_CRB_AGT_ADR 0x47 | ||
93 | #define QLA82XX_HW_PEGR1_CRB_AGT_ADR 0x48 | ||
94 | #define QLA82XX_HW_PEGR2_CRB_AGT_ADR 0x49 | ||
95 | #define QLA82XX_HW_PEGR3_CRB_AGT_ADR 0x4a | ||
96 | #define QLA82XX_HW_PEGN4_CRB_AGT_ADR 0x4b | ||
97 | |||
98 | /* Hub 5 */ | ||
99 | #define QLA82XX_HW_PEGS0_CRB_AGT_ADR 0x40 | ||
100 | #define QLA82XX_HW_PEGS1_CRB_AGT_ADR 0x41 | ||
101 | #define QLA82XX_HW_PEGS2_CRB_AGT_ADR 0x42 | ||
102 | #define QLA82XX_HW_PEGS3_CRB_AGT_ADR 0x43 | ||
103 | #define QLA82XX_HW_PEGSI_CRB_AGT_ADR 0x44 | ||
104 | #define QLA82XX_HW_PEGSD_CRB_AGT_ADR 0x45 | ||
105 | #define QLA82XX_HW_PEGSC_CRB_AGT_ADR 0x46 | ||
106 | |||
107 | /* Hub 6 */ | ||
108 | #define QLA82XX_HW_CAS0_CRB_AGT_ADR 0x46 | ||
109 | #define QLA82XX_HW_CAS1_CRB_AGT_ADR 0x47 | ||
110 | #define QLA82XX_HW_CAS2_CRB_AGT_ADR 0x48 | ||
111 | #define QLA82XX_HW_CAS3_CRB_AGT_ADR 0x49 | ||
112 | #define QLA82XX_HW_NCM_CRB_AGT_ADR 0x16 | ||
113 | #define QLA82XX_HW_TMR_CRB_AGT_ADR 0x17 | ||
114 | #define QLA82XX_HW_XDMA_CRB_AGT_ADR 0x05 | ||
115 | #define QLA82XX_HW_OCM0_CRB_AGT_ADR 0x06 | ||
116 | #define QLA82XX_HW_OCM1_CRB_AGT_ADR 0x07 | ||
117 | |||
118 | /* This field defines PCI/X adr [25:20] of agents on the CRB */ | ||
119 | /* */ | ||
120 | #define QLA82XX_HW_PX_MAP_CRB_PH 0 | ||
121 | #define QLA82XX_HW_PX_MAP_CRB_PS 1 | ||
122 | #define QLA82XX_HW_PX_MAP_CRB_MN 2 | ||
123 | #define QLA82XX_HW_PX_MAP_CRB_MS 3 | ||
124 | #define QLA82XX_HW_PX_MAP_CRB_SRE 5 | ||
125 | #define QLA82XX_HW_PX_MAP_CRB_NIU 6 | ||
126 | #define QLA82XX_HW_PX_MAP_CRB_QMN 7 | ||
127 | #define QLA82XX_HW_PX_MAP_CRB_SQN0 8 | ||
128 | #define QLA82XX_HW_PX_MAP_CRB_SQN1 9 | ||
129 | #define QLA82XX_HW_PX_MAP_CRB_SQN2 10 | ||
130 | #define QLA82XX_HW_PX_MAP_CRB_SQN3 11 | ||
131 | #define QLA82XX_HW_PX_MAP_CRB_QMS 12 | ||
132 | #define QLA82XX_HW_PX_MAP_CRB_SQS0 13 | ||
133 | #define QLA82XX_HW_PX_MAP_CRB_SQS1 14 | ||
134 | #define QLA82XX_HW_PX_MAP_CRB_SQS2 15 | ||
135 | #define QLA82XX_HW_PX_MAP_CRB_SQS3 16 | ||
136 | #define QLA82XX_HW_PX_MAP_CRB_PGN0 17 | ||
137 | #define QLA82XX_HW_PX_MAP_CRB_PGN1 18 | ||
138 | #define QLA82XX_HW_PX_MAP_CRB_PGN2 19 | ||
139 | #define QLA82XX_HW_PX_MAP_CRB_PGN3 20 | ||
140 | #define QLA82XX_HW_PX_MAP_CRB_PGN4 QLA82XX_HW_PX_MAP_CRB_SQS2 | ||
141 | #define QLA82XX_HW_PX_MAP_CRB_PGND 21 | ||
142 | #define QLA82XX_HW_PX_MAP_CRB_PGNI 22 | ||
143 | #define QLA82XX_HW_PX_MAP_CRB_PGS0 23 | ||
144 | #define QLA82XX_HW_PX_MAP_CRB_PGS1 24 | ||
145 | #define QLA82XX_HW_PX_MAP_CRB_PGS2 25 | ||
146 | #define QLA82XX_HW_PX_MAP_CRB_PGS3 26 | ||
147 | #define QLA82XX_HW_PX_MAP_CRB_PGSD 27 | ||
148 | #define QLA82XX_HW_PX_MAP_CRB_PGSI 28 | ||
149 | #define QLA82XX_HW_PX_MAP_CRB_SN 29 | ||
150 | #define QLA82XX_HW_PX_MAP_CRB_EG 31 | ||
151 | #define QLA82XX_HW_PX_MAP_CRB_PH2 32 | ||
152 | #define QLA82XX_HW_PX_MAP_CRB_PS2 33 | ||
153 | #define QLA82XX_HW_PX_MAP_CRB_CAM 34 | ||
154 | #define QLA82XX_HW_PX_MAP_CRB_CAS0 35 | ||
155 | #define QLA82XX_HW_PX_MAP_CRB_CAS1 36 | ||
156 | #define QLA82XX_HW_PX_MAP_CRB_CAS2 37 | ||
157 | #define QLA82XX_HW_PX_MAP_CRB_C2C0 38 | ||
158 | #define QLA82XX_HW_PX_MAP_CRB_C2C1 39 | ||
159 | #define QLA82XX_HW_PX_MAP_CRB_TIMR 40 | ||
160 | #define QLA82XX_HW_PX_MAP_CRB_RPMX1 42 | ||
161 | #define QLA82XX_HW_PX_MAP_CRB_RPMX2 43 | ||
162 | #define QLA82XX_HW_PX_MAP_CRB_RPMX3 44 | ||
163 | #define QLA82XX_HW_PX_MAP_CRB_RPMX4 45 | ||
164 | #define QLA82XX_HW_PX_MAP_CRB_RPMX5 46 | ||
165 | #define QLA82XX_HW_PX_MAP_CRB_RPMX6 47 | ||
166 | #define QLA82XX_HW_PX_MAP_CRB_RPMX7 48 | ||
167 | #define QLA82XX_HW_PX_MAP_CRB_XDMA 49 | ||
168 | #define QLA82XX_HW_PX_MAP_CRB_I2Q 50 | ||
169 | #define QLA82XX_HW_PX_MAP_CRB_ROMUSB 51 | ||
170 | #define QLA82XX_HW_PX_MAP_CRB_CAS3 52 | ||
171 | #define QLA82XX_HW_PX_MAP_CRB_RPMX0 53 | ||
172 | #define QLA82XX_HW_PX_MAP_CRB_RPMX8 54 | ||
173 | #define QLA82XX_HW_PX_MAP_CRB_RPMX9 55 | ||
174 | #define QLA82XX_HW_PX_MAP_CRB_OCM0 56 | ||
175 | #define QLA82XX_HW_PX_MAP_CRB_OCM1 57 | ||
176 | #define QLA82XX_HW_PX_MAP_CRB_SMB 58 | ||
177 | #define QLA82XX_HW_PX_MAP_CRB_I2C0 59 | ||
178 | #define QLA82XX_HW_PX_MAP_CRB_I2C1 60 | ||
179 | #define QLA82XX_HW_PX_MAP_CRB_LPC 61 | ||
180 | #define QLA82XX_HW_PX_MAP_CRB_PGNC 62 | ||
181 | #define QLA82XX_HW_PX_MAP_CRB_PGR0 63 | ||
182 | #define QLA82XX_HW_PX_MAP_CRB_PGR1 4 | ||
183 | #define QLA82XX_HW_PX_MAP_CRB_PGR2 30 | ||
184 | #define QLA82XX_HW_PX_MAP_CRB_PGR3 41 | ||
185 | |||
186 | /* This field defines CRB adr [31:20] of the agents */ | ||
187 | /* */ | ||
188 | |||
189 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_MN ((QLA82XX_HW_H0_CH_HUB_ADR << 7) | \ | ||
190 | QLA82XX_HW_MN_CRB_AGT_ADR) | ||
191 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_PH ((QLA82XX_HW_H0_CH_HUB_ADR << 7) | \ | ||
192 | QLA82XX_HW_PH_CRB_AGT_ADR) | ||
193 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_MS ((QLA82XX_HW_H0_CH_HUB_ADR << 7) | \ | ||
194 | QLA82XX_HW_MS_CRB_AGT_ADR) | ||
195 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_PS ((QLA82XX_HW_H1_CH_HUB_ADR << 7) | \ | ||
196 | QLA82XX_HW_PS_CRB_AGT_ADR) | ||
197 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_SS ((QLA82XX_HW_H1_CH_HUB_ADR << 7) | \ | ||
198 | QLA82XX_HW_SS_CRB_AGT_ADR) | ||
199 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX3 ((QLA82XX_HW_H1_CH_HUB_ADR << 7) | \ | ||
200 | QLA82XX_HW_RPMX3_CRB_AGT_ADR) | ||
201 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_QMS ((QLA82XX_HW_H1_CH_HUB_ADR << 7) | \ | ||
202 | QLA82XX_HW_QMS_CRB_AGT_ADR) | ||
203 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_SQS0 ((QLA82XX_HW_H1_CH_HUB_ADR << 7) | \ | ||
204 | QLA82XX_HW_SQGS0_CRB_AGT_ADR) | ||
205 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_SQS1 ((QLA82XX_HW_H1_CH_HUB_ADR << 7) | \ | ||
206 | QLA82XX_HW_SQGS1_CRB_AGT_ADR) | ||
207 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_SQS2 ((QLA82XX_HW_H1_CH_HUB_ADR << 7) | \ | ||
208 | QLA82XX_HW_SQGS2_CRB_AGT_ADR) | ||
209 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_SQS3 ((QLA82XX_HW_H1_CH_HUB_ADR << 7) | \ | ||
210 | QLA82XX_HW_SQGS3_CRB_AGT_ADR) | ||
211 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_C2C0 ((QLA82XX_HW_H1_CH_HUB_ADR << 7) | \ | ||
212 | QLA82XX_HW_C2C0_CRB_AGT_ADR) | ||
213 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_C2C1 ((QLA82XX_HW_H1_CH_HUB_ADR << 7) | \ | ||
214 | QLA82XX_HW_C2C1_CRB_AGT_ADR) | ||
215 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX2 ((QLA82XX_HW_H1_CH_HUB_ADR << 7) | \ | ||
216 | QLA82XX_HW_RPMX2_CRB_AGT_ADR) | ||
217 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX4 ((QLA82XX_HW_H1_CH_HUB_ADR << 7) | \ | ||
218 | QLA82XX_HW_RPMX4_CRB_AGT_ADR) | ||
219 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX7 ((QLA82XX_HW_H1_CH_HUB_ADR << 7) | \ | ||
220 | QLA82XX_HW_RPMX7_CRB_AGT_ADR) | ||
221 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX9 ((QLA82XX_HW_H1_CH_HUB_ADR << 7) | \ | ||
222 | QLA82XX_HW_RPMX9_CRB_AGT_ADR) | ||
223 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_SMB ((QLA82XX_HW_H1_CH_HUB_ADR << 7) | \ | ||
224 | QLA82XX_HW_SMB_CRB_AGT_ADR) | ||
225 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_NIU ((QLA82XX_HW_H2_CH_HUB_ADR << 7) | \ | ||
226 | QLA82XX_HW_NIU_CRB_AGT_ADR) | ||
227 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_I2C0 ((QLA82XX_HW_H2_CH_HUB_ADR << 7) | \ | ||
228 | QLA82XX_HW_I2C0_CRB_AGT_ADR) | ||
229 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_I2C1 ((QLA82XX_HW_H2_CH_HUB_ADR << 7) | \ | ||
230 | QLA82XX_HW_I2C1_CRB_AGT_ADR) | ||
231 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_SRE ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \ | ||
232 | QLA82XX_HW_SRE_CRB_AGT_ADR) | ||
233 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_EG ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \ | ||
234 | QLA82XX_HW_EG_CRB_AGT_ADR) | ||
235 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX0 ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \ | ||
236 | QLA82XX_HW_RPMX0_CRB_AGT_ADR) | ||
237 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_QMN ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \ | ||
238 | QLA82XX_HW_QM_CRB_AGT_ADR) | ||
239 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_SQN0 ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \ | ||
240 | QLA82XX_HW_SQG0_CRB_AGT_ADR) | ||
241 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_SQN1 ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \ | ||
242 | QLA82XX_HW_SQG1_CRB_AGT_ADR) | ||
243 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_SQN2 ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \ | ||
244 | QLA82XX_HW_SQG2_CRB_AGT_ADR) | ||
245 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_SQN3 ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \ | ||
246 | QLA82XX_HW_SQG3_CRB_AGT_ADR) | ||
247 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX1 ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \ | ||
248 | QLA82XX_HW_RPMX1_CRB_AGT_ADR) | ||
249 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX5 ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \ | ||
250 | QLA82XX_HW_RPMX5_CRB_AGT_ADR) | ||
251 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX6 ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \ | ||
252 | QLA82XX_HW_RPMX6_CRB_AGT_ADR) | ||
253 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX8 ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \ | ||
254 | QLA82XX_HW_RPMX8_CRB_AGT_ADR) | ||
255 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_CAS0 ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \ | ||
256 | QLA82XX_HW_CAS0_CRB_AGT_ADR) | ||
257 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_CAS1 ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \ | ||
258 | QLA82XX_HW_CAS1_CRB_AGT_ADR) | ||
259 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_CAS2 ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \ | ||
260 | QLA82XX_HW_CAS2_CRB_AGT_ADR) | ||
261 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_CAS3 ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \ | ||
262 | QLA82XX_HW_CAS3_CRB_AGT_ADR) | ||
263 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_PGNI ((QLA82XX_HW_H4_CH_HUB_ADR << 7) | \ | ||
264 | QLA82XX_HW_PEGNI_CRB_AGT_ADR) | ||
265 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_PGND ((QLA82XX_HW_H4_CH_HUB_ADR << 7) | \ | ||
266 | QLA82XX_HW_PEGND_CRB_AGT_ADR) | ||
267 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_PGN0 ((QLA82XX_HW_H4_CH_HUB_ADR << 7) | \ | ||
268 | QLA82XX_HW_PEGN0_CRB_AGT_ADR) | ||
269 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_PGN1 ((QLA82XX_HW_H4_CH_HUB_ADR << 7) | \ | ||
270 | QLA82XX_HW_PEGN1_CRB_AGT_ADR) | ||
271 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_PGN2 ((QLA82XX_HW_H4_CH_HUB_ADR << 7) | \ | ||
272 | QLA82XX_HW_PEGN2_CRB_AGT_ADR) | ||
273 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_PGN3 ((QLA82XX_HW_H4_CH_HUB_ADR << 7) | \ | ||
274 | QLA82XX_HW_PEGN3_CRB_AGT_ADR) | ||
275 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_PGN4 ((QLA82XX_HW_H4_CH_HUB_ADR << 7) | \ | ||
276 | QLA82XX_HW_PEGN4_CRB_AGT_ADR) | ||
277 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_PGNC ((QLA82XX_HW_H4_CH_HUB_ADR << 7) | \ | ||
278 | QLA82XX_HW_PEGNC_CRB_AGT_ADR) | ||
279 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_PGR0 ((QLA82XX_HW_H4_CH_HUB_ADR << 7) | \ | ||
280 | QLA82XX_HW_PEGR0_CRB_AGT_ADR) | ||
281 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_PGR1 ((QLA82XX_HW_H4_CH_HUB_ADR << 7) | \ | ||
282 | QLA82XX_HW_PEGR1_CRB_AGT_ADR) | ||
283 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_PGR2 ((QLA82XX_HW_H4_CH_HUB_ADR << 7) | \ | ||
284 | QLA82XX_HW_PEGR2_CRB_AGT_ADR) | ||
285 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_PGR3 ((QLA82XX_HW_H4_CH_HUB_ADR << 7) | \ | ||
286 | QLA82XX_HW_PEGR3_CRB_AGT_ADR) | ||
287 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_PGSI ((QLA82XX_HW_H5_CH_HUB_ADR << 7) | \ | ||
288 | QLA82XX_HW_PEGSI_CRB_AGT_ADR) | ||
289 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_PGSD ((QLA82XX_HW_H5_CH_HUB_ADR << 7) | \ | ||
290 | QLA82XX_HW_PEGSD_CRB_AGT_ADR) | ||
291 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_PGS0 ((QLA82XX_HW_H5_CH_HUB_ADR << 7) | \ | ||
292 | QLA82XX_HW_PEGS0_CRB_AGT_ADR) | ||
293 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_PGS1 ((QLA82XX_HW_H5_CH_HUB_ADR << 7) | \ | ||
294 | QLA82XX_HW_PEGS1_CRB_AGT_ADR) | ||
295 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_PGS2 ((QLA82XX_HW_H5_CH_HUB_ADR << 7) | \ | ||
296 | QLA82XX_HW_PEGS2_CRB_AGT_ADR) | ||
297 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_PGS3 ((QLA82XX_HW_H5_CH_HUB_ADR << 7) | \ | ||
298 | QLA82XX_HW_PEGS3_CRB_AGT_ADR) | ||
299 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_PGSC ((QLA82XX_HW_H5_CH_HUB_ADR << 7) | \ | ||
300 | QLA82XX_HW_PEGSC_CRB_AGT_ADR) | ||
301 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_CAM ((QLA82XX_HW_H6_CH_HUB_ADR << 7) | \ | ||
302 | QLA82XX_HW_NCM_CRB_AGT_ADR) | ||
303 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_TIMR ((QLA82XX_HW_H6_CH_HUB_ADR << 7) | \ | ||
304 | QLA82XX_HW_TMR_CRB_AGT_ADR) | ||
305 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_XDMA ((QLA82XX_HW_H6_CH_HUB_ADR << 7) | \ | ||
306 | QLA82XX_HW_XDMA_CRB_AGT_ADR) | ||
307 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_SN ((QLA82XX_HW_H6_CH_HUB_ADR << 7) | \ | ||
308 | QLA82XX_HW_SN_CRB_AGT_ADR) | ||
309 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_I2Q ((QLA82XX_HW_H6_CH_HUB_ADR << 7) | \ | ||
310 | QLA82XX_HW_I2Q_CRB_AGT_ADR) | ||
311 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_ROMUSB ((QLA82XX_HW_H6_CH_HUB_ADR << 7) | \ | ||
312 | QLA82XX_HW_ROMUSB_CRB_AGT_ADR) | ||
313 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_OCM0 ((QLA82XX_HW_H6_CH_HUB_ADR << 7) | \ | ||
314 | QLA82XX_HW_OCM0_CRB_AGT_ADR) | ||
315 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_OCM1 ((QLA82XX_HW_H6_CH_HUB_ADR << 7) | \ | ||
316 | QLA82XX_HW_OCM1_CRB_AGT_ADR) | ||
317 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_LPC ((QLA82XX_HW_H6_CH_HUB_ADR << 7) | \ | ||
318 | QLA82XX_HW_LPC_CRB_AGT_ADR) | ||
319 | |||
320 | #define ROMUSB_GLB (QLA82XX_CRB_ROMUSB + 0x00000) | ||
321 | #define QLA82XX_ROMUSB_GLB_PEGTUNE_DONE (ROMUSB_GLB + 0x005c) | ||
322 | #define QLA82XX_ROMUSB_GLB_STATUS (ROMUSB_GLB + 0x0004) | ||
323 | #define QLA82XX_ROMUSB_GLB_SW_RESET (ROMUSB_GLB + 0x0008) | ||
324 | #define QLA82XX_ROMUSB_ROM_ADDRESS (ROMUSB_ROM + 0x0008) | ||
325 | #define QLA82XX_ROMUSB_ROM_WDATA (ROMUSB_ROM + 0x000c) | ||
326 | #define QLA82XX_ROMUSB_ROM_ABYTE_CNT (ROMUSB_ROM + 0x0010) | ||
327 | #define QLA82XX_ROMUSB_ROM_DUMMY_BYTE_CNT (ROMUSB_ROM + 0x0014) | ||
328 | #define QLA82XX_ROMUSB_ROM_RDATA (ROMUSB_ROM + 0x0018) | ||
329 | |||
330 | #define ROMUSB_ROM (QLA82XX_CRB_ROMUSB + 0x10000) | ||
331 | #define QLA82XX_ROMUSB_ROM_INSTR_OPCODE (ROMUSB_ROM + 0x0004) | ||
332 | #define QLA82XX_ROMUSB_GLB_CAS_RST (ROMUSB_GLB + 0x0038) | ||
333 | |||
334 | /* Lock IDs for ROM lock */ | ||
335 | #define ROM_LOCK_DRIVER 0x0d417340 | ||
336 | |||
337 | #define QLA82XX_PCI_CRB_WINDOWSIZE 0x00100000 /* all are 1MB windows */ | ||
338 | #define QLA82XX_PCI_CRB_WINDOW(A) \ | ||
339 | (QLA82XX_PCI_CRBSPACE + (A)*QLA82XX_PCI_CRB_WINDOWSIZE) | ||
340 | #define QLA82XX_CRB_C2C_0 \ | ||
341 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_C2C0) | ||
342 | #define QLA82XX_CRB_C2C_1 \ | ||
343 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_C2C1) | ||
344 | #define QLA82XX_CRB_C2C_2 \ | ||
345 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_C2C2) | ||
346 | #define QLA82XX_CRB_CAM \ | ||
347 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_CAM) | ||
348 | #define QLA82XX_CRB_CASPER \ | ||
349 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_CAS) | ||
350 | #define QLA82XX_CRB_CASPER_0 \ | ||
351 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_CAS0) | ||
352 | #define QLA82XX_CRB_CASPER_1 \ | ||
353 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_CAS1) | ||
354 | #define QLA82XX_CRB_CASPER_2 \ | ||
355 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_CAS2) | ||
356 | #define QLA82XX_CRB_DDR_MD \ | ||
357 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_MS) | ||
358 | #define QLA82XX_CRB_DDR_NET \ | ||
359 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_MN) | ||
360 | #define QLA82XX_CRB_EPG \ | ||
361 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_EG) | ||
362 | #define QLA82XX_CRB_I2Q \ | ||
363 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_I2Q) | ||
364 | #define QLA82XX_CRB_NIU \ | ||
365 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_NIU) | ||
366 | |||
367 | #define QLA82XX_CRB_PCIX_HOST \ | ||
368 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PH) | ||
369 | #define QLA82XX_CRB_PCIX_HOST2 \ | ||
370 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PH2) | ||
371 | #define QLA82XX_CRB_PCIX_MD \ | ||
372 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PS) | ||
373 | #define QLA82XX_CRB_PCIE \ | ||
374 | QLA82XX_CRB_PCIX_MD | ||
375 | |||
376 | /* window 1 pcie slot */ | ||
377 | #define QLA82XX_CRB_PCIE2 \ | ||
378 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PS2) | ||
379 | #define QLA82XX_CRB_PEG_MD_0 \ | ||
380 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PGS0) | ||
381 | #define QLA82XX_CRB_PEG_MD_1 \ | ||
382 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PGS1) | ||
383 | #define QLA82XX_CRB_PEG_MD_2 \ | ||
384 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PGS2) | ||
385 | #define QLA82XX_CRB_PEG_MD_3 \ | ||
386 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PGS3) | ||
387 | #define QLA82XX_CRB_PEG_MD_3 \ | ||
388 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PGS3) | ||
389 | #define QLA82XX_CRB_PEG_MD_D \ | ||
390 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PGSD) | ||
391 | #define QLA82XX_CRB_PEG_MD_I \ | ||
392 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PGSI) | ||
393 | #define QLA82XX_CRB_PEG_NET_0 \ | ||
394 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PGN0) | ||
395 | #define QLA82XX_CRB_PEG_NET_1 \ | ||
396 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PGN1) | ||
397 | #define QLA82XX_CRB_PEG_NET_2 \ | ||
398 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PGN2) | ||
399 | #define QLA82XX_CRB_PEG_NET_3 \ | ||
400 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PGN3) | ||
401 | #define QLA82XX_CRB_PEG_NET_4 \ | ||
402 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PGN4) | ||
403 | #define QLA82XX_CRB_PEG_NET_D \ | ||
404 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PGND) | ||
405 | #define QLA82XX_CRB_PEG_NET_I \ | ||
406 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PGNI) | ||
407 | #define QLA82XX_CRB_PQM_MD \ | ||
408 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_QMS) | ||
409 | #define QLA82XX_CRB_PQM_NET \ | ||
410 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_QMN) | ||
411 | #define QLA82XX_CRB_QDR_MD \ | ||
412 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_SS) | ||
413 | #define QLA82XX_CRB_QDR_NET \ | ||
414 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_SN) | ||
415 | #define QLA82XX_CRB_ROMUSB \ | ||
416 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_ROMUSB) | ||
417 | #define QLA82XX_CRB_RPMX_0 \ | ||
418 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_RPMX0) | ||
419 | #define QLA82XX_CRB_RPMX_1 \ | ||
420 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_RPMX1) | ||
421 | #define QLA82XX_CRB_RPMX_2 \ | ||
422 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_RPMX2) | ||
423 | #define QLA82XX_CRB_RPMX_3 \ | ||
424 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_RPMX3) | ||
425 | #define QLA82XX_CRB_RPMX_4 \ | ||
426 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_RPMX4) | ||
427 | #define QLA82XX_CRB_RPMX_5 \ | ||
428 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_RPMX5) | ||
429 | #define QLA82XX_CRB_RPMX_6 \ | ||
430 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_RPMX6) | ||
431 | #define QLA82XX_CRB_RPMX_7 \ | ||
432 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_RPMX7) | ||
433 | #define QLA82XX_CRB_SQM_MD_0 \ | ||
434 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_SQS0) | ||
435 | #define QLA82XX_CRB_SQM_MD_1 \ | ||
436 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_SQS1) | ||
437 | #define QLA82XX_CRB_SQM_MD_2 \ | ||
438 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_SQS2) | ||
439 | #define QLA82XX_CRB_SQM_MD_3 \ | ||
440 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_SQS3) | ||
441 | #define QLA82XX_CRB_SQM_NET_0 \ | ||
442 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_SQN0) | ||
443 | #define QLA82XX_CRB_SQM_NET_1 \ | ||
444 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_SQN1) | ||
445 | #define QLA82XX_CRB_SQM_NET_2 \ | ||
446 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_SQN2) | ||
447 | #define QLA82XX_CRB_SQM_NET_3 \ | ||
448 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_SQN3) | ||
449 | #define QLA82XX_CRB_SRE \ | ||
450 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_SRE) | ||
451 | #define QLA82XX_CRB_TIMER \ | ||
452 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_TIMR) | ||
453 | #define QLA82XX_CRB_XDMA \ | ||
454 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_XDMA) | ||
455 | #define QLA82XX_CRB_I2C0 \ | ||
456 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_I2C0) | ||
457 | #define QLA82XX_CRB_I2C1 \ | ||
458 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_I2C1) | ||
459 | #define QLA82XX_CRB_OCM0 \ | ||
460 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_OCM0) | ||
461 | #define QLA82XX_CRB_SMB \ | ||
462 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_SMB) | ||
463 | #define QLA82XX_CRB_MAX \ | ||
464 | QLA82XX_PCI_CRB_WINDOW(64) | ||
465 | |||
466 | /* | ||
467 | * ====================== BASE ADDRESSES ON-CHIP ====================== | ||
468 | * Base addresses of major components on-chip. | ||
469 | * ====================== BASE ADDRESSES ON-CHIP ====================== | ||
470 | */ | ||
471 | #define QLA82XX_ADDR_DDR_NET (0x0000000000000000ULL) | ||
472 | #define QLA82XX_ADDR_DDR_NET_MAX (0x000000000fffffffULL) | ||
473 | |||
474 | /* Imbus address bit used to indicate a host address. This bit is | ||
475 | * eliminated by the pcie bar and bar select before presentation | ||
476 | * over pcie. */ | ||
477 | /* host memory via IMBUS */ | ||
478 | #define QLA82XX_P2_ADDR_PCIE (0x0000000800000000ULL) | ||
479 | #define QLA82XX_P3_ADDR_PCIE (0x0000008000000000ULL) | ||
480 | #define QLA82XX_ADDR_PCIE_MAX (0x0000000FFFFFFFFFULL) | ||
481 | #define QLA82XX_ADDR_OCM0 (0x0000000200000000ULL) | ||
482 | #define QLA82XX_ADDR_OCM0_MAX (0x00000002000fffffULL) | ||
483 | #define QLA82XX_ADDR_OCM1 (0x0000000200400000ULL) | ||
484 | #define QLA82XX_ADDR_OCM1_MAX (0x00000002004fffffULL) | ||
485 | #define QLA82XX_ADDR_QDR_NET (0x0000000300000000ULL) | ||
486 | |||
487 | #define QLA82XX_P2_ADDR_QDR_NET_MAX (0x00000003001fffffULL) | ||
488 | #define QLA82XX_P3_ADDR_QDR_NET_MAX (0x0000000303ffffffULL) | ||
489 | |||
490 | #define QLA82XX_PCI_CRBSPACE (unsigned long)0x06000000 | ||
491 | #define QLA82XX_PCI_DIRECT_CRB (unsigned long)0x04400000 | ||
492 | #define QLA82XX_PCI_CAMQM (unsigned long)0x04800000 | ||
493 | #define QLA82XX_PCI_CAMQM_MAX (unsigned long)0x04ffffff | ||
494 | #define QLA82XX_PCI_DDR_NET (unsigned long)0x00000000 | ||
495 | #define QLA82XX_PCI_QDR_NET (unsigned long)0x04000000 | ||
496 | #define QLA82XX_PCI_QDR_NET_MAX (unsigned long)0x043fffff | ||
497 | |||
498 | /* | ||
499 | * Register offsets for MN | ||
500 | */ | ||
501 | #define MIU_CONTROL (0x000) | ||
502 | #define MIU_TAG (0x004) | ||
503 | #define MIU_TEST_AGT_CTRL (0x090) | ||
504 | #define MIU_TEST_AGT_ADDR_LO (0x094) | ||
505 | #define MIU_TEST_AGT_ADDR_HI (0x098) | ||
506 | #define MIU_TEST_AGT_WRDATA_LO (0x0a0) | ||
507 | #define MIU_TEST_AGT_WRDATA_HI (0x0a4) | ||
508 | #define MIU_TEST_AGT_WRDATA(i) (0x0a0+(4*(i))) | ||
509 | #define MIU_TEST_AGT_RDDATA_LO (0x0a8) | ||
510 | #define MIU_TEST_AGT_RDDATA_HI (0x0ac) | ||
511 | #define MIU_TEST_AGT_RDDATA(i) (0x0a8+(4*(i))) | ||
512 | #define MIU_TEST_AGT_ADDR_MASK 0xfffffff8 | ||
513 | #define MIU_TEST_AGT_UPPER_ADDR(off) (0) | ||
514 | |||
515 | /* MIU_TEST_AGT_CTRL flags. work for SIU as well */ | ||
516 | #define MIU_TA_CTL_START 1 | ||
517 | #define MIU_TA_CTL_ENABLE 2 | ||
518 | #define MIU_TA_CTL_WRITE 4 | ||
519 | #define MIU_TA_CTL_BUSY 8 | ||
520 | |||
521 | /*CAM RAM */ | ||
522 | # define QLA82XX_CAM_RAM_BASE (QLA82XX_CRB_CAM + 0x02000) | ||
523 | # define QLA82XX_CAM_RAM(reg) (QLA82XX_CAM_RAM_BASE + (reg)) | ||
524 | |||
525 | #define QLA82XX_PEG_TUNE_MN_SPD_ZEROED 0x80000000 | ||
526 | #define QLA82XX_BOOT_LOADER_MN_ISSUE 0xff00ffff | ||
527 | #define QLA82XX_PORT_MODE_ADDR (QLA82XX_CAM_RAM(0x24)) | ||
528 | #define QLA82XX_PEG_HALT_STATUS1 (QLA82XX_CAM_RAM(0xa8)) | ||
529 | #define QLA82XX_PEG_HALT_STATUS2 (QLA82XX_CAM_RAM(0xac)) | ||
530 | #define QLA82XX_PEG_ALIVE_COUNTER (QLA82XX_CAM_RAM(0xb0)) | ||
531 | |||
532 | #define QLA82XX_CAMRAM_DB1 (QLA82XX_CAM_RAM(0x1b8)) | ||
533 | #define QLA82XX_CAMRAM_DB2 (QLA82XX_CAM_RAM(0x1bc)) | ||
534 | |||
535 | #define HALT_STATUS_UNRECOVERABLE 0x80000000 | ||
536 | #define HALT_STATUS_RECOVERABLE 0x40000000 | ||
537 | |||
538 | /* Driver Coexistence Defines */ | ||
539 | #define QLA82XX_CRB_DRV_ACTIVE (QLA82XX_CAM_RAM(0x138)) | ||
540 | #define QLA82XX_CRB_DEV_STATE (QLA82XX_CAM_RAM(0x140)) | ||
541 | #define QLA82XX_CRB_DEV_PART_INFO (QLA82XX_CAM_RAM(0x14c)) | ||
542 | #define QLA82XX_CRB_DRV_IDC_VERSION (QLA82XX_CAM_RAM(0x174)) | ||
543 | #define QLA82XX_CRB_DRV_STATE (QLA82XX_CAM_RAM(0x144)) | ||
544 | #define QLA82XX_CRB_DRV_SCRATCH (QLA82XX_CAM_RAM(0x148)) | ||
545 | #define QLA82XX_CRB_DEV_PART_INFO (QLA82XX_CAM_RAM(0x14c)) | ||
546 | |||
547 | /* Every driver should use these Device State */ | ||
548 | #define QLA82XX_DEV_COLD 1 | ||
549 | #define QLA82XX_DEV_INITIALIZING 2 | ||
550 | #define QLA82XX_DEV_READY 3 | ||
551 | #define QLA82XX_DEV_NEED_RESET 4 | ||
552 | #define QLA82XX_DEV_NEED_QUIESCENT 5 | ||
553 | #define QLA82XX_DEV_FAILED 6 | ||
554 | #define QLA82XX_DEV_QUIESCENT 7 | ||
555 | #define MAX_STATES 8 /* Increment if new state added */ | ||
556 | |||
557 | #define QLA82XX_IDC_VERSION 1 | ||
558 | #define QLA82XX_ROM_DEV_INIT_TIMEOUT 30 | ||
559 | #define QLA82XX_ROM_DRV_RESET_ACK_TIMEOUT 10 | ||
560 | |||
561 | #define QLA82XX_ROM_LOCK_ID (QLA82XX_CAM_RAM(0x100)) | ||
562 | #define QLA82XX_CRB_WIN_LOCK_ID (QLA82XX_CAM_RAM(0x124)) | ||
563 | #define QLA82XX_FW_VERSION_MAJOR (QLA82XX_CAM_RAM(0x150)) | ||
564 | #define QLA82XX_FW_VERSION_MINOR (QLA82XX_CAM_RAM(0x154)) | ||
565 | #define QLA82XX_FW_VERSION_SUB (QLA82XX_CAM_RAM(0x158)) | ||
566 | #define QLA82XX_PCIE_REG(reg) (QLA82XX_CRB_PCIE + (reg)) | ||
567 | |||
568 | #define PCIE_CHICKEN3 (0x120c8) | ||
569 | #define PCIE_SETUP_FUNCTION (0x12040) | ||
570 | #define PCIE_SETUP_FUNCTION2 (0x12048) | ||
571 | |||
572 | #define QLA82XX_PCIX_PS_REG(reg) (QLA82XX_CRB_PCIX_MD + (reg)) | ||
573 | #define QLA82XX_PCIX_PS2_REG(reg) (QLA82XX_CRB_PCIE2 + (reg)) | ||
574 | |||
575 | #define PCIE_SEM2_LOCK (0x1c010) /* Flash lock */ | ||
576 | #define PCIE_SEM2_UNLOCK (0x1c014) /* Flash unlock */ | ||
577 | #define PCIE_SEM5_LOCK (0x1c028) /* Coexistence lock */ | ||
578 | #define PCIE_SEM5_UNLOCK (0x1c02c) /* Coexistence unlock */ | ||
579 | #define PCIE_SEM7_LOCK (0x1c038) /* crb win lock */ | ||
580 | #define PCIE_SEM7_UNLOCK (0x1c03c) /* crbwin unlock*/ | ||
581 | |||
582 | /* Different drive state */ | ||
583 | #define QLA82XX_DRVST_NOT_RDY 0 | ||
584 | #define QLA82XX_DRVST_RST_RDY 1 | ||
585 | #define QLA82XX_DRVST_QSNT_RDY 2 | ||
586 | |||
587 | /* | ||
588 | * The PCI VendorID and DeviceID for our board. | ||
589 | */ | ||
590 | #define PCI_DEVICE_ID_QLOGIC_ISP8021 0x8021 | ||
591 | |||
592 | #define QLA82XX_MSIX_TBL_SPACE 8192 | ||
593 | #define QLA82XX_PCI_REG_MSIX_TBL 0x44 | ||
594 | #define QLA82XX_PCI_MSIX_CONTROL 0x40 | ||
595 | |||
596 | struct crb_128M_2M_sub_block_map { | ||
597 | unsigned valid; | ||
598 | unsigned start_128M; | ||
599 | unsigned end_128M; | ||
600 | unsigned start_2M; | ||
601 | }; | ||
602 | |||
603 | struct crb_128M_2M_block_map { | ||
604 | struct crb_128M_2M_sub_block_map sub_block[16]; | ||
605 | }; | ||
606 | |||
607 | struct crb_addr_pair { | ||
608 | long addr; | ||
609 | long data; | ||
610 | }; | ||
611 | |||
612 | #define ADDR_ERROR ((unsigned long) 0xffffffff) | ||
613 | #define MAX_CTL_CHECK 1000 | ||
614 | |||
615 | /*************************************************************************** | ||
616 | * PCI related defines. | ||
617 | **************************************************************************/ | ||
618 | |||
619 | /* | ||
620 | * Interrupt related defines. | ||
621 | */ | ||
622 | #define PCIX_TARGET_STATUS (0x10118) | ||
623 | #define PCIX_TARGET_STATUS_F1 (0x10160) | ||
624 | #define PCIX_TARGET_STATUS_F2 (0x10164) | ||
625 | #define PCIX_TARGET_STATUS_F3 (0x10168) | ||
626 | #define PCIX_TARGET_STATUS_F4 (0x10360) | ||
627 | #define PCIX_TARGET_STATUS_F5 (0x10364) | ||
628 | #define PCIX_TARGET_STATUS_F6 (0x10368) | ||
629 | #define PCIX_TARGET_STATUS_F7 (0x1036c) | ||
630 | |||
631 | #define PCIX_TARGET_MASK (0x10128) | ||
632 | #define PCIX_TARGET_MASK_F1 (0x10170) | ||
633 | #define PCIX_TARGET_MASK_F2 (0x10174) | ||
634 | #define PCIX_TARGET_MASK_F3 (0x10178) | ||
635 | #define PCIX_TARGET_MASK_F4 (0x10370) | ||
636 | #define PCIX_TARGET_MASK_F5 (0x10374) | ||
637 | #define PCIX_TARGET_MASK_F6 (0x10378) | ||
638 | #define PCIX_TARGET_MASK_F7 (0x1037c) | ||
639 | |||
640 | /* | ||
641 | * Message Signaled Interrupts | ||
642 | */ | ||
643 | #define PCIX_MSI_F0 (0x13000) | ||
644 | #define PCIX_MSI_F1 (0x13004) | ||
645 | #define PCIX_MSI_F2 (0x13008) | ||
646 | #define PCIX_MSI_F3 (0x1300c) | ||
647 | #define PCIX_MSI_F4 (0x13010) | ||
648 | #define PCIX_MSI_F5 (0x13014) | ||
649 | #define PCIX_MSI_F6 (0x13018) | ||
650 | #define PCIX_MSI_F7 (0x1301c) | ||
651 | #define PCIX_MSI_F(FUNC) (0x13000 + ((FUNC) * 4)) | ||
652 | #define PCIX_INT_VECTOR (0x10100) | ||
653 | #define PCIX_INT_MASK (0x10104) | ||
654 | |||
655 | /* | ||
656 | * Interrupt state machine and other bits. | ||
657 | */ | ||
658 | #define PCIE_MISCCFG_RC (0x1206c) | ||
659 | |||
660 | #define ISR_INT_TARGET_STATUS \ | ||
661 | (QLA82XX_PCIX_PS_REG(PCIX_TARGET_STATUS)) | ||
662 | #define ISR_INT_TARGET_STATUS_F1 \ | ||
663 | (QLA82XX_PCIX_PS_REG(PCIX_TARGET_STATUS_F1)) | ||
664 | #define ISR_INT_TARGET_STATUS_F2 \ | ||
665 | (QLA82XX_PCIX_PS_REG(PCIX_TARGET_STATUS_F2)) | ||
666 | #define ISR_INT_TARGET_STATUS_F3 \ | ||
667 | (QLA82XX_PCIX_PS_REG(PCIX_TARGET_STATUS_F3)) | ||
668 | #define ISR_INT_TARGET_STATUS_F4 \ | ||
669 | (QLA82XX_PCIX_PS_REG(PCIX_TARGET_STATUS_F4)) | ||
670 | #define ISR_INT_TARGET_STATUS_F5 \ | ||
671 | (QLA82XX_PCIX_PS_REG(PCIX_TARGET_STATUS_F5)) | ||
672 | #define ISR_INT_TARGET_STATUS_F6 \ | ||
673 | (QLA82XX_PCIX_PS_REG(PCIX_TARGET_STATUS_F6)) | ||
674 | #define ISR_INT_TARGET_STATUS_F7 \ | ||
675 | (QLA82XX_PCIX_PS_REG(PCIX_TARGET_STATUS_F7)) | ||
676 | |||
677 | #define ISR_INT_TARGET_MASK \ | ||
678 | (QLA82XX_PCIX_PS_REG(PCIX_TARGET_MASK)) | ||
679 | #define ISR_INT_TARGET_MASK_F1 \ | ||
680 | (QLA82XX_PCIX_PS_REG(PCIX_TARGET_MASK_F1)) | ||
681 | #define ISR_INT_TARGET_MASK_F2 \ | ||
682 | (QLA82XX_PCIX_PS_REG(PCIX_TARGET_MASK_F2)) | ||
683 | #define ISR_INT_TARGET_MASK_F3 \ | ||
684 | (QLA82XX_PCIX_PS_REG(PCIX_TARGET_MASK_F3)) | ||
685 | #define ISR_INT_TARGET_MASK_F4 \ | ||
686 | (QLA82XX_PCIX_PS_REG(PCIX_TARGET_MASK_F4)) | ||
687 | #define ISR_INT_TARGET_MASK_F5 \ | ||
688 | (QLA82XX_PCIX_PS_REG(PCIX_TARGET_MASK_F5)) | ||
689 | #define ISR_INT_TARGET_MASK_F6 \ | ||
690 | (QLA82XX_PCIX_PS_REG(PCIX_TARGET_MASK_F6)) | ||
691 | #define ISR_INT_TARGET_MASK_F7 \ | ||
692 | (QLA82XX_PCIX_PS_REG(PCIX_TARGET_MASK_F7)) | ||
693 | |||
694 | #define ISR_INT_VECTOR \ | ||
695 | (QLA82XX_PCIX_PS_REG(PCIX_INT_VECTOR)) | ||
696 | #define ISR_INT_MASK \ | ||
697 | (QLA82XX_PCIX_PS_REG(PCIX_INT_MASK)) | ||
698 | #define ISR_INT_STATE_REG \ | ||
699 | (QLA82XX_PCIX_PS_REG(PCIE_MISCCFG_RC)) | ||
700 | |||
701 | #define ISR_MSI_INT_TRIGGER(FUNC) \ | ||
702 | (QLA82XX_PCIX_PS_REG(PCIX_MSI_F(FUNC))) | ||
703 | |||
704 | #define ISR_IS_LEGACY_INTR_IDLE(VAL) (((VAL) & 0x300) == 0) | ||
705 | #define ISR_IS_LEGACY_INTR_TRIGGERED(VAL) (((VAL) & 0x300) == 0x200) | ||
706 | |||
707 | /* | ||
708 | * PCI Interrupt Vector Values. | ||
709 | */ | ||
710 | #define PCIX_INT_VECTOR_BIT_F0 0x0080 | ||
711 | #define PCIX_INT_VECTOR_BIT_F1 0x0100 | ||
712 | #define PCIX_INT_VECTOR_BIT_F2 0x0200 | ||
713 | #define PCIX_INT_VECTOR_BIT_F3 0x0400 | ||
714 | #define PCIX_INT_VECTOR_BIT_F4 0x0800 | ||
715 | #define PCIX_INT_VECTOR_BIT_F5 0x1000 | ||
716 | #define PCIX_INT_VECTOR_BIT_F6 0x2000 | ||
717 | #define PCIX_INT_VECTOR_BIT_F7 0x4000 | ||
718 | |||
719 | struct qla82xx_legacy_intr_set { | ||
720 | uint32_t int_vec_bit; | ||
721 | uint32_t tgt_status_reg; | ||
722 | uint32_t tgt_mask_reg; | ||
723 | uint32_t pci_int_reg; | ||
724 | }; | ||
725 | |||
726 | #define QLA82XX_LEGACY_INTR_CONFIG \ | ||
727 | { \ | ||
728 | { \ | ||
729 | .int_vec_bit = PCIX_INT_VECTOR_BIT_F0, \ | ||
730 | .tgt_status_reg = ISR_INT_TARGET_STATUS, \ | ||
731 | .tgt_mask_reg = ISR_INT_TARGET_MASK, \ | ||
732 | .pci_int_reg = ISR_MSI_INT_TRIGGER(0) }, \ | ||
733 | \ | ||
734 | { \ | ||
735 | .int_vec_bit = PCIX_INT_VECTOR_BIT_F1, \ | ||
736 | .tgt_status_reg = ISR_INT_TARGET_STATUS_F1, \ | ||
737 | .tgt_mask_reg = ISR_INT_TARGET_MASK_F1, \ | ||
738 | .pci_int_reg = ISR_MSI_INT_TRIGGER(1) }, \ | ||
739 | \ | ||
740 | { \ | ||
741 | .int_vec_bit = PCIX_INT_VECTOR_BIT_F2, \ | ||
742 | .tgt_status_reg = ISR_INT_TARGET_STATUS_F2, \ | ||
743 | .tgt_mask_reg = ISR_INT_TARGET_MASK_F2, \ | ||
744 | .pci_int_reg = ISR_MSI_INT_TRIGGER(2) }, \ | ||
745 | \ | ||
746 | { \ | ||
747 | .int_vec_bit = PCIX_INT_VECTOR_BIT_F3, \ | ||
748 | .tgt_status_reg = ISR_INT_TARGET_STATUS_F3, \ | ||
749 | .tgt_mask_reg = ISR_INT_TARGET_MASK_F3, \ | ||
750 | .pci_int_reg = ISR_MSI_INT_TRIGGER(3) }, \ | ||
751 | \ | ||
752 | { \ | ||
753 | .int_vec_bit = PCIX_INT_VECTOR_BIT_F4, \ | ||
754 | .tgt_status_reg = ISR_INT_TARGET_STATUS_F4, \ | ||
755 | .tgt_mask_reg = ISR_INT_TARGET_MASK_F4, \ | ||
756 | .pci_int_reg = ISR_MSI_INT_TRIGGER(4) }, \ | ||
757 | \ | ||
758 | { \ | ||
759 | .int_vec_bit = PCIX_INT_VECTOR_BIT_F5, \ | ||
760 | .tgt_status_reg = ISR_INT_TARGET_STATUS_F5, \ | ||
761 | .tgt_mask_reg = ISR_INT_TARGET_MASK_F5, \ | ||
762 | .pci_int_reg = ISR_MSI_INT_TRIGGER(5) }, \ | ||
763 | \ | ||
764 | { \ | ||
765 | .int_vec_bit = PCIX_INT_VECTOR_BIT_F6, \ | ||
766 | .tgt_status_reg = ISR_INT_TARGET_STATUS_F6, \ | ||
767 | .tgt_mask_reg = ISR_INT_TARGET_MASK_F6, \ | ||
768 | .pci_int_reg = ISR_MSI_INT_TRIGGER(6) }, \ | ||
769 | \ | ||
770 | { \ | ||
771 | .int_vec_bit = PCIX_INT_VECTOR_BIT_F7, \ | ||
772 | .tgt_status_reg = ISR_INT_TARGET_STATUS_F7, \ | ||
773 | .tgt_mask_reg = ISR_INT_TARGET_MASK_F7, \ | ||
774 | .pci_int_reg = ISR_MSI_INT_TRIGGER(7) }, \ | ||
775 | } | ||
776 | |||
777 | #define BOOTLD_START 0x10000 | ||
778 | #define IMAGE_START 0x100000 | ||
779 | #define FLASH_ADDR_START 0x43000 | ||
780 | |||
781 | /* Magic number to let user know flash is programmed */ | ||
782 | #define QLA82XX_BDINFO_MAGIC 0x12345678 | ||
783 | #define FW_SIZE_OFFSET (0x3e840c) | ||
784 | |||
785 | #define QLA82XX_IS_REVISION_P3PLUS(_rev_) ((_rev_) >= 0x50) | ||
786 | #define MIU_TEST_AGT_WRDATA_UPPER_LO (0x0b0) | ||
787 | #define MIU_TEST_AGT_WRDATA_UPPER_HI (0x0b4) | ||
788 | |||
789 | #ifndef readq | ||
790 | static inline u64 readq(void __iomem *addr) | ||
791 | { | ||
792 | return readl(addr) | (((u64) readl(addr + 4)) << 32LL); | ||
793 | } | ||
794 | #endif | ||
795 | |||
796 | #ifndef writeq | ||
797 | static inline void writeq(u64 val, void __iomem *addr) | ||
798 | { | ||
799 | writel(((u32) (val)), (addr)); | ||
800 | writel(((u32) (val >> 32)), (addr + 4)); | ||
801 | } | ||
802 | #endif | ||
803 | |||
804 | /* Request and response queue size */ | ||
805 | #define REQUEST_ENTRY_CNT_82XX 128 /* Number of request entries. */ | ||
806 | #define RESPONSE_ENTRY_CNT_82XX 128 /* Number of response entries.*/ | ||
807 | |||
808 | /* | ||
809 | * ISP 8021 I/O Register Set structure definitions. | ||
810 | */ | ||
811 | struct device_reg_82xx { | ||
812 | uint32_t req_q_out[64]; /* Request Queue out-Pointer (64 * 4) */ | ||
813 | uint32_t rsp_q_in[64]; /* Response Queue In-Pointer. */ | ||
814 | uint32_t rsp_q_out[64]; /* Response Queue Out-Pointer. */ | ||
815 | |||
816 | uint16_t mailbox_in[32]; /* Mail box In registers */ | ||
817 | uint16_t unused_1[32]; | ||
818 | uint32_t hint; /* Host interrupt register */ | ||
819 | #define HINT_MBX_INT_PENDING BIT_0 | ||
820 | uint16_t unused_2[62]; | ||
821 | uint16_t mailbox_out[32]; /* Mail box Out registers */ | ||
822 | uint32_t unused_3[48]; | ||
823 | |||
824 | uint32_t host_status; /* host status */ | ||
825 | #define HSRX_RISC_INT BIT_15 /* RISC to Host interrupt. */ | ||
826 | #define HSRX_RISC_PAUSED BIT_8 /* RISC Paused. */ | ||
827 | uint32_t host_int; /* Interrupt status. */ | ||
828 | #define ISRX_NX_RISC_INT BIT_0 /* RISC interrupt. */ | ||
829 | }; | ||
830 | |||
831 | struct fcp_cmnd { | ||
832 | struct scsi_lun lun; | ||
833 | uint8_t crn; | ||
834 | uint8_t task_attribute; | ||
835 | uint8_t task_managment; | ||
836 | uint8_t additional_cdb_len; | ||
837 | uint8_t cdb[260]; /* 256 for CDB len and 4 for FCP_DL */ | ||
838 | }; | ||
839 | |||
840 | struct dsd_dma { | ||
841 | struct list_head list; | ||
842 | dma_addr_t dsd_list_dma; | ||
843 | void *dsd_addr; | ||
844 | }; | ||
845 | |||
846 | #define QLA_DSDS_PER_IOCB 37 | ||
847 | #define QLA_DSD_SIZE 12 | ||
848 | struct ct6_dsd { | ||
849 | uint16_t fcp_cmnd_len; | ||
850 | dma_addr_t fcp_cmnd_dma; | ||
851 | struct fcp_cmnd *fcp_cmnd; | ||
852 | int dsd_use_cnt; | ||
853 | struct list_head dsd_list; | ||
854 | }; | ||
855 | |||
856 | #define MBC_TOGGLE_INTR 0x10 | ||
857 | |||
858 | /* Flash offset */ | ||
859 | #define FLT_REG_BOOTLOAD_82XX 0x72 | ||
860 | #define FLT_REG_BOOT_CODE_82XX 0x78 | ||
861 | #define FLT_REG_FW_82XX 0x74 | ||
862 | #define FLT_REG_GOLD_FW_82XX 0x75 | ||
863 | #define FLT_REG_VPD_82XX 0x81 | ||
864 | |||
865 | #define FA_VPD_SIZE_82XX 0x400 | ||
866 | |||
867 | #define FA_FLASH_LAYOUT_ADDR_82 0xFC400 | ||
868 | |||
869 | /****************************************************************************** | ||
870 | * | ||
871 | * Definitions specific to M25P flash | ||
872 | * | ||
873 | ******************************************************************************* | ||
874 | * Instructions | ||
875 | */ | ||
876 | #define M25P_INSTR_WREN 0x06 | ||
877 | #define M25P_INSTR_WRDI 0x04 | ||
878 | #define M25P_INSTR_RDID 0x9f | ||
879 | #define M25P_INSTR_RDSR 0x05 | ||
880 | #define M25P_INSTR_WRSR 0x01 | ||
881 | #define M25P_INSTR_READ 0x03 | ||
882 | #define M25P_INSTR_FAST_READ 0x0b | ||
883 | #define M25P_INSTR_PP 0x02 | ||
884 | #define M25P_INSTR_SE 0xd8 | ||
885 | #define M25P_INSTR_BE 0xc7 | ||
886 | #define M25P_INSTR_DP 0xb9 | ||
887 | #define M25P_INSTR_RES 0xab | ||
888 | |||
889 | #endif | ||
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 48c37e38ed01..be1a8fcbb1fb 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c | |||
@@ -24,11 +24,18 @@ | |||
24 | */ | 24 | */ |
25 | char qla2x00_version_str[40]; | 25 | char qla2x00_version_str[40]; |
26 | 26 | ||
27 | static int apidev_major; | ||
28 | |||
27 | /* | 29 | /* |
28 | * SRB allocation cache | 30 | * SRB allocation cache |
29 | */ | 31 | */ |
30 | static struct kmem_cache *srb_cachep; | 32 | static struct kmem_cache *srb_cachep; |
31 | 33 | ||
34 | /* | ||
35 | * CT6 CTX allocation cache | ||
36 | */ | ||
37 | static struct kmem_cache *ctx_cachep; | ||
38 | |||
32 | int ql2xlogintimeout = 20; | 39 | int ql2xlogintimeout = 20; |
33 | module_param(ql2xlogintimeout, int, S_IRUGO|S_IRUSR); | 40 | module_param(ql2xlogintimeout, int, S_IRUGO|S_IRUSR); |
34 | MODULE_PARM_DESC(ql2xlogintimeout, | 41 | MODULE_PARM_DESC(ql2xlogintimeout, |
@@ -65,13 +72,19 @@ MODULE_PARM_DESC(ql2xextended_error_logging, | |||
65 | "Option to enable extended error logging, " | 72 | "Option to enable extended error logging, " |
66 | "Default is 0 - no logging. 1 - log errors."); | 73 | "Default is 0 - no logging. 1 - log errors."); |
67 | 74 | ||
75 | int ql2xshiftctondsd = 6; | ||
76 | module_param(ql2xshiftctondsd, int, S_IRUGO|S_IRUSR); | ||
77 | MODULE_PARM_DESC(ql2xshiftctondsd, | ||
78 | "Set to control shifting of command type processing " | ||
79 | "based on total number of SG elements."); | ||
80 | |||
68 | static void qla2x00_free_device(scsi_qla_host_t *); | 81 | static void qla2x00_free_device(scsi_qla_host_t *); |
69 | 82 | ||
70 | int ql2xfdmienable=1; | 83 | int ql2xfdmienable=1; |
71 | module_param(ql2xfdmienable, int, S_IRUGO|S_IRUSR); | 84 | module_param(ql2xfdmienable, int, S_IRUGO|S_IRUSR); |
72 | MODULE_PARM_DESC(ql2xfdmienable, | 85 | MODULE_PARM_DESC(ql2xfdmienable, |
73 | "Enables FDMI registratons " | 86 | "Enables FDMI registrations. " |
74 | "Default is 0 - no FDMI. 1 - perfom FDMI."); | 87 | "0 - no FDMI. Default is 1 - perform FDMI."); |
75 | 88 | ||
76 | #define MAX_Q_DEPTH 32 | 89 | #define MAX_Q_DEPTH 32 |
77 | static int ql2xmaxqdepth = MAX_Q_DEPTH; | 90 | static int ql2xmaxqdepth = MAX_Q_DEPTH; |
@@ -79,6 +92,19 @@ module_param(ql2xmaxqdepth, int, S_IRUGO|S_IWUSR); | |||
79 | MODULE_PARM_DESC(ql2xmaxqdepth, | 92 | MODULE_PARM_DESC(ql2xmaxqdepth, |
80 | "Maximum queue depth to report for target devices."); | 93 | "Maximum queue depth to report for target devices."); |
81 | 94 | ||
95 | /* Do not change the value of this after module load */ | ||
96 | int ql2xenabledif = 1; | ||
97 | module_param(ql2xenabledif, int, S_IRUGO|S_IWUSR); | ||
98 | MODULE_PARM_DESC(ql2xenabledif, | ||
99 | " Enable T10-CRC-DIF " | ||
100 | " Default is 0 - No DIF Support. 1 - Enable it"); | ||
101 | |||
102 | int ql2xenablehba_err_chk; | ||
103 | module_param(ql2xenablehba_err_chk, int, S_IRUGO|S_IWUSR); | ||
104 | MODULE_PARM_DESC(ql2xenablehba_err_chk, | ||
105 | " Enable T10-CRC-DIF Error isolation by HBA" | ||
106 | " Default is 0 - Error isolation disabled, 1 - Enable it"); | ||
107 | |||
82 | int ql2xiidmaenable=1; | 108 | int ql2xiidmaenable=1; |
83 | module_param(ql2xiidmaenable, int, S_IRUGO|S_IRUSR); | 109 | module_param(ql2xiidmaenable, int, S_IRUGO|S_IRUSR); |
84 | MODULE_PARM_DESC(ql2xiidmaenable, | 110 | MODULE_PARM_DESC(ql2xiidmaenable, |
@@ -114,6 +140,32 @@ MODULE_PARM_DESC(ql2xetsenable, | |||
114 | "Enables firmware ETS burst." | 140 | "Enables firmware ETS burst." |
115 | "Default is 0 - skip ETS enablement."); | 141 | "Default is 0 - skip ETS enablement."); |
116 | 142 | ||
143 | int ql2xdbwr; | ||
144 | module_param(ql2xdbwr, int, S_IRUGO|S_IRUSR); | ||
145 | MODULE_PARM_DESC(ql2xdbwr, | ||
146 | "Option to specify scheme for request queue posting\n" | ||
147 | " 0 -- Regular doorbell.\n" | ||
148 | " 1 -- CAMRAM doorbell (faster).\n"); | ||
149 | |||
150 | int ql2xdontresethba; | ||
151 | module_param(ql2xdontresethba, int, S_IRUGO|S_IRUSR); | ||
152 | MODULE_PARM_DESC(ql2xdontresethba, | ||
153 | "Option to specify reset behaviour\n" | ||
154 | " 0 (Default) -- Reset on failure.\n" | ||
155 | " 1 -- Do not reset on failure.\n"); | ||
156 | |||
157 | int ql2xtargetreset = 1; | ||
158 | module_param(ql2xtargetreset, int, S_IRUGO|S_IRUSR); | ||
159 | MODULE_PARM_DESC(ql2xtargetreset, | ||
160 | "Enable target reset." | ||
161 | "Default is 1 - use hw defaults."); | ||
162 | |||
163 | |||
164 | int ql2xasynctmfenable; | ||
165 | module_param(ql2xasynctmfenable, int, S_IRUGO|S_IRUSR); | ||
166 | MODULE_PARM_DESC(ql2xasynctmfenable, | ||
167 | "Enables issue of TM IOCBs asynchronously via IOCB mechanism" | ||
168 | "Default is 0 - Issue TM IOCBs via mailbox mechanism."); | ||
117 | /* | 169 | /* |
118 | * SCSI host template entry points | 170 | * SCSI host template entry points |
119 | */ | 171 | */ |
@@ -183,6 +235,10 @@ qla2x00_start_timer(scsi_qla_host_t *vha, void *func, unsigned long interval) | |||
183 | static inline void | 235 | static inline void |
184 | qla2x00_restart_timer(scsi_qla_host_t *vha, unsigned long interval) | 236 | qla2x00_restart_timer(scsi_qla_host_t *vha, unsigned long interval) |
185 | { | 237 | { |
238 | /* Currently used for 82XX only. */ | ||
239 | if (vha->device_flags & DFLG_DEV_FAILED) | ||
240 | return; | ||
241 | |||
186 | mod_timer(&vha->timer, jiffies + interval * HZ); | 242 | mod_timer(&vha->timer, jiffies + interval * HZ); |
187 | } | 243 | } |
188 | 244 | ||
@@ -500,6 +556,14 @@ qla2xxx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) | |||
500 | if (fcport->drport) | 556 | if (fcport->drport) |
501 | goto qc24_target_busy; | 557 | goto qc24_target_busy; |
502 | 558 | ||
559 | if (!vha->flags.difdix_supported && | ||
560 | scsi_get_prot_op(cmd) != SCSI_PROT_NORMAL) { | ||
561 | DEBUG2(qla_printk(KERN_ERR, ha, | ||
562 | "DIF Cap Not Reg, fail DIF capable cmd's:%x\n", | ||
563 | cmd->cmnd[0])); | ||
564 | cmd->result = DID_NO_CONNECT << 16; | ||
565 | goto qc24_fail_command; | ||
566 | } | ||
503 | if (atomic_read(&fcport->state) != FCS_ONLINE) { | 567 | if (atomic_read(&fcport->state) != FCS_ONLINE) { |
504 | if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD || | 568 | if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD || |
505 | atomic_read(&base_vha->loop_state) == LOOP_DEAD) { | 569 | atomic_read(&base_vha->loop_state) == LOOP_DEAD) { |
@@ -618,6 +682,50 @@ qla2x00_wait_for_hba_online(scsi_qla_host_t *vha) | |||
618 | return (return_status); | 682 | return (return_status); |
619 | } | 683 | } |
620 | 684 | ||
685 | /* | ||
686 | * qla2x00_wait_for_reset_ready | ||
687 | * Wait till the HBA is online after going through | ||
688 | * <= MAX_RETRIES_OF_ISP_ABORT or | ||
689 | * finally HBA is disabled ie marked offline or flash | ||
690 | * operations are in progress. | ||
691 | * | ||
692 | * Input: | ||
693 | * ha - pointer to host adapter structure | ||
694 | * | ||
695 | * Note: | ||
696 | * Does context switching-Release SPIN_LOCK | ||
697 | * (if any) before calling this routine. | ||
698 | * | ||
699 | * Return: | ||
700 | * Success (Adapter is online/no flash ops) : 0 | ||
701 | * Failed (Adapter is offline/disabled/flash ops in progress) : 1 | ||
702 | */ | ||
703 | int | ||
704 | qla2x00_wait_for_reset_ready(scsi_qla_host_t *vha) | ||
705 | { | ||
706 | int return_status; | ||
707 | unsigned long wait_online; | ||
708 | struct qla_hw_data *ha = vha->hw; | ||
709 | scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev); | ||
710 | |||
711 | wait_online = jiffies + (MAX_LOOP_TIMEOUT * HZ); | ||
712 | while (((test_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags)) || | ||
713 | test_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags) || | ||
714 | test_bit(ISP_ABORT_RETRY, &base_vha->dpc_flags) || | ||
715 | ha->optrom_state != QLA_SWAITING || | ||
716 | ha->dpc_active) && time_before(jiffies, wait_online)) | ||
717 | msleep(1000); | ||
718 | |||
719 | if (base_vha->flags.online && ha->optrom_state == QLA_SWAITING) | ||
720 | return_status = QLA_SUCCESS; | ||
721 | else | ||
722 | return_status = QLA_FUNCTION_FAILED; | ||
723 | |||
724 | DEBUG2(printk("%s return_status=%d\n", __func__, return_status)); | ||
725 | |||
726 | return return_status; | ||
727 | } | ||
728 | |||
621 | int | 729 | int |
622 | qla2x00_wait_for_chip_reset(scsi_qla_host_t *vha) | 730 | qla2x00_wait_for_chip_reset(scsi_qla_host_t *vha) |
623 | { | 731 | { |
@@ -739,7 +847,8 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) | |||
739 | 847 | ||
740 | if (sp == NULL) | 848 | if (sp == NULL) |
741 | continue; | 849 | continue; |
742 | if (sp->ctx) | 850 | if ((sp->ctx) && !(sp->flags & SRB_FCP_CMND_DMA_VALID) && |
851 | !IS_PROT_IO(sp)) | ||
743 | continue; | 852 | continue; |
744 | if (sp->cmd != cmd) | 853 | if (sp->cmd != cmd) |
745 | continue; | 854 | continue; |
@@ -805,7 +914,7 @@ qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *vha, unsigned int t, | |||
805 | sp = req->outstanding_cmds[cnt]; | 914 | sp = req->outstanding_cmds[cnt]; |
806 | if (!sp) | 915 | if (!sp) |
807 | continue; | 916 | continue; |
808 | if (sp->ctx) | 917 | if ((sp->ctx) && !IS_PROT_IO(sp)) |
809 | continue; | 918 | continue; |
810 | if (vha->vp_idx != sp->fcport->vha->vp_idx) | 919 | if (vha->vp_idx != sp->fcport->vha->vp_idx) |
811 | continue; | 920 | continue; |
@@ -834,6 +943,24 @@ qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *vha, unsigned int t, | |||
834 | return status; | 943 | return status; |
835 | } | 944 | } |
836 | 945 | ||
946 | void qla82xx_wait_for_pending_commands(scsi_qla_host_t *vha) | ||
947 | { | ||
948 | int cnt; | ||
949 | srb_t *sp; | ||
950 | struct req_que *req = vha->req; | ||
951 | |||
952 | DEBUG2(qla_printk(KERN_INFO, vha->hw, | ||
953 | "Waiting for pending commands\n")); | ||
954 | for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) { | ||
955 | sp = req->outstanding_cmds[cnt]; | ||
956 | if (qla2x00_eh_wait_for_pending_commands(vha, 0, 0, | ||
957 | sp, WAIT_HOST) == QLA_SUCCESS) { | ||
958 | DEBUG2(qla_printk(KERN_INFO, vha->hw, | ||
959 | "Done wait for pending commands\n")); | ||
960 | } | ||
961 | } | ||
962 | } | ||
963 | |||
837 | static char *reset_errors[] = { | 964 | static char *reset_errors[] = { |
838 | "HBA not online", | 965 | "HBA not online", |
839 | "HBA not ready", | 966 | "HBA not ready", |
@@ -1004,7 +1131,7 @@ qla2xxx_eh_host_reset(struct scsi_cmnd *cmd) | |||
1004 | qla_printk(KERN_INFO, ha, | 1131 | qla_printk(KERN_INFO, ha, |
1005 | "scsi(%ld:%d:%d): ADAPTER RESET ISSUED.\n", vha->host_no, id, lun); | 1132 | "scsi(%ld:%d:%d): ADAPTER RESET ISSUED.\n", vha->host_no, id, lun); |
1006 | 1133 | ||
1007 | if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) | 1134 | if (qla2x00_wait_for_reset_ready(vha) != QLA_SUCCESS) |
1008 | goto eh_host_reset_lock; | 1135 | goto eh_host_reset_lock; |
1009 | 1136 | ||
1010 | /* | 1137 | /* |
@@ -1020,11 +1147,19 @@ qla2xxx_eh_host_reset(struct scsi_cmnd *cmd) | |||
1020 | if (qla2x00_vp_abort_isp(vha)) | 1147 | if (qla2x00_vp_abort_isp(vha)) |
1021 | goto eh_host_reset_lock; | 1148 | goto eh_host_reset_lock; |
1022 | } else { | 1149 | } else { |
1150 | if (IS_QLA82XX(vha->hw)) { | ||
1151 | if (!qla82xx_fcoe_ctx_reset(vha)) { | ||
1152 | /* Ctx reset success */ | ||
1153 | ret = SUCCESS; | ||
1154 | goto eh_host_reset_lock; | ||
1155 | } | ||
1156 | /* fall thru if ctx reset failed */ | ||
1157 | } | ||
1023 | if (ha->wq) | 1158 | if (ha->wq) |
1024 | flush_workqueue(ha->wq); | 1159 | flush_workqueue(ha->wq); |
1025 | 1160 | ||
1026 | set_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags); | 1161 | set_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags); |
1027 | if (qla2x00_abort_isp(base_vha)) { | 1162 | if (ha->isp_ops->abort_isp(base_vha)) { |
1028 | clear_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags); | 1163 | clear_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags); |
1029 | /* failed. schedule dpc to try */ | 1164 | /* failed. schedule dpc to try */ |
1030 | set_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags); | 1165 | set_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags); |
@@ -1064,7 +1199,7 @@ qla2x00_loop_reset(scsi_qla_host_t *vha) | |||
1064 | struct fc_port *fcport; | 1199 | struct fc_port *fcport; |
1065 | struct qla_hw_data *ha = vha->hw; | 1200 | struct qla_hw_data *ha = vha->hw; |
1066 | 1201 | ||
1067 | if (ha->flags.enable_target_reset) { | 1202 | if (ql2xtargetreset == 1 && ha->flags.enable_target_reset) { |
1068 | list_for_each_entry(fcport, &vha->vp_fcports, list) { | 1203 | list_for_each_entry(fcport, &vha->vp_fcports, list) { |
1069 | if (fcport->port_type != FCT_TARGET) | 1204 | if (fcport->port_type != FCT_TARGET) |
1070 | continue; | 1205 | continue; |
@@ -1078,7 +1213,7 @@ qla2x00_loop_reset(scsi_qla_host_t *vha) | |||
1078 | } | 1213 | } |
1079 | } | 1214 | } |
1080 | 1215 | ||
1081 | if (ha->flags.enable_lip_full_login && !IS_QLA81XX(ha)) { | 1216 | if (ha->flags.enable_lip_full_login && !IS_QLA8XXX_TYPE(ha)) { |
1082 | ret = qla2x00_full_login_lip(vha); | 1217 | ret = qla2x00_full_login_lip(vha); |
1083 | if (ret != QLA_SUCCESS) { | 1218 | if (ret != QLA_SUCCESS) { |
1084 | DEBUG2_3(printk("%s(%ld): failed: " | 1219 | DEBUG2_3(printk("%s(%ld): failed: " |
@@ -1125,23 +1260,28 @@ qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res) | |||
1125 | sp = req->outstanding_cmds[cnt]; | 1260 | sp = req->outstanding_cmds[cnt]; |
1126 | if (sp) { | 1261 | if (sp) { |
1127 | req->outstanding_cmds[cnt] = NULL; | 1262 | req->outstanding_cmds[cnt] = NULL; |
1128 | if (!sp->ctx) { | 1263 | if (!sp->ctx || |
1264 | (sp->flags & SRB_FCP_CMND_DMA_VALID) || | ||
1265 | IS_PROT_IO(sp)) { | ||
1129 | sp->cmd->result = res; | 1266 | sp->cmd->result = res; |
1130 | qla2x00_sp_compl(ha, sp); | 1267 | qla2x00_sp_compl(ha, sp); |
1131 | } else { | 1268 | } else { |
1132 | ctx = sp->ctx; | 1269 | ctx = sp->ctx; |
1133 | if (ctx->type == SRB_LOGIN_CMD || ctx->type == SRB_LOGOUT_CMD) { | 1270 | if (ctx->type == SRB_LOGIN_CMD || |
1134 | del_timer_sync(&ctx->timer); | 1271 | ctx->type == SRB_LOGOUT_CMD) { |
1135 | ctx->free(sp); | 1272 | ctx->u.iocb_cmd->free(sp); |
1136 | } else { | 1273 | } else { |
1137 | struct srb_bsg* sp_bsg = (struct srb_bsg*)sp->ctx; | 1274 | struct fc_bsg_job *bsg_job = |
1138 | if (sp_bsg->bsg_job->request->msgcode == FC_BSG_HST_CT) | 1275 | ctx->u.bsg_job; |
1276 | if (bsg_job->request->msgcode | ||
1277 | == FC_BSG_HST_CT) | ||
1139 | kfree(sp->fcport); | 1278 | kfree(sp->fcport); |
1140 | sp_bsg->bsg_job->req->errors = 0; | 1279 | bsg_job->req->errors = 0; |
1141 | sp_bsg->bsg_job->reply->result = res; | 1280 | bsg_job->reply->result = res; |
1142 | sp_bsg->bsg_job->job_done(sp_bsg->bsg_job); | 1281 | bsg_job->job_done(bsg_job); |
1143 | kfree(sp->ctx); | 1282 | kfree(sp->ctx); |
1144 | mempool_free(sp, ha->srb_mempool); | 1283 | mempool_free(sp, |
1284 | ha->srb_mempool); | ||
1145 | } | 1285 | } |
1146 | } | 1286 | } |
1147 | } | 1287 | } |
@@ -1379,6 +1519,7 @@ static struct isp_operations qla2100_isp_ops = { | |||
1379 | .write_optrom = qla2x00_write_optrom_data, | 1519 | .write_optrom = qla2x00_write_optrom_data, |
1380 | .get_flash_version = qla2x00_get_flash_version, | 1520 | .get_flash_version = qla2x00_get_flash_version, |
1381 | .start_scsi = qla2x00_start_scsi, | 1521 | .start_scsi = qla2x00_start_scsi, |
1522 | .abort_isp = qla2x00_abort_isp, | ||
1382 | }; | 1523 | }; |
1383 | 1524 | ||
1384 | static struct isp_operations qla2300_isp_ops = { | 1525 | static struct isp_operations qla2300_isp_ops = { |
@@ -1414,6 +1555,7 @@ static struct isp_operations qla2300_isp_ops = { | |||
1414 | .write_optrom = qla2x00_write_optrom_data, | 1555 | .write_optrom = qla2x00_write_optrom_data, |
1415 | .get_flash_version = qla2x00_get_flash_version, | 1556 | .get_flash_version = qla2x00_get_flash_version, |
1416 | .start_scsi = qla2x00_start_scsi, | 1557 | .start_scsi = qla2x00_start_scsi, |
1558 | .abort_isp = qla2x00_abort_isp, | ||
1417 | }; | 1559 | }; |
1418 | 1560 | ||
1419 | static struct isp_operations qla24xx_isp_ops = { | 1561 | static struct isp_operations qla24xx_isp_ops = { |
@@ -1449,6 +1591,7 @@ static struct isp_operations qla24xx_isp_ops = { | |||
1449 | .write_optrom = qla24xx_write_optrom_data, | 1591 | .write_optrom = qla24xx_write_optrom_data, |
1450 | .get_flash_version = qla24xx_get_flash_version, | 1592 | .get_flash_version = qla24xx_get_flash_version, |
1451 | .start_scsi = qla24xx_start_scsi, | 1593 | .start_scsi = qla24xx_start_scsi, |
1594 | .abort_isp = qla2x00_abort_isp, | ||
1452 | }; | 1595 | }; |
1453 | 1596 | ||
1454 | static struct isp_operations qla25xx_isp_ops = { | 1597 | static struct isp_operations qla25xx_isp_ops = { |
@@ -1483,7 +1626,8 @@ static struct isp_operations qla25xx_isp_ops = { | |||
1483 | .read_optrom = qla25xx_read_optrom_data, | 1626 | .read_optrom = qla25xx_read_optrom_data, |
1484 | .write_optrom = qla24xx_write_optrom_data, | 1627 | .write_optrom = qla24xx_write_optrom_data, |
1485 | .get_flash_version = qla24xx_get_flash_version, | 1628 | .get_flash_version = qla24xx_get_flash_version, |
1486 | .start_scsi = qla24xx_start_scsi, | 1629 | .start_scsi = qla24xx_dif_start_scsi, |
1630 | .abort_isp = qla2x00_abort_isp, | ||
1487 | }; | 1631 | }; |
1488 | 1632 | ||
1489 | static struct isp_operations qla81xx_isp_ops = { | 1633 | static struct isp_operations qla81xx_isp_ops = { |
@@ -1519,6 +1663,43 @@ static struct isp_operations qla81xx_isp_ops = { | |||
1519 | .write_optrom = qla24xx_write_optrom_data, | 1663 | .write_optrom = qla24xx_write_optrom_data, |
1520 | .get_flash_version = qla24xx_get_flash_version, | 1664 | .get_flash_version = qla24xx_get_flash_version, |
1521 | .start_scsi = qla24xx_start_scsi, | 1665 | .start_scsi = qla24xx_start_scsi, |
1666 | .abort_isp = qla2x00_abort_isp, | ||
1667 | }; | ||
1668 | |||
1669 | static struct isp_operations qla82xx_isp_ops = { | ||
1670 | .pci_config = qla82xx_pci_config, | ||
1671 | .reset_chip = qla82xx_reset_chip, | ||
1672 | .chip_diag = qla24xx_chip_diag, | ||
1673 | .config_rings = qla82xx_config_rings, | ||
1674 | .reset_adapter = qla24xx_reset_adapter, | ||
1675 | .nvram_config = qla81xx_nvram_config, | ||
1676 | .update_fw_options = qla24xx_update_fw_options, | ||
1677 | .load_risc = qla82xx_load_risc, | ||
1678 | .pci_info_str = qla82xx_pci_info_str, | ||
1679 | .fw_version_str = qla24xx_fw_version_str, | ||
1680 | .intr_handler = qla82xx_intr_handler, | ||
1681 | .enable_intrs = qla82xx_enable_intrs, | ||
1682 | .disable_intrs = qla82xx_disable_intrs, | ||
1683 | .abort_command = qla24xx_abort_command, | ||
1684 | .target_reset = qla24xx_abort_target, | ||
1685 | .lun_reset = qla24xx_lun_reset, | ||
1686 | .fabric_login = qla24xx_login_fabric, | ||
1687 | .fabric_logout = qla24xx_fabric_logout, | ||
1688 | .calc_req_entries = NULL, | ||
1689 | .build_iocbs = NULL, | ||
1690 | .prep_ms_iocb = qla24xx_prep_ms_iocb, | ||
1691 | .prep_ms_fdmi_iocb = qla24xx_prep_ms_fdmi_iocb, | ||
1692 | .read_nvram = qla24xx_read_nvram_data, | ||
1693 | .write_nvram = qla24xx_write_nvram_data, | ||
1694 | .fw_dump = qla24xx_fw_dump, | ||
1695 | .beacon_on = qla24xx_beacon_on, | ||
1696 | .beacon_off = qla24xx_beacon_off, | ||
1697 | .beacon_blink = qla24xx_beacon_blink, | ||
1698 | .read_optrom = qla82xx_read_optrom_data, | ||
1699 | .write_optrom = qla82xx_write_optrom_data, | ||
1700 | .get_flash_version = qla24xx_get_flash_version, | ||
1701 | .start_scsi = qla82xx_start_scsi, | ||
1702 | .abort_isp = qla82xx_abort_isp, | ||
1522 | }; | 1703 | }; |
1523 | 1704 | ||
1524 | static inline void | 1705 | static inline void |
@@ -1607,10 +1788,22 @@ qla2x00_set_isp_flags(struct qla_hw_data *ha) | |||
1607 | ha->device_type |= DT_IIDMA; | 1788 | ha->device_type |= DT_IIDMA; |
1608 | ha->fw_srisc_address = RISC_START_ADDRESS_2400; | 1789 | ha->fw_srisc_address = RISC_START_ADDRESS_2400; |
1609 | break; | 1790 | break; |
1791 | case PCI_DEVICE_ID_QLOGIC_ISP8021: | ||
1792 | ha->device_type |= DT_ISP8021; | ||
1793 | ha->device_type |= DT_ZIO_SUPPORTED; | ||
1794 | ha->device_type |= DT_FWI2; | ||
1795 | ha->fw_srisc_address = RISC_START_ADDRESS_2400; | ||
1796 | /* Initialize 82XX ISP flags */ | ||
1797 | qla82xx_init_flags(ha); | ||
1798 | break; | ||
1610 | } | 1799 | } |
1611 | 1800 | ||
1612 | /* Get adapter physical port no from interrupt pin register. */ | 1801 | if (IS_QLA82XX(ha)) |
1613 | pci_read_config_byte(ha->pdev, PCI_INTERRUPT_PIN, &ha->port_no); | 1802 | ha->port_no = !(ha->portnum & 1); |
1803 | else | ||
1804 | /* Get adapter physical port no from interrupt pin register. */ | ||
1805 | pci_read_config_byte(ha->pdev, PCI_INTERRUPT_PIN, &ha->port_no); | ||
1806 | |||
1614 | if (ha->port_no & 1) | 1807 | if (ha->port_no & 1) |
1615 | ha->flags.port0 = 1; | 1808 | ha->flags.port0 = 1; |
1616 | else | 1809 | else |
@@ -1624,6 +1817,9 @@ qla2x00_iospace_config(struct qla_hw_data *ha) | |||
1624 | uint16_t msix; | 1817 | uint16_t msix; |
1625 | int cpus; | 1818 | int cpus; |
1626 | 1819 | ||
1820 | if (IS_QLA82XX(ha)) | ||
1821 | return qla82xx_iospace_config(ha); | ||
1822 | |||
1627 | if (pci_request_selected_regions(ha->pdev, ha->bars, | 1823 | if (pci_request_selected_regions(ha->pdev, ha->bars, |
1628 | QLA2XXX_DRIVER_NAME)) { | 1824 | QLA2XXX_DRIVER_NAME)) { |
1629 | qla_printk(KERN_WARNING, ha, | 1825 | qla_printk(KERN_WARNING, ha, |
@@ -1767,7 +1963,8 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1767 | pdev->device == PCI_DEVICE_ID_QLOGIC_ISP5422 || | 1963 | pdev->device == PCI_DEVICE_ID_QLOGIC_ISP5422 || |
1768 | pdev->device == PCI_DEVICE_ID_QLOGIC_ISP5432 || | 1964 | pdev->device == PCI_DEVICE_ID_QLOGIC_ISP5432 || |
1769 | pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2532 || | 1965 | pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2532 || |
1770 | pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8001) { | 1966 | pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8001 || |
1967 | pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8021) { | ||
1771 | bars = pci_select_bars(pdev, IORESOURCE_MEM); | 1968 | bars = pci_select_bars(pdev, IORESOURCE_MEM); |
1772 | mem_only = 1; | 1969 | mem_only = 1; |
1773 | } | 1970 | } |
@@ -1897,6 +2094,19 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1897 | ha->flash_data_off = FARX_ACCESS_FLASH_DATA_81XX; | 2094 | ha->flash_data_off = FARX_ACCESS_FLASH_DATA_81XX; |
1898 | ha->nvram_conf_off = ~0; | 2095 | ha->nvram_conf_off = ~0; |
1899 | ha->nvram_data_off = ~0; | 2096 | ha->nvram_data_off = ~0; |
2097 | } else if (IS_QLA82XX(ha)) { | ||
2098 | ha->mbx_count = MAILBOX_REGISTER_COUNT; | ||
2099 | req_length = REQUEST_ENTRY_CNT_82XX; | ||
2100 | rsp_length = RESPONSE_ENTRY_CNT_82XX; | ||
2101 | ha->max_loop_id = SNS_LAST_LOOP_ID_2300; | ||
2102 | ha->init_cb_size = sizeof(struct mid_init_cb_81xx); | ||
2103 | ha->gid_list_info_size = 8; | ||
2104 | ha->optrom_size = OPTROM_SIZE_82XX; | ||
2105 | ha->isp_ops = &qla82xx_isp_ops; | ||
2106 | ha->flash_conf_off = FARX_ACCESS_FLASH_CONF; | ||
2107 | ha->flash_data_off = FARX_ACCESS_FLASH_DATA; | ||
2108 | ha->nvram_conf_off = FARX_ACCESS_NVRAM_CONF; | ||
2109 | ha->nvram_data_off = FARX_ACCESS_NVRAM_DATA; | ||
1900 | } | 2110 | } |
1901 | 2111 | ||
1902 | mutex_init(&ha->vport_lock); | 2112 | mutex_init(&ha->vport_lock); |
@@ -1969,6 +2179,7 @@ que_init: | |||
1969 | " pointers\n"); | 2179 | " pointers\n"); |
1970 | goto probe_init_failed; | 2180 | goto probe_init_failed; |
1971 | } | 2181 | } |
2182 | |||
1972 | ha->rsp_q_map[0] = rsp; | 2183 | ha->rsp_q_map[0] = rsp; |
1973 | ha->req_q_map[0] = req; | 2184 | ha->req_q_map[0] = req; |
1974 | rsp->req = req; | 2185 | rsp->req = req; |
@@ -1987,6 +2198,12 @@ que_init: | |||
1987 | rsp->rsp_q_out = &ha->mqiobase->isp25mq.rsp_q_out; | 2198 | rsp->rsp_q_out = &ha->mqiobase->isp25mq.rsp_q_out; |
1988 | } | 2199 | } |
1989 | 2200 | ||
2201 | if (IS_QLA82XX(ha)) { | ||
2202 | req->req_q_out = &ha->iobase->isp82.req_q_out[0]; | ||
2203 | rsp->rsp_q_in = &ha->iobase->isp82.rsp_q_in[0]; | ||
2204 | rsp->rsp_q_out = &ha->iobase->isp82.rsp_q_out[0]; | ||
2205 | } | ||
2206 | |||
1990 | if (qla2x00_initialize_adapter(base_vha)) { | 2207 | if (qla2x00_initialize_adapter(base_vha)) { |
1991 | qla_printk(KERN_WARNING, ha, | 2208 | qla_printk(KERN_WARNING, ha, |
1992 | "Failed to initialize adapter\n"); | 2209 | "Failed to initialize adapter\n"); |
@@ -1995,6 +2212,14 @@ que_init: | |||
1995 | "Adapter flags %x.\n", | 2212 | "Adapter flags %x.\n", |
1996 | base_vha->host_no, base_vha->device_flags)); | 2213 | base_vha->host_no, base_vha->device_flags)); |
1997 | 2214 | ||
2215 | if (IS_QLA82XX(ha)) { | ||
2216 | qla82xx_idc_lock(ha); | ||
2217 | qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, | ||
2218 | QLA82XX_DEV_FAILED); | ||
2219 | qla82xx_idc_unlock(ha); | ||
2220 | qla_printk(KERN_INFO, ha, "HW State: FAILED\n"); | ||
2221 | } | ||
2222 | |||
1998 | ret = -ENODEV; | 2223 | ret = -ENODEV; |
1999 | goto probe_failed; | 2224 | goto probe_failed; |
2000 | } | 2225 | } |
@@ -2033,6 +2258,24 @@ skip_dpc: | |||
2033 | DEBUG2(printk("DEBUG: detect hba %ld at address = %p\n", | 2258 | DEBUG2(printk("DEBUG: detect hba %ld at address = %p\n", |
2034 | base_vha->host_no, ha)); | 2259 | base_vha->host_no, ha)); |
2035 | 2260 | ||
2261 | if (IS_QLA25XX(ha) && ql2xenabledif) { | ||
2262 | if (ha->fw_attributes & BIT_4) { | ||
2263 | base_vha->flags.difdix_supported = 1; | ||
2264 | DEBUG18(qla_printk(KERN_INFO, ha, | ||
2265 | "Registering for DIF/DIX type 1 and 3" | ||
2266 | " protection.\n")); | ||
2267 | scsi_host_set_prot(host, | ||
2268 | SHOST_DIF_TYPE1_PROTECTION | ||
2269 | | SHOST_DIF_TYPE3_PROTECTION | ||
2270 | | SHOST_DIX_TYPE1_PROTECTION | ||
2271 | | SHOST_DIX_TYPE3_PROTECTION); | ||
2272 | scsi_host_set_guard(host, SHOST_DIX_GUARD_CRC); | ||
2273 | } else | ||
2274 | base_vha->flags.difdix_supported = 0; | ||
2275 | } | ||
2276 | |||
2277 | ha->isp_ops->enable_intrs(ha); | ||
2278 | |||
2036 | ret = scsi_add_host(host, &pdev->dev); | 2279 | ret = scsi_add_host(host, &pdev->dev); |
2037 | if (ret) | 2280 | if (ret) |
2038 | goto probe_failed; | 2281 | goto probe_failed; |
@@ -2040,8 +2283,6 @@ skip_dpc: | |||
2040 | base_vha->flags.init_done = 1; | 2283 | base_vha->flags.init_done = 1; |
2041 | base_vha->flags.online = 1; | 2284 | base_vha->flags.online = 1; |
2042 | 2285 | ||
2043 | ha->isp_ops->enable_intrs(ha); | ||
2044 | |||
2045 | scsi_scan_host(host); | 2286 | scsi_scan_host(host); |
2046 | 2287 | ||
2047 | qla2x00_alloc_sysfs_attr(base_vha); | 2288 | qla2x00_alloc_sysfs_attr(base_vha); |
@@ -2083,9 +2324,17 @@ probe_failed: | |||
2083 | scsi_host_put(base_vha->host); | 2324 | scsi_host_put(base_vha->host); |
2084 | 2325 | ||
2085 | probe_hw_failed: | 2326 | probe_hw_failed: |
2086 | if (ha->iobase) | 2327 | if (IS_QLA82XX(ha)) { |
2087 | iounmap(ha->iobase); | 2328 | qla82xx_idc_lock(ha); |
2088 | 2329 | qla82xx_clear_drv_active(ha); | |
2330 | qla82xx_idc_unlock(ha); | ||
2331 | iounmap((device_reg_t __iomem *)ha->nx_pcibase); | ||
2332 | if (!ql2xdbwr) | ||
2333 | iounmap((device_reg_t __iomem *)ha->nxdb_wr_ptr); | ||
2334 | } else { | ||
2335 | if (ha->iobase) | ||
2336 | iounmap(ha->iobase); | ||
2337 | } | ||
2089 | pci_release_selected_regions(ha->pdev, ha->bars); | 2338 | pci_release_selected_regions(ha->pdev, ha->bars); |
2090 | kfree(ha); | 2339 | kfree(ha); |
2091 | ha = NULL; | 2340 | ha = NULL; |
@@ -2152,11 +2401,17 @@ qla2x00_remove_one(struct pci_dev *pdev) | |||
2152 | 2401 | ||
2153 | scsi_host_put(base_vha->host); | 2402 | scsi_host_put(base_vha->host); |
2154 | 2403 | ||
2155 | if (ha->iobase) | 2404 | if (IS_QLA82XX(ha)) { |
2156 | iounmap(ha->iobase); | 2405 | iounmap((device_reg_t __iomem *)ha->nx_pcibase); |
2406 | if (!ql2xdbwr) | ||
2407 | iounmap((device_reg_t __iomem *)ha->nxdb_wr_ptr); | ||
2408 | } else { | ||
2409 | if (ha->iobase) | ||
2410 | iounmap(ha->iobase); | ||
2157 | 2411 | ||
2158 | if (ha->mqiobase) | 2412 | if (ha->mqiobase) |
2159 | iounmap(ha->mqiobase); | 2413 | iounmap(ha->mqiobase); |
2414 | } | ||
2160 | 2415 | ||
2161 | pci_release_selected_regions(ha->pdev, ha->bars); | 2416 | pci_release_selected_regions(ha->pdev, ha->bars); |
2162 | kfree(ha); | 2417 | kfree(ha); |
@@ -2205,8 +2460,10 @@ qla2x00_free_device(scsi_qla_host_t *vha) | |||
2205 | vha->flags.online = 0; | 2460 | vha->flags.online = 0; |
2206 | 2461 | ||
2207 | /* turn-off interrupts on the card */ | 2462 | /* turn-off interrupts on the card */ |
2208 | if (ha->interrupts_on) | 2463 | if (ha->interrupts_on) { |
2464 | vha->flags.init_done = 0; | ||
2209 | ha->isp_ops->disable_intrs(ha); | 2465 | ha->isp_ops->disable_intrs(ha); |
2466 | } | ||
2210 | 2467 | ||
2211 | qla2x00_free_irqs(vha); | 2468 | qla2x00_free_irqs(vha); |
2212 | 2469 | ||
@@ -2351,10 +2608,25 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len, | |||
2351 | if (!ha->srb_mempool) | 2608 | if (!ha->srb_mempool) |
2352 | goto fail_free_gid_list; | 2609 | goto fail_free_gid_list; |
2353 | 2610 | ||
2611 | if (IS_QLA82XX(ha)) { | ||
2612 | /* Allocate cache for CT6 Ctx. */ | ||
2613 | if (!ctx_cachep) { | ||
2614 | ctx_cachep = kmem_cache_create("qla2xxx_ctx", | ||
2615 | sizeof(struct ct6_dsd), 0, | ||
2616 | SLAB_HWCACHE_ALIGN, NULL); | ||
2617 | if (!ctx_cachep) | ||
2618 | goto fail_free_gid_list; | ||
2619 | } | ||
2620 | ha->ctx_mempool = mempool_create_slab_pool(SRB_MIN_REQ, | ||
2621 | ctx_cachep); | ||
2622 | if (!ha->ctx_mempool) | ||
2623 | goto fail_free_srb_mempool; | ||
2624 | } | ||
2625 | |||
2354 | /* Get memory for cached NVRAM */ | 2626 | /* Get memory for cached NVRAM */ |
2355 | ha->nvram = kzalloc(MAX_NVRAM_SIZE, GFP_KERNEL); | 2627 | ha->nvram = kzalloc(MAX_NVRAM_SIZE, GFP_KERNEL); |
2356 | if (!ha->nvram) | 2628 | if (!ha->nvram) |
2357 | goto fail_free_srb_mempool; | 2629 | goto fail_free_ctx_mempool; |
2358 | 2630 | ||
2359 | snprintf(name, sizeof(name), "%s_%d", QLA2XXX_DRIVER_NAME, | 2631 | snprintf(name, sizeof(name), "%s_%d", QLA2XXX_DRIVER_NAME, |
2360 | ha->pdev->device); | 2632 | ha->pdev->device); |
@@ -2363,6 +2635,24 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len, | |||
2363 | if (!ha->s_dma_pool) | 2635 | if (!ha->s_dma_pool) |
2364 | goto fail_free_nvram; | 2636 | goto fail_free_nvram; |
2365 | 2637 | ||
2638 | if (IS_QLA82XX(ha) || ql2xenabledif) { | ||
2639 | ha->dl_dma_pool = dma_pool_create(name, &ha->pdev->dev, | ||
2640 | DSD_LIST_DMA_POOL_SIZE, 8, 0); | ||
2641 | if (!ha->dl_dma_pool) { | ||
2642 | qla_printk(KERN_WARNING, ha, | ||
2643 | "Memory Allocation failed - dl_dma_pool\n"); | ||
2644 | goto fail_s_dma_pool; | ||
2645 | } | ||
2646 | |||
2647 | ha->fcp_cmnd_dma_pool = dma_pool_create(name, &ha->pdev->dev, | ||
2648 | FCP_CMND_DMA_POOL_SIZE, 8, 0); | ||
2649 | if (!ha->fcp_cmnd_dma_pool) { | ||
2650 | qla_printk(KERN_WARNING, ha, | ||
2651 | "Memory Allocation failed - fcp_cmnd_dma_pool\n"); | ||
2652 | goto fail_dl_dma_pool; | ||
2653 | } | ||
2654 | } | ||
2655 | |||
2366 | /* Allocate memory for SNS commands */ | 2656 | /* Allocate memory for SNS commands */ |
2367 | if (IS_QLA2100(ha) || IS_QLA2200(ha)) { | 2657 | if (IS_QLA2100(ha) || IS_QLA2200(ha)) { |
2368 | /* Get consistent memory allocated for SNS commands */ | 2658 | /* Get consistent memory allocated for SNS commands */ |
@@ -2429,16 +2719,28 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len, | |||
2429 | ha->npiv_info = NULL; | 2719 | ha->npiv_info = NULL; |
2430 | 2720 | ||
2431 | /* Get consistent memory allocated for EX-INIT-CB. */ | 2721 | /* Get consistent memory allocated for EX-INIT-CB. */ |
2432 | if (IS_QLA81XX(ha)) { | 2722 | if (IS_QLA8XXX_TYPE(ha)) { |
2433 | ha->ex_init_cb = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, | 2723 | ha->ex_init_cb = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, |
2434 | &ha->ex_init_cb_dma); | 2724 | &ha->ex_init_cb_dma); |
2435 | if (!ha->ex_init_cb) | 2725 | if (!ha->ex_init_cb) |
2436 | goto fail_ex_init_cb; | 2726 | goto fail_ex_init_cb; |
2437 | } | 2727 | } |
2438 | 2728 | ||
2729 | INIT_LIST_HEAD(&ha->gbl_dsd_list); | ||
2730 | |||
2731 | /* Get consistent memory allocated for Async Port-Database. */ | ||
2732 | if (!IS_FWI2_CAPABLE(ha)) { | ||
2733 | ha->async_pd = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, | ||
2734 | &ha->async_pd_dma); | ||
2735 | if (!ha->async_pd) | ||
2736 | goto fail_async_pd; | ||
2737 | } | ||
2738 | |||
2439 | INIT_LIST_HEAD(&ha->vp_list); | 2739 | INIT_LIST_HEAD(&ha->vp_list); |
2440 | return 1; | 2740 | return 1; |
2441 | 2741 | ||
2742 | fail_async_pd: | ||
2743 | dma_pool_free(ha->s_dma_pool, ha->ex_init_cb, ha->ex_init_cb_dma); | ||
2442 | fail_ex_init_cb: | 2744 | fail_ex_init_cb: |
2443 | kfree(ha->npiv_info); | 2745 | kfree(ha->npiv_info); |
2444 | fail_npiv_info: | 2746 | fail_npiv_info: |
@@ -2465,11 +2767,24 @@ fail_free_ms_iocb: | |||
2465 | ha->ms_iocb = NULL; | 2767 | ha->ms_iocb = NULL; |
2466 | ha->ms_iocb_dma = 0; | 2768 | ha->ms_iocb_dma = 0; |
2467 | fail_dma_pool: | 2769 | fail_dma_pool: |
2770 | if (IS_QLA82XX(ha) || ql2xenabledif) { | ||
2771 | dma_pool_destroy(ha->fcp_cmnd_dma_pool); | ||
2772 | ha->fcp_cmnd_dma_pool = NULL; | ||
2773 | } | ||
2774 | fail_dl_dma_pool: | ||
2775 | if (IS_QLA82XX(ha) || ql2xenabledif) { | ||
2776 | dma_pool_destroy(ha->dl_dma_pool); | ||
2777 | ha->dl_dma_pool = NULL; | ||
2778 | } | ||
2779 | fail_s_dma_pool: | ||
2468 | dma_pool_destroy(ha->s_dma_pool); | 2780 | dma_pool_destroy(ha->s_dma_pool); |
2469 | ha->s_dma_pool = NULL; | 2781 | ha->s_dma_pool = NULL; |
2470 | fail_free_nvram: | 2782 | fail_free_nvram: |
2471 | kfree(ha->nvram); | 2783 | kfree(ha->nvram); |
2472 | ha->nvram = NULL; | 2784 | ha->nvram = NULL; |
2785 | fail_free_ctx_mempool: | ||
2786 | mempool_destroy(ha->ctx_mempool); | ||
2787 | ha->ctx_mempool = NULL; | ||
2473 | fail_free_srb_mempool: | 2788 | fail_free_srb_mempool: |
2474 | mempool_destroy(ha->srb_mempool); | 2789 | mempool_destroy(ha->srb_mempool); |
2475 | ha->srb_mempool = NULL; | 2790 | ha->srb_mempool = NULL; |
@@ -2538,7 +2853,11 @@ qla2x00_mem_free(struct qla_hw_data *ha) | |||
2538 | dma_pool_free(ha->s_dma_pool, ha->ms_iocb, ha->ms_iocb_dma); | 2853 | dma_pool_free(ha->s_dma_pool, ha->ms_iocb, ha->ms_iocb_dma); |
2539 | 2854 | ||
2540 | if (ha->ex_init_cb) | 2855 | if (ha->ex_init_cb) |
2541 | dma_pool_free(ha->s_dma_pool, ha->ex_init_cb, ha->ex_init_cb_dma); | 2856 | dma_pool_free(ha->s_dma_pool, |
2857 | ha->ex_init_cb, ha->ex_init_cb_dma); | ||
2858 | |||
2859 | if (ha->async_pd) | ||
2860 | dma_pool_free(ha->s_dma_pool, ha->async_pd, ha->async_pd_dma); | ||
2542 | 2861 | ||
2543 | if (ha->s_dma_pool) | 2862 | if (ha->s_dma_pool) |
2544 | dma_pool_destroy(ha->s_dma_pool); | 2863 | dma_pool_destroy(ha->s_dma_pool); |
@@ -2547,14 +2866,39 @@ qla2x00_mem_free(struct qla_hw_data *ha) | |||
2547 | dma_free_coherent(&ha->pdev->dev, GID_LIST_SIZE, ha->gid_list, | 2866 | dma_free_coherent(&ha->pdev->dev, GID_LIST_SIZE, ha->gid_list, |
2548 | ha->gid_list_dma); | 2867 | ha->gid_list_dma); |
2549 | 2868 | ||
2869 | if (IS_QLA82XX(ha)) { | ||
2870 | if (!list_empty(&ha->gbl_dsd_list)) { | ||
2871 | struct dsd_dma *dsd_ptr, *tdsd_ptr; | ||
2872 | |||
2873 | /* clean up allocated prev pool */ | ||
2874 | list_for_each_entry_safe(dsd_ptr, | ||
2875 | tdsd_ptr, &ha->gbl_dsd_list, list) { | ||
2876 | dma_pool_free(ha->dl_dma_pool, | ||
2877 | dsd_ptr->dsd_addr, dsd_ptr->dsd_list_dma); | ||
2878 | list_del(&dsd_ptr->list); | ||
2879 | kfree(dsd_ptr); | ||
2880 | } | ||
2881 | } | ||
2882 | } | ||
2883 | |||
2884 | if (ha->dl_dma_pool) | ||
2885 | dma_pool_destroy(ha->dl_dma_pool); | ||
2886 | |||
2887 | if (ha->fcp_cmnd_dma_pool) | ||
2888 | dma_pool_destroy(ha->fcp_cmnd_dma_pool); | ||
2889 | |||
2890 | if (ha->ctx_mempool) | ||
2891 | mempool_destroy(ha->ctx_mempool); | ||
2892 | |||
2550 | if (ha->init_cb) | 2893 | if (ha->init_cb) |
2551 | dma_free_coherent(&ha->pdev->dev, ha->init_cb_size, | 2894 | dma_free_coherent(&ha->pdev->dev, ha->init_cb_size, |
2552 | ha->init_cb, ha->init_cb_dma); | 2895 | ha->init_cb, ha->init_cb_dma); |
2553 | vfree(ha->optrom_buffer); | 2896 | vfree(ha->optrom_buffer); |
2554 | kfree(ha->nvram); | 2897 | kfree(ha->nvram); |
2555 | kfree(ha->npiv_info); | 2898 | kfree(ha->npiv_info); |
2556 | 2899 | ||
2557 | ha->srb_mempool = NULL; | 2900 | ha->srb_mempool = NULL; |
2901 | ha->ctx_mempool = NULL; | ||
2558 | ha->eft = NULL; | 2902 | ha->eft = NULL; |
2559 | ha->eft_dma = 0; | 2903 | ha->eft_dma = 0; |
2560 | ha->sns_cmd = NULL; | 2904 | ha->sns_cmd = NULL; |
@@ -2567,8 +2911,12 @@ qla2x00_mem_free(struct qla_hw_data *ha) | |||
2567 | ha->init_cb_dma = 0; | 2911 | ha->init_cb_dma = 0; |
2568 | ha->ex_init_cb = NULL; | 2912 | ha->ex_init_cb = NULL; |
2569 | ha->ex_init_cb_dma = 0; | 2913 | ha->ex_init_cb_dma = 0; |
2914 | ha->async_pd = NULL; | ||
2915 | ha->async_pd_dma = 0; | ||
2570 | 2916 | ||
2571 | ha->s_dma_pool = NULL; | 2917 | ha->s_dma_pool = NULL; |
2918 | ha->dl_dma_pool = NULL; | ||
2919 | ha->fcp_cmnd_dma_pool = NULL; | ||
2572 | 2920 | ||
2573 | ha->gid_list = NULL; | 2921 | ha->gid_list = NULL; |
2574 | ha->gid_list_dma = 0; | 2922 | ha->gid_list_dma = 0; |
@@ -2691,6 +3039,8 @@ qla2x00_post_async_work(login, QLA_EVT_ASYNC_LOGIN); | |||
2691 | qla2x00_post_async_work(login_done, QLA_EVT_ASYNC_LOGIN_DONE); | 3039 | qla2x00_post_async_work(login_done, QLA_EVT_ASYNC_LOGIN_DONE); |
2692 | qla2x00_post_async_work(logout, QLA_EVT_ASYNC_LOGOUT); | 3040 | qla2x00_post_async_work(logout, QLA_EVT_ASYNC_LOGOUT); |
2693 | qla2x00_post_async_work(logout_done, QLA_EVT_ASYNC_LOGOUT_DONE); | 3041 | qla2x00_post_async_work(logout_done, QLA_EVT_ASYNC_LOGOUT_DONE); |
3042 | qla2x00_post_async_work(adisc, QLA_EVT_ASYNC_ADISC); | ||
3043 | qla2x00_post_async_work(adisc_done, QLA_EVT_ASYNC_ADISC_DONE); | ||
2694 | 3044 | ||
2695 | int | 3045 | int |
2696 | qla2x00_post_uevent_work(struct scsi_qla_host *vha, u32 code) | 3046 | qla2x00_post_uevent_work(struct scsi_qla_host *vha, u32 code) |
@@ -2760,6 +3110,14 @@ qla2x00_do_work(struct scsi_qla_host *vha) | |||
2760 | qla2x00_async_logout_done(vha, e->u.logio.fcport, | 3110 | qla2x00_async_logout_done(vha, e->u.logio.fcport, |
2761 | e->u.logio.data); | 3111 | e->u.logio.data); |
2762 | break; | 3112 | break; |
3113 | case QLA_EVT_ASYNC_ADISC: | ||
3114 | qla2x00_async_adisc(vha, e->u.logio.fcport, | ||
3115 | e->u.logio.data); | ||
3116 | break; | ||
3117 | case QLA_EVT_ASYNC_ADISC_DONE: | ||
3118 | qla2x00_async_adisc_done(vha, e->u.logio.fcport, | ||
3119 | e->u.logio.data); | ||
3120 | break; | ||
2763 | case QLA_EVT_UEVENT: | 3121 | case QLA_EVT_UEVENT: |
2764 | qla2x00_uevent_emit(vha, e->u.uevent.code); | 3122 | qla2x00_uevent_emit(vha, e->u.uevent.code); |
2765 | break; | 3123 | break; |
@@ -2785,9 +3143,8 @@ void qla2x00_relogin(struct scsi_qla_host *vha) | |||
2785 | * If the port is not ONLINE then try to login | 3143 | * If the port is not ONLINE then try to login |
2786 | * to it if we haven't run out of retries. | 3144 | * to it if we haven't run out of retries. |
2787 | */ | 3145 | */ |
2788 | if (atomic_read(&fcport->state) != | 3146 | if (atomic_read(&fcport->state) != FCS_ONLINE && |
2789 | FCS_ONLINE && fcport->login_retry) { | 3147 | fcport->login_retry && !(fcport->flags & FCF_ASYNC_SENT)) { |
2790 | |||
2791 | fcport->login_retry--; | 3148 | fcport->login_retry--; |
2792 | if (fcport->flags & FCF_FABRIC_DEVICE) { | 3149 | if (fcport->flags & FCF_FABRIC_DEVICE) { |
2793 | if (fcport->flags & FCF_FCP2_DEVICE) | 3150 | if (fcport->flags & FCF_FCP2_DEVICE) |
@@ -2798,6 +3155,7 @@ void qla2x00_relogin(struct scsi_qla_host *vha) | |||
2798 | fcport->d_id.b.al_pa); | 3155 | fcport->d_id.b.al_pa); |
2799 | 3156 | ||
2800 | if (IS_ALOGIO_CAPABLE(ha)) { | 3157 | if (IS_ALOGIO_CAPABLE(ha)) { |
3158 | fcport->flags |= FCF_ASYNC_SENT; | ||
2801 | data[0] = 0; | 3159 | data[0] = 0; |
2802 | data[1] = QLA_LOGIO_LOGIN_RETRIED; | 3160 | data[1] = QLA_LOGIO_LOGIN_RETRIED; |
2803 | status = qla2x00_post_async_login_work( | 3161 | status = qla2x00_post_async_login_work( |
@@ -2896,6 +3254,45 @@ qla2x00_do_dpc(void *data) | |||
2896 | 3254 | ||
2897 | qla2x00_do_work(base_vha); | 3255 | qla2x00_do_work(base_vha); |
2898 | 3256 | ||
3257 | if (IS_QLA82XX(ha)) { | ||
3258 | if (test_and_clear_bit(ISP_UNRECOVERABLE, | ||
3259 | &base_vha->dpc_flags)) { | ||
3260 | qla82xx_idc_lock(ha); | ||
3261 | qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, | ||
3262 | QLA82XX_DEV_FAILED); | ||
3263 | qla82xx_idc_unlock(ha); | ||
3264 | qla_printk(KERN_INFO, ha, | ||
3265 | "HW State: FAILED\n"); | ||
3266 | qla82xx_device_state_handler(base_vha); | ||
3267 | continue; | ||
3268 | } | ||
3269 | |||
3270 | if (test_and_clear_bit(FCOE_CTX_RESET_NEEDED, | ||
3271 | &base_vha->dpc_flags)) { | ||
3272 | |||
3273 | DEBUG(printk(KERN_INFO | ||
3274 | "scsi(%ld): dpc: sched " | ||
3275 | "qla82xx_fcoe_ctx_reset ha = %p\n", | ||
3276 | base_vha->host_no, ha)); | ||
3277 | if (!(test_and_set_bit(ABORT_ISP_ACTIVE, | ||
3278 | &base_vha->dpc_flags))) { | ||
3279 | if (qla82xx_fcoe_ctx_reset(base_vha)) { | ||
3280 | /* FCoE-ctx reset failed. | ||
3281 | * Escalate to chip-reset | ||
3282 | */ | ||
3283 | set_bit(ISP_ABORT_NEEDED, | ||
3284 | &base_vha->dpc_flags); | ||
3285 | } | ||
3286 | clear_bit(ABORT_ISP_ACTIVE, | ||
3287 | &base_vha->dpc_flags); | ||
3288 | } | ||
3289 | |||
3290 | DEBUG(printk("scsi(%ld): dpc:" | ||
3291 | " qla82xx_fcoe_ctx_reset end\n", | ||
3292 | base_vha->host_no)); | ||
3293 | } | ||
3294 | } | ||
3295 | |||
2899 | if (test_and_clear_bit(ISP_ABORT_NEEDED, | 3296 | if (test_and_clear_bit(ISP_ABORT_NEEDED, |
2900 | &base_vha->dpc_flags)) { | 3297 | &base_vha->dpc_flags)) { |
2901 | 3298 | ||
@@ -2905,7 +3302,7 @@ qla2x00_do_dpc(void *data) | |||
2905 | if (!(test_and_set_bit(ABORT_ISP_ACTIVE, | 3302 | if (!(test_and_set_bit(ABORT_ISP_ACTIVE, |
2906 | &base_vha->dpc_flags))) { | 3303 | &base_vha->dpc_flags))) { |
2907 | 3304 | ||
2908 | if (qla2x00_abort_isp(base_vha)) { | 3305 | if (ha->isp_ops->abort_isp(base_vha)) { |
2909 | /* failed. retry later */ | 3306 | /* failed. retry later */ |
2910 | set_bit(ISP_ABORT_NEEDED, | 3307 | set_bit(ISP_ABORT_NEEDED, |
2911 | &base_vha->dpc_flags); | 3308 | &base_vha->dpc_flags); |
@@ -3038,11 +3435,31 @@ static void | |||
3038 | qla2x00_sp_free_dma(srb_t *sp) | 3435 | qla2x00_sp_free_dma(srb_t *sp) |
3039 | { | 3436 | { |
3040 | struct scsi_cmnd *cmd = sp->cmd; | 3437 | struct scsi_cmnd *cmd = sp->cmd; |
3438 | struct qla_hw_data *ha = sp->fcport->vha->hw; | ||
3041 | 3439 | ||
3042 | if (sp->flags & SRB_DMA_VALID) { | 3440 | if (sp->flags & SRB_DMA_VALID) { |
3043 | scsi_dma_unmap(cmd); | 3441 | scsi_dma_unmap(cmd); |
3044 | sp->flags &= ~SRB_DMA_VALID; | 3442 | sp->flags &= ~SRB_DMA_VALID; |
3045 | } | 3443 | } |
3444 | |||
3445 | if (sp->flags & SRB_CRC_PROT_DMA_VALID) { | ||
3446 | dma_unmap_sg(&ha->pdev->dev, scsi_prot_sglist(cmd), | ||
3447 | scsi_prot_sg_count(cmd), cmd->sc_data_direction); | ||
3448 | sp->flags &= ~SRB_CRC_PROT_DMA_VALID; | ||
3449 | } | ||
3450 | |||
3451 | if (sp->flags & SRB_CRC_CTX_DSD_VALID) { | ||
3452 | /* List assured to be having elements */ | ||
3453 | qla2x00_clean_dsd_pool(ha, sp); | ||
3454 | sp->flags &= ~SRB_CRC_CTX_DSD_VALID; | ||
3455 | } | ||
3456 | |||
3457 | if (sp->flags & SRB_CRC_CTX_DMA_VALID) { | ||
3458 | dma_pool_free(ha->dl_dma_pool, sp->ctx, | ||
3459 | ((struct crc_context *)sp->ctx)->crc_ctx_dma); | ||
3460 | sp->flags &= ~SRB_CRC_CTX_DMA_VALID; | ||
3461 | } | ||
3462 | |||
3046 | CMD_SP(cmd) = NULL; | 3463 | CMD_SP(cmd) = NULL; |
3047 | } | 3464 | } |
3048 | 3465 | ||
@@ -3053,8 +3470,18 @@ qla2x00_sp_compl(struct qla_hw_data *ha, srb_t *sp) | |||
3053 | 3470 | ||
3054 | qla2x00_sp_free_dma(sp); | 3471 | qla2x00_sp_free_dma(sp); |
3055 | 3472 | ||
3056 | mempool_free(sp, ha->srb_mempool); | 3473 | if (sp->flags & SRB_FCP_CMND_DMA_VALID) { |
3474 | struct ct6_dsd *ctx = sp->ctx; | ||
3475 | dma_pool_free(ha->fcp_cmnd_dma_pool, ctx->fcp_cmnd, | ||
3476 | ctx->fcp_cmnd_dma); | ||
3477 | list_splice(&ctx->dsd_list, &ha->gbl_dsd_list); | ||
3478 | ha->gbl_dsd_inuse -= ctx->dsd_use_cnt; | ||
3479 | ha->gbl_dsd_avail += ctx->dsd_use_cnt; | ||
3480 | mempool_free(sp->ctx, ha->ctx_mempool); | ||
3481 | sp->ctx = NULL; | ||
3482 | } | ||
3057 | 3483 | ||
3484 | mempool_free(sp, ha->srb_mempool); | ||
3058 | cmd->scsi_done(cmd); | 3485 | cmd->scsi_done(cmd); |
3059 | } | 3486 | } |
3060 | 3487 | ||
@@ -3079,6 +3506,9 @@ qla2x00_timer(scsi_qla_host_t *vha) | |||
3079 | struct qla_hw_data *ha = vha->hw; | 3506 | struct qla_hw_data *ha = vha->hw; |
3080 | struct req_que *req; | 3507 | struct req_que *req; |
3081 | 3508 | ||
3509 | if (IS_QLA82XX(ha)) | ||
3510 | qla82xx_watchdog(vha); | ||
3511 | |||
3082 | /* Hardware read to raise pending EEH errors during mailbox waits. */ | 3512 | /* Hardware read to raise pending EEH errors during mailbox waits. */ |
3083 | if (!pci_channel_offline(ha->pdev)) | 3513 | if (!pci_channel_offline(ha->pdev)) |
3084 | pci_read_config_word(ha->pdev, PCI_VENDOR_ID, &w); | 3514 | pci_read_config_word(ha->pdev, PCI_VENDOR_ID, &w); |
@@ -3143,7 +3573,7 @@ qla2x00_timer(scsi_qla_host_t *vha) | |||
3143 | sp = req->outstanding_cmds[index]; | 3573 | sp = req->outstanding_cmds[index]; |
3144 | if (!sp) | 3574 | if (!sp) |
3145 | continue; | 3575 | continue; |
3146 | if (sp->ctx) | 3576 | if (sp->ctx && !IS_PROT_IO(sp)) |
3147 | continue; | 3577 | continue; |
3148 | sfcp = sp->fcport; | 3578 | sfcp = sp->fcport; |
3149 | if (!(sfcp->flags & FCF_FCP2_DEVICE)) | 3579 | if (!(sfcp->flags & FCF_FCP2_DEVICE)) |
@@ -3193,6 +3623,8 @@ qla2x00_timer(scsi_qla_host_t *vha) | |||
3193 | start_dpc || | 3623 | start_dpc || |
3194 | test_bit(RESET_MARKER_NEEDED, &vha->dpc_flags) || | 3624 | test_bit(RESET_MARKER_NEEDED, &vha->dpc_flags) || |
3195 | test_bit(BEACON_BLINK_NEEDED, &vha->dpc_flags) || | 3625 | test_bit(BEACON_BLINK_NEEDED, &vha->dpc_flags) || |
3626 | test_bit(ISP_UNRECOVERABLE, &vha->dpc_flags) || | ||
3627 | test_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags) || | ||
3196 | test_bit(VP_DPC_NEEDED, &vha->dpc_flags) || | 3628 | test_bit(VP_DPC_NEEDED, &vha->dpc_flags) || |
3197 | test_bit(RELOGIN_NEEDED, &vha->dpc_flags))) | 3629 | test_bit(RELOGIN_NEEDED, &vha->dpc_flags))) |
3198 | qla2xxx_wake_dpc(vha); | 3630 | qla2xxx_wake_dpc(vha); |
@@ -3202,7 +3634,7 @@ qla2x00_timer(scsi_qla_host_t *vha) | |||
3202 | 3634 | ||
3203 | /* Firmware interface routines. */ | 3635 | /* Firmware interface routines. */ |
3204 | 3636 | ||
3205 | #define FW_BLOBS 7 | 3637 | #define FW_BLOBS 8 |
3206 | #define FW_ISP21XX 0 | 3638 | #define FW_ISP21XX 0 |
3207 | #define FW_ISP22XX 1 | 3639 | #define FW_ISP22XX 1 |
3208 | #define FW_ISP2300 2 | 3640 | #define FW_ISP2300 2 |
@@ -3210,6 +3642,7 @@ qla2x00_timer(scsi_qla_host_t *vha) | |||
3210 | #define FW_ISP24XX 4 | 3642 | #define FW_ISP24XX 4 |
3211 | #define FW_ISP25XX 5 | 3643 | #define FW_ISP25XX 5 |
3212 | #define FW_ISP81XX 6 | 3644 | #define FW_ISP81XX 6 |
3645 | #define FW_ISP82XX 7 | ||
3213 | 3646 | ||
3214 | #define FW_FILE_ISP21XX "ql2100_fw.bin" | 3647 | #define FW_FILE_ISP21XX "ql2100_fw.bin" |
3215 | #define FW_FILE_ISP22XX "ql2200_fw.bin" | 3648 | #define FW_FILE_ISP22XX "ql2200_fw.bin" |
@@ -3218,6 +3651,7 @@ qla2x00_timer(scsi_qla_host_t *vha) | |||
3218 | #define FW_FILE_ISP24XX "ql2400_fw.bin" | 3651 | #define FW_FILE_ISP24XX "ql2400_fw.bin" |
3219 | #define FW_FILE_ISP25XX "ql2500_fw.bin" | 3652 | #define FW_FILE_ISP25XX "ql2500_fw.bin" |
3220 | #define FW_FILE_ISP81XX "ql8100_fw.bin" | 3653 | #define FW_FILE_ISP81XX "ql8100_fw.bin" |
3654 | #define FW_FILE_ISP82XX "ql8200_fw.bin" | ||
3221 | 3655 | ||
3222 | static DEFINE_MUTEX(qla_fw_lock); | 3656 | static DEFINE_MUTEX(qla_fw_lock); |
3223 | 3657 | ||
@@ -3229,6 +3663,7 @@ static struct fw_blob qla_fw_blobs[FW_BLOBS] = { | |||
3229 | { .name = FW_FILE_ISP24XX, }, | 3663 | { .name = FW_FILE_ISP24XX, }, |
3230 | { .name = FW_FILE_ISP25XX, }, | 3664 | { .name = FW_FILE_ISP25XX, }, |
3231 | { .name = FW_FILE_ISP81XX, }, | 3665 | { .name = FW_FILE_ISP81XX, }, |
3666 | { .name = FW_FILE_ISP82XX, }, | ||
3232 | }; | 3667 | }; |
3233 | 3668 | ||
3234 | struct fw_blob * | 3669 | struct fw_blob * |
@@ -3252,6 +3687,8 @@ qla2x00_request_firmware(scsi_qla_host_t *vha) | |||
3252 | blob = &qla_fw_blobs[FW_ISP25XX]; | 3687 | blob = &qla_fw_blobs[FW_ISP25XX]; |
3253 | } else if (IS_QLA81XX(ha)) { | 3688 | } else if (IS_QLA81XX(ha)) { |
3254 | blob = &qla_fw_blobs[FW_ISP81XX]; | 3689 | blob = &qla_fw_blobs[FW_ISP81XX]; |
3690 | } else if (IS_QLA82XX(ha)) { | ||
3691 | blob = &qla_fw_blobs[FW_ISP82XX]; | ||
3255 | } | 3692 | } |
3256 | 3693 | ||
3257 | mutex_lock(&qla_fw_lock); | 3694 | mutex_lock(&qla_fw_lock); |
@@ -3392,11 +3829,10 @@ qla2xxx_pci_slot_reset(struct pci_dev *pdev) | |||
3392 | msleep(1000); | 3829 | msleep(1000); |
3393 | 3830 | ||
3394 | set_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags); | 3831 | set_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags); |
3395 | if (qla2x00_abort_isp(base_vha) == QLA_SUCCESS) | 3832 | if (ha->isp_ops->abort_isp(base_vha) == QLA_SUCCESS) |
3396 | ret = PCI_ERS_RESULT_RECOVERED; | 3833 | ret = PCI_ERS_RESULT_RECOVERED; |
3397 | clear_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags); | 3834 | clear_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags); |
3398 | 3835 | ||
3399 | pci_cleanup_aer_uncorrect_error_status(pdev); | ||
3400 | 3836 | ||
3401 | DEBUG17(qla_printk(KERN_WARNING, ha, | 3837 | DEBUG17(qla_printk(KERN_WARNING, ha, |
3402 | "slot_reset-return:ret=%x\n", ret)); | 3838 | "slot_reset-return:ret=%x\n", ret)); |
@@ -3420,6 +3856,8 @@ qla2xxx_pci_resume(struct pci_dev *pdev) | |||
3420 | "from slot/link_reset"); | 3856 | "from slot/link_reset"); |
3421 | } | 3857 | } |
3422 | 3858 | ||
3859 | pci_cleanup_aer_uncorrect_error_status(pdev); | ||
3860 | |||
3423 | ha->flags.eeh_busy = 0; | 3861 | ha->flags.eeh_busy = 0; |
3424 | } | 3862 | } |
3425 | 3863 | ||
@@ -3445,6 +3883,7 @@ static struct pci_device_id qla2xxx_pci_tbl[] = { | |||
3445 | { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP5432) }, | 3883 | { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP5432) }, |
3446 | { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2532) }, | 3884 | { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2532) }, |
3447 | { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP8001) }, | 3885 | { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP8001) }, |
3886 | { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP8021) }, | ||
3448 | { 0 }, | 3887 | { 0 }, |
3449 | }; | 3888 | }; |
3450 | MODULE_DEVICE_TABLE(pci, qla2xxx_pci_tbl); | 3889 | MODULE_DEVICE_TABLE(pci, qla2xxx_pci_tbl); |
@@ -3460,6 +3899,10 @@ static struct pci_driver qla2xxx_pci_driver = { | |||
3460 | .err_handler = &qla2xxx_err_handler, | 3899 | .err_handler = &qla2xxx_err_handler, |
3461 | }; | 3900 | }; |
3462 | 3901 | ||
3902 | static struct file_operations apidev_fops = { | ||
3903 | .owner = THIS_MODULE, | ||
3904 | }; | ||
3905 | |||
3463 | /** | 3906 | /** |
3464 | * qla2x00_module_init - Module initialization. | 3907 | * qla2x00_module_init - Module initialization. |
3465 | **/ | 3908 | **/ |
@@ -3488,6 +3931,13 @@ qla2x00_module_init(void) | |||
3488 | kmem_cache_destroy(srb_cachep); | 3931 | kmem_cache_destroy(srb_cachep); |
3489 | return -ENODEV; | 3932 | return -ENODEV; |
3490 | } | 3933 | } |
3934 | |||
3935 | apidev_major = register_chrdev(0, QLA2XXX_APIDEV, &apidev_fops); | ||
3936 | if (apidev_major < 0) { | ||
3937 | printk(KERN_WARNING "qla2xxx: Unable to register char device " | ||
3938 | "%s\n", QLA2XXX_APIDEV); | ||
3939 | } | ||
3940 | |||
3491 | qla2xxx_transport_vport_template = | 3941 | qla2xxx_transport_vport_template = |
3492 | fc_attach_transport(&qla2xxx_transport_vport_functions); | 3942 | fc_attach_transport(&qla2xxx_transport_vport_functions); |
3493 | if (!qla2xxx_transport_vport_template) { | 3943 | if (!qla2xxx_transport_vport_template) { |
@@ -3513,9 +3963,12 @@ qla2x00_module_init(void) | |||
3513 | static void __exit | 3963 | static void __exit |
3514 | qla2x00_module_exit(void) | 3964 | qla2x00_module_exit(void) |
3515 | { | 3965 | { |
3966 | unregister_chrdev(apidev_major, QLA2XXX_APIDEV); | ||
3516 | pci_unregister_driver(&qla2xxx_pci_driver); | 3967 | pci_unregister_driver(&qla2xxx_pci_driver); |
3517 | qla2x00_release_firmware(); | 3968 | qla2x00_release_firmware(); |
3518 | kmem_cache_destroy(srb_cachep); | 3969 | kmem_cache_destroy(srb_cachep); |
3970 | if (ctx_cachep) | ||
3971 | kmem_cache_destroy(ctx_cachep); | ||
3519 | fc_release_transport(qla2xxx_transport_template); | 3972 | fc_release_transport(qla2xxx_transport_template); |
3520 | fc_release_transport(qla2xxx_transport_vport_template); | 3973 | fc_release_transport(qla2xxx_transport_vport_template); |
3521 | } | 3974 | } |
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index 8b3de4e54c28..de92504d7585 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c | |||
@@ -423,9 +423,6 @@ qla2x00_set_nvram_protection(struct qla_hw_data *ha, int stat) | |||
423 | /* Flash Manipulation Routines */ | 423 | /* Flash Manipulation Routines */ |
424 | /*****************************************************************************/ | 424 | /*****************************************************************************/ |
425 | 425 | ||
426 | #define OPTROM_BURST_SIZE 0x1000 | ||
427 | #define OPTROM_BURST_DWORDS (OPTROM_BURST_SIZE / 4) | ||
428 | |||
429 | static inline uint32_t | 426 | static inline uint32_t |
430 | flash_conf_addr(struct qla_hw_data *ha, uint32_t faddr) | 427 | flash_conf_addr(struct qla_hw_data *ha, uint32_t faddr) |
431 | { | 428 | { |
@@ -565,6 +562,10 @@ qla2xxx_find_flt_start(scsi_qla_host_t *vha, uint32_t *start) | |||
565 | *start = FA_FLASH_LAYOUT_ADDR; | 562 | *start = FA_FLASH_LAYOUT_ADDR; |
566 | else if (IS_QLA81XX(ha)) | 563 | else if (IS_QLA81XX(ha)) |
567 | *start = FA_FLASH_LAYOUT_ADDR_81; | 564 | *start = FA_FLASH_LAYOUT_ADDR_81; |
565 | else if (IS_QLA82XX(ha)) { | ||
566 | *start = FA_FLASH_LAYOUT_ADDR_82; | ||
567 | goto end; | ||
568 | } | ||
568 | /* Begin with first PCI expansion ROM header. */ | 569 | /* Begin with first PCI expansion ROM header. */ |
569 | buf = (uint8_t *)req->ring; | 570 | buf = (uint8_t *)req->ring; |
570 | dcode = (uint32_t *)req->ring; | 571 | dcode = (uint32_t *)req->ring; |
@@ -648,6 +649,12 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr) | |||
648 | const uint32_t def_npiv_conf1[] = | 649 | const uint32_t def_npiv_conf1[] = |
649 | { FA_NPIV_CONF1_ADDR_24, FA_NPIV_CONF1_ADDR, | 650 | { FA_NPIV_CONF1_ADDR_24, FA_NPIV_CONF1_ADDR, |
650 | FA_NPIV_CONF1_ADDR_81 }; | 651 | FA_NPIV_CONF1_ADDR_81 }; |
652 | const uint32_t fcp_prio_cfg0[] = | ||
653 | { FA_FCP_PRIO0_ADDR, FA_FCP_PRIO0_ADDR_25, | ||
654 | 0 }; | ||
655 | const uint32_t fcp_prio_cfg1[] = | ||
656 | { FA_FCP_PRIO1_ADDR, FA_FCP_PRIO1_ADDR_25, | ||
657 | 0 }; | ||
651 | uint32_t def; | 658 | uint32_t def; |
652 | uint16_t *wptr; | 659 | uint16_t *wptr; |
653 | uint16_t cnt, chksum; | 660 | uint16_t cnt, chksum; |
@@ -703,10 +710,14 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr) | |||
703 | break; | 710 | break; |
704 | case FLT_REG_VPD_0: | 711 | case FLT_REG_VPD_0: |
705 | ha->flt_region_vpd_nvram = start; | 712 | ha->flt_region_vpd_nvram = start; |
713 | if (IS_QLA82XX(ha)) | ||
714 | break; | ||
706 | if (ha->flags.port0) | 715 | if (ha->flags.port0) |
707 | ha->flt_region_vpd = start; | 716 | ha->flt_region_vpd = start; |
708 | break; | 717 | break; |
709 | case FLT_REG_VPD_1: | 718 | case FLT_REG_VPD_1: |
719 | if (IS_QLA82XX(ha)) | ||
720 | break; | ||
710 | if (!ha->flags.port0) | 721 | if (!ha->flags.port0) |
711 | ha->flt_region_vpd = start; | 722 | ha->flt_region_vpd = start; |
712 | break; | 723 | break; |
@@ -732,6 +743,29 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr) | |||
732 | case FLT_REG_GOLD_FW: | 743 | case FLT_REG_GOLD_FW: |
733 | ha->flt_region_gold_fw = start; | 744 | ha->flt_region_gold_fw = start; |
734 | break; | 745 | break; |
746 | case FLT_REG_FCP_PRIO_0: | ||
747 | if (ha->flags.port0) | ||
748 | ha->flt_region_fcp_prio = start; | ||
749 | break; | ||
750 | case FLT_REG_FCP_PRIO_1: | ||
751 | if (!ha->flags.port0) | ||
752 | ha->flt_region_fcp_prio = start; | ||
753 | break; | ||
754 | case FLT_REG_BOOT_CODE_82XX: | ||
755 | ha->flt_region_boot = start; | ||
756 | break; | ||
757 | case FLT_REG_FW_82XX: | ||
758 | ha->flt_region_fw = start; | ||
759 | break; | ||
760 | case FLT_REG_GOLD_FW_82XX: | ||
761 | ha->flt_region_gold_fw = start; | ||
762 | break; | ||
763 | case FLT_REG_BOOTLOAD_82XX: | ||
764 | ha->flt_region_bootload = start; | ||
765 | break; | ||
766 | case FLT_REG_VPD_82XX: | ||
767 | ha->flt_region_vpd = start; | ||
768 | break; | ||
735 | } | 769 | } |
736 | } | 770 | } |
737 | goto done; | 771 | goto done; |
@@ -750,12 +784,14 @@ no_flash_data: | |||
750 | ha->flt_region_boot = def_boot[def]; | 784 | ha->flt_region_boot = def_boot[def]; |
751 | ha->flt_region_vpd_nvram = def_vpd_nvram[def]; | 785 | ha->flt_region_vpd_nvram = def_vpd_nvram[def]; |
752 | ha->flt_region_vpd = ha->flags.port0 ? | 786 | ha->flt_region_vpd = ha->flags.port0 ? |
753 | def_vpd0[def]: def_vpd1[def]; | 787 | def_vpd0[def] : def_vpd1[def]; |
754 | ha->flt_region_nvram = ha->flags.port0 ? | 788 | ha->flt_region_nvram = ha->flags.port0 ? |
755 | def_nvram0[def]: def_nvram1[def]; | 789 | def_nvram0[def] : def_nvram1[def]; |
756 | ha->flt_region_fdt = def_fdt[def]; | 790 | ha->flt_region_fdt = def_fdt[def]; |
757 | ha->flt_region_npiv_conf = ha->flags.port0 ? | 791 | ha->flt_region_npiv_conf = ha->flags.port0 ? |
758 | def_npiv_conf0[def]: def_npiv_conf1[def]; | 792 | def_npiv_conf0[def] : def_npiv_conf1[def]; |
793 | ha->flt_region_fcp_prio = ha->flags.port0 ? | ||
794 | fcp_prio_cfg0[def] : fcp_prio_cfg1[def]; | ||
759 | done: | 795 | done: |
760 | DEBUG2(qla_printk(KERN_DEBUG, ha, "FLT[%s]: boot=0x%x fw=0x%x " | 796 | DEBUG2(qla_printk(KERN_DEBUG, ha, "FLT[%s]: boot=0x%x fw=0x%x " |
761 | "vpd_nvram=0x%x vpd=0x%x nvram=0x%x fdt=0x%x flt=0x%x " | 797 | "vpd_nvram=0x%x vpd=0x%x nvram=0x%x fdt=0x%x flt=0x%x " |
@@ -775,7 +811,7 @@ qla2xxx_get_fdt_info(scsi_qla_host_t *vha) | |||
775 | uint16_t *wptr; | 811 | uint16_t *wptr; |
776 | struct qla_fdt_layout *fdt; | 812 | struct qla_fdt_layout *fdt; |
777 | uint8_t man_id, flash_id; | 813 | uint8_t man_id, flash_id; |
778 | uint16_t mid, fid; | 814 | uint16_t mid = 0, fid = 0; |
779 | struct qla_hw_data *ha = vha->hw; | 815 | struct qla_hw_data *ha = vha->hw; |
780 | struct req_que *req = ha->req_q_map[0]; | 816 | struct req_que *req = ha->req_q_map[0]; |
781 | 817 | ||
@@ -816,6 +852,10 @@ qla2xxx_get_fdt_info(scsi_qla_host_t *vha) | |||
816 | goto done; | 852 | goto done; |
817 | no_flash_data: | 853 | no_flash_data: |
818 | loc = locations[0]; | 854 | loc = locations[0]; |
855 | if (IS_QLA82XX(ha)) { | ||
856 | ha->fdt_block_size = FLASH_BLK_SIZE_64K; | ||
857 | goto done; | ||
858 | } | ||
819 | qla24xx_get_flash_manufacturer(ha, &man_id, &flash_id); | 859 | qla24xx_get_flash_manufacturer(ha, &man_id, &flash_id); |
820 | mid = man_id; | 860 | mid = man_id; |
821 | fid = flash_id; | 861 | fid = flash_id; |
@@ -853,6 +893,31 @@ done: | |||
853 | ha->fdt_block_size)); | 893 | ha->fdt_block_size)); |
854 | } | 894 | } |
855 | 895 | ||
896 | static void | ||
897 | qla2xxx_get_idc_param(scsi_qla_host_t *vha) | ||
898 | { | ||
899 | #define QLA82XX_IDC_PARAM_ADDR 0x003e885c | ||
900 | uint32_t *wptr; | ||
901 | struct qla_hw_data *ha = vha->hw; | ||
902 | struct req_que *req = ha->req_q_map[0]; | ||
903 | |||
904 | if (!IS_QLA82XX(ha)) | ||
905 | return; | ||
906 | |||
907 | wptr = (uint32_t *)req->ring; | ||
908 | ha->isp_ops->read_optrom(vha, (uint8_t *)req->ring, | ||
909 | QLA82XX_IDC_PARAM_ADDR , 8); | ||
910 | |||
911 | if (*wptr == __constant_cpu_to_le32(0xffffffff)) { | ||
912 | ha->nx_dev_init_timeout = QLA82XX_ROM_DEV_INIT_TIMEOUT; | ||
913 | ha->nx_reset_timeout = QLA82XX_ROM_DRV_RESET_ACK_TIMEOUT; | ||
914 | } else { | ||
915 | ha->nx_dev_init_timeout = le32_to_cpu(*wptr++); | ||
916 | ha->nx_reset_timeout = le32_to_cpu(*wptr); | ||
917 | } | ||
918 | return; | ||
919 | } | ||
920 | |||
856 | int | 921 | int |
857 | qla2xxx_get_flash_info(scsi_qla_host_t *vha) | 922 | qla2xxx_get_flash_info(scsi_qla_host_t *vha) |
858 | { | 923 | { |
@@ -860,7 +925,7 @@ qla2xxx_get_flash_info(scsi_qla_host_t *vha) | |||
860 | uint32_t flt_addr; | 925 | uint32_t flt_addr; |
861 | struct qla_hw_data *ha = vha->hw; | 926 | struct qla_hw_data *ha = vha->hw; |
862 | 927 | ||
863 | if (!IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha) && !IS_QLA81XX(ha)) | 928 | if (!IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha) && !IS_QLA8XXX_TYPE(ha)) |
864 | return QLA_SUCCESS; | 929 | return QLA_SUCCESS; |
865 | 930 | ||
866 | ret = qla2xxx_find_flt_start(vha, &flt_addr); | 931 | ret = qla2xxx_find_flt_start(vha, &flt_addr); |
@@ -869,6 +934,7 @@ qla2xxx_get_flash_info(scsi_qla_host_t *vha) | |||
869 | 934 | ||
870 | qla2xxx_get_flt_info(vha, flt_addr); | 935 | qla2xxx_get_flt_info(vha, flt_addr); |
871 | qla2xxx_get_fdt_info(vha); | 936 | qla2xxx_get_fdt_info(vha); |
937 | qla2xxx_get_idc_param(vha); | ||
872 | 938 | ||
873 | return QLA_SUCCESS; | 939 | return QLA_SUCCESS; |
874 | } | 940 | } |
@@ -885,7 +951,7 @@ qla2xxx_flash_npiv_conf(scsi_qla_host_t *vha) | |||
885 | struct qla_npiv_entry *entry; | 951 | struct qla_npiv_entry *entry; |
886 | struct qla_hw_data *ha = vha->hw; | 952 | struct qla_hw_data *ha = vha->hw; |
887 | 953 | ||
888 | if (!IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha) && !IS_QLA81XX(ha)) | 954 | if (!IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha) && !IS_QLA8XXX_TYPE(ha)) |
889 | return; | 955 | return; |
890 | 956 | ||
891 | ha->isp_ops->read_optrom(vha, (uint8_t *)&hdr, | 957 | ha->isp_ops->read_optrom(vha, (uint8_t *)&hdr, |
@@ -1178,6 +1244,9 @@ qla24xx_read_nvram_data(scsi_qla_host_t *vha, uint8_t *buf, uint32_t naddr, | |||
1178 | uint32_t *dwptr; | 1244 | uint32_t *dwptr; |
1179 | struct qla_hw_data *ha = vha->hw; | 1245 | struct qla_hw_data *ha = vha->hw; |
1180 | 1246 | ||
1247 | if (IS_QLA82XX(ha)) | ||
1248 | return buf; | ||
1249 | |||
1181 | /* Dword reads to flash. */ | 1250 | /* Dword reads to flash. */ |
1182 | dwptr = (uint32_t *)buf; | 1251 | dwptr = (uint32_t *)buf; |
1183 | for (i = 0; i < bytes >> 2; i++, naddr++) | 1252 | for (i = 0; i < bytes >> 2; i++, naddr++) |
@@ -1233,6 +1302,9 @@ qla24xx_write_nvram_data(scsi_qla_host_t *vha, uint8_t *buf, uint32_t naddr, | |||
1233 | 1302 | ||
1234 | ret = QLA_SUCCESS; | 1303 | ret = QLA_SUCCESS; |
1235 | 1304 | ||
1305 | if (IS_QLA82XX(ha)) | ||
1306 | return ret; | ||
1307 | |||
1236 | /* Enable flash write. */ | 1308 | /* Enable flash write. */ |
1237 | WRT_REG_DWORD(®->ctrl_status, | 1309 | WRT_REG_DWORD(®->ctrl_status, |
1238 | RD_REG_DWORD(®->ctrl_status) | CSRX_FLASH_ENABLE); | 1310 | RD_REG_DWORD(®->ctrl_status) | CSRX_FLASH_ENABLE); |
@@ -1344,6 +1416,9 @@ qla2x00_beacon_blink(struct scsi_qla_host *vha) | |||
1344 | struct qla_hw_data *ha = vha->hw; | 1416 | struct qla_hw_data *ha = vha->hw; |
1345 | struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; | 1417 | struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; |
1346 | 1418 | ||
1419 | if (IS_QLA82XX(ha)) | ||
1420 | return; | ||
1421 | |||
1347 | spin_lock_irqsave(&ha->hardware_lock, flags); | 1422 | spin_lock_irqsave(&ha->hardware_lock, flags); |
1348 | 1423 | ||
1349 | /* Save the Original GPIOE. */ | 1424 | /* Save the Original GPIOE. */ |
@@ -1525,6 +1600,9 @@ qla24xx_beacon_on(struct scsi_qla_host *vha) | |||
1525 | struct qla_hw_data *ha = vha->hw; | 1600 | struct qla_hw_data *ha = vha->hw; |
1526 | struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; | 1601 | struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; |
1527 | 1602 | ||
1603 | if (IS_QLA82XX(ha)) | ||
1604 | return QLA_SUCCESS; | ||
1605 | |||
1528 | if (ha->beacon_blink_led == 0) { | 1606 | if (ha->beacon_blink_led == 0) { |
1529 | /* Enable firmware for update */ | 1607 | /* Enable firmware for update */ |
1530 | ha->fw_options[1] |= ADD_FO1_DISABLE_GPIO_LED_CTRL; | 1608 | ha->fw_options[1] |= ADD_FO1_DISABLE_GPIO_LED_CTRL; |
@@ -1567,6 +1645,9 @@ qla24xx_beacon_off(struct scsi_qla_host *vha) | |||
1567 | struct qla_hw_data *ha = vha->hw; | 1645 | struct qla_hw_data *ha = vha->hw; |
1568 | struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; | 1646 | struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; |
1569 | 1647 | ||
1648 | if (IS_QLA82XX(ha)) | ||
1649 | return QLA_SUCCESS; | ||
1650 | |||
1570 | ha->beacon_blink_led = 0; | 1651 | ha->beacon_blink_led = 0; |
1571 | ha->beacon_color_state = QLA_LED_ALL_ON; | 1652 | ha->beacon_color_state = QLA_LED_ALL_ON; |
1572 | 1653 | ||
@@ -2576,6 +2657,9 @@ qla24xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf) | |||
2576 | int i; | 2657 | int i; |
2577 | struct qla_hw_data *ha = vha->hw; | 2658 | struct qla_hw_data *ha = vha->hw; |
2578 | 2659 | ||
2660 | if (IS_QLA82XX(ha)) | ||
2661 | return ret; | ||
2662 | |||
2579 | if (!mbuf) | 2663 | if (!mbuf) |
2580 | return QLA_FUNCTION_FAILED; | 2664 | return QLA_FUNCTION_FAILED; |
2581 | 2665 | ||
@@ -2722,3 +2806,50 @@ qla2xxx_get_vpd_field(scsi_qla_host_t *vha, char *key, char *str, size_t size) | |||
2722 | 2806 | ||
2723 | return 0; | 2807 | return 0; |
2724 | } | 2808 | } |
2809 | |||
2810 | int | ||
2811 | qla24xx_read_fcp_prio_cfg(scsi_qla_host_t *vha) | ||
2812 | { | ||
2813 | int len, max_len; | ||
2814 | uint32_t fcp_prio_addr; | ||
2815 | struct qla_hw_data *ha = vha->hw; | ||
2816 | |||
2817 | if (!ha->fcp_prio_cfg) { | ||
2818 | ha->fcp_prio_cfg = vmalloc(FCP_PRIO_CFG_SIZE); | ||
2819 | if (!ha->fcp_prio_cfg) { | ||
2820 | qla_printk(KERN_WARNING, ha, | ||
2821 | "Unable to allocate memory for fcp priority data " | ||
2822 | "(%x).\n", FCP_PRIO_CFG_SIZE); | ||
2823 | return QLA_FUNCTION_FAILED; | ||
2824 | } | ||
2825 | } | ||
2826 | memset(ha->fcp_prio_cfg, 0, FCP_PRIO_CFG_SIZE); | ||
2827 | |||
2828 | fcp_prio_addr = ha->flt_region_fcp_prio; | ||
2829 | |||
2830 | /* first read the fcp priority data header from flash */ | ||
2831 | ha->isp_ops->read_optrom(vha, (uint8_t *)ha->fcp_prio_cfg, | ||
2832 | fcp_prio_addr << 2, FCP_PRIO_CFG_HDR_SIZE); | ||
2833 | |||
2834 | if (!qla24xx_fcp_prio_cfg_valid(ha->fcp_prio_cfg, 0)) | ||
2835 | goto fail; | ||
2836 | |||
2837 | /* read remaining FCP CMD config data from flash */ | ||
2838 | fcp_prio_addr += (FCP_PRIO_CFG_HDR_SIZE >> 2); | ||
2839 | len = ha->fcp_prio_cfg->num_entries * FCP_PRIO_CFG_ENTRY_SIZE; | ||
2840 | max_len = FCP_PRIO_CFG_SIZE - FCP_PRIO_CFG_HDR_SIZE; | ||
2841 | |||
2842 | ha->isp_ops->read_optrom(vha, (uint8_t *)&ha->fcp_prio_cfg->entry[0], | ||
2843 | fcp_prio_addr << 2, (len < max_len ? len : max_len)); | ||
2844 | |||
2845 | /* revalidate the entire FCP priority config data, including entries */ | ||
2846 | if (!qla24xx_fcp_prio_cfg_valid(ha->fcp_prio_cfg, 1)) | ||
2847 | goto fail; | ||
2848 | |||
2849 | ha->flags.fcp_prio_enabled = 1; | ||
2850 | return QLA_SUCCESS; | ||
2851 | fail: | ||
2852 | vfree(ha->fcp_prio_cfg); | ||
2853 | ha->fcp_prio_cfg = NULL; | ||
2854 | return QLA_FUNCTION_FAILED; | ||
2855 | } | ||