Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 793955f5 authored by Eric Moore's avatar Eric Moore Committed by James Bottomley
Browse files

[SCSI] fusion - Greater than 255 target and lun support



Add support for greater than 255 target and luns.
Kill the hd->Target[] field, and change all references
of bus_id/target_id, to channel/id.

Signed-off-by: default avatarEric Moore <Eric.Moore@lsi.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent 502c62f1
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@
#EXTRA_CFLAGS += -DMPT_DEBUG_INIT
#EXTRA_CFLAGS += -DMPT_DEBUG_EXIT
#EXTRA_CFLAGS += -DMPT_DEBUG_FAIL
#EXTRA_CFLAGS += -DMPT_DEBUG_TM

#
# driver/module specifics...
@@ -22,7 +23,6 @@
#  For mptscsih:
#CFLAGS_mptscsih.o += -DMPT_DEBUG_DV
#CFLAGS_mptscsih.o += -DMPT_DEBUG_NEGO
#CFLAGS_mptscsih.o += -DMPT_DEBUG_TM
#CFLAGS_mptscsih.o += -DMPT_DEBUG_SCSI
#CFLAGS_mptscsih.o += -DMPT_DEBUG_REPLY
#
+22 −7
Original line number Diff line number Diff line
@@ -82,6 +82,10 @@ static int mpt_msi_enable;
module_param(mpt_msi_enable, int, 0);
MODULE_PARM_DESC(mpt_msi_enable, " MSI Support Enable (default=0)");

static int mpt_channel_mapping;
module_param(mpt_channel_mapping, int, 0);
MODULE_PARM_DESC(mpt_channel_mapping, " Mapping id's to channels (default=0)");

#ifdef MFCNT
static int mfcounter = 0;
#define PRINT_MF_COUNT 20000
@@ -2505,6 +2509,7 @@ GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
	int			 ii;
	int			 req_sz;
	int			 reply_sz;
	int			 max_id;

	/* IOC *must* NOT be in RESET state! */
	if (ioc->last_state == MPI_IOC_STATE_RESET) {
@@ -2552,6 +2557,21 @@ GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
	pfacts->MaxPersistentIDs = le16_to_cpu(pfacts->MaxPersistentIDs);
	pfacts->MaxLanBuckets = le16_to_cpu(pfacts->MaxLanBuckets);

	max_id = (ioc->bus_type == SAS) ? pfacts->PortSCSIID :
	    pfacts->MaxDevices;
	ioc->devices_per_bus = (max_id > 255) ? 256 : max_id;
	ioc->number_of_buses = (ioc->devices_per_bus < 256) ? 1 : max_id/256;

	/*
	 * Place all the devices on channels
	 *
	 * (for debuging)
	 */
	if (mpt_channel_mapping) {
		ioc->devices_per_bus = 1;
		ioc->number_of_buses = (max_id > 255) ? 255 : max_id;
	}

	return 0;
}

@@ -2592,13 +2612,8 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepFlag)
	ddlprintk((MYIOC_s_INFO_FMT "upload_fw %d facts.Flags=%x\n",
		   ioc->name, ioc->upload_fw, ioc->facts.Flags));

	if(ioc->bus_type == SAS)
		ioc_init.MaxDevices = ioc->facts.MaxDevices;
	else if(ioc->bus_type == FC)
		ioc_init.MaxDevices = MPT_MAX_FC_DEVICES;
	else
		ioc_init.MaxDevices = MPT_MAX_SCSI_DEVICES;
	ioc_init.MaxBuses = MPT_MAX_BUS;
	ioc_init.MaxDevices = (U8)ioc->devices_per_bus;
	ioc_init.MaxBuses = (U8)ioc->number_of_buses;
	dinitprintk((MYIOC_s_INFO_FMT "facts.MsgVersion=%x\n",
		   ioc->name, ioc->facts.MsgVersion));
	if (ioc->facts.MsgVersion >= MPI_VERSION_01_05) {
+6 −6
Original line number Diff line number Diff line
@@ -334,8 +334,8 @@ typedef struct _VirtTarget {
	struct scsi_target	*starget;
	u8			 tflags;
	u8			 ioc_id;
	u8			 target_id;
	u8			 bus_id;
	u8			 id;
	u8			 channel;
	u8			 minSyncFactor;	/* 0xFF is async */
	u8			 maxOffset;	/* 0 if async */
	u8			 maxWidth;	/* 0 if narrow, 1 if wide */
@@ -344,13 +344,12 @@ typedef struct _VirtTarget {
	u8			 type;		/* byte 0 of Inquiry data */
	u8			 deleted;	/* target in process of being removed */
	u32			 num_luns;
	u32			 luns[8];		/* Max LUNs is 256 */
} VirtTarget;

typedef struct _VirtDevice {
	VirtTarget		*vtarget;
	u8			 configured_lun;
	u32			 lun;
	int			 lun;
} VirtDevice;

/*
@@ -412,7 +411,7 @@ typedef struct _MPT_IOCTL {
	u8			 rsvd;
	u8			 status;	/* current command status */
	u8			 reset;		/* 1 if bus reset allowed */
	u8			 target;	/* target for reset */
	u8			 id;		/* target for reset */
	struct mutex		 ioctl_mutex;
} MPT_IOCTL;

@@ -528,6 +527,8 @@ typedef struct _MPT_ADAPTER
	u32			 mem_phys;	/* == f4020000 (mmap) */
	u32			 pio_mem_phys;	/* Programmed IO (downloadboot) */
	int			 mem_size;	/* mmap memory size */
	int			 number_of_buses;
	int			 devices_per_bus;
	int			 alloc_total;
	u32			 last_state;
	int			 active;
@@ -957,7 +958,6 @@ typedef struct _MPT_SCSI_HOST {
	int			  port;
	u32			  pad0;
	struct scsi_cmnd	**ScsiLookup;
	VirtTarget		**Targets;
	MPT_LOCAL_REPLY		 *pLocal;		/* used for internal commands */
	struct timer_list	  timer;
		/* Pool of memory for holding SCpnts before doing
+51 −108
Original line number Diff line number Diff line
@@ -361,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;
@@ -1159,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
@@ -1257,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
	 */
@@ -1319,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))) {
@@ -1389,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));
	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++;
						--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++;
			}
		}
	}
data_space_full:
	karg.numDevices = numDevices;

	/* Copy part of the data from kernel memory to user memory
@@ -1821,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;
@@ -1902,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__);
@@ -1917,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();

@@ -1936,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))
				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).
@@ -1959,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 - "
@@ -2038,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",
+21 −30
Original line number Diff line number Diff line
@@ -86,6 +86,12 @@ MODULE_PARM_DESC(mptfc_dev_loss_tmo, " Initial time the driver programs the "
				     " return following a device loss event."
				     "  Default=60.");

/* scsi-mid layer global parmeter is max_report_luns, which is 511 */
#define MPTFC_MAX_LUN (16895)
static int max_lun = MPTFC_MAX_LUN;
module_param(max_lun, int, 0);
MODULE_PARM_DESC(max_lun, " max lun, default=16895 ");

static int	mptfcDoneCtx = -1;
static int	mptfcTaskCtx = -1;
static int	mptfcInternalCtx = -1; /* Used only for internal commands */
@@ -292,10 +298,9 @@ mptfc_GetFcDevPage0(MPT_ADAPTER *ioc, int ioc_port,
	U32			 port_id = 0xffffff;
	int			 num_targ = 0;
	int			 max_bus = ioc->facts.MaxBuses;
	int			 max_targ = ioc->facts.MaxDevices;
	int			 max_targ;

	if (max_bus == 0 || max_targ == 0)
		goto out;
	max_targ = (ioc->facts.MaxDevices == 0) ? 256 : ioc->facts.MaxDevices;

	data_sz = sizeof(FCDevicePage0_t) * max_bus * max_targ;
	p_p0 = p0_array =  kzalloc(data_sz, GFP_KERNEL);
@@ -467,8 +472,8 @@ mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
			if (ri->starget) {
				vtarget = ri->starget->hostdata;
				if (vtarget) {
					vtarget->target_id = pg0->CurrentTargetID;
					vtarget->bus_id = pg0->CurrentBus;
					vtarget->id = pg0->CurrentTargetID;
					vtarget->channel = pg0->CurrentBus;
				}
			}
			*((struct mptfc_rport_info **)rport->dd_data) = ri;
@@ -540,8 +545,8 @@ mptfc_target_alloc(struct scsi_target *starget)
	if (rport) {
		ri = *((struct mptfc_rport_info **)rport->dd_data);
		if (ri) {	/* better be! */
			vtarget->target_id = ri->pg0.CurrentTargetID;
			vtarget->bus_id = ri->pg0.CurrentBus;
			vtarget->id = ri->pg0.CurrentTargetID;
			vtarget->channel = ri->pg0.CurrentBus;
			ri->starget = starget;
			rc = 0;
		}
@@ -592,7 +597,6 @@ mptfc_slave_alloc(struct scsi_device *sdev)
	if (vtarget->num_luns == 0) {
		vtarget->ioc_id = hd->ioc->id;
		vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
		hd->Targets[sdev->id] = vtarget;
	}

	vdev->vtarget = vtarget;
@@ -630,16 +634,17 @@ mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
	struct mptfc_rport_info	*ri;
	struct fc_rport	*rport = starget_to_rport(scsi_target(SCpnt->device));
	int		err;
	VirtDevice	*vdev = SCpnt->device->hostdata;

	err = fc_remote_port_chkready(rport);
	if (unlikely(err)) {
		SCpnt->result = err;
	if (!vdev || !vdev->vtarget) {
		SCpnt->result = DID_NO_CONNECT << 16;
		done(SCpnt);
		return 0;
	}

	if (!SCpnt->device->hostdata) {	/* vdev */
		SCpnt->result = DID_NO_CONNECT << 16;
	err = fc_remote_port_chkready(rport);
	if (unlikely(err)) {
		SCpnt->result = err;
		done(SCpnt);
		return 0;
	}
@@ -1143,7 +1148,7 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
		printk(MYIOC_s_WARN_FMT
			"Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n",
			ioc->name, ioc);
		return -ENODEV;
		return 0;
	}

	sh = scsi_host_alloc(&mptfc_driver_template, sizeof(MPT_SCSI_HOST));
@@ -1173,10 +1178,9 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
	/* set 16 byte cdb's */
	sh->max_cmd_len = 16;

	sh->max_id = MPT_MAX_FC_DEVICES<256 ? MPT_MAX_FC_DEVICES : 255;
	sh->max_id = ioc->pfacts->MaxDevices;
	sh->max_lun = max_lun;

	sh->max_lun = MPT_LAST_LUN + 1;
	sh->max_channel = 0;
	sh->this_id = ioc->pfacts[0].PortSCSIID;

	/* Required entry.
@@ -1230,19 +1234,6 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
	dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
		 ioc->name, hd->ScsiLookup));

	/* Allocate memory for the device structures.
	 * A non-Null pointer at an offset
	 * indicates a device exists.
	 * max_id = 1 + maximum id (hosts.h)
	 */
	hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC);
	if (!hd->Targets) {
		error = -ENOMEM;
		goto out_mptfc_probe;
	}

	dprintk((KERN_INFO "  vdev @ %p\n", hd->Targets));

	/* Clear the TM flags
	 */
	hd->tmPending = 0;
Loading