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

[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
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#EXTRA_CFLAGS += -DMPT_DEBUG_INIT #EXTRA_CFLAGS += -DMPT_DEBUG_INIT
#EXTRA_CFLAGS += -DMPT_DEBUG_EXIT #EXTRA_CFLAGS += -DMPT_DEBUG_EXIT
#EXTRA_CFLAGS += -DMPT_DEBUG_FAIL #EXTRA_CFLAGS += -DMPT_DEBUG_FAIL
#EXTRA_CFLAGS += -DMPT_DEBUG_TM
# #
# driver/module specifics... # driver/module specifics...
...@@ -22,7 +23,6 @@ ...@@ -22,7 +23,6 @@
# For mptscsih: # For mptscsih:
#CFLAGS_mptscsih.o += -DMPT_DEBUG_DV #CFLAGS_mptscsih.o += -DMPT_DEBUG_DV
#CFLAGS_mptscsih.o += -DMPT_DEBUG_NEGO #CFLAGS_mptscsih.o += -DMPT_DEBUG_NEGO
#CFLAGS_mptscsih.o += -DMPT_DEBUG_TM
#CFLAGS_mptscsih.o += -DMPT_DEBUG_SCSI #CFLAGS_mptscsih.o += -DMPT_DEBUG_SCSI
#CFLAGS_mptscsih.o += -DMPT_DEBUG_REPLY #CFLAGS_mptscsih.o += -DMPT_DEBUG_REPLY
# #
......
...@@ -82,6 +82,10 @@ static int mpt_msi_enable; ...@@ -82,6 +82,10 @@ static int mpt_msi_enable;
module_param(mpt_msi_enable, int, 0); module_param(mpt_msi_enable, int, 0);
MODULE_PARM_DESC(mpt_msi_enable, " MSI Support Enable (default=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 #ifdef MFCNT
static int mfcounter = 0; static int mfcounter = 0;
#define PRINT_MF_COUNT 20000 #define PRINT_MF_COUNT 20000
...@@ -2505,6 +2509,7 @@ GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag) ...@@ -2505,6 +2509,7 @@ GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
int ii; int ii;
int req_sz; int req_sz;
int reply_sz; int reply_sz;
int max_id;
/* IOC *must* NOT be in RESET state! */ /* IOC *must* NOT be in RESET state! */
if (ioc->last_state == MPI_IOC_STATE_RESET) { if (ioc->last_state == MPI_IOC_STATE_RESET) {
...@@ -2552,6 +2557,21 @@ GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag) ...@@ -2552,6 +2557,21 @@ GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
pfacts->MaxPersistentIDs = le16_to_cpu(pfacts->MaxPersistentIDs); pfacts->MaxPersistentIDs = le16_to_cpu(pfacts->MaxPersistentIDs);
pfacts->MaxLanBuckets = le16_to_cpu(pfacts->MaxLanBuckets); 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; return 0;
} }
...@@ -2592,13 +2612,8 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepFlag) ...@@ -2592,13 +2612,8 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepFlag)
ddlprintk((MYIOC_s_INFO_FMT "upload_fw %d facts.Flags=%x\n", ddlprintk((MYIOC_s_INFO_FMT "upload_fw %d facts.Flags=%x\n",
ioc->name, ioc->upload_fw, ioc->facts.Flags)); ioc->name, ioc->upload_fw, ioc->facts.Flags));
if(ioc->bus_type == SAS) ioc_init.MaxDevices = (U8)ioc->devices_per_bus;
ioc_init.MaxDevices = ioc->facts.MaxDevices; ioc_init.MaxBuses = (U8)ioc->number_of_buses;
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;
dinitprintk((MYIOC_s_INFO_FMT "facts.MsgVersion=%x\n", dinitprintk((MYIOC_s_INFO_FMT "facts.MsgVersion=%x\n",
ioc->name, ioc->facts.MsgVersion)); ioc->name, ioc->facts.MsgVersion));
if (ioc->facts.MsgVersion >= MPI_VERSION_01_05) { if (ioc->facts.MsgVersion >= MPI_VERSION_01_05) {
......
...@@ -334,8 +334,8 @@ typedef struct _VirtTarget { ...@@ -334,8 +334,8 @@ typedef struct _VirtTarget {
struct scsi_target *starget; struct scsi_target *starget;
u8 tflags; u8 tflags;
u8 ioc_id; u8 ioc_id;
u8 target_id; u8 id;
u8 bus_id; u8 channel;
u8 minSyncFactor; /* 0xFF is async */ u8 minSyncFactor; /* 0xFF is async */
u8 maxOffset; /* 0 if async */ u8 maxOffset; /* 0 if async */
u8 maxWidth; /* 0 if narrow, 1 if wide */ u8 maxWidth; /* 0 if narrow, 1 if wide */
...@@ -344,13 +344,12 @@ typedef struct _VirtTarget { ...@@ -344,13 +344,12 @@ typedef struct _VirtTarget {
u8 type; /* byte 0 of Inquiry data */ u8 type; /* byte 0 of Inquiry data */
u8 deleted; /* target in process of being removed */ u8 deleted; /* target in process of being removed */
u32 num_luns; u32 num_luns;
u32 luns[8]; /* Max LUNs is 256 */
} VirtTarget; } VirtTarget;
typedef struct _VirtDevice { typedef struct _VirtDevice {
VirtTarget *vtarget; VirtTarget *vtarget;
u8 configured_lun; u8 configured_lun;
u32 lun; int lun;
} VirtDevice; } VirtDevice;
/* /*
...@@ -412,7 +411,7 @@ typedef struct _MPT_IOCTL { ...@@ -412,7 +411,7 @@ typedef struct _MPT_IOCTL {
u8 rsvd; u8 rsvd;
u8 status; /* current command status */ u8 status; /* current command status */
u8 reset; /* 1 if bus reset allowed */ u8 reset; /* 1 if bus reset allowed */
u8 target; /* target for reset */ u8 id; /* target for reset */
struct mutex ioctl_mutex; struct mutex ioctl_mutex;
} MPT_IOCTL; } MPT_IOCTL;
...@@ -528,6 +527,8 @@ typedef struct _MPT_ADAPTER ...@@ -528,6 +527,8 @@ typedef struct _MPT_ADAPTER
u32 mem_phys; /* == f4020000 (mmap) */ u32 mem_phys; /* == f4020000 (mmap) */
u32 pio_mem_phys; /* Programmed IO (downloadboot) */ u32 pio_mem_phys; /* Programmed IO (downloadboot) */
int mem_size; /* mmap memory size */ int mem_size; /* mmap memory size */
int number_of_buses;
int devices_per_bus;
int alloc_total; int alloc_total;
u32 last_state; u32 last_state;
int active; int active;
...@@ -957,7 +958,6 @@ typedef struct _MPT_SCSI_HOST { ...@@ -957,7 +958,6 @@ typedef struct _MPT_SCSI_HOST {
int port; int port;
u32 pad0; u32 pad0;
struct scsi_cmnd **ScsiLookup; struct scsi_cmnd **ScsiLookup;
VirtTarget **Targets;
MPT_LOCAL_REPLY *pLocal; /* used for internal commands */ MPT_LOCAL_REPLY *pLocal; /* used for internal commands */
struct timer_list timer; struct timer_list timer;
/* Pool of memory for holding SCpnts before doing /* Pool of memory for holding SCpnts before doing
......
...@@ -361,7 +361,7 @@ static int mptctl_bus_reset(MPT_IOCTL *ioctl) ...@@ -361,7 +361,7 @@ static int mptctl_bus_reset(MPT_IOCTL *ioctl)
ioctl->ioc->name, mf)); ioctl->ioc->name, mf));
pScsiTm = (SCSITaskMgmt_t *) mf; pScsiTm = (SCSITaskMgmt_t *) mf;
pScsiTm->TargetID = ioctl->target; pScsiTm->TargetID = ioctl->id;
pScsiTm->Bus = hd->port; /* 0 */ pScsiTm->Bus = hd->port; /* 0 */
pScsiTm->ChainOffset = 0; pScsiTm->ChainOffset = 0;
pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT; pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
...@@ -1159,15 +1159,12 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size) ...@@ -1159,15 +1159,12 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size)
struct mpt_ioctl_iocinfo *karg; struct mpt_ioctl_iocinfo *karg;
MPT_ADAPTER *ioc; MPT_ADAPTER *ioc;
struct pci_dev *pdev; struct pci_dev *pdev;
struct Scsi_Host *sh;
MPT_SCSI_HOST *hd;
int iocnum; int iocnum;
int numDevices = 0;
unsigned int max_id;
int ii;
unsigned int port; unsigned int port;
int cim_rev; int cim_rev;
u8 revision; u8 revision;
struct scsi_device *sdev;
VirtDevice *vdev;
dctlprintk((": mptctl_getiocinfo called.\n")); dctlprintk((": mptctl_getiocinfo called.\n"));
/* Add of PCI INFO results in unaligned access for /* Add of PCI INFO results in unaligned access for
...@@ -1257,23 +1254,16 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size) ...@@ -1257,23 +1254,16 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size)
/* Get number of devices /* Get number of devices
*/ */
if ((sh = ioc->sh) != NULL) { karg->numDevices = 0;
/* sh->max_id = maximum target ID + 1 if (ioc->sh) {
*/ shost_for_each_device(sdev, ioc->sh) {
max_id = sh->max_id - 1; vdev = sdev->hostdata;
hd = (MPT_SCSI_HOST *) sh->hostdata; if (vdev->vtarget->tflags &
MPT_TARGET_FLAGS_RAID_COMPONENT)
/* Check all of the target structures and continue;
* keep a counter. karg->numDevices++;
*/
if (hd && hd->Targets) {
for (ii = 0; ii <= max_id; ii++) {
if (hd->Targets[ii])
numDevices++;
}
} }
} }
karg->numDevices = numDevices;
/* Set the BIOS and FW Version /* Set the BIOS and FW Version
*/ */
...@@ -1319,21 +1309,16 @@ mptctl_gettargetinfo (unsigned long arg) ...@@ -1319,21 +1309,16 @@ mptctl_gettargetinfo (unsigned long arg)
struct mpt_ioctl_targetinfo __user *uarg = (void __user *) arg; struct mpt_ioctl_targetinfo __user *uarg = (void __user *) arg;
struct mpt_ioctl_targetinfo karg; struct mpt_ioctl_targetinfo karg;
MPT_ADAPTER *ioc; MPT_ADAPTER *ioc;
struct Scsi_Host *sh; VirtDevice *vdev;
MPT_SCSI_HOST *hd;
VirtTarget *vdev;
char *pmem; char *pmem;
int *pdata; int *pdata;
IOCPage2_t *pIoc2;
IOCPage3_t *pIoc3;
int iocnum; int iocnum;
int numDevices = 0; int numDevices = 0;
unsigned int max_id; int lun;
int id, jj, indexed_lun, lun_index;
u32 lun;
int maxWordsLeft; int maxWordsLeft;
int numBytes; int numBytes;
u8 port, devType, bus_id; u8 port;
struct scsi_device *sdev;
dctlprintk(("mptctl_gettargetinfo called.\n")); dctlprintk(("mptctl_gettargetinfo called.\n"));
if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_targetinfo))) { if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_targetinfo))) {
...@@ -1389,74 +1374,22 @@ mptctl_gettargetinfo (unsigned long arg) ...@@ -1389,74 +1374,22 @@ mptctl_gettargetinfo (unsigned long arg)
/* Get number of devices /* Get number of devices
*/ */
if ((sh = ioc->sh) != NULL) { if (ioc->sh){
shost_for_each_device(sdev, ioc->sh) {
max_id = sh->max_id - 1; if (!maxWordsLeft)
hd = (MPT_SCSI_HOST *) sh->hostdata; continue;
vdev = sdev->hostdata;
/* Check all of the target structures. if (vdev->vtarget->tflags &
* Save the Id and increment the counter, MPT_TARGET_FLAGS_RAID_COMPONENT)
* if ptr non-null. continue;
* sh->max_id = maximum target ID + 1 lun = (vdev->vtarget->raidVolume) ? 0x80 : vdev->lun;
*/ *pdata = (((u8)lun << 16) + (vdev->vtarget->channel << 8) +
if (hd && hd->Targets) { (vdev->vtarget->id ));
mpt_findImVolumes(ioc); pdata++;
pIoc2 = ioc->raid_data.pIocPg2; numDevices++;
for ( id = 0; id <= max_id; ) { --maxWordsLeft;
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++;
}
} }
} }
data_space_full:
karg.numDevices = numDevices; karg.numDevices = numDevices;
/* Copy part of the data from kernel memory to user memory /* 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) ...@@ -1821,6 +1754,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
int msgContext; int msgContext;
u16 req_idx; u16 req_idx;
ulong timeout; ulong timeout;
struct scsi_device *sdev;
dctlprintk(("mptctl_do_mpt_command called.\n")); dctlprintk(("mptctl_do_mpt_command called.\n"));
bufIn.kptr = bufOut.kptr = NULL; bufIn.kptr = bufOut.kptr = NULL;
...@@ -1902,14 +1836,13 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) ...@@ -1902,14 +1836,13 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
case MPI_FUNCTION_SCSI_IO_REQUEST: case MPI_FUNCTION_SCSI_IO_REQUEST:
if (ioc->sh) { if (ioc->sh) {
SCSIIORequest_t *pScsiReq = (SCSIIORequest_t *) mf; SCSIIORequest_t *pScsiReq = (SCSIIORequest_t *) mf;
VirtTarget *pTarget = NULL;
MPT_SCSI_HOST *hd = NULL;
int qtag = MPI_SCSIIO_CONTROL_UNTAGGED; int qtag = MPI_SCSIIO_CONTROL_UNTAGGED;
int scsidir = 0; int scsidir = 0;
int target = (int) pScsiReq->TargetID;
int dataSize; 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 - " printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
"Target ID out of bounds. \n", "Target ID out of bounds. \n",
__FILE__, __LINE__); __FILE__, __LINE__);
...@@ -1917,6 +1850,14 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) ...@@ -1917,6 +1850,14 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
goto done_free_mem; 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 &= ~MPI_SCSIIO_MSGFLGS_SENSE_WIDTH;
pScsiReq->MsgFlags |= mpt_msg_flags(); pScsiReq->MsgFlags |= mpt_msg_flags();
...@@ -1936,13 +1877,15 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) ...@@ -1936,13 +1877,15 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
cpu_to_le32(ioc->sense_buf_low_dma cpu_to_le32(ioc->sense_buf_low_dma
+ (req_idx * MPT_SENSE_BUFFER_ALLOC)); + (req_idx * MPT_SENSE_BUFFER_ALLOC));
if ((hd = (MPT_SCSI_HOST *) ioc->sh->hostdata)) { shost_for_each_device(sdev, ioc->sh) {
if (hd->Targets) struct scsi_target *starget = scsi_target(sdev);
pTarget = hd->Targets[target]; VirtTarget *vtarget = starget->hostdata;
}
if (pTarget &&(pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)) if ((pScsiReq->TargetID == vtarget->id) &&
qtag = MPI_SCSIIO_CONTROL_SIMPLEQ; (pScsiReq->Bus == vtarget->channel) &&
(vtarget->tflags & MPT_TARGET_FLAGS_Q_YES))
qtag = MPI_SCSIIO_CONTROL_SIMPLEQ;
}
/* Have the IOCTL driver set the direction based /* Have the IOCTL driver set the direction based
* on the dataOutSize (ordering issue with Sparc). * on the dataOutSize (ordering issue with Sparc).
...@@ -1959,7 +1902,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) ...@@ -1959,7 +1902,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
pScsiReq->DataLength = cpu_to_le32(dataSize); pScsiReq->DataLength = cpu_to_le32(dataSize);
ioc->ioctl->reset = MPTCTL_RESET_OK; ioc->ioctl->reset = MPTCTL_RESET_OK;
ioc->ioctl->target = target; ioc->ioctl->id = pScsiReq->TargetID;
} else { } else {
printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " 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) ...@@ -2038,7 +1981,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
pScsiReq->DataLength = cpu_to_le32(dataSize); pScsiReq->DataLength = cpu_to_le32(dataSize);
ioc->ioctl->reset = MPTCTL_RESET_OK; ioc->ioctl->reset = MPTCTL_RESET_OK;
ioc->ioctl->target = pScsiReq->TargetID; ioc->ioctl->id = pScsiReq->TargetID;
} else { } else {
printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
"SCSI driver is not loaded. \n", "SCSI driver is not loaded. \n",
......
...@@ -86,6 +86,12 @@ MODULE_PARM_DESC(mptfc_dev_loss_tmo, " Initial time the driver programs the " ...@@ -86,6 +86,12 @@ MODULE_PARM_DESC(mptfc_dev_loss_tmo, " Initial time the driver programs the "
" return following a device loss event." " return following a device loss event."
" Default=60."); " 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 mptfcDoneCtx = -1;
static int mptfcTaskCtx = -1; static int mptfcTaskCtx = -1;
static int mptfcInternalCtx = -1; /* Used only for internal commands */ static int mptfcInternalCtx = -1; /* Used only for internal commands */
...@@ -292,10 +298,9 @@ mptfc_GetFcDevPage0(MPT_ADAPTER *ioc, int ioc_port, ...@@ -292,10 +298,9 @@ mptfc_GetFcDevPage0(MPT_ADAPTER *ioc, int ioc_port,
U32 port_id = 0xffffff; U32 port_id = 0xffffff;
int num_targ = 0; int num_targ = 0;
int max_bus = ioc->facts.MaxBuses; int max_bus = ioc->facts.MaxBuses;
int max_targ = ioc->facts.MaxDevices; int max_targ;
if (max_bus == 0 || max_targ == 0) max_targ = (ioc->facts.MaxDevices == 0) ? 256 : ioc->facts.MaxDevices;
goto out;
data_sz = sizeof(FCDevicePage0_t) * max_bus * max_targ; data_sz = sizeof(FCDevicePage0_t) * max_bus * max_targ;
p_p0 = p0_array = kzalloc(data_sz, GFP_KERNEL); p_p0 = p0_array = kzalloc(data_sz, GFP_KERNEL);
...@@ -467,8 +472,8 @@ mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0) ...@@ -467,8 +472,8 @@ mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
if (ri->starget) { if (ri->starget) {
vtarget = ri->starget->hostdata; vtarget = ri->starget->hostdata;
if (vtarget) { if (vtarget) {
vtarget->target_id = pg0->CurrentTargetID; vtarget->id = pg0->CurrentTargetID;
vtarget->bus_id = pg0->CurrentBus; vtarget->channel = pg0->CurrentBus;
} }
} }
*((struct mptfc_rport_info **)rport->dd_data) = ri; *((struct mptfc_rport_info **)rport->dd_data) = ri;
...@@ -540,8 +545,8 @@ mptfc_target_alloc(struct scsi_target *starget) ...@@ -540,8 +545,8 @@ mptfc_target_alloc(struct scsi_target *starget)
if (rport) { if (rport) {
ri = *((struct mptfc_rport_info **)rport->dd_data); ri = *((struct mptfc_rport_info **)rport->dd_data);
if (ri) { /* better be! */ if (ri) { /* better be! */
vtarget->target_id = ri->pg0.CurrentTargetID; vtarget->id = ri->pg0.CurrentTargetID;
vtarget->bus_id = ri->pg0.CurrentBus; vtarget->channel = ri->pg0.CurrentBus;
ri->starget = starget; ri->starget = starget;
rc = 0; rc = 0;
} }
...@@ -592,7 +597,6 @@ mptfc_slave_alloc(struct scsi_device *sdev) ...@@ -592,7 +597,6 @@ mptfc_slave_alloc(struct scsi_device *sdev)
if (vtarget->num_luns == 0) { if (vtarget->num_luns == 0) {
vtarget->ioc_id = hd->ioc->id; vtarget->ioc_id = hd->ioc->id;
vtarget->tflags = MPT_TARGET_FLAGS_Q_YES; vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
hd->Targets[sdev->id] = vtarget;
} }
vdev->vtarget = vtarget; vdev->vtarget = vtarget;
...@@ -630,16 +634,17 @@ mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) ...@@ -630,16 +634,17 @@ mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
struct mptfc_rport_info *ri; struct mptfc_rport_info *ri;
struct fc_rport *rport = starget_to_rport(scsi_target(SCpnt->device)); struct fc_rport *rport = starget_to_rport(scsi_target(SCpnt->device));
int err; int err;
VirtDevice *vdev = SCpnt->device->hostdata;
err = fc_remote_port_chkready(rport); if (!vdev || !vdev->vtarget) {
if (unlikely(err)) { SCpnt->result = DID_NO_CONNECT << 16;
SCpnt->result = err;
done(SCpnt); done(SCpnt);
return 0; return 0;
} }
if (!SCpnt->device->hostdata) { /* vdev */ err = fc_remote_port_chkready(rport);
SCpnt->result = DID_NO_CONNECT << 16; if (unlikely(err)) {
SCpnt->result = err;
done(SCpnt); done(SCpnt);
return 0; return 0;
} }
...@@ -1143,7 +1148,7 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -1143,7 +1148,7 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
printk(MYIOC_s_WARN_FMT printk(MYIOC_s_WARN_FMT
"Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n", "Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n",
ioc->name, ioc); ioc->name, ioc);
return -ENODEV; return 0;
} }
sh = scsi_host_alloc(&mptfc_driver_template, sizeof(MPT_SCSI_HOST)); 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) ...@@ -1173,10 +1178,9 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
/* set 16 byte cdb's */ /* set 16 byte cdb's */
sh->max_cmd_len = 16; 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; sh->this_id = ioc->pfacts[0].PortSCSIID;
/* Required entry. /* Required entry.
...@@ -1230,19 +1234,6 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -1230,19 +1234,6 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n", dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
ioc->name, hd->ScsiLookup)); 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 /* Clear the TM flags
*/ */
hd->tmPending = 0; hd->tmPending = 0;
......
...@@ -83,6 +83,12 @@ MODULE_PARM_DESC(mpt_pt_clear, ...@@ -83,6 +83,12 @@ MODULE_PARM_DESC(mpt_pt_clear,
" Clear persistency table: enable=1 " " Clear persistency table: enable=1 "
"(default=MPTSCSIH_PT_CLEAR=0)"); "(default=MPTSCSIH_PT_CLEAR=0)");
/* scsi-mid layer global parmeter is max_report_luns, which is 511 */
#define MPTSAS_MAX_LUN (16895)
static int max_lun = MPTSAS_MAX_LUN;
module_param(max_lun, int, 0);
MODULE_PARM_DESC(max_lun, " max lun, default=16895 ");
static int mptsasDoneCtx = -1; static int mptsasDoneCtx = -1;
static int mptsasTaskCtx = -1; static int mptsasTaskCtx = -1;
static int mptsasInternalCtx = -1; /* Used only for internal commands */ static int mptsasInternalCtx = -1; /* Used only for internal commands */
...@@ -568,12 +574,12 @@ mptsas_target_reset(MPT_ADAPTER *ioc, VirtTarget * vtarget) ...@@ -568,12 +574,12 @@ mptsas_target_reset(MPT_ADAPTER *ioc, VirtTarget * vtarget)
if (mptscsih_TMHandler(hd, if (mptscsih_TMHandler(hd,
MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
vtarget->bus_id, vtarget->target_id, 0, 0, 5) < 0) { vtarget->channel, vtarget->id, 0, 0, 5) < 0) {
hd->tmPending = 0; hd->tmPending = 0;
hd->tmState = TM_STATE_NONE; hd->tmState = TM_STATE_NONE;
printk(MYIOC_s_WARN_FMT printk(MYIOC_s_WARN_FMT
"Error processing TaskMgmt id=%d TARGET_RESET\n", "Error processing TaskMgmt id=%d TARGET_RESET\n",
ioc->name, vtarget->target_id); ioc->name, vtarget->id);
} }
} }
...@@ -661,8 +667,7 @@ mptsas_target_alloc(struct scsi_target *starget) ...@@ -661,8 +667,7 @@ mptsas_target_alloc(struct scsi_target *starget)
struct Scsi_Host *host = dev_to_shost(&starget->dev); struct Scsi_Host *host = dev_to_shost(&starget->dev);
MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
VirtTarget *vtarget; VirtTarget *vtarget;
u32 target_id; u8 id, channel;
u32 channel;
struct sas_rphy *rphy; struct sas_rphy *rphy;
struct mptsas_portinfo *p; struct mptsas_portinfo *p;
int i; int i;
...@@ -673,15 +678,19 @@ mptsas_target_alloc(struct scsi_target *starget) ...@@ -673,15 +678,19 @@ mptsas_target_alloc(struct scsi_target *starget)
vtarget->starget = starget; vtarget->starget = starget;
vtarget->ioc_id = hd->ioc->id; vtarget->ioc_id = hd->ioc->id;
vtarget->tflags = MPT_TARGET_FLAGS_Q_YES|MPT_TARGET_FLAGS_VALID_INQUIRY; vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
id = starget->id;
target_id = starget->id;
channel = 0; channel = 0;
hd->Targets[target_id] = vtarget; /*
* RAID volumes placed beyond the last expected port.
if (starget->channel == MPTSAS_RAID_CHANNEL) */
if (starget->channel == MPTSAS_RAID_CHANNEL) {
for (i=0; i < hd->ioc->raid_data.pIocPg2->NumActiveVolumes; i++)
if (id == hd->ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID)
channel = hd->ioc->raid_data.pIocPg2->RaidVolume[i].VolumeBus;
goto out; goto out;
}
rphy = dev_to_rphy(starget->dev.parent); rphy = dev_to_rphy(starget->dev.parent);
mutex_lock(&hd->ioc->sas_topology_mutex); mutex_lock(&hd->ioc->sas_topology_mutex);
...@@ -690,16 +699,16 @@ mptsas_target_alloc(struct scsi_target *starget) ...@@ -690,16 +699,16 @@ mptsas_target_alloc(struct scsi_target *starget)
if (p->phy_info[i].attached.sas_address != if (p->phy_info[i].attached.sas_address !=
rphy->identify.sas_address) rphy->identify.sas_address)
continue; continue;
target_id = p->phy_info[i].attached.id; id = p->phy_info[i].attached.id;
channel = p->phy_info[i].attached.channel; channel = p->phy_info[i].attached.channel;
mptsas_set_starget(&p->phy_info[i], starget); mptsas_set_starget(&p->phy_info[i], starget);
/* /*
* Exposing hidden raid components * Exposing hidden raid components
*/ */
if (mptscsih_is_phys_disk(hd->ioc, target_id)) { if (mptscsih_is_phys_disk(hd->ioc, channel, id)) {
target_id = mptscsih_raid_id_to_num(hd, id = mptscsih_raid_id_to_num(hd->ioc,
target_id); channel, id);
vtarget->tflags |= vtarget->tflags |=
MPT_TARGET_FLAGS_RAID_COMPONENT; MPT_TARGET_FLAGS_RAID_COMPONENT;
} }
...@@ -713,8 +722,8 @@ mptsas_target_alloc(struct scsi_target *starget) ...@@ -713,8 +722,8 @@ mptsas_target_alloc(struct scsi_target *starget)
return -ENXIO; return -ENXIO;
out: out:
vtarget->target_id = target_id; vtarget->id = id;
vtarget->bus_id = channel; vtarget->channel = channel;
starget->hostdata = vtarget; starget->hostdata = vtarget;
return 0; return 0;
} }
...@@ -786,7 +795,8 @@ mptsas_slave_alloc(struct scsi_device *sdev) ...@@ -786,7 +795,8 @@ mptsas_slave_alloc(struct scsi_device *sdev)
* Exposing hidden raid components * Exposing hidden raid components
*/ */
if (mptscsih_is_phys_disk(hd->ioc, if (mptscsih_is_phys_disk(hd->ioc,
p->phy_info[i].attached.id)) p->phy_info[i].attached.channel,
p->phy_info[i].attached.id))
sdev->no_uld_attach = 1; sdev->no_uld_attach = 1;
mutex_unlock(&hd->ioc->sas_topology_mutex); mutex_unlock(&hd->ioc->sas_topology_mutex);
goto out; goto out;
...@@ -808,13 +818,14 @@ mptsas_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) ...@@ -808,13 +818,14 @@ mptsas_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
{ {
VirtDevice *vdev = SCpnt->device->hostdata; VirtDevice *vdev = SCpnt->device->hostdata;
// scsi_print_command(SCpnt); if (!vdev || !vdev->vtarget || vdev->vtarget->deleted) {
if (vdev->vtarget->deleted) {
SCpnt->result = DID_NO_CONNECT << 16; SCpnt->result = DID_NO_CONNECT << 16;
done(SCpnt); done(SCpnt);
return 0; return 0;
} }
// scsi_print_command(SCpnt);
return mptscsih_qcmd(SCpnt,done); return mptscsih_qcmd(SCpnt,done);
} }
...@@ -1976,7 +1987,7 @@ mptsas_scan_sas_topology(MPT_ADAPTER *ioc) ...@@ -1976,7 +1987,7 @@ mptsas_scan_sas_topology(MPT_ADAPTER *ioc)
goto out; goto out;
if (!ioc->raid_data.pIocPg2->NumActiveVolumes) if (!ioc->raid_data.pIocPg2->NumActiveVolumes)
goto out; goto out;
for (i=0; i<ioc->raid_data.pIocPg2->NumActiveVolumes; i++) { for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL, scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL,
ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0); ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0);
} }
...@@ -2160,7 +2171,7 @@ mptsas_hotplug_work(struct work_struct *work) ...@@ -2160,7 +2171,7 @@ mptsas_hotplug_work(struct work_struct *work)
* Handling RAID components * Handling RAID components
*/ */
if (ev->phys_disk_num_valid) { if (ev->phys_disk_num_valid) {
vtarget->target_id = ev->phys_disk_num; vtarget->id = ev->phys_disk_num;
vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT; vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT;
mptsas_reprobe_target(starget, 1); mptsas_reprobe_target(starget, 1);
break; break;
...@@ -2233,7 +2244,7 @@ mptsas_hotplug_work(struct work_struct *work) ...@@ -2233,7 +2244,7 @@ mptsas_hotplug_work(struct work_struct *work)
*/ */
if (vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) { if (vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
vtarget->tflags &= ~MPT_TARGET_FLAGS_RAID_COMPONENT; vtarget->tflags &= ~MPT_TARGET_FLAGS_RAID_COMPONENT;
vtarget->target_id = ev->id; vtarget->id = ev->id;
mptsas_reprobe_target(starget, 0); mptsas_reprobe_target(starget, 0);
} }
break; break;
...@@ -2611,12 +2622,11 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -2611,12 +2622,11 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
/* set 16 byte cdb's */ /* set 16 byte cdb's */
sh->max_cmd_len = 16; sh->max_cmd_len = 16;
sh->max_id = ioc->pfacts->MaxDevices + 1; sh->max_id = ioc->pfacts[0].PortSCSIID;
sh->max_lun = max_lun;
sh->transportt = mptsas_transport_template; sh->transportt = mptsas_transport_template;
sh->max_lun = MPT_LAST_LUN + 1;
sh->max_channel = 0;
sh->this_id = ioc->pfacts[0].PortSCSIID; sh->this_id = ioc->pfacts[0].PortSCSIID;
/* Required entry. /* Required entry.
...@@ -2676,19 +2686,6 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -2676,19 +2686,6 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n", dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
ioc->name, hd->ScsiLookup)); 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_mptsas_probe;
}
dprintk((KERN_INFO " vtarget @ %p\n", hd->Targets));
/* Clear the TM flags /* Clear the TM flags
*/ */
hd->tmPending = 0; hd->tmPending = 0;
......
This diff is collapsed.
...@@ -53,6 +53,24 @@ ...@@ -53,6 +53,24 @@
* SCSI Public stuff... * SCSI Public stuff...
*/ */
#define MPT_SCANDV_GOOD (0x00000000) /* must be 0 */
#define MPT_SCANDV_DID_RESET (0x00000001)
#define MPT_SCANDV_SENSE (0x00000002)
#define MPT_SCANDV_SOME_ERROR (0x00000004)
#define MPT_SCANDV_SELECTION_TIMEOUT (0x00000008)
#define MPT_SCANDV_ISSUE_SENSE (0x00000010)
#define MPT_SCANDV_FALLBACK (0x00000020)
#define MPT_SCANDV_MAX_RETRIES (10)
#define MPT_ICFLAG_BUF_CAP 0x01 /* ReadBuffer Read Capacity format */
#define MPT_ICFLAG_ECHO 0x02 /* ReadBuffer Echo buffer format */
#define MPT_ICFLAG_EBOS 0x04 /* ReadBuffer Echo buffer has EBOS */
#define MPT_ICFLAG_PHYS_DISK 0x08 /* Any SCSI IO but do Phys Disk Format */
#define MPT_ICFLAG_TAGGED_CMD 0x10 /* Do tagged IO */
#define MPT_ICFLAG_DID_RESET 0x20 /* Bus Reset occurred with this command */
#define MPT_ICFLAG_RESERVED 0x40 /* Reserved has been issued */
#define MPT_SCSI_CMD_PER_DEV_HIGH 64 #define MPT_SCSI_CMD_PER_DEV_HIGH 64
#define MPT_SCSI_CMD_PER_DEV_LOW 32 #define MPT_SCSI_CMD_PER_DEV_LOW 32
...@@ -69,9 +87,22 @@ ...@@ -69,9 +87,22 @@
#define MPTSCSIH_SAF_TE 0 #define MPTSCSIH_SAF_TE 0
#define MPTSCSIH_PT_CLEAR 0 #define MPTSCSIH_PT_CLEAR 0
#endif #endif
typedef struct _internal_cmd {
char *data; /* data pointer */
dma_addr_t data_dma; /* data dma address */
int size; /* transfer size */
u8 cmd; /* SCSI Op Code */
u8 channel; /* bus number */
u8 id; /* SCSI ID (virtual) */
int lun;
u8 flags; /* Bit Field - See above */
u8 physDiskNum; /* Phys disk number, -1 else */
u8 rsvd2;
u8 rsvd;
} INTERNAL_CMD;
extern void mptscsih_remove(struct pci_dev *); extern void mptscsih_remove(struct pci_dev *);
extern void mptscsih_shutdown(struct pci_dev *); extern void mptscsih_shutdown(struct pci_dev *);
#ifdef CONFIG_PM #ifdef CONFIG_PM
...@@ -81,9 +112,6 @@ extern int mptscsih_resume(struct pci_dev *pdev); ...@@ -81,9 +112,6 @@ extern int mptscsih_resume(struct pci_dev *pdev);
extern int mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, int length, int func); extern int mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, int length, int func);
extern const char * mptscsih_info(struct Scsi_Host *SChost); extern const char * mptscsih_info(struct Scsi_Host *SChost);
extern int mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)); extern int mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *));
extern int mptscsih_target_alloc(struct scsi_target *starget);
extern int mptscsih_slave_alloc(struct scsi_device *device);
extern void mptscsih_target_destroy(struct scsi_target *starget);
extern void mptscsih_slave_destroy(struct scsi_device *device); extern void mptscsih_slave_destroy(struct scsi_device *device);
extern int mptscsih_slave_configure(struct scsi_device *device); extern int mptscsih_slave_configure(struct scsi_device *device);
extern int mptscsih_abort(struct scsi_cmnd * SCpnt); extern int mptscsih_abort(struct scsi_cmnd * SCpnt);
...@@ -98,6 +126,6 @@ extern int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pE ...@@ -98,6 +126,6 @@ extern int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pE
extern int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset); extern int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
extern int mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth); extern int mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth);
extern void mptscsih_timer_expired(unsigned long data); extern void mptscsih_timer_expired(unsigned long data);
extern int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout); extern int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout);
extern int mptscsih_raid_id_to_num(MPT_SCSI_HOST *hd, uint physdiskid); extern u8 mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id);
extern int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id); extern int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id);
...@@ -95,25 +95,76 @@ static int mptspiDoneCtx = -1; ...@@ -95,25 +95,76 @@ static int mptspiDoneCtx = -1;
static int mptspiTaskCtx = -1; static int mptspiTaskCtx = -1;
static int mptspiInternalCtx = -1; /* Used only for internal commands */ static int mptspiInternalCtx = -1; /* Used only for internal commands */
/**
* mptspi_is_raid - Determines whether target is belonging to volume
* @hd: Pointer to a SCSI HOST structure
* @id: target device id
*
* Return:
* non-zero = true
* zero = false
*
*/
static int
mptspi_is_raid(struct _MPT_SCSI_HOST *hd, u32 id)
{
int i, rc = 0;
if (!hd->ioc->raid_data.pIocPg2)
goto out;
if (!hd->ioc->raid_data.pIocPg2->NumActiveVolumes)
goto out;
for (i=0; i < hd->ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
if (hd->ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID == id) {
rc = 1;
goto out;
}
}
out:
return rc;
}
static int mptspi_target_alloc(struct scsi_target *starget) static int mptspi_target_alloc(struct scsi_target *starget)
{ {
struct Scsi_Host *shost = dev_to_shost(&starget->dev); struct Scsi_Host *shost = dev_to_shost(&starget->dev);
struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata; struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata;
int ret; VirtTarget *vtarget;
if (hd == NULL) if (hd == NULL)
return -ENODEV; return -ENODEV;
ret = mptscsih_target_alloc(starget); vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
if (ret) if (!vtarget)
return ret; return -ENOMEM;
vtarget->ioc_id = hd->ioc->id;
vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
vtarget->id = (u8)starget->id;
vtarget->channel = (u8)starget->channel;
vtarget->starget = starget;
starget->hostdata = vtarget;
if (starget->channel == 1) {
if (mptscsih_is_phys_disk(hd->ioc, 0, starget->id) == 0)
return 0;
vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT;
/* The real channel for this device is zero */
vtarget->channel = 0;
/* The actual physdisknum (for RAID passthrough) */
vtarget->id = mptscsih_raid_id_to_num(hd->ioc, 0,
starget->id);
}
/* if we're a device on virtual channel 1 and we're not part if (starget->channel == 0 &&
* of an array, just return here (otherwise the setup below mptspi_is_raid(hd, starget->id)) {
* may actually affect a real physical device on channel 0 */ vtarget->raidVolume = 1;
if (starget->channel == 1 && ddvprintk((KERN_INFO
mptscsih_raid_id_to_num(hd, starget->id) < 0) "RAID Volume @ channel=%d id=%d\n", starget->channel,
return 0; starget->id));
}
if (hd->ioc->spi_data.nvram && if (hd->ioc->spi_data.nvram &&
hd->ioc->spi_data.nvram[starget->id] != MPT_HOST_NVRAM_INVALID) { hd->ioc->spi_data.nvram[starget->id] != MPT_HOST_NVRAM_INVALID) {
...@@ -132,6 +183,14 @@ static int mptspi_target_alloc(struct scsi_target *starget) ...@@ -132,6 +183,14 @@ static int mptspi_target_alloc(struct scsi_target *starget)
return 0; return 0;
} }
void
mptspi_target_destroy(struct scsi_target *starget)
{
if (starget->hostdata)
kfree(starget->hostdata);
starget->hostdata = NULL;
}
static int mptspi_read_spi_device_pg0(struct scsi_target *starget, static int mptspi_read_spi_device_pg0(struct scsi_target *starget,
struct _CONFIG_PAGE_SCSI_DEVICE_0 *pass_pg0) struct _CONFIG_PAGE_SCSI_DEVICE_0 *pass_pg0)
{ {
...@@ -147,7 +206,7 @@ static int mptspi_read_spi_device_pg0(struct scsi_target *starget, ...@@ -147,7 +206,7 @@ static int mptspi_read_spi_device_pg0(struct scsi_target *starget,
/* No SPI parameters for RAID devices */ /* No SPI parameters for RAID devices */
if (starget->channel == 0 && if (starget->channel == 0 &&
(hd->ioc->raid_data.isRaid & (1 << starget->id))) mptspi_is_raid(hd, starget->id))
return -1; return -1;
size = ioc->spi_data.sdp0length * 4; size = ioc->spi_data.sdp0length * 4;
...@@ -233,7 +292,7 @@ static void mptspi_read_parameters(struct scsi_target *starget) ...@@ -233,7 +292,7 @@ static void mptspi_read_parameters(struct scsi_target *starget)
} }
static int static int
mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, int disk) mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, u8 channel, u8 id)
{ {
MpiRaidActionRequest_t *pReq; MpiRaidActionRequest_t *pReq;
MPT_FRAME_HDR *mf; MPT_FRAME_HDR *mf;
...@@ -253,8 +312,8 @@ mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, int disk) ...@@ -253,8 +312,8 @@ mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, int disk)
pReq->Reserved1 = 0; pReq->Reserved1 = 0;
pReq->ChainOffset = 0; pReq->ChainOffset = 0;
pReq->Function = MPI_FUNCTION_RAID_ACTION; pReq->Function = MPI_FUNCTION_RAID_ACTION;
pReq->VolumeID = disk; pReq->VolumeID = id;
pReq->VolumeBus = 0; pReq->VolumeBus = channel;
pReq->PhysDiskNum = 0; pReq->PhysDiskNum = 0;
pReq->MsgFlags = 0; pReq->MsgFlags = 0;
pReq->Reserved2 = 0; pReq->Reserved2 = 0;
...@@ -263,8 +322,8 @@ mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, int disk) ...@@ -263,8 +322,8 @@ mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, int disk)
mpt_add_sge((char *)&pReq->ActionDataSGE, mpt_add_sge((char *)&pReq->ActionDataSGE,
MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1); MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1);
ddvprintk((MYIOC_s_INFO_FMT "RAID Volume action %x id %d\n", ddvprintk((MYIOC_s_INFO_FMT "RAID Volume action=%x channel=%d id=%d\n",
hd->ioc->name, action, io->id)); hd->ioc->name, pReq->Action, channel, id));
hd->pLocal = NULL; hd->pLocal = NULL;
hd->timer.expires = jiffies + HZ*10; /* 10 second timeout */ hd->timer.expires = jiffies + HZ*10; /* 10 second timeout */
...@@ -292,12 +351,12 @@ static void mptspi_dv_device(struct _MPT_SCSI_HOST *hd, ...@@ -292,12 +351,12 @@ static void mptspi_dv_device(struct _MPT_SCSI_HOST *hd,
/* no DV on RAID devices */ /* no DV on RAID devices */
if (sdev->channel == 0 && if (sdev->channel == 0 &&
(hd->ioc->raid_data.isRaid & (1 << sdev->id))) mptspi_is_raid(hd, sdev->id))
return; return;
/* If this is a piece of a RAID, then quiesce first */ /* If this is a piece of a RAID, then quiesce first */
if (sdev->channel == 1 && if (sdev->channel == 1 &&
mptscsih_quiesce_raid(hd, 1, vtarget->target_id) < 0) { mptscsih_quiesce_raid(hd, 1, vtarget->channel, vtarget->id) < 0) {
starget_printk(KERN_ERR, scsi_target(sdev), starget_printk(KERN_ERR, scsi_target(sdev),
"Integrated RAID quiesce failed\n"); "Integrated RAID quiesce failed\n");
return; return;
...@@ -306,7 +365,7 @@ static void mptspi_dv_device(struct _MPT_SCSI_HOST *hd, ...@@ -306,7 +365,7 @@ static void mptspi_dv_device(struct _MPT_SCSI_HOST *hd,
spi_dv_device(sdev); spi_dv_device(sdev);
if (sdev->channel == 1 && if (sdev->channel == 1 &&
mptscsih_quiesce_raid(hd, 0, vtarget->target_id) < 0) mptscsih_quiesce_raid(hd, 0, vtarget->channel, vtarget->id) < 0)
starget_printk(KERN_ERR, scsi_target(sdev), starget_printk(KERN_ERR, scsi_target(sdev),
"Integrated RAID resume failed\n"); "Integrated RAID resume failed\n");
...@@ -317,33 +376,32 @@ static void mptspi_dv_device(struct _MPT_SCSI_HOST *hd, ...@@ -317,33 +376,32 @@ static void mptspi_dv_device(struct _MPT_SCSI_HOST *hd,
static int mptspi_slave_alloc(struct scsi_device *sdev) static int mptspi_slave_alloc(struct scsi_device *sdev)
{ {
int ret;
MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sdev->host->hostdata; MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sdev->host->hostdata;
/* gcc doesn't see that all uses of this variable occur within VirtTarget *vtarget;
* the if() statements, so stop it from whining */ VirtDevice *vdev;
int physdisknum = 0; struct scsi_target *starget;
if (sdev->channel == 1) {
physdisknum = mptscsih_raid_id_to_num(hd, sdev->id);
if (physdisknum < 0) if (sdev->channel == 1 &&
return physdisknum; mptscsih_is_phys_disk(hd->ioc, 0, sdev->id) == 0)
return -ENXIO;
vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
if (!vdev) {
printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
hd->ioc->name, sizeof(VirtDevice));
return -ENOMEM;
} }
ret = mptscsih_slave_alloc(sdev); vdev->lun = sdev->lun;
sdev->hostdata = vdev;
if (ret) starget = scsi_target(sdev);
return ret; vtarget = starget->hostdata;
vdev->vtarget = vtarget;
vtarget->num_luns++;
if (sdev->channel == 1) { if (sdev->channel == 1)
VirtDevice *vdev = sdev->hostdata;
sdev->no_uld_attach = 1; sdev->no_uld_attach = 1;
vdev->vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT;
/* The real channel for this device is zero */
vdev->vtarget->bus_id = 0;
/* The actual physdisknum (for RAID passthrough) */
vdev->vtarget->target_id = physdisknum;
}
return 0; return 0;
} }
...@@ -358,13 +416,35 @@ static int mptspi_slave_configure(struct scsi_device *sdev) ...@@ -358,13 +416,35 @@ static int mptspi_slave_configure(struct scsi_device *sdev)
return ret; return ret;
if ((sdev->channel == 1 || if ((sdev->channel == 1 ||
!(hd->ioc->raid_data.isRaid & (1 << sdev->id))) && !(mptspi_is_raid(hd, sdev->id))) &&
!spi_initial_dv(sdev->sdev_target)) !spi_initial_dv(sdev->sdev_target))
mptspi_dv_device(hd, sdev); mptspi_dv_device(hd, sdev);
return 0; return 0;
} }
static int
mptspi_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
{
struct _MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata;
VirtDevice *vdev = SCpnt->device->hostdata;
if (!vdev || !vdev->vtarget) {
SCpnt->result = DID_NO_CONNECT << 16;
done(SCpnt);
return 0;
}
if (SCpnt->device->channel == 1 &&
mptscsih_is_phys_disk(hd->ioc, 0, SCpnt->device->id) == 0) {
SCpnt->result = DID_NO_CONNECT << 16;
done(SCpnt);
return 0;
}
return mptscsih_qcmd(SCpnt,done);
}
static void mptspi_slave_destroy(struct scsi_device *sdev) static void mptspi_slave_destroy(struct scsi_device *sdev)
{ {
struct scsi_target *starget = scsi_target(sdev); struct scsi_target *starget = scsi_target(sdev);
...@@ -392,11 +472,11 @@ static struct scsi_host_template mptspi_driver_template = { ...@@ -392,11 +472,11 @@ static struct scsi_host_template mptspi_driver_template = {
.proc_info = mptscsih_proc_info, .proc_info = mptscsih_proc_info,
.name = "MPT SPI Host", .name = "MPT SPI Host",
.info = mptscsih_info, .info = mptscsih_info,
.queuecommand = mptscsih_qcmd, .queuecommand = mptspi_qcmd,
.target_alloc = mptspi_target_alloc, .target_alloc = mptspi_target_alloc,
.slave_alloc = mptspi_slave_alloc, .slave_alloc = mptspi_slave_alloc,
.slave_configure = mptspi_slave_configure, .slave_configure = mptspi_slave_configure,
.target_destroy = mptscsih_target_destroy, .target_destroy = mptspi_target_destroy,
.slave_destroy = mptspi_slave_destroy, .slave_destroy = mptspi_slave_destroy,
.change_queue_depth = mptscsih_change_queue_depth, .change_queue_depth = mptscsih_change_queue_depth,
.eh_abort_handler = mptscsih_abort, .eh_abort_handler = mptscsih_abort,
...@@ -427,7 +507,7 @@ static int mptspi_write_spi_device_pg1(struct scsi_target *starget, ...@@ -427,7 +507,7 @@ static int mptspi_write_spi_device_pg1(struct scsi_target *starget,
/* don't allow updating nego parameters on RAID devices */ /* don't allow updating nego parameters on RAID devices */
if (starget->channel == 0 && if (starget->channel == 0 &&
(hd->ioc->raid_data.isRaid & (1 << starget->id))) mptspi_is_raid(hd, starget->id))
return -1; return -1;
size = ioc->spi_data.sdp1length * 4; size = ioc->spi_data.sdp1length * 4;
...@@ -672,9 +752,9 @@ static void mpt_work_wrapper(struct work_struct *work) ...@@ -672,9 +752,9 @@ static void mpt_work_wrapper(struct work_struct *work)
if (sdev->channel != 1) if (sdev->channel != 1)
continue; continue;
/* The target_id is the raid PhysDiskNum, even if /* The id is the raid PhysDiskNum, even if
* starget->id is the actual target address */ * starget->id is the actual target address */
if(vtarget->target_id != disk) if(vtarget->id != disk)
continue; continue;
starget_printk(KERN_INFO, vtarget->starget, starget_printk(KERN_INFO, vtarget->starget,
...@@ -727,7 +807,7 @@ mptspi_deny_binding(struct scsi_target *starget) ...@@ -727,7 +807,7 @@ mptspi_deny_binding(struct scsi_target *starget)
{ {
struct _MPT_SCSI_HOST *hd = struct _MPT_SCSI_HOST *hd =
(struct _MPT_SCSI_HOST *)dev_to_shost(starget->dev.parent)->hostdata; (struct _MPT_SCSI_HOST *)dev_to_shost(starget->dev.parent)->hostdata;
return ((hd->ioc->raid_data.isRaid & (1 << starget->id)) && return ((mptspi_is_raid(hd, starget->id)) &&
starget->channel == 0) ? 1 : 0; starget->channel == 0) ? 1 : 0;
} }
...@@ -945,7 +1025,7 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -945,7 +1025,7 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
* max_lun = 1 + actual last lun, * max_lun = 1 + actual last lun,
* see hosts.h :o( * see hosts.h :o(
*/ */
sh->max_id = MPT_MAX_SCSI_DEVICES; sh->max_id = ioc->devices_per_bus;
sh->max_lun = MPT_LAST_LUN + 1; sh->max_lun = MPT_LAST_LUN + 1;
/* /*
...@@ -1009,20 +1089,6 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -1009,20 +1089,6 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n", dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
ioc->name, hd->ScsiLookup)); 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 * (sh->max_channel + 1),
sizeof(void *), GFP_ATOMIC);
if (!hd->Targets) {
error = -ENOMEM;
goto out_mptspi_probe;
}
dprintk((KERN_INFO " vdev @ %p\n", hd->Targets));
/* Clear the TM flags /* Clear the TM flags
*/ */
hd->tmPending = 0; hd->tmPending = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment