[SCSI] Merge scsi-misc-2.6 into scsi-rc-fixes-2.6
[safe/jmp/linux-2.6] / drivers / scsi / qla2xxx / qla_sup.c
index 2a9b3f8..de92504 100644 (file)
@@ -7,6 +7,7 @@
 #include "qla_def.h"
 
 #include <linux/delay.h>
+#include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <asm/uaccess.h>
 
@@ -422,9 +423,6 @@ qla2x00_set_nvram_protection(struct qla_hw_data *ha, int stat)
 /* Flash Manipulation Routines                                               */
 /*****************************************************************************/
 
-#define OPTROM_BURST_SIZE      0x1000
-#define OPTROM_BURST_DWORDS    (OPTROM_BURST_SIZE / 4)
-
 static inline uint32_t
 flash_conf_addr(struct qla_hw_data *ha, uint32_t faddr)
 {
@@ -564,6 +562,10 @@ qla2xxx_find_flt_start(scsi_qla_host_t *vha, uint32_t *start)
                *start = FA_FLASH_LAYOUT_ADDR;
        else if (IS_QLA81XX(ha))
                *start = FA_FLASH_LAYOUT_ADDR_81;
+       else if (IS_QLA82XX(ha)) {
+               *start = FA_FLASH_LAYOUT_ADDR_82;
+               goto end;
+       }
        /* Begin with first PCI expansion ROM header. */
        buf = (uint8_t *)req->ring;
        dcode = (uint32_t *)req->ring;
@@ -647,6 +649,12 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr)
        const uint32_t def_npiv_conf1[] =
                { FA_NPIV_CONF1_ADDR_24, FA_NPIV_CONF1_ADDR,
                        FA_NPIV_CONF1_ADDR_81 };
+       const uint32_t fcp_prio_cfg0[] =
+               { FA_FCP_PRIO0_ADDR, FA_FCP_PRIO0_ADDR_25,
+                       0 };
+       const uint32_t fcp_prio_cfg1[] =
+               { FA_FCP_PRIO1_ADDR, FA_FCP_PRIO1_ADDR_25,
+                       0 };
        uint32_t def;
        uint16_t *wptr;
        uint16_t cnt, chksum;
@@ -702,32 +710,62 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr)
                        break;
                case FLT_REG_VPD_0:
                        ha->flt_region_vpd_nvram = start;
-                       if (!(PCI_FUNC(ha->pdev->devfn) & 1))
+                       if (IS_QLA82XX(ha))
+                               break;
+                       if (ha->flags.port0)
                                ha->flt_region_vpd = start;
                        break;
                case FLT_REG_VPD_1:
-                       if (PCI_FUNC(ha->pdev->devfn) & 1)
+                       if (IS_QLA82XX(ha))
+                               break;
+                       if (!ha->flags.port0)
                                ha->flt_region_vpd = start;
                        break;
                case FLT_REG_NVRAM_0:
-                       if (!(PCI_FUNC(ha->pdev->devfn) & 1))
+                       if (ha->flags.port0)
                                ha->flt_region_nvram = start;
                        break;
                case FLT_REG_NVRAM_1:
-                       if (PCI_FUNC(ha->pdev->devfn) & 1)
+                       if (!ha->flags.port0)
                                ha->flt_region_nvram = start;
                        break;
                case FLT_REG_FDT:
                        ha->flt_region_fdt = start;
                        break;
                case FLT_REG_NPIV_CONF_0:
-                       if (!(PCI_FUNC(ha->pdev->devfn) & 1))
+                       if (ha->flags.port0)
                                ha->flt_region_npiv_conf = start;
                        break;
                case FLT_REG_NPIV_CONF_1:
-                       if (PCI_FUNC(ha->pdev->devfn) & 1)
+                       if (!ha->flags.port0)
                                ha->flt_region_npiv_conf = start;
                        break;
+               case FLT_REG_GOLD_FW:
+                       ha->flt_region_gold_fw = start;
+                       break;
+               case FLT_REG_FCP_PRIO_0:
+                       if (ha->flags.port0)
+                               ha->flt_region_fcp_prio = start;
+                       break;
+               case FLT_REG_FCP_PRIO_1:
+                       if (!ha->flags.port0)
+                               ha->flt_region_fcp_prio = start;
+                       break;
+               case FLT_REG_BOOT_CODE_82XX:
+                       ha->flt_region_boot = start;
+                       break;
+               case FLT_REG_FW_82XX:
+                       ha->flt_region_fw = start;
+                       break;
+               case FLT_REG_GOLD_FW_82XX:
+                       ha->flt_region_gold_fw = start;
+                       break;
+               case FLT_REG_BOOTLOAD_82XX:
+                       ha->flt_region_bootload = start;
+                       break;
+               case FLT_REG_VPD_82XX:
+                       ha->flt_region_vpd = start;
+                       break;
                }
        }
        goto done;
@@ -745,13 +783,15 @@ no_flash_data:
        ha->flt_region_fw = def_fw[def];
        ha->flt_region_boot = def_boot[def];
        ha->flt_region_vpd_nvram = def_vpd_nvram[def];
-       ha->flt_region_vpd = !(PCI_FUNC(ha->pdev->devfn) & 1) ?
-           def_vpd0[def]: def_vpd1[def];
-       ha->flt_region_nvram = !(PCI_FUNC(ha->pdev->devfn) & 1) ?
-           def_nvram0[def]: def_nvram1[def];
+       ha->flt_region_vpd = ha->flags.port0 ?
+           def_vpd0[def] : def_vpd1[def];
+       ha->flt_region_nvram = ha->flags.port0 ?
+           def_nvram0[def] : def_nvram1[def];
        ha->flt_region_fdt = def_fdt[def];
-       ha->flt_region_npiv_conf = !(PCI_FUNC(ha->pdev->devfn) & 1) ?
-           def_npiv_conf0[def]: def_npiv_conf1[def];
+       ha->flt_region_npiv_conf = ha->flags.port0 ?
+           def_npiv_conf0[def] : def_npiv_conf1[def];
+       ha->flt_region_fcp_prio = ha->flags.port0 ?
+           fcp_prio_cfg0[def] : fcp_prio_cfg1[def];
 done:
        DEBUG2(qla_printk(KERN_DEBUG, ha, "FLT[%s]: boot=0x%x fw=0x%x "
            "vpd_nvram=0x%x vpd=0x%x nvram=0x%x fdt=0x%x flt=0x%x "
@@ -771,7 +811,7 @@ qla2xxx_get_fdt_info(scsi_qla_host_t *vha)
        uint16_t *wptr;
        struct qla_fdt_layout *fdt;
        uint8_t man_id, flash_id;
-       uint16_t mid, fid;
+       uint16_t mid = 0, fid = 0;
        struct qla_hw_data *ha = vha->hw;
        struct req_que *req = ha->req_q_map[0];
 
@@ -812,6 +852,10 @@ qla2xxx_get_fdt_info(scsi_qla_host_t *vha)
        goto done;
 no_flash_data:
        loc = locations[0];
+       if (IS_QLA82XX(ha)) {
+               ha->fdt_block_size = FLASH_BLK_SIZE_64K;
+               goto done;
+       }
        qla24xx_get_flash_manufacturer(ha, &man_id, &flash_id);
        mid = man_id;
        fid = flash_id;
@@ -849,6 +893,31 @@ done:
            ha->fdt_block_size));
 }
 
+static void
+qla2xxx_get_idc_param(scsi_qla_host_t *vha)
+{
+#define QLA82XX_IDC_PARAM_ADDR       0x003e885c
+       uint32_t *wptr;
+       struct qla_hw_data *ha = vha->hw;
+       struct req_que *req = ha->req_q_map[0];
+
+       if (!IS_QLA82XX(ha))
+               return;
+
+       wptr = (uint32_t *)req->ring;
+       ha->isp_ops->read_optrom(vha, (uint8_t *)req->ring,
+               QLA82XX_IDC_PARAM_ADDR , 8);
+
+       if (*wptr == __constant_cpu_to_le32(0xffffffff)) {
+               ha->nx_dev_init_timeout = QLA82XX_ROM_DEV_INIT_TIMEOUT;
+               ha->nx_reset_timeout = QLA82XX_ROM_DRV_RESET_ACK_TIMEOUT;
+       } else {
+               ha->nx_dev_init_timeout = le32_to_cpu(*wptr++);
+               ha->nx_reset_timeout = le32_to_cpu(*wptr);
+       }
+       return;
+}
+
 int
 qla2xxx_get_flash_info(scsi_qla_host_t *vha)
 {
@@ -856,7 +925,7 @@ qla2xxx_get_flash_info(scsi_qla_host_t *vha)
        uint32_t flt_addr;
        struct qla_hw_data *ha = vha->hw;
 
-       if (!IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha) && !IS_QLA81XX(ha))
+       if (!IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha) && !IS_QLA8XXX_TYPE(ha))
                return QLA_SUCCESS;
 
        ret = qla2xxx_find_flt_start(vha, &flt_addr);
@@ -865,6 +934,7 @@ qla2xxx_get_flash_info(scsi_qla_host_t *vha)
 
        qla2xxx_get_flt_info(vha, flt_addr);
        qla2xxx_get_fdt_info(vha);
+       qla2xxx_get_idc_param(vha);
 
        return QLA_SUCCESS;
 }
@@ -881,7 +951,7 @@ qla2xxx_flash_npiv_conf(scsi_qla_host_t *vha)
        struct qla_npiv_entry *entry;
        struct qla_hw_data *ha = vha->hw;
 
-       if (!IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha) && !IS_QLA81XX(ha))
+       if (!IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha) && !IS_QLA8XXX_TYPE(ha))
                return;
 
        ha->isp_ops->read_optrom(vha, (uint8_t *)&hdr,
@@ -920,12 +990,13 @@ qla2xxx_flash_npiv_conf(scsi_qla_host_t *vha)
 
        entry = data + sizeof(struct qla_npiv_header);
        cnt = le16_to_cpu(hdr.entries);
-       ha->flex_port_count = cnt;
        for (i = 0; cnt; cnt--, entry++, i++) {
                uint16_t flags;
                struct fc_vport_identifiers vid;
                struct fc_vport *vport;
 
+               memcpy(&ha->npiv_info[i], entry, sizeof(struct qla_npiv_entry));
+
                flags = le16_to_cpu(entry->flags);
                if (flags == 0xffff)
                        continue;
@@ -939,11 +1010,11 @@ qla2xxx_flash_npiv_conf(scsi_qla_host_t *vha)
                vid.port_name = wwn_to_u64(entry->port_name);
                vid.node_name = wwn_to_u64(entry->node_name);
 
-               memcpy(&ha->npiv_info[i], entry, sizeof(struct qla_npiv_entry));
-
-               DEBUG2(qla_printk(KERN_DEBUG, ha, "NPIV[%02x]: wwpn=%llx "
+               DEBUG2(qla_printk(KERN_INFO, ha, "NPIV[%02x]: wwpn=%llx "
                        "wwnn=%llx vf_id=0x%x Q_qos=0x%x F_qos=0x%x.\n", cnt,
-                       vid.port_name, vid.node_name, le16_to_cpu(entry->vf_id),
+                       (unsigned long long)vid.port_name,
+                       (unsigned long long)vid.node_name,
+                       le16_to_cpu(entry->vf_id),
                        entry->q_qos, entry->f_qos));
 
                if (i < QLA_PRECONFIG_VPORTS) {
@@ -952,12 +1023,12 @@ qla2xxx_flash_npiv_conf(scsi_qla_host_t *vha)
                                qla_printk(KERN_INFO, ha,
                                "NPIV-Config: Failed to create vport [%02x]: "
                                "wwpn=%llx wwnn=%llx.\n", cnt,
-                               vid.port_name, vid.node_name);
+                               (unsigned long long)vid.port_name,
+                               (unsigned long long)vid.node_name);
                }
        }
 done:
        kfree(data);
-       ha->npiv_info = NULL;
 }
 
 static int
@@ -1173,6 +1244,9 @@ qla24xx_read_nvram_data(scsi_qla_host_t *vha, uint8_t *buf, uint32_t naddr,
        uint32_t *dwptr;
        struct qla_hw_data *ha = vha->hw;
 
+       if (IS_QLA82XX(ha))
+               return  buf;
+
        /* Dword reads to flash. */
        dwptr = (uint32_t *)buf;
        for (i = 0; i < bytes >> 2; i++, naddr++)
@@ -1228,6 +1302,9 @@ qla24xx_write_nvram_data(scsi_qla_host_t *vha, uint8_t *buf, uint32_t naddr,
 
        ret = QLA_SUCCESS;
 
+       if (IS_QLA82XX(ha))
+               return ret;
+
        /* Enable flash write. */
        WRT_REG_DWORD(&reg->ctrl_status,
            RD_REG_DWORD(&reg->ctrl_status) | CSRX_FLASH_ENABLE);
@@ -1339,6 +1416,9 @@ qla2x00_beacon_blink(struct scsi_qla_host *vha)
        struct qla_hw_data *ha = vha->hw;
        struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
 
+       if (IS_QLA82XX(ha))
+               return;
+
        spin_lock_irqsave(&ha->hardware_lock, flags);
 
        /* Save the Original GPIOE. */
@@ -1520,6 +1600,9 @@ qla24xx_beacon_on(struct scsi_qla_host *vha)
        struct qla_hw_data *ha = vha->hw;
        struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
 
+       if (IS_QLA82XX(ha))
+               return QLA_SUCCESS;
+
        if (ha->beacon_blink_led == 0) {
                /* Enable firmware for update */
                ha->fw_options[1] |= ADD_FO1_DISABLE_GPIO_LED_CTRL;
@@ -1562,6 +1645,9 @@ qla24xx_beacon_off(struct scsi_qla_host *vha)
        struct qla_hw_data *ha = vha->hw;
        struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
 
+       if (IS_QLA82XX(ha))
+               return QLA_SUCCESS;
+
        ha->beacon_blink_led = 0;
        ha->beacon_color_state = QLA_LED_ALL_ON;
 
@@ -2288,11 +2374,14 @@ qla25xx_read_optrom_data(struct scsi_qla_host *vha, uint8_t *buf,
        uint32_t faddr, left, burst;
        struct qla_hw_data *ha = vha->hw;
 
+       if (IS_QLA25XX(ha) || IS_QLA81XX(ha))
+               goto try_fast;
        if (offset & 0xfff)
                goto slow_read;
        if (length < OPTROM_BURST_SIZE)
                goto slow_read;
 
+try_fast:
        optrom = dma_alloc_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE,
            &optrom_dma, GFP_KERNEL);
        if (!optrom) {
@@ -2568,6 +2657,9 @@ qla24xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf)
        int i;
        struct qla_hw_data *ha = vha->hw;
 
+       if (IS_QLA82XX(ha))
+               return ret;
+
        if (!mbuf)
                return QLA_FUNCTION_FAILED;
 
@@ -2714,3 +2806,50 @@ qla2xxx_get_vpd_field(scsi_qla_host_t *vha, char *key, char *str, size_t size)
 
        return 0;
 }
+
+int
+qla24xx_read_fcp_prio_cfg(scsi_qla_host_t *vha)
+{
+       int len, max_len;
+       uint32_t fcp_prio_addr;
+       struct qla_hw_data *ha = vha->hw;
+
+       if (!ha->fcp_prio_cfg) {
+               ha->fcp_prio_cfg = vmalloc(FCP_PRIO_CFG_SIZE);
+               if (!ha->fcp_prio_cfg) {
+                       qla_printk(KERN_WARNING, ha,
+                       "Unable to allocate memory for fcp priority data "
+                                       "(%x).\n", FCP_PRIO_CFG_SIZE);
+                       return QLA_FUNCTION_FAILED;
+               }
+       }
+       memset(ha->fcp_prio_cfg, 0, FCP_PRIO_CFG_SIZE);
+
+       fcp_prio_addr = ha->flt_region_fcp_prio;
+
+       /* first read the fcp priority data header from flash */
+       ha->isp_ops->read_optrom(vha, (uint8_t *)ha->fcp_prio_cfg,
+                       fcp_prio_addr << 2, FCP_PRIO_CFG_HDR_SIZE);
+
+       if (!qla24xx_fcp_prio_cfg_valid(ha->fcp_prio_cfg, 0))
+               goto fail;
+
+       /* read remaining FCP CMD config data from flash */
+       fcp_prio_addr += (FCP_PRIO_CFG_HDR_SIZE >> 2);
+       len = ha->fcp_prio_cfg->num_entries * FCP_PRIO_CFG_ENTRY_SIZE;
+       max_len = FCP_PRIO_CFG_SIZE - FCP_PRIO_CFG_HDR_SIZE;
+
+       ha->isp_ops->read_optrom(vha, (uint8_t *)&ha->fcp_prio_cfg->entry[0],
+                       fcp_prio_addr << 2, (len < max_len ? len : max_len));
+
+       /* revalidate the entire FCP priority config data, including entries */
+       if (!qla24xx_fcp_prio_cfg_valid(ha->fcp_prio_cfg, 1))
+               goto fail;
+
+       ha->flags.fcp_prio_enabled = 1;
+       return QLA_SUCCESS;
+fail:
+       vfree(ha->fcp_prio_cfg);
+       ha->fcp_prio_cfg = NULL;
+       return QLA_FUNCTION_FAILED;
+}