[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: Eric Moore <Eric.Moore@lsi.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
This commit is contained in:
Eric Moore
2007-01-29 09:42:20 -07:00
committed by James Bottomley
parent 502c62f17a
commit 793955f549
9 changed files with 379 additions and 476 deletions

View File

@@ -95,25 +95,76 @@ static int mptspiDoneCtx = -1;
static int mptspiTaskCtx = -1;
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)
{
struct Scsi_Host *shost = dev_to_shost(&starget->dev);
struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata;
int ret;
VirtTarget *vtarget;
if (hd == NULL)
return -ENODEV;
ret = mptscsih_target_alloc(starget);
if (ret)
return ret;
vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
if (!vtarget)
return -ENOMEM;
/* if we're a device on virtual channel 1 and we're not part
* of an array, just return here (otherwise the setup below
* may actually affect a real physical device on channel 0 */
if (starget->channel == 1 &&
mptscsih_raid_id_to_num(hd, starget->id) < 0)
return 0;
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 (starget->channel == 0 &&
mptspi_is_raid(hd, starget->id)) {
vtarget->raidVolume = 1;
ddvprintk((KERN_INFO
"RAID Volume @ channel=%d id=%d\n", starget->channel,
starget->id));
}
if (hd->ioc->spi_data.nvram &&
hd->ioc->spi_data.nvram[starget->id] != MPT_HOST_NVRAM_INVALID) {
@@ -132,6 +183,14 @@ static int mptspi_target_alloc(struct scsi_target *starget)
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,
struct _CONFIG_PAGE_SCSI_DEVICE_0 *pass_pg0)
{
@@ -147,7 +206,7 @@ static int mptspi_read_spi_device_pg0(struct scsi_target *starget,
/* No SPI parameters for RAID devices */
if (starget->channel == 0 &&
(hd->ioc->raid_data.isRaid & (1 << starget->id)))
mptspi_is_raid(hd, starget->id))
return -1;
size = ioc->spi_data.sdp0length * 4;
@@ -233,7 +292,7 @@ static void mptspi_read_parameters(struct scsi_target *starget)
}
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;
MPT_FRAME_HDR *mf;
@@ -253,8 +312,8 @@ mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, int disk)
pReq->Reserved1 = 0;
pReq->ChainOffset = 0;
pReq->Function = MPI_FUNCTION_RAID_ACTION;
pReq->VolumeID = disk;
pReq->VolumeBus = 0;
pReq->VolumeID = id;
pReq->VolumeBus = channel;
pReq->PhysDiskNum = 0;
pReq->MsgFlags = 0;
pReq->Reserved2 = 0;
@@ -263,8 +322,8 @@ mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, int disk)
mpt_add_sge((char *)&pReq->ActionDataSGE,
MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1);
ddvprintk((MYIOC_s_INFO_FMT "RAID Volume action %x id %d\n",
hd->ioc->name, action, io->id));
ddvprintk((MYIOC_s_INFO_FMT "RAID Volume action=%x channel=%d id=%d\n",
hd->ioc->name, pReq->Action, channel, id));
hd->pLocal = NULL;
hd->timer.expires = jiffies + HZ*10; /* 10 second timeout */
@@ -292,12 +351,12 @@ static void mptspi_dv_device(struct _MPT_SCSI_HOST *hd,
/* no DV on RAID devices */
if (sdev->channel == 0 &&
(hd->ioc->raid_data.isRaid & (1 << sdev->id)))
mptspi_is_raid(hd, sdev->id))
return;
/* If this is a piece of a RAID, then quiesce first */
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),
"Integrated RAID quiesce failed\n");
return;
@@ -306,7 +365,7 @@ static void mptspi_dv_device(struct _MPT_SCSI_HOST *hd,
spi_dv_device(sdev);
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),
"Integrated RAID resume failed\n");
@@ -317,33 +376,32 @@ static void mptspi_dv_device(struct _MPT_SCSI_HOST *hd,
static int mptspi_slave_alloc(struct scsi_device *sdev)
{
int ret;
MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sdev->host->hostdata;
/* gcc doesn't see that all uses of this variable occur within
* the if() statements, so stop it from whining */
int physdisknum = 0;
VirtTarget *vtarget;
VirtDevice *vdev;
struct scsi_target *starget;
if (sdev->channel == 1) {
physdisknum = mptscsih_raid_id_to_num(hd, sdev->id);
if (sdev->channel == 1 &&
mptscsih_is_phys_disk(hd->ioc, 0, sdev->id) == 0)
return -ENXIO;
if (physdisknum < 0)
return physdisknum;
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)
return ret;
starget = scsi_target(sdev);
vtarget = starget->hostdata;
vdev->vtarget = vtarget;
vtarget->num_luns++;
if (sdev->channel == 1) {
VirtDevice *vdev = sdev->hostdata;
if (sdev->channel == 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;
}
@@ -358,13 +416,35 @@ static int mptspi_slave_configure(struct scsi_device *sdev)
return ret;
if ((sdev->channel == 1 ||
!(hd->ioc->raid_data.isRaid & (1 << sdev->id))) &&
!(mptspi_is_raid(hd, sdev->id))) &&
!spi_initial_dv(sdev->sdev_target))
mptspi_dv_device(hd, sdev);
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)
{
struct scsi_target *starget = scsi_target(sdev);
@@ -392,11 +472,11 @@ static struct scsi_host_template mptspi_driver_template = {
.proc_info = mptscsih_proc_info,
.name = "MPT SPI Host",
.info = mptscsih_info,
.queuecommand = mptscsih_qcmd,
.queuecommand = mptspi_qcmd,
.target_alloc = mptspi_target_alloc,
.slave_alloc = mptspi_slave_alloc,
.slave_configure = mptspi_slave_configure,
.target_destroy = mptscsih_target_destroy,
.target_destroy = mptspi_target_destroy,
.slave_destroy = mptspi_slave_destroy,
.change_queue_depth = mptscsih_change_queue_depth,
.eh_abort_handler = mptscsih_abort,
@@ -427,7 +507,7 @@ static int mptspi_write_spi_device_pg1(struct scsi_target *starget,
/* don't allow updating nego parameters on RAID devices */
if (starget->channel == 0 &&
(hd->ioc->raid_data.isRaid & (1 << starget->id)))
mptspi_is_raid(hd, starget->id))
return -1;
size = ioc->spi_data.sdp1length * 4;
@@ -672,9 +752,9 @@ static void mpt_work_wrapper(struct work_struct *work)
if (sdev->channel != 1)
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 */
if(vtarget->target_id != disk)
if(vtarget->id != disk)
continue;
starget_printk(KERN_INFO, vtarget->starget,
@@ -727,7 +807,7 @@ mptspi_deny_binding(struct scsi_target *starget)
{
struct _MPT_SCSI_HOST *hd =
(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;
}
@@ -945,7 +1025,7 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
* max_lun = 1 + actual last lun,
* 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;
/*
@@ -1009,20 +1089,6 @@ mptspi_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 * (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
*/
hd->tmPending = 0;