aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/message/fusion/mptspi.c
diff options
context:
space:
mode:
authorJames Bottomley <James.Bottomley@steeleye.com>2006-03-01 10:02:49 -0500
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-03-01 10:44:04 -0500
commitc92f222e1f14588171e63b550ca8c85fa9130061 (patch)
tree83db58755951518865324ac880fc321e516755b9 /drivers/message/fusion/mptspi.c
parent3ef0b47ee498ea183bffd9b3b4a1eef757fef4ba (diff)
[SCSI] mptspi: Add transport class Domain Validation
This is the first half of a patch to add the generic domain validation to mptspi. It also creates a secondary "virtual" channel for raid component devices since these are now exported with no_uld_attach. What Eric and I would have really liked is to export all physical components on channel 0 and all raid components on channel 1. Unfortunately, this would result in device renumbering on platforms with mixed RAID/Physical devices which was considered unacceptable for userland stability reasons. Still to be done is to plug back the extra parameter setting and DV pieces on reset and hotplug. Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/message/fusion/mptspi.c')
-rw-r--r--drivers/message/fusion/mptspi.c733
1 files changed, 680 insertions, 53 deletions
diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c
index f148dfa39117..437189f871b0 100644
--- a/drivers/message/fusion/mptspi.c
+++ b/drivers/message/fusion/mptspi.c
@@ -56,12 +56,15 @@
56#include <linux/reboot.h> /* notifier code */ 56#include <linux/reboot.h> /* notifier code */
57#include <linux/sched.h> 57#include <linux/sched.h>
58#include <linux/workqueue.h> 58#include <linux/workqueue.h>
59#include <linux/raid_class.h>
59 60
60#include <scsi/scsi.h> 61#include <scsi/scsi.h>
61#include <scsi/scsi_cmnd.h> 62#include <scsi/scsi_cmnd.h>
62#include <scsi/scsi_device.h> 63#include <scsi/scsi_device.h>
63#include <scsi/scsi_host.h> 64#include <scsi/scsi_host.h>
64#include <scsi/scsi_tcq.h> 65#include <scsi/scsi_tcq.h>
66#include <scsi/scsi_transport.h>
67#include <scsi/scsi_transport_spi.h>
65 68
66#include "mptbase.h" 69#include "mptbase.h"
67#include "mptscsih.h" 70#include "mptscsih.h"
@@ -76,20 +79,6 @@ MODULE_DESCRIPTION(my_NAME);
76MODULE_LICENSE("GPL"); 79MODULE_LICENSE("GPL");
77 80
78/* Command line args */ 81/* Command line args */
79#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
80static int mpt_dv = MPTSCSIH_DOMAIN_VALIDATION;
81module_param(mpt_dv, int, 0);
82MODULE_PARM_DESC(mpt_dv, " DV Algorithm: enhanced=1, basic=0 (default=MPTSCSIH_DOMAIN_VALIDATION=1)");
83
84static int mpt_width = MPTSCSIH_MAX_WIDTH;
85module_param(mpt_width, int, 0);
86MODULE_PARM_DESC(mpt_width, " Max Bus Width: wide=1, narrow=0 (default=MPTSCSIH_MAX_WIDTH=1)");
87
88static ushort mpt_factor = MPTSCSIH_MIN_SYNC;
89module_param(mpt_factor, ushort, 0);
90MODULE_PARM_DESC(mpt_factor, " Min Sync Factor (default=MPTSCSIH_MIN_SYNC=0x08)");
91#endif
92
93static int mpt_saf_te = MPTSCSIH_SAF_TE; 82static int mpt_saf_te = MPTSCSIH_SAF_TE;
94module_param(mpt_saf_te, int, 0); 83module_param(mpt_saf_te, int, 0);
95MODULE_PARM_DESC(mpt_saf_te, " Force enabling SEP Processor: enable=1 (default=MPTSCSIH_SAF_TE=0)"); 84MODULE_PARM_DESC(mpt_saf_te, " Force enabling SEP Processor: enable=1 (default=MPTSCSIH_SAF_TE=0)");
@@ -98,10 +87,308 @@ static int mpt_pq_filter = 0;
98module_param(mpt_pq_filter, int, 0); 87module_param(mpt_pq_filter, int, 0);
99MODULE_PARM_DESC(mpt_pq_filter, " Enable peripheral qualifier filter: enable=1 (default=0)"); 88MODULE_PARM_DESC(mpt_pq_filter, " Enable peripheral qualifier filter: enable=1 (default=0)");
100 89
90static void mptspi_write_offset(struct scsi_target *, int);
91static void mptspi_write_width(struct scsi_target *, int);
92static int mptspi_write_spi_device_pg1(struct scsi_target *,
93 struct _CONFIG_PAGE_SCSI_DEVICE_1 *);
94
95static struct scsi_transport_template *mptspi_transport_template = NULL;
96
101static int mptspiDoneCtx = -1; 97static int mptspiDoneCtx = -1;
102static int mptspiTaskCtx = -1; 98static int mptspiTaskCtx = -1;
103static int mptspiInternalCtx = -1; /* Used only for internal commands */ 99static int mptspiInternalCtx = -1; /* Used only for internal commands */
104 100
101static int mptspi_target_alloc(struct scsi_target *starget)
102{
103 struct Scsi_Host *shost = dev_to_shost(&starget->dev);
104 struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata;
105 int ret;
106
107 if (hd == NULL)
108 return -ENODEV;
109
110 ret = mptscsih_target_alloc(starget);
111 if (ret)
112 return ret;
113
114 /* if we're a device on virtual channel 1 and we're not part
115 * of an array, just return here (otherwise the setup below
116 * may actually affect a real physical device on channel 0 */
117 if (starget->channel == 1 &&
118 mptscsih_raid_id_to_num(hd, starget->id) < 0)
119 return 0;
120
121 if (hd->ioc->spi_data.nvram &&
122 hd->ioc->spi_data.nvram[starget->id] != MPT_HOST_NVRAM_INVALID) {
123 u32 nvram = hd->ioc->spi_data.nvram[starget->id];
124 spi_min_period(starget) = (nvram & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT;
125 spi_max_width(starget) = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
126 } else {
127 spi_min_period(starget) = hd->ioc->spi_data.minSyncFactor;
128 spi_max_width(starget) = hd->ioc->spi_data.maxBusWidth;
129 }
130 spi_max_offset(starget) = hd->ioc->spi_data.maxSyncOffset;
131
132 spi_offset(starget) = 0;
133 mptspi_write_width(starget, 0);
134
135 return 0;
136}
137
138static int mptspi_read_spi_device_pg0(struct scsi_target *starget,
139 struct _CONFIG_PAGE_SCSI_DEVICE_0 *pass_pg0)
140{
141 struct Scsi_Host *shost = dev_to_shost(&starget->dev);
142 struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata;
143 struct _MPT_ADAPTER *ioc = hd->ioc;
144 struct _CONFIG_PAGE_SCSI_DEVICE_0 *pg0;
145 dma_addr_t pg0_dma;
146 int size;
147 struct _x_config_parms cfg;
148 struct _CONFIG_PAGE_HEADER hdr;
149 int err = -EBUSY;
150
151 /* No SPI parameters for RAID devices */
152 if (starget->channel == 0 &&
153 (hd->ioc->raid_data.isRaid & (1 << starget->id)))
154 return -1;
155
156 size = ioc->spi_data.sdp0length * 4;
157 /*
158 if (ioc->spi_data.sdp0length & 1)
159 size += size + 4;
160 size += 2048;
161 */
162
163 pg0 = dma_alloc_coherent(&ioc->pcidev->dev, size, &pg0_dma, GFP_KERNEL);
164 if (pg0 == NULL) {
165 starget_printk(KERN_ERR, starget, "dma_alloc_coherent for parameters failed\n");
166 return -EINVAL;
167 }
168
169 memset(&hdr, 0, sizeof(hdr));
170
171 hdr.PageVersion = ioc->spi_data.sdp0version;
172 hdr.PageLength = ioc->spi_data.sdp0length;
173 hdr.PageNumber = 0;
174 hdr.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
175
176 memset(&cfg, 0, sizeof(cfg));
177
178 cfg.cfghdr.hdr = &hdr;
179 cfg.physAddr = pg0_dma;
180 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
181 cfg.dir = 0;
182 cfg.pageAddr = starget->id;
183
184 if (mpt_config(ioc, &cfg)) {
185 starget_printk(KERN_ERR, starget, "mpt_config failed\n");
186 goto out_free;
187 }
188 err = 0;
189 memcpy(pass_pg0, pg0, size);
190
191 out_free:
192 dma_free_coherent(&ioc->pcidev->dev, size, pg0, pg0_dma);
193 return err;
194}
195
196static u32 mptspi_getRP(struct scsi_target *starget)
197{
198 u32 nego = 0;
199
200 nego |= spi_iu(starget) ? MPI_SCSIDEVPAGE1_RP_IU : 0;
201 nego |= spi_dt(starget) ? MPI_SCSIDEVPAGE1_RP_DT : 0;
202 nego |= spi_qas(starget) ? MPI_SCSIDEVPAGE1_RP_QAS : 0;
203 nego |= spi_hold_mcs(starget) ? MPI_SCSIDEVPAGE1_RP_HOLD_MCS : 0;
204 nego |= spi_wr_flow(starget) ? MPI_SCSIDEVPAGE1_RP_WR_FLOW : 0;
205 nego |= spi_rd_strm(starget) ? MPI_SCSIDEVPAGE1_RP_RD_STRM : 0;
206 nego |= spi_rti(starget) ? MPI_SCSIDEVPAGE1_RP_RTI : 0;
207 nego |= spi_pcomp_en(starget) ? MPI_SCSIDEVPAGE1_RP_PCOMP_EN : 0;
208
209 nego |= (spi_period(starget) << MPI_SCSIDEVPAGE1_RP_SHIFT_MIN_SYNC_PERIOD) & MPI_SCSIDEVPAGE1_RP_MIN_SYNC_PERIOD_MASK;
210 nego |= (spi_offset(starget) << MPI_SCSIDEVPAGE1_RP_SHIFT_MAX_SYNC_OFFSET) & MPI_SCSIDEVPAGE1_RP_MAX_SYNC_OFFSET_MASK;
211 nego |= spi_width(starget) ? MPI_SCSIDEVPAGE1_RP_WIDE : 0;
212
213 return nego;
214}
215
216static void mptspi_read_parameters(struct scsi_target *starget)
217{
218 int nego;
219 struct _CONFIG_PAGE_SCSI_DEVICE_0 pg0;
220
221 mptspi_read_spi_device_pg0(starget, &pg0);
222
223 nego = le32_to_cpu(pg0.NegotiatedParameters);
224
225 spi_iu(starget) = (nego & MPI_SCSIDEVPAGE0_NP_IU) ? 1 : 0;
226 spi_dt(starget) = (nego & MPI_SCSIDEVPAGE0_NP_DT) ? 1 : 0;
227 spi_qas(starget) = (nego & MPI_SCSIDEVPAGE0_NP_QAS) ? 1 : 0;
228 spi_wr_flow(starget) = (nego & MPI_SCSIDEVPAGE0_NP_WR_FLOW) ? 1 : 0;
229 spi_rd_strm(starget) = (nego & MPI_SCSIDEVPAGE0_NP_RD_STRM) ? 1 : 0;
230 spi_rti(starget) = (nego & MPI_SCSIDEVPAGE0_NP_RTI) ? 1 : 0;
231 spi_pcomp_en(starget) = (nego & MPI_SCSIDEVPAGE0_NP_PCOMP_EN) ? 1 : 0;
232 spi_hold_mcs(starget) = (nego & MPI_SCSIDEVPAGE0_NP_HOLD_MCS) ? 1 : 0;
233 spi_period(starget) = (nego & MPI_SCSIDEVPAGE0_NP_NEG_SYNC_PERIOD_MASK) >> MPI_SCSIDEVPAGE0_NP_SHIFT_SYNC_PERIOD;
234 spi_offset(starget) = (nego & MPI_SCSIDEVPAGE0_NP_NEG_SYNC_OFFSET_MASK) >> MPI_SCSIDEVPAGE0_NP_SHIFT_SYNC_OFFSET;
235 spi_width(starget) = (nego & MPI_SCSIDEVPAGE0_NP_WIDE) ? 1 : 0;
236}
237
238static int
239mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, int disk)
240{
241 MpiRaidActionRequest_t *pReq;
242 MPT_FRAME_HDR *mf;
243
244 /* Get and Populate a free Frame
245 */
246 if ((mf = mpt_get_msg_frame(hd->ioc->InternalCtx, hd->ioc)) == NULL) {
247 ddvprintk((MYIOC_s_WARN_FMT "_do_raid: no msg frames!\n",
248 hd->ioc->name));
249 return -EAGAIN;
250 }
251 pReq = (MpiRaidActionRequest_t *)mf;
252 if (quiesce)
253 pReq->Action = MPI_RAID_ACTION_QUIESCE_PHYS_IO;
254 else
255 pReq->Action = MPI_RAID_ACTION_ENABLE_PHYS_IO;
256 pReq->Reserved1 = 0;
257 pReq->ChainOffset = 0;
258 pReq->Function = MPI_FUNCTION_RAID_ACTION;
259 pReq->VolumeID = disk;
260 pReq->VolumeBus = 0;
261 pReq->PhysDiskNum = 0;
262 pReq->MsgFlags = 0;
263 pReq->Reserved2 = 0;
264 pReq->ActionDataWord = 0; /* Reserved for this action */
265
266 mpt_add_sge((char *)&pReq->ActionDataSGE,
267 MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1);
268
269 ddvprintk((MYIOC_s_INFO_FMT "RAID Volume action %x id %d\n",
270 hd->ioc->name, action, io->id));
271
272 hd->pLocal = NULL;
273 hd->timer.expires = jiffies + HZ*10; /* 10 second timeout */
274 hd->scandv_wait_done = 0;
275
276 /* Save cmd pointer, for resource free if timeout or
277 * FW reload occurs
278 */
279 hd->cmdPtr = mf;
280
281 add_timer(&hd->timer);
282 mpt_put_msg_frame(hd->ioc->InternalCtx, hd->ioc, mf);
283 wait_event(hd->scandv_waitq, hd->scandv_wait_done);
284
285 if ((hd->pLocal == NULL) || (hd->pLocal->completion != 0))
286 return -1;
287
288 return 0;
289}
290
291static void mptspi_dv_device(struct _MPT_SCSI_HOST *hd,
292 struct scsi_device *sdev)
293{
294 VirtTarget *vtarget = scsi_target(sdev)->hostdata;
295
296 /* no DV on RAID devices */
297 if (sdev->channel == 0 &&
298 (hd->ioc->raid_data.isRaid & (1 << sdev->id)))
299 return;
300
301 /* If this is a piece of a RAID, then quiesce first */
302 if (sdev->channel == 1 &&
303 mptscsih_quiesce_raid(hd, 1, vtarget->target_id) < 0) {
304 starget_printk(KERN_ERR, scsi_target(sdev),
305 "Integrated RAID quiesce failed\n");
306 return;
307 }
308
309 spi_dv_device(sdev);
310
311 if (sdev->channel == 1 &&
312 mptscsih_quiesce_raid(hd, 0, vtarget->target_id) < 0)
313 starget_printk(KERN_ERR, scsi_target(sdev),
314 "Integrated RAID resume failed\n");
315
316 mptspi_read_parameters(sdev->sdev_target);
317 spi_display_xfer_agreement(sdev->sdev_target);
318 mptspi_read_parameters(sdev->sdev_target);
319}
320
321static int mptspi_slave_alloc(struct scsi_device *sdev)
322{
323 int ret;
324 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sdev->host->hostdata;
325 /* gcc doesn't see that all uses of this variable occur within
326 * the if() statements, so stop it from whining */
327 int physdisknum = 0;
328
329 if (sdev->channel == 1) {
330 physdisknum = mptscsih_raid_id_to_num(hd, sdev->id);
331
332 if (physdisknum < 0)
333 return physdisknum;
334 }
335
336 ret = mptscsih_slave_alloc(sdev);
337
338 if (ret)
339 return ret;
340
341 if (sdev->channel == 1) {
342 VirtDevice *vdev = sdev->hostdata;
343 sdev->no_uld_attach = 1;
344 vdev->vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT;
345 /* The real channel for this device is zero */
346 vdev->bus_id = 0;
347 /* The actual physdisknum (for RAID passthrough) */
348 vdev->target_id = physdisknum;
349 }
350
351 return 0;
352}
353
354static int mptspi_slave_configure(struct scsi_device *sdev)
355{
356 int ret = mptscsih_slave_configure(sdev);
357 struct _MPT_SCSI_HOST *hd =
358 (struct _MPT_SCSI_HOST *)sdev->host->hostdata;
359
360 if (ret)
361 return ret;
362
363 if ((sdev->channel == 1 ||
364 !(hd->ioc->raid_data.isRaid & (1 << sdev->id))) &&
365 !spi_initial_dv(sdev->sdev_target))
366 mptspi_dv_device(hd, sdev);
367
368 return 0;
369}
370
371static void mptspi_slave_destroy(struct scsi_device *sdev)
372{
373 struct scsi_target *starget = scsi_target(sdev);
374 VirtTarget *vtarget = starget->hostdata;
375 VirtDevice *vdevice = sdev->hostdata;
376
377 /* Will this be the last lun on a non-raid device? */
378 if (vtarget->num_luns == 1 && vdevice->configured_lun) {
379 struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
380
381 /* Async Narrow */
382 pg1.RequestedParameters = 0;
383 pg1.Reserved = 0;
384 pg1.Configuration = 0;
385
386 mptspi_write_spi_device_pg1(starget, &pg1);
387 }
388
389 mptscsih_slave_destroy(sdev);
390}
391
105static struct scsi_host_template mptspi_driver_template = { 392static struct scsi_host_template mptspi_driver_template = {
106 .module = THIS_MODULE, 393 .module = THIS_MODULE,
107 .proc_name = "mptspi", 394 .proc_name = "mptspi",
@@ -109,11 +396,11 @@ static struct scsi_host_template mptspi_driver_template = {
109 .name = "MPT SPI Host", 396 .name = "MPT SPI Host",
110 .info = mptscsih_info, 397 .info = mptscsih_info,
111 .queuecommand = mptscsih_qcmd, 398 .queuecommand = mptscsih_qcmd,
112 .target_alloc = mptscsih_target_alloc, 399 .target_alloc = mptspi_target_alloc,
113 .slave_alloc = mptscsih_slave_alloc, 400 .slave_alloc = mptspi_slave_alloc,
114 .slave_configure = mptscsih_slave_configure, 401 .slave_configure = mptspi_slave_configure,
115 .target_destroy = mptscsih_target_destroy, 402 .target_destroy = mptscsih_target_destroy,
116 .slave_destroy = mptscsih_slave_destroy, 403 .slave_destroy = mptspi_slave_destroy,
117 .change_queue_depth = mptscsih_change_queue_depth, 404 .change_queue_depth = mptscsih_change_queue_depth,
118 .eh_abort_handler = mptscsih_abort, 405 .eh_abort_handler = mptscsih_abort,
119 .eh_device_reset_handler = mptscsih_dev_reset, 406 .eh_device_reset_handler = mptscsih_dev_reset,
@@ -128,6 +415,360 @@ static struct scsi_host_template mptspi_driver_template = {
128 .use_clustering = ENABLE_CLUSTERING, 415 .use_clustering = ENABLE_CLUSTERING,
129}; 416};
130 417
418static int mptspi_write_spi_device_pg1(struct scsi_target *starget,
419 struct _CONFIG_PAGE_SCSI_DEVICE_1 *pass_pg1)
420{
421 struct Scsi_Host *shost = dev_to_shost(&starget->dev);
422 struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata;
423 struct _MPT_ADAPTER *ioc = hd->ioc;
424 struct _CONFIG_PAGE_SCSI_DEVICE_1 *pg1;
425 dma_addr_t pg1_dma;
426 int size;
427 struct _x_config_parms cfg;
428 struct _CONFIG_PAGE_HEADER hdr;
429 int err = -EBUSY;
430
431 /* don't allow updating nego parameters on RAID devices */
432 if (starget->channel == 0 &&
433 (hd->ioc->raid_data.isRaid & (1 << starget->id)))
434 return -1;
435
436 size = ioc->spi_data.sdp1length * 4;
437
438 pg1 = dma_alloc_coherent(&ioc->pcidev->dev, size, &pg1_dma, GFP_KERNEL);
439 if (pg1 == NULL) {
440 starget_printk(KERN_ERR, starget, "dma_alloc_coherent for parameters failed\n");
441 return -EINVAL;
442 }
443
444 memset(&hdr, 0, sizeof(hdr));
445
446 hdr.PageVersion = ioc->spi_data.sdp1version;
447 hdr.PageLength = ioc->spi_data.sdp1length;
448 hdr.PageNumber = 1;
449 hdr.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
450
451 memset(&cfg, 0, sizeof(cfg));
452
453 cfg.cfghdr.hdr = &hdr;
454 cfg.physAddr = pg1_dma;
455 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
456 cfg.dir = 1;
457 cfg.pageAddr = starget->id;
458
459 memcpy(pg1, pass_pg1, size);
460
461 pg1->Header.PageVersion = hdr.PageVersion;
462 pg1->Header.PageLength = hdr.PageLength;
463 pg1->Header.PageNumber = hdr.PageNumber;
464 pg1->Header.PageType = hdr.PageType;
465
466 if (mpt_config(ioc, &cfg)) {
467 starget_printk(KERN_ERR, starget, "mpt_config failed\n");
468 goto out_free;
469 }
470 err = 0;
471
472 out_free:
473 dma_free_coherent(&ioc->pcidev->dev, size, pg1, pg1_dma);
474 return err;
475}
476
477static void mptspi_write_offset(struct scsi_target *starget, int offset)
478{
479 struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
480 u32 nego;
481
482 if (offset < 0)
483 offset = 0;
484
485 if (offset > 255)
486 offset = 255;
487
488 if (spi_offset(starget) == -1)
489 mptspi_read_parameters(starget);
490
491 spi_offset(starget) = offset;
492
493 nego = mptspi_getRP(starget);
494
495 pg1.RequestedParameters = cpu_to_le32(nego);
496 pg1.Reserved = 0;
497 pg1.Configuration = 0;
498
499 mptspi_write_spi_device_pg1(starget, &pg1);
500}
501
502static void mptspi_write_period(struct scsi_target *starget, int period)
503{
504 struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
505 u32 nego;
506
507 if (period < 8)
508 period = 8;
509
510 if (period > 255)
511 period = 255;
512
513 if (spi_period(starget) == -1)
514 mptspi_read_parameters(starget);
515
516 if (period == 8) {
517 spi_iu(starget) = 1;
518 spi_dt(starget) = 1;
519 } else if (period == 9) {
520 spi_dt(starget) = 1;
521 }
522
523 spi_period(starget) = period;
524
525 nego = mptspi_getRP(starget);
526
527 pg1.RequestedParameters = cpu_to_le32(nego);
528 pg1.Reserved = 0;
529 pg1.Configuration = 0;
530
531 mptspi_write_spi_device_pg1(starget, &pg1);
532}
533
534static void mptspi_write_dt(struct scsi_target *starget, int dt)
535{
536 struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
537 u32 nego;
538
539 if (spi_period(starget) == -1)
540 mptspi_read_parameters(starget);
541
542 if (!dt && spi_period(starget) < 10)
543 spi_period(starget) = 10;
544
545 spi_dt(starget) = dt;
546
547 nego = mptspi_getRP(starget);
548
549
550 pg1.RequestedParameters = cpu_to_le32(nego);
551 pg1.Reserved = 0;
552 pg1.Configuration = 0;
553
554 mptspi_write_spi_device_pg1(starget, &pg1);
555}
556
557static void mptspi_write_iu(struct scsi_target *starget, int iu)
558{
559 struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
560 u32 nego;
561
562 if (spi_period(starget) == -1)
563 mptspi_read_parameters(starget);
564
565 if (!iu && spi_period(starget) < 9)
566 spi_period(starget) = 9;
567
568 spi_iu(starget) = iu;
569
570 nego = mptspi_getRP(starget);
571
572 pg1.RequestedParameters = cpu_to_le32(nego);
573 pg1.Reserved = 0;
574 pg1.Configuration = 0;
575
576 mptspi_write_spi_device_pg1(starget, &pg1);
577}
578
579#define MPTSPI_SIMPLE_TRANSPORT_PARM(parm) \
580static void mptspi_write_##parm(struct scsi_target *starget, int parm)\
581{ \
582 struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1; \
583 u32 nego; \
584 \
585 spi_##parm(starget) = parm; \
586 \
587 nego = mptspi_getRP(starget); \
588 \
589 pg1.RequestedParameters = cpu_to_le32(nego); \
590 pg1.Reserved = 0; \
591 pg1.Configuration = 0; \
592 \
593 mptspi_write_spi_device_pg1(starget, &pg1); \
594}
595
596MPTSPI_SIMPLE_TRANSPORT_PARM(rd_strm)
597MPTSPI_SIMPLE_TRANSPORT_PARM(wr_flow)
598MPTSPI_SIMPLE_TRANSPORT_PARM(rti)
599MPTSPI_SIMPLE_TRANSPORT_PARM(hold_mcs)
600MPTSPI_SIMPLE_TRANSPORT_PARM(pcomp_en)
601
602static void mptspi_write_qas(struct scsi_target *starget, int qas)
603{
604 struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
605 struct Scsi_Host *shost = dev_to_shost(&starget->dev);
606 struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata;
607 VirtTarget *vtarget = starget->hostdata;
608 u32 nego;
609
610 if ((vtarget->negoFlags & MPT_TARGET_NO_NEGO_QAS) ||
611 hd->ioc->spi_data.noQas)
612 spi_qas(starget) = 0;
613 else
614 spi_qas(starget) = qas;
615
616 nego = mptspi_getRP(starget);
617
618 pg1.RequestedParameters = cpu_to_le32(nego);
619 pg1.Reserved = 0;
620 pg1.Configuration = 0;
621
622 mptspi_write_spi_device_pg1(starget, &pg1);
623}
624
625static void mptspi_write_width(struct scsi_target *starget, int width)
626{
627 struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
628 u32 nego;
629
630 if (!width) {
631 spi_dt(starget) = 0;
632 if (spi_period(starget) < 10)
633 spi_period(starget) = 10;
634 }
635
636 spi_width(starget) = width;
637
638 nego = mptspi_getRP(starget);
639
640 pg1.RequestedParameters = cpu_to_le32(nego);
641 pg1.Reserved = 0;
642 pg1.Configuration = 0;
643
644 mptspi_write_spi_device_pg1(starget, &pg1);
645}
646
647struct work_queue_wrapper {
648 struct work_struct work;
649 struct _MPT_SCSI_HOST *hd;
650 int disk;
651};
652
653static void mpt_work_wrapper(void *data)
654{
655 struct work_queue_wrapper *wqw = (struct work_queue_wrapper *)data;
656 struct _MPT_SCSI_HOST *hd = wqw->hd;
657 struct Scsi_Host *shost = hd->ioc->sh;
658 struct scsi_device *sdev;
659 int disk = wqw->disk;
660 struct _CONFIG_PAGE_IOC_3 *pg3;
661
662 kfree(wqw);
663
664 mpt_findImVolumes(hd->ioc);
665 pg3 = hd->ioc->raid_data.pIocPg3;
666 if (!pg3)
667 return;
668
669 shost_for_each_device(sdev,shost) {
670 struct scsi_target *starget = scsi_target(sdev);
671 VirtTarget *vtarget = starget->hostdata;
672
673 /* only want to search RAID components */
674 if (sdev->channel != 1)
675 continue;
676
677 /* The target_id is the raid PhysDiskNum, even if
678 * starget->id is the actual target address */
679 if(vtarget->target_id != disk)
680 continue;
681
682 starget_printk(KERN_INFO, vtarget->starget,
683 "Integrated RAID requests DV of new device\n");
684 mptspi_dv_device(hd, sdev);
685 }
686 shost_printk(KERN_INFO, shost,
687 "Integrated RAID detects new device %d\n", disk);
688 scsi_scan_target(&hd->ioc->sh->shost_gendev, 1, disk, 0, 1);
689}
690
691
692static void mpt_dv_raid(struct _MPT_SCSI_HOST *hd, int disk)
693{
694 struct work_queue_wrapper *wqw = kmalloc(sizeof(*wqw), GFP_ATOMIC);
695
696 if (!wqw) {
697 shost_printk(KERN_ERR, hd->ioc->sh,
698 "Failed to act on RAID event for physical disk %d\n",
699 disk);
700 return;
701 }
702 INIT_WORK(&wqw->work, mpt_work_wrapper, wqw);
703 wqw->hd = hd;
704 wqw->disk = disk;
705
706 schedule_work(&wqw->work);
707}
708
709static int
710mptspi_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
711{
712 u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
713 struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)ioc->sh->hostdata;
714
715 if (hd && event == MPI_EVENT_INTEGRATED_RAID) {
716 int reason
717 = (le32_to_cpu(pEvReply->Data[0]) & 0x00FF0000) >> 16;
718
719 if (reason == MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) {
720 int disk = (le32_to_cpu(pEvReply->Data[0]) & 0xFF000000) >> 24;
721 mpt_dv_raid(hd, disk);
722 }
723 }
724 return mptscsih_event_process(ioc, pEvReply);
725}
726
727static int
728mptspi_deny_binding(struct scsi_target *starget)
729{
730 struct _MPT_SCSI_HOST *hd =
731 (struct _MPT_SCSI_HOST *)dev_to_shost(starget->dev.parent)->hostdata;
732 return ((hd->ioc->raid_data.isRaid & (1 << starget->id)) &&
733 starget->channel == 0) ? 1 : 0;
734}
735
736static struct spi_function_template mptspi_transport_functions = {
737 .get_offset = mptspi_read_parameters,
738 .set_offset = mptspi_write_offset,
739 .show_offset = 1,
740 .get_period = mptspi_read_parameters,
741 .set_period = mptspi_write_period,
742 .show_period = 1,
743 .get_width = mptspi_read_parameters,
744 .set_width = mptspi_write_width,
745 .show_width = 1,
746 .get_iu = mptspi_read_parameters,
747 .set_iu = mptspi_write_iu,
748 .show_iu = 1,
749 .get_dt = mptspi_read_parameters,
750 .set_dt = mptspi_write_dt,
751 .show_dt = 1,
752 .get_qas = mptspi_read_parameters,
753 .set_qas = mptspi_write_qas,
754 .show_qas = 1,
755 .get_wr_flow = mptspi_read_parameters,
756 .set_wr_flow = mptspi_write_wr_flow,
757 .show_wr_flow = 1,
758 .get_rd_strm = mptspi_read_parameters,
759 .set_rd_strm = mptspi_write_rd_strm,
760 .show_rd_strm = 1,
761 .get_rti = mptspi_read_parameters,
762 .set_rti = mptspi_write_rti,
763 .show_rti = 1,
764 .get_pcomp_en = mptspi_read_parameters,
765 .set_pcomp_en = mptspi_write_pcomp_en,
766 .show_pcomp_en = 1,
767 .get_hold_mcs = mptspi_read_parameters,
768 .set_hold_mcs = mptspi_write_hold_mcs,
769 .show_hold_mcs = 1,
770 .deny_binding = mptspi_deny_binding,
771};
131 772
132/**************************************************************************** 773/****************************************************************************
133 * Supported hardware 774 * Supported hardware
@@ -242,7 +883,14 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
242 sh->max_id = MPT_MAX_SCSI_DEVICES; 883 sh->max_id = MPT_MAX_SCSI_DEVICES;
243 884
244 sh->max_lun = MPT_LAST_LUN + 1; 885 sh->max_lun = MPT_LAST_LUN + 1;
245 sh->max_channel = 0; 886 /*
887 * If RAID Firmware Detected, setup virtual channel
888 */
889 if ((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK)
890 > MPI_FW_HEADER_PID_PROD_TARGET_SCSI)
891 sh->max_channel = 1;
892 else
893 sh->max_channel = 0;
246 sh->this_id = ioc->pfacts[0].PortSCSIID; 894 sh->this_id = ioc->pfacts[0].PortSCSIID;
247 895
248 /* Required entry. 896 /* Required entry.
@@ -301,7 +949,8 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
301 * indicates a device exists. 949 * indicates a device exists.
302 * max_id = 1 + maximum id (hosts.h) 950 * max_id = 1 + maximum id (hosts.h)
303 */ 951 */
304 hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC); 952 hd->Targets = kcalloc(sh->max_id * (sh->max_channel + 1),
953 sizeof(void *), GFP_ATOMIC);
305 if (!hd->Targets) { 954 if (!hd->Targets) {
306 error = -ENOMEM; 955 error = -ENOMEM;
307 goto out_mptspi_probe; 956 goto out_mptspi_probe;
@@ -334,49 +983,23 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
334 ioc->spi_data.Saf_Te = mpt_saf_te; 983 ioc->spi_data.Saf_Te = mpt_saf_te;
335 hd->mpt_pq_filter = mpt_pq_filter; 984 hd->mpt_pq_filter = mpt_pq_filter;
336 985
337#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
338 if (ioc->spi_data.maxBusWidth > mpt_width)
339 ioc->spi_data.maxBusWidth = mpt_width;
340 if (ioc->spi_data.minSyncFactor < mpt_factor)
341 ioc->spi_data.minSyncFactor = mpt_factor;
342 if (ioc->spi_data.minSyncFactor == MPT_ASYNC) {
343 ioc->spi_data.maxSyncOffset = 0;
344 }
345 ioc->spi_data.mpt_dv = mpt_dv;
346 hd->negoNvram = 0;
347
348 ddvprintk((MYIOC_s_INFO_FMT
349 "dv %x width %x factor %x saf_te %x mpt_pq_filter %x\n",
350 ioc->name,
351 mpt_dv,
352 mpt_width,
353 mpt_factor,
354 mpt_saf_te,
355 mpt_pq_filter));
356#else
357 hd->negoNvram = MPT_SCSICFG_USE_NVRAM; 986 hd->negoNvram = MPT_SCSICFG_USE_NVRAM;
358 ddvprintk((MYIOC_s_INFO_FMT 987 ddvprintk((MYIOC_s_INFO_FMT
359 "saf_te %x mpt_pq_filter %x\n", 988 "saf_te %x mpt_pq_filter %x\n",
360 ioc->name, 989 ioc->name,
361 mpt_saf_te, 990 mpt_saf_te,
362 mpt_pq_filter)); 991 mpt_pq_filter));
363#endif
364
365 ioc->spi_data.forceDv = 0;
366 ioc->spi_data.noQas = 0; 992 ioc->spi_data.noQas = 0;
367 993
368 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++)
369 ioc->spi_data.dvStatus[ii] =
370 MPT_SCSICFG_NEGOTIATE;
371
372 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++)
373 ioc->spi_data.dvStatus[ii] |=
374 MPT_SCSICFG_DV_NOT_DONE;
375
376 init_waitqueue_head(&hd->scandv_waitq); 994 init_waitqueue_head(&hd->scandv_waitq);
377 hd->scandv_wait_done = 0; 995 hd->scandv_wait_done = 0;
378 hd->last_queue_full = 0; 996 hd->last_queue_full = 0;
379 997
998 /* Some versions of the firmware don't support page 0; without
999 * that we can't get the parameters */
1000 if (hd->ioc->spi_data.sdp0length != 0)
1001 sh->transportt = mptspi_transport_template;
1002
380 error = scsi_add_host (sh, &ioc->pcidev->dev); 1003 error = scsi_add_host (sh, &ioc->pcidev->dev);
381 if(error) { 1004 if(error) {
382 dprintk((KERN_ERR MYNAM 1005 dprintk((KERN_ERR MYNAM
@@ -423,14 +1046,17 @@ static struct pci_driver mptspi_driver = {
423static int __init 1046static int __init
424mptspi_init(void) 1047mptspi_init(void)
425{ 1048{
426
427 show_mptmod_ver(my_NAME, my_VERSION); 1049 show_mptmod_ver(my_NAME, my_VERSION);
428 1050
1051 mptspi_transport_template = spi_attach_transport(&mptspi_transport_functions);
1052 if (!mptspi_transport_template)
1053 return -ENODEV;
1054
429 mptspiDoneCtx = mpt_register(mptscsih_io_done, MPTSPI_DRIVER); 1055 mptspiDoneCtx = mpt_register(mptscsih_io_done, MPTSPI_DRIVER);
430 mptspiTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSPI_DRIVER); 1056 mptspiTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSPI_DRIVER);
431 mptspiInternalCtx = mpt_register(mptscsih_scandv_complete, MPTSPI_DRIVER); 1057 mptspiInternalCtx = mpt_register(mptscsih_scandv_complete, MPTSPI_DRIVER);
432 1058
433 if (mpt_event_register(mptspiDoneCtx, mptscsih_event_process) == 0) { 1059 if (mpt_event_register(mptspiDoneCtx, mptspi_event_process) == 0) {
434 devtprintk((KERN_INFO MYNAM 1060 devtprintk((KERN_INFO MYNAM
435 ": Registered for IOC event notifications\n")); 1061 ": Registered for IOC event notifications\n"));
436 } 1062 }
@@ -465,6 +1091,7 @@ mptspi_exit(void)
465 mpt_deregister(mptspiInternalCtx); 1091 mpt_deregister(mptspiInternalCtx);
466 mpt_deregister(mptspiTaskCtx); 1092 mpt_deregister(mptspiTaskCtx);
467 mpt_deregister(mptspiDoneCtx); 1093 mpt_deregister(mptspiDoneCtx);
1094 spi_release_transport(mptspi_transport_template);
468} 1095}
469 1096
470module_init(mptspi_init); 1097module_init(mptspi_init);