blob: f2a4d382ea19e5403b2d2643b5a301476ae3f718 [file] [log] [blame]
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001/*
2 * linux/drivers/message/fusion/mptspi.c
3 * For use with LSI Logic PCI chip/adapter(s)
4 * running LSI Logic Fusion MPT (Message Passing Technology) firmware.
5 *
6 * Copyright (c) 1999-2005 LSI Logic Corporation
7 * (mailto:mpt_linux_developer@lsil.com)
8 *
9 */
10/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
11/*
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; version 2 of the License.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 NO WARRANTY
22 THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
23 CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
24 LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
25 MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
26 solely responsible for determining the appropriateness of using and
27 distributing the Program and assumes all risks associated with its
28 exercise of rights under this Agreement, including but not limited to
29 the risks and costs of program errors, damage to or loss of data,
30 programs or equipment, and unavailability or interruption of operations.
31
32 DISCLAIMER OF LIABILITY
33 NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
34 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35 DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
36 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
37 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
38 USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
39 HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
40
41 You should have received a copy of the GNU General Public License
42 along with this program; if not, write to the Free Software
43 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
44*/
45/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
46
47#include "linux_compat.h" /* linux-2.6 tweaks */
48#include <linux/module.h>
49#include <linux/kernel.h>
50#include <linux/init.h>
51#include <linux/errno.h>
52#include <linux/kdev_t.h>
53#include <linux/blkdev.h>
54#include <linux/delay.h> /* for mdelay */
55#include <linux/interrupt.h> /* needed for in_interrupt() proto */
56#include <linux/reboot.h> /* notifier code */
57#include <linux/sched.h>
58#include <linux/workqueue.h>
James Bottomleyc92f2222006-03-01 09:02:49 -060059#include <linux/raid_class.h>
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -040060
61#include <scsi/scsi.h>
62#include <scsi/scsi_cmnd.h>
63#include <scsi/scsi_device.h>
64#include <scsi/scsi_host.h>
65#include <scsi/scsi_tcq.h>
James Bottomleyc92f2222006-03-01 09:02:49 -060066#include <scsi/scsi_transport.h>
67#include <scsi/scsi_transport_spi.h>
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -040068
69#include "mptbase.h"
70#include "mptscsih.h"
71
72/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
73#define my_NAME "Fusion MPT SPI Host driver"
74#define my_VERSION MPT_LINUX_VERSION_COMMON
75#define MYNAM "mptspi"
76
77MODULE_AUTHOR(MODULEAUTHOR);
78MODULE_DESCRIPTION(my_NAME);
79MODULE_LICENSE("GPL");
80
81/* Command line args */
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -040082static int mpt_saf_te = MPTSCSIH_SAF_TE;
83module_param(mpt_saf_te, int, 0);
84MODULE_PARM_DESC(mpt_saf_te, " Force enabling SEP Processor: enable=1 (default=MPTSCSIH_SAF_TE=0)");
85
86static int mpt_pq_filter = 0;
87module_param(mpt_pq_filter, int, 0);
88MODULE_PARM_DESC(mpt_pq_filter, " Enable peripheral qualifier filter: enable=1 (default=0)");
89
James Bottomleyc92f2222006-03-01 09:02:49 -060090static 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
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -040097static int mptspiDoneCtx = -1;
98static int mptspiTaskCtx = -1;
99static int mptspiInternalCtx = -1; /* Used only for internal commands */
100
James Bottomleyc92f2222006-03-01 09:02:49 -0600101static 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 */
Moore, Eric914c2d82006-03-14 09:19:36 -0700346 vdev->vtarget->bus_id = 0;
James Bottomleyc92f2222006-03-01 09:02:49 -0600347 /* The actual physdisknum (for RAID passthrough) */
Moore, Eric914c2d82006-03-14 09:19:36 -0700348 vdev->vtarget->target_id = physdisknum;
James Bottomleyc92f2222006-03-01 09:02:49 -0600349 }
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
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -0400392static struct scsi_host_template mptspi_driver_template = {
Moore, Eric Deanf78496d2005-11-16 18:54:14 -0700393 .module = THIS_MODULE,
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -0400394 .proc_name = "mptspi",
395 .proc_info = mptscsih_proc_info,
396 .name = "MPT SPI Host",
397 .info = mptscsih_info,
398 .queuecommand = mptscsih_qcmd,
James Bottomleyc92f2222006-03-01 09:02:49 -0600399 .target_alloc = mptspi_target_alloc,
400 .slave_alloc = mptspi_slave_alloc,
401 .slave_configure = mptspi_slave_configure,
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700402 .target_destroy = mptscsih_target_destroy,
James Bottomleyc92f2222006-03-01 09:02:49 -0600403 .slave_destroy = mptspi_slave_destroy,
Moore, Eric Dean6e3815b2005-06-24 12:18:57 -0600404 .change_queue_depth = mptscsih_change_queue_depth,
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -0400405 .eh_abort_handler = mptscsih_abort,
406 .eh_device_reset_handler = mptscsih_dev_reset,
407 .eh_bus_reset_handler = mptscsih_bus_reset,
408 .eh_host_reset_handler = mptscsih_host_reset,
409 .bios_param = mptscsih_bios_param,
410 .can_queue = MPT_SCSI_CAN_QUEUE,
411 .this_id = -1,
412 .sg_tablesize = MPT_SCSI_SG_DEPTH,
413 .max_sectors = 8192,
414 .cmd_per_lun = 7,
415 .use_clustering = ENABLE_CLUSTERING,
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -0400416};
417
James Bottomleyc92f2222006-03-01 09:02:49 -0600418static 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};
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -0400772
773/****************************************************************************
774 * Supported hardware
775 */
776
777static struct pci_device_id mptspi_pci_table[] = {
778 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_53C1030,
779 PCI_ANY_ID, PCI_ANY_ID },
780 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_1030_53C1035,
781 PCI_ANY_ID, PCI_ANY_ID },
782 {0} /* Terminating entry */
783};
784MODULE_DEVICE_TABLE(pci, mptspi_pci_table);
785
Eric Moore6e1cad02006-04-25 17:38:58 -0600786
787/*
788 * renegotiate for a given target
789 */
790static void
791mptspi_dv_renegotiate_work(void *data)
792{
793 struct work_queue_wrapper *wqw = (struct work_queue_wrapper *)data;
794 struct _MPT_SCSI_HOST *hd = wqw->hd;
795 struct scsi_device *sdev;
796
797 kfree(wqw);
798
799 shost_for_each_device(sdev, hd->ioc->sh)
800 mptspi_dv_device(hd, sdev);
801}
802
803static void
804mptspi_dv_renegotiate(struct _MPT_SCSI_HOST *hd)
805{
806 struct work_queue_wrapper *wqw = kmalloc(sizeof(*wqw), GFP_ATOMIC);
807
808 if (!wqw)
809 return;
810
811 INIT_WORK(&wqw->work, mptspi_dv_renegotiate_work, wqw);
812 wqw->hd = hd;
813
814 schedule_work(&wqw->work);
815}
816
817/*
818 * spi module reset handler
819 */
820static int
821mptspi_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
822{
823 struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)ioc->sh->hostdata;
824 int rc;
825
826 rc = mptscsih_ioc_reset(ioc, reset_phase);
827
828 if (reset_phase == MPT_IOC_POST_RESET)
829 mptspi_dv_renegotiate(hd);
830
831 return rc;
832}
833
834/*
835 * spi module resume handler
836 */
837static int
838mptspi_resume(struct pci_dev *pdev)
839{
840 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
841 struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)ioc->sh->hostdata;
842 int rc;
843
844 rc = mptscsih_resume(pdev);
845 mptspi_dv_renegotiate(hd);
846
847 return rc;
848}
849
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -0400850/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
851/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
852/*
853 * mptspi_probe - Installs scsi devices per bus.
854 * @pdev: Pointer to pci_dev structure
855 *
856 * Returns 0 for success, non-zero for failure.
857 *
858 */
859static int
860mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
861{
862 struct Scsi_Host *sh;
863 MPT_SCSI_HOST *hd;
864 MPT_ADAPTER *ioc;
865 unsigned long flags;
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +0100866 int ii;
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -0400867 int numSGE = 0;
868 int scale;
869 int ioc_cap;
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -0400870 int error=0;
871 int r;
Christoph Hellwigc6678e02005-08-18 16:24:53 +0200872
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -0400873 if ((r = mpt_attach(pdev,id)) != 0)
874 return r;
Christoph Hellwigc6678e02005-08-18 16:24:53 +0200875
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -0400876 ioc = pci_get_drvdata(pdev);
Moore, Eric Dean d335cc32005-04-30 17:09:38 -0500877 ioc->DoneCtx = mptspiDoneCtx;
878 ioc->TaskCtx = mptspiTaskCtx;
879 ioc->InternalCtx = mptspiInternalCtx;
Christoph Hellwigc6678e02005-08-18 16:24:53 +0200880
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -0400881 /* Added sanity check on readiness of the MPT adapter.
882 */
883 if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
884 printk(MYIOC_s_WARN_FMT
885 "Skipping because it's not operational!\n",
886 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -0700887 error = -ENODEV;
888 goto out_mptspi_probe;
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -0400889 }
890
891 if (!ioc->active) {
892 printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
893 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -0700894 error = -ENODEV;
895 goto out_mptspi_probe;
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -0400896 }
897
898 /* Sanity check - ensure at least 1 port is INITIATOR capable
899 */
900 ioc_cap = 0;
901 for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
902 if (ioc->pfacts[ii].ProtocolFlags &
903 MPI_PORTFACTS_PROTOCOL_INITIATOR)
904 ioc_cap ++;
905 }
906
907 if (!ioc_cap) {
908 printk(MYIOC_s_WARN_FMT
909 "Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n",
910 ioc->name, ioc);
Moore, Eric Dean466544d2005-09-14 18:09:10 -0600911 return 0;
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -0400912 }
913
914 sh = scsi_host_alloc(&mptspi_driver_template, sizeof(MPT_SCSI_HOST));
915
916 if (!sh) {
917 printk(MYIOC_s_WARN_FMT
918 "Unable to register controller with SCSI subsystem\n",
919 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -0700920 error = -1;
921 goto out_mptspi_probe;
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -0400922 }
923
924 spin_lock_irqsave(&ioc->FreeQlock, flags);
925
926 /* Attach the SCSI Host to the IOC structure
927 */
928 ioc->sh = sh;
929
930 sh->io_port = 0;
931 sh->n_io_port = 0;
932 sh->irq = 0;
933
934 /* set 16 byte cdb's */
935 sh->max_cmd_len = 16;
936
937 /* Yikes! This is important!
938 * Otherwise, by default, linux
939 * only scans target IDs 0-7!
940 * pfactsN->MaxDevices unreliable
941 * (not supported in early
942 * versions of the FW).
943 * max_id = 1 + actual max id,
944 * max_lun = 1 + actual last lun,
945 * see hosts.h :o(
946 */
947 sh->max_id = MPT_MAX_SCSI_DEVICES;
948
949 sh->max_lun = MPT_LAST_LUN + 1;
James Bottomleyc92f2222006-03-01 09:02:49 -0600950 /*
951 * If RAID Firmware Detected, setup virtual channel
952 */
953 if ((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK)
954 > MPI_FW_HEADER_PID_PROD_TARGET_SCSI)
955 sh->max_channel = 1;
956 else
957 sh->max_channel = 0;
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -0400958 sh->this_id = ioc->pfacts[0].PortSCSIID;
959
960 /* Required entry.
961 */
962 sh->unique_id = ioc->id;
963
964 /* Verify that we won't exceed the maximum
965 * number of chain buffers
966 * We can optimize: ZZ = req_sz/sizeof(SGE)
967 * For 32bit SGE's:
968 * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
969 * + (req_sz - 64)/sizeof(SGE)
970 * A slightly different algorithm is required for
971 * 64bit SGEs.
972 */
973 scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
974 if (sizeof(dma_addr_t) == sizeof(u64)) {
975 numSGE = (scale - 1) *
976 (ioc->facts.MaxChainDepth-1) + scale +
977 (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
978 sizeof(u32));
979 } else {
980 numSGE = 1 + (scale - 1) *
981 (ioc->facts.MaxChainDepth-1) + scale +
982 (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
983 sizeof(u32));
984 }
985
986 if (numSGE < sh->sg_tablesize) {
987 /* Reset this value */
988 dprintk((MYIOC_s_INFO_FMT
989 "Resetting sg_tablesize to %d from %d\n",
990 ioc->name, numSGE, sh->sg_tablesize));
991 sh->sg_tablesize = numSGE;
992 }
993
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -0400994 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
995
996 hd = (MPT_SCSI_HOST *) sh->hostdata;
997 hd->ioc = ioc;
998
999 /* SCSI needs scsi_cmnd lookup table!
1000 * (with size equal to req_depth*PtrSz!)
1001 */
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001002 hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
1003 if (!hd->ScsiLookup) {
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001004 error = -ENOMEM;
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001005 goto out_mptspi_probe;
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001006 }
1007
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001008 dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
1009 ioc->name, hd->ScsiLookup));
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001010
1011 /* Allocate memory for the device structures.
1012 * A non-Null pointer at an offset
1013 * indicates a device exists.
1014 * max_id = 1 + maximum id (hosts.h)
1015 */
James Bottomleyc92f2222006-03-01 09:02:49 -06001016 hd->Targets = kcalloc(sh->max_id * (sh->max_channel + 1),
1017 sizeof(void *), GFP_ATOMIC);
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001018 if (!hd->Targets) {
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001019 error = -ENOMEM;
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001020 goto out_mptspi_probe;
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001021 }
1022
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001023 dprintk((KERN_INFO " vdev @ %p\n", hd->Targets));
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001024
1025 /* Clear the TM flags
1026 */
1027 hd->tmPending = 0;
1028 hd->tmState = TM_STATE_NONE;
1029 hd->resetPending = 0;
1030 hd->abortSCpnt = NULL;
1031
1032 /* Clear the pointer used to store
1033 * single-threaded commands, i.e., those
1034 * issued during a bus scan, dv and
1035 * configuration pages.
1036 */
1037 hd->cmdPtr = NULL;
1038
1039 /* Initialize this SCSI Hosts' timers
1040 * To use, set the timer expires field
1041 * and add_timer
1042 */
1043 init_timer(&hd->timer);
1044 hd->timer.data = (unsigned long) hd;
1045 hd->timer.function = mptscsih_timer_expired;
1046
1047 ioc->spi_data.Saf_Te = mpt_saf_te;
1048 hd->mpt_pq_filter = mpt_pq_filter;
1049
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001050 hd->negoNvram = MPT_SCSICFG_USE_NVRAM;
1051 ddvprintk((MYIOC_s_INFO_FMT
1052 "saf_te %x mpt_pq_filter %x\n",
1053 ioc->name,
1054 mpt_saf_te,
1055 mpt_pq_filter));
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001056 ioc->spi_data.noQas = 0;
1057
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001058 init_waitqueue_head(&hd->scandv_waitq);
1059 hd->scandv_wait_done = 0;
1060 hd->last_queue_full = 0;
1061
James Bottomleyc92f2222006-03-01 09:02:49 -06001062 /* Some versions of the firmware don't support page 0; without
1063 * that we can't get the parameters */
1064 if (hd->ioc->spi_data.sdp0length != 0)
1065 sh->transportt = mptspi_transport_template;
1066
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001067 error = scsi_add_host (sh, &ioc->pcidev->dev);
1068 if(error) {
1069 dprintk((KERN_ERR MYNAM
1070 "scsi_add_host failed\n"));
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001071 goto out_mptspi_probe;
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001072 }
1073
Moore, Ericd8e925d2006-01-16 18:53:06 -07001074 /*
1075 * issue internal bus reset
1076 */
1077 if (ioc->spi_data.bus_reset)
1078 mptscsih_TMHandler(hd,
1079 MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
1080 0, 0, 0, 0, 5);
1081
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001082 scsi_scan_host(sh);
1083 return 0;
1084
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001085out_mptspi_probe:
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001086
1087 mptscsih_remove(pdev);
1088 return error;
1089}
1090
1091static struct pci_driver mptspi_driver = {
1092 .name = "mptspi",
1093 .id_table = mptspi_pci_table,
1094 .probe = mptspi_probe,
1095 .remove = __devexit_p(mptscsih_remove),
Greg Kroah-Hartmand18c3db2005-06-23 17:35:56 -07001096 .shutdown = mptscsih_shutdown,
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001097#ifdef CONFIG_PM
1098 .suspend = mptscsih_suspend,
Eric Moore6e1cad02006-04-25 17:38:58 -06001099 .resume = mptspi_resume,
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001100#endif
1101};
1102
1103/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1104/**
1105 * mptspi_init - Register MPT adapter(s) as SCSI host(s) with
1106 * linux scsi mid-layer.
1107 *
1108 * Returns 0 for success, non-zero for failure.
1109 */
1110static int __init
1111mptspi_init(void)
1112{
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001113 show_mptmod_ver(my_NAME, my_VERSION);
1114
James Bottomleyc92f2222006-03-01 09:02:49 -06001115 mptspi_transport_template = spi_attach_transport(&mptspi_transport_functions);
1116 if (!mptspi_transport_template)
1117 return -ENODEV;
1118
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001119 mptspiDoneCtx = mpt_register(mptscsih_io_done, MPTSPI_DRIVER);
1120 mptspiTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSPI_DRIVER);
1121 mptspiInternalCtx = mpt_register(mptscsih_scandv_complete, MPTSPI_DRIVER);
1122
James Bottomleyc92f2222006-03-01 09:02:49 -06001123 if (mpt_event_register(mptspiDoneCtx, mptspi_event_process) == 0) {
Moore, Eric3a892be2006-03-14 09:14:03 -07001124 devtverboseprintk((KERN_INFO MYNAM
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001125 ": Registered for IOC event notifications\n"));
1126 }
1127
Eric Moore6e1cad02006-04-25 17:38:58 -06001128 if (mpt_reset_register(mptspiDoneCtx, mptspi_ioc_reset) == 0) {
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001129 dprintk((KERN_INFO MYNAM
1130 ": Registered for IOC reset notifications\n"));
1131 }
1132
1133 return pci_register_driver(&mptspi_driver);
1134}
1135
1136/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1137/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1138/**
1139 * mptspi_exit - Unregisters MPT adapter(s)
1140 *
1141 */
1142static void __exit
1143mptspi_exit(void)
1144{
1145 pci_unregister_driver(&mptspi_driver);
Moore, Ericd8e925d2006-01-16 18:53:06 -07001146
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001147 mpt_reset_deregister(mptspiDoneCtx);
1148 dprintk((KERN_INFO MYNAM
1149 ": Deregistered for IOC reset notifications\n"));
1150
1151 mpt_event_deregister(mptspiDoneCtx);
1152 dprintk((KERN_INFO MYNAM
1153 ": Deregistered for IOC event notifications\n"));
1154
1155 mpt_deregister(mptspiInternalCtx);
1156 mpt_deregister(mptspiTaskCtx);
1157 mpt_deregister(mptspiDoneCtx);
James Bottomleyc92f2222006-03-01 09:02:49 -06001158 spi_release_transport(mptspi_transport_template);
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001159}
1160
1161module_init(mptspi_init);
1162module_exit(mptspi_exit);