aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/message/fusion/mptspi.c
diff options
context:
space:
mode:
authorEric Moore <eric.moore@lsi.com>2007-01-29 11:42:20 -0500
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2007-02-02 21:48:49 -0500
commit793955f549c710a1b0c18f823d5d710840747b15 (patch)
treeef85a09c1d90404a83f95b35d6fd717c421a4e5b /drivers/message/fusion/mptspi.c
parent502c62f17aa7daa78d5da963305251b872885ff9 (diff)
[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>
Diffstat (limited to 'drivers/message/fusion/mptspi.c')
-rw-r--r--drivers/message/fusion/mptspi.c188
1 files changed, 127 insertions, 61 deletions
diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c
index 203c661d2c79..aec0c2fe221f 100644
--- a/drivers/message/fusion/mptspi.c
+++ b/drivers/message/fusion/mptspi.c
@@ -95,25 +95,76 @@ static int mptspiDoneCtx = -1;
95static int mptspiTaskCtx = -1; 95static int mptspiTaskCtx = -1;
96static int mptspiInternalCtx = -1; /* Used only for internal commands */ 96static int mptspiInternalCtx = -1; /* Used only for internal commands */
97 97
98
99/**
100 * mptspi_is_raid - Determines whether target is belonging to volume
101 * @hd: Pointer to a SCSI HOST structure
102 * @id: target device id
103 *
104 * Return:
105 * non-zero = true
106 * zero = false
107 *
108 */
109static int
110mptspi_is_raid(struct _MPT_SCSI_HOST *hd, u32 id)
111{
112 int i, rc = 0;
113
114 if (!hd->ioc->raid_data.pIocPg2)
115 goto out;
116
117 if (!hd->ioc->raid_data.pIocPg2->NumActiveVolumes)
118 goto out;
119 for (i=0; i < hd->ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
120 if (hd->ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID == id) {
121 rc = 1;
122 goto out;
123 }
124 }
125
126 out:
127 return rc;
128}
129
98static int mptspi_target_alloc(struct scsi_target *starget) 130static int mptspi_target_alloc(struct scsi_target *starget)
99{ 131{
100 struct Scsi_Host *shost = dev_to_shost(&starget->dev); 132 struct Scsi_Host *shost = dev_to_shost(&starget->dev);
101 struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata; 133 struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata;
102 int ret; 134 VirtTarget *vtarget;
103 135
104 if (hd == NULL) 136 if (hd == NULL)
105 return -ENODEV; 137 return -ENODEV;
106 138
107 ret = mptscsih_target_alloc(starget); 139 vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
108 if (ret) 140 if (!vtarget)
109 return ret; 141 return -ENOMEM;
142
143 vtarget->ioc_id = hd->ioc->id;
144 vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
145 vtarget->id = (u8)starget->id;
146 vtarget->channel = (u8)starget->channel;
147 vtarget->starget = starget;
148 starget->hostdata = vtarget;
149
150 if (starget->channel == 1) {
151 if (mptscsih_is_phys_disk(hd->ioc, 0, starget->id) == 0)
152 return 0;
153 vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT;
154 /* The real channel for this device is zero */
155 vtarget->channel = 0;
156 /* The actual physdisknum (for RAID passthrough) */
157 vtarget->id = mptscsih_raid_id_to_num(hd->ioc, 0,
158 starget->id);
159 }
110 160
111 /* if we're a device on virtual channel 1 and we're not part 161 if (starget->channel == 0 &&
112 * of an array, just return here (otherwise the setup below 162 mptspi_is_raid(hd, starget->id)) {
113 * may actually affect a real physical device on channel 0 */ 163 vtarget->raidVolume = 1;
114 if (starget->channel == 1 && 164 ddvprintk((KERN_INFO
115 mptscsih_raid_id_to_num(hd, starget->id) < 0) 165 "RAID Volume @ channel=%d id=%d\n", starget->channel,
116 return 0; 166 starget->id));
167 }
117 168
118 if (hd->ioc->spi_data.nvram && 169 if (hd->ioc->spi_data.nvram &&
119 hd->ioc->spi_data.nvram[starget->id] != MPT_HOST_NVRAM_INVALID) { 170 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 return 0; 183 return 0;
133} 184}
134 185
186void
187mptspi_target_destroy(struct scsi_target *starget)
188{
189 if (starget->hostdata)
190 kfree(starget->hostdata);
191 starget->hostdata = NULL;
192}
193
135static int mptspi_read_spi_device_pg0(struct scsi_target *starget, 194static int mptspi_read_spi_device_pg0(struct scsi_target *starget,
136 struct _CONFIG_PAGE_SCSI_DEVICE_0 *pass_pg0) 195 struct _CONFIG_PAGE_SCSI_DEVICE_0 *pass_pg0)
137{ 196{
@@ -147,7 +206,7 @@ static int mptspi_read_spi_device_pg0(struct scsi_target *starget,
147 206
148 /* No SPI parameters for RAID devices */ 207 /* No SPI parameters for RAID devices */
149 if (starget->channel == 0 && 208 if (starget->channel == 0 &&
150 (hd->ioc->raid_data.isRaid & (1 << starget->id))) 209 mptspi_is_raid(hd, starget->id))
151 return -1; 210 return -1;
152 211
153 size = ioc->spi_data.sdp0length * 4; 212 size = ioc->spi_data.sdp0length * 4;
@@ -233,7 +292,7 @@ static void mptspi_read_parameters(struct scsi_target *starget)
233} 292}
234 293
235static int 294static int
236mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, int disk) 295mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, u8 channel, u8 id)
237{ 296{
238 MpiRaidActionRequest_t *pReq; 297 MpiRaidActionRequest_t *pReq;
239 MPT_FRAME_HDR *mf; 298 MPT_FRAME_HDR *mf;
@@ -253,8 +312,8 @@ mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, int disk)
253 pReq->Reserved1 = 0; 312 pReq->Reserved1 = 0;
254 pReq->ChainOffset = 0; 313 pReq->ChainOffset = 0;
255 pReq->Function = MPI_FUNCTION_RAID_ACTION; 314 pReq->Function = MPI_FUNCTION_RAID_ACTION;
256 pReq->VolumeID = disk; 315 pReq->VolumeID = id;
257 pReq->VolumeBus = 0; 316 pReq->VolumeBus = channel;
258 pReq->PhysDiskNum = 0; 317 pReq->PhysDiskNum = 0;
259 pReq->MsgFlags = 0; 318 pReq->MsgFlags = 0;
260 pReq->Reserved2 = 0; 319 pReq->Reserved2 = 0;
@@ -263,8 +322,8 @@ mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, int disk)
263 mpt_add_sge((char *)&pReq->ActionDataSGE, 322 mpt_add_sge((char *)&pReq->ActionDataSGE,
264 MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1); 323 MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1);
265 324
266 ddvprintk((MYIOC_s_INFO_FMT "RAID Volume action %x id %d\n", 325 ddvprintk((MYIOC_s_INFO_FMT "RAID Volume action=%x channel=%d id=%d\n",
267 hd->ioc->name, action, io->id)); 326 hd->ioc->name, pReq->Action, channel, id));
268 327
269 hd->pLocal = NULL; 328 hd->pLocal = NULL;
270 hd->timer.expires = jiffies + HZ*10; /* 10 second timeout */ 329 hd->timer.expires = jiffies + HZ*10; /* 10 second timeout */
@@ -292,12 +351,12 @@ static void mptspi_dv_device(struct _MPT_SCSI_HOST *hd,
292 351
293 /* no DV on RAID devices */ 352 /* no DV on RAID devices */
294 if (sdev->channel == 0 && 353 if (sdev->channel == 0 &&
295 (hd->ioc->raid_data.isRaid & (1 << sdev->id))) 354 mptspi_is_raid(hd, sdev->id))
296 return; 355 return;
297 356
298 /* If this is a piece of a RAID, then quiesce first */ 357 /* If this is a piece of a RAID, then quiesce first */
299 if (sdev->channel == 1 && 358 if (sdev->channel == 1 &&
300 mptscsih_quiesce_raid(hd, 1, vtarget->target_id) < 0) { 359 mptscsih_quiesce_raid(hd, 1, vtarget->channel, vtarget->id) < 0) {
301 starget_printk(KERN_ERR, scsi_target(sdev), 360 starget_printk(KERN_ERR, scsi_target(sdev),
302 "Integrated RAID quiesce failed\n"); 361 "Integrated RAID quiesce failed\n");
303 return; 362 return;
@@ -306,7 +365,7 @@ static void mptspi_dv_device(struct _MPT_SCSI_HOST *hd,
306 spi_dv_device(sdev); 365 spi_dv_device(sdev);
307 366
308 if (sdev->channel == 1 && 367 if (sdev->channel == 1 &&
309 mptscsih_quiesce_raid(hd, 0, vtarget->target_id) < 0) 368 mptscsih_quiesce_raid(hd, 0, vtarget->channel, vtarget->id) < 0)
310 starget_printk(KERN_ERR, scsi_target(sdev), 369 starget_printk(KERN_ERR, scsi_target(sdev),
311 "Integrated RAID resume failed\n"); 370 "Integrated RAID resume failed\n");
312 371
@@ -317,33 +376,32 @@ static void mptspi_dv_device(struct _MPT_SCSI_HOST *hd,
317 376
318static int mptspi_slave_alloc(struct scsi_device *sdev) 377static int mptspi_slave_alloc(struct scsi_device *sdev)
319{ 378{
320 int ret;
321 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sdev->host->hostdata; 379 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sdev->host->hostdata;
322 /* gcc doesn't see that all uses of this variable occur within 380 VirtTarget *vtarget;
323 * the if() statements, so stop it from whining */ 381 VirtDevice *vdev;
324 int physdisknum = 0; 382 struct scsi_target *starget;
325
326 if (sdev->channel == 1) {
327 physdisknum = mptscsih_raid_id_to_num(hd, sdev->id);
328 383
329 if (physdisknum < 0) 384 if (sdev->channel == 1 &&
330 return physdisknum; 385 mptscsih_is_phys_disk(hd->ioc, 0, sdev->id) == 0)
386 return -ENXIO;
387
388 vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
389 if (!vdev) {
390 printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
391 hd->ioc->name, sizeof(VirtDevice));
392 return -ENOMEM;
331 } 393 }
332 394
333 ret = mptscsih_slave_alloc(sdev); 395 vdev->lun = sdev->lun;
396 sdev->hostdata = vdev;
334 397
335 if (ret) 398 starget = scsi_target(sdev);
336 return ret; 399 vtarget = starget->hostdata;
400 vdev->vtarget = vtarget;
401 vtarget->num_luns++;
337 402
338 if (sdev->channel == 1) { 403 if (sdev->channel == 1)
339 VirtDevice *vdev = sdev->hostdata;
340 sdev->no_uld_attach = 1; 404 sdev->no_uld_attach = 1;
341 vdev->vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT;
342 /* The real channel for this device is zero */
343 vdev->vtarget->bus_id = 0;
344 /* The actual physdisknum (for RAID passthrough) */
345 vdev->vtarget->target_id = physdisknum;
346 }
347 405
348 return 0; 406 return 0;
349} 407}
@@ -358,13 +416,35 @@ static int mptspi_slave_configure(struct scsi_device *sdev)
358 return ret; 416 return ret;
359 417
360 if ((sdev->channel == 1 || 418 if ((sdev->channel == 1 ||
361 !(hd->ioc->raid_data.isRaid & (1 << sdev->id))) && 419 !(mptspi_is_raid(hd, sdev->id))) &&
362 !spi_initial_dv(sdev->sdev_target)) 420 !spi_initial_dv(sdev->sdev_target))
363 mptspi_dv_device(hd, sdev); 421 mptspi_dv_device(hd, sdev);
364 422
365 return 0; 423 return 0;
366} 424}
367 425
426static int
427mptspi_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
428{
429 struct _MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata;
430 VirtDevice *vdev = SCpnt->device->hostdata;
431
432 if (!vdev || !vdev->vtarget) {
433 SCpnt->result = DID_NO_CONNECT << 16;
434 done(SCpnt);
435 return 0;
436 }
437
438 if (SCpnt->device->channel == 1 &&
439 mptscsih_is_phys_disk(hd->ioc, 0, SCpnt->device->id) == 0) {
440 SCpnt->result = DID_NO_CONNECT << 16;
441 done(SCpnt);
442 return 0;
443 }
444
445 return mptscsih_qcmd(SCpnt,done);
446}
447
368static void mptspi_slave_destroy(struct scsi_device *sdev) 448static void mptspi_slave_destroy(struct scsi_device *sdev)
369{ 449{
370 struct scsi_target *starget = scsi_target(sdev); 450 struct scsi_target *starget = scsi_target(sdev);
@@ -392,11 +472,11 @@ static struct scsi_host_template mptspi_driver_template = {
392 .proc_info = mptscsih_proc_info, 472 .proc_info = mptscsih_proc_info,
393 .name = "MPT SPI Host", 473 .name = "MPT SPI Host",
394 .info = mptscsih_info, 474 .info = mptscsih_info,
395 .queuecommand = mptscsih_qcmd, 475 .queuecommand = mptspi_qcmd,
396 .target_alloc = mptspi_target_alloc, 476 .target_alloc = mptspi_target_alloc,
397 .slave_alloc = mptspi_slave_alloc, 477 .slave_alloc = mptspi_slave_alloc,
398 .slave_configure = mptspi_slave_configure, 478 .slave_configure = mptspi_slave_configure,
399 .target_destroy = mptscsih_target_destroy, 479 .target_destroy = mptspi_target_destroy,
400 .slave_destroy = mptspi_slave_destroy, 480 .slave_destroy = mptspi_slave_destroy,
401 .change_queue_depth = mptscsih_change_queue_depth, 481 .change_queue_depth = mptscsih_change_queue_depth,
402 .eh_abort_handler = mptscsih_abort, 482 .eh_abort_handler = mptscsih_abort,
@@ -427,7 +507,7 @@ static int mptspi_write_spi_device_pg1(struct scsi_target *starget,
427 507
428 /* don't allow updating nego parameters on RAID devices */ 508 /* don't allow updating nego parameters on RAID devices */
429 if (starget->channel == 0 && 509 if (starget->channel == 0 &&
430 (hd->ioc->raid_data.isRaid & (1 << starget->id))) 510 mptspi_is_raid(hd, starget->id))
431 return -1; 511 return -1;
432 512
433 size = ioc->spi_data.sdp1length * 4; 513 size = ioc->spi_data.sdp1length * 4;
@@ -672,9 +752,9 @@ static void mpt_work_wrapper(struct work_struct *work)
672 if (sdev->channel != 1) 752 if (sdev->channel != 1)
673 continue; 753 continue;
674 754
675 /* The target_id is the raid PhysDiskNum, even if 755 /* The id is the raid PhysDiskNum, even if
676 * starget->id is the actual target address */ 756 * starget->id is the actual target address */
677 if(vtarget->target_id != disk) 757 if(vtarget->id != disk)
678 continue; 758 continue;
679 759
680 starget_printk(KERN_INFO, vtarget->starget, 760 starget_printk(KERN_INFO, vtarget->starget,
@@ -727,7 +807,7 @@ mptspi_deny_binding(struct scsi_target *starget)
727{ 807{
728 struct _MPT_SCSI_HOST *hd = 808 struct _MPT_SCSI_HOST *hd =
729 (struct _MPT_SCSI_HOST *)dev_to_shost(starget->dev.parent)->hostdata; 809 (struct _MPT_SCSI_HOST *)dev_to_shost(starget->dev.parent)->hostdata;
730 return ((hd->ioc->raid_data.isRaid & (1 << starget->id)) && 810 return ((mptspi_is_raid(hd, starget->id)) &&
731 starget->channel == 0) ? 1 : 0; 811 starget->channel == 0) ? 1 : 0;
732} 812}
733 813
@@ -945,7 +1025,7 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
945 * max_lun = 1 + actual last lun, 1025 * max_lun = 1 + actual last lun,
946 * see hosts.h :o( 1026 * see hosts.h :o(
947 */ 1027 */
948 sh->max_id = MPT_MAX_SCSI_DEVICES; 1028 sh->max_id = ioc->devices_per_bus;
949 1029
950 sh->max_lun = MPT_LAST_LUN + 1; 1030 sh->max_lun = MPT_LAST_LUN + 1;
951 /* 1031 /*
@@ -1009,20 +1089,6 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
1009 dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n", 1089 dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
1010 ioc->name, hd->ScsiLookup)); 1090 ioc->name, hd->ScsiLookup));
1011 1091
1012 /* Allocate memory for the device structures.
1013 * A non-Null pointer at an offset
1014 * indicates a device exists.
1015 * max_id = 1 + maximum id (hosts.h)
1016 */
1017 hd->Targets = kcalloc(sh->max_id * (sh->max_channel + 1),
1018 sizeof(void *), GFP_ATOMIC);
1019 if (!hd->Targets) {
1020 error = -ENOMEM;
1021 goto out_mptspi_probe;
1022 }
1023
1024 dprintk((KERN_INFO " vdev @ %p\n", hd->Targets));
1025
1026 /* Clear the TM flags 1092 /* Clear the TM flags
1027 */ 1093 */
1028 hd->tmPending = 0; 1094 hd->tmPending = 0;