Merge branch 'master' into for_paulus
[linux-drm-fsl-dcu.git] / drivers / message / fusion / mptctl.c
index 30975ccd9947622de211661134bc74e94ceea254..9d0f30478e464d5a08a15ed8bcc07a1ef01fe9c7 100644 (file)
@@ -4,8 +4,8 @@
  *      For use with LSI Logic PCI chip/adapters
  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
  *
- *  Copyright (c) 1999-2005 LSI Logic Corporation
- *  (mailto:mpt_linux_developer@lsil.com)
+ *  Copyright (c) 1999-2007 LSI Logic Corporation
+ *  (mailto:mpt_linux_developer@lsi.com)
  *
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -66,7 +66,7 @@
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_tcq.h>
 
-#define COPYRIGHT      "Copyright (c) 1999-2005 LSI Logic Corporation"
+#define COPYRIGHT      "Copyright (c) 1999-2007 LSI Logic Corporation"
 #define MODULEAUTHOR   "LSI Logic Corporation"
 #include "mptbase.h"
 #include "mptctl.h"
@@ -79,6 +79,7 @@
 MODULE_AUTHOR(MODULEAUTHOR);
 MODULE_DESCRIPTION(my_NAME);
 MODULE_LICENSE("GPL");
+MODULE_VERSION(my_VERSION);
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 
@@ -312,7 +313,7 @@ static void mptctl_timeout_expired (MPT_IOCTL *ioctl)
                 */
                dctlprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
                         ioctl->ioc->name));
-               mpt_HardResetHandler(ioctl->ioc, NO_SLEEP);
+               mpt_HardResetHandler(ioctl->ioc, CAN_SLEEP);
        }
        return;
 
@@ -360,7 +361,7 @@ static int mptctl_bus_reset(MPT_IOCTL *ioctl)
                        ioctl->ioc->name, mf));
 
        pScsiTm = (SCSITaskMgmt_t *) mf;
-       pScsiTm->TargetID = ioctl->target;
+       pScsiTm->TargetID = ioctl->id;
        pScsiTm->Bus = hd->port;        /* 0 */
        pScsiTm->ChainOffset = 0;
        pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
@@ -1158,15 +1159,12 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size)
        struct mpt_ioctl_iocinfo *karg;
        MPT_ADAPTER             *ioc;
        struct pci_dev          *pdev;
-       struct Scsi_Host        *sh;
-       MPT_SCSI_HOST           *hd;
        int                     iocnum;
-       int                     numDevices = 0;
-       unsigned int            max_id;
-       int                     ii;
        unsigned int            port;
        int                     cim_rev;
        u8                      revision;
+       struct scsi_device      *sdev;
+       VirtDevice              *vdev;
 
        dctlprintk((": mptctl_getiocinfo called.\n"));
        /* Add of PCI INFO results in unaligned access for
@@ -1256,23 +1254,16 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size)
 
        /* Get number of devices
          */
-       if ((sh = ioc->sh) != NULL) {
-                /* sh->max_id = maximum target ID + 1
-                */
-               max_id = sh->max_id - 1;
-               hd = (MPT_SCSI_HOST *) sh->hostdata;
-
-               /* Check all of the target structures and
-                * keep a counter.
-                */
-               if (hd && hd->Targets) {
-                       for (ii = 0; ii <= max_id; ii++) {
-                               if (hd->Targets[ii])
-                                       numDevices++;
-                       }
+       karg->numDevices = 0;
+       if (ioc->sh) {
+               shost_for_each_device(sdev, ioc->sh) {
+                       vdev = sdev->hostdata;
+                       if (vdev->vtarget->tflags &
+                           MPT_TARGET_FLAGS_RAID_COMPONENT)
+                               continue;
+                       karg->numDevices++;
                }
        }
-       karg->numDevices = numDevices;
 
        /* Set the BIOS and FW Version
         */
@@ -1318,21 +1309,16 @@ mptctl_gettargetinfo (unsigned long arg)
        struct mpt_ioctl_targetinfo __user *uarg = (void __user *) arg;
        struct mpt_ioctl_targetinfo karg;
        MPT_ADAPTER             *ioc;
-       struct Scsi_Host        *sh;
-       MPT_SCSI_HOST           *hd;
-       VirtTarget              *vdev;
+       VirtDevice              *vdev;
        char                    *pmem;
        int                     *pdata;
-       IOCPage2_t              *pIoc2;
-       IOCPage3_t              *pIoc3;
        int                     iocnum;
        int                     numDevices = 0;
-       unsigned int            max_id;
-       int                     id, jj, indexed_lun, lun_index;
-       u32                     lun;
+       int                     lun;
        int                     maxWordsLeft;
        int                     numBytes;
-       u8                      port, devType, bus_id;
+       u8                      port;
+       struct scsi_device      *sdev;
 
        dctlprintk(("mptctl_gettargetinfo called.\n"));
        if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_targetinfo))) {
@@ -1388,74 +1374,22 @@ mptctl_gettargetinfo (unsigned long arg)
 
        /* Get number of devices
          */
-       if ((sh = ioc->sh) != NULL) {
-
-               max_id = sh->max_id - 1;
-               hd = (MPT_SCSI_HOST *) sh->hostdata;
-
-               /* Check all of the target structures.
-                * Save the Id and increment the counter,
-                * if ptr non-null.
-                * sh->max_id = maximum target ID + 1
-                */
-               if (hd && hd->Targets) {
-                       mpt_findImVolumes(ioc);
-                       pIoc2 = ioc->raid_data.pIocPg2;
-                       for ( id = 0; id <= max_id; ) {
-                               if ( pIoc2 && pIoc2->NumActiveVolumes ) {
-                                       if ( id == pIoc2->RaidVolume[0].VolumeID ) {
-                                               if (maxWordsLeft <= 0) {
-                                                       printk(KERN_ERR "mptctl_gettargetinfo - "
-                       "buffer is full but volume is available on ioc %d\n, numDevices=%d", iocnum, numDevices);
-                                                       goto data_space_full;
-                                               }
-                                               if ( ( pIoc2->RaidVolume[0].Flags & MPI_IOCPAGE2_FLAG_VOLUME_INACTIVE ) == 0 )
-                                                       devType = 0x80;
-                                               else
-                                                       devType = 0xC0;
-                                               bus_id = pIoc2->RaidVolume[0].VolumeBus;
-                                               numDevices++;
-                                               *pdata = ( (devType << 24) | (bus_id << 8) | id );
-                                               dctlprintk((KERN_ERR "mptctl_gettargetinfo - "
-               "volume ioc=%d target=%x numDevices=%d pdata=%p\n", iocnum, *pdata, numDevices, pdata));
-                                               pdata++;
-                                               --maxWordsLeft;
-                                               goto next_id;
-                                       } else {
-                                               pIoc3 = ioc->raid_data.pIocPg3;
-                                               for ( jj = 0; jj < pIoc3->NumPhysDisks; jj++ ) {
-                                                       if ( pIoc3->PhysDisk[jj].PhysDiskID == id )
-                                                               goto next_id;
-                                               }
-                                       }
-                               }
-                               if ( (vdev = hd->Targets[id]) ) {
-                                       for (jj = 0; jj <= MPT_LAST_LUN; jj++) {
-                                               lun_index = (jj >> 5);
-                                               indexed_lun = (jj % 32);
-                                               lun = (1 << indexed_lun);
-                                               if (vdev->luns[lun_index] & lun) {
-                                                       if (maxWordsLeft <= 0) {
-                                                               printk(KERN_ERR "mptctl_gettargetinfo - "
-                       "buffer is full but more targets are available on ioc %d numDevices=%d\n", iocnum, numDevices);
-                                                               goto data_space_full;
-                                                       }
-                                                       bus_id = vdev->bus_id;
-                                                       numDevices++;
-                                                       *pdata = ( (jj << 16) | (bus_id << 8) | id );
-                                                       dctlprintk((KERN_ERR "mptctl_gettargetinfo - "
-               "target ioc=%d target=%x numDevices=%d pdata=%p\n", iocnum, *pdata, numDevices, pdata));
-                                                       pdata++;
-                                                       --maxWordsLeft;
-                                               }
-                                       }
-                               }
-next_id:
-                               id++;
-                       }
+       if (ioc->sh){
+               shost_for_each_device(sdev, ioc->sh) {
+                       if (!maxWordsLeft)
+                               continue;
+                       vdev = sdev->hostdata;
+                       if (vdev->vtarget->tflags &
+                           MPT_TARGET_FLAGS_RAID_COMPONENT)
+                               continue;
+                       lun = (vdev->vtarget->raidVolume) ? 0x80 : vdev->lun;
+                       *pdata = (((u8)lun << 16) + (vdev->vtarget->channel << 8) +
+                           (vdev->vtarget->id ));
+                       pdata++;
+                       numDevices++;
+                       --maxWordsLeft;
                }
        }
-data_space_full:
        karg.numDevices = numDevices;
 
        /* Copy part of the data from kernel memory to user memory
@@ -1820,6 +1754,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
        int             msgContext;
        u16             req_idx;
        ulong           timeout;
+       struct scsi_device *sdev;
 
        dctlprintk(("mptctl_do_mpt_command called.\n"));
        bufIn.kptr = bufOut.kptr = NULL;
@@ -1901,14 +1836,13 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
        case MPI_FUNCTION_SCSI_IO_REQUEST:
                if (ioc->sh) {
                        SCSIIORequest_t *pScsiReq = (SCSIIORequest_t *) mf;
-                       VirtTarget      *pTarget = NULL;
-                       MPT_SCSI_HOST   *hd = NULL;
                        int qtag = MPI_SCSIIO_CONTROL_UNTAGGED;
                        int scsidir = 0;
-                       int target = (int) pScsiReq->TargetID;
                        int dataSize;
+                       u32 id;
 
-                       if ((target < 0) || (target >= ioc->sh->max_id)) {
+                       id = (ioc->devices_per_bus == 0) ? 256 : ioc->devices_per_bus;
+                       if (pScsiReq->TargetID > id) {
                                printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
                                        "Target ID out of bounds. \n",
                                        __FILE__, __LINE__);
@@ -1916,6 +1850,14 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
                                goto done_free_mem;
                        }
 
+                       if (pScsiReq->Bus >= ioc->number_of_buses) {
+                               printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
+                                       "Target Bus out of bounds. \n",
+                                       __FILE__, __LINE__);
+                               rc = -ENODEV;
+                               goto done_free_mem;
+                       }
+
                        pScsiReq->MsgFlags &= ~MPI_SCSIIO_MSGFLGS_SENSE_WIDTH;
                        pScsiReq->MsgFlags |= mpt_msg_flags();
 
@@ -1935,13 +1877,15 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
                                cpu_to_le32(ioc->sense_buf_low_dma
                                   + (req_idx * MPT_SENSE_BUFFER_ALLOC));
 
-                       if ((hd = (MPT_SCSI_HOST *) ioc->sh->hostdata)) {
-                               if (hd->Targets)
-                                       pTarget = hd->Targets[target];
-                       }
+                       shost_for_each_device(sdev, ioc->sh) {
+                               struct scsi_target *starget = scsi_target(sdev);
+                               VirtTarget *vtarget = starget->hostdata;
 
-                       if (pTarget &&(pTarget->tflags & MPT_TARGET_FLAGS_Q_YES))
-                               qtag = MPI_SCSIIO_CONTROL_SIMPLEQ;
+                               if ((pScsiReq->TargetID == vtarget->id) &&
+                                   (pScsiReq->Bus == vtarget->channel) &&
+                                   (vtarget->tflags & MPT_TARGET_FLAGS_Q_YES))
+                                       qtag = MPI_SCSIIO_CONTROL_SIMPLEQ;
+                       }
 
                        /* Have the IOCTL driver set the direction based
                         * on the dataOutSize (ordering issue with Sparc).
@@ -1958,7 +1902,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
                        pScsiReq->DataLength = cpu_to_le32(dataSize);
 
                        ioc->ioctl->reset = MPTCTL_RESET_OK;
-                       ioc->ioctl->target = target;
+                       ioc->ioctl->id = pScsiReq->TargetID;
 
                } else {
                        printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
@@ -2037,7 +1981,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
                        pScsiReq->DataLength = cpu_to_le32(dataSize);
 
                        ioc->ioctl->reset = MPTCTL_RESET_OK;
-                       ioc->ioctl->target = pScsiReq->TargetID;
+                       ioc->ioctl->id = pScsiReq->TargetID;
                } else {
                        printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
                                "SCSI driver is not loaded. \n",
@@ -2718,7 +2662,7 @@ mptctl_hp_targetinfo(unsigned long arg)
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 
-static struct file_operations mptctl_fops = {
+static const struct file_operations mptctl_fops = {
        .owner =        THIS_MODULE,
        .llseek =       no_llseek,
        .release =      mptctl_release,