Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6
[deliverable/linux.git] / drivers / scsi / qla2xxx / qla_init.c
index b247bc22704e7bb09bfb3c4794bf417d8beb0bcb..2a45aec4ff29e6499a36456d24f6f496caf9ff4a 100644 (file)
 
 #include "qla_devtbl.h"
 
+#ifdef CONFIG_SPARC
+#include <asm/prom.h>
+#endif
+
 /* XXX(hch): this is ugly, but we don't want to pull in exioctl.h */
 #ifndef EXT_IS_LUN_BIT_SET
 #define EXT_IS_LUN_BIT_SET(P,L) \
@@ -77,7 +81,7 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha)
        qla_printk(KERN_INFO, ha, "Configuring PCI space...\n");
        rval = ha->isp_ops.pci_config(ha);
        if (rval) {
-               DEBUG2(printk("scsi(%ld): Unable to configure PCI space=n",
+               DEBUG2(printk("scsi(%ld): Unable to configure PCI space.\n",
                    ha->host_no));
                return (rval);
        }
@@ -88,12 +92,7 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha)
 
        qla_printk(KERN_INFO, ha, "Configure NVRAM parameters...\n");
 
-       rval = ha->isp_ops.nvram_config(ha);
-       if (rval) {
-               DEBUG2(printk("scsi(%ld): Unable to verify NVRAM data.\n",
-                   ha->host_no));
-               return rval;
-       }
+       ha->isp_ops.nvram_config(ha);
 
        if (ha->flags.disable_serdes) {
                /* Mask HBA via NVRAM settings? */
@@ -130,18 +129,17 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha)
 int
 qla2100_pci_config(scsi_qla_host_t *ha)
 {
-       uint16_t w, mwi;
+       int ret;
+       uint16_t w;
        uint32_t d;
        unsigned long flags;
        struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
 
        pci_set_master(ha->pdev);
-       mwi = 0;
-       if (pci_set_mwi(ha->pdev))
-               mwi = PCI_COMMAND_INVALIDATE;
+       ret = pci_set_mwi(ha->pdev);
 
        pci_read_config_word(ha->pdev, PCI_COMMAND, &w);
-       w |= mwi | (PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
+       w |= (PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
        pci_write_config_word(ha->pdev, PCI_COMMAND, w);
 
        /* Reset expansion ROM address decode enable */
@@ -166,22 +164,22 @@ qla2100_pci_config(scsi_qla_host_t *ha)
 int
 qla2300_pci_config(scsi_qla_host_t *ha)
 {
-       uint16_t        w, mwi;
+       int             ret;
+       uint16_t        w;
        uint32_t        d;
        unsigned long   flags = 0;
        uint32_t        cnt;
        struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
 
        pci_set_master(ha->pdev);
-       mwi = 0;
-       if (pci_set_mwi(ha->pdev))
-               mwi = PCI_COMMAND_INVALIDATE;
+       ret = pci_set_mwi(ha->pdev);
 
        pci_read_config_word(ha->pdev, PCI_COMMAND, &w);
-       w |= mwi | (PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
+       w |= (PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
 
        if (IS_QLA2322(ha) || IS_QLA6322(ha))
                w &= ~PCI_COMMAND_INTX_DISABLE;
+       pci_write_config_word(ha->pdev, PCI_COMMAND, w);
 
        /*
         * If this is a 2300 card and not 2312, reset the
@@ -210,7 +208,7 @@ qla2300_pci_config(scsi_qla_host_t *ha)
                ha->fb_rev = RD_FB_CMD_REG(ha, reg);
 
                if (ha->fb_rev == FPM_2300)
-                       w &= ~PCI_COMMAND_INVALIDATE;
+                       pci_clear_mwi(ha->pdev);
 
                /* Deselect FPM registers. */
                WRT_REG_WORD(&reg->ctrl_status, 0x0);
@@ -227,7 +225,6 @@ qla2300_pci_config(scsi_qla_host_t *ha)
 
                spin_unlock_irqrestore(&ha->hardware_lock, flags);
        }
-       pci_write_config_word(ha->pdev, PCI_COMMAND, w);
 
        pci_write_config_byte(ha->pdev, PCI_LATENCY_TIMER, 0x80);
 
@@ -253,19 +250,18 @@ qla2300_pci_config(scsi_qla_host_t *ha)
 int
 qla24xx_pci_config(scsi_qla_host_t *ha)
 {
-       uint16_t w, mwi;
+       int ret;
+       uint16_t w;
        uint32_t d;
        unsigned long flags = 0;
        struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
        int pcix_cmd_reg, pcie_dctl_reg;
 
        pci_set_master(ha->pdev);
-       mwi = 0;
-       if (pci_set_mwi(ha->pdev))
-               mwi = PCI_COMMAND_INVALIDATE;
+       ret = pci_set_mwi(ha->pdev);
 
        pci_read_config_word(ha->pdev, PCI_COMMAND, &w);
-       w |= mwi | (PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
+       w |= (PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
        w &= ~PCI_COMMAND_INTX_DISABLE;
        pci_write_config_word(ha->pdev, PCI_COMMAND, w);
 
@@ -1393,6 +1389,27 @@ qla2x00_set_model_info(scsi_qla_host_t *ha, uint8_t *model, size_t len, char *de
        }
 }
 
+/* On sparc systems, obtain port and node WWN from firmware
+ * properties.
+ */
+static void qla2xxx_nvram_wwn_from_ofw(scsi_qla_host_t *ha, nvram_t *nv)
+{
+#ifdef CONFIG_SPARC
+       struct pci_dev *pdev = ha->pdev;
+       struct device_node *dp = pci_device_to_OF_node(pdev);
+       const u8 *val;
+       int len;
+
+       val = of_get_property(dp, "port-wwn", &len);
+       if (val && len >= WWN_SIZE)
+               memcpy(nv->port_name, val, WWN_SIZE);
+
+       val = of_get_property(dp, "node-wwn", &len);
+       if (val && len >= WWN_SIZE)
+               memcpy(nv->node_name, val, WWN_SIZE);
+#endif
+}
+
 /*
 * NVRAM configuration for ISP 2xxx
 *
@@ -1409,6 +1426,7 @@ qla2x00_set_model_info(scsi_qla_host_t *ha, uint8_t *model, size_t len, char *de
 int
 qla2x00_nvram_config(scsi_qla_host_t *ha)
 {
+       int             rval;
        uint8_t         chksum = 0;
        uint16_t        cnt;
        uint8_t         *dptr1, *dptr2;
@@ -1417,6 +1435,8 @@ qla2x00_nvram_config(scsi_qla_host_t *ha)
        uint8_t         *ptr = (uint8_t *)ha->request_ring;
        struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
 
+       rval = QLA_SUCCESS;
+
        /* Determine NVRAM starting address. */
        ha->nvram_size = sizeof(nvram_t);
        ha->nvram_base = 0;
@@ -1440,7 +1460,57 @@ qla2x00_nvram_config(scsi_qla_host_t *ha)
                qla_printk(KERN_WARNING, ha, "Inconsistent NVRAM detected: "
                    "checksum=0x%x id=%c version=0x%x.\n", chksum, nv->id[0],
                    nv->nvram_version);
-               return QLA_FUNCTION_FAILED;
+               qla_printk(KERN_WARNING, ha, "Falling back to functioning (yet "
+                   "invalid -- WWPN) defaults.\n");
+
+               /*
+                * Set default initialization control block.
+                */
+               memset(nv, 0, ha->nvram_size);
+               nv->parameter_block_version = ICB_VERSION;
+
+               if (IS_QLA23XX(ha)) {
+                       nv->firmware_options[0] = BIT_2 | BIT_1;
+                       nv->firmware_options[1] = BIT_7 | BIT_5;
+                       nv->add_firmware_options[0] = BIT_5;
+                       nv->add_firmware_options[1] = BIT_5 | BIT_4;
+                       nv->frame_payload_size = __constant_cpu_to_le16(2048);
+                       nv->special_options[1] = BIT_7;
+               } else if (IS_QLA2200(ha)) {
+                       nv->firmware_options[0] = BIT_2 | BIT_1;
+                       nv->firmware_options[1] = BIT_7 | BIT_5;
+                       nv->add_firmware_options[0] = BIT_5;
+                       nv->add_firmware_options[1] = BIT_5 | BIT_4;
+                       nv->frame_payload_size = __constant_cpu_to_le16(1024);
+               } else if (IS_QLA2100(ha)) {
+                       nv->firmware_options[0] = BIT_3 | BIT_1;
+                       nv->firmware_options[1] = BIT_5;
+                       nv->frame_payload_size = __constant_cpu_to_le16(1024);
+               }
+
+               nv->max_iocb_allocation = __constant_cpu_to_le16(256);
+               nv->execution_throttle = __constant_cpu_to_le16(16);
+               nv->retry_count = 8;
+               nv->retry_delay = 1;
+
+               nv->port_name[0] = 33;
+               nv->port_name[3] = 224;
+               nv->port_name[4] = 139;
+
+               qla2xxx_nvram_wwn_from_ofw(ha, nv);
+
+               nv->login_timeout = 4;
+
+               /*
+                * Set default host adapter parameters
+                */
+               nv->host_p[1] = BIT_2;
+               nv->reset_delay = 5;
+               nv->port_down_retry_count = 8;
+               nv->max_luns_per_target = __constant_cpu_to_le16(8);
+               nv->link_down_timeout = 60;
+
+               rval = 1;
        }
 
 #if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2)
@@ -1653,7 +1723,11 @@ qla2x00_nvram_config(scsi_qla_host_t *ha)
                }
        }
 
-       return QLA_SUCCESS;
+       if (rval) {
+               DEBUG2_3(printk(KERN_WARNING
+                   "scsi(%ld): NVRAM configuration failed!\n", ha->host_no));
+       }
+       return (rval);
 }
 
 static void
@@ -2065,40 +2139,7 @@ qla2x00_iidma_fcport(scsi_qla_host_t *ha, fc_port_t *fcport)
        }
 }
 
-/*
- * qla2x00_update_fcport
- *     Updates device on list.
- *
- * Input:
- *     ha = adapter block pointer.
- *     fcport = port structure pointer.
- *
- * Return:
- *     0  - Success
- *  BIT_0 - error
- *
- * Context:
- *     Kernel context.
- */
-void
-qla2x00_update_fcport(scsi_qla_host_t *ha, fc_port_t *fcport)
-{
-       fcport->ha = ha;
-       fcport->login_retry = 0;
-       fcport->port_login_retry_count = ha->port_down_retry_count *
-           PORT_RETRY_TIME;
-       atomic_set(&fcport->port_down_timer, ha->port_down_retry_count *
-           PORT_RETRY_TIME);
-       fcport->flags &= ~FCF_LOGIN_NEEDED;
-
-       qla2x00_iidma_fcport(ha, fcport);
-
-       atomic_set(&fcport->state, FCS_ONLINE);
-
-       qla2x00_reg_remote_port(ha, fcport);
-}
-
-void
+static void
 qla2x00_reg_remote_port(scsi_qla_host_t *ha, fc_port_t *fcport)
 {
        struct fc_rport_identifiers rport_ids;
@@ -2140,6 +2181,39 @@ qla2x00_reg_remote_port(scsi_qla_host_t *ha, fc_port_t *fcport)
                fcport->os_target_id = rport->scsi_target_id;
 }
 
+/*
+ * qla2x00_update_fcport
+ *     Updates device on list.
+ *
+ * Input:
+ *     ha = adapter block pointer.
+ *     fcport = port structure pointer.
+ *
+ * Return:
+ *     0  - Success
+ *  BIT_0 - error
+ *
+ * Context:
+ *     Kernel context.
+ */
+void
+qla2x00_update_fcport(scsi_qla_host_t *ha, fc_port_t *fcport)
+{
+       fcport->ha = ha;
+       fcport->login_retry = 0;
+       fcport->port_login_retry_count = ha->port_down_retry_count *
+           PORT_RETRY_TIME;
+       atomic_set(&fcport->port_down_timer, ha->port_down_retry_count *
+           PORT_RETRY_TIME);
+       fcport->flags &= ~FCF_LOGIN_NEEDED;
+
+       qla2x00_iidma_fcport(ha, fcport);
+
+       atomic_set(&fcport->state, FCS_ONLINE);
+
+       qla2x00_reg_remote_port(ha, fcport);
+}
+
 /*
  * qla2x00_configure_fabric
  *      Setup SNS devices with loop ID's.
@@ -3071,9 +3145,7 @@ qla2x00_abort_isp(scsi_qla_host_t *ha)
 
                ha->isp_ops.get_flash_version(ha, ha->request_ring);
 
-               rval = ha->isp_ops.nvram_config(ha);
-               if (rval)
-                       goto isp_abort_retry;
+               ha->isp_ops.nvram_config(ha);
 
                if (!qla2x00_restart_isp(ha)) {
                        clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags);
@@ -3103,7 +3175,6 @@ qla2x00_abort_isp(scsi_qla_host_t *ha)
                                }
                        }
                } else {        /* failed the ISP abort */
-isp_abort_retry:
                        ha->flags.online = 1;
                        if (test_bit(ISP_ABORT_RETRY, &ha->dpc_flags)) {
                                if (ha->isp_abort_cnt == 0) {
@@ -3290,9 +3361,31 @@ qla24xx_reset_adapter(scsi_qla_host_t *ha)
        spin_unlock_irqrestore(&ha->hardware_lock, flags);
 }
 
+/* On sparc systems, obtain port and node WWN from firmware
+ * properties.
+ */
+static void qla24xx_nvram_wwn_from_ofw(scsi_qla_host_t *ha, struct nvram_24xx *nv)
+{
+#ifdef CONFIG_SPARC
+       struct pci_dev *pdev = ha->pdev;
+       struct device_node *dp = pci_device_to_OF_node(pdev);
+       const u8 *val;
+       int len;
+
+       val = of_get_property(dp, "port-wwn", &len);
+       if (val && len >= WWN_SIZE)
+               memcpy(nv->port_name, val, WWN_SIZE);
+
+       val = of_get_property(dp, "node-wwn", &len);
+       if (val && len >= WWN_SIZE)
+               memcpy(nv->node_name, val, WWN_SIZE);
+#endif
+}
+
 int
 qla24xx_nvram_config(scsi_qla_host_t *ha)
 {
+       int   rval;
        struct init_cb_24xx *icb;
        struct nvram_24xx *nv;
        uint32_t *dptr;
@@ -3300,6 +3393,7 @@ qla24xx_nvram_config(scsi_qla_host_t *ha)
        uint32_t chksum;
        uint16_t cnt;
 
+       rval = QLA_SUCCESS;
        icb = (struct init_cb_24xx *)ha->init_cb;
        nv = (struct nvram_24xx *)ha->request_ring;
 
@@ -3332,7 +3426,52 @@ qla24xx_nvram_config(scsi_qla_host_t *ha)
                qla_printk(KERN_WARNING, ha, "Inconsistent NVRAM detected: "
                    "checksum=0x%x id=%c version=0x%x.\n", chksum, nv->id[0],
                    le16_to_cpu(nv->nvram_version));
-               return QLA_FUNCTION_FAILED;
+               qla_printk(KERN_WARNING, ha, "Falling back to functioning (yet "
+                   "invalid -- WWPN) defaults.\n");
+
+               /*
+                * Set default initialization control block.
+                */
+               memset(nv, 0, ha->nvram_size);
+               nv->nvram_version = __constant_cpu_to_le16(ICB_VERSION);
+               nv->version = __constant_cpu_to_le16(ICB_VERSION);
+               nv->frame_payload_size = __constant_cpu_to_le16(2048);
+               nv->execution_throttle = __constant_cpu_to_le16(0xFFFF);
+               nv->exchange_count = __constant_cpu_to_le16(0);
+               nv->hard_address = __constant_cpu_to_le16(124);
+               nv->port_name[0] = 0x21;
+               nv->port_name[1] = 0x00 + PCI_FUNC(ha->pdev->devfn);
+               nv->port_name[2] = 0x00;
+               nv->port_name[3] = 0xe0;
+               nv->port_name[4] = 0x8b;
+               nv->port_name[5] = 0x1c;
+               nv->port_name[6] = 0x55;
+               nv->port_name[7] = 0x86;
+               nv->node_name[0] = 0x20;
+               nv->node_name[1] = 0x00;
+               nv->node_name[2] = 0x00;
+               nv->node_name[3] = 0xe0;
+               nv->node_name[4] = 0x8b;
+               nv->node_name[5] = 0x1c;
+               nv->node_name[6] = 0x55;
+               nv->node_name[7] = 0x86;
+               qla24xx_nvram_wwn_from_ofw(ha, nv);
+               nv->login_retry_count = __constant_cpu_to_le16(8);
+               nv->interrupt_delay_timer = __constant_cpu_to_le16(0);
+               nv->login_timeout = __constant_cpu_to_le16(0);
+               nv->firmware_options_1 =
+                   __constant_cpu_to_le32(BIT_14|BIT_13|BIT_2|BIT_1);
+               nv->firmware_options_2 = __constant_cpu_to_le32(2 << 4);
+               nv->firmware_options_2 |= __constant_cpu_to_le32(BIT_12);
+               nv->firmware_options_3 = __constant_cpu_to_le32(2 << 13);
+               nv->host_p = __constant_cpu_to_le32(BIT_11|BIT_10);
+               nv->efi_parameters = __constant_cpu_to_le32(0);
+               nv->reset_delay = 5;
+               nv->max_luns_per_target = __constant_cpu_to_le16(128);
+               nv->port_down_retry_count = __constant_cpu_to_le16(30);
+               nv->link_down_timeout = __constant_cpu_to_le16(30);
+
+               rval = 1;
        }
 
        /* Reset Initialization control block */
@@ -3380,9 +3519,11 @@ qla24xx_nvram_config(scsi_qla_host_t *ha)
 
        /* Set host adapter parameters. */
        ha->flags.disable_risc_code_load = 0;
-       ha->flags.enable_lip_reset = 1;
-       ha->flags.enable_lip_full_login = 1;
-       ha->flags.enable_target_reset = 1;
+       ha->flags.enable_lip_reset = 0;
+       ha->flags.enable_lip_full_login =
+           le32_to_cpu(nv->host_p) & BIT_10 ? 1: 0;
+       ha->flags.enable_target_reset =
+           le32_to_cpu(nv->host_p) & BIT_11 ? 1: 0;
        ha->flags.enable_led_scheme = 0;
        ha->flags.disable_serdes = le32_to_cpu(nv->host_p) & BIT_5 ? 1: 0;
 
@@ -3477,7 +3618,11 @@ qla24xx_nvram_config(scsi_qla_host_t *ha)
                ha->flags.process_response_queue = 1;
        }
 
-       return QLA_SUCCESS;
+       if (rval) {
+               DEBUG2_3(printk(KERN_WARNING
+                   "scsi(%ld): NVRAM configuration failed!\n", ha->host_no));
+       }
+       return (rval);
 }
 
 static int
@@ -3780,6 +3925,8 @@ qla2x00_try_to_stop_firmware(scsi_qla_host_t *ha)
 
        if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha))
                return;
+       if (!ha->fw_major_version)
+               return;
 
        ret = qla2x00_stop_firmware(ha);
        for (retries = 5; ret != QLA_SUCCESS && retries ; retries--) {
This page took 0.031862 seconds and 5 git commands to generate.