Merge tag 'pull-tmpfile' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
[linux-2.6-block.git] / drivers / scsi / mpt3sas / mpt3sas_base.c
index 331e896d8225df01040460c377876bf583894356..8b22df8c1792dbca52b37bf5399ccc6e151aeafc 100644 (file)
@@ -2990,19 +2990,26 @@ static int
 _base_config_dma_addressing(struct MPT3SAS_ADAPTER *ioc, struct pci_dev *pdev)
 {
        struct sysinfo s;
+       u64 coherent_dma_mask, dma_mask;
 
-       if (ioc->is_mcpu_endpoint ||
-           sizeof(dma_addr_t) == 4 || ioc->use_32bit_dma ||
-           dma_get_required_mask(&pdev->dev) <= DMA_BIT_MASK(32))
+       if (ioc->is_mcpu_endpoint || sizeof(dma_addr_t) == 4 ||
+           dma_get_required_mask(&pdev->dev) <= 32) {
                ioc->dma_mask = 32;
+               coherent_dma_mask = dma_mask = DMA_BIT_MASK(32);
        /* Set 63 bit DMA mask for all SAS3 and SAS35 controllers */
-       else if (ioc->hba_mpi_version_belonged > MPI2_VERSION)
+       } else if (ioc->hba_mpi_version_belonged > MPI2_VERSION) {
                ioc->dma_mask = 63;
-       else
+               coherent_dma_mask = dma_mask = DMA_BIT_MASK(63);
+       } else {
                ioc->dma_mask = 64;
+               coherent_dma_mask = dma_mask = DMA_BIT_MASK(64);
+       }
 
-       if (dma_set_mask(&pdev->dev, DMA_BIT_MASK(ioc->dma_mask)) ||
-           dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(ioc->dma_mask)))
+       if (ioc->use_32bit_dma)
+               coherent_dma_mask = DMA_BIT_MASK(32);
+
+       if (dma_set_mask(&pdev->dev, dma_mask) ||
+           dma_set_coherent_mask(&pdev->dev, coherent_dma_mask))
                return -ENODEV;
 
        if (ioc->dma_mask > 32) {
@@ -4313,7 +4320,7 @@ _base_put_smid_scsi_io_atomic(struct MPT3SAS_ADAPTER *ioc, u16 smid,
        descriptor.MSIxIndex = _base_set_and_get_msix_index(ioc, smid);
        descriptor.SMID = cpu_to_le16(smid);
 
-       writel(*request, &ioc->chip->AtomicRequestDescriptorPost);
+       writel(cpu_to_le32(*request), &ioc->chip->AtomicRequestDescriptorPost);
 }
 
 /**
@@ -4335,7 +4342,7 @@ _base_put_smid_fast_path_atomic(struct MPT3SAS_ADAPTER *ioc, u16 smid,
        descriptor.MSIxIndex = _base_set_and_get_msix_index(ioc, smid);
        descriptor.SMID = cpu_to_le16(smid);
 
-       writel(*request, &ioc->chip->AtomicRequestDescriptorPost);
+       writel(cpu_to_le32(*request), &ioc->chip->AtomicRequestDescriptorPost);
 }
 
 /**
@@ -4358,7 +4365,7 @@ _base_put_smid_hi_priority_atomic(struct MPT3SAS_ADAPTER *ioc, u16 smid,
        descriptor.MSIxIndex = msix_task;
        descriptor.SMID = cpu_to_le16(smid);
 
-       writel(*request, &ioc->chip->AtomicRequestDescriptorPost);
+       writel(cpu_to_le32(*request), &ioc->chip->AtomicRequestDescriptorPost);
 }
 
 /**
@@ -4379,7 +4386,7 @@ _base_put_smid_default_atomic(struct MPT3SAS_ADAPTER *ioc, u16 smid)
        descriptor.MSIxIndex = _base_set_and_get_msix_index(ioc, smid);
        descriptor.SMID = cpu_to_le16(smid);
 
-       writel(*request, &ioc->chip->AtomicRequestDescriptorPost);
+       writel(cpu_to_le32(*request), &ioc->chip->AtomicRequestDescriptorPost);
 }
 
 /**
@@ -5424,6 +5431,151 @@ out:
        return rc;
 }
 
+/**
+ * mpt3sas_atto_validate_nvram - validate the ATTO nvram read from mfg pg1
+ *
+ * @ioc : per adapter object
+ * @n   : ptr to the ATTO nvram structure
+ * Return: 0 for success, non-zero for failure.
+ */
+static int
+mpt3sas_atto_validate_nvram(struct MPT3SAS_ADAPTER *ioc,
+                           struct ATTO_SAS_NVRAM *n)
+{
+       int r = -EINVAL;
+       union ATTO_SAS_ADDRESS *s1;
+       u32 len;
+       u8 *pb;
+       u8 ckSum;
+
+       /* validate nvram checksum */
+       pb = (u8 *) n;
+       ckSum = ATTO_SASNVR_CKSUM_SEED;
+       len = sizeof(struct ATTO_SAS_NVRAM);
+
+       while (len--)
+               ckSum = ckSum + pb[len];
+
+       if (ckSum) {
+               ioc_err(ioc, "Invalid ATTO NVRAM checksum\n");
+               return r;
+       }
+
+       s1 = (union ATTO_SAS_ADDRESS *) n->SasAddr;
+
+       if (n->Signature[0] != 'E'
+       || n->Signature[1] != 'S'
+       || n->Signature[2] != 'A'
+       || n->Signature[3] != 'S')
+               ioc_err(ioc, "Invalid ATTO NVRAM signature\n");
+       else if (n->Version > ATTO_SASNVR_VERSION)
+               ioc_info(ioc, "Invalid ATTO NVRAM version");
+       else if ((n->SasAddr[7] & (ATTO_SAS_ADDR_ALIGN - 1))
+                       || s1->b[0] != 0x50
+                       || s1->b[1] != 0x01
+                       || s1->b[2] != 0x08
+                       || (s1->b[3] & 0xF0) != 0x60
+                       || ((s1->b[3] & 0x0F) | le32_to_cpu(s1->d[1])) == 0) {
+               ioc_err(ioc, "Invalid ATTO SAS address\n");
+       } else
+               r = 0;
+       return r;
+}
+
+/**
+ * mpt3sas_atto_get_sas_addr - get the ATTO SAS address from mfg page 1
+ *
+ * @ioc : per adapter object
+ * @*sas_addr : return sas address
+ * Return: 0 for success, non-zero for failure.
+ */
+static int
+mpt3sas_atto_get_sas_addr(struct MPT3SAS_ADAPTER *ioc, union ATTO_SAS_ADDRESS *sas_addr)
+{
+       Mpi2ManufacturingPage1_t mfg_pg1;
+       Mpi2ConfigReply_t mpi_reply;
+       struct ATTO_SAS_NVRAM *nvram;
+       int r;
+       __be64 addr;
+
+       r = mpt3sas_config_get_manufacturing_pg1(ioc, &mpi_reply, &mfg_pg1);
+       if (r) {
+               ioc_err(ioc, "Failed to read manufacturing page 1\n");
+               return r;
+       }
+
+       /* validate nvram */
+       nvram = (struct ATTO_SAS_NVRAM *) mfg_pg1.VPD;
+       r = mpt3sas_atto_validate_nvram(ioc, nvram);
+       if (r)
+               return r;
+
+       addr = *((__be64 *) nvram->SasAddr);
+       sas_addr->q = cpu_to_le64(be64_to_cpu(addr));
+       return r;
+}
+
+/**
+ * mpt3sas_atto_init - perform initializaion for ATTO branded
+ *                                     adapter.
+ * @ioc : per adapter object
+ *5
+ * Return: 0 for success, non-zero for failure.
+ */
+static int
+mpt3sas_atto_init(struct MPT3SAS_ADAPTER *ioc)
+{
+       int sz = 0;
+       Mpi2BiosPage4_t *bios_pg4 = NULL;
+       Mpi2ConfigReply_t mpi_reply;
+       int r;
+       int ix;
+       union ATTO_SAS_ADDRESS sas_addr;
+       union ATTO_SAS_ADDRESS temp;
+       union ATTO_SAS_ADDRESS bias;
+
+       r = mpt3sas_atto_get_sas_addr(ioc, &sas_addr);
+       if (r)
+               return r;
+
+       /* get header first to get size */
+       r = mpt3sas_config_get_bios_pg4(ioc, &mpi_reply, NULL, 0);
+       if (r) {
+               ioc_err(ioc, "Failed to read ATTO bios page 4 header.\n");
+               return r;
+       }
+
+       sz = mpi_reply.Header.PageLength * sizeof(u32);
+       bios_pg4 = kzalloc(sz, GFP_KERNEL);
+       if (!bios_pg4) {
+               ioc_err(ioc, "Failed to allocate memory for ATTO bios page.\n");
+               return -ENOMEM;
+       }
+
+       /* read bios page 4 */
+       r = mpt3sas_config_get_bios_pg4(ioc, &mpi_reply, bios_pg4, sz);
+       if (r) {
+               ioc_err(ioc, "Failed to read ATTO bios page 4\n");
+               goto out;
+       }
+
+       /* Update bios page 4 with the ATTO WWID */
+       bias.q = sas_addr.q;
+       bias.b[7] += ATTO_SAS_ADDR_DEVNAME_BIAS;
+
+       for (ix = 0; ix < bios_pg4->NumPhys; ix++) {
+               temp.q = sas_addr.q;
+               temp.b[7] += ix;
+               bios_pg4->Phy[ix].ReassignmentWWID = temp.q;
+               bios_pg4->Phy[ix].ReassignmentDeviceName = bias.q;
+       }
+       r = mpt3sas_config_set_bios_pg4(ioc, &mpi_reply, bios_pg4, sz);
+
+out:
+       kfree(bios_pg4);
+       return r;
+}
+
 /**
  * _base_static_config_pages - static start of day config pages
  * @ioc: per adapter object
@@ -5447,6 +5599,13 @@ _base_static_config_pages(struct MPT3SAS_ADAPTER *ioc)
                if (rc)
                        return rc;
        }
+
+       if (ioc->pdev->vendor == MPI2_MFGPAGE_VENDORID_ATTO) {
+               rc = mpt3sas_atto_init(ioc);
+               if (rc)
+                       return rc;
+       }
+
        /*
         * Ensure correct T10 PI operation if vendor left EEDPTagMode
         * flag unset in NVDATA.
@@ -5496,12 +5655,21 @@ _base_static_config_pages(struct MPT3SAS_ADAPTER *ioc)
        rc = _base_assign_fw_reported_qd(ioc);
        if (rc)
                return rc;
-       rc = mpt3sas_config_get_bios_pg2(ioc, &mpi_reply, &ioc->bios_pg2);
-       if (rc)
-               return rc;
-       rc = mpt3sas_config_get_bios_pg3(ioc, &mpi_reply, &ioc->bios_pg3);
-       if (rc)
-               return rc;
+
+       /*
+        * ATTO doesn't use bios page 2 and 3 for bios settings.
+        */
+       if (ioc->pdev->vendor ==  MPI2_MFGPAGE_VENDORID_ATTO)
+               ioc->bios_pg3.BiosVersion = 0;
+       else {
+               rc = mpt3sas_config_get_bios_pg2(ioc, &mpi_reply, &ioc->bios_pg2);
+               if (rc)
+                       return rc;
+               rc = mpt3sas_config_get_bios_pg3(ioc, &mpi_reply, &ioc->bios_pg3);
+               if (rc)
+                       return rc;
+       }
+
        rc = mpt3sas_config_get_ioc_pg8(ioc, &mpi_reply, &ioc->ioc_pg8);
        if (rc)
                return rc;
@@ -6895,7 +7063,7 @@ _base_handshake_req_reply_wait(struct MPT3SAS_ADAPTER *ioc, int request_bytes,
 
        /* send message 32-bits at a time */
        for (i = 0, failed = 0; i < request_bytes/4 && !failed; i++) {
-               writel(request[i], &ioc->chip->Doorbell);
+               writel(cpu_to_le32(request[i]), &ioc->chip->Doorbell);
                if ((_base_wait_for_doorbell_ack(ioc, 5)))
                        failed = 1;
        }
@@ -6914,16 +7082,16 @@ _base_handshake_req_reply_wait(struct MPT3SAS_ADAPTER *ioc, int request_bytes,
        }
 
        /* read the first two 16-bits, it gives the total length of the reply */
-       reply[0] = ioc->base_readl(&ioc->chip->Doorbell)
-               & MPI2_DOORBELL_DATA_MASK;
+       reply[0] = le16_to_cpu(ioc->base_readl(&ioc->chip->Doorbell)
+           & MPI2_DOORBELL_DATA_MASK);
        writel(0, &ioc->chip->HostInterruptStatus);
        if ((_base_wait_for_doorbell_int(ioc, 5))) {
                ioc_err(ioc, "doorbell handshake int failed (line=%d)\n",
                        __LINE__);
                return -EFAULT;
        }
-       reply[1] = ioc->base_readl(&ioc->chip->Doorbell)
-               & MPI2_DOORBELL_DATA_MASK;
+       reply[1] = le16_to_cpu(ioc->base_readl(&ioc->chip->Doorbell)
+           & MPI2_DOORBELL_DATA_MASK);
        writel(0, &ioc->chip->HostInterruptStatus);
 
        for (i = 2; i < default_reply->MsgLength * 2; i++)  {
@@ -6935,8 +7103,9 @@ _base_handshake_req_reply_wait(struct MPT3SAS_ADAPTER *ioc, int request_bytes,
                if (i >=  reply_bytes/2) /* overflow case */
                        ioc->base_readl(&ioc->chip->Doorbell);
                else
-                       reply[i] = ioc->base_readl(&ioc->chip->Doorbell)
-                               & MPI2_DOORBELL_DATA_MASK;
+                       reply[i] = le16_to_cpu(
+                           ioc->base_readl(&ioc->chip->Doorbell)
+                           & MPI2_DOORBELL_DATA_MASK);
                writel(0, &ioc->chip->HostInterruptStatus);
        }