blob: aec0c2fe221fb0dd45ab1dcb21059dcb790ecbea [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
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04007 * (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");
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 Moore793955f2007-01-29 09:42:20 -070098
99/**
100 * mptspi_is_raid - Determines whether target is belonging to volume
101 * @hd: Pointer to a SCSI HOST structure
102 * @id: target device id
103 *
104 * Return:
105 * non-zero = true
106 * zero = false
107 *
108 */
109static int
110mptspi_is_raid(struct _MPT_SCSI_HOST *hd, u32 id)
111{
112 int i, rc = 0;
113
114 if (!hd->ioc->raid_data.pIocPg2)
115 goto out;
116
117 if (!hd->ioc->raid_data.pIocPg2->NumActiveVolumes)
118 goto out;
119 for (i=0; i < hd->ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
120 if (hd->ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID == id) {
121 rc = 1;
122 goto out;
123 }
124 }
125
126 out:
127 return rc;
128}
129
James Bottomleyc92f2222006-03-01 09:02:49 -0600130static int mptspi_target_alloc(struct scsi_target *starget)
131{
132 struct Scsi_Host *shost = dev_to_shost(&starget->dev);
133 struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata;
Eric Moore793955f2007-01-29 09:42:20 -0700134 VirtTarget *vtarget;
James Bottomleyc92f2222006-03-01 09:02:49 -0600135
136 if (hd == NULL)
137 return -ENODEV;
138
Eric Moore793955f2007-01-29 09:42:20 -0700139 vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
140 if (!vtarget)
141 return -ENOMEM;
James Bottomleyc92f2222006-03-01 09:02:49 -0600142
Eric Moore793955f2007-01-29 09:42:20 -0700143 vtarget->ioc_id = hd->ioc->id;
144 vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
145 vtarget->id = (u8)starget->id;
146 vtarget->channel = (u8)starget->channel;
147 vtarget->starget = starget;
148 starget->hostdata = vtarget;
149
150 if (starget->channel == 1) {
151 if (mptscsih_is_phys_disk(hd->ioc, 0, starget->id) == 0)
152 return 0;
153 vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT;
154 /* The real channel for this device is zero */
155 vtarget->channel = 0;
156 /* The actual physdisknum (for RAID passthrough) */
157 vtarget->id = mptscsih_raid_id_to_num(hd->ioc, 0,
158 starget->id);
159 }
160
161 if (starget->channel == 0 &&
162 mptspi_is_raid(hd, starget->id)) {
163 vtarget->raidVolume = 1;
164 ddvprintk((KERN_INFO
165 "RAID Volume @ channel=%d id=%d\n", starget->channel,
166 starget->id));
167 }
James Bottomleyc92f2222006-03-01 09:02:49 -0600168
169 if (hd->ioc->spi_data.nvram &&
170 hd->ioc->spi_data.nvram[starget->id] != MPT_HOST_NVRAM_INVALID) {
171 u32 nvram = hd->ioc->spi_data.nvram[starget->id];
172 spi_min_period(starget) = (nvram & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT;
173 spi_max_width(starget) = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
174 } else {
175 spi_min_period(starget) = hd->ioc->spi_data.minSyncFactor;
176 spi_max_width(starget) = hd->ioc->spi_data.maxBusWidth;
177 }
178 spi_max_offset(starget) = hd->ioc->spi_data.maxSyncOffset;
179
180 spi_offset(starget) = 0;
181 mptspi_write_width(starget, 0);
182
183 return 0;
184}
185
Eric Moore793955f2007-01-29 09:42:20 -0700186void
187mptspi_target_destroy(struct scsi_target *starget)
188{
189 if (starget->hostdata)
190 kfree(starget->hostdata);
191 starget->hostdata = NULL;
192}
193
James Bottomleyc92f2222006-03-01 09:02:49 -0600194static int mptspi_read_spi_device_pg0(struct scsi_target *starget,
195 struct _CONFIG_PAGE_SCSI_DEVICE_0 *pass_pg0)
196{
197 struct Scsi_Host *shost = dev_to_shost(&starget->dev);
198 struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata;
199 struct _MPT_ADAPTER *ioc = hd->ioc;
200 struct _CONFIG_PAGE_SCSI_DEVICE_0 *pg0;
201 dma_addr_t pg0_dma;
202 int size;
203 struct _x_config_parms cfg;
204 struct _CONFIG_PAGE_HEADER hdr;
205 int err = -EBUSY;
206
207 /* No SPI parameters for RAID devices */
208 if (starget->channel == 0 &&
Eric Moore793955f2007-01-29 09:42:20 -0700209 mptspi_is_raid(hd, starget->id))
James Bottomleyc92f2222006-03-01 09:02:49 -0600210 return -1;
211
212 size = ioc->spi_data.sdp0length * 4;
213 /*
214 if (ioc->spi_data.sdp0length & 1)
215 size += size + 4;
216 size += 2048;
217 */
218
219 pg0 = dma_alloc_coherent(&ioc->pcidev->dev, size, &pg0_dma, GFP_KERNEL);
220 if (pg0 == NULL) {
221 starget_printk(KERN_ERR, starget, "dma_alloc_coherent for parameters failed\n");
222 return -EINVAL;
223 }
224
225 memset(&hdr, 0, sizeof(hdr));
226
227 hdr.PageVersion = ioc->spi_data.sdp0version;
228 hdr.PageLength = ioc->spi_data.sdp0length;
229 hdr.PageNumber = 0;
230 hdr.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
231
232 memset(&cfg, 0, sizeof(cfg));
233
234 cfg.cfghdr.hdr = &hdr;
235 cfg.physAddr = pg0_dma;
236 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
237 cfg.dir = 0;
238 cfg.pageAddr = starget->id;
239
240 if (mpt_config(ioc, &cfg)) {
241 starget_printk(KERN_ERR, starget, "mpt_config failed\n");
242 goto out_free;
243 }
244 err = 0;
245 memcpy(pass_pg0, pg0, size);
246
247 out_free:
248 dma_free_coherent(&ioc->pcidev->dev, size, pg0, pg0_dma);
249 return err;
250}
251
252static u32 mptspi_getRP(struct scsi_target *starget)
253{
254 u32 nego = 0;
255
256 nego |= spi_iu(starget) ? MPI_SCSIDEVPAGE1_RP_IU : 0;
257 nego |= spi_dt(starget) ? MPI_SCSIDEVPAGE1_RP_DT : 0;
258 nego |= spi_qas(starget) ? MPI_SCSIDEVPAGE1_RP_QAS : 0;
259 nego |= spi_hold_mcs(starget) ? MPI_SCSIDEVPAGE1_RP_HOLD_MCS : 0;
260 nego |= spi_wr_flow(starget) ? MPI_SCSIDEVPAGE1_RP_WR_FLOW : 0;
261 nego |= spi_rd_strm(starget) ? MPI_SCSIDEVPAGE1_RP_RD_STRM : 0;
262 nego |= spi_rti(starget) ? MPI_SCSIDEVPAGE1_RP_RTI : 0;
263 nego |= spi_pcomp_en(starget) ? MPI_SCSIDEVPAGE1_RP_PCOMP_EN : 0;
264
265 nego |= (spi_period(starget) << MPI_SCSIDEVPAGE1_RP_SHIFT_MIN_SYNC_PERIOD) & MPI_SCSIDEVPAGE1_RP_MIN_SYNC_PERIOD_MASK;
266 nego |= (spi_offset(starget) << MPI_SCSIDEVPAGE1_RP_SHIFT_MAX_SYNC_OFFSET) & MPI_SCSIDEVPAGE1_RP_MAX_SYNC_OFFSET_MASK;
267 nego |= spi_width(starget) ? MPI_SCSIDEVPAGE1_RP_WIDE : 0;
268
269 return nego;
270}
271
272static void mptspi_read_parameters(struct scsi_target *starget)
273{
274 int nego;
275 struct _CONFIG_PAGE_SCSI_DEVICE_0 pg0;
276
277 mptspi_read_spi_device_pg0(starget, &pg0);
278
279 nego = le32_to_cpu(pg0.NegotiatedParameters);
280
281 spi_iu(starget) = (nego & MPI_SCSIDEVPAGE0_NP_IU) ? 1 : 0;
282 spi_dt(starget) = (nego & MPI_SCSIDEVPAGE0_NP_DT) ? 1 : 0;
283 spi_qas(starget) = (nego & MPI_SCSIDEVPAGE0_NP_QAS) ? 1 : 0;
284 spi_wr_flow(starget) = (nego & MPI_SCSIDEVPAGE0_NP_WR_FLOW) ? 1 : 0;
285 spi_rd_strm(starget) = (nego & MPI_SCSIDEVPAGE0_NP_RD_STRM) ? 1 : 0;
286 spi_rti(starget) = (nego & MPI_SCSIDEVPAGE0_NP_RTI) ? 1 : 0;
287 spi_pcomp_en(starget) = (nego & MPI_SCSIDEVPAGE0_NP_PCOMP_EN) ? 1 : 0;
288 spi_hold_mcs(starget) = (nego & MPI_SCSIDEVPAGE0_NP_HOLD_MCS) ? 1 : 0;
289 spi_period(starget) = (nego & MPI_SCSIDEVPAGE0_NP_NEG_SYNC_PERIOD_MASK) >> MPI_SCSIDEVPAGE0_NP_SHIFT_SYNC_PERIOD;
290 spi_offset(starget) = (nego & MPI_SCSIDEVPAGE0_NP_NEG_SYNC_OFFSET_MASK) >> MPI_SCSIDEVPAGE0_NP_SHIFT_SYNC_OFFSET;
291 spi_width(starget) = (nego & MPI_SCSIDEVPAGE0_NP_WIDE) ? 1 : 0;
292}
293
294static int
Eric Moore793955f2007-01-29 09:42:20 -0700295mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, u8 channel, u8 id)
James Bottomleyc92f2222006-03-01 09:02:49 -0600296{
297 MpiRaidActionRequest_t *pReq;
298 MPT_FRAME_HDR *mf;
299
300 /* Get and Populate a free Frame
301 */
302 if ((mf = mpt_get_msg_frame(hd->ioc->InternalCtx, hd->ioc)) == NULL) {
303 ddvprintk((MYIOC_s_WARN_FMT "_do_raid: no msg frames!\n",
304 hd->ioc->name));
305 return -EAGAIN;
306 }
307 pReq = (MpiRaidActionRequest_t *)mf;
308 if (quiesce)
309 pReq->Action = MPI_RAID_ACTION_QUIESCE_PHYS_IO;
310 else
311 pReq->Action = MPI_RAID_ACTION_ENABLE_PHYS_IO;
312 pReq->Reserved1 = 0;
313 pReq->ChainOffset = 0;
314 pReq->Function = MPI_FUNCTION_RAID_ACTION;
Eric Moore793955f2007-01-29 09:42:20 -0700315 pReq->VolumeID = id;
316 pReq->VolumeBus = channel;
James Bottomleyc92f2222006-03-01 09:02:49 -0600317 pReq->PhysDiskNum = 0;
318 pReq->MsgFlags = 0;
319 pReq->Reserved2 = 0;
320 pReq->ActionDataWord = 0; /* Reserved for this action */
321
322 mpt_add_sge((char *)&pReq->ActionDataSGE,
323 MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1);
324
Eric Moore793955f2007-01-29 09:42:20 -0700325 ddvprintk((MYIOC_s_INFO_FMT "RAID Volume action=%x channel=%d id=%d\n",
326 hd->ioc->name, pReq->Action, channel, id));
James Bottomleyc92f2222006-03-01 09:02:49 -0600327
328 hd->pLocal = NULL;
329 hd->timer.expires = jiffies + HZ*10; /* 10 second timeout */
330 hd->scandv_wait_done = 0;
331
332 /* Save cmd pointer, for resource free if timeout or
333 * FW reload occurs
334 */
335 hd->cmdPtr = mf;
336
337 add_timer(&hd->timer);
338 mpt_put_msg_frame(hd->ioc->InternalCtx, hd->ioc, mf);
339 wait_event(hd->scandv_waitq, hd->scandv_wait_done);
340
341 if ((hd->pLocal == NULL) || (hd->pLocal->completion != 0))
342 return -1;
343
344 return 0;
345}
346
347static void mptspi_dv_device(struct _MPT_SCSI_HOST *hd,
348 struct scsi_device *sdev)
349{
350 VirtTarget *vtarget = scsi_target(sdev)->hostdata;
351
352 /* no DV on RAID devices */
353 if (sdev->channel == 0 &&
Eric Moore793955f2007-01-29 09:42:20 -0700354 mptspi_is_raid(hd, sdev->id))
James Bottomleyc92f2222006-03-01 09:02:49 -0600355 return;
356
357 /* If this is a piece of a RAID, then quiesce first */
358 if (sdev->channel == 1 &&
Eric Moore793955f2007-01-29 09:42:20 -0700359 mptscsih_quiesce_raid(hd, 1, vtarget->channel, vtarget->id) < 0) {
James Bottomleyc92f2222006-03-01 09:02:49 -0600360 starget_printk(KERN_ERR, scsi_target(sdev),
361 "Integrated RAID quiesce failed\n");
362 return;
363 }
364
365 spi_dv_device(sdev);
366
367 if (sdev->channel == 1 &&
Eric Moore793955f2007-01-29 09:42:20 -0700368 mptscsih_quiesce_raid(hd, 0, vtarget->channel, vtarget->id) < 0)
James Bottomleyc92f2222006-03-01 09:02:49 -0600369 starget_printk(KERN_ERR, scsi_target(sdev),
370 "Integrated RAID resume failed\n");
371
372 mptspi_read_parameters(sdev->sdev_target);
373 spi_display_xfer_agreement(sdev->sdev_target);
374 mptspi_read_parameters(sdev->sdev_target);
375}
376
377static int mptspi_slave_alloc(struct scsi_device *sdev)
378{
James Bottomleyc92f2222006-03-01 09:02:49 -0600379 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sdev->host->hostdata;
Eric Moore793955f2007-01-29 09:42:20 -0700380 VirtTarget *vtarget;
381 VirtDevice *vdev;
382 struct scsi_target *starget;
James Bottomleyc92f2222006-03-01 09:02:49 -0600383
Eric Moore793955f2007-01-29 09:42:20 -0700384 if (sdev->channel == 1 &&
385 mptscsih_is_phys_disk(hd->ioc, 0, sdev->id) == 0)
386 return -ENXIO;
James Bottomleyc92f2222006-03-01 09:02:49 -0600387
Eric Moore793955f2007-01-29 09:42:20 -0700388 vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
389 if (!vdev) {
390 printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
391 hd->ioc->name, sizeof(VirtDevice));
392 return -ENOMEM;
James Bottomleyc92f2222006-03-01 09:02:49 -0600393 }
394
Eric Moore793955f2007-01-29 09:42:20 -0700395 vdev->lun = sdev->lun;
396 sdev->hostdata = vdev;
James Bottomleyc92f2222006-03-01 09:02:49 -0600397
Eric Moore793955f2007-01-29 09:42:20 -0700398 starget = scsi_target(sdev);
399 vtarget = starget->hostdata;
400 vdev->vtarget = vtarget;
401 vtarget->num_luns++;
James Bottomleyc92f2222006-03-01 09:02:49 -0600402
Eric Moore793955f2007-01-29 09:42:20 -0700403 if (sdev->channel == 1)
James Bottomleyc92f2222006-03-01 09:02:49 -0600404 sdev->no_uld_attach = 1;
James Bottomleyc92f2222006-03-01 09:02:49 -0600405
406 return 0;
407}
408
409static int mptspi_slave_configure(struct scsi_device *sdev)
410{
411 int ret = mptscsih_slave_configure(sdev);
412 struct _MPT_SCSI_HOST *hd =
413 (struct _MPT_SCSI_HOST *)sdev->host->hostdata;
414
415 if (ret)
416 return ret;
417
418 if ((sdev->channel == 1 ||
Eric Moore793955f2007-01-29 09:42:20 -0700419 !(mptspi_is_raid(hd, sdev->id))) &&
James Bottomleyc92f2222006-03-01 09:02:49 -0600420 !spi_initial_dv(sdev->sdev_target))
421 mptspi_dv_device(hd, sdev);
422
423 return 0;
424}
425
Eric Moore793955f2007-01-29 09:42:20 -0700426static int
427mptspi_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
428{
429 struct _MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata;
430 VirtDevice *vdev = SCpnt->device->hostdata;
431
432 if (!vdev || !vdev->vtarget) {
433 SCpnt->result = DID_NO_CONNECT << 16;
434 done(SCpnt);
435 return 0;
436 }
437
438 if (SCpnt->device->channel == 1 &&
439 mptscsih_is_phys_disk(hd->ioc, 0, SCpnt->device->id) == 0) {
440 SCpnt->result = DID_NO_CONNECT << 16;
441 done(SCpnt);
442 return 0;
443 }
444
445 return mptscsih_qcmd(SCpnt,done);
446}
447
James Bottomleyc92f2222006-03-01 09:02:49 -0600448static void mptspi_slave_destroy(struct scsi_device *sdev)
449{
450 struct scsi_target *starget = scsi_target(sdev);
451 VirtTarget *vtarget = starget->hostdata;
452 VirtDevice *vdevice = sdev->hostdata;
453
454 /* Will this be the last lun on a non-raid device? */
455 if (vtarget->num_luns == 1 && vdevice->configured_lun) {
456 struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
457
458 /* Async Narrow */
459 pg1.RequestedParameters = 0;
460 pg1.Reserved = 0;
461 pg1.Configuration = 0;
462
463 mptspi_write_spi_device_pg1(starget, &pg1);
464 }
465
466 mptscsih_slave_destroy(sdev);
467}
468
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -0400469static struct scsi_host_template mptspi_driver_template = {
Moore, Eric Deanf78496d2005-11-16 18:54:14 -0700470 .module = THIS_MODULE,
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -0400471 .proc_name = "mptspi",
472 .proc_info = mptscsih_proc_info,
473 .name = "MPT SPI Host",
474 .info = mptscsih_info,
Eric Moore793955f2007-01-29 09:42:20 -0700475 .queuecommand = mptspi_qcmd,
James Bottomleyc92f2222006-03-01 09:02:49 -0600476 .target_alloc = mptspi_target_alloc,
477 .slave_alloc = mptspi_slave_alloc,
478 .slave_configure = mptspi_slave_configure,
Eric Moore793955f2007-01-29 09:42:20 -0700479 .target_destroy = mptspi_target_destroy,
James Bottomleyc92f2222006-03-01 09:02:49 -0600480 .slave_destroy = mptspi_slave_destroy,
Moore, Eric Dean6e3815b2005-06-24 12:18:57 -0600481 .change_queue_depth = mptscsih_change_queue_depth,
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -0400482 .eh_abort_handler = mptscsih_abort,
483 .eh_device_reset_handler = mptscsih_dev_reset,
484 .eh_bus_reset_handler = mptscsih_bus_reset,
485 .eh_host_reset_handler = mptscsih_host_reset,
486 .bios_param = mptscsih_bios_param,
487 .can_queue = MPT_SCSI_CAN_QUEUE,
488 .this_id = -1,
489 .sg_tablesize = MPT_SCSI_SG_DEPTH,
490 .max_sectors = 8192,
491 .cmd_per_lun = 7,
492 .use_clustering = ENABLE_CLUSTERING,
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -0400493};
494
James Bottomleyc92f2222006-03-01 09:02:49 -0600495static int mptspi_write_spi_device_pg1(struct scsi_target *starget,
496 struct _CONFIG_PAGE_SCSI_DEVICE_1 *pass_pg1)
497{
498 struct Scsi_Host *shost = dev_to_shost(&starget->dev);
499 struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata;
500 struct _MPT_ADAPTER *ioc = hd->ioc;
501 struct _CONFIG_PAGE_SCSI_DEVICE_1 *pg1;
502 dma_addr_t pg1_dma;
503 int size;
504 struct _x_config_parms cfg;
505 struct _CONFIG_PAGE_HEADER hdr;
506 int err = -EBUSY;
507
508 /* don't allow updating nego parameters on RAID devices */
509 if (starget->channel == 0 &&
Eric Moore793955f2007-01-29 09:42:20 -0700510 mptspi_is_raid(hd, starget->id))
James Bottomleyc92f2222006-03-01 09:02:49 -0600511 return -1;
512
513 size = ioc->spi_data.sdp1length * 4;
514
515 pg1 = dma_alloc_coherent(&ioc->pcidev->dev, size, &pg1_dma, GFP_KERNEL);
516 if (pg1 == NULL) {
517 starget_printk(KERN_ERR, starget, "dma_alloc_coherent for parameters failed\n");
518 return -EINVAL;
519 }
520
521 memset(&hdr, 0, sizeof(hdr));
522
523 hdr.PageVersion = ioc->spi_data.sdp1version;
524 hdr.PageLength = ioc->spi_data.sdp1length;
525 hdr.PageNumber = 1;
526 hdr.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
527
528 memset(&cfg, 0, sizeof(cfg));
529
530 cfg.cfghdr.hdr = &hdr;
531 cfg.physAddr = pg1_dma;
532 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
533 cfg.dir = 1;
534 cfg.pageAddr = starget->id;
535
536 memcpy(pg1, pass_pg1, size);
537
538 pg1->Header.PageVersion = hdr.PageVersion;
539 pg1->Header.PageLength = hdr.PageLength;
540 pg1->Header.PageNumber = hdr.PageNumber;
541 pg1->Header.PageType = hdr.PageType;
542
543 if (mpt_config(ioc, &cfg)) {
544 starget_printk(KERN_ERR, starget, "mpt_config failed\n");
545 goto out_free;
546 }
547 err = 0;
548
549 out_free:
550 dma_free_coherent(&ioc->pcidev->dev, size, pg1, pg1_dma);
551 return err;
552}
553
554static void mptspi_write_offset(struct scsi_target *starget, int offset)
555{
556 struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
557 u32 nego;
558
559 if (offset < 0)
560 offset = 0;
561
562 if (offset > 255)
563 offset = 255;
564
565 if (spi_offset(starget) == -1)
566 mptspi_read_parameters(starget);
567
568 spi_offset(starget) = offset;
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
579static void mptspi_write_period(struct scsi_target *starget, int period)
580{
581 struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
582 u32 nego;
583
584 if (period < 8)
585 period = 8;
586
587 if (period > 255)
588 period = 255;
589
590 if (spi_period(starget) == -1)
591 mptspi_read_parameters(starget);
592
593 if (period == 8) {
594 spi_iu(starget) = 1;
595 spi_dt(starget) = 1;
596 } else if (period == 9) {
597 spi_dt(starget) = 1;
598 }
599
600 spi_period(starget) = period;
601
602 nego = mptspi_getRP(starget);
603
604 pg1.RequestedParameters = cpu_to_le32(nego);
605 pg1.Reserved = 0;
606 pg1.Configuration = 0;
607
608 mptspi_write_spi_device_pg1(starget, &pg1);
609}
610
611static void mptspi_write_dt(struct scsi_target *starget, int dt)
612{
613 struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
614 u32 nego;
615
616 if (spi_period(starget) == -1)
617 mptspi_read_parameters(starget);
618
619 if (!dt && spi_period(starget) < 10)
620 spi_period(starget) = 10;
621
622 spi_dt(starget) = dt;
623
624 nego = mptspi_getRP(starget);
625
626
627 pg1.RequestedParameters = cpu_to_le32(nego);
628 pg1.Reserved = 0;
629 pg1.Configuration = 0;
630
631 mptspi_write_spi_device_pg1(starget, &pg1);
632}
633
634static void mptspi_write_iu(struct scsi_target *starget, int iu)
635{
636 struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
637 u32 nego;
638
639 if (spi_period(starget) == -1)
640 mptspi_read_parameters(starget);
641
642 if (!iu && spi_period(starget) < 9)
643 spi_period(starget) = 9;
644
645 spi_iu(starget) = iu;
646
647 nego = mptspi_getRP(starget);
648
649 pg1.RequestedParameters = cpu_to_le32(nego);
650 pg1.Reserved = 0;
651 pg1.Configuration = 0;
652
653 mptspi_write_spi_device_pg1(starget, &pg1);
654}
655
656#define MPTSPI_SIMPLE_TRANSPORT_PARM(parm) \
657static void mptspi_write_##parm(struct scsi_target *starget, int parm)\
658{ \
659 struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1; \
660 u32 nego; \
661 \
662 spi_##parm(starget) = parm; \
663 \
664 nego = mptspi_getRP(starget); \
665 \
666 pg1.RequestedParameters = cpu_to_le32(nego); \
667 pg1.Reserved = 0; \
668 pg1.Configuration = 0; \
669 \
670 mptspi_write_spi_device_pg1(starget, &pg1); \
671}
672
673MPTSPI_SIMPLE_TRANSPORT_PARM(rd_strm)
674MPTSPI_SIMPLE_TRANSPORT_PARM(wr_flow)
675MPTSPI_SIMPLE_TRANSPORT_PARM(rti)
676MPTSPI_SIMPLE_TRANSPORT_PARM(hold_mcs)
677MPTSPI_SIMPLE_TRANSPORT_PARM(pcomp_en)
678
679static void mptspi_write_qas(struct scsi_target *starget, int qas)
680{
681 struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
682 struct Scsi_Host *shost = dev_to_shost(&starget->dev);
683 struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata;
684 VirtTarget *vtarget = starget->hostdata;
685 u32 nego;
686
687 if ((vtarget->negoFlags & MPT_TARGET_NO_NEGO_QAS) ||
688 hd->ioc->spi_data.noQas)
689 spi_qas(starget) = 0;
690 else
691 spi_qas(starget) = qas;
692
693 nego = mptspi_getRP(starget);
694
695 pg1.RequestedParameters = cpu_to_le32(nego);
696 pg1.Reserved = 0;
697 pg1.Configuration = 0;
698
699 mptspi_write_spi_device_pg1(starget, &pg1);
700}
701
702static void mptspi_write_width(struct scsi_target *starget, int width)
703{
704 struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
705 u32 nego;
706
707 if (!width) {
708 spi_dt(starget) = 0;
709 if (spi_period(starget) < 10)
710 spi_period(starget) = 10;
711 }
712
713 spi_width(starget) = width;
714
715 nego = mptspi_getRP(starget);
716
717 pg1.RequestedParameters = cpu_to_le32(nego);
718 pg1.Reserved = 0;
719 pg1.Configuration = 0;
720
721 mptspi_write_spi_device_pg1(starget, &pg1);
722}
723
724struct work_queue_wrapper {
725 struct work_struct work;
726 struct _MPT_SCSI_HOST *hd;
727 int disk;
728};
729
David Howellsc4028952006-11-22 14:57:56 +0000730static void mpt_work_wrapper(struct work_struct *work)
James Bottomleyc92f2222006-03-01 09:02:49 -0600731{
David Howellsc4028952006-11-22 14:57:56 +0000732 struct work_queue_wrapper *wqw =
733 container_of(work, struct work_queue_wrapper, work);
James Bottomleyc92f2222006-03-01 09:02:49 -0600734 struct _MPT_SCSI_HOST *hd = wqw->hd;
735 struct Scsi_Host *shost = hd->ioc->sh;
736 struct scsi_device *sdev;
737 int disk = wqw->disk;
738 struct _CONFIG_PAGE_IOC_3 *pg3;
739
740 kfree(wqw);
741
742 mpt_findImVolumes(hd->ioc);
743 pg3 = hd->ioc->raid_data.pIocPg3;
744 if (!pg3)
745 return;
746
747 shost_for_each_device(sdev,shost) {
748 struct scsi_target *starget = scsi_target(sdev);
749 VirtTarget *vtarget = starget->hostdata;
750
751 /* only want to search RAID components */
752 if (sdev->channel != 1)
753 continue;
754
Eric Moore793955f2007-01-29 09:42:20 -0700755 /* The id is the raid PhysDiskNum, even if
James Bottomleyc92f2222006-03-01 09:02:49 -0600756 * starget->id is the actual target address */
Eric Moore793955f2007-01-29 09:42:20 -0700757 if(vtarget->id != disk)
James Bottomleyc92f2222006-03-01 09:02:49 -0600758 continue;
759
760 starget_printk(KERN_INFO, vtarget->starget,
761 "Integrated RAID requests DV of new device\n");
762 mptspi_dv_device(hd, sdev);
763 }
764 shost_printk(KERN_INFO, shost,
765 "Integrated RAID detects new device %d\n", disk);
766 scsi_scan_target(&hd->ioc->sh->shost_gendev, 1, disk, 0, 1);
767}
768
769
770static void mpt_dv_raid(struct _MPT_SCSI_HOST *hd, int disk)
771{
772 struct work_queue_wrapper *wqw = kmalloc(sizeof(*wqw), GFP_ATOMIC);
773
774 if (!wqw) {
775 shost_printk(KERN_ERR, hd->ioc->sh,
776 "Failed to act on RAID event for physical disk %d\n",
777 disk);
778 return;
779 }
David Howellsc4028952006-11-22 14:57:56 +0000780 INIT_WORK(&wqw->work, mpt_work_wrapper);
James Bottomleyc92f2222006-03-01 09:02:49 -0600781 wqw->hd = hd;
782 wqw->disk = disk;
783
784 schedule_work(&wqw->work);
785}
786
787static int
788mptspi_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
789{
790 u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
791 struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)ioc->sh->hostdata;
792
793 if (hd && event == MPI_EVENT_INTEGRATED_RAID) {
794 int reason
795 = (le32_to_cpu(pEvReply->Data[0]) & 0x00FF0000) >> 16;
796
797 if (reason == MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) {
798 int disk = (le32_to_cpu(pEvReply->Data[0]) & 0xFF000000) >> 24;
799 mpt_dv_raid(hd, disk);
800 }
801 }
802 return mptscsih_event_process(ioc, pEvReply);
803}
804
805static int
806mptspi_deny_binding(struct scsi_target *starget)
807{
808 struct _MPT_SCSI_HOST *hd =
809 (struct _MPT_SCSI_HOST *)dev_to_shost(starget->dev.parent)->hostdata;
Eric Moore793955f2007-01-29 09:42:20 -0700810 return ((mptspi_is_raid(hd, starget->id)) &&
James Bottomleyc92f2222006-03-01 09:02:49 -0600811 starget->channel == 0) ? 1 : 0;
812}
813
814static struct spi_function_template mptspi_transport_functions = {
815 .get_offset = mptspi_read_parameters,
816 .set_offset = mptspi_write_offset,
817 .show_offset = 1,
818 .get_period = mptspi_read_parameters,
819 .set_period = mptspi_write_period,
820 .show_period = 1,
821 .get_width = mptspi_read_parameters,
822 .set_width = mptspi_write_width,
823 .show_width = 1,
824 .get_iu = mptspi_read_parameters,
825 .set_iu = mptspi_write_iu,
826 .show_iu = 1,
827 .get_dt = mptspi_read_parameters,
828 .set_dt = mptspi_write_dt,
829 .show_dt = 1,
830 .get_qas = mptspi_read_parameters,
831 .set_qas = mptspi_write_qas,
832 .show_qas = 1,
833 .get_wr_flow = mptspi_read_parameters,
834 .set_wr_flow = mptspi_write_wr_flow,
835 .show_wr_flow = 1,
836 .get_rd_strm = mptspi_read_parameters,
837 .set_rd_strm = mptspi_write_rd_strm,
838 .show_rd_strm = 1,
839 .get_rti = mptspi_read_parameters,
840 .set_rti = mptspi_write_rti,
841 .show_rti = 1,
842 .get_pcomp_en = mptspi_read_parameters,
843 .set_pcomp_en = mptspi_write_pcomp_en,
844 .show_pcomp_en = 1,
845 .get_hold_mcs = mptspi_read_parameters,
846 .set_hold_mcs = mptspi_write_hold_mcs,
847 .show_hold_mcs = 1,
848 .deny_binding = mptspi_deny_binding,
849};
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -0400850
851/****************************************************************************
852 * Supported hardware
853 */
854
855static struct pci_device_id mptspi_pci_table[] = {
Eric Moore87cf8982006-06-27 16:09:26 -0600856 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_53C1030,
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -0400857 PCI_ANY_ID, PCI_ANY_ID },
Eric Moore87cf8982006-06-27 16:09:26 -0600858 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_53C1035,
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -0400859 PCI_ANY_ID, PCI_ANY_ID },
860 {0} /* Terminating entry */
861};
862MODULE_DEVICE_TABLE(pci, mptspi_pci_table);
863
Eric Moore6e1cad02006-04-25 17:38:58 -0600864
865/*
866 * renegotiate for a given target
867 */
868static void
David Howellsc4028952006-11-22 14:57:56 +0000869mptspi_dv_renegotiate_work(struct work_struct *work)
Eric Moore6e1cad02006-04-25 17:38:58 -0600870{
David Howellsc4028952006-11-22 14:57:56 +0000871 struct work_queue_wrapper *wqw =
872 container_of(work, struct work_queue_wrapper, work);
Eric Moore6e1cad02006-04-25 17:38:58 -0600873 struct _MPT_SCSI_HOST *hd = wqw->hd;
874 struct scsi_device *sdev;
875
876 kfree(wqw);
877
878 shost_for_each_device(sdev, hd->ioc->sh)
879 mptspi_dv_device(hd, sdev);
880}
881
882static void
883mptspi_dv_renegotiate(struct _MPT_SCSI_HOST *hd)
884{
885 struct work_queue_wrapper *wqw = kmalloc(sizeof(*wqw), GFP_ATOMIC);
886
887 if (!wqw)
888 return;
889
David Howellsc4028952006-11-22 14:57:56 +0000890 INIT_WORK(&wqw->work, mptspi_dv_renegotiate_work);
Eric Moore6e1cad02006-04-25 17:38:58 -0600891 wqw->hd = hd;
892
893 schedule_work(&wqw->work);
894}
895
896/*
897 * spi module reset handler
898 */
899static int
900mptspi_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
901{
902 struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)ioc->sh->hostdata;
903 int rc;
904
905 rc = mptscsih_ioc_reset(ioc, reset_phase);
906
907 if (reset_phase == MPT_IOC_POST_RESET)
908 mptspi_dv_renegotiate(hd);
909
910 return rc;
911}
912
Tom "spot" Callawayc29ca9d2006-06-09 17:01:48 -0700913#ifdef CONFIG_PM
Eric Moore6e1cad02006-04-25 17:38:58 -0600914/*
915 * spi module resume handler
916 */
917static int
918mptspi_resume(struct pci_dev *pdev)
919{
920 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
921 struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)ioc->sh->hostdata;
922 int rc;
923
924 rc = mptscsih_resume(pdev);
925 mptspi_dv_renegotiate(hd);
926
927 return rc;
928}
Tom "spot" Callawayc29ca9d2006-06-09 17:01:48 -0700929#endif
Eric Moore6e1cad02006-04-25 17:38:58 -0600930
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -0400931/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
932/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
933/*
934 * mptspi_probe - Installs scsi devices per bus.
935 * @pdev: Pointer to pci_dev structure
936 *
937 * Returns 0 for success, non-zero for failure.
938 *
939 */
940static int
941mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
942{
943 struct Scsi_Host *sh;
944 MPT_SCSI_HOST *hd;
945 MPT_ADAPTER *ioc;
946 unsigned long flags;
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +0100947 int ii;
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -0400948 int numSGE = 0;
949 int scale;
950 int ioc_cap;
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -0400951 int error=0;
952 int r;
Christoph Hellwigc6678e02005-08-18 16:24:53 +0200953
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -0400954 if ((r = mpt_attach(pdev,id)) != 0)
955 return r;
Christoph Hellwigc6678e02005-08-18 16:24:53 +0200956
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -0400957 ioc = pci_get_drvdata(pdev);
Moore, Eric Dean d335cc32005-04-30 17:09:38 -0500958 ioc->DoneCtx = mptspiDoneCtx;
959 ioc->TaskCtx = mptspiTaskCtx;
960 ioc->InternalCtx = mptspiInternalCtx;
Christoph Hellwigc6678e02005-08-18 16:24:53 +0200961
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -0400962 /* Added sanity check on readiness of the MPT adapter.
963 */
964 if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
965 printk(MYIOC_s_WARN_FMT
966 "Skipping because it's not operational!\n",
967 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -0700968 error = -ENODEV;
969 goto out_mptspi_probe;
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -0400970 }
971
972 if (!ioc->active) {
973 printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
974 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -0700975 error = -ENODEV;
976 goto out_mptspi_probe;
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -0400977 }
978
979 /* Sanity check - ensure at least 1 port is INITIATOR capable
980 */
981 ioc_cap = 0;
982 for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
983 if (ioc->pfacts[ii].ProtocolFlags &
984 MPI_PORTFACTS_PROTOCOL_INITIATOR)
985 ioc_cap ++;
986 }
987
988 if (!ioc_cap) {
989 printk(MYIOC_s_WARN_FMT
990 "Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n",
991 ioc->name, ioc);
Moore, Eric Dean466544d2005-09-14 18:09:10 -0600992 return 0;
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -0400993 }
994
995 sh = scsi_host_alloc(&mptspi_driver_template, sizeof(MPT_SCSI_HOST));
996
997 if (!sh) {
998 printk(MYIOC_s_WARN_FMT
999 "Unable to register controller with SCSI subsystem\n",
1000 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001001 error = -1;
1002 goto out_mptspi_probe;
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001003 }
1004
1005 spin_lock_irqsave(&ioc->FreeQlock, flags);
1006
1007 /* Attach the SCSI Host to the IOC structure
1008 */
1009 ioc->sh = sh;
1010
1011 sh->io_port = 0;
1012 sh->n_io_port = 0;
1013 sh->irq = 0;
1014
1015 /* set 16 byte cdb's */
1016 sh->max_cmd_len = 16;
1017
1018 /* Yikes! This is important!
1019 * Otherwise, by default, linux
1020 * only scans target IDs 0-7!
1021 * pfactsN->MaxDevices unreliable
1022 * (not supported in early
1023 * versions of the FW).
1024 * max_id = 1 + actual max id,
1025 * max_lun = 1 + actual last lun,
1026 * see hosts.h :o(
1027 */
Eric Moore793955f2007-01-29 09:42:20 -07001028 sh->max_id = ioc->devices_per_bus;
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001029
1030 sh->max_lun = MPT_LAST_LUN + 1;
James Bottomleyc92f2222006-03-01 09:02:49 -06001031 /*
1032 * If RAID Firmware Detected, setup virtual channel
1033 */
1034 if ((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK)
1035 > MPI_FW_HEADER_PID_PROD_TARGET_SCSI)
1036 sh->max_channel = 1;
1037 else
1038 sh->max_channel = 0;
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001039 sh->this_id = ioc->pfacts[0].PortSCSIID;
1040
1041 /* Required entry.
1042 */
1043 sh->unique_id = ioc->id;
1044
1045 /* Verify that we won't exceed the maximum
1046 * number of chain buffers
1047 * We can optimize: ZZ = req_sz/sizeof(SGE)
1048 * For 32bit SGE's:
1049 * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
1050 * + (req_sz - 64)/sizeof(SGE)
1051 * A slightly different algorithm is required for
1052 * 64bit SGEs.
1053 */
1054 scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
1055 if (sizeof(dma_addr_t) == sizeof(u64)) {
1056 numSGE = (scale - 1) *
1057 (ioc->facts.MaxChainDepth-1) + scale +
1058 (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
1059 sizeof(u32));
1060 } else {
1061 numSGE = 1 + (scale - 1) *
1062 (ioc->facts.MaxChainDepth-1) + scale +
1063 (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
1064 sizeof(u32));
1065 }
1066
1067 if (numSGE < sh->sg_tablesize) {
1068 /* Reset this value */
1069 dprintk((MYIOC_s_INFO_FMT
1070 "Resetting sg_tablesize to %d from %d\n",
1071 ioc->name, numSGE, sh->sg_tablesize));
1072 sh->sg_tablesize = numSGE;
1073 }
1074
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001075 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
1076
1077 hd = (MPT_SCSI_HOST *) sh->hostdata;
1078 hd->ioc = ioc;
1079
1080 /* SCSI needs scsi_cmnd lookup table!
1081 * (with size equal to req_depth*PtrSz!)
1082 */
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001083 hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
1084 if (!hd->ScsiLookup) {
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001085 error = -ENOMEM;
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001086 goto out_mptspi_probe;
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001087 }
1088
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001089 dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
1090 ioc->name, hd->ScsiLookup));
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001091
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001092 /* Clear the TM flags
1093 */
1094 hd->tmPending = 0;
1095 hd->tmState = TM_STATE_NONE;
1096 hd->resetPending = 0;
1097 hd->abortSCpnt = NULL;
1098
1099 /* Clear the pointer used to store
1100 * single-threaded commands, i.e., those
1101 * issued during a bus scan, dv and
1102 * configuration pages.
1103 */
1104 hd->cmdPtr = NULL;
1105
1106 /* Initialize this SCSI Hosts' timers
1107 * To use, set the timer expires field
1108 * and add_timer
1109 */
1110 init_timer(&hd->timer);
1111 hd->timer.data = (unsigned long) hd;
1112 hd->timer.function = mptscsih_timer_expired;
1113
1114 ioc->spi_data.Saf_Te = mpt_saf_te;
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001115
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001116 hd->negoNvram = MPT_SCSICFG_USE_NVRAM;
1117 ddvprintk((MYIOC_s_INFO_FMT
Eric Mooreba856d32006-07-11 17:34:01 -06001118 "saf_te %x\n",
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001119 ioc->name,
Eric Mooreba856d32006-07-11 17:34:01 -06001120 mpt_saf_te));
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001121 ioc->spi_data.noQas = 0;
1122
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001123 init_waitqueue_head(&hd->scandv_waitq);
1124 hd->scandv_wait_done = 0;
1125 hd->last_queue_full = 0;
1126
James Bottomleyc92f2222006-03-01 09:02:49 -06001127 /* Some versions of the firmware don't support page 0; without
1128 * that we can't get the parameters */
1129 if (hd->ioc->spi_data.sdp0length != 0)
1130 sh->transportt = mptspi_transport_template;
1131
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001132 error = scsi_add_host (sh, &ioc->pcidev->dev);
1133 if(error) {
1134 dprintk((KERN_ERR MYNAM
1135 "scsi_add_host failed\n"));
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001136 goto out_mptspi_probe;
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001137 }
1138
Moore, Ericd8e925d2006-01-16 18:53:06 -07001139 /*
1140 * issue internal bus reset
1141 */
1142 if (ioc->spi_data.bus_reset)
1143 mptscsih_TMHandler(hd,
1144 MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
1145 0, 0, 0, 0, 5);
1146
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001147 scsi_scan_host(sh);
1148 return 0;
1149
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001150out_mptspi_probe:
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001151
1152 mptscsih_remove(pdev);
1153 return error;
1154}
1155
1156static struct pci_driver mptspi_driver = {
1157 .name = "mptspi",
1158 .id_table = mptspi_pci_table,
1159 .probe = mptspi_probe,
1160 .remove = __devexit_p(mptscsih_remove),
Greg Kroah-Hartmand18c3db2005-06-23 17:35:56 -07001161 .shutdown = mptscsih_shutdown,
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001162#ifdef CONFIG_PM
1163 .suspend = mptscsih_suspend,
Eric Moore6e1cad02006-04-25 17:38:58 -06001164 .resume = mptspi_resume,
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001165#endif
1166};
1167
1168/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1169/**
Randy Dunlapd9489fb2006-12-06 20:38:43 -08001170 * mptspi_init - Register MPT adapter(s) as SCSI host(s) with SCSI mid-layer.
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001171 *
1172 * Returns 0 for success, non-zero for failure.
1173 */
1174static int __init
1175mptspi_init(void)
1176{
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001177 show_mptmod_ver(my_NAME, my_VERSION);
1178
James Bottomleyc92f2222006-03-01 09:02:49 -06001179 mptspi_transport_template = spi_attach_transport(&mptspi_transport_functions);
1180 if (!mptspi_transport_template)
1181 return -ENODEV;
1182
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001183 mptspiDoneCtx = mpt_register(mptscsih_io_done, MPTSPI_DRIVER);
1184 mptspiTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSPI_DRIVER);
1185 mptspiInternalCtx = mpt_register(mptscsih_scandv_complete, MPTSPI_DRIVER);
1186
James Bottomleyc92f2222006-03-01 09:02:49 -06001187 if (mpt_event_register(mptspiDoneCtx, mptspi_event_process) == 0) {
Moore, Eric3a892be2006-03-14 09:14:03 -07001188 devtverboseprintk((KERN_INFO MYNAM
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001189 ": Registered for IOC event notifications\n"));
1190 }
1191
Eric Moore6e1cad02006-04-25 17:38:58 -06001192 if (mpt_reset_register(mptspiDoneCtx, mptspi_ioc_reset) == 0) {
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001193 dprintk((KERN_INFO MYNAM
1194 ": Registered for IOC reset notifications\n"));
1195 }
1196
1197 return pci_register_driver(&mptspi_driver);
1198}
1199
1200/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1201/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1202/**
1203 * mptspi_exit - Unregisters MPT adapter(s)
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001204 */
1205static void __exit
1206mptspi_exit(void)
1207{
1208 pci_unregister_driver(&mptspi_driver);
Moore, Ericd8e925d2006-01-16 18:53:06 -07001209
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001210 mpt_reset_deregister(mptspiDoneCtx);
1211 dprintk((KERN_INFO MYNAM
1212 ": Deregistered for IOC reset notifications\n"));
1213
1214 mpt_event_deregister(mptspiDoneCtx);
1215 dprintk((KERN_INFO MYNAM
1216 ": Deregistered for IOC event notifications\n"));
1217
1218 mpt_deregister(mptspiInternalCtx);
1219 mpt_deregister(mptspiTaskCtx);
1220 mpt_deregister(mptspiDoneCtx);
James Bottomleyc92f2222006-03-01 09:02:49 -06001221 spi_release_transport(mptspi_transport_template);
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001222}
1223
1224module_init(mptspi_init);
1225module_exit(mptspi_exit);