blob: 4248bf331e13971e25ff60e21d550a9b1f68e490 [file] [log] [blame]
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001/*
2 * linux/drivers/message/fusion/mptspi.c
Prakash, Sathyaf36789e2007-08-14 16:22:54 +05303 * For use with LSI PCI chip/adapter(s)
4 * running LSI Fusion MPT (Message Passing Technology) firmware.
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04005 *
Prakash, Sathyaf36789e2007-08-14 16:22:54 +05306 * Copyright (c) 1999-2007 LSI Corporation
Eric Moore16d20102007-06-13 16:31:07 -06007 * (mailto:DL-MPTFusionLinux@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
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -040047#include <linux/module.h>
48#include <linux/kernel.h>
49#include <linux/init.h>
50#include <linux/errno.h>
51#include <linux/kdev_t.h>
52#include <linux/blkdev.h>
53#include <linux/delay.h> /* for mdelay */
54#include <linux/interrupt.h> /* needed for in_interrupt() proto */
55#include <linux/reboot.h> /* notifier code */
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -040056#include <linux/workqueue.h>
James Bottomleyc92f2222006-03-01 09:02:49 -060057#include <linux/raid_class.h>
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -040058
59#include <scsi/scsi.h>
60#include <scsi/scsi_cmnd.h>
61#include <scsi/scsi_device.h>
62#include <scsi/scsi_host.h>
63#include <scsi/scsi_tcq.h>
James Bottomleyc92f2222006-03-01 09:02:49 -060064#include <scsi/scsi_transport.h>
65#include <scsi/scsi_transport_spi.h>
Eric Moore873c82e2007-01-29 09:44:06 -070066#include <scsi/scsi_dbg.h>
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -040067
68#include "mptbase.h"
69#include "mptscsih.h"
70
71/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
72#define my_NAME "Fusion MPT SPI Host driver"
73#define my_VERSION MPT_LINUX_VERSION_COMMON
74#define MYNAM "mptspi"
75
76MODULE_AUTHOR(MODULEAUTHOR);
77MODULE_DESCRIPTION(my_NAME);
78MODULE_LICENSE("GPL");
Eric Moore9f4203b2007-01-04 20:47:47 -070079MODULE_VERSION(my_VERSION);
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -040080
81/* Command line args */
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -040082static int mpt_saf_te = MPTSCSIH_SAF_TE;
83module_param(mpt_saf_te, int, 0);
84MODULE_PARM_DESC(mpt_saf_te, " Force enabling SEP Processor: enable=1 (default=MPTSCSIH_SAF_TE=0)");
85
James Bottomleyc92f2222006-03-01 09:02:49 -060086static void mptspi_write_offset(struct scsi_target *, int);
87static void mptspi_write_width(struct scsi_target *, int);
88static int mptspi_write_spi_device_pg1(struct scsi_target *,
89 struct _CONFIG_PAGE_SCSI_DEVICE_1 *);
90
91static struct scsi_transport_template *mptspi_transport_template = NULL;
92
Prakash, Sathyaf606f572007-08-14 16:12:53 +053093static u8 mptspiDoneCtx = MPT_MAX_PROTOCOL_DRIVERS;
94static u8 mptspiTaskCtx = MPT_MAX_PROTOCOL_DRIVERS;
95static u8 mptspiInternalCtx = MPT_MAX_PROTOCOL_DRIVERS; /* Used only for internal commands */
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -040096
Eric Moore5a9c47b2007-01-29 09:43:17 -070097/**
Randy Dunlap1544d672007-02-20 11:17:03 -080098 * mptspi_setTargetNegoParms - Update the target negotiation parameters
Eric Moore5a9c47b2007-01-29 09:43:17 -070099 * @hd: Pointer to a SCSI Host Structure
Randy Dunlap1544d672007-02-20 11:17:03 -0800100 * @target: per target private data
Eric Moore5a9c47b2007-01-29 09:43:17 -0700101 * @sdev: SCSI device
102 *
Randy Dunlap1544d672007-02-20 11:17:03 -0800103 * Update the target negotiation parameters based on the the Inquiry
104 * data, adapter capabilities, and NVRAM settings.
Eric Moore5a9c47b2007-01-29 09:43:17 -0700105 **/
106static void
107mptspi_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target,
108 struct scsi_device *sdev)
109{
110 SpiCfgData *pspi_data = &hd->ioc->spi_data;
111 int id = (int) target->id;
112 int nvram;
113 u8 width = MPT_NARROW;
114 u8 factor = MPT_ASYNC;
115 u8 offset = 0;
116 u8 nfactor;
117 u8 noQas = 1;
118
119 target->negoFlags = pspi_data->noQas;
120
121 if (sdev->scsi_level < SCSI_2) {
122 width = 0;
123 factor = MPT_ULTRA2;
124 offset = pspi_data->maxSyncOffset;
125 target->tflags &= ~MPT_TARGET_FLAGS_Q_YES;
126 } else {
127 if (scsi_device_wide(sdev))
128 width = 1;
129
130 if (scsi_device_sync(sdev)) {
131 factor = pspi_data->minSyncFactor;
132 if (!scsi_device_dt(sdev))
133 factor = MPT_ULTRA2;
134 else {
135 if (!scsi_device_ius(sdev) &&
136 !scsi_device_qas(sdev))
137 factor = MPT_ULTRA160;
138 else {
139 factor = MPT_ULTRA320;
140 if (scsi_device_qas(sdev)) {
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +0530141 ddvprintk(hd->ioc,
Eric Moore29dd3602007-09-14 18:46:51 -0600142 printk(MYIOC_s_DEBUG_FMT "Enabling QAS due to "
143 "byte56=%02x on id=%d!\n", hd->ioc->name,
144 scsi_device_qas(sdev), id));
Eric Moore5a9c47b2007-01-29 09:43:17 -0700145 noQas = 0;
146 }
147 if (sdev->type == TYPE_TAPE &&
148 scsi_device_ius(sdev))
149 target->negoFlags |= MPT_TAPE_NEGO_IDP;
150 }
151 }
152 offset = pspi_data->maxSyncOffset;
153
154 /* If RAID, never disable QAS
155 * else if non RAID, do not disable
156 * QAS if bit 1 is set
157 * bit 1 QAS support, non-raid only
158 * bit 0 IU support
159 */
160 if (target->raidVolume == 1)
161 noQas = 0;
162 } else {
163 factor = MPT_ASYNC;
164 offset = 0;
165 }
166 }
167
168 if (!sdev->tagged_supported)
169 target->tflags &= ~MPT_TARGET_FLAGS_Q_YES;
170
171 /* Update tflags based on NVRAM settings. (SCSI only)
172 */
173 if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) {
174 nvram = pspi_data->nvram[id];
175 nfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8;
176
177 if (width)
178 width = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
179
180 if (offset > 0) {
181 /* Ensure factor is set to the
182 * maximum of: adapter, nvram, inquiry
183 */
184 if (nfactor) {
185 if (nfactor < pspi_data->minSyncFactor )
186 nfactor = pspi_data->minSyncFactor;
187
188 factor = max(factor, nfactor);
189 if (factor == MPT_ASYNC)
190 offset = 0;
191 } else {
192 offset = 0;
193 factor = MPT_ASYNC;
194 }
195 } else {
196 factor = MPT_ASYNC;
197 }
198 }
199
200 /* Make sure data is consistent
201 */
202 if ((!width) && (factor < MPT_ULTRA2))
203 factor = MPT_ULTRA2;
204
205 /* Save the data to the target structure.
206 */
207 target->minSyncFactor = factor;
208 target->maxOffset = offset;
209 target->maxWidth = width;
210
211 target->tflags |= MPT_TARGET_FLAGS_VALID_NEGO;
212
213 /* Disable unused features.
214 */
215 if (!width)
216 target->negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
217
218 if (!offset)
219 target->negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
220
221 if ( factor > MPT_ULTRA320 )
222 noQas = 0;
223
224 if (noQas && (pspi_data->noQas == 0)) {
225 pspi_data->noQas |= MPT_TARGET_NO_NEGO_QAS;
226 target->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
227
228 /* Disable QAS in a mixed configuration case
229 */
230
Eric Moore29dd3602007-09-14 18:46:51 -0600231 ddvprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT
232 "Disabling QAS due to noQas=%02x on id=%d!\n", hd->ioc->name, noQas, id));
Eric Moore5a9c47b2007-01-29 09:43:17 -0700233 }
234}
235
236/**
237 * mptspi_writeIOCPage4 - write IOC Page 4
238 * @hd: Pointer to a SCSI Host Structure
Randy Dunlap1544d672007-02-20 11:17:03 -0800239 * @channel: channel number
Eric Moore5a9c47b2007-01-29 09:43:17 -0700240 * @id: write IOC Page4 for this ID & Bus
241 *
242 * Return: -EAGAIN if unable to obtain a Message Frame
243 * or 0 if success.
244 *
245 * Remark: We do not wait for a return, write pages sequentially.
246 **/
247static int
248mptspi_writeIOCPage4(MPT_SCSI_HOST *hd, u8 channel , u8 id)
249{
250 MPT_ADAPTER *ioc = hd->ioc;
251 Config_t *pReq;
252 IOCPage4_t *IOCPage4Ptr;
253 MPT_FRAME_HDR *mf;
254 dma_addr_t dataDma;
255 u16 req_idx;
256 u32 frameOffset;
257 u32 flagsLength;
258 int ii;
259
260 /* Get a MF for this command.
261 */
262 if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) {
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +0530263 dfailprintk(ioc, printk(MYIOC_s_WARN_FMT
264 "writeIOCPage4 : no msg frames!\n",ioc->name));
Eric Moore5a9c47b2007-01-29 09:43:17 -0700265 return -EAGAIN;
266 }
267
268 /* Set the request and the data pointers.
269 * Place data at end of MF.
270 */
271 pReq = (Config_t *)mf;
272
273 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
274 frameOffset = ioc->req_sz - sizeof(IOCPage4_t);
275
276 /* Complete the request frame (same for all requests).
277 */
278 pReq->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
279 pReq->Reserved = 0;
280 pReq->ChainOffset = 0;
281 pReq->Function = MPI_FUNCTION_CONFIG;
282 pReq->ExtPageLength = 0;
283 pReq->ExtPageType = 0;
284 pReq->MsgFlags = 0;
285 for (ii=0; ii < 8; ii++) {
286 pReq->Reserved2[ii] = 0;
287 }
288
289 IOCPage4Ptr = ioc->spi_data.pIocPg4;
290 dataDma = ioc->spi_data.IocPg4_dma;
291 ii = IOCPage4Ptr->ActiveSEP++;
292 IOCPage4Ptr->SEP[ii].SEPTargetID = id;
293 IOCPage4Ptr->SEP[ii].SEPBus = channel;
294 pReq->Header = IOCPage4Ptr->Header;
295 pReq->PageAddress = cpu_to_le32(id | (channel << 8 ));
296
297 /* Add a SGE to the config request.
298 */
299 flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE |
300 (IOCPage4Ptr->Header.PageLength + ii) * 4;
301
302 mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma);
303
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +0530304 ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT
Eric Moore5a9c47b2007-01-29 09:43:17 -0700305 "writeIOCPage4: MaxSEP=%d ActiveSEP=%d id=%d bus=%d\n",
Eric Moore29dd3602007-09-14 18:46:51 -0600306 ioc->name, IOCPage4Ptr->MaxSEP, IOCPage4Ptr->ActiveSEP, id, channel));
Eric Moore5a9c47b2007-01-29 09:43:17 -0700307
308 mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
309
310 return 0;
311}
312
313/**
314 * mptspi_initTarget - Target, LUN alloc/free functionality.
315 * @hd: Pointer to MPT_SCSI_HOST structure
316 * @vtarget: per target private data
317 * @sdev: SCSI device
318 *
319 * NOTE: It's only SAFE to call this routine if data points to
320 * sane & valid STANDARD INQUIRY data!
321 *
322 * Allocate and initialize memory for this target.
323 * Save inquiry data.
324 *
325 **/
326static void
327mptspi_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget,
328 struct scsi_device *sdev)
329{
330
331 /* Is LUN supported? If so, upper 2 bits will be 0
332 * in first byte of inquiry data.
333 */
334 if (sdev->inq_periph_qual != 0)
335 return;
336
337 if (vtarget == NULL)
338 return;
339
340 vtarget->type = sdev->type;
341
342 if ((sdev->type == TYPE_PROCESSOR) && (hd->ioc->spi_data.Saf_Te)) {
343 /* Treat all Processors as SAF-TE if
344 * command line option is set */
345 vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
346 mptspi_writeIOCPage4(hd, vtarget->channel, vtarget->id);
347 }else if ((sdev->type == TYPE_PROCESSOR) &&
348 !(vtarget->tflags & MPT_TARGET_FLAGS_SAF_TE_ISSUED )) {
349 if (sdev->inquiry_len > 49 ) {
350 if (sdev->inquiry[44] == 'S' &&
351 sdev->inquiry[45] == 'A' &&
352 sdev->inquiry[46] == 'F' &&
353 sdev->inquiry[47] == '-' &&
354 sdev->inquiry[48] == 'T' &&
355 sdev->inquiry[49] == 'E' ) {
356 vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
357 mptspi_writeIOCPage4(hd, vtarget->channel, vtarget->id);
358 }
359 }
360 }
361 mptspi_setTargetNegoParms(hd, vtarget, sdev);
362}
Eric Moore793955f2007-01-29 09:42:20 -0700363
364/**
365 * mptspi_is_raid - Determines whether target is belonging to volume
366 * @hd: Pointer to a SCSI HOST structure
367 * @id: target device id
368 *
369 * Return:
370 * non-zero = true
371 * zero = false
372 *
373 */
374static int
375mptspi_is_raid(struct _MPT_SCSI_HOST *hd, u32 id)
376{
377 int i, rc = 0;
378
379 if (!hd->ioc->raid_data.pIocPg2)
380 goto out;
381
382 if (!hd->ioc->raid_data.pIocPg2->NumActiveVolumes)
383 goto out;
384 for (i=0; i < hd->ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
385 if (hd->ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID == id) {
386 rc = 1;
387 goto out;
388 }
389 }
390
391 out:
392 return rc;
393}
394
James Bottomleyc92f2222006-03-01 09:02:49 -0600395static int mptspi_target_alloc(struct scsi_target *starget)
396{
397 struct Scsi_Host *shost = dev_to_shost(&starget->dev);
398 struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata;
Eric Moore793955f2007-01-29 09:42:20 -0700399 VirtTarget *vtarget;
James Bottomleyc92f2222006-03-01 09:02:49 -0600400
401 if (hd == NULL)
402 return -ENODEV;
403
Eric Moore793955f2007-01-29 09:42:20 -0700404 vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
405 if (!vtarget)
406 return -ENOMEM;
James Bottomleyc92f2222006-03-01 09:02:49 -0600407
Eric Moore793955f2007-01-29 09:42:20 -0700408 vtarget->ioc_id = hd->ioc->id;
409 vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
410 vtarget->id = (u8)starget->id;
411 vtarget->channel = (u8)starget->channel;
412 vtarget->starget = starget;
413 starget->hostdata = vtarget;
414
415 if (starget->channel == 1) {
416 if (mptscsih_is_phys_disk(hd->ioc, 0, starget->id) == 0)
417 return 0;
418 vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT;
419 /* The real channel for this device is zero */
420 vtarget->channel = 0;
421 /* The actual physdisknum (for RAID passthrough) */
422 vtarget->id = mptscsih_raid_id_to_num(hd->ioc, 0,
423 starget->id);
424 }
425
426 if (starget->channel == 0 &&
427 mptspi_is_raid(hd, starget->id)) {
428 vtarget->raidVolume = 1;
Eric Moore29dd3602007-09-14 18:46:51 -0600429 ddvprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT
430 "RAID Volume @ channel=%d id=%d\n", hd->ioc->name, starget->channel,
Eric Moore793955f2007-01-29 09:42:20 -0700431 starget->id));
432 }
James Bottomleyc92f2222006-03-01 09:02:49 -0600433
434 if (hd->ioc->spi_data.nvram &&
435 hd->ioc->spi_data.nvram[starget->id] != MPT_HOST_NVRAM_INVALID) {
436 u32 nvram = hd->ioc->spi_data.nvram[starget->id];
437 spi_min_period(starget) = (nvram & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT;
438 spi_max_width(starget) = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
439 } else {
440 spi_min_period(starget) = hd->ioc->spi_data.minSyncFactor;
441 spi_max_width(starget) = hd->ioc->spi_data.maxBusWidth;
442 }
443 spi_max_offset(starget) = hd->ioc->spi_data.maxSyncOffset;
444
445 spi_offset(starget) = 0;
446 mptspi_write_width(starget, 0);
447
448 return 0;
449}
450
Adrian Bunk301b01a2007-03-26 21:59:46 -0800451static void
Eric Moore793955f2007-01-29 09:42:20 -0700452mptspi_target_destroy(struct scsi_target *starget)
453{
454 if (starget->hostdata)
455 kfree(starget->hostdata);
456 starget->hostdata = NULL;
457}
458
Eric Moore873c82e2007-01-29 09:44:06 -0700459/**
460 * mptspi_print_write_nego - negotiation parameters debug info that is being sent
461 * @hd: Pointer to a SCSI HOST structure
462 * @starget: SCSI target
463 * @ii: negotiation parameters
464 *
465 */
466static void
467mptspi_print_write_nego(struct _MPT_SCSI_HOST *hd, struct scsi_target *starget, u32 ii)
468{
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +0530469 ddvprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "id=%d Requested = 0x%08x"
Eric Moore873c82e2007-01-29 09:44:06 -0700470 " ( %s factor = 0x%02x @ offset = 0x%02x %s%s%s%s%s%s%s%s)\n",
471 hd->ioc->name, starget->id, ii,
472 ii & MPI_SCSIDEVPAGE0_NP_WIDE ? "Wide ": "",
473 ((ii >> 8) & 0xFF), ((ii >> 16) & 0xFF),
474 ii & MPI_SCSIDEVPAGE0_NP_IU ? "IU ": "",
475 ii & MPI_SCSIDEVPAGE0_NP_DT ? "DT ": "",
476 ii & MPI_SCSIDEVPAGE0_NP_QAS ? "QAS ": "",
477 ii & MPI_SCSIDEVPAGE0_NP_HOLD_MCS ? "HOLDMCS ": "",
478 ii & MPI_SCSIDEVPAGE0_NP_WR_FLOW ? "WRFLOW ": "",
479 ii & MPI_SCSIDEVPAGE0_NP_RD_STRM ? "RDSTRM ": "",
480 ii & MPI_SCSIDEVPAGE0_NP_RTI ? "RTI ": "",
481 ii & MPI_SCSIDEVPAGE0_NP_PCOMP_EN ? "PCOMP ": ""));
482}
483
484/**
485 * mptspi_print_read_nego - negotiation parameters debug info that is being read
486 * @hd: Pointer to a SCSI HOST structure
487 * @starget: SCSI target
488 * @ii: negotiation parameters
489 *
490 */
491static void
492mptspi_print_read_nego(struct _MPT_SCSI_HOST *hd, struct scsi_target *starget, u32 ii)
493{
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +0530494 ddvprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "id=%d Read = 0x%08x"
Eric Moore873c82e2007-01-29 09:44:06 -0700495 " ( %s factor = 0x%02x @ offset = 0x%02x %s%s%s%s%s%s%s%s)\n",
496 hd->ioc->name, starget->id, ii,
497 ii & MPI_SCSIDEVPAGE0_NP_WIDE ? "Wide ": "",
498 ((ii >> 8) & 0xFF), ((ii >> 16) & 0xFF),
499 ii & MPI_SCSIDEVPAGE0_NP_IU ? "IU ": "",
500 ii & MPI_SCSIDEVPAGE0_NP_DT ? "DT ": "",
501 ii & MPI_SCSIDEVPAGE0_NP_QAS ? "QAS ": "",
502 ii & MPI_SCSIDEVPAGE0_NP_HOLD_MCS ? "HOLDMCS ": "",
503 ii & MPI_SCSIDEVPAGE0_NP_WR_FLOW ? "WRFLOW ": "",
504 ii & MPI_SCSIDEVPAGE0_NP_RD_STRM ? "RDSTRM ": "",
505 ii & MPI_SCSIDEVPAGE0_NP_RTI ? "RTI ": "",
506 ii & MPI_SCSIDEVPAGE0_NP_PCOMP_EN ? "PCOMP ": ""));
507}
508
James Bottomleyc92f2222006-03-01 09:02:49 -0600509static int mptspi_read_spi_device_pg0(struct scsi_target *starget,
510 struct _CONFIG_PAGE_SCSI_DEVICE_0 *pass_pg0)
511{
512 struct Scsi_Host *shost = dev_to_shost(&starget->dev);
513 struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata;
514 struct _MPT_ADAPTER *ioc = hd->ioc;
515 struct _CONFIG_PAGE_SCSI_DEVICE_0 *pg0;
516 dma_addr_t pg0_dma;
517 int size;
518 struct _x_config_parms cfg;
519 struct _CONFIG_PAGE_HEADER hdr;
520 int err = -EBUSY;
521
522 /* No SPI parameters for RAID devices */
523 if (starget->channel == 0 &&
Eric Moore793955f2007-01-29 09:42:20 -0700524 mptspi_is_raid(hd, starget->id))
James Bottomleyc92f2222006-03-01 09:02:49 -0600525 return -1;
526
527 size = ioc->spi_data.sdp0length * 4;
528 /*
529 if (ioc->spi_data.sdp0length & 1)
530 size += size + 4;
531 size += 2048;
532 */
533
534 pg0 = dma_alloc_coherent(&ioc->pcidev->dev, size, &pg0_dma, GFP_KERNEL);
535 if (pg0 == NULL) {
Eric Moore29dd3602007-09-14 18:46:51 -0600536 starget_printk(MYIOC_s_ERR_FMT, starget,
537 "dma_alloc_coherent for parameters failed\n", ioc->name);
James Bottomleyc92f2222006-03-01 09:02:49 -0600538 return -EINVAL;
539 }
540
541 memset(&hdr, 0, sizeof(hdr));
542
543 hdr.PageVersion = ioc->spi_data.sdp0version;
544 hdr.PageLength = ioc->spi_data.sdp0length;
545 hdr.PageNumber = 0;
546 hdr.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
547
548 memset(&cfg, 0, sizeof(cfg));
549
550 cfg.cfghdr.hdr = &hdr;
551 cfg.physAddr = pg0_dma;
552 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
553 cfg.dir = 0;
554 cfg.pageAddr = starget->id;
555
556 if (mpt_config(ioc, &cfg)) {
Eric Moore29dd3602007-09-14 18:46:51 -0600557 starget_printk(MYIOC_s_ERR_FMT, starget, "mpt_config failed\n", ioc->name);
James Bottomleyc92f2222006-03-01 09:02:49 -0600558 goto out_free;
559 }
560 err = 0;
561 memcpy(pass_pg0, pg0, size);
562
Eric Moore873c82e2007-01-29 09:44:06 -0700563 mptspi_print_read_nego(hd, starget, le32_to_cpu(pg0->NegotiatedParameters));
564
James Bottomleyc92f2222006-03-01 09:02:49 -0600565 out_free:
566 dma_free_coherent(&ioc->pcidev->dev, size, pg0, pg0_dma);
567 return err;
568}
569
570static u32 mptspi_getRP(struct scsi_target *starget)
571{
572 u32 nego = 0;
573
574 nego |= spi_iu(starget) ? MPI_SCSIDEVPAGE1_RP_IU : 0;
575 nego |= spi_dt(starget) ? MPI_SCSIDEVPAGE1_RP_DT : 0;
576 nego |= spi_qas(starget) ? MPI_SCSIDEVPAGE1_RP_QAS : 0;
577 nego |= spi_hold_mcs(starget) ? MPI_SCSIDEVPAGE1_RP_HOLD_MCS : 0;
578 nego |= spi_wr_flow(starget) ? MPI_SCSIDEVPAGE1_RP_WR_FLOW : 0;
579 nego |= spi_rd_strm(starget) ? MPI_SCSIDEVPAGE1_RP_RD_STRM : 0;
580 nego |= spi_rti(starget) ? MPI_SCSIDEVPAGE1_RP_RTI : 0;
581 nego |= spi_pcomp_en(starget) ? MPI_SCSIDEVPAGE1_RP_PCOMP_EN : 0;
582
583 nego |= (spi_period(starget) << MPI_SCSIDEVPAGE1_RP_SHIFT_MIN_SYNC_PERIOD) & MPI_SCSIDEVPAGE1_RP_MIN_SYNC_PERIOD_MASK;
584 nego |= (spi_offset(starget) << MPI_SCSIDEVPAGE1_RP_SHIFT_MAX_SYNC_OFFSET) & MPI_SCSIDEVPAGE1_RP_MAX_SYNC_OFFSET_MASK;
585 nego |= spi_width(starget) ? MPI_SCSIDEVPAGE1_RP_WIDE : 0;
586
587 return nego;
588}
589
590static void mptspi_read_parameters(struct scsi_target *starget)
591{
592 int nego;
593 struct _CONFIG_PAGE_SCSI_DEVICE_0 pg0;
594
595 mptspi_read_spi_device_pg0(starget, &pg0);
596
597 nego = le32_to_cpu(pg0.NegotiatedParameters);
598
599 spi_iu(starget) = (nego & MPI_SCSIDEVPAGE0_NP_IU) ? 1 : 0;
600 spi_dt(starget) = (nego & MPI_SCSIDEVPAGE0_NP_DT) ? 1 : 0;
601 spi_qas(starget) = (nego & MPI_SCSIDEVPAGE0_NP_QAS) ? 1 : 0;
602 spi_wr_flow(starget) = (nego & MPI_SCSIDEVPAGE0_NP_WR_FLOW) ? 1 : 0;
603 spi_rd_strm(starget) = (nego & MPI_SCSIDEVPAGE0_NP_RD_STRM) ? 1 : 0;
604 spi_rti(starget) = (nego & MPI_SCSIDEVPAGE0_NP_RTI) ? 1 : 0;
605 spi_pcomp_en(starget) = (nego & MPI_SCSIDEVPAGE0_NP_PCOMP_EN) ? 1 : 0;
606 spi_hold_mcs(starget) = (nego & MPI_SCSIDEVPAGE0_NP_HOLD_MCS) ? 1 : 0;
607 spi_period(starget) = (nego & MPI_SCSIDEVPAGE0_NP_NEG_SYNC_PERIOD_MASK) >> MPI_SCSIDEVPAGE0_NP_SHIFT_SYNC_PERIOD;
608 spi_offset(starget) = (nego & MPI_SCSIDEVPAGE0_NP_NEG_SYNC_OFFSET_MASK) >> MPI_SCSIDEVPAGE0_NP_SHIFT_SYNC_OFFSET;
609 spi_width(starget) = (nego & MPI_SCSIDEVPAGE0_NP_WIDE) ? 1 : 0;
610}
611
612static int
Eric Moore793955f2007-01-29 09:42:20 -0700613mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, u8 channel, u8 id)
James Bottomleyc92f2222006-03-01 09:02:49 -0600614{
615 MpiRaidActionRequest_t *pReq;
616 MPT_FRAME_HDR *mf;
617
618 /* Get and Populate a free Frame
619 */
620 if ((mf = mpt_get_msg_frame(hd->ioc->InternalCtx, hd->ioc)) == NULL) {
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +0530621 ddvprintk(hd->ioc, printk(MYIOC_s_WARN_FMT "_do_raid: no msg frames!\n",
James Bottomleyc92f2222006-03-01 09:02:49 -0600622 hd->ioc->name));
623 return -EAGAIN;
624 }
625 pReq = (MpiRaidActionRequest_t *)mf;
626 if (quiesce)
627 pReq->Action = MPI_RAID_ACTION_QUIESCE_PHYS_IO;
628 else
629 pReq->Action = MPI_RAID_ACTION_ENABLE_PHYS_IO;
630 pReq->Reserved1 = 0;
631 pReq->ChainOffset = 0;
632 pReq->Function = MPI_FUNCTION_RAID_ACTION;
Eric Moore793955f2007-01-29 09:42:20 -0700633 pReq->VolumeID = id;
634 pReq->VolumeBus = channel;
James Bottomleyc92f2222006-03-01 09:02:49 -0600635 pReq->PhysDiskNum = 0;
636 pReq->MsgFlags = 0;
637 pReq->Reserved2 = 0;
638 pReq->ActionDataWord = 0; /* Reserved for this action */
639
640 mpt_add_sge((char *)&pReq->ActionDataSGE,
641 MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1);
642
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +0530643 ddvprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "RAID Volume action=%x channel=%d id=%d\n",
Eric Moore793955f2007-01-29 09:42:20 -0700644 hd->ioc->name, pReq->Action, channel, id));
James Bottomleyc92f2222006-03-01 09:02:49 -0600645
646 hd->pLocal = NULL;
647 hd->timer.expires = jiffies + HZ*10; /* 10 second timeout */
648 hd->scandv_wait_done = 0;
649
650 /* Save cmd pointer, for resource free if timeout or
651 * FW reload occurs
652 */
653 hd->cmdPtr = mf;
654
655 add_timer(&hd->timer);
656 mpt_put_msg_frame(hd->ioc->InternalCtx, hd->ioc, mf);
657 wait_event(hd->scandv_waitq, hd->scandv_wait_done);
658
659 if ((hd->pLocal == NULL) || (hd->pLocal->completion != 0))
660 return -1;
661
662 return 0;
663}
664
665static void mptspi_dv_device(struct _MPT_SCSI_HOST *hd,
666 struct scsi_device *sdev)
667{
668 VirtTarget *vtarget = scsi_target(sdev)->hostdata;
669
670 /* no DV on RAID devices */
671 if (sdev->channel == 0 &&
Eric Moore793955f2007-01-29 09:42:20 -0700672 mptspi_is_raid(hd, sdev->id))
James Bottomleyc92f2222006-03-01 09:02:49 -0600673 return;
674
675 /* If this is a piece of a RAID, then quiesce first */
676 if (sdev->channel == 1 &&
Eric Moore793955f2007-01-29 09:42:20 -0700677 mptscsih_quiesce_raid(hd, 1, vtarget->channel, vtarget->id) < 0) {
Eric Moore29dd3602007-09-14 18:46:51 -0600678 starget_printk(MYIOC_s_ERR_FMT, scsi_target(sdev),
679 "Integrated RAID quiesce failed\n", hd->ioc->name);
James Bottomleyc92f2222006-03-01 09:02:49 -0600680 return;
681 }
682
Eric Moore729782452007-02-07 16:51:40 -0700683 hd->spi_pending |= (1 << sdev->id);
James Bottomleyc92f2222006-03-01 09:02:49 -0600684 spi_dv_device(sdev);
Eric Moore729782452007-02-07 16:51:40 -0700685 hd->spi_pending &= ~(1 << sdev->id);
James Bottomleyc92f2222006-03-01 09:02:49 -0600686
687 if (sdev->channel == 1 &&
Eric Moore793955f2007-01-29 09:42:20 -0700688 mptscsih_quiesce_raid(hd, 0, vtarget->channel, vtarget->id) < 0)
Eric Moore29dd3602007-09-14 18:46:51 -0600689 starget_printk(MYIOC_s_ERR_FMT, scsi_target(sdev),
690 "Integrated RAID resume failed\n", hd->ioc->name);
James Bottomleyc92f2222006-03-01 09:02:49 -0600691
692 mptspi_read_parameters(sdev->sdev_target);
693 spi_display_xfer_agreement(sdev->sdev_target);
694 mptspi_read_parameters(sdev->sdev_target);
695}
696
697static int mptspi_slave_alloc(struct scsi_device *sdev)
698{
James Bottomleyc92f2222006-03-01 09:02:49 -0600699 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sdev->host->hostdata;
Eric Moore793955f2007-01-29 09:42:20 -0700700 VirtTarget *vtarget;
Eric Moorea69de502007-09-14 18:48:19 -0600701 VirtDevice *vdevice;
Eric Moore793955f2007-01-29 09:42:20 -0700702 struct scsi_target *starget;
James Bottomleyc92f2222006-03-01 09:02:49 -0600703
Eric Moore793955f2007-01-29 09:42:20 -0700704 if (sdev->channel == 1 &&
705 mptscsih_is_phys_disk(hd->ioc, 0, sdev->id) == 0)
706 return -ENXIO;
James Bottomleyc92f2222006-03-01 09:02:49 -0600707
Eric Moorea69de502007-09-14 18:48:19 -0600708 vdevice = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
709 if (!vdevice) {
Eric Moore793955f2007-01-29 09:42:20 -0700710 printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
711 hd->ioc->name, sizeof(VirtDevice));
712 return -ENOMEM;
James Bottomleyc92f2222006-03-01 09:02:49 -0600713 }
714
Eric Moorea69de502007-09-14 18:48:19 -0600715 vdevice->lun = sdev->lun;
716 sdev->hostdata = vdevice;
James Bottomleyc92f2222006-03-01 09:02:49 -0600717
Eric Moore793955f2007-01-29 09:42:20 -0700718 starget = scsi_target(sdev);
719 vtarget = starget->hostdata;
Eric Moorea69de502007-09-14 18:48:19 -0600720 vdevice->vtarget = vtarget;
Eric Moore793955f2007-01-29 09:42:20 -0700721 vtarget->num_luns++;
James Bottomleyc92f2222006-03-01 09:02:49 -0600722
Eric Moore793955f2007-01-29 09:42:20 -0700723 if (sdev->channel == 1)
James Bottomleyc92f2222006-03-01 09:02:49 -0600724 sdev->no_uld_attach = 1;
James Bottomleyc92f2222006-03-01 09:02:49 -0600725
726 return 0;
727}
728
729static int mptspi_slave_configure(struct scsi_device *sdev)
730{
James Bottomleyc92f2222006-03-01 09:02:49 -0600731 struct _MPT_SCSI_HOST *hd =
732 (struct _MPT_SCSI_HOST *)sdev->host->hostdata;
Eric Moore5a9c47b2007-01-29 09:43:17 -0700733 VirtTarget *vtarget = scsi_target(sdev)->hostdata;
Doug Chapman29982e92007-05-07 15:59:46 -0400734 int ret;
735
736 mptspi_initTarget(hd, vtarget, sdev);
737
738 ret = mptscsih_slave_configure(sdev);
James Bottomleyc92f2222006-03-01 09:02:49 -0600739
740 if (ret)
741 return ret;
742
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +0530743 ddvprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "id=%d min_period=0x%02x"
Eric Moore873c82e2007-01-29 09:44:06 -0700744 " max_offset=0x%02x max_width=%d\n", hd->ioc->name,
745 sdev->id, spi_min_period(scsi_target(sdev)),
746 spi_max_offset(scsi_target(sdev)),
747 spi_max_width(scsi_target(sdev))));
748
James Bottomleyc92f2222006-03-01 09:02:49 -0600749 if ((sdev->channel == 1 ||
Eric Moore793955f2007-01-29 09:42:20 -0700750 !(mptspi_is_raid(hd, sdev->id))) &&
James Bottomleyc92f2222006-03-01 09:02:49 -0600751 !spi_initial_dv(sdev->sdev_target))
752 mptspi_dv_device(hd, sdev);
753
754 return 0;
755}
756
Eric Moore793955f2007-01-29 09:42:20 -0700757static int
758mptspi_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
759{
760 struct _MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata;
Eric Moorea69de502007-09-14 18:48:19 -0600761 VirtDevice *vdevice = SCpnt->device->hostdata;
Eric Moore793955f2007-01-29 09:42:20 -0700762
Eric Moorea69de502007-09-14 18:48:19 -0600763 if (!vdevice || !vdevice->vtarget) {
Eric Moore793955f2007-01-29 09:42:20 -0700764 SCpnt->result = DID_NO_CONNECT << 16;
765 done(SCpnt);
766 return 0;
767 }
768
769 if (SCpnt->device->channel == 1 &&
770 mptscsih_is_phys_disk(hd->ioc, 0, SCpnt->device->id) == 0) {
771 SCpnt->result = DID_NO_CONNECT << 16;
772 done(SCpnt);
773 return 0;
774 }
775
Eric Moore873c82e2007-01-29 09:44:06 -0700776 if (spi_dv_pending(scsi_target(SCpnt->device)))
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +0530777 ddvprintk(hd->ioc, scsi_print_command(SCpnt));
Eric Moore873c82e2007-01-29 09:44:06 -0700778
Eric Moore793955f2007-01-29 09:42:20 -0700779 return mptscsih_qcmd(SCpnt,done);
780}
781
James Bottomleyc92f2222006-03-01 09:02:49 -0600782static void mptspi_slave_destroy(struct scsi_device *sdev)
783{
784 struct scsi_target *starget = scsi_target(sdev);
785 VirtTarget *vtarget = starget->hostdata;
786 VirtDevice *vdevice = sdev->hostdata;
787
788 /* Will this be the last lun on a non-raid device? */
789 if (vtarget->num_luns == 1 && vdevice->configured_lun) {
790 struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
791
792 /* Async Narrow */
793 pg1.RequestedParameters = 0;
794 pg1.Reserved = 0;
795 pg1.Configuration = 0;
796
797 mptspi_write_spi_device_pg1(starget, &pg1);
798 }
799
800 mptscsih_slave_destroy(sdev);
801}
802
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -0400803static struct scsi_host_template mptspi_driver_template = {
Moore, Eric Deanf78496d2005-11-16 18:54:14 -0700804 .module = THIS_MODULE,
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -0400805 .proc_name = "mptspi",
806 .proc_info = mptscsih_proc_info,
807 .name = "MPT SPI Host",
808 .info = mptscsih_info,
Eric Moore793955f2007-01-29 09:42:20 -0700809 .queuecommand = mptspi_qcmd,
James Bottomleyc92f2222006-03-01 09:02:49 -0600810 .target_alloc = mptspi_target_alloc,
811 .slave_alloc = mptspi_slave_alloc,
812 .slave_configure = mptspi_slave_configure,
Eric Moore793955f2007-01-29 09:42:20 -0700813 .target_destroy = mptspi_target_destroy,
James Bottomleyc92f2222006-03-01 09:02:49 -0600814 .slave_destroy = mptspi_slave_destroy,
Moore, Eric Dean6e3815b2005-06-24 12:18:57 -0600815 .change_queue_depth = mptscsih_change_queue_depth,
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -0400816 .eh_abort_handler = mptscsih_abort,
817 .eh_device_reset_handler = mptscsih_dev_reset,
818 .eh_bus_reset_handler = mptscsih_bus_reset,
819 .eh_host_reset_handler = mptscsih_host_reset,
820 .bios_param = mptscsih_bios_param,
821 .can_queue = MPT_SCSI_CAN_QUEUE,
822 .this_id = -1,
823 .sg_tablesize = MPT_SCSI_SG_DEPTH,
824 .max_sectors = 8192,
825 .cmd_per_lun = 7,
826 .use_clustering = ENABLE_CLUSTERING,
Prakash, Sathyaedb90682007-07-17 14:39:14 +0530827 .shost_attrs = mptscsih_host_attrs,
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -0400828};
829
James Bottomleyc92f2222006-03-01 09:02:49 -0600830static int mptspi_write_spi_device_pg1(struct scsi_target *starget,
831 struct _CONFIG_PAGE_SCSI_DEVICE_1 *pass_pg1)
832{
833 struct Scsi_Host *shost = dev_to_shost(&starget->dev);
834 struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata;
835 struct _MPT_ADAPTER *ioc = hd->ioc;
836 struct _CONFIG_PAGE_SCSI_DEVICE_1 *pg1;
837 dma_addr_t pg1_dma;
838 int size;
839 struct _x_config_parms cfg;
840 struct _CONFIG_PAGE_HEADER hdr;
841 int err = -EBUSY;
842
843 /* don't allow updating nego parameters on RAID devices */
844 if (starget->channel == 0 &&
Eric Moore793955f2007-01-29 09:42:20 -0700845 mptspi_is_raid(hd, starget->id))
James Bottomleyc92f2222006-03-01 09:02:49 -0600846 return -1;
847
848 size = ioc->spi_data.sdp1length * 4;
849
850 pg1 = dma_alloc_coherent(&ioc->pcidev->dev, size, &pg1_dma, GFP_KERNEL);
851 if (pg1 == NULL) {
Eric Moore29dd3602007-09-14 18:46:51 -0600852 starget_printk(MYIOC_s_ERR_FMT, starget,
853 "dma_alloc_coherent for parameters failed\n", ioc->name);
James Bottomleyc92f2222006-03-01 09:02:49 -0600854 return -EINVAL;
855 }
856
857 memset(&hdr, 0, sizeof(hdr));
858
859 hdr.PageVersion = ioc->spi_data.sdp1version;
860 hdr.PageLength = ioc->spi_data.sdp1length;
861 hdr.PageNumber = 1;
862 hdr.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
863
864 memset(&cfg, 0, sizeof(cfg));
865
866 cfg.cfghdr.hdr = &hdr;
867 cfg.physAddr = pg1_dma;
868 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
869 cfg.dir = 1;
870 cfg.pageAddr = starget->id;
871
872 memcpy(pg1, pass_pg1, size);
873
874 pg1->Header.PageVersion = hdr.PageVersion;
875 pg1->Header.PageLength = hdr.PageLength;
876 pg1->Header.PageNumber = hdr.PageNumber;
877 pg1->Header.PageType = hdr.PageType;
878
Eric Moore873c82e2007-01-29 09:44:06 -0700879 mptspi_print_write_nego(hd, starget, le32_to_cpu(pg1->RequestedParameters));
880
James Bottomleyc92f2222006-03-01 09:02:49 -0600881 if (mpt_config(ioc, &cfg)) {
Eric Moore29dd3602007-09-14 18:46:51 -0600882 starget_printk(MYIOC_s_ERR_FMT, starget,
883 "mpt_config failed\n", ioc->name);
James Bottomleyc92f2222006-03-01 09:02:49 -0600884 goto out_free;
885 }
886 err = 0;
887
888 out_free:
889 dma_free_coherent(&ioc->pcidev->dev, size, pg1, pg1_dma);
890 return err;
891}
892
893static void mptspi_write_offset(struct scsi_target *starget, int offset)
894{
895 struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
896 u32 nego;
897
898 if (offset < 0)
899 offset = 0;
900
901 if (offset > 255)
902 offset = 255;
903
904 if (spi_offset(starget) == -1)
905 mptspi_read_parameters(starget);
906
907 spi_offset(starget) = offset;
908
909 nego = mptspi_getRP(starget);
910
911 pg1.RequestedParameters = cpu_to_le32(nego);
912 pg1.Reserved = 0;
913 pg1.Configuration = 0;
914
915 mptspi_write_spi_device_pg1(starget, &pg1);
916}
917
918static void mptspi_write_period(struct scsi_target *starget, int period)
919{
920 struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
921 u32 nego;
922
923 if (period < 8)
924 period = 8;
925
926 if (period > 255)
927 period = 255;
928
929 if (spi_period(starget) == -1)
930 mptspi_read_parameters(starget);
931
932 if (period == 8) {
933 spi_iu(starget) = 1;
934 spi_dt(starget) = 1;
935 } else if (period == 9) {
936 spi_dt(starget) = 1;
937 }
938
939 spi_period(starget) = period;
940
941 nego = mptspi_getRP(starget);
942
943 pg1.RequestedParameters = cpu_to_le32(nego);
944 pg1.Reserved = 0;
945 pg1.Configuration = 0;
946
947 mptspi_write_spi_device_pg1(starget, &pg1);
948}
949
950static void mptspi_write_dt(struct scsi_target *starget, int dt)
951{
952 struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
953 u32 nego;
954
955 if (spi_period(starget) == -1)
956 mptspi_read_parameters(starget);
957
958 if (!dt && spi_period(starget) < 10)
959 spi_period(starget) = 10;
960
961 spi_dt(starget) = dt;
962
963 nego = mptspi_getRP(starget);
964
965
966 pg1.RequestedParameters = cpu_to_le32(nego);
967 pg1.Reserved = 0;
968 pg1.Configuration = 0;
969
970 mptspi_write_spi_device_pg1(starget, &pg1);
971}
972
973static void mptspi_write_iu(struct scsi_target *starget, int iu)
974{
975 struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
976 u32 nego;
977
978 if (spi_period(starget) == -1)
979 mptspi_read_parameters(starget);
980
981 if (!iu && spi_period(starget) < 9)
982 spi_period(starget) = 9;
983
984 spi_iu(starget) = iu;
985
986 nego = mptspi_getRP(starget);
987
988 pg1.RequestedParameters = cpu_to_le32(nego);
989 pg1.Reserved = 0;
990 pg1.Configuration = 0;
991
992 mptspi_write_spi_device_pg1(starget, &pg1);
993}
994
995#define MPTSPI_SIMPLE_TRANSPORT_PARM(parm) \
996static void mptspi_write_##parm(struct scsi_target *starget, int parm)\
997{ \
998 struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1; \
999 u32 nego; \
1000 \
1001 spi_##parm(starget) = parm; \
1002 \
1003 nego = mptspi_getRP(starget); \
1004 \
1005 pg1.RequestedParameters = cpu_to_le32(nego); \
1006 pg1.Reserved = 0; \
1007 pg1.Configuration = 0; \
1008 \
1009 mptspi_write_spi_device_pg1(starget, &pg1); \
1010}
1011
1012MPTSPI_SIMPLE_TRANSPORT_PARM(rd_strm)
1013MPTSPI_SIMPLE_TRANSPORT_PARM(wr_flow)
1014MPTSPI_SIMPLE_TRANSPORT_PARM(rti)
1015MPTSPI_SIMPLE_TRANSPORT_PARM(hold_mcs)
1016MPTSPI_SIMPLE_TRANSPORT_PARM(pcomp_en)
1017
1018static void mptspi_write_qas(struct scsi_target *starget, int qas)
1019{
1020 struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
1021 struct Scsi_Host *shost = dev_to_shost(&starget->dev);
1022 struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata;
1023 VirtTarget *vtarget = starget->hostdata;
1024 u32 nego;
1025
1026 if ((vtarget->negoFlags & MPT_TARGET_NO_NEGO_QAS) ||
1027 hd->ioc->spi_data.noQas)
1028 spi_qas(starget) = 0;
1029 else
1030 spi_qas(starget) = qas;
1031
1032 nego = mptspi_getRP(starget);
1033
1034 pg1.RequestedParameters = cpu_to_le32(nego);
1035 pg1.Reserved = 0;
1036 pg1.Configuration = 0;
1037
1038 mptspi_write_spi_device_pg1(starget, &pg1);
1039}
1040
1041static void mptspi_write_width(struct scsi_target *starget, int width)
1042{
1043 struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
1044 u32 nego;
1045
1046 if (!width) {
1047 spi_dt(starget) = 0;
1048 if (spi_period(starget) < 10)
1049 spi_period(starget) = 10;
1050 }
1051
1052 spi_width(starget) = width;
1053
1054 nego = mptspi_getRP(starget);
1055
1056 pg1.RequestedParameters = cpu_to_le32(nego);
1057 pg1.Reserved = 0;
1058 pg1.Configuration = 0;
1059
1060 mptspi_write_spi_device_pg1(starget, &pg1);
1061}
1062
1063struct work_queue_wrapper {
1064 struct work_struct work;
1065 struct _MPT_SCSI_HOST *hd;
1066 int disk;
1067};
1068
David Howellsc4028952006-11-22 14:57:56 +00001069static void mpt_work_wrapper(struct work_struct *work)
James Bottomleyc92f2222006-03-01 09:02:49 -06001070{
David Howellsc4028952006-11-22 14:57:56 +00001071 struct work_queue_wrapper *wqw =
1072 container_of(work, struct work_queue_wrapper, work);
James Bottomleyc92f2222006-03-01 09:02:49 -06001073 struct _MPT_SCSI_HOST *hd = wqw->hd;
1074 struct Scsi_Host *shost = hd->ioc->sh;
1075 struct scsi_device *sdev;
1076 int disk = wqw->disk;
1077 struct _CONFIG_PAGE_IOC_3 *pg3;
1078
1079 kfree(wqw);
1080
1081 mpt_findImVolumes(hd->ioc);
1082 pg3 = hd->ioc->raid_data.pIocPg3;
1083 if (!pg3)
1084 return;
1085
1086 shost_for_each_device(sdev,shost) {
1087 struct scsi_target *starget = scsi_target(sdev);
1088 VirtTarget *vtarget = starget->hostdata;
1089
1090 /* only want to search RAID components */
1091 if (sdev->channel != 1)
1092 continue;
1093
Eric Moore793955f2007-01-29 09:42:20 -07001094 /* The id is the raid PhysDiskNum, even if
James Bottomleyc92f2222006-03-01 09:02:49 -06001095 * starget->id is the actual target address */
Eric Moore793955f2007-01-29 09:42:20 -07001096 if(vtarget->id != disk)
James Bottomleyc92f2222006-03-01 09:02:49 -06001097 continue;
1098
Eric Moore29dd3602007-09-14 18:46:51 -06001099 starget_printk(MYIOC_s_INFO_FMT, vtarget->starget,
1100 "Integrated RAID requests DV of new device\n", hd->ioc->name);
James Bottomleyc92f2222006-03-01 09:02:49 -06001101 mptspi_dv_device(hd, sdev);
1102 }
Eric Moore29dd3602007-09-14 18:46:51 -06001103 shost_printk(MYIOC_s_INFO_FMT, shost,
1104 "Integrated RAID detects new device %d\n", hd->ioc->name, disk);
James Bottomleyc92f2222006-03-01 09:02:49 -06001105 scsi_scan_target(&hd->ioc->sh->shost_gendev, 1, disk, 0, 1);
1106}
1107
1108
1109static void mpt_dv_raid(struct _MPT_SCSI_HOST *hd, int disk)
1110{
1111 struct work_queue_wrapper *wqw = kmalloc(sizeof(*wqw), GFP_ATOMIC);
1112
1113 if (!wqw) {
Eric Moore29dd3602007-09-14 18:46:51 -06001114 shost_printk(MYIOC_s_ERR_FMT, hd->ioc->sh,
1115 "Failed to act on RAID event for physical disk %d\n",
1116 hd->ioc->name, disk);
James Bottomleyc92f2222006-03-01 09:02:49 -06001117 return;
1118 }
David Howellsc4028952006-11-22 14:57:56 +00001119 INIT_WORK(&wqw->work, mpt_work_wrapper);
James Bottomleyc92f2222006-03-01 09:02:49 -06001120 wqw->hd = hd;
1121 wqw->disk = disk;
1122
1123 schedule_work(&wqw->work);
1124}
1125
1126static int
1127mptspi_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
1128{
1129 u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
1130 struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)ioc->sh->hostdata;
1131
1132 if (hd && event == MPI_EVENT_INTEGRATED_RAID) {
1133 int reason
1134 = (le32_to_cpu(pEvReply->Data[0]) & 0x00FF0000) >> 16;
1135
1136 if (reason == MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) {
1137 int disk = (le32_to_cpu(pEvReply->Data[0]) & 0xFF000000) >> 24;
1138 mpt_dv_raid(hd, disk);
1139 }
1140 }
1141 return mptscsih_event_process(ioc, pEvReply);
1142}
1143
1144static int
1145mptspi_deny_binding(struct scsi_target *starget)
1146{
1147 struct _MPT_SCSI_HOST *hd =
1148 (struct _MPT_SCSI_HOST *)dev_to_shost(starget->dev.parent)->hostdata;
Eric Moore793955f2007-01-29 09:42:20 -07001149 return ((mptspi_is_raid(hd, starget->id)) &&
James Bottomleyc92f2222006-03-01 09:02:49 -06001150 starget->channel == 0) ? 1 : 0;
1151}
1152
1153static struct spi_function_template mptspi_transport_functions = {
1154 .get_offset = mptspi_read_parameters,
1155 .set_offset = mptspi_write_offset,
1156 .show_offset = 1,
1157 .get_period = mptspi_read_parameters,
1158 .set_period = mptspi_write_period,
1159 .show_period = 1,
1160 .get_width = mptspi_read_parameters,
1161 .set_width = mptspi_write_width,
1162 .show_width = 1,
1163 .get_iu = mptspi_read_parameters,
1164 .set_iu = mptspi_write_iu,
1165 .show_iu = 1,
1166 .get_dt = mptspi_read_parameters,
1167 .set_dt = mptspi_write_dt,
1168 .show_dt = 1,
1169 .get_qas = mptspi_read_parameters,
1170 .set_qas = mptspi_write_qas,
1171 .show_qas = 1,
1172 .get_wr_flow = mptspi_read_parameters,
1173 .set_wr_flow = mptspi_write_wr_flow,
1174 .show_wr_flow = 1,
1175 .get_rd_strm = mptspi_read_parameters,
1176 .set_rd_strm = mptspi_write_rd_strm,
1177 .show_rd_strm = 1,
1178 .get_rti = mptspi_read_parameters,
1179 .set_rti = mptspi_write_rti,
1180 .show_rti = 1,
1181 .get_pcomp_en = mptspi_read_parameters,
1182 .set_pcomp_en = mptspi_write_pcomp_en,
1183 .show_pcomp_en = 1,
1184 .get_hold_mcs = mptspi_read_parameters,
1185 .set_hold_mcs = mptspi_write_hold_mcs,
1186 .show_hold_mcs = 1,
1187 .deny_binding = mptspi_deny_binding,
1188};
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001189
1190/****************************************************************************
1191 * Supported hardware
1192 */
1193
1194static struct pci_device_id mptspi_pci_table[] = {
Eric Moore87cf8982006-06-27 16:09:26 -06001195 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_53C1030,
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001196 PCI_ANY_ID, PCI_ANY_ID },
Eric Moore232f08f2007-08-14 17:28:27 -06001197 { PCI_VENDOR_ID_ATTO, MPI_MANUFACTPAGE_DEVID_53C1030,
1198 PCI_ANY_ID, PCI_ANY_ID },
Eric Moore87cf8982006-06-27 16:09:26 -06001199 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_53C1035,
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001200 PCI_ANY_ID, PCI_ANY_ID },
1201 {0} /* Terminating entry */
1202};
1203MODULE_DEVICE_TABLE(pci, mptspi_pci_table);
1204
Eric Moore6e1cad02006-04-25 17:38:58 -06001205
1206/*
1207 * renegotiate for a given target
1208 */
1209static void
David Howellsc4028952006-11-22 14:57:56 +00001210mptspi_dv_renegotiate_work(struct work_struct *work)
Eric Moore6e1cad02006-04-25 17:38:58 -06001211{
David Howellsc4028952006-11-22 14:57:56 +00001212 struct work_queue_wrapper *wqw =
1213 container_of(work, struct work_queue_wrapper, work);
Eric Moore6e1cad02006-04-25 17:38:58 -06001214 struct _MPT_SCSI_HOST *hd = wqw->hd;
1215 struct scsi_device *sdev;
Eric Moore729782452007-02-07 16:51:40 -07001216 struct scsi_target *starget;
1217 struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
1218 u32 nego;
Eric Moore6e1cad02006-04-25 17:38:58 -06001219
1220 kfree(wqw);
1221
Eric Moore729782452007-02-07 16:51:40 -07001222 if (hd->spi_pending) {
1223 shost_for_each_device(sdev, hd->ioc->sh) {
1224 if (hd->spi_pending & (1 << sdev->id))
1225 continue;
1226 starget = scsi_target(sdev);
1227 nego = mptspi_getRP(starget);
1228 pg1.RequestedParameters = cpu_to_le32(nego);
1229 pg1.Reserved = 0;
1230 pg1.Configuration = 0;
1231 mptspi_write_spi_device_pg1(starget, &pg1);
1232 }
1233 } else {
1234 shost_for_each_device(sdev, hd->ioc->sh)
1235 mptspi_dv_device(hd, sdev);
1236 }
Eric Moore6e1cad02006-04-25 17:38:58 -06001237}
1238
1239static void
1240mptspi_dv_renegotiate(struct _MPT_SCSI_HOST *hd)
1241{
1242 struct work_queue_wrapper *wqw = kmalloc(sizeof(*wqw), GFP_ATOMIC);
1243
1244 if (!wqw)
1245 return;
1246
David Howellsc4028952006-11-22 14:57:56 +00001247 INIT_WORK(&wqw->work, mptspi_dv_renegotiate_work);
Eric Moore6e1cad02006-04-25 17:38:58 -06001248 wqw->hd = hd;
1249
1250 schedule_work(&wqw->work);
1251}
1252
1253/*
1254 * spi module reset handler
1255 */
1256static int
1257mptspi_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
1258{
1259 struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)ioc->sh->hostdata;
1260 int rc;
1261
1262 rc = mptscsih_ioc_reset(ioc, reset_phase);
1263
1264 if (reset_phase == MPT_IOC_POST_RESET)
1265 mptspi_dv_renegotiate(hd);
1266
1267 return rc;
1268}
1269
Tom "spot" Callawayc29ca9d2006-06-09 17:01:48 -07001270#ifdef CONFIG_PM
Eric Moore6e1cad02006-04-25 17:38:58 -06001271/*
1272 * spi module resume handler
1273 */
1274static int
1275mptspi_resume(struct pci_dev *pdev)
1276{
1277 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1278 struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)ioc->sh->hostdata;
1279 int rc;
1280
1281 rc = mptscsih_resume(pdev);
1282 mptspi_dv_renegotiate(hd);
1283
1284 return rc;
1285}
Tom "spot" Callawayc29ca9d2006-06-09 17:01:48 -07001286#endif
Eric Moore6e1cad02006-04-25 17:38:58 -06001287
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001288/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1289/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1290/*
1291 * mptspi_probe - Installs scsi devices per bus.
1292 * @pdev: Pointer to pci_dev structure
1293 *
1294 * Returns 0 for success, non-zero for failure.
1295 *
1296 */
1297static int
1298mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
1299{
1300 struct Scsi_Host *sh;
1301 MPT_SCSI_HOST *hd;
1302 MPT_ADAPTER *ioc;
1303 unsigned long flags;
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001304 int ii;
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001305 int numSGE = 0;
1306 int scale;
1307 int ioc_cap;
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001308 int error=0;
1309 int r;
Christoph Hellwigc6678e02005-08-18 16:24:53 +02001310
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001311 if ((r = mpt_attach(pdev,id)) != 0)
1312 return r;
Christoph Hellwigc6678e02005-08-18 16:24:53 +02001313
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001314 ioc = pci_get_drvdata(pdev);
Moore, Eric Dean d335cc32005-04-30 17:09:38 -05001315 ioc->DoneCtx = mptspiDoneCtx;
1316 ioc->TaskCtx = mptspiTaskCtx;
1317 ioc->InternalCtx = mptspiInternalCtx;
Christoph Hellwigc6678e02005-08-18 16:24:53 +02001318
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001319 /* Added sanity check on readiness of the MPT adapter.
1320 */
1321 if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
1322 printk(MYIOC_s_WARN_FMT
1323 "Skipping because it's not operational!\n",
1324 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001325 error = -ENODEV;
1326 goto out_mptspi_probe;
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001327 }
1328
1329 if (!ioc->active) {
1330 printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
1331 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001332 error = -ENODEV;
1333 goto out_mptspi_probe;
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001334 }
1335
1336 /* Sanity check - ensure at least 1 port is INITIATOR capable
1337 */
1338 ioc_cap = 0;
1339 for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
1340 if (ioc->pfacts[ii].ProtocolFlags &
1341 MPI_PORTFACTS_PROTOCOL_INITIATOR)
1342 ioc_cap ++;
1343 }
1344
1345 if (!ioc_cap) {
1346 printk(MYIOC_s_WARN_FMT
1347 "Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n",
1348 ioc->name, ioc);
Moore, Eric Dean466544d2005-09-14 18:09:10 -06001349 return 0;
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001350 }
1351
1352 sh = scsi_host_alloc(&mptspi_driver_template, sizeof(MPT_SCSI_HOST));
1353
1354 if (!sh) {
1355 printk(MYIOC_s_WARN_FMT
1356 "Unable to register controller with SCSI subsystem\n",
1357 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001358 error = -1;
1359 goto out_mptspi_probe;
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001360 }
1361
1362 spin_lock_irqsave(&ioc->FreeQlock, flags);
1363
1364 /* Attach the SCSI Host to the IOC structure
1365 */
1366 ioc->sh = sh;
1367
1368 sh->io_port = 0;
1369 sh->n_io_port = 0;
1370 sh->irq = 0;
1371
1372 /* set 16 byte cdb's */
1373 sh->max_cmd_len = 16;
1374
1375 /* Yikes! This is important!
1376 * Otherwise, by default, linux
1377 * only scans target IDs 0-7!
1378 * pfactsN->MaxDevices unreliable
1379 * (not supported in early
1380 * versions of the FW).
1381 * max_id = 1 + actual max id,
1382 * max_lun = 1 + actual last lun,
1383 * see hosts.h :o(
1384 */
Eric Moore793955f2007-01-29 09:42:20 -07001385 sh->max_id = ioc->devices_per_bus;
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001386
1387 sh->max_lun = MPT_LAST_LUN + 1;
James Bottomleyc92f2222006-03-01 09:02:49 -06001388 /*
1389 * If RAID Firmware Detected, setup virtual channel
1390 */
Eric Mooreb506ade2007-01-29 09:45:37 -07001391 if (ioc->ir_firmware)
James Bottomleyc92f2222006-03-01 09:02:49 -06001392 sh->max_channel = 1;
1393 else
1394 sh->max_channel = 0;
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001395 sh->this_id = ioc->pfacts[0].PortSCSIID;
1396
1397 /* Required entry.
1398 */
1399 sh->unique_id = ioc->id;
1400
1401 /* Verify that we won't exceed the maximum
1402 * number of chain buffers
1403 * We can optimize: ZZ = req_sz/sizeof(SGE)
1404 * For 32bit SGE's:
1405 * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
1406 * + (req_sz - 64)/sizeof(SGE)
1407 * A slightly different algorithm is required for
1408 * 64bit SGEs.
1409 */
1410 scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
1411 if (sizeof(dma_addr_t) == sizeof(u64)) {
1412 numSGE = (scale - 1) *
1413 (ioc->facts.MaxChainDepth-1) + scale +
1414 (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
1415 sizeof(u32));
1416 } else {
1417 numSGE = 1 + (scale - 1) *
1418 (ioc->facts.MaxChainDepth-1) + scale +
1419 (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
1420 sizeof(u32));
1421 }
1422
1423 if (numSGE < sh->sg_tablesize) {
1424 /* Reset this value */
Eric Moore29dd3602007-09-14 18:46:51 -06001425 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001426 "Resetting sg_tablesize to %d from %d\n",
1427 ioc->name, numSGE, sh->sg_tablesize));
1428 sh->sg_tablesize = numSGE;
1429 }
1430
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001431 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
1432
1433 hd = (MPT_SCSI_HOST *) sh->hostdata;
1434 hd->ioc = ioc;
1435
1436 /* SCSI needs scsi_cmnd lookup table!
1437 * (with size equal to req_depth*PtrSz!)
1438 */
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001439 hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
1440 if (!hd->ScsiLookup) {
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001441 error = -ENOMEM;
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001442 goto out_mptspi_probe;
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001443 }
1444
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05301445 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScsiLookup @ %p\n",
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001446 ioc->name, hd->ScsiLookup));
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001447
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001448 /* Clear the TM flags
1449 */
1450 hd->tmPending = 0;
1451 hd->tmState = TM_STATE_NONE;
1452 hd->resetPending = 0;
1453 hd->abortSCpnt = NULL;
1454
1455 /* Clear the pointer used to store
1456 * single-threaded commands, i.e., those
1457 * issued during a bus scan, dv and
1458 * configuration pages.
1459 */
1460 hd->cmdPtr = NULL;
1461
1462 /* Initialize this SCSI Hosts' timers
1463 * To use, set the timer expires field
1464 * and add_timer
1465 */
1466 init_timer(&hd->timer);
1467 hd->timer.data = (unsigned long) hd;
1468 hd->timer.function = mptscsih_timer_expired;
1469
1470 ioc->spi_data.Saf_Te = mpt_saf_te;
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001471
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001472 hd->negoNvram = MPT_SCSICFG_USE_NVRAM;
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05301473 ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT
Eric Mooreba856d32006-07-11 17:34:01 -06001474 "saf_te %x\n",
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001475 ioc->name,
Eric Mooreba856d32006-07-11 17:34:01 -06001476 mpt_saf_te));
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001477 ioc->spi_data.noQas = 0;
1478
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001479 init_waitqueue_head(&hd->scandv_waitq);
1480 hd->scandv_wait_done = 0;
1481 hd->last_queue_full = 0;
Eric Moore729782452007-02-07 16:51:40 -07001482 hd->spi_pending = 0;
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001483
James Bottomleyc92f2222006-03-01 09:02:49 -06001484 /* Some versions of the firmware don't support page 0; without
1485 * that we can't get the parameters */
1486 if (hd->ioc->spi_data.sdp0length != 0)
1487 sh->transportt = mptspi_transport_template;
1488
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001489 error = scsi_add_host (sh, &ioc->pcidev->dev);
1490 if(error) {
Eric Moore29dd3602007-09-14 18:46:51 -06001491 dprintk(ioc, printk(MYIOC_s_ERR_FMT
1492 "scsi_add_host failed\n", ioc->name));
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001493 goto out_mptspi_probe;
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001494 }
1495
Moore, Ericd8e925d2006-01-16 18:53:06 -07001496 /*
1497 * issue internal bus reset
1498 */
1499 if (ioc->spi_data.bus_reset)
1500 mptscsih_TMHandler(hd,
1501 MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
1502 0, 0, 0, 0, 5);
1503
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001504 scsi_scan_host(sh);
1505 return 0;
1506
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001507out_mptspi_probe:
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001508
1509 mptscsih_remove(pdev);
1510 return error;
1511}
1512
1513static struct pci_driver mptspi_driver = {
1514 .name = "mptspi",
1515 .id_table = mptspi_pci_table,
1516 .probe = mptspi_probe,
1517 .remove = __devexit_p(mptscsih_remove),
Greg Kroah-Hartmand18c3db2005-06-23 17:35:56 -07001518 .shutdown = mptscsih_shutdown,
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001519#ifdef CONFIG_PM
1520 .suspend = mptscsih_suspend,
Eric Moore6e1cad02006-04-25 17:38:58 -06001521 .resume = mptspi_resume,
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001522#endif
1523};
1524
1525/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1526/**
Randy Dunlapd9489fb2006-12-06 20:38:43 -08001527 * mptspi_init - Register MPT adapter(s) as SCSI host(s) with SCSI mid-layer.
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001528 *
1529 * Returns 0 for success, non-zero for failure.
1530 */
1531static int __init
1532mptspi_init(void)
1533{
Prakash, Sathya57ce21b2007-07-02 17:04:10 +05301534 int error;
1535
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001536 show_mptmod_ver(my_NAME, my_VERSION);
1537
James Bottomleyc92f2222006-03-01 09:02:49 -06001538 mptspi_transport_template = spi_attach_transport(&mptspi_transport_functions);
1539 if (!mptspi_transport_template)
1540 return -ENODEV;
1541
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001542 mptspiDoneCtx = mpt_register(mptscsih_io_done, MPTSPI_DRIVER);
1543 mptspiTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSPI_DRIVER);
1544 mptspiInternalCtx = mpt_register(mptscsih_scandv_complete, MPTSPI_DRIVER);
1545
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05301546 mpt_event_register(mptspiDoneCtx, mptspi_event_process);
1547 mpt_reset_register(mptspiDoneCtx, mptspi_ioc_reset);
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001548
Prakash, Sathya57ce21b2007-07-02 17:04:10 +05301549 error = pci_register_driver(&mptspi_driver);
1550 if (error)
1551 spi_release_transport(mptspi_transport_template);
1552
1553 return error;
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001554}
1555
1556/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1557/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1558/**
1559 * mptspi_exit - Unregisters MPT adapter(s)
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001560 */
1561static void __exit
1562mptspi_exit(void)
1563{
1564 pci_unregister_driver(&mptspi_driver);
Moore, Ericd8e925d2006-01-16 18:53:06 -07001565
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001566 mpt_reset_deregister(mptspiDoneCtx);
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001567 mpt_event_deregister(mptspiDoneCtx);
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001568
1569 mpt_deregister(mptspiInternalCtx);
1570 mpt_deregister(mptspiTaskCtx);
1571 mpt_deregister(mptspiDoneCtx);
James Bottomleyc92f2222006-03-01 09:02:49 -06001572 spi_release_transport(mptspi_transport_template);
Moore, Eric Dean 243eabc2005-04-22 18:02:25 -04001573}
1574
1575module_init(mptspi_init);
1576module_exit(mptspi_exit);