blob: 85f21b54cb7de6702e89d4fb6728fa25e37e0e3c [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 *
Eric Moore9f4203b2007-01-04 20:47:47 -07006 * Copyright (c) 1999-2007 LSI Logic Corporation
Eric Moore07c861d2007-01-29 09:48:50 -07007 * (mailto:mpt_linux_developer@lsi.com)
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04008 *
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 */
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -040057#include <linux/workqueue.h>
James Bottomleyc92f2222006-03-01 09:02:49 -060058#include <linux/raid_class.h>
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -040059
60#include <scsi/scsi.h>
61#include <scsi/scsi_cmnd.h>
62#include <scsi/scsi_device.h>
63#include <scsi/scsi_host.h>
64#include <scsi/scsi_tcq.h>
James Bottomleyc92f2222006-03-01 09:02:49 -060065#include <scsi/scsi_transport.h>
66#include <scsi/scsi_transport_spi.h>
Eric Moore873c82e2007-01-29 09:44:06 -070067#include <scsi/scsi_dbg.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");
Eric Moore9f4203b2007-01-04 20:47:47 -070080MODULE_VERSION(my_VERSION);
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -040081
82/* Command line args */
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -040083static int mpt_saf_te = MPTSCSIH_SAF_TE;
84module_param(mpt_saf_te, int, 0);
85MODULE_PARM_DESC(mpt_saf_te, " Force enabling SEP Processor: enable=1 (default=MPTSCSIH_SAF_TE=0)");
86
James Bottomleyc92f2222006-03-01 09:02:49 -060087static void mptspi_write_offset(struct scsi_target *, int);
88static void mptspi_write_width(struct scsi_target *, int);
89static int mptspi_write_spi_device_pg1(struct scsi_target *,
90 struct _CONFIG_PAGE_SCSI_DEVICE_1 *);
91
92static struct scsi_transport_template *mptspi_transport_template = NULL;
93
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -040094static int mptspiDoneCtx = -1;
95static int mptspiTaskCtx = -1;
96static int mptspiInternalCtx = -1; /* Used only for internal commands */
97
Eric Moore5a9c47b2007-01-29 09:43:17 -070098/**
99 * mptspi_setTargetNegoParms - Update the target negotiation
100 * parameters based on the the Inquiry data, adapter capabilities,
101 * and NVRAM settings
102 *
103 * @hd: Pointer to a SCSI Host Structure
104 * @vtarget: per target private data
105 * @sdev: SCSI device
106 *
107 **/
108static void
109mptspi_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target,
110 struct scsi_device *sdev)
111{
112 SpiCfgData *pspi_data = &hd->ioc->spi_data;
113 int id = (int) target->id;
114 int nvram;
115 u8 width = MPT_NARROW;
116 u8 factor = MPT_ASYNC;
117 u8 offset = 0;
118 u8 nfactor;
119 u8 noQas = 1;
120
121 target->negoFlags = pspi_data->noQas;
122
123 if (sdev->scsi_level < SCSI_2) {
124 width = 0;
125 factor = MPT_ULTRA2;
126 offset = pspi_data->maxSyncOffset;
127 target->tflags &= ~MPT_TARGET_FLAGS_Q_YES;
128 } else {
129 if (scsi_device_wide(sdev))
130 width = 1;
131
132 if (scsi_device_sync(sdev)) {
133 factor = pspi_data->minSyncFactor;
134 if (!scsi_device_dt(sdev))
135 factor = MPT_ULTRA2;
136 else {
137 if (!scsi_device_ius(sdev) &&
138 !scsi_device_qas(sdev))
139 factor = MPT_ULTRA160;
140 else {
141 factor = MPT_ULTRA320;
142 if (scsi_device_qas(sdev)) {
143 ddvprintk((KERN_INFO "Enabling QAS due to byte56=%02x on id=%d!\n", scsi_device_qas(sdev), id));
144 noQas = 0;
145 }
146 if (sdev->type == TYPE_TAPE &&
147 scsi_device_ius(sdev))
148 target->negoFlags |= MPT_TAPE_NEGO_IDP;
149 }
150 }
151 offset = pspi_data->maxSyncOffset;
152
153 /* If RAID, never disable QAS
154 * else if non RAID, do not disable
155 * QAS if bit 1 is set
156 * bit 1 QAS support, non-raid only
157 * bit 0 IU support
158 */
159 if (target->raidVolume == 1)
160 noQas = 0;
161 } else {
162 factor = MPT_ASYNC;
163 offset = 0;
164 }
165 }
166
167 if (!sdev->tagged_supported)
168 target->tflags &= ~MPT_TARGET_FLAGS_Q_YES;
169
170 /* Update tflags based on NVRAM settings. (SCSI only)
171 */
172 if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) {
173 nvram = pspi_data->nvram[id];
174 nfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8;
175
176 if (width)
177 width = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
178
179 if (offset > 0) {
180 /* Ensure factor is set to the
181 * maximum of: adapter, nvram, inquiry
182 */
183 if (nfactor) {
184 if (nfactor < pspi_data->minSyncFactor )
185 nfactor = pspi_data->minSyncFactor;
186
187 factor = max(factor, nfactor);
188 if (factor == MPT_ASYNC)
189 offset = 0;
190 } else {
191 offset = 0;
192 factor = MPT_ASYNC;
193 }
194 } else {
195 factor = MPT_ASYNC;
196 }
197 }
198
199 /* Make sure data is consistent
200 */
201 if ((!width) && (factor < MPT_ULTRA2))
202 factor = MPT_ULTRA2;
203
204 /* Save the data to the target structure.
205 */
206 target->minSyncFactor = factor;
207 target->maxOffset = offset;
208 target->maxWidth = width;
209
210 target->tflags |= MPT_TARGET_FLAGS_VALID_NEGO;
211
212 /* Disable unused features.
213 */
214 if (!width)
215 target->negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
216
217 if (!offset)
218 target->negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
219
220 if ( factor > MPT_ULTRA320 )
221 noQas = 0;
222
223 if (noQas && (pspi_data->noQas == 0)) {
224 pspi_data->noQas |= MPT_TARGET_NO_NEGO_QAS;
225 target->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
226
227 /* Disable QAS in a mixed configuration case
228 */
229
230 ddvprintk((KERN_INFO "Disabling QAS due to noQas=%02x on id=%d!\n", noQas, id));
231 }
232}
233
234/**
235 * mptspi_writeIOCPage4 - write IOC Page 4
236 * @hd: Pointer to a SCSI Host Structure
237 * @channel:
238 * @id: write IOC Page4 for this ID & Bus
239 *
240 * Return: -EAGAIN if unable to obtain a Message Frame
241 * or 0 if success.
242 *
243 * Remark: We do not wait for a return, write pages sequentially.
244 **/
245static int
246mptspi_writeIOCPage4(MPT_SCSI_HOST *hd, u8 channel , u8 id)
247{
248 MPT_ADAPTER *ioc = hd->ioc;
249 Config_t *pReq;
250 IOCPage4_t *IOCPage4Ptr;
251 MPT_FRAME_HDR *mf;
252 dma_addr_t dataDma;
253 u16 req_idx;
254 u32 frameOffset;
255 u32 flagsLength;
256 int ii;
257
258 /* Get a MF for this command.
259 */
260 if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) {
261 dfailprintk((MYIOC_s_WARN_FMT "writeIOCPage4 : no msg frames!\n",
262 ioc->name));
263 return -EAGAIN;
264 }
265
266 /* Set the request and the data pointers.
267 * Place data at end of MF.
268 */
269 pReq = (Config_t *)mf;
270
271 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
272 frameOffset = ioc->req_sz - sizeof(IOCPage4_t);
273
274 /* Complete the request frame (same for all requests).
275 */
276 pReq->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
277 pReq->Reserved = 0;
278 pReq->ChainOffset = 0;
279 pReq->Function = MPI_FUNCTION_CONFIG;
280 pReq->ExtPageLength = 0;
281 pReq->ExtPageType = 0;
282 pReq->MsgFlags = 0;
283 for (ii=0; ii < 8; ii++) {
284 pReq->Reserved2[ii] = 0;
285 }
286
287 IOCPage4Ptr = ioc->spi_data.pIocPg4;
288 dataDma = ioc->spi_data.IocPg4_dma;
289 ii = IOCPage4Ptr->ActiveSEP++;
290 IOCPage4Ptr->SEP[ii].SEPTargetID = id;
291 IOCPage4Ptr->SEP[ii].SEPBus = channel;
292 pReq->Header = IOCPage4Ptr->Header;
293 pReq->PageAddress = cpu_to_le32(id | (channel << 8 ));
294
295 /* Add a SGE to the config request.
296 */
297 flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE |
298 (IOCPage4Ptr->Header.PageLength + ii) * 4;
299
300 mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma);
301
302 ddvprintk((MYIOC_s_INFO_FMT
303 "writeIOCPage4: MaxSEP=%d ActiveSEP=%d id=%d bus=%d\n",
304 ioc->name, IOCPage4Ptr->MaxSEP, IOCPage4Ptr->ActiveSEP, id, channel));
305
306 mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
307
308 return 0;
309}
310
311/**
312 * mptspi_initTarget - Target, LUN alloc/free functionality.
313 * @hd: Pointer to MPT_SCSI_HOST structure
314 * @vtarget: per target private data
315 * @sdev: SCSI device
316 *
317 * NOTE: It's only SAFE to call this routine if data points to
318 * sane & valid STANDARD INQUIRY data!
319 *
320 * Allocate and initialize memory for this target.
321 * Save inquiry data.
322 *
323 **/
324static void
325mptspi_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget,
326 struct scsi_device *sdev)
327{
328
329 /* Is LUN supported? If so, upper 2 bits will be 0
330 * in first byte of inquiry data.
331 */
332 if (sdev->inq_periph_qual != 0)
333 return;
334
335 if (vtarget == NULL)
336 return;
337
338 vtarget->type = sdev->type;
339
340 if ((sdev->type == TYPE_PROCESSOR) && (hd->ioc->spi_data.Saf_Te)) {
341 /* Treat all Processors as SAF-TE if
342 * command line option is set */
343 vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
344 mptspi_writeIOCPage4(hd, vtarget->channel, vtarget->id);
345 }else if ((sdev->type == TYPE_PROCESSOR) &&
346 !(vtarget->tflags & MPT_TARGET_FLAGS_SAF_TE_ISSUED )) {
347 if (sdev->inquiry_len > 49 ) {
348 if (sdev->inquiry[44] == 'S' &&
349 sdev->inquiry[45] == 'A' &&
350 sdev->inquiry[46] == 'F' &&
351 sdev->inquiry[47] == '-' &&
352 sdev->inquiry[48] == 'T' &&
353 sdev->inquiry[49] == 'E' ) {
354 vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
355 mptspi_writeIOCPage4(hd, vtarget->channel, vtarget->id);
356 }
357 }
358 }
359 mptspi_setTargetNegoParms(hd, vtarget, sdev);
360}
Eric Moore793955f2007-01-29 09:42:20 -0700361
362/**
363 * mptspi_is_raid - Determines whether target is belonging to volume
364 * @hd: Pointer to a SCSI HOST structure
365 * @id: target device id
366 *
367 * Return:
368 * non-zero = true
369 * zero = false
370 *
371 */
372static int
373mptspi_is_raid(struct _MPT_SCSI_HOST *hd, u32 id)
374{
375 int i, rc = 0;
376
377 if (!hd->ioc->raid_data.pIocPg2)
378 goto out;
379
380 if (!hd->ioc->raid_data.pIocPg2->NumActiveVolumes)
381 goto out;
382 for (i=0; i < hd->ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
383 if (hd->ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID == id) {
384 rc = 1;
385 goto out;
386 }
387 }
388
389 out:
390 return rc;
391}
392
James Bottomleyc92f2222006-03-01 09:02:49 -0600393static int mptspi_target_alloc(struct scsi_target *starget)
394{
395 struct Scsi_Host *shost = dev_to_shost(&starget->dev);
396 struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata;
Eric Moore793955f2007-01-29 09:42:20 -0700397 VirtTarget *vtarget;
James Bottomleyc92f2222006-03-01 09:02:49 -0600398
399 if (hd == NULL)
400 return -ENODEV;
401
Eric Moore793955f2007-01-29 09:42:20 -0700402 vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
403 if (!vtarget)
404 return -ENOMEM;
James Bottomleyc92f2222006-03-01 09:02:49 -0600405
Eric Moore793955f2007-01-29 09:42:20 -0700406 vtarget->ioc_id = hd->ioc->id;
407 vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
408 vtarget->id = (u8)starget->id;
409 vtarget->channel = (u8)starget->channel;
410 vtarget->starget = starget;
411 starget->hostdata = vtarget;
412
413 if (starget->channel == 1) {
414 if (mptscsih_is_phys_disk(hd->ioc, 0, starget->id) == 0)
415 return 0;
416 vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT;
417 /* The real channel for this device is zero */
418 vtarget->channel = 0;
419 /* The actual physdisknum (for RAID passthrough) */
420 vtarget->id = mptscsih_raid_id_to_num(hd->ioc, 0,
421 starget->id);
422 }
423
424 if (starget->channel == 0 &&
425 mptspi_is_raid(hd, starget->id)) {
426 vtarget->raidVolume = 1;
427 ddvprintk((KERN_INFO
428 "RAID Volume @ channel=%d id=%d\n", starget->channel,
429 starget->id));
430 }
James Bottomleyc92f2222006-03-01 09:02:49 -0600431
432 if (hd->ioc->spi_data.nvram &&
433 hd->ioc->spi_data.nvram[starget->id] != MPT_HOST_NVRAM_INVALID) {
434 u32 nvram = hd->ioc->spi_data.nvram[starget->id];
435 spi_min_period(starget) = (nvram & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT;
436 spi_max_width(starget) = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
437 } else {
438 spi_min_period(starget) = hd->ioc->spi_data.minSyncFactor;
439 spi_max_width(starget) = hd->ioc->spi_data.maxBusWidth;
440 }
441 spi_max_offset(starget) = hd->ioc->spi_data.maxSyncOffset;
442
443 spi_offset(starget) = 0;
444 mptspi_write_width(starget, 0);
445
446 return 0;
447}
448
Eric Moore793955f2007-01-29 09:42:20 -0700449void
450mptspi_target_destroy(struct scsi_target *starget)
451{
452 if (starget->hostdata)
453 kfree(starget->hostdata);
454 starget->hostdata = NULL;
455}
456
Eric Moore873c82e2007-01-29 09:44:06 -0700457/**
458 * mptspi_print_write_nego - negotiation parameters debug info that is being sent
459 * @hd: Pointer to a SCSI HOST structure
460 * @starget: SCSI target
461 * @ii: negotiation parameters
462 *
463 */
464static void
465mptspi_print_write_nego(struct _MPT_SCSI_HOST *hd, struct scsi_target *starget, u32 ii)
466{
467 ddvprintk((MYIOC_s_INFO_FMT "id=%d Requested = 0x%08x"
468 " ( %s factor = 0x%02x @ offset = 0x%02x %s%s%s%s%s%s%s%s)\n",
469 hd->ioc->name, starget->id, ii,
470 ii & MPI_SCSIDEVPAGE0_NP_WIDE ? "Wide ": "",
471 ((ii >> 8) & 0xFF), ((ii >> 16) & 0xFF),
472 ii & MPI_SCSIDEVPAGE0_NP_IU ? "IU ": "",
473 ii & MPI_SCSIDEVPAGE0_NP_DT ? "DT ": "",
474 ii & MPI_SCSIDEVPAGE0_NP_QAS ? "QAS ": "",
475 ii & MPI_SCSIDEVPAGE0_NP_HOLD_MCS ? "HOLDMCS ": "",
476 ii & MPI_SCSIDEVPAGE0_NP_WR_FLOW ? "WRFLOW ": "",
477 ii & MPI_SCSIDEVPAGE0_NP_RD_STRM ? "RDSTRM ": "",
478 ii & MPI_SCSIDEVPAGE0_NP_RTI ? "RTI ": "",
479 ii & MPI_SCSIDEVPAGE0_NP_PCOMP_EN ? "PCOMP ": ""));
480}
481
482/**
483 * mptspi_print_read_nego - negotiation parameters debug info that is being read
484 * @hd: Pointer to a SCSI HOST structure
485 * @starget: SCSI target
486 * @ii: negotiation parameters
487 *
488 */
489static void
490mptspi_print_read_nego(struct _MPT_SCSI_HOST *hd, struct scsi_target *starget, u32 ii)
491{
492 ddvprintk((MYIOC_s_INFO_FMT "id=%d Read = 0x%08x"
493 " ( %s factor = 0x%02x @ offset = 0x%02x %s%s%s%s%s%s%s%s)\n",
494 hd->ioc->name, starget->id, ii,
495 ii & MPI_SCSIDEVPAGE0_NP_WIDE ? "Wide ": "",
496 ((ii >> 8) & 0xFF), ((ii >> 16) & 0xFF),
497 ii & MPI_SCSIDEVPAGE0_NP_IU ? "IU ": "",
498 ii & MPI_SCSIDEVPAGE0_NP_DT ? "DT ": "",
499 ii & MPI_SCSIDEVPAGE0_NP_QAS ? "QAS ": "",
500 ii & MPI_SCSIDEVPAGE0_NP_HOLD_MCS ? "HOLDMCS ": "",
501 ii & MPI_SCSIDEVPAGE0_NP_WR_FLOW ? "WRFLOW ": "",
502 ii & MPI_SCSIDEVPAGE0_NP_RD_STRM ? "RDSTRM ": "",
503 ii & MPI_SCSIDEVPAGE0_NP_RTI ? "RTI ": "",
504 ii & MPI_SCSIDEVPAGE0_NP_PCOMP_EN ? "PCOMP ": ""));
505}
506
James Bottomleyc92f2222006-03-01 09:02:49 -0600507static int mptspi_read_spi_device_pg0(struct scsi_target *starget,
508 struct _CONFIG_PAGE_SCSI_DEVICE_0 *pass_pg0)
509{
510 struct Scsi_Host *shost = dev_to_shost(&starget->dev);
511 struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata;
512 struct _MPT_ADAPTER *ioc = hd->ioc;
513 struct _CONFIG_PAGE_SCSI_DEVICE_0 *pg0;
514 dma_addr_t pg0_dma;
515 int size;
516 struct _x_config_parms cfg;
517 struct _CONFIG_PAGE_HEADER hdr;
518 int err = -EBUSY;
519
520 /* No SPI parameters for RAID devices */
521 if (starget->channel == 0 &&
Eric Moore793955f2007-01-29 09:42:20 -0700522 mptspi_is_raid(hd, starget->id))
James Bottomleyc92f2222006-03-01 09:02:49 -0600523 return -1;
524
525 size = ioc->spi_data.sdp0length * 4;
526 /*
527 if (ioc->spi_data.sdp0length & 1)
528 size += size + 4;
529 size += 2048;
530 */
531
532 pg0 = dma_alloc_coherent(&ioc->pcidev->dev, size, &pg0_dma, GFP_KERNEL);
533 if (pg0 == NULL) {
534 starget_printk(KERN_ERR, starget, "dma_alloc_coherent for parameters failed\n");
535 return -EINVAL;
536 }
537
538 memset(&hdr, 0, sizeof(hdr));
539
540 hdr.PageVersion = ioc->spi_data.sdp0version;
541 hdr.PageLength = ioc->spi_data.sdp0length;
542 hdr.PageNumber = 0;
543 hdr.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
544
545 memset(&cfg, 0, sizeof(cfg));
546
547 cfg.cfghdr.hdr = &hdr;
548 cfg.physAddr = pg0_dma;
549 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
550 cfg.dir = 0;
551 cfg.pageAddr = starget->id;
552
553 if (mpt_config(ioc, &cfg)) {
554 starget_printk(KERN_ERR, starget, "mpt_config failed\n");
555 goto out_free;
556 }
557 err = 0;
558 memcpy(pass_pg0, pg0, size);
559
Eric Moore873c82e2007-01-29 09:44:06 -0700560 mptspi_print_read_nego(hd, starget, le32_to_cpu(pg0->NegotiatedParameters));
561
James Bottomleyc92f2222006-03-01 09:02:49 -0600562 out_free:
563 dma_free_coherent(&ioc->pcidev->dev, size, pg0, pg0_dma);
564 return err;
565}
566
567static u32 mptspi_getRP(struct scsi_target *starget)
568{
569 u32 nego = 0;
570
571 nego |= spi_iu(starget) ? MPI_SCSIDEVPAGE1_RP_IU : 0;
572 nego |= spi_dt(starget) ? MPI_SCSIDEVPAGE1_RP_DT : 0;
573 nego |= spi_qas(starget) ? MPI_SCSIDEVPAGE1_RP_QAS : 0;
574 nego |= spi_hold_mcs(starget) ? MPI_SCSIDEVPAGE1_RP_HOLD_MCS : 0;
575 nego |= spi_wr_flow(starget) ? MPI_SCSIDEVPAGE1_RP_WR_FLOW : 0;
576 nego |= spi_rd_strm(starget) ? MPI_SCSIDEVPAGE1_RP_RD_STRM : 0;
577 nego |= spi_rti(starget) ? MPI_SCSIDEVPAGE1_RP_RTI : 0;
578 nego |= spi_pcomp_en(starget) ? MPI_SCSIDEVPAGE1_RP_PCOMP_EN : 0;
579
580 nego |= (spi_period(starget) << MPI_SCSIDEVPAGE1_RP_SHIFT_MIN_SYNC_PERIOD) & MPI_SCSIDEVPAGE1_RP_MIN_SYNC_PERIOD_MASK;
581 nego |= (spi_offset(starget) << MPI_SCSIDEVPAGE1_RP_SHIFT_MAX_SYNC_OFFSET) & MPI_SCSIDEVPAGE1_RP_MAX_SYNC_OFFSET_MASK;
582 nego |= spi_width(starget) ? MPI_SCSIDEVPAGE1_RP_WIDE : 0;
583
584 return nego;
585}
586
587static void mptspi_read_parameters(struct scsi_target *starget)
588{
589 int nego;
590 struct _CONFIG_PAGE_SCSI_DEVICE_0 pg0;
591
592 mptspi_read_spi_device_pg0(starget, &pg0);
593
594 nego = le32_to_cpu(pg0.NegotiatedParameters);
595
596 spi_iu(starget) = (nego & MPI_SCSIDEVPAGE0_NP_IU) ? 1 : 0;
597 spi_dt(starget) = (nego & MPI_SCSIDEVPAGE0_NP_DT) ? 1 : 0;
598 spi_qas(starget) = (nego & MPI_SCSIDEVPAGE0_NP_QAS) ? 1 : 0;
599 spi_wr_flow(starget) = (nego & MPI_SCSIDEVPAGE0_NP_WR_FLOW) ? 1 : 0;
600 spi_rd_strm(starget) = (nego & MPI_SCSIDEVPAGE0_NP_RD_STRM) ? 1 : 0;
601 spi_rti(starget) = (nego & MPI_SCSIDEVPAGE0_NP_RTI) ? 1 : 0;
602 spi_pcomp_en(starget) = (nego & MPI_SCSIDEVPAGE0_NP_PCOMP_EN) ? 1 : 0;
603 spi_hold_mcs(starget) = (nego & MPI_SCSIDEVPAGE0_NP_HOLD_MCS) ? 1 : 0;
604 spi_period(starget) = (nego & MPI_SCSIDEVPAGE0_NP_NEG_SYNC_PERIOD_MASK) >> MPI_SCSIDEVPAGE0_NP_SHIFT_SYNC_PERIOD;
605 spi_offset(starget) = (nego & MPI_SCSIDEVPAGE0_NP_NEG_SYNC_OFFSET_MASK) >> MPI_SCSIDEVPAGE0_NP_SHIFT_SYNC_OFFSET;
606 spi_width(starget) = (nego & MPI_SCSIDEVPAGE0_NP_WIDE) ? 1 : 0;
607}
608
609static int
Eric Moore793955f2007-01-29 09:42:20 -0700610mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, u8 channel, u8 id)
James Bottomleyc92f2222006-03-01 09:02:49 -0600611{
612 MpiRaidActionRequest_t *pReq;
613 MPT_FRAME_HDR *mf;
614
615 /* Get and Populate a free Frame
616 */
617 if ((mf = mpt_get_msg_frame(hd->ioc->InternalCtx, hd->ioc)) == NULL) {
618 ddvprintk((MYIOC_s_WARN_FMT "_do_raid: no msg frames!\n",
619 hd->ioc->name));
620 return -EAGAIN;
621 }
622 pReq = (MpiRaidActionRequest_t *)mf;
623 if (quiesce)
624 pReq->Action = MPI_RAID_ACTION_QUIESCE_PHYS_IO;
625 else
626 pReq->Action = MPI_RAID_ACTION_ENABLE_PHYS_IO;
627 pReq->Reserved1 = 0;
628 pReq->ChainOffset = 0;
629 pReq->Function = MPI_FUNCTION_RAID_ACTION;
Eric Moore793955f2007-01-29 09:42:20 -0700630 pReq->VolumeID = id;
631 pReq->VolumeBus = channel;
James Bottomleyc92f2222006-03-01 09:02:49 -0600632 pReq->PhysDiskNum = 0;
633 pReq->MsgFlags = 0;
634 pReq->Reserved2 = 0;
635 pReq->ActionDataWord = 0; /* Reserved for this action */
636
637 mpt_add_sge((char *)&pReq->ActionDataSGE,
638 MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1);
639
Eric Moore793955f2007-01-29 09:42:20 -0700640 ddvprintk((MYIOC_s_INFO_FMT "RAID Volume action=%x channel=%d id=%d\n",
641 hd->ioc->name, pReq->Action, channel, id));
James Bottomleyc92f2222006-03-01 09:02:49 -0600642
643 hd->pLocal = NULL;
644 hd->timer.expires = jiffies + HZ*10; /* 10 second timeout */
645 hd->scandv_wait_done = 0;
646
647 /* Save cmd pointer, for resource free if timeout or
648 * FW reload occurs
649 */
650 hd->cmdPtr = mf;
651
652 add_timer(&hd->timer);
653 mpt_put_msg_frame(hd->ioc->InternalCtx, hd->ioc, mf);
654 wait_event(hd->scandv_waitq, hd->scandv_wait_done);
655
656 if ((hd->pLocal == NULL) || (hd->pLocal->completion != 0))
657 return -1;
658
659 return 0;
660}
661
662static void mptspi_dv_device(struct _MPT_SCSI_HOST *hd,
663 struct scsi_device *sdev)
664{
665 VirtTarget *vtarget = scsi_target(sdev)->hostdata;
666
667 /* no DV on RAID devices */
668 if (sdev->channel == 0 &&
Eric Moore793955f2007-01-29 09:42:20 -0700669 mptspi_is_raid(hd, sdev->id))
James Bottomleyc92f2222006-03-01 09:02:49 -0600670 return;
671
672 /* If this is a piece of a RAID, then quiesce first */
673 if (sdev->channel == 1 &&
Eric Moore793955f2007-01-29 09:42:20 -0700674 mptscsih_quiesce_raid(hd, 1, vtarget->channel, vtarget->id) < 0) {
James Bottomleyc92f2222006-03-01 09:02:49 -0600675 starget_printk(KERN_ERR, scsi_target(sdev),
676 "Integrated RAID quiesce failed\n");
677 return;
678 }
679
680 spi_dv_device(sdev);
681
682 if (sdev->channel == 1 &&
Eric Moore793955f2007-01-29 09:42:20 -0700683 mptscsih_quiesce_raid(hd, 0, vtarget->channel, vtarget->id) < 0)
James Bottomleyc92f2222006-03-01 09:02:49 -0600684 starget_printk(KERN_ERR, scsi_target(sdev),
685 "Integrated RAID resume failed\n");
686
687 mptspi_read_parameters(sdev->sdev_target);
688 spi_display_xfer_agreement(sdev->sdev_target);
689 mptspi_read_parameters(sdev->sdev_target);
690}
691
692static int mptspi_slave_alloc(struct scsi_device *sdev)
693{
James Bottomleyc92f2222006-03-01 09:02:49 -0600694 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sdev->host->hostdata;
Eric Moore793955f2007-01-29 09:42:20 -0700695 VirtTarget *vtarget;
696 VirtDevice *vdev;
697 struct scsi_target *starget;
James Bottomleyc92f2222006-03-01 09:02:49 -0600698
Eric Moore793955f2007-01-29 09:42:20 -0700699 if (sdev->channel == 1 &&
700 mptscsih_is_phys_disk(hd->ioc, 0, sdev->id) == 0)
701 return -ENXIO;
James Bottomleyc92f2222006-03-01 09:02:49 -0600702
Eric Moore793955f2007-01-29 09:42:20 -0700703 vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
704 if (!vdev) {
705 printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
706 hd->ioc->name, sizeof(VirtDevice));
707 return -ENOMEM;
James Bottomleyc92f2222006-03-01 09:02:49 -0600708 }
709
Eric Moore793955f2007-01-29 09:42:20 -0700710 vdev->lun = sdev->lun;
711 sdev->hostdata = vdev;
James Bottomleyc92f2222006-03-01 09:02:49 -0600712
Eric Moore793955f2007-01-29 09:42:20 -0700713 starget = scsi_target(sdev);
714 vtarget = starget->hostdata;
715 vdev->vtarget = vtarget;
716 vtarget->num_luns++;
James Bottomleyc92f2222006-03-01 09:02:49 -0600717
Eric Moore793955f2007-01-29 09:42:20 -0700718 if (sdev->channel == 1)
James Bottomleyc92f2222006-03-01 09:02:49 -0600719 sdev->no_uld_attach = 1;
James Bottomleyc92f2222006-03-01 09:02:49 -0600720
721 return 0;
722}
723
724static int mptspi_slave_configure(struct scsi_device *sdev)
725{
James Bottomleyc92f2222006-03-01 09:02:49 -0600726 struct _MPT_SCSI_HOST *hd =
727 (struct _MPT_SCSI_HOST *)sdev->host->hostdata;
Eric Moore5a9c47b2007-01-29 09:43:17 -0700728 VirtTarget *vtarget = scsi_target(sdev)->hostdata;
729 int ret = mptscsih_slave_configure(sdev);
James Bottomleyc92f2222006-03-01 09:02:49 -0600730
731 if (ret)
732 return ret;
733
Eric Moore5a9c47b2007-01-29 09:43:17 -0700734 mptspi_initTarget(hd, vtarget, sdev);
735
Eric Moore873c82e2007-01-29 09:44:06 -0700736 ddvprintk((MYIOC_s_INFO_FMT "id=%d min_period=0x%02x"
737 " max_offset=0x%02x max_width=%d\n", hd->ioc->name,
738 sdev->id, spi_min_period(scsi_target(sdev)),
739 spi_max_offset(scsi_target(sdev)),
740 spi_max_width(scsi_target(sdev))));
741
James Bottomleyc92f2222006-03-01 09:02:49 -0600742 if ((sdev->channel == 1 ||
Eric Moore793955f2007-01-29 09:42:20 -0700743 !(mptspi_is_raid(hd, sdev->id))) &&
James Bottomleyc92f2222006-03-01 09:02:49 -0600744 !spi_initial_dv(sdev->sdev_target))
745 mptspi_dv_device(hd, sdev);
746
747 return 0;
748}
749
Eric Moore793955f2007-01-29 09:42:20 -0700750static int
751mptspi_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
752{
753 struct _MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata;
754 VirtDevice *vdev = SCpnt->device->hostdata;
755
756 if (!vdev || !vdev->vtarget) {
757 SCpnt->result = DID_NO_CONNECT << 16;
758 done(SCpnt);
759 return 0;
760 }
761
762 if (SCpnt->device->channel == 1 &&
763 mptscsih_is_phys_disk(hd->ioc, 0, SCpnt->device->id) == 0) {
764 SCpnt->result = DID_NO_CONNECT << 16;
765 done(SCpnt);
766 return 0;
767 }
768
Eric Moore873c82e2007-01-29 09:44:06 -0700769#ifdef MPT_DEBUG_DV
770 if (spi_dv_pending(scsi_target(SCpnt->device)))
771 scsi_print_command(SCpnt);
772#endif
773
Eric Moore793955f2007-01-29 09:42:20 -0700774 return mptscsih_qcmd(SCpnt,done);
775}
776
James Bottomleyc92f2222006-03-01 09:02:49 -0600777static void mptspi_slave_destroy(struct scsi_device *sdev)
778{
779 struct scsi_target *starget = scsi_target(sdev);
780 VirtTarget *vtarget = starget->hostdata;
781 VirtDevice *vdevice = sdev->hostdata;
782
783 /* Will this be the last lun on a non-raid device? */
784 if (vtarget->num_luns == 1 && vdevice->configured_lun) {
785 struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
786
787 /* Async Narrow */
788 pg1.RequestedParameters = 0;
789 pg1.Reserved = 0;
790 pg1.Configuration = 0;
791
792 mptspi_write_spi_device_pg1(starget, &pg1);
793 }
794
795 mptscsih_slave_destroy(sdev);
796}
797
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -0400798static struct scsi_host_template mptspi_driver_template = {
Moore, Eric Deanf78496d2005-11-16 18:54:14 -0700799 .module = THIS_MODULE,
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -0400800 .proc_name = "mptspi",
801 .proc_info = mptscsih_proc_info,
802 .name = "MPT SPI Host",
803 .info = mptscsih_info,
Eric Moore793955f2007-01-29 09:42:20 -0700804 .queuecommand = mptspi_qcmd,
James Bottomleyc92f2222006-03-01 09:02:49 -0600805 .target_alloc = mptspi_target_alloc,
806 .slave_alloc = mptspi_slave_alloc,
807 .slave_configure = mptspi_slave_configure,
Eric Moore793955f2007-01-29 09:42:20 -0700808 .target_destroy = mptspi_target_destroy,
James Bottomleyc92f2222006-03-01 09:02:49 -0600809 .slave_destroy = mptspi_slave_destroy,
Moore, Eric Dean6e3815b2005-06-24 12:18:57 -0600810 .change_queue_depth = mptscsih_change_queue_depth,
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -0400811 .eh_abort_handler = mptscsih_abort,
812 .eh_device_reset_handler = mptscsih_dev_reset,
813 .eh_bus_reset_handler = mptscsih_bus_reset,
814 .eh_host_reset_handler = mptscsih_host_reset,
815 .bios_param = mptscsih_bios_param,
816 .can_queue = MPT_SCSI_CAN_QUEUE,
817 .this_id = -1,
818 .sg_tablesize = MPT_SCSI_SG_DEPTH,
819 .max_sectors = 8192,
820 .cmd_per_lun = 7,
821 .use_clustering = ENABLE_CLUSTERING,
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -0400822};
823
James Bottomleyc92f2222006-03-01 09:02:49 -0600824static int mptspi_write_spi_device_pg1(struct scsi_target *starget,
825 struct _CONFIG_PAGE_SCSI_DEVICE_1 *pass_pg1)
826{
827 struct Scsi_Host *shost = dev_to_shost(&starget->dev);
828 struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata;
829 struct _MPT_ADAPTER *ioc = hd->ioc;
830 struct _CONFIG_PAGE_SCSI_DEVICE_1 *pg1;
831 dma_addr_t pg1_dma;
832 int size;
833 struct _x_config_parms cfg;
834 struct _CONFIG_PAGE_HEADER hdr;
835 int err = -EBUSY;
836
837 /* don't allow updating nego parameters on RAID devices */
838 if (starget->channel == 0 &&
Eric Moore793955f2007-01-29 09:42:20 -0700839 mptspi_is_raid(hd, starget->id))
James Bottomleyc92f2222006-03-01 09:02:49 -0600840 return -1;
841
842 size = ioc->spi_data.sdp1length * 4;
843
844 pg1 = dma_alloc_coherent(&ioc->pcidev->dev, size, &pg1_dma, GFP_KERNEL);
845 if (pg1 == NULL) {
846 starget_printk(KERN_ERR, starget, "dma_alloc_coherent for parameters failed\n");
847 return -EINVAL;
848 }
849
850 memset(&hdr, 0, sizeof(hdr));
851
852 hdr.PageVersion = ioc->spi_data.sdp1version;
853 hdr.PageLength = ioc->spi_data.sdp1length;
854 hdr.PageNumber = 1;
855 hdr.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
856
857 memset(&cfg, 0, sizeof(cfg));
858
859 cfg.cfghdr.hdr = &hdr;
860 cfg.physAddr = pg1_dma;
861 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
862 cfg.dir = 1;
863 cfg.pageAddr = starget->id;
864
865 memcpy(pg1, pass_pg1, size);
866
867 pg1->Header.PageVersion = hdr.PageVersion;
868 pg1->Header.PageLength = hdr.PageLength;
869 pg1->Header.PageNumber = hdr.PageNumber;
870 pg1->Header.PageType = hdr.PageType;
871
Eric Moore873c82e2007-01-29 09:44:06 -0700872 mptspi_print_write_nego(hd, starget, le32_to_cpu(pg1->RequestedParameters));
873
James Bottomleyc92f2222006-03-01 09:02:49 -0600874 if (mpt_config(ioc, &cfg)) {
875 starget_printk(KERN_ERR, starget, "mpt_config failed\n");
876 goto out_free;
877 }
878 err = 0;
879
880 out_free:
881 dma_free_coherent(&ioc->pcidev->dev, size, pg1, pg1_dma);
882 return err;
883}
884
885static void mptspi_write_offset(struct scsi_target *starget, int offset)
886{
887 struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
888 u32 nego;
889
890 if (offset < 0)
891 offset = 0;
892
893 if (offset > 255)
894 offset = 255;
895
896 if (spi_offset(starget) == -1)
897 mptspi_read_parameters(starget);
898
899 spi_offset(starget) = offset;
900
901 nego = mptspi_getRP(starget);
902
903 pg1.RequestedParameters = cpu_to_le32(nego);
904 pg1.Reserved = 0;
905 pg1.Configuration = 0;
906
907 mptspi_write_spi_device_pg1(starget, &pg1);
908}
909
910static void mptspi_write_period(struct scsi_target *starget, int period)
911{
912 struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
913 u32 nego;
914
915 if (period < 8)
916 period = 8;
917
918 if (period > 255)
919 period = 255;
920
921 if (spi_period(starget) == -1)
922 mptspi_read_parameters(starget);
923
924 if (period == 8) {
925 spi_iu(starget) = 1;
926 spi_dt(starget) = 1;
927 } else if (period == 9) {
928 spi_dt(starget) = 1;
929 }
930
931 spi_period(starget) = period;
932
933 nego = mptspi_getRP(starget);
934
935 pg1.RequestedParameters = cpu_to_le32(nego);
936 pg1.Reserved = 0;
937 pg1.Configuration = 0;
938
939 mptspi_write_spi_device_pg1(starget, &pg1);
940}
941
942static void mptspi_write_dt(struct scsi_target *starget, int dt)
943{
944 struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
945 u32 nego;
946
947 if (spi_period(starget) == -1)
948 mptspi_read_parameters(starget);
949
950 if (!dt && spi_period(starget) < 10)
951 spi_period(starget) = 10;
952
953 spi_dt(starget) = dt;
954
955 nego = mptspi_getRP(starget);
956
957
958 pg1.RequestedParameters = cpu_to_le32(nego);
959 pg1.Reserved = 0;
960 pg1.Configuration = 0;
961
962 mptspi_write_spi_device_pg1(starget, &pg1);
963}
964
965static void mptspi_write_iu(struct scsi_target *starget, int iu)
966{
967 struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
968 u32 nego;
969
970 if (spi_period(starget) == -1)
971 mptspi_read_parameters(starget);
972
973 if (!iu && spi_period(starget) < 9)
974 spi_period(starget) = 9;
975
976 spi_iu(starget) = iu;
977
978 nego = mptspi_getRP(starget);
979
980 pg1.RequestedParameters = cpu_to_le32(nego);
981 pg1.Reserved = 0;
982 pg1.Configuration = 0;
983
984 mptspi_write_spi_device_pg1(starget, &pg1);
985}
986
987#define MPTSPI_SIMPLE_TRANSPORT_PARM(parm) \
988static void mptspi_write_##parm(struct scsi_target *starget, int parm)\
989{ \
990 struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1; \
991 u32 nego; \
992 \
993 spi_##parm(starget) = parm; \
994 \
995 nego = mptspi_getRP(starget); \
996 \
997 pg1.RequestedParameters = cpu_to_le32(nego); \
998 pg1.Reserved = 0; \
999 pg1.Configuration = 0; \
1000 \
1001 mptspi_write_spi_device_pg1(starget, &pg1); \
1002}
1003
1004MPTSPI_SIMPLE_TRANSPORT_PARM(rd_strm)
1005MPTSPI_SIMPLE_TRANSPORT_PARM(wr_flow)
1006MPTSPI_SIMPLE_TRANSPORT_PARM(rti)
1007MPTSPI_SIMPLE_TRANSPORT_PARM(hold_mcs)
1008MPTSPI_SIMPLE_TRANSPORT_PARM(pcomp_en)
1009
1010static void mptspi_write_qas(struct scsi_target *starget, int qas)
1011{
1012 struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
1013 struct Scsi_Host *shost = dev_to_shost(&starget->dev);
1014 struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata;
1015 VirtTarget *vtarget = starget->hostdata;
1016 u32 nego;
1017
1018 if ((vtarget->negoFlags & MPT_TARGET_NO_NEGO_QAS) ||
1019 hd->ioc->spi_data.noQas)
1020 spi_qas(starget) = 0;
1021 else
1022 spi_qas(starget) = qas;
1023
1024 nego = mptspi_getRP(starget);
1025
1026 pg1.RequestedParameters = cpu_to_le32(nego);
1027 pg1.Reserved = 0;
1028 pg1.Configuration = 0;
1029
1030 mptspi_write_spi_device_pg1(starget, &pg1);
1031}
1032
1033static void mptspi_write_width(struct scsi_target *starget, int width)
1034{
1035 struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
1036 u32 nego;
1037
1038 if (!width) {
1039 spi_dt(starget) = 0;
1040 if (spi_period(starget) < 10)
1041 spi_period(starget) = 10;
1042 }
1043
1044 spi_width(starget) = width;
1045
1046 nego = mptspi_getRP(starget);
1047
1048 pg1.RequestedParameters = cpu_to_le32(nego);
1049 pg1.Reserved = 0;
1050 pg1.Configuration = 0;
1051
1052 mptspi_write_spi_device_pg1(starget, &pg1);
1053}
1054
1055struct work_queue_wrapper {
1056 struct work_struct work;
1057 struct _MPT_SCSI_HOST *hd;
1058 int disk;
1059};
1060
David Howellsc4028952006-11-22 14:57:56 +00001061static void mpt_work_wrapper(struct work_struct *work)
James Bottomleyc92f2222006-03-01 09:02:49 -06001062{
David Howellsc4028952006-11-22 14:57:56 +00001063 struct work_queue_wrapper *wqw =
1064 container_of(work, struct work_queue_wrapper, work);
James Bottomleyc92f2222006-03-01 09:02:49 -06001065 struct _MPT_SCSI_HOST *hd = wqw->hd;
1066 struct Scsi_Host *shost = hd->ioc->sh;
1067 struct scsi_device *sdev;
1068 int disk = wqw->disk;
1069 struct _CONFIG_PAGE_IOC_3 *pg3;
1070
1071 kfree(wqw);
1072
1073 mpt_findImVolumes(hd->ioc);
1074 pg3 = hd->ioc->raid_data.pIocPg3;
1075 if (!pg3)
1076 return;
1077
1078 shost_for_each_device(sdev,shost) {
1079 struct scsi_target *starget = scsi_target(sdev);
1080 VirtTarget *vtarget = starget->hostdata;
1081
1082 /* only want to search RAID components */
1083 if (sdev->channel != 1)
1084 continue;
1085
Eric Moore793955f2007-01-29 09:42:20 -07001086 /* The id is the raid PhysDiskNum, even if
James Bottomleyc92f2222006-03-01 09:02:49 -06001087 * starget->id is the actual target address */
Eric Moore793955f2007-01-29 09:42:20 -07001088 if(vtarget->id != disk)
James Bottomleyc92f2222006-03-01 09:02:49 -06001089 continue;
1090
1091 starget_printk(KERN_INFO, vtarget->starget,
1092 "Integrated RAID requests DV of new device\n");
1093 mptspi_dv_device(hd, sdev);
1094 }
1095 shost_printk(KERN_INFO, shost,
1096 "Integrated RAID detects new device %d\n", disk);
1097 scsi_scan_target(&hd->ioc->sh->shost_gendev, 1, disk, 0, 1);
1098}
1099
1100
1101static void mpt_dv_raid(struct _MPT_SCSI_HOST *hd, int disk)
1102{
1103 struct work_queue_wrapper *wqw = kmalloc(sizeof(*wqw), GFP_ATOMIC);
1104
1105 if (!wqw) {
1106 shost_printk(KERN_ERR, hd->ioc->sh,
1107 "Failed to act on RAID event for physical disk %d\n",
1108 disk);
1109 return;
1110 }
David Howellsc4028952006-11-22 14:57:56 +00001111 INIT_WORK(&wqw->work, mpt_work_wrapper);
James Bottomleyc92f2222006-03-01 09:02:49 -06001112 wqw->hd = hd;
1113 wqw->disk = disk;
1114
1115 schedule_work(&wqw->work);
1116}
1117
1118static int
1119mptspi_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
1120{
1121 u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
1122 struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)ioc->sh->hostdata;
1123
1124 if (hd && event == MPI_EVENT_INTEGRATED_RAID) {
1125 int reason
1126 = (le32_to_cpu(pEvReply->Data[0]) & 0x00FF0000) >> 16;
1127
1128 if (reason == MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) {
1129 int disk = (le32_to_cpu(pEvReply->Data[0]) & 0xFF000000) >> 24;
1130 mpt_dv_raid(hd, disk);
1131 }
1132 }
1133 return mptscsih_event_process(ioc, pEvReply);
1134}
1135
1136static int
1137mptspi_deny_binding(struct scsi_target *starget)
1138{
1139 struct _MPT_SCSI_HOST *hd =
1140 (struct _MPT_SCSI_HOST *)dev_to_shost(starget->dev.parent)->hostdata;
Eric Moore793955f2007-01-29 09:42:20 -07001141 return ((mptspi_is_raid(hd, starget->id)) &&
James Bottomleyc92f2222006-03-01 09:02:49 -06001142 starget->channel == 0) ? 1 : 0;
1143}
1144
1145static struct spi_function_template mptspi_transport_functions = {
1146 .get_offset = mptspi_read_parameters,
1147 .set_offset = mptspi_write_offset,
1148 .show_offset = 1,
1149 .get_period = mptspi_read_parameters,
1150 .set_period = mptspi_write_period,
1151 .show_period = 1,
1152 .get_width = mptspi_read_parameters,
1153 .set_width = mptspi_write_width,
1154 .show_width = 1,
1155 .get_iu = mptspi_read_parameters,
1156 .set_iu = mptspi_write_iu,
1157 .show_iu = 1,
1158 .get_dt = mptspi_read_parameters,
1159 .set_dt = mptspi_write_dt,
1160 .show_dt = 1,
1161 .get_qas = mptspi_read_parameters,
1162 .set_qas = mptspi_write_qas,
1163 .show_qas = 1,
1164 .get_wr_flow = mptspi_read_parameters,
1165 .set_wr_flow = mptspi_write_wr_flow,
1166 .show_wr_flow = 1,
1167 .get_rd_strm = mptspi_read_parameters,
1168 .set_rd_strm = mptspi_write_rd_strm,
1169 .show_rd_strm = 1,
1170 .get_rti = mptspi_read_parameters,
1171 .set_rti = mptspi_write_rti,
1172 .show_rti = 1,
1173 .get_pcomp_en = mptspi_read_parameters,
1174 .set_pcomp_en = mptspi_write_pcomp_en,
1175 .show_pcomp_en = 1,
1176 .get_hold_mcs = mptspi_read_parameters,
1177 .set_hold_mcs = mptspi_write_hold_mcs,
1178 .show_hold_mcs = 1,
1179 .deny_binding = mptspi_deny_binding,
1180};
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001181
1182/****************************************************************************
1183 * Supported hardware
1184 */
1185
1186static struct pci_device_id mptspi_pci_table[] = {
Eric Moore87cf8982006-06-27 16:09:26 -06001187 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_53C1030,
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001188 PCI_ANY_ID, PCI_ANY_ID },
Eric Moore87cf8982006-06-27 16:09:26 -06001189 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_53C1035,
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001190 PCI_ANY_ID, PCI_ANY_ID },
1191 {0} /* Terminating entry */
1192};
1193MODULE_DEVICE_TABLE(pci, mptspi_pci_table);
1194
Eric Moore6e1cad02006-04-25 17:38:58 -06001195
1196/*
1197 * renegotiate for a given target
1198 */
1199static void
David Howellsc4028952006-11-22 14:57:56 +00001200mptspi_dv_renegotiate_work(struct work_struct *work)
Eric Moore6e1cad02006-04-25 17:38:58 -06001201{
David Howellsc4028952006-11-22 14:57:56 +00001202 struct work_queue_wrapper *wqw =
1203 container_of(work, struct work_queue_wrapper, work);
Eric Moore6e1cad02006-04-25 17:38:58 -06001204 struct _MPT_SCSI_HOST *hd = wqw->hd;
1205 struct scsi_device *sdev;
1206
1207 kfree(wqw);
1208
1209 shost_for_each_device(sdev, hd->ioc->sh)
1210 mptspi_dv_device(hd, sdev);
1211}
1212
1213static void
1214mptspi_dv_renegotiate(struct _MPT_SCSI_HOST *hd)
1215{
1216 struct work_queue_wrapper *wqw = kmalloc(sizeof(*wqw), GFP_ATOMIC);
1217
1218 if (!wqw)
1219 return;
1220
David Howellsc4028952006-11-22 14:57:56 +00001221 INIT_WORK(&wqw->work, mptspi_dv_renegotiate_work);
Eric Moore6e1cad02006-04-25 17:38:58 -06001222 wqw->hd = hd;
1223
1224 schedule_work(&wqw->work);
1225}
1226
1227/*
1228 * spi module reset handler
1229 */
1230static int
1231mptspi_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
1232{
1233 struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)ioc->sh->hostdata;
1234 int rc;
1235
1236 rc = mptscsih_ioc_reset(ioc, reset_phase);
1237
1238 if (reset_phase == MPT_IOC_POST_RESET)
1239 mptspi_dv_renegotiate(hd);
1240
1241 return rc;
1242}
1243
Tom "spot" Callawayc29ca9d2006-06-09 17:01:48 -07001244#ifdef CONFIG_PM
Eric Moore6e1cad02006-04-25 17:38:58 -06001245/*
1246 * spi module resume handler
1247 */
1248static int
1249mptspi_resume(struct pci_dev *pdev)
1250{
1251 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1252 struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)ioc->sh->hostdata;
1253 int rc;
1254
1255 rc = mptscsih_resume(pdev);
1256 mptspi_dv_renegotiate(hd);
1257
1258 return rc;
1259}
Tom "spot" Callawayc29ca9d2006-06-09 17:01:48 -07001260#endif
Eric Moore6e1cad02006-04-25 17:38:58 -06001261
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001262/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1263/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1264/*
1265 * mptspi_probe - Installs scsi devices per bus.
1266 * @pdev: Pointer to pci_dev structure
1267 *
1268 * Returns 0 for success, non-zero for failure.
1269 *
1270 */
1271static int
1272mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
1273{
1274 struct Scsi_Host *sh;
1275 MPT_SCSI_HOST *hd;
1276 MPT_ADAPTER *ioc;
1277 unsigned long flags;
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001278 int ii;
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001279 int numSGE = 0;
1280 int scale;
1281 int ioc_cap;
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001282 int error=0;
1283 int r;
Christoph Hellwigc6678e02005-08-18 16:24:53 +02001284
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001285 if ((r = mpt_attach(pdev,id)) != 0)
1286 return r;
Christoph Hellwigc6678e02005-08-18 16:24:53 +02001287
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001288 ioc = pci_get_drvdata(pdev);
Moore, Eric Dean d335cc32005-04-30 17:09:38 -05001289 ioc->DoneCtx = mptspiDoneCtx;
1290 ioc->TaskCtx = mptspiTaskCtx;
1291 ioc->InternalCtx = mptspiInternalCtx;
Christoph Hellwigc6678e02005-08-18 16:24:53 +02001292
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001293 /* Added sanity check on readiness of the MPT adapter.
1294 */
1295 if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
1296 printk(MYIOC_s_WARN_FMT
1297 "Skipping because it's not operational!\n",
1298 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001299 error = -ENODEV;
1300 goto out_mptspi_probe;
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001301 }
1302
1303 if (!ioc->active) {
1304 printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
1305 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001306 error = -ENODEV;
1307 goto out_mptspi_probe;
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001308 }
1309
1310 /* Sanity check - ensure at least 1 port is INITIATOR capable
1311 */
1312 ioc_cap = 0;
1313 for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
1314 if (ioc->pfacts[ii].ProtocolFlags &
1315 MPI_PORTFACTS_PROTOCOL_INITIATOR)
1316 ioc_cap ++;
1317 }
1318
1319 if (!ioc_cap) {
1320 printk(MYIOC_s_WARN_FMT
1321 "Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n",
1322 ioc->name, ioc);
Moore, Eric Dean466544d2005-09-14 18:09:10 -06001323 return 0;
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001324 }
1325
1326 sh = scsi_host_alloc(&mptspi_driver_template, sizeof(MPT_SCSI_HOST));
1327
1328 if (!sh) {
1329 printk(MYIOC_s_WARN_FMT
1330 "Unable to register controller with SCSI subsystem\n",
1331 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001332 error = -1;
1333 goto out_mptspi_probe;
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001334 }
1335
1336 spin_lock_irqsave(&ioc->FreeQlock, flags);
1337
1338 /* Attach the SCSI Host to the IOC structure
1339 */
1340 ioc->sh = sh;
1341
1342 sh->io_port = 0;
1343 sh->n_io_port = 0;
1344 sh->irq = 0;
1345
1346 /* set 16 byte cdb's */
1347 sh->max_cmd_len = 16;
1348
1349 /* Yikes! This is important!
1350 * Otherwise, by default, linux
1351 * only scans target IDs 0-7!
1352 * pfactsN->MaxDevices unreliable
1353 * (not supported in early
1354 * versions of the FW).
1355 * max_id = 1 + actual max id,
1356 * max_lun = 1 + actual last lun,
1357 * see hosts.h :o(
1358 */
Eric Moore793955f2007-01-29 09:42:20 -07001359 sh->max_id = ioc->devices_per_bus;
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001360
1361 sh->max_lun = MPT_LAST_LUN + 1;
James Bottomleyc92f2222006-03-01 09:02:49 -06001362 /*
1363 * If RAID Firmware Detected, setup virtual channel
1364 */
Eric Mooreb506ade2007-01-29 09:45:37 -07001365 if (ioc->ir_firmware)
James Bottomleyc92f2222006-03-01 09:02:49 -06001366 sh->max_channel = 1;
1367 else
1368 sh->max_channel = 0;
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001369 sh->this_id = ioc->pfacts[0].PortSCSIID;
1370
1371 /* Required entry.
1372 */
1373 sh->unique_id = ioc->id;
1374
1375 /* Verify that we won't exceed the maximum
1376 * number of chain buffers
1377 * We can optimize: ZZ = req_sz/sizeof(SGE)
1378 * For 32bit SGE's:
1379 * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
1380 * + (req_sz - 64)/sizeof(SGE)
1381 * A slightly different algorithm is required for
1382 * 64bit SGEs.
1383 */
1384 scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
1385 if (sizeof(dma_addr_t) == sizeof(u64)) {
1386 numSGE = (scale - 1) *
1387 (ioc->facts.MaxChainDepth-1) + scale +
1388 (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
1389 sizeof(u32));
1390 } else {
1391 numSGE = 1 + (scale - 1) *
1392 (ioc->facts.MaxChainDepth-1) + scale +
1393 (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
1394 sizeof(u32));
1395 }
1396
1397 if (numSGE < sh->sg_tablesize) {
1398 /* Reset this value */
1399 dprintk((MYIOC_s_INFO_FMT
1400 "Resetting sg_tablesize to %d from %d\n",
1401 ioc->name, numSGE, sh->sg_tablesize));
1402 sh->sg_tablesize = numSGE;
1403 }
1404
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001405 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
1406
1407 hd = (MPT_SCSI_HOST *) sh->hostdata;
1408 hd->ioc = ioc;
1409
1410 /* SCSI needs scsi_cmnd lookup table!
1411 * (with size equal to req_depth*PtrSz!)
1412 */
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001413 hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
1414 if (!hd->ScsiLookup) {
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001415 error = -ENOMEM;
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001416 goto out_mptspi_probe;
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001417 }
1418
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001419 dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
1420 ioc->name, hd->ScsiLookup));
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001421
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001422 /* Clear the TM flags
1423 */
1424 hd->tmPending = 0;
1425 hd->tmState = TM_STATE_NONE;
1426 hd->resetPending = 0;
1427 hd->abortSCpnt = NULL;
1428
1429 /* Clear the pointer used to store
1430 * single-threaded commands, i.e., those
1431 * issued during a bus scan, dv and
1432 * configuration pages.
1433 */
1434 hd->cmdPtr = NULL;
1435
1436 /* Initialize this SCSI Hosts' timers
1437 * To use, set the timer expires field
1438 * and add_timer
1439 */
1440 init_timer(&hd->timer);
1441 hd->timer.data = (unsigned long) hd;
1442 hd->timer.function = mptscsih_timer_expired;
1443
1444 ioc->spi_data.Saf_Te = mpt_saf_te;
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001445
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001446 hd->negoNvram = MPT_SCSICFG_USE_NVRAM;
1447 ddvprintk((MYIOC_s_INFO_FMT
Eric Mooreba856d32006-07-11 17:34:01 -06001448 "saf_te %x\n",
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001449 ioc->name,
Eric Mooreba856d32006-07-11 17:34:01 -06001450 mpt_saf_te));
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001451 ioc->spi_data.noQas = 0;
1452
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001453 init_waitqueue_head(&hd->scandv_waitq);
1454 hd->scandv_wait_done = 0;
1455 hd->last_queue_full = 0;
1456
James Bottomleyc92f2222006-03-01 09:02:49 -06001457 /* Some versions of the firmware don't support page 0; without
1458 * that we can't get the parameters */
1459 if (hd->ioc->spi_data.sdp0length != 0)
1460 sh->transportt = mptspi_transport_template;
1461
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001462 error = scsi_add_host (sh, &ioc->pcidev->dev);
1463 if(error) {
1464 dprintk((KERN_ERR MYNAM
1465 "scsi_add_host failed\n"));
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001466 goto out_mptspi_probe;
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001467 }
1468
Moore, Ericd8e925d2006-01-16 18:53:06 -07001469 /*
1470 * issue internal bus reset
1471 */
1472 if (ioc->spi_data.bus_reset)
1473 mptscsih_TMHandler(hd,
1474 MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
1475 0, 0, 0, 0, 5);
1476
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001477 scsi_scan_host(sh);
1478 return 0;
1479
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001480out_mptspi_probe:
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001481
1482 mptscsih_remove(pdev);
1483 return error;
1484}
1485
1486static struct pci_driver mptspi_driver = {
1487 .name = "mptspi",
1488 .id_table = mptspi_pci_table,
1489 .probe = mptspi_probe,
1490 .remove = __devexit_p(mptscsih_remove),
Greg Kroah-Hartmand18c3db2005-06-23 17:35:56 -07001491 .shutdown = mptscsih_shutdown,
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001492#ifdef CONFIG_PM
1493 .suspend = mptscsih_suspend,
Eric Moore6e1cad02006-04-25 17:38:58 -06001494 .resume = mptspi_resume,
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001495#endif
1496};
1497
1498/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1499/**
Randy Dunlapd9489fb2006-12-06 20:38:43 -08001500 * mptspi_init - Register MPT adapter(s) as SCSI host(s) with SCSI mid-layer.
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001501 *
1502 * Returns 0 for success, non-zero for failure.
1503 */
1504static int __init
1505mptspi_init(void)
1506{
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001507 show_mptmod_ver(my_NAME, my_VERSION);
1508
James Bottomleyc92f2222006-03-01 09:02:49 -06001509 mptspi_transport_template = spi_attach_transport(&mptspi_transport_functions);
1510 if (!mptspi_transport_template)
1511 return -ENODEV;
1512
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001513 mptspiDoneCtx = mpt_register(mptscsih_io_done, MPTSPI_DRIVER);
1514 mptspiTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSPI_DRIVER);
1515 mptspiInternalCtx = mpt_register(mptscsih_scandv_complete, MPTSPI_DRIVER);
1516
James Bottomleyc92f2222006-03-01 09:02:49 -06001517 if (mpt_event_register(mptspiDoneCtx, mptspi_event_process) == 0) {
Moore, Eric3a892be2006-03-14 09:14:03 -07001518 devtverboseprintk((KERN_INFO MYNAM
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001519 ": Registered for IOC event notifications\n"));
1520 }
1521
Eric Moore6e1cad02006-04-25 17:38:58 -06001522 if (mpt_reset_register(mptspiDoneCtx, mptspi_ioc_reset) == 0) {
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001523 dprintk((KERN_INFO MYNAM
1524 ": Registered for IOC reset notifications\n"));
1525 }
1526
1527 return pci_register_driver(&mptspi_driver);
1528}
1529
1530/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1531/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1532/**
1533 * mptspi_exit - Unregisters MPT adapter(s)
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001534 */
1535static void __exit
1536mptspi_exit(void)
1537{
1538 pci_unregister_driver(&mptspi_driver);
Moore, Ericd8e925d2006-01-16 18:53:06 -07001539
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001540 mpt_reset_deregister(mptspiDoneCtx);
1541 dprintk((KERN_INFO MYNAM
1542 ": Deregistered for IOC reset notifications\n"));
1543
1544 mpt_event_deregister(mptspiDoneCtx);
1545 dprintk((KERN_INFO MYNAM
1546 ": Deregistered for IOC event notifications\n"));
1547
1548 mpt_deregister(mptspiInternalCtx);
1549 mpt_deregister(mptspiTaskCtx);
1550 mpt_deregister(mptspiDoneCtx);
James Bottomleyc92f2222006-03-01 09:02:49 -06001551 spi_release_transport(mptspi_transport_template);
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001552}
1553
1554module_init(mptspi_init);
1555module_exit(mptspi_exit);