[SCSI] allow sleeping in ->eh_abort_handler()
[deliverable/linux.git] / drivers / message / fusion / mptscsih.c
CommitLineData
1da177e4
LT
1/*
2 * linux/drivers/message/fusion/mptscsih.c
0d0c7974 3 * For use with LSI Logic PCI chip/adapter(s)
1da177e4
LT
4 * running LSI Logic Fusion MPT (Message Passing Technology) firmware.
5 *
0d0c7974 6 * Copyright (c) 1999-2005 LSI Logic Corporation
1da177e4
LT
7 * (mailto:mpt_linux_developer@lsil.com)
8 *
1da177e4
LT
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>
59
60#include <scsi/scsi.h>
61#include <scsi/scsi_cmnd.h>
62#include <scsi/scsi_device.h>
63#include <scsi/scsi_host.h>
64#include <scsi/scsi_tcq.h>
65
66#include "mptbase.h"
67#include "mptscsih.h"
68
69/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
70#define my_NAME "Fusion MPT SCSI Host driver"
71#define my_VERSION MPT_LINUX_VERSION_COMMON
72#define MYNAM "mptscsih"
73
74MODULE_AUTHOR(MODULEAUTHOR);
75MODULE_DESCRIPTION(my_NAME);
76MODULE_LICENSE("GPL");
77
1da177e4
LT
78/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
79
80typedef struct _BIG_SENSE_BUF {
81 u8 data[MPT_SENSE_BUFFER_ALLOC];
82} BIG_SENSE_BUF;
83
84#define MPT_SCANDV_GOOD (0x00000000) /* must be 0 */
85#define MPT_SCANDV_DID_RESET (0x00000001)
86#define MPT_SCANDV_SENSE (0x00000002)
87#define MPT_SCANDV_SOME_ERROR (0x00000004)
88#define MPT_SCANDV_SELECTION_TIMEOUT (0x00000008)
89#define MPT_SCANDV_ISSUE_SENSE (0x00000010)
90#define MPT_SCANDV_FALLBACK (0x00000020)
91
92#define MPT_SCANDV_MAX_RETRIES (10)
93
94#define MPT_ICFLAG_BUF_CAP 0x01 /* ReadBuffer Read Capacity format */
95#define MPT_ICFLAG_ECHO 0x02 /* ReadBuffer Echo buffer format */
96#define MPT_ICFLAG_PHYS_DISK 0x04 /* Any SCSI IO but do Phys Disk Format */
97#define MPT_ICFLAG_TAGGED_CMD 0x08 /* Do tagged IO */
98#define MPT_ICFLAG_DID_RESET 0x20 /* Bus Reset occurred with this command */
99#define MPT_ICFLAG_RESERVED 0x40 /* Reserved has been issued */
100
101typedef struct _internal_cmd {
102 char *data; /* data pointer */
103 dma_addr_t data_dma; /* data dma address */
104 int size; /* transfer size */
105 u8 cmd; /* SCSI Op Code */
106 u8 bus; /* bus number */
107 u8 id; /* SCSI ID (virtual) */
108 u8 lun;
109 u8 flags; /* Bit Field - See above */
110 u8 physDiskNum; /* Phys disk number, -1 else */
111 u8 rsvd2;
112 u8 rsvd;
113} INTERNAL_CMD;
114
115typedef struct _negoparms {
116 u8 width;
117 u8 offset;
118 u8 factor;
119 u8 flags;
120} NEGOPARMS;
121
122typedef struct _dv_parameters {
123 NEGOPARMS max;
124 NEGOPARMS now;
125 u8 cmd;
126 u8 id;
127 u16 pad1;
128} DVPARAMETERS;
129
1da177e4
LT
130/*
131 * Other private/forward protos...
132 */
0d0c7974 133int mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
1da177e4 134static void mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq);
0d0c7974 135int mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
1da177e4
LT
136
137static int mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt,
138 SCSIIORequest_t *pReq, int req_idx);
139static void mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx);
0d0c7974 140static void mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply);
1da177e4
LT
141static int mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd);
142static int mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout );
143static u32 SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc);
144
145static int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout);
146static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout);
147
0d0c7974
MED
148int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
149int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
1da177e4
LT
150
151static void mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *data, int dlen);
152static void mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56);
153static void mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq);
154static void mptscsih_setDevicePage1Flags (u8 width, u8 factor, u8 offset, int *requestedPtr, int *configurationPtr, u8 flags);
155static void mptscsih_no_negotiate(MPT_SCSI_HOST *hd, int target_id);
156static int mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target, int flags);
157static int mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus);
0d0c7974 158int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
1da177e4
LT
159static int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd);
160static int mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum);
161
162#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
163static int mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io);
164static void mptscsih_domainValidation(void *hd);
165static int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id);
166static void mptscsih_qas_check(MPT_SCSI_HOST *hd, int id);
167static int mptscsih_doDv(MPT_SCSI_HOST *hd, int channel, int target);
168static void mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage);
169static void mptscsih_fillbuf(char *buffer, int size, int index, int width);
170#endif
1da177e4 171
0d0c7974
MED
172void mptscsih_remove(struct pci_dev *);
173void mptscsih_shutdown(struct device *);
1da177e4 174#ifdef CONFIG_PM
0d0c7974
MED
175int mptscsih_suspend(struct pci_dev *pdev, pm_message_t state);
176int mptscsih_resume(struct pci_dev *pdev);
1da177e4
LT
177#endif
178
1da177e4
LT
179#define SNS_LEN(scp) sizeof((scp)->sense_buffer)
180
181#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
182/*
183 * Domain Validation task structure
184 */
185static DEFINE_SPINLOCK(dvtaskQ_lock);
186static int dvtaskQ_active = 0;
187static int dvtaskQ_release = 0;
0d0c7974 188static struct work_struct dvTaskQ_task;
1da177e4
LT
189#endif
190
1da177e4
LT
191/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
192/**
193 * mptscsih_add_sge - Place a simple SGE at address pAddr.
194 * @pAddr: virtual address for SGE
195 * @flagslength: SGE flags and data transfer length
196 * @dma_addr: Physical address
197 *
198 * This routine places a MPT request frame back on the MPT adapter's
199 * FreeQ.
200 */
201static inline void
202mptscsih_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr)
203{
204 if (sizeof(dma_addr_t) == sizeof(u64)) {
205 SGESimple64_t *pSge = (SGESimple64_t *) pAddr;
206 u32 tmp = dma_addr & 0xFFFFFFFF;
207
208 pSge->FlagsLength = cpu_to_le32(flagslength);
209 pSge->Address.Low = cpu_to_le32(tmp);
210 tmp = (u32) ((u64)dma_addr >> 32);
211 pSge->Address.High = cpu_to_le32(tmp);
212
213 } else {
214 SGESimple32_t *pSge = (SGESimple32_t *) pAddr;
215 pSge->FlagsLength = cpu_to_le32(flagslength);
216 pSge->Address = cpu_to_le32(dma_addr);
217 }
218} /* mptscsih_add_sge() */
219
220/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
221/**
222 * mptscsih_add_chain - Place a chain SGE at address pAddr.
223 * @pAddr: virtual address for SGE
224 * @next: nextChainOffset value (u32's)
225 * @length: length of next SGL segment
226 * @dma_addr: Physical address
227 *
228 * This routine places a MPT request frame back on the MPT adapter's
229 * FreeQ.
230 */
231static inline void
232mptscsih_add_chain(char *pAddr, u8 next, u16 length, dma_addr_t dma_addr)
233{
234 if (sizeof(dma_addr_t) == sizeof(u64)) {
235 SGEChain64_t *pChain = (SGEChain64_t *) pAddr;
236 u32 tmp = dma_addr & 0xFFFFFFFF;
237
238 pChain->Length = cpu_to_le16(length);
239 pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();
240
241 pChain->NextChainOffset = next;
242
243 pChain->Address.Low = cpu_to_le32(tmp);
244 tmp = (u32) ((u64)dma_addr >> 32);
245 pChain->Address.High = cpu_to_le32(tmp);
246 } else {
247 SGEChain32_t *pChain = (SGEChain32_t *) pAddr;
248 pChain->Length = cpu_to_le16(length);
249 pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();
250 pChain->NextChainOffset = next;
251 pChain->Address = cpu_to_le32(dma_addr);
252 }
253} /* mptscsih_add_chain() */
254
255/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
256/*
257 * mptscsih_getFreeChainBuffer - Function to get a free chain
258 * from the MPT_SCSI_HOST FreeChainQ.
259 * @ioc: Pointer to MPT_ADAPTER structure
260 * @req_idx: Index of the SCSI IO request frame. (output)
261 *
262 * return SUCCESS or FAILED
263 */
264static inline int
265mptscsih_getFreeChainBuffer(MPT_ADAPTER *ioc, int *retIndex)
266{
267 MPT_FRAME_HDR *chainBuf;
268 unsigned long flags;
269 int rc;
270 int chain_idx;
271
272 dsgprintk((MYIOC_s_INFO_FMT "getFreeChainBuffer called\n",
273 ioc->name));
274 spin_lock_irqsave(&ioc->FreeQlock, flags);
275 if (!list_empty(&ioc->FreeChainQ)) {
276 int offset;
277
278 chainBuf = list_entry(ioc->FreeChainQ.next, MPT_FRAME_HDR,
279 u.frame.linkage.list);
280 list_del(&chainBuf->u.frame.linkage.list);
281 offset = (u8 *)chainBuf - (u8 *)ioc->ChainBuffer;
282 chain_idx = offset / ioc->req_sz;
283 rc = SUCCESS;
284 dsgprintk((MYIOC_s_INFO_FMT "getFreeChainBuffer (index %d), got buf=%p\n",
285 ioc->name, *retIndex, chainBuf));
286 } else {
287 rc = FAILED;
288 chain_idx = MPT_HOST_NO_CHAIN;
289 dfailprintk((MYIOC_s_ERR_FMT "getFreeChainBuffer failed\n",
290 ioc->name));
291 }
292 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
293
294 *retIndex = chain_idx;
295 return rc;
296} /* mptscsih_getFreeChainBuffer() */
297
298/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
299/*
300 * mptscsih_AddSGE - Add a SGE (plus chain buffers) to the
301 * SCSIIORequest_t Message Frame.
302 * @ioc: Pointer to MPT_ADAPTER structure
303 * @SCpnt: Pointer to scsi_cmnd structure
304 * @pReq: Pointer to SCSIIORequest_t structure
305 *
306 * Returns ...
307 */
308static int
309mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt,
310 SCSIIORequest_t *pReq, int req_idx)
311{
312 char *psge;
313 char *chainSge;
314 struct scatterlist *sg;
315 int frm_sz;
316 int sges_left, sg_done;
317 int chain_idx = MPT_HOST_NO_CHAIN;
318 int sgeOffset;
319 int numSgeSlots, numSgeThisFrame;
320 u32 sgflags, sgdir, thisxfer = 0;
321 int chain_dma_off = 0;
322 int newIndex;
323 int ii;
324 dma_addr_t v2;
325 u32 RequestNB;
326
327 sgdir = le32_to_cpu(pReq->Control) & MPI_SCSIIO_CONTROL_DATADIRECTION_MASK;
328 if (sgdir == MPI_SCSIIO_CONTROL_WRITE) {
329 sgdir = MPT_TRANSFER_HOST_TO_IOC;
330 } else {
331 sgdir = MPT_TRANSFER_IOC_TO_HOST;
332 }
333
334 psge = (char *) &pReq->SGL;
335 frm_sz = ioc->req_sz;
336
337 /* Map the data portion, if any.
338 * sges_left = 0 if no data transfer.
339 */
340 if ( (sges_left = SCpnt->use_sg) ) {
341 sges_left = pci_map_sg(ioc->pcidev,
342 (struct scatterlist *) SCpnt->request_buffer,
343 SCpnt->use_sg,
344 SCpnt->sc_data_direction);
345 if (sges_left == 0)
346 return FAILED;
347 } else if (SCpnt->request_bufflen) {
348 SCpnt->SCp.dma_handle = pci_map_single(ioc->pcidev,
349 SCpnt->request_buffer,
350 SCpnt->request_bufflen,
351 SCpnt->sc_data_direction);
352 dsgprintk((MYIOC_s_INFO_FMT "SG: non-SG for %p, len=%d\n",
353 ioc->name, SCpnt, SCpnt->request_bufflen));
354 mptscsih_add_sge((char *) &pReq->SGL,
355 0xD1000000|MPT_SGE_FLAGS_ADDRESSING|sgdir|SCpnt->request_bufflen,
356 SCpnt->SCp.dma_handle);
357
358 return SUCCESS;
359 }
360
361 /* Handle the SG case.
362 */
363 sg = (struct scatterlist *) SCpnt->request_buffer;
364 sg_done = 0;
365 sgeOffset = sizeof(SCSIIORequest_t) - sizeof(SGE_IO_UNION);
366 chainSge = NULL;
367
368 /* Prior to entering this loop - the following must be set
369 * current MF: sgeOffset (bytes)
370 * chainSge (Null if original MF is not a chain buffer)
371 * sg_done (num SGE done for this MF)
372 */
373
374nextSGEset:
375 numSgeSlots = ((frm_sz - sgeOffset) / (sizeof(u32) + sizeof(dma_addr_t)) );
376 numSgeThisFrame = (sges_left < numSgeSlots) ? sges_left : numSgeSlots;
377
378 sgflags = MPT_SGE_FLAGS_SIMPLE_ELEMENT | MPT_SGE_FLAGS_ADDRESSING | sgdir;
379
380 /* Get first (num - 1) SG elements
381 * Skip any SG entries with a length of 0
382 * NOTE: at finish, sg and psge pointed to NEXT data/location positions
383 */
384 for (ii=0; ii < (numSgeThisFrame-1); ii++) {
385 thisxfer = sg_dma_len(sg);
386 if (thisxfer == 0) {
387 sg ++; /* Get next SG element from the OS */
388 sg_done++;
389 continue;
390 }
391
392 v2 = sg_dma_address(sg);
393 mptscsih_add_sge(psge, sgflags | thisxfer, v2);
394
395 sg++; /* Get next SG element from the OS */
396 psge += (sizeof(u32) + sizeof(dma_addr_t));
397 sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
398 sg_done++;
399 }
400
401 if (numSgeThisFrame == sges_left) {
402 /* Add last element, end of buffer and end of list flags.
403 */
404 sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT |
405 MPT_SGE_FLAGS_END_OF_BUFFER |
406 MPT_SGE_FLAGS_END_OF_LIST;
407
408 /* Add last SGE and set termination flags.
409 * Note: Last SGE may have a length of 0 - which should be ok.
410 */
411 thisxfer = sg_dma_len(sg);
412
413 v2 = sg_dma_address(sg);
414 mptscsih_add_sge(psge, sgflags | thisxfer, v2);
415 /*
416 sg++;
417 psge += (sizeof(u32) + sizeof(dma_addr_t));
418 */
419 sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
420 sg_done++;
421
422 if (chainSge) {
423 /* The current buffer is a chain buffer,
424 * but there is not another one.
425 * Update the chain element
426 * Offset and Length fields.
427 */
428 mptscsih_add_chain((char *)chainSge, 0, sgeOffset, ioc->ChainBufferDMA + chain_dma_off);
429 } else {
430 /* The current buffer is the original MF
431 * and there is no Chain buffer.
432 */
433 pReq->ChainOffset = 0;
434 RequestNB = (((sgeOffset - 1) >> ioc->NBShiftFactor) + 1) & 0x03;
435 dsgprintk((MYIOC_s_ERR_FMT
436 "Single Buffer RequestNB=%x, sgeOffset=%d\n", ioc->name, RequestNB, sgeOffset));
437 ioc->RequestNB[req_idx] = RequestNB;
438 }
439 } else {
440 /* At least one chain buffer is needed.
441 * Complete the first MF
442 * - last SGE element, set the LastElement bit
443 * - set ChainOffset (words) for orig MF
444 * (OR finish previous MF chain buffer)
445 * - update MFStructPtr ChainIndex
446 * - Populate chain element
447 * Also
448 * Loop until done.
449 */
450
451 dsgprintk((MYIOC_s_INFO_FMT "SG: Chain Required! sg done %d\n",
452 ioc->name, sg_done));
453
454 /* Set LAST_ELEMENT flag for last non-chain element
455 * in the buffer. Since psge points at the NEXT
456 * SGE element, go back one SGE element, update the flags
457 * and reset the pointer. (Note: sgflags & thisxfer are already
458 * set properly).
459 */
460 if (sg_done) {
461 u32 *ptmp = (u32 *) (psge - (sizeof(u32) + sizeof(dma_addr_t)));
462 sgflags = le32_to_cpu(*ptmp);
463 sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT;
464 *ptmp = cpu_to_le32(sgflags);
465 }
466
467 if (chainSge) {
468 /* The current buffer is a chain buffer.
469 * chainSge points to the previous Chain Element.
470 * Update its chain element Offset and Length (must
471 * include chain element size) fields.
472 * Old chain element is now complete.
473 */
474 u8 nextChain = (u8) (sgeOffset >> 2);
475 sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
476 mptscsih_add_chain((char *)chainSge, nextChain, sgeOffset, ioc->ChainBufferDMA + chain_dma_off);
477 } else {
478 /* The original MF buffer requires a chain buffer -
479 * set the offset.
480 * Last element in this MF is a chain element.
481 */
482 pReq->ChainOffset = (u8) (sgeOffset >> 2);
483 RequestNB = (((sgeOffset - 1) >> ioc->NBShiftFactor) + 1) & 0x03;
484 dsgprintk((MYIOC_s_ERR_FMT "Chain Buffer Needed, RequestNB=%x sgeOffset=%d\n", ioc->name, RequestNB, sgeOffset));
485 ioc->RequestNB[req_idx] = RequestNB;
486 }
487
488 sges_left -= sg_done;
489
490
491 /* NOTE: psge points to the beginning of the chain element
492 * in current buffer. Get a chain buffer.
493 */
494 dsgprintk((MYIOC_s_INFO_FMT
495 "calling getFreeChainBuffer SCSI cmd=%02x (%p)\n",
496 ioc->name, pReq->CDB[0], SCpnt));
497 if ((mptscsih_getFreeChainBuffer(ioc, &newIndex)) == FAILED)
498 return FAILED;
499
500 /* Update the tracking arrays.
501 * If chainSge == NULL, update ReqToChain, else ChainToChain
502 */
503 if (chainSge) {
504 ioc->ChainToChain[chain_idx] = newIndex;
505 } else {
506 ioc->ReqToChain[req_idx] = newIndex;
507 }
508 chain_idx = newIndex;
509 chain_dma_off = ioc->req_sz * chain_idx;
510
511 /* Populate the chainSGE for the current buffer.
512 * - Set chain buffer pointer to psge and fill
513 * out the Address and Flags fields.
514 */
515 chainSge = (char *) psge;
516 dsgprintk((KERN_INFO " Current buff @ %p (index 0x%x)",
517 psge, req_idx));
518
519 /* Start the SGE for the next buffer
520 */
521 psge = (char *) (ioc->ChainBuffer + chain_dma_off);
522 sgeOffset = 0;
523 sg_done = 0;
524
525 dsgprintk((KERN_INFO " Chain buff @ %p (index 0x%x)\n",
526 psge, chain_idx));
527
528 /* Start the SGE for the next buffer
529 */
530
531 goto nextSGEset;
532 }
533
534 return SUCCESS;
535} /* mptscsih_AddSGE() */
536
537/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
538/*
539 * mptscsih_io_done - Main SCSI IO callback routine registered to
540 * Fusion MPT (base) driver
541 * @ioc: Pointer to MPT_ADAPTER structure
542 * @mf: Pointer to original MPT request frame
543 * @r: Pointer to MPT reply frame (NULL if TurboReply)
544 *
545 * This routine is called from mpt.c::mpt_interrupt() at the completion
546 * of any SCSI IO request.
547 * This routine is registered with the Fusion MPT (base) driver at driver
548 * load/init time via the mpt_register() API call.
549 *
550 * Returns 1 indicating alloc'd request frame ptr should be freed.
551 */
0d0c7974 552int
1da177e4
LT
553mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
554{
555 struct scsi_cmnd *sc;
556 MPT_SCSI_HOST *hd;
557 SCSIIORequest_t *pScsiReq;
558 SCSIIOReply_t *pScsiReply;
559 u16 req_idx;
560
561 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
562
563 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
564 sc = hd->ScsiLookup[req_idx];
565 if (sc == NULL) {
566 MPIHeader_t *hdr = (MPIHeader_t *)mf;
567
568 /* Remark: writeSDP1 will use the ScsiDoneCtx
569 * If a SCSI I/O cmd, device disabled by OS and
570 * completion done. Cannot touch sc struct. Just free mem.
571 */
572 if (hdr->Function == MPI_FUNCTION_SCSI_IO_REQUEST)
573 printk(MYIOC_s_ERR_FMT "NULL ScsiCmd ptr!\n",
574 ioc->name);
575
576 mptscsih_freeChainBuffers(ioc, req_idx);
577 return 1;
578 }
579
580 dmfprintk((MYIOC_s_INFO_FMT
581 "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d)\n",
582 ioc->name, mf, mr, sc, req_idx));
583
584 sc->result = DID_OK << 16; /* Set default reply as OK */
585 pScsiReq = (SCSIIORequest_t *) mf;
586 pScsiReply = (SCSIIOReply_t *) mr;
587
588 if (pScsiReply == NULL) {
589 /* special context reply handling */
590 ;
591 } else {
592 u32 xfer_cnt;
593 u16 status;
594 u8 scsi_state, scsi_status;
595
596 status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK;
597 scsi_state = pScsiReply->SCSIState;
598 scsi_status = pScsiReply->SCSIStatus;
599 xfer_cnt = le32_to_cpu(pScsiReply->TransferCount);
600 sc->resid = sc->request_bufflen - xfer_cnt;
601
602 dreplyprintk((KERN_NOTICE "Reply ha=%d id=%d lun=%d:\n"
603 "IOCStatus=%04xh SCSIState=%02xh SCSIStatus=%02xh\n"
604 "resid=%d bufflen=%d xfer_cnt=%d\n",
605 ioc->id, pScsiReq->TargetID, pScsiReq->LUN[1],
606 status, scsi_state, scsi_status, sc->resid,
607 sc->request_bufflen, xfer_cnt));
608
609 if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID)
0d0c7974
MED
610 mptscsih_copy_sense_data(sc, hd, mf, pScsiReply);
611
1da177e4
LT
612 /*
613 * Look for + dump FCP ResponseInfo[]!
614 */
615 if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID) {
616 printk(KERN_NOTICE " FCP_ResponseInfo=%08xh\n",
617 le32_to_cpu(pScsiReply->ResponseInfo));
618 }
619
620 switch(status) {
621 case MPI_IOCSTATUS_BUSY: /* 0x0002 */
622 /* CHECKME!
623 * Maybe: DRIVER_BUSY | SUGGEST_RETRY | DID_SOFT_ERROR (retry)
624 * But not: DID_BUS_BUSY lest one risk
625 * killing interrupt handler:-(
626 */
627 sc->result = SAM_STAT_BUSY;
628 break;
629
630 case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
631 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
632 sc->result = DID_BAD_TARGET << 16;
633 break;
634
635 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
636 /* Spoof to SCSI Selection Timeout! */
637 sc->result = DID_NO_CONNECT << 16;
638
639 if (hd->sel_timeout[pScsiReq->TargetID] < 0xFFFF)
640 hd->sel_timeout[pScsiReq->TargetID]++;
641 break;
642
643 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
644 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
645 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
646 /* Linux handles an unsolicited DID_RESET better
647 * than an unsolicited DID_ABORT.
648 */
649 sc->result = DID_RESET << 16;
650
651 /* GEM Workaround. */
652 if (ioc->bus_type == SCSI)
653 mptscsih_no_negotiate(hd, sc->device->id);
654 break;
655
656 case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
657 if ( xfer_cnt >= sc->underflow ) {
658 /* Sufficient data transfer occurred */
659 sc->result = (DID_OK << 16) | scsi_status;
660 } else if ( xfer_cnt == 0 ) {
661 /* A CRC Error causes this condition; retry */
662 sc->result = (DRIVER_SENSE << 24) | (DID_OK << 16) |
663 (CHECK_CONDITION << 1);
664 sc->sense_buffer[0] = 0x70;
665 sc->sense_buffer[2] = NO_SENSE;
666 sc->sense_buffer[12] = 0;
667 sc->sense_buffer[13] = 0;
668 } else {
669 sc->result = DID_SOFT_ERROR << 16;
670 }
671 dreplyprintk((KERN_NOTICE "RESIDUAL_MISMATCH: result=%x on id=%d\n", sc->result, sc->target));
672 break;
0d0c7974 673
1da177e4
LT
674 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
675 /*
676 * Do upfront check for valid SenseData and give it
677 * precedence!
678 */
679 sc->result = (DID_OK << 16) | scsi_status;
680 if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
681 /* Have already saved the status and sense data
682 */
683 ;
684 } else {
685 if (xfer_cnt < sc->underflow) {
686 sc->result = DID_SOFT_ERROR << 16;
687 }
688 if (scsi_state & (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)) {
689 /* What to do?
690 */
691 sc->result = DID_SOFT_ERROR << 16;
692 }
693 else if (scsi_state & MPI_SCSI_STATE_TERMINATED) {
694 /* Not real sure here either... */
695 sc->result = DID_RESET << 16;
696 }
697 }
698
699 dreplyprintk((KERN_NOTICE " sc->underflow={report ERR if < %02xh bytes xfer'd}\n",
700 sc->underflow));
701 dreplyprintk((KERN_NOTICE " ActBytesXferd=%02xh\n", xfer_cnt));
702 /* Report Queue Full
703 */
704 if (scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL)
705 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
0d0c7974 706
1da177e4
LT
707 break;
708
709 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
710 case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */
711 scsi_status = pScsiReply->SCSIStatus;
712 sc->result = (DID_OK << 16) | scsi_status;
713 if (scsi_state == 0) {
714 ;
715 } else if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
716 /*
717 * If running against circa 200003dd 909 MPT f/w,
718 * may get this (AUTOSENSE_VALID) for actual TASK_SET_FULL
719 * (QUEUE_FULL) returned from device! --> get 0x0000?128
720 * and with SenseBytes set to 0.
721 */
722 if (pScsiReply->SCSIStatus == MPI_SCSI_STATUS_TASK_SET_FULL)
723 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
724
725 }
726 else if (scsi_state &
727 (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)
728 ) {
729 /*
730 * What to do?
731 */
732 sc->result = DID_SOFT_ERROR << 16;
733 }
734 else if (scsi_state & MPI_SCSI_STATE_TERMINATED) {
735 /* Not real sure here either... */
736 sc->result = DID_RESET << 16;
737 }
738 else if (scsi_state & MPI_SCSI_STATE_QUEUE_TAG_REJECTED) {
739 /* Device Inq. data indicates that it supports
740 * QTags, but rejects QTag messages.
741 * This command completed OK.
742 *
743 * Not real sure here either so do nothing... */
744 }
745
746 if (sc->result == MPI_SCSI_STATUS_TASK_SET_FULL)
747 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
748
749 /* Add handling of:
750 * Reservation Conflict, Busy,
751 * Command Terminated, CHECK
752 */
753 break;
754
755 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
756 sc->result = DID_SOFT_ERROR << 16;
757 break;
758
759 case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */
760 case MPI_IOCSTATUS_INVALID_SGL: /* 0x0003 */
761 case MPI_IOCSTATUS_INTERNAL_ERROR: /* 0x0004 */
762 case MPI_IOCSTATUS_RESERVED: /* 0x0005 */
763 case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */
764 case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */
765 case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */
766 case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
767 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
768 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
769 default:
770 /*
771 * What to do?
772 */
773 sc->result = DID_SOFT_ERROR << 16;
774 break;
775
776 } /* switch(status) */
777
778 dreplyprintk((KERN_NOTICE " sc->result is %08xh\n", sc->result));
779 } /* end of address reply case */
780
781 /* Unmap the DMA buffers, if any. */
782 if (sc->use_sg) {
783 pci_unmap_sg(ioc->pcidev, (struct scatterlist *) sc->request_buffer,
784 sc->use_sg, sc->sc_data_direction);
785 } else if (sc->request_bufflen) {
786 pci_unmap_single(ioc->pcidev, sc->SCp.dma_handle,
787 sc->request_bufflen, sc->sc_data_direction);
788 }
789
790 hd->ScsiLookup[req_idx] = NULL;
791
792 sc->scsi_done(sc); /* Issue the command callback */
793
794 /* Free Chain buffers */
795 mptscsih_freeChainBuffers(ioc, req_idx);
796 return 1;
797}
798
799
800/*
801 * mptscsih_flush_running_cmds - For each command found, search
802 * Scsi_Host instance taskQ and reply to OS.
803 * Called only if recovering from a FW reload.
804 * @hd: Pointer to a SCSI HOST structure
805 *
806 * Returns: None.
807 *
808 * Must be called while new I/Os are being queued.
809 */
810static void
811mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
812{
813 MPT_ADAPTER *ioc = hd->ioc;
814 struct scsi_cmnd *SCpnt;
815 MPT_FRAME_HDR *mf;
816 int ii;
817 int max = ioc->req_depth;
818
819 dprintk((KERN_INFO MYNAM ": flush_ScsiLookup called\n"));
820 for (ii= 0; ii < max; ii++) {
821 if ((SCpnt = hd->ScsiLookup[ii]) != NULL) {
822
823 /* Command found.
824 */
825
826 /* Null ScsiLookup index
827 */
828 hd->ScsiLookup[ii] = NULL;
829
830 mf = MPT_INDEX_2_MFPTR(ioc, ii);
831 dmfprintk(( "flush: ScsiDone (mf=%p,sc=%p)\n",
832 mf, SCpnt));
833
834 /* Set status, free OS resources (SG DMA buffers)
835 * Do OS callback
836 * Free driver resources (chain, msg buffers)
837 */
0d0c7974
MED
838 if (SCpnt->use_sg) {
839 pci_unmap_sg(ioc->pcidev,
840 (struct scatterlist *) SCpnt->request_buffer,
841 SCpnt->use_sg,
842 SCpnt->sc_data_direction);
843 } else if (SCpnt->request_bufflen) {
844 pci_unmap_single(ioc->pcidev,
845 SCpnt->SCp.dma_handle,
846 SCpnt->request_bufflen,
847 SCpnt->sc_data_direction);
1da177e4
LT
848 }
849 SCpnt->result = DID_RESET << 16;
850 SCpnt->host_scribble = NULL;
851
852 /* Free Chain buffers */
853 mptscsih_freeChainBuffers(ioc, ii);
854
855 /* Free Message frames */
856 mpt_free_msg_frame(ioc, mf);
857
858 SCpnt->scsi_done(SCpnt); /* Issue the command callback */
859 }
860 }
861
862 return;
863}
864
865/*
866 * mptscsih_search_running_cmds - Delete any commands associated
867 * with the specified target and lun. Function called only
868 * when a lun is disable by mid-layer.
869 * Do NOT access the referenced scsi_cmnd structure or
870 * members. Will cause either a paging or NULL ptr error.
871 * @hd: Pointer to a SCSI HOST structure
872 * @target: target id
873 * @lun: lun
874 *
875 * Returns: None.
876 *
877 * Called from slave_destroy.
878 */
879static void
880mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, uint target, uint lun)
881{
882 SCSIIORequest_t *mf = NULL;
883 int ii;
884 int max = hd->ioc->req_depth;
885
886 dsprintk((KERN_INFO MYNAM ": search_running target %d lun %d max %d\n",
887 target, lun, max));
888
889 for (ii=0; ii < max; ii++) {
890 if (hd->ScsiLookup[ii] != NULL) {
891
892 mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(hd->ioc, ii);
893
894 dsprintk(( "search_running: found (sc=%p, mf = %p) target %d, lun %d \n",
895 hd->ScsiLookup[ii], mf, mf->TargetID, mf->LUN[1]));
896
897 if ((mf->TargetID != ((u8)target)) || (mf->LUN[1] != ((u8) lun)))
898 continue;
899
900 /* Cleanup
901 */
902 hd->ScsiLookup[ii] = NULL;
903 mptscsih_freeChainBuffers(hd->ioc, ii);
904 mpt_free_msg_frame(hd->ioc, (MPT_FRAME_HDR *)mf);
905 }
906 }
907
908 return;
909}
910
911/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1da177e4
LT
912
913/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
914/*
915 * mptscsih_report_queue_full - Report QUEUE_FULL status returned
916 * from a SCSI target device.
917 * @sc: Pointer to scsi_cmnd structure
918 * @pScsiReply: Pointer to SCSIIOReply_t
919 * @pScsiReq: Pointer to original SCSI request
920 *
921 * This routine periodically reports QUEUE_FULL status returned from a
922 * SCSI target device. It reports this to the console via kernel
923 * printk() API call, not more than once every 10 seconds.
924 */
925static void
926mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq)
927{
928 long time = jiffies;
1da177e4 929 MPT_SCSI_HOST *hd;
1da177e4 930
0d0c7974
MED
931 if (sc->device == NULL)
932 return;
933 if (sc->device->host == NULL)
934 return;
935 if ((hd = (MPT_SCSI_HOST *)sc->device->host->hostdata) == NULL)
936 return;
1da177e4 937
0d0c7974
MED
938 if (time - hd->last_queue_full > 10 * HZ) {
939 dprintk((MYIOC_s_WARN_FMT "Device (%d:%d:%d) reported QUEUE_FULL!\n",
940 hd->ioc->name, 0, sc->device->id, sc->device->lun));
941 hd->last_queue_full = time;
1da177e4 942 }
1da177e4
LT
943}
944
945/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
946/*
947 * mptscsih_remove - Removed scsi devices
948 * @pdev: Pointer to pci_dev structure
949 *
950 *
951 */
0d0c7974 952void
1da177e4
LT
953mptscsih_remove(struct pci_dev *pdev)
954{
955 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
956 struct Scsi_Host *host = ioc->sh;
957 MPT_SCSI_HOST *hd;
958 int count;
959 unsigned long flags;
0d0c7974 960 int sz1;
1da177e4
LT
961
962 if(!host)
963 return;
964
965 scsi_remove_host(host);
966
0d0c7974
MED
967 if((hd = (MPT_SCSI_HOST *)host->hostdata) == NULL)
968 return;
969
1da177e4
LT
970#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
971 /* Check DV thread active */
972 count = 10 * HZ;
973 spin_lock_irqsave(&dvtaskQ_lock, flags);
974 if (dvtaskQ_active) {
975 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
976 while(dvtaskQ_active && --count) {
977 set_current_state(TASK_INTERRUPTIBLE);
978 schedule_timeout(1);
979 }
980 } else {
981 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
982 }
983 if (!count)
984 printk(KERN_ERR MYNAM ": ERROR - DV thread still active!\n");
985#if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY)
986 else
987 printk(KERN_ERR MYNAM ": DV thread orig %d, count %d\n", 10 * HZ, count);
988#endif
989#endif
990
0d0c7974 991 mptscsih_shutdown(&pdev->dev);
1da177e4 992
0d0c7974 993 sz1=0;
1da177e4 994
0d0c7974
MED
995 if (hd->ScsiLookup != NULL) {
996 sz1 = hd->ioc->req_depth * sizeof(void *);
997 kfree(hd->ScsiLookup);
998 hd->ScsiLookup = NULL;
999 }
1da177e4 1000
d485eb83
MED
1001 /*
1002 * Free pointer array.
1003 */
1004 kfree(hd->Targets);
1005 hd->Targets = NULL;
1da177e4 1006
0d0c7974
MED
1007 dprintk((MYIOC_s_INFO_FMT
1008 "Free'd ScsiLookup (%d) memory\n",
1009 hd->ioc->name, sz1));
1da177e4 1010
d485eb83 1011 kfree(hd->info_kbuf);
1da177e4 1012
0d0c7974
MED
1013 /* NULL the Scsi_Host pointer
1014 */
1015 hd->ioc->sh = NULL;
1da177e4
LT
1016
1017 scsi_host_put(host);
1da177e4 1018
0d0c7974
MED
1019 mpt_detach(pdev);
1020
1da177e4
LT
1021}
1022
1023/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1024/*
1025 * mptscsih_shutdown - reboot notifier
1026 *
1027 */
0d0c7974 1028void
1da177e4
LT
1029mptscsih_shutdown(struct device * dev)
1030{
1031 MPT_ADAPTER *ioc = pci_get_drvdata(to_pci_dev(dev));
1032 struct Scsi_Host *host = ioc->sh;
1033 MPT_SCSI_HOST *hd;
1034
1035 if(!host)
1036 return;
1037
1038 hd = (MPT_SCSI_HOST *)host->hostdata;
1039
1040 /* Flush the cache of this adapter
1041 */
1042 if(hd != NULL)
1043 mptscsih_synchronize_cache(hd, 0);
1044
1045}
1046
1047#ifdef CONFIG_PM
1048/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1049/*
0d0c7974 1050 * mptscsih_suspend - Fusion MPT scsi driver suspend routine.
1da177e4
LT
1051 *
1052 *
1053 */
0d0c7974 1054int
8d189f72 1055mptscsih_suspend(struct pci_dev *pdev, pm_message_t state)
1da177e4
LT
1056{
1057 mptscsih_shutdown(&pdev->dev);
0d0c7974 1058 return mpt_suspend(pdev,state);
1da177e4
LT
1059}
1060
1061/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1062/*
1063 * mptscsih_resume - Fusion MPT scsi driver resume routine.
1064 *
1065 *
1066 */
0d0c7974 1067int
1da177e4
LT
1068mptscsih_resume(struct pci_dev *pdev)
1069{
1070 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1071 struct Scsi_Host *host = ioc->sh;
1072 MPT_SCSI_HOST *hd;
1073
0d0c7974
MED
1074 mpt_resume(pdev);
1075
1da177e4
LT
1076 if(!host)
1077 return 0;
1078
1079 hd = (MPT_SCSI_HOST *)host->hostdata;
1080 if(!hd)
1081 return 0;
1082
1083#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
1084 {
1085 unsigned long lflags;
1086 spin_lock_irqsave(&dvtaskQ_lock, lflags);
1087 if (!dvtaskQ_active) {
1088 dvtaskQ_active = 1;
1089 spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
0d0c7974 1090 INIT_WORK(&dvTaskQ_task,
1da177e4 1091 mptscsih_domainValidation, (void *) hd);
0d0c7974 1092 schedule_work(&dvTaskQ_task);
1da177e4
LT
1093 } else {
1094 spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
1095 }
1096 }
1097#endif
1098 return 0;
1099}
1100
1101#endif
1102
1da177e4
LT
1103/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1104/**
1105 * mptscsih_info - Return information about MPT adapter
1106 * @SChost: Pointer to Scsi_Host structure
1107 *
1108 * (linux scsi_host_template.info routine)
1109 *
1110 * Returns pointer to buffer where information was written.
1111 */
0d0c7974 1112const char *
1da177e4
LT
1113mptscsih_info(struct Scsi_Host *SChost)
1114{
1115 MPT_SCSI_HOST *h;
1116 int size = 0;
1117
1da177e4 1118 h = (MPT_SCSI_HOST *)SChost->hostdata;
0d0c7974 1119
1da177e4 1120 if (h) {
0d0c7974
MED
1121 if (h->info_kbuf == NULL)
1122 if ((h->info_kbuf = kmalloc(0x1000 /* 4Kb */, GFP_KERNEL)) == NULL)
1123 return h->info_kbuf;
1124 h->info_kbuf[0] = '\0';
1125
1126 mpt_print_ioc_summary(h->ioc, h->info_kbuf, &size, 0, 0);
1127 h->info_kbuf[size-1] = '\0';
1da177e4
LT
1128 }
1129
0d0c7974 1130 return h->info_kbuf;
1da177e4
LT
1131}
1132
1133struct info_str {
1134 char *buffer;
1135 int length;
1136 int offset;
1137 int pos;
1138};
1139
0d0c7974
MED
1140static void
1141mptscsih_copy_mem_info(struct info_str *info, char *data, int len)
1da177e4
LT
1142{
1143 if (info->pos + len > info->length)
1144 len = info->length - info->pos;
1145
1146 if (info->pos + len < info->offset) {
1147 info->pos += len;
1148 return;
1149 }
1150
1151 if (info->pos < info->offset) {
1152 data += (info->offset - info->pos);
1153 len -= (info->offset - info->pos);
1154 }
1155
1156 if (len > 0) {
1157 memcpy(info->buffer + info->pos, data, len);
1158 info->pos += len;
1159 }
1160}
1161
0d0c7974
MED
1162static int
1163mptscsih_copy_info(struct info_str *info, char *fmt, ...)
1da177e4
LT
1164{
1165 va_list args;
1166 char buf[81];
1167 int len;
1168
1169 va_start(args, fmt);
1170 len = vsprintf(buf, fmt, args);
1171 va_end(args);
1172
0d0c7974 1173 mptscsih_copy_mem_info(info, buf, len);
1da177e4
LT
1174 return len;
1175}
1176
0d0c7974
MED
1177static int
1178mptscsih_host_info(MPT_ADAPTER *ioc, char *pbuf, off_t offset, int len)
1da177e4
LT
1179{
1180 struct info_str info;
1181
1182 info.buffer = pbuf;
1183 info.length = len;
1184 info.offset = offset;
1185 info.pos = 0;
1186
0d0c7974
MED
1187 mptscsih_copy_info(&info, "%s: %s, ", ioc->name, ioc->prod_name);
1188 mptscsih_copy_info(&info, "%s%08xh, ", MPT_FW_REV_MAGIC_ID_STRING, ioc->facts.FWVersion.Word);
1189 mptscsih_copy_info(&info, "Ports=%d, ", ioc->facts.NumberOfPorts);
1190 mptscsih_copy_info(&info, "MaxQ=%d\n", ioc->req_depth);
1da177e4
LT
1191
1192 return ((info.pos > info.offset) ? info.pos - info.offset : 0);
1193}
1194
1195/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1196/**
1197 * mptscsih_proc_info - Return information about MPT adapter
1198 *
1199 * (linux scsi_host_template.info routine)
1200 *
1201 * buffer: if write, user data; if read, buffer for user
1202 * length: if write, return length;
1203 * offset: if write, 0; if read, the current offset into the buffer from
1204 * the previous read.
1205 * hostno: scsi host number
1206 * func: if write = 1; if read = 0
1207 */
0d0c7974 1208int
1da177e4
LT
1209mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
1210 int length, int func)
1211{
1212 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
1213 MPT_ADAPTER *ioc = hd->ioc;
1214 int size = 0;
1215
1216 if (func) {
1217 /*
1218 * write is not supported
1219 */
1220 } else {
1221 if (start)
1222 *start = buffer;
1223
1224 size = mptscsih_host_info(ioc, buffer, offset, length);
1225 }
1226
1227 return size;
1228}
1229
1230/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1231#define ADD_INDEX_LOG(req_ent) do { } while(0)
1232
1233/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1234/**
1235 * mptscsih_qcmd - Primary Fusion MPT SCSI initiator IO start routine.
1236 * @SCpnt: Pointer to scsi_cmnd structure
1237 * @done: Pointer SCSI mid-layer IO completion function
1238 *
1239 * (linux scsi_host_template.queuecommand routine)
1240 * This is the primary SCSI IO start routine. Create a MPI SCSIIORequest
1241 * from a linux scsi_cmnd request and send it to the IOC.
1242 *
1243 * Returns 0. (rtn value discarded by linux scsi mid-layer)
1244 */
0d0c7974 1245int
1da177e4
LT
1246mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
1247{
1248 MPT_SCSI_HOST *hd;
1249 MPT_FRAME_HDR *mf;
1250 SCSIIORequest_t *pScsiReq;
1251 VirtDevice *pTarget;
1252 int target;
1253 int lun;
1254 u32 datalen;
1255 u32 scsictl;
1256 u32 scsidir;
1257 u32 cmd_len;
1258 int my_idx;
1259 int ii;
1260
1261 hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata;
1262 target = SCpnt->device->id;
1263 lun = SCpnt->device->lun;
1264 SCpnt->scsi_done = done;
1265
1266 pTarget = hd->Targets[target];
1267
1268 dmfprintk((MYIOC_s_INFO_FMT "qcmd: SCpnt=%p, done()=%p\n",
1269 (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt, done));
1270
1271 if (hd->resetPending) {
1272 dtmprintk((MYIOC_s_WARN_FMT "qcmd: SCpnt=%p timeout + 60HZ\n",
1273 (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt));
1274 return SCSI_MLQUEUE_HOST_BUSY;
1275 }
1276
1277 /*
1278 * Put together a MPT SCSI request...
1279 */
0d0c7974 1280 if ((mf = mpt_get_msg_frame(hd->ioc->DoneCtx, hd->ioc)) == NULL) {
1da177e4
LT
1281 dprintk((MYIOC_s_WARN_FMT "QueueCmd, no msg frames!!\n",
1282 hd->ioc->name));
1283 return SCSI_MLQUEUE_HOST_BUSY;
1284 }
1285
1286 pScsiReq = (SCSIIORequest_t *) mf;
1287
1288 my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
1289
1290 ADD_INDEX_LOG(my_idx);
1291
0d0c7974 1292 /* TUR's being issued with scsictl=0x02000000 (DATA_IN)!
1da177e4
LT
1293 * Seems we may receive a buffer (datalen>0) even when there
1294 * will be no data transfer! GRRRRR...
1295 */
1296 if (SCpnt->sc_data_direction == DMA_FROM_DEVICE) {
1297 datalen = SCpnt->request_bufflen;
1298 scsidir = MPI_SCSIIO_CONTROL_READ; /* DATA IN (host<--ioc<--dev) */
1299 } else if (SCpnt->sc_data_direction == DMA_TO_DEVICE) {
1300 datalen = SCpnt->request_bufflen;
1301 scsidir = MPI_SCSIIO_CONTROL_WRITE; /* DATA OUT (host-->ioc-->dev) */
1302 } else {
1303 datalen = 0;
1304 scsidir = MPI_SCSIIO_CONTROL_NODATATRANSFER;
1305 }
1306
1307 /* Default to untagged. Once a target structure has been allocated,
1308 * use the Inquiry data to determine if device supports tagged.
1309 */
1310 if ( pTarget
1311 && (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)
1312 && (SCpnt->device->tagged_supported)) {
1313 scsictl = scsidir | MPI_SCSIIO_CONTROL_SIMPLEQ;
1314 } else {
1315 scsictl = scsidir | MPI_SCSIIO_CONTROL_UNTAGGED;
1316 }
1317
1318 /* Use the above information to set up the message frame
1319 */
1320 pScsiReq->TargetID = (u8) target;
1321 pScsiReq->Bus = (u8) SCpnt->device->channel;
1322 pScsiReq->ChainOffset = 0;
1323 pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
1324 pScsiReq->CDBLength = SCpnt->cmd_len;
1325 pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
1326 pScsiReq->Reserved = 0;
1327 pScsiReq->MsgFlags = mpt_msg_flags();
1328 pScsiReq->LUN[0] = 0;
1329 pScsiReq->LUN[1] = lun;
1330 pScsiReq->LUN[2] = 0;
1331 pScsiReq->LUN[3] = 0;
1332 pScsiReq->LUN[4] = 0;
1333 pScsiReq->LUN[5] = 0;
1334 pScsiReq->LUN[6] = 0;
1335 pScsiReq->LUN[7] = 0;
1336 pScsiReq->Control = cpu_to_le32(scsictl);
1337
1338 /*
1339 * Write SCSI CDB into the message
1340 */
1341 cmd_len = SCpnt->cmd_len;
1342 for (ii=0; ii < cmd_len; ii++)
1343 pScsiReq->CDB[ii] = SCpnt->cmnd[ii];
1344
1345 for (ii=cmd_len; ii < 16; ii++)
1346 pScsiReq->CDB[ii] = 0;
1347
1348 /* DataLength */
1349 pScsiReq->DataLength = cpu_to_le32(datalen);
1350
1351 /* SenseBuffer low address */
1352 pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma
1353 + (my_idx * MPT_SENSE_BUFFER_ALLOC));
1354
1355 /* Now add the SG list
1356 * Always have a SGE even if null length.
1357 */
1358 if (datalen == 0) {
1359 /* Add a NULL SGE */
1360 mptscsih_add_sge((char *)&pScsiReq->SGL, MPT_SGE_FLAGS_SSIMPLE_READ | 0,
1361 (dma_addr_t) -1);
1362 } else {
1363 /* Add a 32 or 64 bit SGE */
1364 if (mptscsih_AddSGE(hd->ioc, SCpnt, pScsiReq, my_idx) != SUCCESS)
1365 goto fail;
1366 }
1367
1368 hd->ScsiLookup[my_idx] = SCpnt;
1369 SCpnt->host_scribble = NULL;
1370
1371#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
1372 if (hd->ioc->bus_type == SCSI) {
1373 int dvStatus = hd->ioc->spi_data.dvStatus[target];
1374 int issueCmd = 1;
1375
1376 if (dvStatus || hd->ioc->spi_data.forceDv) {
1377
1378 if ((dvStatus & MPT_SCSICFG_NEED_DV) ||
1379 (hd->ioc->spi_data.forceDv & MPT_SCSICFG_NEED_DV)) {
1380 unsigned long lflags;
1381 /* Schedule DV if necessary */
1382 spin_lock_irqsave(&dvtaskQ_lock, lflags);
1383 if (!dvtaskQ_active) {
1384 dvtaskQ_active = 1;
1385 spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
0d0c7974 1386 INIT_WORK(&dvTaskQ_task, mptscsih_domainValidation, (void *) hd);
1da177e4 1387
0d0c7974 1388 schedule_work(&dvTaskQ_task);
1da177e4
LT
1389 } else {
1390 spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
1391 }
1392 hd->ioc->spi_data.forceDv &= ~MPT_SCSICFG_NEED_DV;
1393 }
1394
1395 /* Trying to do DV to this target, extend timeout.
1396 * Wait to issue until flag is clear
1397 */
1398 if (dvStatus & MPT_SCSICFG_DV_PENDING) {
1399 mod_timer(&SCpnt->eh_timeout, jiffies + 40 * HZ);
1400 issueCmd = 0;
1401 }
1402
1403 /* Set the DV flags.
1404 */
1405 if (dvStatus & MPT_SCSICFG_DV_NOT_DONE)
1406 mptscsih_set_dvflags(hd, pScsiReq);
1407
1408 if (!issueCmd)
1409 goto fail;
1410 }
1411 }
1412#endif
1413
0d0c7974 1414 mpt_put_msg_frame(hd->ioc->DoneCtx, hd->ioc, mf);
1da177e4
LT
1415 dmfprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n",
1416 hd->ioc->name, SCpnt, mf, my_idx));
1417 DBG_DUMP_REQUEST_FRAME(mf)
1418 return 0;
1419
1420 fail:
1421 mptscsih_freeChainBuffers(hd->ioc, my_idx);
1422 mpt_free_msg_frame(hd->ioc, mf);
1423 return SCSI_MLQUEUE_HOST_BUSY;
1424}
1425
1426/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1427/*
1428 * mptscsih_freeChainBuffers - Function to free chain buffers associated
1429 * with a SCSI IO request
1430 * @hd: Pointer to the MPT_SCSI_HOST instance
1431 * @req_idx: Index of the SCSI IO request frame.
1432 *
1433 * Called if SG chain buffer allocation fails and mptscsih callbacks.
1434 * No return.
1435 */
1436static void
1437mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx)
1438{
1439 MPT_FRAME_HDR *chain;
1440 unsigned long flags;
1441 int chain_idx;
1442 int next;
1443
1444 /* Get the first chain index and reset
1445 * tracker state.
1446 */
1447 chain_idx = ioc->ReqToChain[req_idx];
1448 ioc->ReqToChain[req_idx] = MPT_HOST_NO_CHAIN;
1449
1450 while (chain_idx != MPT_HOST_NO_CHAIN) {
1451
1452 /* Save the next chain buffer index */
1453 next = ioc->ChainToChain[chain_idx];
1454
1455 /* Free this chain buffer and reset
1456 * tracker
1457 */
1458 ioc->ChainToChain[chain_idx] = MPT_HOST_NO_CHAIN;
1459
1460 chain = (MPT_FRAME_HDR *) (ioc->ChainBuffer
1461 + (chain_idx * ioc->req_sz));
1462
1463 spin_lock_irqsave(&ioc->FreeQlock, flags);
1464 list_add_tail(&chain->u.frame.linkage.list, &ioc->FreeChainQ);
1465 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
1466
1467 dmfprintk((MYIOC_s_INFO_FMT "FreeChainBuffers (index %d)\n",
1468 ioc->name, chain_idx));
1469
1470 /* handle next */
1471 chain_idx = next;
1472 }
1473 return;
1474}
1475
1476/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1477/*
1478 * Reset Handling
1479 */
1480
1481/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1482/*
1483 * mptscsih_TMHandler - Generic handler for SCSI Task Management.
1484 * Fall through to mpt_HardResetHandler if: not operational, too many
1485 * failed TM requests or handshake failure.
1486 *
1487 * @ioc: Pointer to MPT_ADAPTER structure
1488 * @type: Task Management type
1489 * @target: Logical Target ID for reset (if appropriate)
1490 * @lun: Logical Unit for reset (if appropriate)
1491 * @ctx2abort: Context for the task to be aborted (if appropriate)
1492 *
1493 * Remark: Currently invoked from a non-interrupt thread (_bh).
1494 *
1495 * Remark: With old EH code, at most 1 SCSI TaskMgmt function per IOC
1496 * will be active.
1497 *
1498 * Returns 0 for SUCCESS or -1 if FAILED.
1499 */
1500static int
1501mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout)
1502{
1503 MPT_ADAPTER *ioc;
1504 int rc = -1;
1505 int doTask = 1;
1506 u32 ioc_raw_state;
1507 unsigned long flags;
1508
1509 /* If FW is being reloaded currently, return success to
1510 * the calling function.
1511 */
1512 if (hd == NULL)
1513 return 0;
1514
1515 ioc = hd->ioc;
1516 if (ioc == NULL) {
1517 printk(KERN_ERR MYNAM " TMHandler" " NULL ioc!\n");
1518 return FAILED;
1519 }
1520 dtmprintk((MYIOC_s_INFO_FMT "TMHandler Entered!\n", ioc->name));
1521
1522 // SJR - CHECKME - Can we avoid this here?
1523 // (mpt_HardResetHandler has this check...)
1524 spin_lock_irqsave(&ioc->diagLock, flags);
1525 if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)) {
1526 spin_unlock_irqrestore(&ioc->diagLock, flags);
1527 return FAILED;
1528 }
1529 spin_unlock_irqrestore(&ioc->diagLock, flags);
1530
1531 /* Wait a fixed amount of time for the TM pending flag to be cleared.
1532 * If we time out and not bus reset, then we return a FAILED status to the caller.
1533 * The call to mptscsih_tm_pending_wait() will set the pending flag if we are
1534 * successful. Otherwise, reload the FW.
1535 */
1536 if (mptscsih_tm_pending_wait(hd) == FAILED) {
1537 if (type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) {
1538 dtmprintk((KERN_WARNING MYNAM ": %s: TMHandler abort: "
1539 "Timed out waiting for last TM (%d) to complete! \n",
1540 hd->ioc->name, hd->tmPending));
1541 return FAILED;
1542 } else if (type == MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET) {
1543 dtmprintk((KERN_WARNING MYNAM ": %s: TMHandler target reset: "
1544 "Timed out waiting for last TM (%d) to complete! \n",
1545 hd->ioc->name, hd->tmPending));
1546 return FAILED;
1547 } else if (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
1548 dtmprintk((KERN_WARNING MYNAM ": %s: TMHandler bus reset: "
1549 "Timed out waiting for last TM (%d) to complete! \n",
1550 hd->ioc->name, hd->tmPending));
1551 if (hd->tmPending & (1 << MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS))
1552 return FAILED;
1553
1554 doTask = 0;
1555 }
1556 } else {
1557 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
1558 hd->tmPending |= (1 << type);
1559 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
1560 }
1561
1562 /* Is operational?
1563 */
1564 ioc_raw_state = mpt_GetIocState(hd->ioc, 0);
1565
1566#ifdef MPT_DEBUG_RESET
1567 if ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) {
1568 printk(MYIOC_s_WARN_FMT
1569 "TM Handler: IOC Not operational(0x%x)!\n",
1570 hd->ioc->name, ioc_raw_state);
1571 }
1572#endif
1573
1574 if (doTask && ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL)
1575 && !(ioc_raw_state & MPI_DOORBELL_ACTIVE)) {
1576
1577 /* Isse the Task Mgmt request.
1578 */
1579 if (hd->hard_resets < -1)
1580 hd->hard_resets++;
1581 rc = mptscsih_IssueTaskMgmt(hd, type, channel, target, lun, ctx2abort, timeout);
1582 if (rc) {
1583 printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n", hd->ioc->name);
1584 } else {
1585 dtmprintk((MYIOC_s_INFO_FMT "Issue of TaskMgmt Successful!\n", hd->ioc->name));
1586 }
1587 }
1588
1589 /* Only fall through to the HRH if this is a bus reset
1590 */
1591 if ((type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) && (rc ||
1592 ioc->reload_fw || (ioc->alt_ioc && ioc->alt_ioc->reload_fw))) {
1593 dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
1594 hd->ioc->name));
1595 rc = mpt_HardResetHandler(hd->ioc, CAN_SLEEP);
1596 }
1597
1598 dtmprintk((MYIOC_s_INFO_FMT "TMHandler rc = %d!\n", hd->ioc->name, rc));
1599
1600 return rc;
1601}
1602
1603
1604/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1605/*
1606 * mptscsih_IssueTaskMgmt - Generic send Task Management function.
1607 * @hd: Pointer to MPT_SCSI_HOST structure
1608 * @type: Task Management type
1609 * @target: Logical Target ID for reset (if appropriate)
1610 * @lun: Logical Unit for reset (if appropriate)
1611 * @ctx2abort: Context for the task to be aborted (if appropriate)
1612 *
1613 * Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
1614 * or a non-interrupt thread. In the former, must not call schedule().
1615 *
1616 * Not all fields are meaningfull for all task types.
1617 *
1618 * Returns 0 for SUCCESS, -999 for "no msg frames",
1619 * else other non-zero value returned.
1620 */
1621static int
1622mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout)
1623{
1624 MPT_FRAME_HDR *mf;
1625 SCSITaskMgmt_t *pScsiTm;
1626 int ii;
1627 int retval;
1628
1629 /* Return Fail to calling function if no message frames available.
1630 */
0d0c7974 1631 if ((mf = mpt_get_msg_frame(hd->ioc->TaskCtx, hd->ioc)) == NULL) {
1da177e4
LT
1632 dfailprintk((MYIOC_s_ERR_FMT "IssueTaskMgmt, no msg frames!!\n",
1633 hd->ioc->name));
1634 //return FAILED;
1635 return -999;
1636 }
1637 dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt request @ %p\n",
1638 hd->ioc->name, mf));
1639
1640 /* Format the Request
1641 */
1642 pScsiTm = (SCSITaskMgmt_t *) mf;
1643 pScsiTm->TargetID = target;
1644 pScsiTm->Bus = channel;
1645 pScsiTm->ChainOffset = 0;
1646 pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
1647
1648 pScsiTm->Reserved = 0;
1649 pScsiTm->TaskType = type;
1650 pScsiTm->Reserved1 = 0;
1651 pScsiTm->MsgFlags = (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS)
1652 ? MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION : 0;
1653
1654 for (ii= 0; ii < 8; ii++) {
1655 pScsiTm->LUN[ii] = 0;
1656 }
1657 pScsiTm->LUN[1] = lun;
1658
1659 for (ii=0; ii < 7; ii++)
1660 pScsiTm->Reserved2[ii] = 0;
1661
1662 pScsiTm->TaskMsgContext = ctx2abort;
1663
1664 dtmprintk((MYIOC_s_INFO_FMT
1665 "IssueTaskMgmt: ctx2abort (0x%08x) type=%d\n",
1666 hd->ioc->name, ctx2abort, type));
1667
1668 DBG_DUMP_TM_REQUEST_FRAME((u32 *)pScsiTm);
1669
0d0c7974 1670 if ((retval = mpt_send_handshake_request(hd->ioc->TaskCtx, hd->ioc,
1da177e4
LT
1671 sizeof(SCSITaskMgmt_t), (u32*)pScsiTm,
1672 CAN_SLEEP)) != 0) {
1673 dfailprintk((MYIOC_s_ERR_FMT "_send_handshake FAILED!"
1674 " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd,
1675 hd->ioc, mf));
1676 mpt_free_msg_frame(hd->ioc, mf);
1677 return retval;
1678 }
1679
1680 if(mptscsih_tm_wait_for_completion(hd, timeout) == FAILED) {
1681 dfailprintk((MYIOC_s_ERR_FMT "_wait_for_completion FAILED!"
1682 " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd,
1683 hd->ioc, mf));
1684 mpt_free_msg_frame(hd->ioc, mf);
1685 dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
1686 hd->ioc->name));
1687 retval = mpt_HardResetHandler(hd->ioc, CAN_SLEEP);
1688 }
1689
1690 return retval;
1691}
1692
1693/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1694/**
1695 * mptscsih_abort - Abort linux scsi_cmnd routine, new_eh variant
1696 * @SCpnt: Pointer to scsi_cmnd structure, IO to be aborted
1697 *
1698 * (linux scsi_host_template.eh_abort_handler routine)
1699 *
1700 * Returns SUCCESS or FAILED.
1701 */
0d0c7974 1702int
1da177e4
LT
1703mptscsih_abort(struct scsi_cmnd * SCpnt)
1704{
1705 MPT_SCSI_HOST *hd;
1706 MPT_ADAPTER *ioc;
1707 MPT_FRAME_HDR *mf;
1708 u32 ctx2abort;
1709 int scpnt_idx;
1da177e4
LT
1710
1711 /* If we can't locate our host adapter structure, return FAILED status.
1712 */
1713 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL) {
1714 SCpnt->result = DID_RESET << 16;
1715 SCpnt->scsi_done(SCpnt);
1716 dfailprintk((KERN_WARNING MYNAM ": mptscsih_abort: "
1717 "Can't locate host! (sc=%p)\n",
1718 SCpnt));
1719 return FAILED;
1720 }
1721
1722 ioc = hd->ioc;
1723 if (hd->resetPending)
1724 return FAILED;
1725
1726 printk(KERN_WARNING MYNAM ": %s: >> Attempting task abort! (sc=%p)\n",
1727 hd->ioc->name, SCpnt);
1728
1729 if (hd->timeouts < -1)
1730 hd->timeouts++;
1731
1732 /* Find this command
1733 */
1734 if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) {
1735 /* Cmd not found in ScsiLookup.
1736 * Do OS callback.
1737 */
1738 SCpnt->result = DID_RESET << 16;
1739 dtmprintk((KERN_WARNING MYNAM ": %s: mptscsih_abort: "
1740 "Command not in the active list! (sc=%p)\n",
1741 hd->ioc->name, SCpnt));
1742 return SUCCESS;
1743 }
1744
1745 /* Most important! Set TaskMsgContext to SCpnt's MsgContext!
1746 * (the IO to be ABORT'd)
1747 *
1748 * NOTE: Since we do not byteswap MsgContext, we do not
1749 * swap it here either. It is an opaque cookie to
1750 * the controller, so it does not matter. -DaveM
1751 */
1752 mf = MPT_INDEX_2_MFPTR(hd->ioc, scpnt_idx);
1753 ctx2abort = mf->u.frame.hwhdr.msgctxu.MsgContext;
1754
1755 hd->abortSCpnt = SCpnt;
1756
1da177e4
LT
1757 if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
1758 SCpnt->device->channel, SCpnt->device->id, SCpnt->device->lun,
1759 ctx2abort, 2 /* 2 second timeout */)
1760 < 0) {
1761
1762 /* The TM request failed and the subsequent FW-reload failed!
1763 * Fatal error case.
1764 */
1765 printk(MYIOC_s_WARN_FMT "Error issuing abort task! (sc=%p)\n",
1766 hd->ioc->name, SCpnt);
1767
1768 /* We must clear our pending flag before clearing our state.
1769 */
1770 hd->tmPending = 0;
1771 hd->tmState = TM_STATE_NONE;
1772
1da177e4
LT
1773 /* Unmap the DMA buffers, if any. */
1774 if (SCpnt->use_sg) {
1775 pci_unmap_sg(ioc->pcidev, (struct scatterlist *) SCpnt->request_buffer,
1776 SCpnt->use_sg, SCpnt->sc_data_direction);
1777 } else if (SCpnt->request_bufflen) {
1778 pci_unmap_single(ioc->pcidev, SCpnt->SCp.dma_handle,
1779 SCpnt->request_bufflen, SCpnt->sc_data_direction);
1780 }
1781 hd->ScsiLookup[scpnt_idx] = NULL;
1782 SCpnt->result = DID_RESET << 16;
1783 SCpnt->scsi_done(SCpnt); /* Issue the command callback */
1784 mptscsih_freeChainBuffers(ioc, scpnt_idx);
1785 mpt_free_msg_frame(ioc, mf);
1786 return FAILED;
1787 }
1da177e4
LT
1788 return SUCCESS;
1789}
1790
1791/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1792/**
1793 * mptscsih_dev_reset - Perform a SCSI TARGET_RESET! new_eh variant
1794 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1795 *
1796 * (linux scsi_host_template.eh_dev_reset_handler routine)
1797 *
1798 * Returns SUCCESS or FAILED.
1799 */
0d0c7974 1800int
1da177e4
LT
1801mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
1802{
1803 MPT_SCSI_HOST *hd;
1804 spinlock_t *host_lock = SCpnt->device->host->host_lock;
1805
1806 /* If we can't locate our host adapter structure, return FAILED status.
1807 */
1808 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
1809 dtmprintk((KERN_WARNING MYNAM ": mptscsih_dev_reset: "
1810 "Can't locate host! (sc=%p)\n",
1811 SCpnt));
1812 return FAILED;
1813 }
1814
1815 if (hd->resetPending)
1816 return FAILED;
1817
1818 printk(KERN_WARNING MYNAM ": %s: >> Attempting target reset! (sc=%p)\n",
1819 hd->ioc->name, SCpnt);
1820
1821 spin_unlock_irq(host_lock);
1822 if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
1823 SCpnt->device->channel, SCpnt->device->id,
1824 0, 0, 5 /* 5 second timeout */)
1825 < 0){
1826 /* The TM request failed and the subsequent FW-reload failed!
1827 * Fatal error case.
1828 */
1829 printk(MYIOC_s_WARN_FMT "Error processing TaskMgmt request (sc=%p)\n",
1830 hd->ioc->name, SCpnt);
1831 hd->tmPending = 0;
1832 hd->tmState = TM_STATE_NONE;
1833 spin_lock_irq(host_lock);
1834 return FAILED;
1835 }
1836 spin_lock_irq(host_lock);
1837 return SUCCESS;
1838
1839}
1840
1841/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1842/**
1843 * mptscsih_bus_reset - Perform a SCSI BUS_RESET! new_eh variant
1844 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1845 *
1846 * (linux scsi_host_template.eh_bus_reset_handler routine)
1847 *
1848 * Returns SUCCESS or FAILED.
1849 */
0d0c7974 1850int
1da177e4
LT
1851mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
1852{
1853 MPT_SCSI_HOST *hd;
1854 spinlock_t *host_lock = SCpnt->device->host->host_lock;
1855
1856 /* If we can't locate our host adapter structure, return FAILED status.
1857 */
1858 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
1859 dtmprintk((KERN_WARNING MYNAM ": mptscsih_bus_reset: "
1860 "Can't locate host! (sc=%p)\n",
1861 SCpnt ) );
1862 return FAILED;
1863 }
1864
1865 printk(KERN_WARNING MYNAM ": %s: >> Attempting bus reset! (sc=%p)\n",
1866 hd->ioc->name, SCpnt);
1867
1868 if (hd->timeouts < -1)
1869 hd->timeouts++;
1870
1871 /* We are now ready to execute the task management request. */
1872 spin_unlock_irq(host_lock);
1873 if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
1874 SCpnt->device->channel, 0, 0, 0, 5 /* 5 second timeout */)
1875 < 0){
1876
1877 /* The TM request failed and the subsequent FW-reload failed!
1878 * Fatal error case.
1879 */
1880 printk(MYIOC_s_WARN_FMT
1881 "Error processing TaskMgmt request (sc=%p)\n",
1882 hd->ioc->name, SCpnt);
1883 hd->tmPending = 0;
1884 hd->tmState = TM_STATE_NONE;
1885 spin_lock_irq(host_lock);
1886 return FAILED;
1887 }
1888 spin_lock_irq(host_lock);
1889 return SUCCESS;
1890}
1891
1892/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1893/**
1894 * mptscsih_host_reset - Perform a SCSI host adapter RESET!
1895 * new_eh variant
1896 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1897 *
1898 * (linux scsi_host_template.eh_host_reset_handler routine)
1899 *
1900 * Returns SUCCESS or FAILED.
1901 */
0d0c7974 1902int
1da177e4
LT
1903mptscsih_host_reset(struct scsi_cmnd *SCpnt)
1904{
1905 MPT_SCSI_HOST * hd;
1906 int status = SUCCESS;
1907 spinlock_t *host_lock = SCpnt->device->host->host_lock;
1908
1909 /* If we can't locate the host to reset, then we failed. */
1910 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
1911 dtmprintk( ( KERN_WARNING MYNAM ": mptscsih_host_reset: "
1912 "Can't locate host! (sc=%p)\n",
1913 SCpnt ) );
1914 return FAILED;
1915 }
1916
1917 printk(KERN_WARNING MYNAM ": %s: >> Attempting host reset! (sc=%p)\n",
1918 hd->ioc->name, SCpnt);
1919
1920 /* If our attempts to reset the host failed, then return a failed
1921 * status. The host will be taken off line by the SCSI mid-layer.
1922 */
1923 spin_unlock_irq(host_lock);
1924 if (mpt_HardResetHandler(hd->ioc, CAN_SLEEP) < 0){
1925 status = FAILED;
1926 } else {
1927 /* Make sure TM pending is cleared and TM state is set to
1928 * NONE.
1929 */
1930 hd->tmPending = 0;
1931 hd->tmState = TM_STATE_NONE;
1932 }
1933 spin_lock_irq(host_lock);
1934
1935
1936 dtmprintk( ( KERN_WARNING MYNAM ": mptscsih_host_reset: "
1937 "Status = %s\n",
1938 (status == SUCCESS) ? "SUCCESS" : "FAILED" ) );
1939
1940 return status;
1941}
1942
1943/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1944/**
1945 * mptscsih_tm_pending_wait - wait for pending task management request to
1946 * complete.
1947 * @hd: Pointer to MPT host structure.
1948 *
1949 * Returns {SUCCESS,FAILED}.
1950 */
1951static int
1952mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd)
1953{
1954 unsigned long flags;
1955 int loop_count = 4 * 10; /* Wait 10 seconds */
1956 int status = FAILED;
1957
1958 do {
1959 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
1960 if (hd->tmState == TM_STATE_NONE) {
1961 hd->tmState = TM_STATE_IN_PROGRESS;
1962 hd->tmPending = 1;
1963 status = SUCCESS;
1964 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
1965 break;
1966 }
1967 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
1968 msleep(250);
1969 } while (--loop_count);
1970
1971 return status;
1972}
1973
1974/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1975/**
1976 * mptscsih_tm_wait_for_completion - wait for completion of TM task
1977 * @hd: Pointer to MPT host structure.
1978 *
1979 * Returns {SUCCESS,FAILED}.
1980 */
1981static int
1982mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout )
1983{
1984 unsigned long flags;
1985 int loop_count = 4 * timeout;
1986 int status = FAILED;
1987
1988 do {
1989 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
1990 if(hd->tmPending == 0) {
1991 status = SUCCESS;
1992 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
1993 break;
1994 }
1995 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
1996 msleep_interruptible(250);
1997 } while (--loop_count);
1998
1999 return status;
2000}
2001
2002/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2003/**
2004 * mptscsih_taskmgmt_complete - Registered with Fusion MPT base driver
2005 * @ioc: Pointer to MPT_ADAPTER structure
2006 * @mf: Pointer to SCSI task mgmt request frame
2007 * @mr: Pointer to SCSI task mgmt reply frame
2008 *
2009 * This routine is called from mptbase.c::mpt_interrupt() at the completion
2010 * of any SCSI task management request.
2011 * This routine is registered with the MPT (base) driver at driver
2012 * load/init time via the mpt_register() API call.
2013 *
2014 * Returns 1 indicating alloc'd request frame ptr should be freed.
2015 */
0d0c7974 2016int
1da177e4
LT
2017mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
2018{
2019 SCSITaskMgmtReply_t *pScsiTmReply;
2020 SCSITaskMgmt_t *pScsiTmReq;
2021 MPT_SCSI_HOST *hd;
2022 unsigned long flags;
2023 u16 iocstatus;
2024 u8 tmType;
2025
2026 dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt completed (mf=%p,mr=%p)\n",
2027 ioc->name, mf, mr));
2028 if (ioc->sh) {
2029 /* Depending on the thread, a timer is activated for
2030 * the TM request. Delete this timer on completion of TM.
2031 * Decrement count of outstanding TM requests.
2032 */
2033 hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
2034 } else {
2035 dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt Complete: NULL Scsi Host Ptr\n",
2036 ioc->name));
2037 return 1;
2038 }
2039
2040 if (mr == NULL) {
2041 dtmprintk((MYIOC_s_WARN_FMT "ERROR! TaskMgmt Reply: NULL Request %p\n",
2042 ioc->name, mf));
2043 return 1;
2044 } else {
2045 pScsiTmReply = (SCSITaskMgmtReply_t*)mr;
2046 pScsiTmReq = (SCSITaskMgmt_t*)mf;
2047
2048 /* Figure out if this was ABORT_TASK, TARGET_RESET, or BUS_RESET! */
2049 tmType = pScsiTmReq->TaskType;
2050
2051 dtmprintk((MYIOC_s_WARN_FMT " TaskType = %d, TerminationCount=%d\n",
2052 ioc->name, tmType, le32_to_cpu(pScsiTmReply->TerminationCount)));
2053 DBG_DUMP_TM_REPLY_FRAME((u32 *)pScsiTmReply);
2054
2055 iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
2056 dtmprintk((MYIOC_s_WARN_FMT " SCSI TaskMgmt (%d) IOCStatus=%04x IOCLogInfo=%08x\n",
2057 ioc->name, tmType, iocstatus, le32_to_cpu(pScsiTmReply->IOCLogInfo)));
2058 /* Error? (anything non-zero?) */
2059 if (iocstatus) {
2060
2061 /* clear flags and continue.
2062 */
2063 if (tmType == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK)
2064 hd->abortSCpnt = NULL;
2065
2066 /* If an internal command is present
2067 * or the TM failed - reload the FW.
2068 * FC FW may respond FAILED to an ABORT
2069 */
2070 if (tmType == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
2071 if ((hd->cmdPtr) ||
2072 (iocstatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED)) {
2073 if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0) {
2074 printk((KERN_WARNING
2075 " Firmware Reload FAILED!!\n"));
2076 }
2077 }
2078 }
2079 } else {
2080 dtmprintk((MYIOC_s_WARN_FMT " TaskMgmt SUCCESS\n", ioc->name));
2081
2082 hd->abortSCpnt = NULL;
2083
2084 }
2085 }
2086
2087 spin_lock_irqsave(&ioc->FreeQlock, flags);
2088 hd->tmPending = 0;
2089 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
2090 hd->tmState = TM_STATE_NONE;
2091
2092 return 1;
2093}
2094
2095/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2096/*
2097 * This is anyones guess quite frankly.
2098 */
0d0c7974 2099int
1da177e4
LT
2100mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev,
2101 sector_t capacity, int geom[])
2102{
2103 int heads;
2104 int sectors;
2105 sector_t cylinders;
2106 ulong dummy;
2107
2108 heads = 64;
2109 sectors = 32;
2110
2111 dummy = heads * sectors;
2112 cylinders = capacity;
2113 sector_div(cylinders,dummy);
2114
2115 /*
2116 * Handle extended translation size for logical drives
2117 * > 1Gb
2118 */
2119 if ((ulong)capacity >= 0x200000) {
2120 heads = 255;
2121 sectors = 63;
2122 dummy = heads * sectors;
2123 cylinders = capacity;
2124 sector_div(cylinders,dummy);
2125 }
2126
2127 /* return result */
2128 geom[0] = heads;
2129 geom[1] = sectors;
2130 geom[2] = cylinders;
2131
2132 dprintk((KERN_NOTICE
2133 ": bios_param: Id=%i Lun=%i Channel=%i CHS=%i/%i/%i\n",
2134 sdev->id, sdev->lun,sdev->channel,(int)cylinders,heads,sectors));
2135
2136 return 0;
2137}
2138
2139/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2140/*
2141 * OS entry point to allow host driver to alloc memory
2142 * for each scsi device. Called once per device the bus scan.
2143 * Return non-zero if allocation fails.
2144 * Init memory once per id (not LUN).
2145 */
0d0c7974 2146int
1da177e4
LT
2147mptscsih_slave_alloc(struct scsi_device *device)
2148{
2149 struct Scsi_Host *host = device->host;
2150 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
2151 VirtDevice *vdev;
2152 uint target = device->id;
2153
2154 if (hd == NULL)
2155 return -ENODEV;
2156
2157 if ((vdev = hd->Targets[target]) != NULL)
2158 goto out;
2159
2160 vdev = kmalloc(sizeof(VirtDevice), GFP_KERNEL);
2161 if (!vdev) {
2162 printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
2163 hd->ioc->name, sizeof(VirtDevice));
2164 return -ENOMEM;
2165 }
2166
2167 memset(vdev, 0, sizeof(VirtDevice));
2168 vdev->tflags = MPT_TARGET_FLAGS_Q_YES;
2169 vdev->ioc_id = hd->ioc->id;
2170 vdev->target_id = device->id;
2171 vdev->bus_id = device->channel;
2172 vdev->raidVolume = 0;
2173 hd->Targets[device->id] = vdev;
2174 if (hd->ioc->bus_type == SCSI) {
2175 if (hd->ioc->spi_data.isRaid & (1 << device->id)) {
2176 vdev->raidVolume = 1;
2177 ddvtprintk((KERN_INFO
2178 "RAID Volume @ id %d\n", device->id));
2179 }
2180 } else {
2181 vdev->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
2182 }
2183
2184 out:
2185 vdev->num_luns++;
2186 return 0;
2187}
2188
0d0c7974
MED
2189static int
2190mptscsih_is_raid_volume(MPT_SCSI_HOST *hd, uint id)
1da177e4
LT
2191{
2192 int i;
2193
2194 if (!hd->ioc->spi_data.isRaid || !hd->ioc->spi_data.pIocPg3)
2195 return 0;
2196
2197 for (i = 0; i < hd->ioc->spi_data.pIocPg3->NumPhysDisks; i++) {
2198 if (id == hd->ioc->spi_data.pIocPg3->PhysDisk[i].PhysDiskID)
2199 return 1;
2200 }
2201
2202 return 0;
2203}
2204
2205/*
2206 * OS entry point to allow for host driver to free allocated memory
2207 * Called if no device present or device being unloaded
2208 */
0d0c7974 2209void
1da177e4
LT
2210mptscsih_slave_destroy(struct scsi_device *device)
2211{
2212 struct Scsi_Host *host = device->host;
2213 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
2214 VirtDevice *vdev;
2215 uint target = device->id;
2216 uint lun = device->lun;
2217
2218 if (hd == NULL)
2219 return;
2220
2221 mptscsih_search_running_cmds(hd, target, lun);
2222
2223 vdev = hd->Targets[target];
2224 vdev->luns[0] &= ~(1 << lun);
2225 if (--vdev->num_luns)
2226 return;
2227
2228 kfree(hd->Targets[target]);
2229 hd->Targets[target] = NULL;
0d0c7974 2230
1da177e4
LT
2231 if (hd->ioc->bus_type == SCSI) {
2232 if (mptscsih_is_raid_volume(hd, target)) {
2233 hd->ioc->spi_data.forceDv |= MPT_SCSICFG_RELOAD_IOC_PG3;
2234 } else {
2235 hd->ioc->spi_data.dvStatus[target] =
2236 MPT_SCSICFG_NEGOTIATE;
2237
2238 if (!hd->negoNvram) {
2239 hd->ioc->spi_data.dvStatus[target] |=
2240 MPT_SCSICFG_DV_NOT_DONE;
2241 }
2242 }
2243 }
2244}
2245
2246static void
2247mptscsih_set_queue_depth(struct scsi_device *device, MPT_SCSI_HOST *hd,
2248 VirtDevice *pTarget, int qdepth)
2249{
2250 int max_depth;
2251 int tagged;
2252
2253 if (hd->ioc->bus_type == SCSI) {
2254 if (pTarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) {
2255 if (!(pTarget->tflags & MPT_TARGET_FLAGS_Q_YES))
2256 max_depth = 1;
2257 else if (((pTarget->inq_data[0] & 0x1f) == 0x00) &&
2258 (pTarget->minSyncFactor <= MPT_ULTRA160 ))
2259 max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
2260 else
2261 max_depth = MPT_SCSI_CMD_PER_DEV_LOW;
2262 } else {
2263 /* error case - No Inq. Data */
2264 max_depth = 1;
2265 }
2266 } else
2267 max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
2268
2269 if (qdepth > max_depth)
2270 qdepth = max_depth;
2271 if (qdepth == 1)
2272 tagged = 0;
2273 else
2274 tagged = MSG_SIMPLE_TAG;
2275
2276 scsi_adjust_queue_depth(device, tagged, qdepth);
2277}
2278
2279
2280/*
2281 * OS entry point to adjust the queue_depths on a per-device basis.
2282 * Called once per device the bus scan. Use it to force the queue_depth
2283 * member to 1 if a device does not support Q tags.
2284 * Return non-zero if fails.
2285 */
0d0c7974 2286int
1da177e4
LT
2287mptscsih_slave_configure(struct scsi_device *device)
2288{
2289 struct Scsi_Host *sh = device->host;
2290 VirtDevice *pTarget;
2291 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sh->hostdata;
2292
2293 if ((hd == NULL) || (hd->Targets == NULL)) {
2294 return 0;
2295 }
2296
2297 dsprintk((MYIOC_s_INFO_FMT
2298 "device @ %p, id=%d, LUN=%d, channel=%d\n",
2299 hd->ioc->name, device, device->id, device->lun, device->channel));
2300 dsprintk((MYIOC_s_INFO_FMT
2301 "sdtr %d wdtr %d ppr %d inq length=%d\n",
2302 hd->ioc->name, device->sdtr, device->wdtr,
2303 device->ppr, device->inquiry_len));
2304
2305 if (device->id > sh->max_id) {
2306 /* error case, should never happen */
2307 scsi_adjust_queue_depth(device, 0, 1);
2308 goto slave_configure_exit;
2309 }
2310
2311 pTarget = hd->Targets[device->id];
2312
2313 if (pTarget == NULL) {
2314 /* Driver doesn't know about this device.
2315 * Kernel may generate a "Dummy Lun 0" which
2316 * may become a real Lun if a
2317 * "scsi add-single-device" command is executed
2318 * while the driver is active (hot-plug a
2319 * device). LSI Raid controllers need
2320 * queue_depth set to DEV_HIGH for this reason.
2321 */
2322 scsi_adjust_queue_depth(device, MSG_SIMPLE_TAG,
2323 MPT_SCSI_CMD_PER_DEV_HIGH);
2324 goto slave_configure_exit;
2325 }
2326
2327 mptscsih_initTarget(hd, device->channel, device->id, device->lun,
2328 device->inquiry, device->inquiry_len );
2329 mptscsih_set_queue_depth(device, hd, pTarget, MPT_SCSI_CMD_PER_DEV_HIGH);
2330
2331 dsprintk((MYIOC_s_INFO_FMT
2332 "Queue depth=%d, tflags=%x\n",
2333 hd->ioc->name, device->queue_depth, pTarget->tflags));
2334
2335 dsprintk((MYIOC_s_INFO_FMT
2336 "negoFlags=%x, maxOffset=%x, SyncFactor=%x\n",
2337 hd->ioc->name, pTarget->negoFlags, pTarget->maxOffset, pTarget->minSyncFactor));
2338
2339slave_configure_exit:
2340
2341 dsprintk((MYIOC_s_INFO_FMT
2342 "tagged %d, simple %d, ordered %d\n",
2343 hd->ioc->name,device->tagged_supported, device->simple_tags,
2344 device->ordered_tags));
2345
2346 return 0;
2347}
2348
0d0c7974 2349ssize_t
1da177e4
LT
2350mptscsih_store_queue_depth(struct device *dev, const char *buf, size_t count)
2351{
2352 int depth;
2353 struct scsi_device *sdev = to_scsi_device(dev);
2354 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) sdev->host->hostdata;
2355 VirtDevice *pTarget;
2356
2357 depth = simple_strtoul(buf, NULL, 0);
2358 if (depth == 0)
2359 return -EINVAL;
2360 pTarget = hd->Targets[sdev->id];
2361 if (pTarget == NULL)
2362 return -EINVAL;
2363 mptscsih_set_queue_depth(sdev, (MPT_SCSI_HOST *) sdev->host->hostdata,
2364 pTarget, depth);
2365 return count;
2366}
2367
2368/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2369/*
2370 * Private routines...
2371 */
2372
2373/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2374/* Utility function to copy sense data from the scsi_cmnd buffer
2375 * to the FC and SCSI target structures.
2376 *
2377 */
2378static void
0d0c7974 2379mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply)
1da177e4
LT
2380{
2381 VirtDevice *target;
2382 SCSIIORequest_t *pReq;
2383 u32 sense_count = le32_to_cpu(pScsiReply->SenseCount);
2384 int index;
2385
2386 /* Get target structure
2387 */
2388 pReq = (SCSIIORequest_t *) mf;
2389 index = (int) pReq->TargetID;
2390 target = hd->Targets[index];
2391
2392 if (sense_count) {
2393 u8 *sense_data;
2394 int req_index;
2395
2396 /* Copy the sense received into the scsi command block. */
2397 req_index = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
2398 sense_data = ((u8 *)hd->ioc->sense_buf_pool + (req_index * MPT_SENSE_BUFFER_ALLOC));
2399 memcpy(sc->sense_buffer, sense_data, SNS_LEN(sc));
2400
2401 /* Log SMART data (asc = 0x5D, non-IM case only) if required.
2402 */
2403 if ((hd->ioc->events) && (hd->ioc->eventTypes & (1 << MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE))) {
2404 if ((sense_data[12] == 0x5D) && (target->raidVolume == 0)) {
2405 int idx;
2406 MPT_ADAPTER *ioc = hd->ioc;
2407
2408 idx = ioc->eventContext % ioc->eventLogSize;
2409 ioc->events[idx].event = MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE;
2410 ioc->events[idx].eventContext = ioc->eventContext;
2411
2412 ioc->events[idx].data[0] = (pReq->LUN[1] << 24) ||
2413 (MPI_EVENT_SCSI_DEV_STAT_RC_SMART_DATA << 16) ||
2414 (pReq->Bus << 8) || pReq->TargetID;
2415
2416 ioc->events[idx].data[1] = (sense_data[13] << 8) || sense_data[12];
2417
2418 ioc->eventContext++;
2419 }
2420 }
2421 } else {
2422 dprintk((MYIOC_s_INFO_FMT "Hmmm... SenseData len=0! (?)\n",
2423 hd->ioc->name));
2424 }
2425}
2426
2427static u32
2428SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc)
2429{
2430 MPT_SCSI_HOST *hd;
2431 int i;
2432
2433 hd = (MPT_SCSI_HOST *) sc->device->host->hostdata;
2434
2435 for (i = 0; i < hd->ioc->req_depth; i++) {
2436 if (hd->ScsiLookup[i] == sc) {
2437 return i;
2438 }
2439 }
2440
2441 return -1;
2442}
2443
2444/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
0d0c7974 2445int
1da177e4
LT
2446mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
2447{
2448 MPT_SCSI_HOST *hd;
2449 unsigned long flags;
2450
2451 dtmprintk((KERN_WARNING MYNAM
2452 ": IOC %s_reset routed to SCSI host driver!\n",
2453 reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
2454 reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
2455
2456 /* If a FW reload request arrives after base installed but
2457 * before all scsi hosts have been attached, then an alt_ioc
2458 * may have a NULL sh pointer.
2459 */
2460 if ((ioc->sh == NULL) || (ioc->sh->hostdata == NULL))
2461 return 0;
2462 else
2463 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
2464
2465 if (reset_phase == MPT_IOC_SETUP_RESET) {
2466 dtmprintk((MYIOC_s_WARN_FMT "Setup-Diag Reset\n", ioc->name));
2467
2468 /* Clean Up:
2469 * 1. Set Hard Reset Pending Flag
2470 * All new commands go to doneQ
2471 */
2472 hd->resetPending = 1;
2473
2474 } else if (reset_phase == MPT_IOC_PRE_RESET) {
2475 dtmprintk((MYIOC_s_WARN_FMT "Pre-Diag Reset\n", ioc->name));
2476
2477 /* 2. Flush running commands
2478 * Clean ScsiLookup (and associated memory)
2479 * AND clean mytaskQ
2480 */
2481
2482 /* 2b. Reply to OS all known outstanding I/O commands.
2483 */
2484 mptscsih_flush_running_cmds(hd);
2485
2486 /* 2c. If there was an internal command that
2487 * has not completed, configuration or io request,
2488 * free these resources.
2489 */
2490 if (hd->cmdPtr) {
2491 del_timer(&hd->timer);
2492 mpt_free_msg_frame(ioc, hd->cmdPtr);
2493 }
2494
2495 dtmprintk((MYIOC_s_WARN_FMT "Pre-Reset complete.\n", ioc->name));
2496
2497 } else {
2498 dtmprintk((MYIOC_s_WARN_FMT "Post-Diag Reset\n", ioc->name));
2499
2500 /* Once a FW reload begins, all new OS commands are
2501 * redirected to the doneQ w/ a reset status.
2502 * Init all control structures.
2503 */
2504
2505 /* ScsiLookup initialization
2506 */
2507 {
2508 int ii;
2509 for (ii=0; ii < hd->ioc->req_depth; ii++)
2510 hd->ScsiLookup[ii] = NULL;
2511 }
2512
2513 /* 2. Chain Buffer initialization
2514 */
2515
2516 /* 4. Renegotiate to all devices, if SCSI
2517 */
2518 if (ioc->bus_type == SCSI) {
2519 dnegoprintk(("writeSDP1: ALL_IDS USE_NVRAM\n"));
2520 mptscsih_writeSDP1(hd, 0, 0, MPT_SCSICFG_ALL_IDS | MPT_SCSICFG_USE_NVRAM);
2521 }
2522
2523 /* 5. Enable new commands to be posted
2524 */
2525 spin_lock_irqsave(&ioc->FreeQlock, flags);
2526 hd->tmPending = 0;
2527 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
2528 hd->resetPending = 0;
2529 hd->tmState = TM_STATE_NONE;
2530
2531 /* 6. If there was an internal command,
2532 * wake this process up.
2533 */
2534 if (hd->cmdPtr) {
2535 /*
2536 * Wake up the original calling thread
2537 */
2538 hd->pLocal = &hd->localReply;
2539 hd->pLocal->completion = MPT_SCANDV_DID_RESET;
0d0c7974
MED
2540 hd->scandv_wait_done = 1;
2541 wake_up(&hd->scandv_waitq);
1da177e4
LT
2542 hd->cmdPtr = NULL;
2543 }
2544
2545 /* 7. Set flag to force DV and re-read IOC Page 3
2546 */
2547 if (ioc->bus_type == SCSI) {
2548 ioc->spi_data.forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3;
2549 ddvtprintk(("Set reload IOC Pg3 Flag\n"));
2550 }
2551
2552 dtmprintk((MYIOC_s_WARN_FMT "Post-Reset complete.\n", ioc->name));
2553
2554 }
2555
2556 return 1; /* currently means nothing really */
2557}
2558
2559/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
0d0c7974 2560int
1da177e4
LT
2561mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
2562{
2563 MPT_SCSI_HOST *hd;
2564 u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
2565
2566 devtprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
2567 ioc->name, event));
2568
2569 switch (event) {
2570 case MPI_EVENT_UNIT_ATTENTION: /* 03 */
2571 /* FIXME! */
2572 break;
2573 case MPI_EVENT_IOC_BUS_RESET: /* 04 */
2574 case MPI_EVENT_EXT_BUS_RESET: /* 05 */
2575 hd = NULL;
2576 if (ioc->sh) {
2577 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
2578 if (hd && (ioc->bus_type == SCSI) && (hd->soft_resets < -1))
2579 hd->soft_resets++;
2580 }
2581 break;
2582 case MPI_EVENT_LOGOUT: /* 09 */
2583 /* FIXME! */
2584 break;
2585
2586 /*
2587 * CHECKME! Don't think we need to do
2588 * anything for these, but...
2589 */
2590 case MPI_EVENT_RESCAN: /* 06 */
2591 case MPI_EVENT_LINK_STATUS_CHANGE: /* 07 */
2592 case MPI_EVENT_LOOP_STATE_CHANGE: /* 08 */
2593 /*
2594 * CHECKME! Falling thru...
2595 */
2596 break;
2597
2598 case MPI_EVENT_INTEGRATED_RAID: /* 0B */
2599#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
2600 /* negoNvram set to 0 if DV enabled and to USE_NVRAM if
2601 * if DV disabled. Need to check for target mode.
2602 */
2603 hd = NULL;
2604 if (ioc->sh)
2605 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
2606
2607 if (hd && (ioc->bus_type == SCSI) && (hd->negoNvram == 0)) {
2608 ScsiCfgData *pSpi;
2609 Ioc3PhysDisk_t *pPDisk;
2610 int numPDisk;
2611 u8 reason;
2612 u8 physDiskNum;
2613
2614 reason = (le32_to_cpu(pEvReply->Data[0]) & 0x00FF0000) >> 16;
2615 if (reason == MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) {
2616 /* New or replaced disk.
2617 * Set DV flag and schedule DV.
2618 */
2619 pSpi = &ioc->spi_data;
2620 physDiskNum = (le32_to_cpu(pEvReply->Data[0]) & 0xFF000000) >> 24;
2621 ddvtprintk(("DV requested for phys disk id %d\n", physDiskNum));
2622 if (pSpi->pIocPg3) {
2623 pPDisk = pSpi->pIocPg3->PhysDisk;
2624 numPDisk =pSpi->pIocPg3->NumPhysDisks;
2625
2626 while (numPDisk) {
2627 if (physDiskNum == pPDisk->PhysDiskNum) {
2628 pSpi->dvStatus[pPDisk->PhysDiskID] = (MPT_SCSICFG_NEED_DV | MPT_SCSICFG_DV_NOT_DONE);
2629 pSpi->forceDv = MPT_SCSICFG_NEED_DV;
2630 ddvtprintk(("NEED_DV set for phys disk id %d\n", pPDisk->PhysDiskID));
2631 break;
2632 }
2633 pPDisk++;
2634 numPDisk--;
2635 }
2636
2637 if (numPDisk == 0) {
2638 /* The physical disk that needs DV was not found
2639 * in the stored IOC Page 3. The driver must reload
2640 * this page. DV routine will set the NEED_DV flag for
2641 * all phys disks that have DV_NOT_DONE set.
2642 */
2643 pSpi->forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3;
2644 ddvtprintk(("phys disk %d not found. Setting reload IOC Pg3 Flag\n", physDiskNum));
2645 }
2646 }
2647 }
2648 }
2649#endif
2650
2651#if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY)
2652 printk("Raid Event RF: ");
2653 {
2654 u32 *m = (u32 *)pEvReply;
2655 int ii;
2656 int n = (int)pEvReply->MsgLength;
2657 for (ii=6; ii < n; ii++)
2658 printk(" %08x", le32_to_cpu(m[ii]));
2659 printk("\n");
2660 }
2661#endif
2662 break;
2663
2664 case MPI_EVENT_NONE: /* 00 */
2665 case MPI_EVENT_LOG_DATA: /* 01 */
2666 case MPI_EVENT_STATE_CHANGE: /* 02 */
2667 case MPI_EVENT_EVENT_CHANGE: /* 0A */
2668 default:
2669 dprintk((KERN_INFO " Ignoring event (=%02Xh)\n", event));
2670 break;
2671 }
2672
2673 return 1; /* currently means nothing really */
2674}
2675
1da177e4
LT
2676/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2677/*
2678 * mptscsih_initTarget - Target, LUN alloc/free functionality.
2679 * @hd: Pointer to MPT_SCSI_HOST structure
2680 * @bus_id: Bus number (?)
2681 * @target_id: SCSI target id
2682 * @lun: SCSI LUN id
2683 * @data: Pointer to data
2684 * @dlen: Number of INQUIRY bytes
2685 *
2686 * NOTE: It's only SAFE to call this routine if data points to
2687 * sane & valid STANDARD INQUIRY data!
2688 *
2689 * Allocate and initialize memory for this target.
2690 * Save inquiry data.
2691 *
2692 */
2693static void
2694mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *data, int dlen)
2695{
2696 int indexed_lun, lun_index;
2697 VirtDevice *vdev;
2698 ScsiCfgData *pSpi;
2699 char data_56;
2700
2701 dinitprintk((MYIOC_s_INFO_FMT "initTarget bus=%d id=%d lun=%d hd=%p\n",
2702 hd->ioc->name, bus_id, target_id, lun, hd));
2703
2704 /*
2705 * If the peripheral qualifier filter is enabled then if the target reports a 0x1
2706 * (i.e. The targer is capable of supporting the specified peripheral device type
2707 * on this logical unit; however, the physical device is not currently connected
2708 * to this logical unit) it will be converted to a 0x3 (i.e. The target is not
2709 * capable of supporting a physical device on this logical unit). This is to work
2710 * around a bug in th emid-layer in some distributions in which the mid-layer will
2711 * continue to try to communicate to the LUN and evntually create a dummy LUN.
2712 */
0d0c7974 2713 if (hd->mpt_pq_filter && dlen && (data[0] & 0xE0))
1da177e4 2714 data[0] |= 0x40;
0d0c7974 2715
1da177e4
LT
2716 /* Is LUN supported? If so, upper 2 bits will be 0
2717 * in first byte of inquiry data.
2718 */
2719 if (data[0] & 0xe0)
2720 return;
2721
2722 if ((vdev = hd->Targets[target_id]) == NULL) {
2723 return;
2724 }
2725
2726 lun_index = (lun >> 5); /* 32 luns per lun_index */
2727 indexed_lun = (lun % 32);
2728 vdev->luns[lun_index] |= (1 << indexed_lun);
2729
2730 if (hd->ioc->bus_type == SCSI) {
2731 if ((data[0] == TYPE_PROCESSOR) && (hd->ioc->spi_data.Saf_Te)) {
2732 /* Treat all Processors as SAF-TE if
2733 * command line option is set */
2734 vdev->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
2735 mptscsih_writeIOCPage4(hd, target_id, bus_id);
2736 }else if ((data[0] == TYPE_PROCESSOR) &&
2737 !(vdev->tflags & MPT_TARGET_FLAGS_SAF_TE_ISSUED )) {
2738 if ( dlen > 49 ) {
2739 vdev->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
2740 if ( data[44] == 'S' &&
2741 data[45] == 'A' &&
2742 data[46] == 'F' &&
2743 data[47] == '-' &&
2744 data[48] == 'T' &&
2745 data[49] == 'E' ) {
2746 vdev->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
2747 mptscsih_writeIOCPage4(hd, target_id, bus_id);
2748 }
2749 }
2750 }
2751 if (!(vdev->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY)) {
2752 if ( dlen > 8 ) {
2753 memcpy (vdev->inq_data, data, 8);
2754 } else {
2755 memcpy (vdev->inq_data, data, dlen);
2756 }
2757
2758 /* If have not done DV, set the DV flag.
2759 */
2760 pSpi = &hd->ioc->spi_data;
2761 if ((data[0] == TYPE_TAPE) || (data[0] == TYPE_PROCESSOR)) {
2762 if (pSpi->dvStatus[target_id] & MPT_SCSICFG_DV_NOT_DONE)
2763 pSpi->dvStatus[target_id] |= MPT_SCSICFG_NEED_DV;
2764 }
2765
2766 vdev->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
2767
2768
2769 data_56 = 0x0F; /* Default to full capabilities if Inq data length is < 57 */
2770 if (dlen > 56) {
2771 if ( (!(vdev->tflags & MPT_TARGET_FLAGS_VALID_56))) {
2772 /* Update the target capabilities
2773 */
2774 data_56 = data[56];
2775 vdev->tflags |= MPT_TARGET_FLAGS_VALID_56;
2776 }
2777 }
2778 mptscsih_setTargetNegoParms(hd, vdev, data_56);
2779 } else {
2780 /* Initial Inquiry may not request enough data bytes to
2781 * obtain byte 57. DV will; if target doesn't return
2782 * at least 57 bytes, data[56] will be zero. */
2783 if (dlen > 56) {
2784 if ( (!(vdev->tflags & MPT_TARGET_FLAGS_VALID_56))) {
2785 /* Update the target capabilities
2786 */
2787 data_56 = data[56];
2788 vdev->tflags |= MPT_TARGET_FLAGS_VALID_56;
2789 mptscsih_setTargetNegoParms(hd, vdev, data_56);
2790 }
2791 }
2792 }
2793 }
2794}
2795
2796/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2797/*
2798 * Update the target negotiation parameters based on the
2799 * the Inquiry data, adapter capabilities, and NVRAM settings.
2800 *
2801 */
2802static void
2803mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56)
2804{
2805 ScsiCfgData *pspi_data = &hd->ioc->spi_data;
2806 int id = (int) target->target_id;
2807 int nvram;
2808 VirtDevice *vdev;
2809 int ii;
2810 u8 width = MPT_NARROW;
2811 u8 factor = MPT_ASYNC;
2812 u8 offset = 0;
2813 u8 version, nfactor;
2814 u8 noQas = 1;
2815
2816 target->negoFlags = pspi_data->noQas;
2817
2818 /* noQas == 0 => device supports QAS. Need byte 56 of Inq to determine
2819 * support. If available, default QAS to off and allow enabling.
2820 * If not available, default QAS to on, turn off for non-disks.
2821 */
2822
2823 /* Set flags based on Inquiry data
2824 */
2825 version = target->inq_data[2] & 0x07;
2826 if (version < 2) {
2827 width = 0;
2828 factor = MPT_ULTRA2;
2829 offset = pspi_data->maxSyncOffset;
2830 target->tflags &= ~MPT_TARGET_FLAGS_Q_YES;
2831 } else {
2832 if (target->inq_data[7] & 0x20) {
2833 width = 1;
2834 }
2835
2836 if (target->inq_data[7] & 0x10) {
2837 factor = pspi_data->minSyncFactor;
2838 if (target->tflags & MPT_TARGET_FLAGS_VALID_56) {
2839 /* bits 2 & 3 show Clocking support */
2840 if ((byte56 & 0x0C) == 0)
2841 factor = MPT_ULTRA2;
2842 else {
2843 if ((byte56 & 0x03) == 0)
2844 factor = MPT_ULTRA160;
2845 else {
2846 factor = MPT_ULTRA320;
2847 if (byte56 & 0x02)
2848 {
2849 ddvtprintk((KERN_INFO "Enabling QAS due to byte56=%02x on id=%d!\n", byte56, id));
2850 noQas = 0;
2851 }
2852 if (target->inq_data[0] == TYPE_TAPE) {
2853 if (byte56 & 0x01)
2854 target->negoFlags |= MPT_TAPE_NEGO_IDP;
2855 }
2856 }
2857 }
2858 } else {
2859 ddvtprintk((KERN_INFO "Enabling QAS on id=%d due to ~TARGET_FLAGS_VALID_56!\n", id));
2860 noQas = 0;
2861 }
0d0c7974 2862
1da177e4
LT
2863 offset = pspi_data->maxSyncOffset;
2864
2865 /* If RAID, never disable QAS
2866 * else if non RAID, do not disable
2867 * QAS if bit 1 is set
2868 * bit 1 QAS support, non-raid only
2869 * bit 0 IU support
2870 */
2871 if (target->raidVolume == 1) {
2872 noQas = 0;
2873 }
2874 } else {
2875 factor = MPT_ASYNC;
2876 offset = 0;
2877 }
2878 }
2879
2880 if ( (target->inq_data[7] & 0x02) == 0) {
2881 target->tflags &= ~MPT_TARGET_FLAGS_Q_YES;
2882 }
2883
2884 /* Update tflags based on NVRAM settings. (SCSI only)
2885 */
2886 if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) {
2887 nvram = pspi_data->nvram[id];
2888 nfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8;
2889
2890 if (width)
2891 width = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
2892
2893 if (offset > 0) {
2894 /* Ensure factor is set to the
2895 * maximum of: adapter, nvram, inquiry
2896 */
2897 if (nfactor) {
2898 if (nfactor < pspi_data->minSyncFactor )
2899 nfactor = pspi_data->minSyncFactor;
2900
2901 factor = max(factor, nfactor);
2902 if (factor == MPT_ASYNC)
2903 offset = 0;
2904 } else {
2905 offset = 0;
2906 factor = MPT_ASYNC;
2907 }
2908 } else {
2909 factor = MPT_ASYNC;
2910 }
2911 }
2912
2913 /* Make sure data is consistent
2914 */
2915 if ((!width) && (factor < MPT_ULTRA2)) {
2916 factor = MPT_ULTRA2;
2917 }
2918
2919 /* Save the data to the target structure.
2920 */
2921 target->minSyncFactor = factor;
2922 target->maxOffset = offset;
2923 target->maxWidth = width;
2924
2925 target->tflags |= MPT_TARGET_FLAGS_VALID_NEGO;
2926
2927 /* Disable unused features.
2928 */
2929 if (!width)
2930 target->negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
2931
2932 if (!offset)
2933 target->negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
2934
2935 if ( factor > MPT_ULTRA320 )
2936 noQas = 0;
2937
2938 /* GEM, processor WORKAROUND
2939 */
2940 if ((target->inq_data[0] == TYPE_PROCESSOR) || (target->inq_data[0] > 0x08)) {
2941 target->negoFlags |= (MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC);
2942 pspi_data->dvStatus[id] |= MPT_SCSICFG_BLK_NEGO;
2943 } else {
2944 if (noQas && (pspi_data->noQas == 0)) {
2945 pspi_data->noQas |= MPT_TARGET_NO_NEGO_QAS;
2946 target->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
2947
2948 /* Disable QAS in a mixed configuration case
2949 */
2950
2951 ddvtprintk((KERN_INFO "Disabling QAS due to noQas=%02x on id=%d!\n", noQas, id));
2952 for (ii = 0; ii < id; ii++) {
2953 if ( (vdev = hd->Targets[ii]) ) {
2954 vdev->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
2955 mptscsih_writeSDP1(hd, 0, ii, vdev->negoFlags);
0d0c7974 2956 }
1da177e4
LT
2957 }
2958 }
2959 }
2960
2961 /* Write SDP1 on this I/O to this target */
2962 if (pspi_data->dvStatus[id] & MPT_SCSICFG_NEGOTIATE) {
2963 ddvtprintk((KERN_INFO "MPT_SCSICFG_NEGOTIATE on id=%d!\n", id));
2964 mptscsih_writeSDP1(hd, 0, id, hd->negoNvram);
2965 pspi_data->dvStatus[id] &= ~MPT_SCSICFG_NEGOTIATE;
2966 } else if (pspi_data->dvStatus[id] & MPT_SCSICFG_BLK_NEGO) {
2967 ddvtprintk((KERN_INFO "MPT_SCSICFG_BLK_NEGO on id=%d!\n", id));
2968 mptscsih_writeSDP1(hd, 0, id, MPT_SCSICFG_BLK_NEGO);
2969 pspi_data->dvStatus[id] &= ~MPT_SCSICFG_BLK_NEGO;
2970 }
2971}
2972
2973/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2974/* If DV disabled (negoNvram set to USE_NVARM) or if not LUN 0, return.
2975 * Else set the NEED_DV flag after Read Capacity Issued (disks)
2976 * or Mode Sense (cdroms).
2977 *
2978 * Tapes, initTarget will set this flag on completion of Inquiry command.
2979 * Called only if DV_NOT_DONE flag is set
2980 */
0d0c7974
MED
2981static void
2982mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq)
1da177e4
LT
2983{
2984 u8 cmd;
2985 ScsiCfgData *pSpi;
2986
2987 ddvtprintk((" set_dvflags: id=%d lun=%d negoNvram=%x cmd=%x\n",
2988 pReq->TargetID, pReq->LUN[1], hd->negoNvram, pReq->CDB[0]));
0d0c7974 2989
1da177e4
LT
2990 if ((pReq->LUN[1] != 0) || (hd->negoNvram != 0))
2991 return;
2992
2993 cmd = pReq->CDB[0];
2994
2995 if ((cmd == READ_CAPACITY) || (cmd == MODE_SENSE)) {
2996 pSpi = &hd->ioc->spi_data;
2997 if ((pSpi->isRaid & (1 << pReq->TargetID)) && pSpi->pIocPg3) {
2998 /* Set NEED_DV for all hidden disks
2999 */
3000 Ioc3PhysDisk_t *pPDisk = pSpi->pIocPg3->PhysDisk;
3001 int numPDisk = pSpi->pIocPg3->NumPhysDisks;
3002
3003 while (numPDisk) {
3004 pSpi->dvStatus[pPDisk->PhysDiskID] |= MPT_SCSICFG_NEED_DV;
3005 ddvtprintk(("NEED_DV set for phys disk id %d\n", pPDisk->PhysDiskID));
3006 pPDisk++;
3007 numPDisk--;
3008 }
3009 }
3010 pSpi->dvStatus[pReq->TargetID] |= MPT_SCSICFG_NEED_DV;
3011 ddvtprintk(("NEED_DV set for visible disk id %d\n", pReq->TargetID));
3012 }
3013}
3014
3015/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3016/*
3017 * If no Target, bus reset on 1st I/O. Set the flag to
3018 * prevent any future negotiations to this device.
3019 */
0d0c7974
MED
3020static void
3021mptscsih_no_negotiate(MPT_SCSI_HOST *hd, int target_id)
1da177e4
LT
3022{
3023
3024 if ((hd->Targets) && (hd->Targets[target_id] == NULL))
3025 hd->ioc->spi_data.dvStatus[target_id] |= MPT_SCSICFG_BLK_NEGO;
3026
3027 return;
3028}
3029
3030/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3031/*
3032 * SCSI Config Page functionality ...
3033 */
3034/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3035/* mptscsih_setDevicePage1Flags - add Requested and Configuration fields flags
3036 * based on width, factor and offset parameters.
3037 * @width: bus width
3038 * @factor: sync factor
3039 * @offset: sync offset
3040 * @requestedPtr: pointer to requested values (updated)
3041 * @configurationPtr: pointer to configuration values (updated)
3042 * @flags: flags to block WDTR or SDTR negotiation
3043 *
3044 * Return: None.
3045 *
3046 * Remark: Called by writeSDP1 and _dv_params
3047 */
3048static void
3049mptscsih_setDevicePage1Flags (u8 width, u8 factor, u8 offset, int *requestedPtr, int *configurationPtr, u8 flags)
3050{
3051 u8 nowide = flags & MPT_TARGET_NO_NEGO_WIDE;
3052 u8 nosync = flags & MPT_TARGET_NO_NEGO_SYNC;
3053
3054 *configurationPtr = 0;
3055 *requestedPtr = width ? MPI_SCSIDEVPAGE1_RP_WIDE : 0;
3056 *requestedPtr |= (offset << 16) | (factor << 8);
3057
3058 if (width && offset && !nowide && !nosync) {
3059 if (factor < MPT_ULTRA160) {
3060 *requestedPtr |= (MPI_SCSIDEVPAGE1_RP_IU + MPI_SCSIDEVPAGE1_RP_DT);
3061 if ((flags & MPT_TARGET_NO_NEGO_QAS) == 0)
3062 *requestedPtr |= MPI_SCSIDEVPAGE1_RP_QAS;
3063 if (flags & MPT_TAPE_NEGO_IDP)
3064 *requestedPtr |= 0x08000000;
3065 } else if (factor < MPT_ULTRA2) {
3066 *requestedPtr |= MPI_SCSIDEVPAGE1_RP_DT;
3067 }
3068 }
3069
3070 if (nowide)
3071 *configurationPtr |= MPI_SCSIDEVPAGE1_CONF_WDTR_DISALLOWED;
3072
3073 if (nosync)
3074 *configurationPtr |= MPI_SCSIDEVPAGE1_CONF_SDTR_DISALLOWED;
3075
3076 return;
3077}
3078
3079/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3080/* mptscsih_writeSDP1 - write SCSI Device Page 1
3081 * @hd: Pointer to a SCSI Host Strucutre
3082 * @portnum: IOC port number
3083 * @target_id: writeSDP1 for single ID
3084 * @flags: MPT_SCSICFG_ALL_IDS, MPT_SCSICFG_USE_NVRAM, MPT_SCSICFG_BLK_NEGO
3085 *
3086 * Return: -EFAULT if read of config page header fails
3087 * or 0 if success.
3088 *
3089 * Remark: If a target has been found, the settings from the
3090 * target structure are used, else the device is set
3091 * to async/narrow.
3092 *
3093 * Remark: Called during init and after a FW reload.
3094 * Remark: We do not wait for a return, write pages sequentially.
3095 */
3096static int
3097mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target_id, int flags)
3098{
3099 MPT_ADAPTER *ioc = hd->ioc;
3100 Config_t *pReq;
3101 SCSIDevicePage1_t *pData;
3102 VirtDevice *pTarget;
3103 MPT_FRAME_HDR *mf;
3104 dma_addr_t dataDma;
3105 u16 req_idx;
3106 u32 frameOffset;
3107 u32 requested, configuration, flagsLength;
3108 int ii, nvram;
3109 int id = 0, maxid = 0;
3110 u8 width;
3111 u8 factor;
3112 u8 offset;
3113 u8 bus = 0;
3114 u8 negoFlags;
3115 u8 maxwidth, maxoffset, maxfactor;
3116
3117 if (ioc->spi_data.sdp1length == 0)
3118 return 0;
3119
3120 if (flags & MPT_SCSICFG_ALL_IDS) {
3121 id = 0;
3122 maxid = ioc->sh->max_id - 1;
3123 } else if (ioc->sh) {
3124 id = target_id;
3125 maxid = min_t(int, id, ioc->sh->max_id - 1);
3126 }
3127
3128 for (; id <= maxid; id++) {
3129
3130 if (id == ioc->pfacts[portnum].PortSCSIID)
3131 continue;
3132
3133 /* Use NVRAM to get adapter and target maximums
3134 * Data over-riden by target structure information, if present
3135 */
3136 maxwidth = ioc->spi_data.maxBusWidth;
3137 maxoffset = ioc->spi_data.maxSyncOffset;
3138 maxfactor = ioc->spi_data.minSyncFactor;
3139 if (ioc->spi_data.nvram && (ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
3140 nvram = ioc->spi_data.nvram[id];
3141
3142 if (maxwidth)
3143 maxwidth = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
3144
3145 if (maxoffset > 0) {
3146 maxfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8;
3147 if (maxfactor == 0) {
3148 /* Key for async */
3149 maxfactor = MPT_ASYNC;
3150 maxoffset = 0;
3151 } else if (maxfactor < ioc->spi_data.minSyncFactor) {
3152 maxfactor = ioc->spi_data.minSyncFactor;
3153 }
3154 } else
3155 maxfactor = MPT_ASYNC;
3156 }
3157
3158 /* Set the negotiation flags.
3159 */
3160 negoFlags = ioc->spi_data.noQas;
3161 if (!maxwidth)
3162 negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
3163
3164 if (!maxoffset)
3165 negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
3166
3167 if (flags & MPT_SCSICFG_USE_NVRAM) {
3168 width = maxwidth;
3169 factor = maxfactor;
3170 offset = maxoffset;
3171 } else {
3172 width = 0;
3173 factor = MPT_ASYNC;
3174 offset = 0;
3175 //negoFlags = 0;
3176 //negoFlags = MPT_TARGET_NO_NEGO_SYNC;
3177 }
3178
3179 /* If id is not a raid volume, get the updated
3180 * transmission settings from the target structure.
3181 */
3182 if (hd->Targets && (pTarget = hd->Targets[id]) && !pTarget->raidVolume) {
3183 width = pTarget->maxWidth;
3184 factor = pTarget->minSyncFactor;
3185 offset = pTarget->maxOffset;
3186 negoFlags = pTarget->negoFlags;
3187 }
0d0c7974 3188
1da177e4
LT
3189#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
3190 /* Force to async and narrow if DV has not been executed
3191 * for this ID
3192 */
3193 if ((hd->ioc->spi_data.dvStatus[id] & MPT_SCSICFG_DV_NOT_DONE) != 0) {
3194 width = 0;
3195 factor = MPT_ASYNC;
3196 offset = 0;
3197 }
3198#endif
3199
3200 if (flags & MPT_SCSICFG_BLK_NEGO)
3201 negoFlags = MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC;
3202
3203 mptscsih_setDevicePage1Flags(width, factor, offset,
3204 &requested, &configuration, negoFlags);
3205 dnegoprintk(("writeSDP1: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n",
3206 target_id, width, factor, offset, negoFlags, requested, configuration));
3207
3208 /* Get a MF for this command.
3209 */
0d0c7974 3210 if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) {
1da177e4
LT
3211 dprintk((MYIOC_s_WARN_FMT "write SDP1: no msg frames!\n",
3212 ioc->name));
3213 return -EAGAIN;
3214 }
3215
3216 ddvprintk((MYIOC_s_INFO_FMT "WriteSDP1 (mf=%p, id=%d, req=0x%x, cfg=0x%x)\n",
3217 hd->ioc->name, mf, id, requested, configuration));
3218
3219
3220 /* Set the request and the data pointers.
3221 * Request takes: 36 bytes (32 bit SGE)
3222 * SCSI Device Page 1 requires 16 bytes
3223 * 40 + 16 <= size of SCSI IO Request = 56 bytes
3224 * and MF size >= 64 bytes.
3225 * Place data at end of MF.
3226 */
3227 pReq = (Config_t *)mf;
3228
3229 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
3230 frameOffset = ioc->req_sz - sizeof(SCSIDevicePage1_t);
3231
3232 pData = (SCSIDevicePage1_t *)((u8 *) mf + frameOffset);
3233 dataDma = ioc->req_frames_dma + (req_idx * ioc->req_sz) + frameOffset;
3234
3235 /* Complete the request frame (same for all requests).
3236 */
3237 pReq->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
3238 pReq->Reserved = 0;
3239 pReq->ChainOffset = 0;
3240 pReq->Function = MPI_FUNCTION_CONFIG;
3241 pReq->ExtPageLength = 0;
3242 pReq->ExtPageType = 0;
3243 pReq->MsgFlags = 0;
3244 for (ii=0; ii < 8; ii++) {
3245 pReq->Reserved2[ii] = 0;
3246 }
3247 pReq->Header.PageVersion = ioc->spi_data.sdp1version;
3248 pReq->Header.PageLength = ioc->spi_data.sdp1length;
3249 pReq->Header.PageNumber = 1;
3250 pReq->Header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
3251 pReq->PageAddress = cpu_to_le32(id | (bus << 8 ));
3252
3253 /* Add a SGE to the config request.
3254 */
3255 flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE | ioc->spi_data.sdp1length * 4;
3256
3257 mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma);
3258
3259 /* Set up the common data portion
3260 */
3261 pData->Header.PageVersion = pReq->Header.PageVersion;
3262 pData->Header.PageLength = pReq->Header.PageLength;
3263 pData->Header.PageNumber = pReq->Header.PageNumber;
3264 pData->Header.PageType = pReq->Header.PageType;
3265 pData->RequestedParameters = cpu_to_le32(requested);
3266 pData->Reserved = 0;
3267 pData->Configuration = cpu_to_le32(configuration);
3268
3269 dprintk((MYIOC_s_INFO_FMT
3270 "write SDP1: id %d pgaddr 0x%x req 0x%x config 0x%x\n",
3271 ioc->name, id, (id | (bus<<8)),
3272 requested, configuration));
3273
0d0c7974 3274 mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
1da177e4
LT
3275 }
3276
3277 return 0;
3278}
3279
3280/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3281/* mptscsih_writeIOCPage4 - write IOC Page 4
3282 * @hd: Pointer to a SCSI Host Structure
3283 * @target_id: write IOC Page4 for this ID & Bus
3284 *
3285 * Return: -EAGAIN if unable to obtain a Message Frame
3286 * or 0 if success.
3287 *
3288 * Remark: We do not wait for a return, write pages sequentially.
3289 */
3290static int
3291mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus)
3292{
3293 MPT_ADAPTER *ioc = hd->ioc;
3294 Config_t *pReq;
3295 IOCPage4_t *IOCPage4Ptr;
3296 MPT_FRAME_HDR *mf;
3297 dma_addr_t dataDma;
3298 u16 req_idx;
3299 u32 frameOffset;
3300 u32 flagsLength;
3301 int ii;
3302
3303 /* Get a MF for this command.
3304 */
0d0c7974 3305 if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) {
1da177e4
LT
3306 dprintk((MYIOC_s_WARN_FMT "writeIOCPage4 : no msg frames!\n",
3307 ioc->name));
3308 return -EAGAIN;
3309 }
3310
3311 /* Set the request and the data pointers.
3312 * Place data at end of MF.
3313 */
3314 pReq = (Config_t *)mf;
3315
3316 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
3317 frameOffset = ioc->req_sz - sizeof(IOCPage4_t);
3318
3319 /* Complete the request frame (same for all requests).
3320 */
3321 pReq->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
3322 pReq->Reserved = 0;
3323 pReq->ChainOffset = 0;
3324 pReq->Function = MPI_FUNCTION_CONFIG;
3325 pReq->ExtPageLength = 0;
3326 pReq->ExtPageType = 0;
3327 pReq->MsgFlags = 0;
3328 for (ii=0; ii < 8; ii++) {
3329 pReq->Reserved2[ii] = 0;
3330 }
3331
3332 IOCPage4Ptr = ioc->spi_data.pIocPg4;
3333 dataDma = ioc->spi_data.IocPg4_dma;
3334 ii = IOCPage4Ptr->ActiveSEP++;
3335 IOCPage4Ptr->SEP[ii].SEPTargetID = target_id;
3336 IOCPage4Ptr->SEP[ii].SEPBus = bus;
3337 pReq->Header = IOCPage4Ptr->Header;
3338 pReq->PageAddress = cpu_to_le32(target_id | (bus << 8 ));
3339
3340 /* Add a SGE to the config request.
3341 */
3342 flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE |
3343 (IOCPage4Ptr->Header.PageLength + ii) * 4;
3344
3345 mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma);
3346
3347 dinitprintk((MYIOC_s_INFO_FMT
3348 "writeIOCPage4: MaxSEP=%d ActiveSEP=%d id=%d bus=%d\n",
3349 ioc->name, IOCPage4Ptr->MaxSEP, IOCPage4Ptr->ActiveSEP, target_id, bus));
3350
0d0c7974 3351 mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
1da177e4
LT
3352
3353 return 0;
3354}
3355
3356/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3357/*
3358 * Bus Scan and Domain Validation functionality ...
3359 */
3360
3361/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3362/*
3363 * mptscsih_scandv_complete - Scan and DV callback routine registered
3364 * to Fustion MPT (base) driver.
3365 *
3366 * @ioc: Pointer to MPT_ADAPTER structure
3367 * @mf: Pointer to original MPT request frame
3368 * @mr: Pointer to MPT reply frame (NULL if TurboReply)
3369 *
3370 * This routine is called from mpt.c::mpt_interrupt() at the completion
3371 * of any SCSI IO request.
3372 * This routine is registered with the Fusion MPT (base) driver at driver
3373 * load/init time via the mpt_register() API call.
3374 *
3375 * Returns 1 indicating alloc'd request frame ptr should be freed.
3376 *
3377 * Remark: Sets a completion code and (possibly) saves sense data
3378 * in the IOC member localReply structure.
3379 * Used ONLY for DV and other internal commands.
3380 */
0d0c7974 3381int
1da177e4
LT
3382mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
3383{
3384 MPT_SCSI_HOST *hd;
3385 SCSIIORequest_t *pReq;
3386 int completionCode;
3387 u16 req_idx;
3388
0d0c7974
MED
3389 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
3390
1da177e4
LT
3391 if ((mf == NULL) ||
3392 (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) {
3393 printk(MYIOC_s_ERR_FMT
3394 "ScanDvComplete, %s req frame ptr! (=%p)\n",
3395 ioc->name, mf?"BAD":"NULL", (void *) mf);
3396 goto wakeup;
3397 }
3398
1da177e4
LT
3399 del_timer(&hd->timer);
3400 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
3401 hd->ScsiLookup[req_idx] = NULL;
3402 pReq = (SCSIIORequest_t *) mf;
3403
3404 if (mf != hd->cmdPtr) {
3405 printk(MYIOC_s_WARN_FMT "ScanDvComplete (mf=%p, cmdPtr=%p, idx=%d)\n",
3406 hd->ioc->name, (void *)mf, (void *) hd->cmdPtr, req_idx);
3407 }
3408 hd->cmdPtr = NULL;
3409
3410 ddvprintk((MYIOC_s_INFO_FMT "ScanDvComplete (mf=%p,mr=%p,idx=%d)\n",
3411 hd->ioc->name, mf, mr, req_idx));
3412
3413 hd->pLocal = &hd->localReply;
3414 hd->pLocal->scsiStatus = 0;
3415
3416 /* If target struct exists, clear sense valid flag.
3417 */
3418 if (mr == NULL) {
3419 completionCode = MPT_SCANDV_GOOD;
3420 } else {
3421 SCSIIOReply_t *pReply;
3422 u16 status;
3423 u8 scsi_status;
3424
3425 pReply = (SCSIIOReply_t *) mr;
3426
3427 status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
3428 scsi_status = pReply->SCSIStatus;
3429
3430 ddvtprintk((KERN_NOTICE " IOCStatus=%04xh, SCSIState=%02xh, SCSIStatus=%02xh, IOCLogInfo=%08xh\n",
3431 status, pReply->SCSIState, scsi_status,
3432 le32_to_cpu(pReply->IOCLogInfo)));
3433
3434 switch(status) {
3435
3436 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
3437 completionCode = MPT_SCANDV_SELECTION_TIMEOUT;
3438 break;
3439
3440 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
3441 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
3442 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
3443 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
3444 completionCode = MPT_SCANDV_DID_RESET;
3445 break;
3446
3447 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
3448 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
3449 case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */
3450 if (pReply->Function == MPI_FUNCTION_CONFIG) {
3451 ConfigReply_t *pr = (ConfigReply_t *)mr;
3452 completionCode = MPT_SCANDV_GOOD;
3453 hd->pLocal->header.PageVersion = pr->Header.PageVersion;
3454 hd->pLocal->header.PageLength = pr->Header.PageLength;
3455 hd->pLocal->header.PageNumber = pr->Header.PageNumber;
3456 hd->pLocal->header.PageType = pr->Header.PageType;
3457
3458 } else if (pReply->Function == MPI_FUNCTION_RAID_ACTION) {
3459 /* If the RAID Volume request is successful,
3460 * return GOOD, else indicate that
3461 * some type of error occurred.
3462 */
3463 MpiRaidActionReply_t *pr = (MpiRaidActionReply_t *)mr;
3464 if (pr->ActionStatus == MPI_RAID_ACTION_ASTATUS_SUCCESS)
3465 completionCode = MPT_SCANDV_GOOD;
3466 else
3467 completionCode = MPT_SCANDV_SOME_ERROR;
3468
3469 } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) {
3470 u8 *sense_data;
3471 int sz;
3472
3473 /* save sense data in global structure
3474 */
3475 completionCode = MPT_SCANDV_SENSE;
3476 hd->pLocal->scsiStatus = scsi_status;
3477 sense_data = ((u8 *)hd->ioc->sense_buf_pool +
3478 (req_idx * MPT_SENSE_BUFFER_ALLOC));
3479
3480 sz = min_t(int, pReq->SenseBufferLength,
3481 SCSI_STD_SENSE_BYTES);
3482 memcpy(hd->pLocal->sense, sense_data, sz);
3483
3484 ddvprintk((KERN_NOTICE " Check Condition, sense ptr %p\n",
3485 sense_data));
3486 } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_FAILED) {
3487 if (pReq->CDB[0] == INQUIRY)
3488 completionCode = MPT_SCANDV_ISSUE_SENSE;
3489 else
3490 completionCode = MPT_SCANDV_DID_RESET;
3491 }
3492 else if (pReply->SCSIState & MPI_SCSI_STATE_NO_SCSI_STATUS)
3493 completionCode = MPT_SCANDV_DID_RESET;
3494 else if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
3495 completionCode = MPT_SCANDV_DID_RESET;
3496 else {
3497 completionCode = MPT_SCANDV_GOOD;
3498 hd->pLocal->scsiStatus = scsi_status;
3499 }
3500 break;
3501
3502 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
3503 if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
3504 completionCode = MPT_SCANDV_DID_RESET;
3505 else
3506 completionCode = MPT_SCANDV_SOME_ERROR;
3507 break;
3508
3509 default:
3510 completionCode = MPT_SCANDV_SOME_ERROR;
3511 break;
3512
3513 } /* switch(status) */
3514
3515 ddvtprintk((KERN_NOTICE " completionCode set to %08xh\n",
3516 completionCode));
3517 } /* end of address reply case */
3518
3519 hd->pLocal->completion = completionCode;
3520
3521 /* MF and RF are freed in mpt_interrupt
3522 */
3523wakeup:
3524 /* Free Chain buffers (will never chain) in scan or dv */
3525 //mptscsih_freeChainBuffers(ioc, req_idx);
3526
3527 /*
3528 * Wake up the original calling thread
3529 */
0d0c7974
MED
3530 hd->scandv_wait_done = 1;
3531 wake_up(&hd->scandv_waitq);
1da177e4
LT
3532
3533 return 1;
3534}
3535
3536/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3537/* mptscsih_timer_expired - Call back for timer process.
3538 * Used only for dv functionality.
3539 * @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
3540 *
3541 */
0d0c7974
MED
3542void
3543mptscsih_timer_expired(unsigned long data)
1da177e4
LT
3544{
3545 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) data;
3546
3547 ddvprintk((MYIOC_s_WARN_FMT "Timer Expired! Cmd %p\n", hd->ioc->name, hd->cmdPtr));
3548
3549 if (hd->cmdPtr) {
3550 MPIHeader_t *cmd = (MPIHeader_t *)hd->cmdPtr;
3551
3552 if (cmd->Function == MPI_FUNCTION_SCSI_IO_REQUEST) {
3553 /* Desire to issue a task management request here.
3554 * TM requests MUST be single threaded.
3555 * If old eh code and no TM current, issue request.
3556 * If new eh code, do nothing. Wait for OS cmd timeout
3557 * for bus reset.
3558 */
3559 ddvtprintk((MYIOC_s_NOTE_FMT "DV Cmd Timeout: NoOp\n", hd->ioc->name));
3560 } else {
3561 /* Perform a FW reload */
3562 if (mpt_HardResetHandler(hd->ioc, NO_SLEEP) < 0) {
3563 printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", hd->ioc->name);
3564 }
3565 }
3566 } else {
3567 /* This should NEVER happen */
3568 printk(MYIOC_s_WARN_FMT "Null cmdPtr!!!!\n", hd->ioc->name);
3569 }
3570
3571 /* No more processing.
3572 * TM call will generate an interrupt for SCSI TM Management.
3573 * The FW will reply to all outstanding commands, callback will finish cleanup.
3574 * Hard reset clean-up will free all resources.
3575 */
3576 ddvprintk((MYIOC_s_WARN_FMT "Timer Expired Complete!\n", hd->ioc->name));
3577
3578 return;
3579}
3580
3581#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
3582/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3583/* mptscsih_do_raid - Format and Issue a RAID volume request message.
3584 * @hd: Pointer to scsi host structure
3585 * @action: What do be done.
3586 * @id: Logical target id.
3587 * @bus: Target locations bus.
3588 *
3589 * Returns: < 0 on a fatal error
3590 * 0 on success
3591 *
3592 * Remark: Wait to return until reply processed by the ISR.
3593 */
3594static int
3595mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io)
3596{
3597 MpiRaidActionRequest_t *pReq;
3598 MPT_FRAME_HDR *mf;
3599 int in_isr;
3600
3601 in_isr = in_interrupt();
3602 if (in_isr) {
3603 dprintk((MYIOC_s_WARN_FMT "Internal raid request not allowed in ISR context!\n",
3604 hd->ioc->name));
3605 return -EPERM;
3606 }
3607
3608 /* Get and Populate a free Frame
3609 */
0d0c7974 3610 if ((mf = mpt_get_msg_frame(hd->ioc->InternalCtx, hd->ioc)) == NULL) {
1da177e4
LT
3611 ddvprintk((MYIOC_s_WARN_FMT "_do_raid: no msg frames!\n",
3612 hd->ioc->name));
3613 return -EAGAIN;
3614 }
3615 pReq = (MpiRaidActionRequest_t *)mf;
3616 pReq->Action = action;
3617 pReq->Reserved1 = 0;
3618 pReq->ChainOffset = 0;
3619 pReq->Function = MPI_FUNCTION_RAID_ACTION;
3620 pReq->VolumeID = io->id;
3621 pReq->VolumeBus = io->bus;
3622 pReq->PhysDiskNum = io->physDiskNum;
3623 pReq->MsgFlags = 0;
3624 pReq->Reserved2 = 0;
3625 pReq->ActionDataWord = 0; /* Reserved for this action */
3626 //pReq->ActionDataSGE = 0;
3627
3628 mpt_add_sge((char *)&pReq->ActionDataSGE,
3629 MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1);
3630
3631 ddvprintk((MYIOC_s_INFO_FMT "RAID Volume action %x id %d\n",
3632 hd->ioc->name, action, io->id));
3633
3634 hd->pLocal = NULL;
3635 hd->timer.expires = jiffies + HZ*10; /* 10 second timeout */
0d0c7974 3636 hd->scandv_wait_done = 0;
1da177e4
LT
3637
3638 /* Save cmd pointer, for resource free if timeout or
3639 * FW reload occurs
3640 */
3641 hd->cmdPtr = mf;
3642
3643 add_timer(&hd->timer);
0d0c7974
MED
3644 mpt_put_msg_frame(hd->ioc->InternalCtx, hd->ioc, mf);
3645 wait_event(hd->scandv_waitq, hd->scandv_wait_done);
1da177e4
LT
3646
3647 if ((hd->pLocal == NULL) || (hd->pLocal->completion != MPT_SCANDV_GOOD))
3648 return -1;
3649
3650 return 0;
3651}
3652#endif /* ~MPTSCSIH_ENABLE_DOMAIN_VALIDATION */
3653
3654/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3655/**
3656 * mptscsih_do_cmd - Do internal command.
3657 * @hd: MPT_SCSI_HOST pointer
3658 * @io: INTERNAL_CMD pointer.
3659 *
3660 * Issue the specified internally generated command and do command
3661 * specific cleanup. For bus scan / DV only.
3662 * NOTES: If command is Inquiry and status is good,
3663 * initialize a target structure, save the data
3664 *
3665 * Remark: Single threaded access only.
3666 *
3667 * Return:
3668 * < 0 if an illegal command or no resources
3669 *
3670 * 0 if good
3671 *
3672 * > 0 if command complete but some type of completion error.
3673 */
3674static int
3675mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
3676{
3677 MPT_FRAME_HDR *mf;
3678 SCSIIORequest_t *pScsiReq;
3679 SCSIIORequest_t ReqCopy;
3680 int my_idx, ii, dir;
3681 int rc, cmdTimeout;
3682 int in_isr;
3683 char cmdLen;
3684 char CDB[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
3685 char cmd = io->cmd;
3686
3687 in_isr = in_interrupt();
3688 if (in_isr) {
3689 dprintk((MYIOC_s_WARN_FMT "Internal SCSI IO request not allowed in ISR context!\n",
3690 hd->ioc->name));
3691 return -EPERM;
3692 }
3693
3694
3695 /* Set command specific information
3696 */
3697 switch (cmd) {
3698 case INQUIRY:
3699 cmdLen = 6;
3700 dir = MPI_SCSIIO_CONTROL_READ;
3701 CDB[0] = cmd;
3702 CDB[4] = io->size;
3703 cmdTimeout = 10;
3704 break;
3705
3706 case TEST_UNIT_READY:
3707 cmdLen = 6;
3708 dir = MPI_SCSIIO_CONTROL_READ;
3709 cmdTimeout = 10;
3710 break;
3711
3712 case START_STOP:
3713 cmdLen = 6;
3714 dir = MPI_SCSIIO_CONTROL_READ;
3715 CDB[0] = cmd;
3716 CDB[4] = 1; /*Spin up the disk */
3717 cmdTimeout = 15;
3718 break;
3719
3720 case REQUEST_SENSE:
3721 cmdLen = 6;
3722 CDB[0] = cmd;
3723 CDB[4] = io->size;
3724 dir = MPI_SCSIIO_CONTROL_READ;
3725 cmdTimeout = 10;
3726 break;
3727
3728 case READ_BUFFER:
3729 cmdLen = 10;
3730 dir = MPI_SCSIIO_CONTROL_READ;
3731 CDB[0] = cmd;
3732 if (io->flags & MPT_ICFLAG_ECHO) {
3733 CDB[1] = 0x0A;
3734 } else {
3735 CDB[1] = 0x02;
3736 }
3737
3738 if (io->flags & MPT_ICFLAG_BUF_CAP) {
3739 CDB[1] |= 0x01;
3740 }
3741 CDB[6] = (io->size >> 16) & 0xFF;
3742 CDB[7] = (io->size >> 8) & 0xFF;
3743 CDB[8] = io->size & 0xFF;
3744 cmdTimeout = 10;
3745 break;
3746
3747 case WRITE_BUFFER:
3748 cmdLen = 10;
3749 dir = MPI_SCSIIO_CONTROL_WRITE;
3750 CDB[0] = cmd;
3751 if (io->flags & MPT_ICFLAG_ECHO) {
3752 CDB[1] = 0x0A;
3753 } else {
3754 CDB[1] = 0x02;
3755 }
3756 CDB[6] = (io->size >> 16) & 0xFF;
3757 CDB[7] = (io->size >> 8) & 0xFF;
3758 CDB[8] = io->size & 0xFF;
3759 cmdTimeout = 10;
3760 break;
3761
3762 case RESERVE:
3763 cmdLen = 6;
3764 dir = MPI_SCSIIO_CONTROL_READ;
3765 CDB[0] = cmd;
3766 cmdTimeout = 10;
3767 break;
3768
3769 case RELEASE:
3770 cmdLen = 6;
3771 dir = MPI_SCSIIO_CONTROL_READ;
3772 CDB[0] = cmd;
3773 cmdTimeout = 10;
3774 break;
3775
3776 case SYNCHRONIZE_CACHE:
3777 cmdLen = 10;
3778 dir = MPI_SCSIIO_CONTROL_READ;
3779 CDB[0] = cmd;
3780// CDB[1] = 0x02; /* set immediate bit */
3781 cmdTimeout = 10;
3782 break;
3783
3784 default:
3785 /* Error Case */
3786 return -EFAULT;
3787 }
3788
3789 /* Get and Populate a free Frame
3790 */
0d0c7974 3791 if ((mf = mpt_get_msg_frame(hd->ioc->InternalCtx, hd->ioc)) == NULL) {
1da177e4
LT
3792 ddvprintk((MYIOC_s_WARN_FMT "No msg frames!\n",
3793 hd->ioc->name));
3794 return -EBUSY;
3795 }
3796
3797 pScsiReq = (SCSIIORequest_t *) mf;
3798
3799 /* Get the request index */
3800 my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
3801 ADD_INDEX_LOG(my_idx); /* for debug */
3802
3803 if (io->flags & MPT_ICFLAG_PHYS_DISK) {
3804 pScsiReq->TargetID = io->physDiskNum;
3805 pScsiReq->Bus = 0;
3806 pScsiReq->ChainOffset = 0;
3807 pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
3808 } else {
3809 pScsiReq->TargetID = io->id;
3810 pScsiReq->Bus = io->bus;
3811 pScsiReq->ChainOffset = 0;
3812 pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
3813 }
3814
3815 pScsiReq->CDBLength = cmdLen;
3816 pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
3817
3818 pScsiReq->Reserved = 0;
3819
3820 pScsiReq->MsgFlags = mpt_msg_flags();
3821 /* MsgContext set in mpt_get_msg_fram call */
3822
3823 for (ii=0; ii < 8; ii++)
3824 pScsiReq->LUN[ii] = 0;
3825 pScsiReq->LUN[1] = io->lun;
3826
3827 if (io->flags & MPT_ICFLAG_TAGGED_CMD)
3828 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_SIMPLEQ);
3829 else
3830 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
3831
3832 if (cmd == REQUEST_SENSE) {
3833 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
3834 ddvprintk((MYIOC_s_INFO_FMT "Untagged! 0x%2x\n",
3835 hd->ioc->name, cmd));
3836 }
3837
3838 for (ii=0; ii < 16; ii++)
3839 pScsiReq->CDB[ii] = CDB[ii];
3840
3841 pScsiReq->DataLength = cpu_to_le32(io->size);
3842 pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma
3843 + (my_idx * MPT_SENSE_BUFFER_ALLOC));
3844
3845 ddvprintk((MYIOC_s_INFO_FMT "Sending Command 0x%x for (%d:%d:%d)\n",
3846 hd->ioc->name, cmd, io->bus, io->id, io->lun));
3847
3848 if (dir == MPI_SCSIIO_CONTROL_READ) {
3849 mpt_add_sge((char *) &pScsiReq->SGL,
3850 MPT_SGE_FLAGS_SSIMPLE_READ | io->size,
3851 io->data_dma);
3852 } else {
3853 mpt_add_sge((char *) &pScsiReq->SGL,
3854 MPT_SGE_FLAGS_SSIMPLE_WRITE | io->size,
3855 io->data_dma);
3856 }
3857
3858 /* The ISR will free the request frame, but we need
3859 * the information to initialize the target. Duplicate.
3860 */
3861 memcpy(&ReqCopy, pScsiReq, sizeof(SCSIIORequest_t));
3862
3863 /* Issue this command after:
3864 * finish init
3865 * add timer
3866 * Wait until the reply has been received
3867 * ScsiScanDvCtx callback function will
3868 * set hd->pLocal;
3869 * set scandv_wait_done and call wake_up
3870 */
3871 hd->pLocal = NULL;
3872 hd->timer.expires = jiffies + HZ*cmdTimeout;
0d0c7974 3873 hd->scandv_wait_done = 0;
1da177e4
LT
3874
3875 /* Save cmd pointer, for resource free if timeout or
3876 * FW reload occurs
3877 */
3878 hd->cmdPtr = mf;
3879
3880 add_timer(&hd->timer);
0d0c7974
MED
3881 mpt_put_msg_frame(hd->ioc->InternalCtx, hd->ioc, mf);
3882 wait_event(hd->scandv_waitq, hd->scandv_wait_done);
1da177e4
LT
3883
3884 if (hd->pLocal) {
3885 rc = hd->pLocal->completion;
3886 hd->pLocal->skip = 0;
3887
3888 /* Always set fatal error codes in some cases.
3889 */
3890 if (rc == MPT_SCANDV_SELECTION_TIMEOUT)
3891 rc = -ENXIO;
3892 else if (rc == MPT_SCANDV_SOME_ERROR)
3893 rc = -rc;
3894 } else {
3895 rc = -EFAULT;
3896 /* This should never happen. */
3897 ddvprintk((MYIOC_s_INFO_FMT "_do_cmd: Null pLocal!!!\n",
3898 hd->ioc->name));
3899 }
3900
3901 return rc;
3902}
3903
3904/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3905/**
3906 * mptscsih_synchronize_cache - Send SYNCHRONIZE_CACHE to all disks.
3907 * @hd: Pointer to MPT_SCSI_HOST structure
3908 * @portnum: IOC port number
3909 *
3910 * Uses the ISR, but with special processing.
3911 * MUST be single-threaded.
3912 *
3913 * Return: 0 on completion
3914 */
3915static int
3916mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum)
3917{
3918 MPT_ADAPTER *ioc= hd->ioc;
3919 VirtDevice *pTarget;
3920 SCSIDevicePage1_t *pcfg1Data = NULL;
3921 INTERNAL_CMD iocmd;
3922 CONFIGPARMS cfg;
3923 dma_addr_t cfg1_dma_addr = -1;
3924 ConfigPageHeader_t header1;
3925 int bus = 0;
3926 int id = 0;
3927 int lun;
3928 int indexed_lun, lun_index;
3929 int hostId = ioc->pfacts[portnum].PortSCSIID;
3930 int max_id;
3931 int requested, configuration, data;
3932 int doConfig = 0;
3933 u8 flags, factor;
3934
3935 max_id = ioc->sh->max_id - 1;
3936
3937 /* Following parameters will not change
3938 * in this routine.
3939 */
3940 iocmd.cmd = SYNCHRONIZE_CACHE;
3941 iocmd.flags = 0;
3942 iocmd.physDiskNum = -1;
3943 iocmd.data = NULL;
3944 iocmd.data_dma = -1;
3945 iocmd.size = 0;
3946 iocmd.rsvd = iocmd.rsvd2 = 0;
3947
3948 /* No SCSI hosts
3949 */
3950 if (hd->Targets == NULL)
3951 return 0;
3952
3953 /* Skip the host
3954 */
3955 if (id == hostId)
3956 id++;
3957
3958 /* Write SDP1 for all SCSI devices
3959 * Alloc memory and set up config buffer
3960 */
3961 if (ioc->bus_type == SCSI) {
3962 if (ioc->spi_data.sdp1length > 0) {
3963 pcfg1Data = (SCSIDevicePage1_t *)pci_alloc_consistent(ioc->pcidev,
3964 ioc->spi_data.sdp1length * 4, &cfg1_dma_addr);
3965
3966 if (pcfg1Data != NULL) {
3967 doConfig = 1;
3968 header1.PageVersion = ioc->spi_data.sdp1version;
3969 header1.PageLength = ioc->spi_data.sdp1length;
3970 header1.PageNumber = 1;
3971 header1.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
3972 cfg.hdr = &header1;
3973 cfg.physAddr = cfg1_dma_addr;
3974 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
3975 cfg.dir = 1;
3976 cfg.timeout = 0;
3977 }
3978 }
3979 }
3980
3981 /* loop through all devices on this port
3982 */
3983 while (bus < MPT_MAX_BUS) {
3984 iocmd.bus = bus;
3985 iocmd.id = id;
3986 pTarget = hd->Targets[(int)id];
3987
3988 if (doConfig) {
3989
3990 /* Set the negotiation flags */
3991 if (pTarget && (pTarget = hd->Targets[id]) && !pTarget->raidVolume) {
3992 flags = pTarget->negoFlags;
3993 } else {
3994 flags = hd->ioc->spi_data.noQas;
3995 if (hd->ioc->spi_data.nvram && (hd->ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
3996 data = hd->ioc->spi_data.nvram[id];
3997
3998 if (data & MPT_NVRAM_WIDE_DISABLE)
3999 flags |= MPT_TARGET_NO_NEGO_WIDE;
4000
4001 factor = (data & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT;
4002 if ((factor == 0) || (factor == MPT_ASYNC))
4003 flags |= MPT_TARGET_NO_NEGO_SYNC;
4004 }
4005 }
4006
4007 /* Force to async, narrow */
4008 mptscsih_setDevicePage1Flags(0, MPT_ASYNC, 0, &requested,
4009 &configuration, flags);
4010 dnegoprintk(("syncronize cache: id=%d width=0 factor=MPT_ASYNC "
4011 "offset=0 negoFlags=%x request=%x config=%x\n",
4012 id, flags, requested, configuration));
4013 pcfg1Data->RequestedParameters = le32_to_cpu(requested);
4014 pcfg1Data->Reserved = 0;
4015 pcfg1Data->Configuration = le32_to_cpu(configuration);
4016 cfg.pageAddr = (bus<<8) | id;
4017 mpt_config(hd->ioc, &cfg);
4018 }
4019
4020 /* If target Ptr NULL or if this target is NOT a disk, skip.
4021 */
4022 if ((pTarget) && (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)){
4023 for (lun=0; lun <= MPT_LAST_LUN; lun++) {
4024 /* If LUN present, issue the command
4025 */
4026 lun_index = (lun >> 5); /* 32 luns per lun_index */
4027 indexed_lun = (lun % 32);
4028 if (pTarget->luns[lun_index] & (1<<indexed_lun)) {
4029 iocmd.lun = lun;
4030 (void) mptscsih_do_cmd(hd, &iocmd);
4031 }
4032 }
4033 }
4034
4035 /* get next relevant device */
4036 id++;
4037
4038 if (id == hostId)
4039 id++;
4040
4041 if (id > max_id) {
4042 id = 0;
4043 bus++;
4044 }
4045 }
4046
4047 if (pcfg1Data) {
4048 pci_free_consistent(ioc->pcidev, header1.PageLength * 4, pcfg1Data, cfg1_dma_addr);
4049 }
4050
4051 return 0;
4052}
4053
4054#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
4055/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4056/**
4057 * mptscsih_domainValidation - Top level handler for domain validation.
4058 * @hd: Pointer to MPT_SCSI_HOST structure.
4059 *
4060 * Uses the ISR, but with special processing.
4061 * Called from schedule, should not be in interrupt mode.
4062 * While thread alive, do dv for all devices needing dv
4063 *
4064 * Return: None.
4065 */
4066static void
4067mptscsih_domainValidation(void *arg)
4068{
4069 MPT_SCSI_HOST *hd;
4070 MPT_ADAPTER *ioc;
4071 unsigned long flags;
4072 int id, maxid, dvStatus, did;
4073 int ii, isPhysDisk;
4074
4075 spin_lock_irqsave(&dvtaskQ_lock, flags);
4076 dvtaskQ_active = 1;
4077 if (dvtaskQ_release) {
4078 dvtaskQ_active = 0;
4079 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
4080 return;
4081 }
4082 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
4083
4084 /* For this ioc, loop through all devices and do dv to each device.
4085 * When complete with this ioc, search through the ioc list, and
4086 * for each scsi ioc found, do dv for all devices. Exit when no
4087 * device needs dv.
4088 */
4089 did = 1;
4090 while (did) {
4091 did = 0;
4092 list_for_each_entry(ioc, &ioc_list, list) {
4093 spin_lock_irqsave(&dvtaskQ_lock, flags);
4094 if (dvtaskQ_release) {
4095 dvtaskQ_active = 0;
4096 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
4097 return;
4098 }
4099 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
4100
4101 msleep(250);
4102
4103 /* DV only to SCSI adapters */
4104 if (ioc->bus_type != SCSI)
4105 continue;
4106
4107 /* Make sure everything looks ok */
4108 if (ioc->sh == NULL)
4109 continue;
4110
4111 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
4112 if (hd == NULL)
4113 continue;
4114
4115 if ((ioc->spi_data.forceDv & MPT_SCSICFG_RELOAD_IOC_PG3) != 0) {
4116 mpt_read_ioc_pg_3(ioc);
4117 if (ioc->spi_data.pIocPg3) {
4118 Ioc3PhysDisk_t *pPDisk = ioc->spi_data.pIocPg3->PhysDisk;
4119 int numPDisk = ioc->spi_data.pIocPg3->NumPhysDisks;
4120
4121 while (numPDisk) {
4122 if (ioc->spi_data.dvStatus[pPDisk->PhysDiskID] & MPT_SCSICFG_DV_NOT_DONE)
4123 ioc->spi_data.dvStatus[pPDisk->PhysDiskID] |= MPT_SCSICFG_NEED_DV;
4124
4125 pPDisk++;
4126 numPDisk--;
4127 }
4128 }
4129 ioc->spi_data.forceDv &= ~MPT_SCSICFG_RELOAD_IOC_PG3;
4130 }
4131
4132 maxid = min_t(int, ioc->sh->max_id, MPT_MAX_SCSI_DEVICES);
4133
4134 for (id = 0; id < maxid; id++) {
4135 spin_lock_irqsave(&dvtaskQ_lock, flags);
4136 if (dvtaskQ_release) {
4137 dvtaskQ_active = 0;
4138 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
4139 return;
4140 }
4141 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
4142 dvStatus = hd->ioc->spi_data.dvStatus[id];
4143
4144 if (dvStatus & MPT_SCSICFG_NEED_DV) {
4145 did++;
4146 hd->ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_DV_PENDING;
4147 hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_NEED_DV;
4148
4149 msleep(250);
4150
4151 /* If hidden phys disk, block IO's to all
4152 * raid volumes
4153 * else, process normally
4154 */
4155 isPhysDisk = mptscsih_is_phys_disk(ioc, id);
4156 if (isPhysDisk) {
4157 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
4158 if (hd->ioc->spi_data.isRaid & (1 << ii)) {
4159 hd->ioc->spi_data.dvStatus[ii] |= MPT_SCSICFG_DV_PENDING;
4160 }
4161 }
4162 }
4163
4164 if (mptscsih_doDv(hd, 0, id) == 1) {
4165 /* Untagged device was busy, try again
4166 */
4167 hd->ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_NEED_DV;
4168 hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_DV_PENDING;
4169 } else {
4170 /* DV is complete. Clear flags.
4171 */
4172 hd->ioc->spi_data.dvStatus[id] &= ~(MPT_SCSICFG_DV_NOT_DONE | MPT_SCSICFG_DV_PENDING);
4173 }
4174
4175 if (isPhysDisk) {
4176 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
4177 if (hd->ioc->spi_data.isRaid & (1 << ii)) {
4178 hd->ioc->spi_data.dvStatus[ii] &= ~MPT_SCSICFG_DV_PENDING;
4179 }
4180 }
4181 }
4182
4183 if (hd->ioc->spi_data.noQas)
4184 mptscsih_qas_check(hd, id);
4185 }
4186 }
4187 }
4188 }
4189
4190 spin_lock_irqsave(&dvtaskQ_lock, flags);
4191 dvtaskQ_active = 0;
4192 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
4193
4194 return;
4195}
4196
4197/* Search IOC page 3 to determine if this is hidden physical disk
4198 */
0d0c7974
MED
4199static int
4200mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id)
1da177e4
LT
4201{
4202 if (ioc->spi_data.pIocPg3) {
4203 Ioc3PhysDisk_t *pPDisk = ioc->spi_data.pIocPg3->PhysDisk;
4204 int numPDisk = ioc->spi_data.pIocPg3->NumPhysDisks;
4205
4206 while (numPDisk) {
4207 if (pPDisk->PhysDiskID == id) {
4208 return 1;
4209 }
4210 pPDisk++;
4211 numPDisk--;
4212 }
4213 }
4214 return 0;
4215}
4216
4217/* Write SDP1 if no QAS has been enabled
4218 */
0d0c7974
MED
4219static void
4220mptscsih_qas_check(MPT_SCSI_HOST *hd, int id)
1da177e4
LT
4221{
4222 VirtDevice *pTarget;
4223 int ii;
4224
4225 if (hd->Targets == NULL)
4226 return;
4227
4228 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
4229 if (ii == id)
4230 continue;
4231
4232 if ((hd->ioc->spi_data.dvStatus[ii] & MPT_SCSICFG_DV_NOT_DONE) != 0)
4233 continue;
4234
4235 pTarget = hd->Targets[ii];
4236
4237 if ((pTarget != NULL) && (!pTarget->raidVolume)) {
4238 if ((pTarget->negoFlags & hd->ioc->spi_data.noQas) == 0) {
4239 pTarget->negoFlags |= hd->ioc->spi_data.noQas;
4240 dnegoprintk(("writeSDP1: id=%d flags=0\n", id));
4241 mptscsih_writeSDP1(hd, 0, ii, 0);
4242 }
4243 } else {
4244 if (mptscsih_is_phys_disk(hd->ioc, ii) == 1) {
4245 dnegoprintk(("writeSDP1: id=%d SCSICFG_USE_NVRAM\n", id));
4246 mptscsih_writeSDP1(hd, 0, ii, MPT_SCSICFG_USE_NVRAM);
4247 }
4248 }
4249 }
4250 return;
4251}
4252
4253
4254
4255#define MPT_GET_NVRAM_VALS 0x01
4256#define MPT_UPDATE_MAX 0x02
4257#define MPT_SET_MAX 0x04
4258#define MPT_SET_MIN 0x08
4259#define MPT_FALLBACK 0x10
4260#define MPT_SAVE 0x20
4261
4262/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4263/**
4264 * mptscsih_doDv - Perform domain validation to a target.
4265 * @hd: Pointer to MPT_SCSI_HOST structure.
4266 * @portnum: IOC port number.
4267 * @target: Physical ID of this target
4268 *
4269 * Uses the ISR, but with special processing.
4270 * MUST be single-threaded.
4271 * Test will exit if target is at async & narrow.
4272 *
4273 * Return: None.
4274 */
4275static int
4276mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
4277{
4278 MPT_ADAPTER *ioc = hd->ioc;
4279 VirtDevice *pTarget;
4280 SCSIDevicePage1_t *pcfg1Data;
4281 SCSIDevicePage0_t *pcfg0Data;
4282 u8 *pbuf1;
4283 u8 *pbuf2;
4284 u8 *pDvBuf;
4285 dma_addr_t dvbuf_dma = -1;
4286 dma_addr_t buf1_dma = -1;
4287 dma_addr_t buf2_dma = -1;
4288 dma_addr_t cfg1_dma_addr = -1;
4289 dma_addr_t cfg0_dma_addr = -1;
4290 ConfigPageHeader_t header1;
4291 ConfigPageHeader_t header0;
4292 DVPARAMETERS dv;
4293 INTERNAL_CMD iocmd;
4294 CONFIGPARMS cfg;
4295 int dv_alloc = 0;
4296 int rc, sz = 0;
4297 int bufsize = 0;
4298 int dataBufSize = 0;
4299 int echoBufSize = 0;
4300 int notDone;
4301 int patt;
4302 int repeat;
4303 int retcode = 0;
4304 int nfactor = MPT_ULTRA320;
4305 char firstPass = 1;
4306 char doFallback = 0;
4307 char readPage0;
4308 char bus, lun;
4309 char inq0 = 0;
4310
4311 if (ioc->spi_data.sdp1length == 0)
4312 return 0;
4313
4314 if (ioc->spi_data.sdp0length == 0)
4315 return 0;
4316
4317 /* If multiple buses are used, require that the initiator
4318 * id be the same on all buses.
4319 */
4320 if (id == ioc->pfacts[0].PortSCSIID)
4321 return 0;
4322
4323 lun = 0;
4324 bus = (u8) bus_number;
4325 ddvtprintk((MYIOC_s_NOTE_FMT
4326 "DV started: bus=%d, id=%d dv @ %p\n",
4327 ioc->name, bus, id, &dv));
4328
4329 /* Prep DV structure
4330 */
4331 memset (&dv, 0, sizeof(DVPARAMETERS));
4332 dv.id = id;
4333
4334 /* Populate tmax with the current maximum
4335 * transfer parameters for this target.
4336 * Exit if narrow and async.
4337 */
4338 dv.cmd = MPT_GET_NVRAM_VALS;
4339 mptscsih_dv_parms(hd, &dv, NULL);
4340
4341 /* Prep SCSI IO structure
4342 */
4343 iocmd.id = id;
4344 iocmd.bus = bus;
4345 iocmd.lun = lun;
4346 iocmd.flags = 0;
4347 iocmd.physDiskNum = -1;
4348 iocmd.rsvd = iocmd.rsvd2 = 0;
4349
4350 pTarget = hd->Targets[id];
4351
4352 /* Use tagged commands if possible.
4353 */
4354 if (pTarget) {
4355 if (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)
4356 iocmd.flags |= MPT_ICFLAG_TAGGED_CMD;
4357 else {
4358 if (hd->ioc->facts.FWVersion.Word < 0x01000600)
4359 return 0;
4360
4361 if ((hd->ioc->facts.FWVersion.Word >= 0x01010000) &&
4362 (hd->ioc->facts.FWVersion.Word < 0x01010B00))
4363 return 0;
4364 }
4365 }
4366
4367 /* Prep cfg structure
4368 */
4369 cfg.pageAddr = (bus<<8) | id;
4370 cfg.hdr = NULL;
4371
4372 /* Prep SDP0 header
4373 */
4374 header0.PageVersion = ioc->spi_data.sdp0version;
4375 header0.PageLength = ioc->spi_data.sdp0length;
4376 header0.PageNumber = 0;
4377 header0.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
4378
4379 /* Prep SDP1 header
4380 */
4381 header1.PageVersion = ioc->spi_data.sdp1version;
4382 header1.PageLength = ioc->spi_data.sdp1length;
4383 header1.PageNumber = 1;
4384 header1.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
4385
4386 if (header0.PageLength & 1)
4387 dv_alloc = (header0.PageLength * 4) + 4;
4388
4389 dv_alloc += (2048 + (header1.PageLength * 4));
4390
4391 pDvBuf = pci_alloc_consistent(ioc->pcidev, dv_alloc, &dvbuf_dma);
4392 if (pDvBuf == NULL)
4393 return 0;
4394
4395 sz = 0;
4396 pbuf1 = (u8 *)pDvBuf;
4397 buf1_dma = dvbuf_dma;
4398 sz +=1024;
4399
4400 pbuf2 = (u8 *) (pDvBuf + sz);
4401 buf2_dma = dvbuf_dma + sz;
4402 sz +=1024;
4403
4404 pcfg0Data = (SCSIDevicePage0_t *) (pDvBuf + sz);
4405 cfg0_dma_addr = dvbuf_dma + sz;
4406 sz += header0.PageLength * 4;
4407
4408 /* 8-byte alignment
4409 */
4410 if (header0.PageLength & 1)
4411 sz += 4;
4412
4413 pcfg1Data = (SCSIDevicePage1_t *) (pDvBuf + sz);
4414 cfg1_dma_addr = dvbuf_dma + sz;
4415
4416 /* Skip this ID? Set cfg.hdr to force config page write
4417 */
4418 {
4419 ScsiCfgData *pspi_data = &hd->ioc->spi_data;
4420 if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) {
4421 /* Set the factor from nvram */
4422 nfactor = (pspi_data->nvram[id] & MPT_NVRAM_SYNC_MASK) >> 8;
4423 if (nfactor < pspi_data->minSyncFactor )
4424 nfactor = pspi_data->minSyncFactor;
4425
4426 if (!(pspi_data->nvram[id] & MPT_NVRAM_ID_SCAN_ENABLE) ||
4427 (pspi_data->PortFlags == MPI_SCSIPORTPAGE2_PORT_FLAGS_OFF_DV) ) {
4428
4429 ddvprintk((MYIOC_s_NOTE_FMT "DV Skipped: bus, id, lun (%d, %d, %d)\n",
4430 ioc->name, bus, id, lun));
4431
4432 dv.cmd = MPT_SET_MAX;
4433 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
4434 cfg.hdr = &header1;
4435
4436 /* Save the final negotiated settings to
4437 * SCSI device page 1.
4438 */
4439 cfg.physAddr = cfg1_dma_addr;
4440 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
4441 cfg.dir = 1;
4442 mpt_config(hd->ioc, &cfg);
4443 goto target_done;
4444 }
4445 }
4446 }
4447
4448 /* Finish iocmd inititialization - hidden or visible disk? */
4449 if (ioc->spi_data.pIocPg3) {
4450 /* Search IOC page 3 for matching id
4451 */
4452 Ioc3PhysDisk_t *pPDisk = ioc->spi_data.pIocPg3->PhysDisk;
4453 int numPDisk = ioc->spi_data.pIocPg3->NumPhysDisks;
4454
4455 while (numPDisk) {
4456 if (pPDisk->PhysDiskID == id) {
4457 /* match */
4458 iocmd.flags |= MPT_ICFLAG_PHYS_DISK;
4459 iocmd.physDiskNum = pPDisk->PhysDiskNum;
4460
4461 /* Quiesce the IM
4462 */
4463 if (mptscsih_do_raid(hd, MPI_RAID_ACTION_QUIESCE_PHYS_IO, &iocmd) < 0) {
4464 ddvprintk((MYIOC_s_ERR_FMT "RAID Queisce FAILED!\n", ioc->name));
4465 goto target_done;
4466 }
4467 break;
4468 }
4469 pPDisk++;
4470 numPDisk--;
4471 }
4472 }
4473
4474 /* RAID Volume ID's may double for a physical device. If RAID but
4475 * not a physical ID as well, skip DV.
4476 */
4477 if ((hd->ioc->spi_data.isRaid & (1 << id)) && !(iocmd.flags & MPT_ICFLAG_PHYS_DISK))
4478 goto target_done;
4479
4480
4481 /* Basic Test.
4482 * Async & Narrow - Inquiry
4483 * Async & Narrow - Inquiry
4484 * Maximum transfer rate - Inquiry
4485 * Compare buffers:
4486 * If compare, test complete.
4487 * If miscompare and first pass, repeat
4488 * If miscompare and not first pass, fall back and repeat
4489 */
4490 hd->pLocal = NULL;
4491 readPage0 = 0;
4492 sz = SCSI_MAX_INQUIRY_BYTES;
4493 rc = MPT_SCANDV_GOOD;
4494 while (1) {
4495 ddvprintk((MYIOC_s_NOTE_FMT "DV: Start Basic test on id=%d\n", ioc->name, id));
4496 retcode = 0;
4497 dv.cmd = MPT_SET_MIN;
4498 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
4499
4500 cfg.hdr = &header1;
4501 cfg.physAddr = cfg1_dma_addr;
4502 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
4503 cfg.dir = 1;
4504 if (mpt_config(hd->ioc, &cfg) != 0)
4505 goto target_done;
4506
4507 /* Wide - narrow - wide workaround case
4508 */
4509 if ((rc == MPT_SCANDV_ISSUE_SENSE) && dv.max.width) {
4510 /* Send an untagged command to reset disk Qs corrupted
4511 * when a parity error occurs on a Request Sense.
4512 */
4513 if ((hd->ioc->facts.FWVersion.Word >= 0x01000600) ||
4514 ((hd->ioc->facts.FWVersion.Word >= 0x01010000) &&
4515 (hd->ioc->facts.FWVersion.Word < 0x01010B00)) ) {
4516
4517 iocmd.cmd = REQUEST_SENSE;
4518 iocmd.data_dma = buf1_dma;
4519 iocmd.data = pbuf1;
4520 iocmd.size = 0x12;
4521 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4522 goto target_done;
4523 else {
4524 if (hd->pLocal == NULL)
4525 goto target_done;
4526 rc = hd->pLocal->completion;
4527 if ((rc == MPT_SCANDV_GOOD) || (rc == MPT_SCANDV_SENSE)) {
4528 dv.max.width = 0;
4529 doFallback = 0;
4530 } else
4531 goto target_done;
4532 }
4533 } else
4534 goto target_done;
4535 }
4536
4537 iocmd.cmd = INQUIRY;
4538 iocmd.data_dma = buf1_dma;
4539 iocmd.data = pbuf1;
4540 iocmd.size = sz;
4541 memset(pbuf1, 0x00, sz);
4542 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4543 goto target_done;
4544 else {
4545 if (hd->pLocal == NULL)
4546 goto target_done;
4547 rc = hd->pLocal->completion;
4548 if (rc == MPT_SCANDV_GOOD) {
4549 if (hd->pLocal->scsiStatus == SAM_STAT_BUSY) {
4550 if ((iocmd.flags & MPT_ICFLAG_TAGGED_CMD) == 0)
4551 retcode = 1;
4552 else
4553 retcode = 0;
4554
4555 goto target_done;
4556 }
4557 } else if (rc == MPT_SCANDV_SENSE) {
4558 ;
4559 } else {
4560 /* If first command doesn't complete
4561 * with a good status or with a check condition,
4562 * exit.
4563 */
4564 goto target_done;
4565 }
4566 }
4567
4568 /* Reset the size for disks
4569 */
4570 inq0 = (*pbuf1) & 0x1F;
4571 if ((inq0 == 0) && pTarget && !pTarget->raidVolume) {
4572 sz = 0x40;
4573 iocmd.size = sz;
4574 }
4575
4576 /* Another GEM workaround. Check peripheral device type,
4577 * if PROCESSOR, quit DV.
4578 */
4579 if (inq0 == TYPE_PROCESSOR) {
4580 mptscsih_initTarget(hd,
4581 bus,
4582 id,
4583 lun,
4584 pbuf1,
4585 sz);
4586 goto target_done;
4587 }
4588
4589 if (inq0 > 0x08)
4590 goto target_done;
4591
4592 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4593 goto target_done;
4594
4595 if (sz == 0x40) {
4596 if ((pTarget->maxWidth == 1) && (pTarget->maxOffset) && (nfactor < 0x0A)
4597 && (pTarget->minSyncFactor > 0x09)) {
4598 if ((pbuf1[56] & 0x04) == 0)
4599 ;
4600 else if ((pbuf1[56] & 0x01) == 1) {
4601 pTarget->minSyncFactor =
4602 nfactor > MPT_ULTRA320 ? nfactor : MPT_ULTRA320;
4603 } else {
4604 pTarget->minSyncFactor =
4605 nfactor > MPT_ULTRA160 ? nfactor : MPT_ULTRA160;
4606 }
4607
4608 dv.max.factor = pTarget->minSyncFactor;
4609
4610 if ((pbuf1[56] & 0x02) == 0) {
4611 pTarget->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
4612 hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS;
4613 ddvprintk((MYIOC_s_NOTE_FMT
4614 "DV: Start Basic noQas on id=%d due to pbuf1[56]=%x\n",
4615 ioc->name, id, pbuf1[56]));
4616 }
4617 }
4618 }
4619
4620 if (doFallback)
4621 dv.cmd = MPT_FALLBACK;
4622 else
4623 dv.cmd = MPT_SET_MAX;
4624
4625 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
4626 if (mpt_config(hd->ioc, &cfg) != 0)
4627 goto target_done;
4628
4629 if ((!dv.now.width) && (!dv.now.offset))
4630 goto target_done;
4631
4632 iocmd.cmd = INQUIRY;
4633 iocmd.data_dma = buf2_dma;
4634 iocmd.data = pbuf2;
4635 iocmd.size = sz;
4636 memset(pbuf2, 0x00, sz);
4637 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4638 goto target_done;
4639 else if (hd->pLocal == NULL)
4640 goto target_done;
4641 else {
4642 /* Save the return code.
4643 * If this is the first pass,
4644 * read SCSI Device Page 0
4645 * and update the target max parameters.
4646 */
4647 rc = hd->pLocal->completion;
4648 doFallback = 0;
4649 if (rc == MPT_SCANDV_GOOD) {
4650 if (!readPage0) {
4651 u32 sdp0_info;
4652 u32 sdp0_nego;
4653
4654 cfg.hdr = &header0;
4655 cfg.physAddr = cfg0_dma_addr;
4656 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4657 cfg.dir = 0;
4658
4659 if (mpt_config(hd->ioc, &cfg) != 0)
4660 goto target_done;
4661
4662 sdp0_info = le32_to_cpu(pcfg0Data->Information) & 0x0E;
4663 sdp0_nego = (le32_to_cpu(pcfg0Data->NegotiatedParameters) & 0xFF00 ) >> 8;
4664
4665 /* Quantum and Fujitsu workarounds.
4666 * Quantum: PPR U320 -> PPR reply with Ultra2 and wide
4667 * Fujitsu: PPR U320 -> Msg Reject and Ultra2 and wide
4668 * Resetart with a request for U160.
4669 */
4670 if ((dv.now.factor == MPT_ULTRA320) && (sdp0_nego == MPT_ULTRA2)) {
4671 doFallback = 1;
4672 } else {
4673 dv.cmd = MPT_UPDATE_MAX;
4674 mptscsih_dv_parms(hd, &dv, (void *)pcfg0Data);
4675 /* Update the SCSI device page 1 area
4676 */
4677 pcfg1Data->RequestedParameters = pcfg0Data->NegotiatedParameters;
4678 readPage0 = 1;
4679 }
4680 }
4681
4682 /* Quantum workaround. Restart this test will the fallback
4683 * flag set.
4684 */
4685 if (doFallback == 0) {
4686 if (memcmp(pbuf1, pbuf2, sz) != 0) {
4687 if (!firstPass)
4688 doFallback = 1;
4689 } else {
4690 ddvprintk((MYIOC_s_NOTE_FMT
4691 "DV:Inquiry compared id=%d, calling initTarget\n", ioc->name, id));
4692 hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_DV_NOT_DONE;
4693 mptscsih_initTarget(hd,
4694 bus,
4695 id,
4696 lun,
4697 pbuf1,
4698 sz);
4699 break; /* test complete */
4700 }
4701 }
4702
4703
4704 } else if (rc == MPT_SCANDV_ISSUE_SENSE)
4705 doFallback = 1; /* set fallback flag */
4706 else if ((rc == MPT_SCANDV_DID_RESET) ||
4707 (rc == MPT_SCANDV_SENSE) ||
4708 (rc == MPT_SCANDV_FALLBACK))
4709 doFallback = 1; /* set fallback flag */
4710 else
4711 goto target_done;
4712
4713 firstPass = 0;
4714 }
4715 }
4716 ddvprintk((MYIOC_s_NOTE_FMT "DV: Basic test on id=%d completed OK.\n", ioc->name, id));
4717
0d0c7974 4718 if (ioc->spi_data.mpt_dv == 0)
1da177e4
LT
4719 goto target_done;
4720
4721 inq0 = (*pbuf1) & 0x1F;
4722
4723 /* Continue only for disks
4724 */
4725 if (inq0 != 0)
4726 goto target_done;
4727
4728 if ( ioc->spi_data.PortFlags == MPI_SCSIPORTPAGE2_PORT_FLAGS_BASIC_DV_ONLY )
4729 goto target_done;
4730
4731 /* Start the Enhanced Test.
4732 * 0) issue TUR to clear out check conditions
4733 * 1) read capacity of echo (regular) buffer
4734 * 2) reserve device
4735 * 3) do write-read-compare data pattern test
4736 * 4) release
4737 * 5) update nego parms to target struct
4738 */
4739 cfg.hdr = &header1;
4740 cfg.physAddr = cfg1_dma_addr;
4741 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
4742 cfg.dir = 1;
4743
4744 iocmd.cmd = TEST_UNIT_READY;
4745 iocmd.data_dma = -1;
4746 iocmd.data = NULL;
4747 iocmd.size = 0;
4748 notDone = 1;
4749 while (notDone) {
4750 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4751 goto target_done;
4752
4753 if (hd->pLocal == NULL)
4754 goto target_done;
4755
4756 rc = hd->pLocal->completion;
4757 if (rc == MPT_SCANDV_GOOD)
4758 notDone = 0;
4759 else if (rc == MPT_SCANDV_SENSE) {
4760 u8 skey = hd->pLocal->sense[2] & 0x0F;
4761 u8 asc = hd->pLocal->sense[12];
4762 u8 ascq = hd->pLocal->sense[13];
4763 ddvprintk((MYIOC_s_INFO_FMT
4764 "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
4765 ioc->name, skey, asc, ascq));
4766
4767 if (skey == UNIT_ATTENTION)
4768 notDone++; /* repeat */
4769 else if ((skey == NOT_READY) &&
4770 (asc == 0x04)&&(ascq == 0x01)) {
4771 /* wait then repeat */
4772 mdelay (2000);
4773 notDone++;
4774 } else if ((skey == NOT_READY) && (asc == 0x3A)) {
4775 /* no medium, try read test anyway */
4776 notDone = 0;
4777 } else {
4778 /* All other errors are fatal.
4779 */
4780 ddvprintk((MYIOC_s_INFO_FMT "DV: fatal error.",
4781 ioc->name));
4782 goto target_done;
4783 }
4784 } else
4785 goto target_done;
4786 }
4787
4788 iocmd.cmd = READ_BUFFER;
4789 iocmd.data_dma = buf1_dma;
4790 iocmd.data = pbuf1;
4791 iocmd.size = 4;
4792 iocmd.flags |= MPT_ICFLAG_BUF_CAP;
4793
4794 dataBufSize = 0;
4795 echoBufSize = 0;
4796 for (patt = 0; patt < 2; patt++) {
4797 if (patt == 0)
4798 iocmd.flags |= MPT_ICFLAG_ECHO;
4799 else
4800 iocmd.flags &= ~MPT_ICFLAG_ECHO;
4801
4802 notDone = 1;
4803 while (notDone) {
4804 bufsize = 0;
4805
4806 /* If not ready after 8 trials,
4807 * give up on this device.
4808 */
4809 if (notDone > 8)
4810 goto target_done;
4811
4812 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4813 goto target_done;
4814 else if (hd->pLocal == NULL)
4815 goto target_done;
4816 else {
4817 rc = hd->pLocal->completion;
4818 ddvprintk(("ReadBuffer Comp Code %d", rc));
4819 ddvprintk((" buff: %0x %0x %0x %0x\n",
4820 pbuf1[0], pbuf1[1], pbuf1[2], pbuf1[3]));
4821
4822 if (rc == MPT_SCANDV_GOOD) {
4823 notDone = 0;
4824 if (iocmd.flags & MPT_ICFLAG_ECHO) {
4825 bufsize = ((pbuf1[2] & 0x1F) <<8) | pbuf1[3];
4826 } else {
4827 bufsize = pbuf1[1]<<16 | pbuf1[2]<<8 | pbuf1[3];
4828 }
4829 } else if (rc == MPT_SCANDV_SENSE) {
4830 u8 skey = hd->pLocal->sense[2] & 0x0F;
4831 u8 asc = hd->pLocal->sense[12];
4832 u8 ascq = hd->pLocal->sense[13];
4833 ddvprintk((MYIOC_s_INFO_FMT
4834 "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
4835 ioc->name, skey, asc, ascq));
4836 if (skey == ILLEGAL_REQUEST) {
4837 notDone = 0;
4838 } else if (skey == UNIT_ATTENTION) {
4839 notDone++; /* repeat */
4840 } else if ((skey == NOT_READY) &&
4841 (asc == 0x04)&&(ascq == 0x01)) {
4842 /* wait then repeat */
4843 mdelay (2000);
4844 notDone++;
4845 } else {
4846 /* All other errors are fatal.
4847 */
4848 ddvprintk((MYIOC_s_INFO_FMT "DV: fatal error.",
4849 ioc->name));
4850 goto target_done;
4851 }
4852 } else {
4853 /* All other errors are fatal
4854 */
4855 goto target_done;
4856 }
4857 }
4858 }
4859
4860 if (iocmd.flags & MPT_ICFLAG_ECHO)
4861 echoBufSize = bufsize;
4862 else
4863 dataBufSize = bufsize;
4864 }
4865 sz = 0;
4866 iocmd.flags &= ~MPT_ICFLAG_BUF_CAP;
4867
4868 /* Use echo buffers if possible,
4869 * Exit if both buffers are 0.
4870 */
4871 if (echoBufSize > 0) {
4872 iocmd.flags |= MPT_ICFLAG_ECHO;
4873 if (dataBufSize > 0)
4874 bufsize = min(echoBufSize, dataBufSize);
4875 else
4876 bufsize = echoBufSize;
4877 } else if (dataBufSize == 0)
4878 goto target_done;
4879
4880 ddvprintk((MYIOC_s_INFO_FMT "%s Buffer Capacity %d\n", ioc->name,
4881 (iocmd.flags & MPT_ICFLAG_ECHO) ? "Echo" : " ", bufsize));
4882
4883 /* Data buffers for write-read-compare test max 1K.
4884 */
4885 sz = min(bufsize, 1024);
4886
4887 /* --- loop ----
4888 * On first pass, always issue a reserve.
4889 * On additional loops, only if a reset has occurred.
4890 * iocmd.flags indicates if echo or regular buffer
4891 */
4892 for (patt = 0; patt < 4; patt++) {
4893 ddvprintk(("Pattern %d\n", patt));
4894 if ((iocmd.flags & MPT_ICFLAG_RESERVED) && (iocmd.flags & MPT_ICFLAG_DID_RESET)) {
4895 iocmd.cmd = TEST_UNIT_READY;
4896 iocmd.data_dma = -1;
4897 iocmd.data = NULL;
4898 iocmd.size = 0;
4899 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4900 goto target_done;
4901
4902 iocmd.cmd = RELEASE;
4903 iocmd.data_dma = -1;
4904 iocmd.data = NULL;
4905 iocmd.size = 0;
4906 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4907 goto target_done;
4908 else if (hd->pLocal == NULL)
4909 goto target_done;
4910 else {
4911 rc = hd->pLocal->completion;
4912 ddvprintk(("Release rc %d\n", rc));
4913 if (rc == MPT_SCANDV_GOOD)
4914 iocmd.flags &= ~MPT_ICFLAG_RESERVED;
4915 else
4916 goto target_done;
4917 }
4918 iocmd.flags &= ~MPT_ICFLAG_RESERVED;
4919 }
4920 iocmd.flags &= ~MPT_ICFLAG_DID_RESET;
4921
4922 repeat = 5;
4923 while (repeat && (!(iocmd.flags & MPT_ICFLAG_RESERVED))) {
4924 iocmd.cmd = RESERVE;
4925 iocmd.data_dma = -1;
4926 iocmd.data = NULL;
4927 iocmd.size = 0;
4928 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4929 goto target_done;
4930 else if (hd->pLocal == NULL)
4931 goto target_done;
4932 else {
4933 rc = hd->pLocal->completion;
4934 if (rc == MPT_SCANDV_GOOD) {
4935 iocmd.flags |= MPT_ICFLAG_RESERVED;
4936 } else if (rc == MPT_SCANDV_SENSE) {
4937 /* Wait if coming ready
4938 */
4939 u8 skey = hd->pLocal->sense[2] & 0x0F;
4940 u8 asc = hd->pLocal->sense[12];
4941 u8 ascq = hd->pLocal->sense[13];
4942 ddvprintk((MYIOC_s_INFO_FMT
4943 "DV: Reserve Failed: ", ioc->name));
4944 ddvprintk(("SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
4945 skey, asc, ascq));
4946
4947 if ((skey == NOT_READY) && (asc == 0x04)&&
4948 (ascq == 0x01)) {
4949 /* wait then repeat */
4950 mdelay (2000);
4951 notDone++;
4952 } else {
4953 ddvprintk((MYIOC_s_INFO_FMT
4954 "DV: Reserved Failed.", ioc->name));
4955 goto target_done;
4956 }
4957 } else {
4958 ddvprintk((MYIOC_s_INFO_FMT "DV: Reserved Failed.",
4959 ioc->name));
4960 goto target_done;
4961 }
4962 }
4963 }
4964
4965 mptscsih_fillbuf(pbuf1, sz, patt, 1);
4966 iocmd.cmd = WRITE_BUFFER;
4967 iocmd.data_dma = buf1_dma;
4968 iocmd.data = pbuf1;
4969 iocmd.size = sz;
4970 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4971 goto target_done;
4972 else if (hd->pLocal == NULL)
4973 goto target_done;
4974 else {
4975 rc = hd->pLocal->completion;
4976 if (rc == MPT_SCANDV_GOOD)
4977 ; /* Issue read buffer */
4978 else if (rc == MPT_SCANDV_DID_RESET) {
4979 /* If using echo buffers, reset to data buffers.
4980 * Else do Fallback and restart
4981 * this test (re-issue reserve
4982 * because of bus reset).
4983 */
4984 if ((iocmd.flags & MPT_ICFLAG_ECHO) && (dataBufSize >= bufsize)) {
4985 iocmd.flags &= ~MPT_ICFLAG_ECHO;
4986 } else {
4987 dv.cmd = MPT_FALLBACK;
4988 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
4989
4990 if (mpt_config(hd->ioc, &cfg) != 0)
4991 goto target_done;
4992
4993 if ((!dv.now.width) && (!dv.now.offset))
4994 goto target_done;
4995 }
4996
4997 iocmd.flags |= MPT_ICFLAG_DID_RESET;
4998 patt = -1;
4999 continue;
5000 } else if (rc == MPT_SCANDV_SENSE) {
5001 /* Restart data test if UA, else quit.
5002 */
5003 u8 skey = hd->pLocal->sense[2] & 0x0F;
5004 ddvprintk((MYIOC_s_INFO_FMT
5005 "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", ioc->name, skey,
5006 hd->pLocal->sense[12], hd->pLocal->sense[13]));
5007 if (skey == UNIT_ATTENTION) {
5008 patt = -1;
5009 continue;
5010 } else if (skey == ILLEGAL_REQUEST) {
5011 if (iocmd.flags & MPT_ICFLAG_ECHO) {
5012 if (dataBufSize >= bufsize) {
5013 iocmd.flags &= ~MPT_ICFLAG_ECHO;
5014 patt = -1;
5015 continue;
5016 }
5017 }
5018 goto target_done;
5019 }
5020 else
5021 goto target_done;
5022 } else {
5023 /* fatal error */
5024 goto target_done;
5025 }
5026 }
5027
5028 iocmd.cmd = READ_BUFFER;
5029 iocmd.data_dma = buf2_dma;
5030 iocmd.data = pbuf2;
5031 iocmd.size = sz;
5032 if (mptscsih_do_cmd(hd, &iocmd) < 0)
5033 goto target_done;
5034 else if (hd->pLocal == NULL)
5035 goto target_done;
5036 else {
5037 rc = hd->pLocal->completion;
5038 if (rc == MPT_SCANDV_GOOD) {
5039 /* If buffers compare,
5040 * go to next pattern,
5041 * else, do a fallback and restart
5042 * data transfer test.
5043 */
5044 if (memcmp (pbuf1, pbuf2, sz) == 0) {
5045 ; /* goto next pattern */
5046 } else {
5047 /* Miscompare with Echo buffer, go to data buffer,
5048 * if that buffer exists.
5049 * Miscompare with Data buffer, check first 4 bytes,
5050 * some devices return capacity. Exit in this case.
5051 */
5052 if (iocmd.flags & MPT_ICFLAG_ECHO) {
5053 if (dataBufSize >= bufsize)
5054 iocmd.flags &= ~MPT_ICFLAG_ECHO;
5055 else
5056 goto target_done;
5057 } else {
5058 if (dataBufSize == (pbuf2[1]<<16 | pbuf2[2]<<8 | pbuf2[3])) {
5059 /* Argh. Device returning wrong data.
5060 * Quit DV for this device.
5061 */
5062 goto target_done;
5063 }
5064
5065 /* Had an actual miscompare. Slow down.*/
5066 dv.cmd = MPT_FALLBACK;
5067 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
5068
5069 if (mpt_config(hd->ioc, &cfg) != 0)
5070 goto target_done;
5071
5072 if ((!dv.now.width) && (!dv.now.offset))
5073 goto target_done;
5074 }
5075
5076 patt = -1;
5077 continue;
5078 }
5079 } else if (rc == MPT_SCANDV_DID_RESET) {
5080 /* Do Fallback and restart
5081 * this test (re-issue reserve
5082 * because of bus reset).
5083 */
5084 dv.cmd = MPT_FALLBACK;
5085 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
5086
5087 if (mpt_config(hd->ioc, &cfg) != 0)
5088 goto target_done;
5089
5090 if ((!dv.now.width) && (!dv.now.offset))
5091 goto target_done;
5092
5093 iocmd.flags |= MPT_ICFLAG_DID_RESET;
5094 patt = -1;
5095 continue;
5096 } else if (rc == MPT_SCANDV_SENSE) {
5097 /* Restart data test if UA, else quit.
5098 */
5099 u8 skey = hd->pLocal->sense[2] & 0x0F;
5100 ddvprintk((MYIOC_s_INFO_FMT
5101 "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", ioc->name, skey,
5102 hd->pLocal->sense[12], hd->pLocal->sense[13]));
5103 if (skey == UNIT_ATTENTION) {
5104 patt = -1;
5105 continue;
5106 }
5107 else
5108 goto target_done;
5109 } else {
5110 /* fatal error */
5111 goto target_done;
5112 }
5113 }
5114
5115 } /* --- end of patt loop ---- */
5116
5117target_done:
5118 if (iocmd.flags & MPT_ICFLAG_RESERVED) {
5119 iocmd.cmd = RELEASE;
5120 iocmd.data_dma = -1;
5121 iocmd.data = NULL;
5122 iocmd.size = 0;
5123 if (mptscsih_do_cmd(hd, &iocmd) < 0)
5124 printk(MYIOC_s_INFO_FMT "DV: Release failed. id %d",
5125 ioc->name, id);
5126 else if (hd->pLocal) {
5127 if (hd->pLocal->completion == MPT_SCANDV_GOOD)
5128 iocmd.flags &= ~MPT_ICFLAG_RESERVED;
5129 } else {
5130 printk(MYIOC_s_INFO_FMT "DV: Release failed. id %d",
5131 ioc->name, id);
5132 }
5133 }
5134
5135
5136 /* Set if cfg1_dma_addr contents is valid
5137 */
5138 if ((cfg.hdr != NULL) && (retcode == 0)){
5139 /* If disk, not U320, disable QAS
5140 */
5141 if ((inq0 == 0) && (dv.now.factor > MPT_ULTRA320)) {
5142 hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS;
5143 ddvprintk((MYIOC_s_NOTE_FMT
5144 "noQas set due to id=%d has factor=%x\n", ioc->name, id, dv.now.factor));
5145 }
5146
5147 dv.cmd = MPT_SAVE;
5148 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
5149
5150 /* Double writes to SDP1 can cause problems,
5151 * skip save of the final negotiated settings to
5152 * SCSI device page 1.
5153 *
5154 cfg.hdr = &header1;
5155 cfg.physAddr = cfg1_dma_addr;
5156 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
5157 cfg.dir = 1;
5158 mpt_config(hd->ioc, &cfg);
5159 */
5160 }
5161
5162 /* If this is a RAID Passthrough, enable internal IOs
5163 */
5164 if (iocmd.flags & MPT_ICFLAG_PHYS_DISK) {
5165 if (mptscsih_do_raid(hd, MPI_RAID_ACTION_ENABLE_PHYS_IO, &iocmd) < 0)
5166 ddvprintk((MYIOC_s_ERR_FMT "RAID Enable FAILED!\n", ioc->name));
5167 }
5168
5169 /* Done with the DV scan of the current target
5170 */
5171 if (pDvBuf)
5172 pci_free_consistent(ioc->pcidev, dv_alloc, pDvBuf, dvbuf_dma);
5173
5174 ddvtprintk((MYIOC_s_INFO_FMT "DV Done id=%d\n",
5175 ioc->name, id));
5176
5177 return retcode;
5178}
5179
5180/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5181/* mptscsih_dv_parms - perform a variety of operations on the
5182 * parameters used for negotiation.
5183 * @hd: Pointer to a SCSI host.
5184 * @dv: Pointer to a structure that contains the maximum and current
5185 * negotiated parameters.
5186 */
5187static void
5188mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage)
5189{
5190 VirtDevice *pTarget;
5191 SCSIDevicePage0_t *pPage0;
5192 SCSIDevicePage1_t *pPage1;
5193 int val = 0, data, configuration;
5194 u8 width = 0;
5195 u8 offset = 0;
5196 u8 factor = 0;
5197 u8 negoFlags = 0;
5198 u8 cmd = dv->cmd;
5199 u8 id = dv->id;
5200
5201 switch (cmd) {
5202 case MPT_GET_NVRAM_VALS:
5203 ddvprintk((MYIOC_s_NOTE_FMT "Getting NVRAM: ",
5204 hd->ioc->name));
5205 /* Get the NVRAM values and save in tmax
5206 * If not an LVD bus, the adapter minSyncFactor has been
5207 * already throttled back.
5208 */
5209 if ((hd->Targets)&&((pTarget = hd->Targets[(int)id]) != NULL) && !pTarget->raidVolume) {
5210 width = pTarget->maxWidth;
5211 offset = pTarget->maxOffset;
5212 factor = pTarget->minSyncFactor;
5213 negoFlags = pTarget->negoFlags;
5214 } else {
5215 if (hd->ioc->spi_data.nvram && (hd->ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
5216 data = hd->ioc->spi_data.nvram[id];
5217 width = data & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
5218 if ((offset = hd->ioc->spi_data.maxSyncOffset) == 0)
5219 factor = MPT_ASYNC;
5220 else {
5221 factor = (data & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT;
5222 if ((factor == 0) || (factor == MPT_ASYNC)){
5223 factor = MPT_ASYNC;
5224 offset = 0;
5225 }
5226 }
5227 } else {
5228 width = MPT_NARROW;
5229 offset = 0;
5230 factor = MPT_ASYNC;
5231 }
5232
5233 /* Set the negotiation flags */
5234 negoFlags = hd->ioc->spi_data.noQas;
5235 if (!width)
5236 negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
5237
5238 if (!offset)
5239 negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
5240 }
5241
5242 /* limit by adapter capabilities */
5243 width = min(width, hd->ioc->spi_data.maxBusWidth);
5244 offset = min(offset, hd->ioc->spi_data.maxSyncOffset);
5245 factor = max(factor, hd->ioc->spi_data.minSyncFactor);
5246
5247 /* Check Consistency */
5248 if (offset && (factor < MPT_ULTRA2) && !width)
5249 factor = MPT_ULTRA2;
5250
5251 dv->max.width = width;
5252 dv->max.offset = offset;
5253 dv->max.factor = factor;
5254 dv->max.flags = negoFlags;
5255 ddvprintk((" id=%d width=%d factor=%x offset=%x flags=%x\n",
5256 id, width, factor, offset, negoFlags));
5257 break;
5258
5259 case MPT_UPDATE_MAX:
5260 ddvprintk((MYIOC_s_NOTE_FMT
5261 "Updating with SDP0 Data: ", hd->ioc->name));
5262 /* Update tmax values with those from Device Page 0.*/
5263 pPage0 = (SCSIDevicePage0_t *) pPage;
5264 if (pPage0) {
5265 val = cpu_to_le32(pPage0->NegotiatedParameters);
5266 dv->max.width = val & MPI_SCSIDEVPAGE0_NP_WIDE ? 1 : 0;
5267 dv->max.offset = (val&MPI_SCSIDEVPAGE0_NP_NEG_SYNC_OFFSET_MASK) >> 16;
5268 dv->max.factor = (val&MPI_SCSIDEVPAGE0_NP_NEG_SYNC_PERIOD_MASK) >> 8;
5269 }
5270
5271 dv->now.width = dv->max.width;
5272 dv->now.offset = dv->max.offset;
5273 dv->now.factor = dv->max.factor;
5274 ddvprintk(("id=%d width=%d factor=%x offset=%x flags=%x\n",
5275 id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags));
5276 break;
5277
5278 case MPT_SET_MAX:
5279 ddvprintk((MYIOC_s_NOTE_FMT "Setting Max: ",
5280 hd->ioc->name));
5281 /* Set current to the max values. Update the config page.*/
5282 dv->now.width = dv->max.width;
5283 dv->now.offset = dv->max.offset;
5284 dv->now.factor = dv->max.factor;
5285 dv->now.flags = dv->max.flags;
5286
5287 pPage1 = (SCSIDevicePage1_t *)pPage;
5288 if (pPage1) {
5289 mptscsih_setDevicePage1Flags (dv->now.width, dv->now.factor,
5290 dv->now.offset, &val, &configuration, dv->now.flags);
5291 dnegoprintk(("Setting Max: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n",
5292 id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags, val, configuration));
5293 pPage1->RequestedParameters = le32_to_cpu(val);
5294 pPage1->Reserved = 0;
5295 pPage1->Configuration = le32_to_cpu(configuration);
5296 }
5297
5298 ddvprintk(("id=%d width=%d factor=%x offset=%x flags=%x request=%x configuration=%x\n",
5299 id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags, val, configuration));
5300 break;
5301
5302 case MPT_SET_MIN:
5303 ddvprintk((MYIOC_s_NOTE_FMT "Setting Min: ",
5304 hd->ioc->name));
5305 /* Set page to asynchronous and narrow
5306 * Do not update now, breaks fallback routine. */
5307 width = MPT_NARROW;
5308 offset = 0;
5309 factor = MPT_ASYNC;
5310 negoFlags = dv->max.flags;
5311
5312 pPage1 = (SCSIDevicePage1_t *)pPage;
5313 if (pPage1) {
5314 mptscsih_setDevicePage1Flags (width, factor,
5315 offset, &val, &configuration, negoFlags);
5316 dnegoprintk(("Setting Min: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n",
5317 id, width, factor, offset, negoFlags, val, configuration));
5318 pPage1->RequestedParameters = le32_to_cpu(val);
5319 pPage1->Reserved = 0;
5320 pPage1->Configuration = le32_to_cpu(configuration);
5321 }
5322 ddvprintk(("id=%d width=%d factor=%x offset=%x request=%x config=%x negoFlags=%x\n",
5323 id, width, factor, offset, val, configuration, negoFlags));
5324 break;
5325
5326 case MPT_FALLBACK:
5327 ddvprintk((MYIOC_s_NOTE_FMT
5328 "Fallback: Start: offset %d, factor %x, width %d \n",
5329 hd->ioc->name, dv->now.offset,
5330 dv->now.factor, dv->now.width));
5331 width = dv->now.width;
5332 offset = dv->now.offset;
5333 factor = dv->now.factor;
5334 if ((offset) && (dv->max.width)) {
5335 if (factor < MPT_ULTRA160)
5336 factor = MPT_ULTRA160;
5337 else if (factor < MPT_ULTRA2) {
5338 factor = MPT_ULTRA2;
5339 width = MPT_WIDE;
5340 } else if ((factor == MPT_ULTRA2) && width) {
5341 factor = MPT_ULTRA2;
5342 width = MPT_NARROW;
5343 } else if (factor < MPT_ULTRA) {
5344 factor = MPT_ULTRA;
5345 width = MPT_WIDE;
5346 } else if ((factor == MPT_ULTRA) && width) {
5347 width = MPT_NARROW;
5348 } else if (factor < MPT_FAST) {
5349 factor = MPT_FAST;
5350 width = MPT_WIDE;
5351 } else if ((factor == MPT_FAST) && width) {
5352 factor = MPT_FAST;
5353 width = MPT_NARROW;
5354 } else if (factor < MPT_SCSI) {
5355 factor = MPT_SCSI;
5356 width = MPT_WIDE;
5357 } else if ((factor == MPT_SCSI) && width) {
5358 factor = MPT_SCSI;
5359 width = MPT_NARROW;
5360 } else {
5361 factor = MPT_ASYNC;
5362 offset = 0;
5363 }
5364
5365 } else if (offset) {
5366 width = MPT_NARROW;
5367 if (factor < MPT_ULTRA)
5368 factor = MPT_ULTRA;
5369 else if (factor < MPT_FAST)
5370 factor = MPT_FAST;
5371 else if (factor < MPT_SCSI)
5372 factor = MPT_SCSI;
5373 else {
5374 factor = MPT_ASYNC;
5375 offset = 0;
5376 }
5377
5378 } else {
5379 width = MPT_NARROW;
5380 factor = MPT_ASYNC;
5381 }
5382 dv->max.flags |= MPT_TARGET_NO_NEGO_QAS;
5383 dv->max.flags &= ~MPT_TAPE_NEGO_IDP;
5384
5385 dv->now.width = width;
5386 dv->now.offset = offset;
5387 dv->now.factor = factor;
5388 dv->now.flags = dv->max.flags;
5389
5390 pPage1 = (SCSIDevicePage1_t *)pPage;
5391 if (pPage1) {
5392 mptscsih_setDevicePage1Flags (width, factor, offset, &val,
5393 &configuration, dv->now.flags);
5394 dnegoprintk(("Finish: id=%d width=%d offset=%d factor=%x flags=%x request=%x config=%x\n",
5395 id, width, offset, factor, dv->now.flags, val, configuration));
5396
5397 pPage1->RequestedParameters = le32_to_cpu(val);
5398 pPage1->Reserved = 0;
5399 pPage1->Configuration = le32_to_cpu(configuration);
5400 }
5401
5402 ddvprintk(("Finish: id=%d offset=%d factor=%x width=%d request=%x config=%x\n",
5403 id, dv->now.offset, dv->now.factor, dv->now.width, val, configuration));
5404 break;
5405
5406 case MPT_SAVE:
5407 ddvprintk((MYIOC_s_NOTE_FMT
5408 "Saving to Target structure: ", hd->ioc->name));
5409 ddvprintk(("id=%d width=%x factor=%x offset=%d flags=%x\n",
5410 id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags));
5411
5412 /* Save these values to target structures
5413 * or overwrite nvram (phys disks only).
5414 */
5415
5416 if ((hd->Targets)&&((pTarget = hd->Targets[(int)id]) != NULL) && !pTarget->raidVolume ) {
5417 pTarget->maxWidth = dv->now.width;
5418 pTarget->maxOffset = dv->now.offset;
5419 pTarget->minSyncFactor = dv->now.factor;
5420 pTarget->negoFlags = dv->now.flags;
5421 } else {
5422 /* Preserv all flags, use
5423 * read-modify-write algorithm
5424 */
5425 if (hd->ioc->spi_data.nvram) {
5426 data = hd->ioc->spi_data.nvram[id];
5427
5428 if (dv->now.width)
5429 data &= ~MPT_NVRAM_WIDE_DISABLE;
5430 else
5431 data |= MPT_NVRAM_WIDE_DISABLE;
5432
5433 if (!dv->now.offset)
5434 factor = MPT_ASYNC;
5435
5436 data &= ~MPT_NVRAM_SYNC_MASK;
5437 data |= (dv->now.factor << MPT_NVRAM_SYNC_SHIFT) & MPT_NVRAM_SYNC_MASK;
5438
5439 hd->ioc->spi_data.nvram[id] = data;
5440 }
5441 }
5442 break;
5443 }
5444}
5445
5446/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5447/* mptscsih_fillbuf - fill a buffer with a special data pattern
5448 * cleanup. For bus scan only.
5449 *
5450 * @buffer: Pointer to data buffer to be filled.
5451 * @size: Number of bytes to fill
5452 * @index: Pattern index
5453 * @width: bus width, 0 (8 bits) or 1 (16 bits)
5454 */
5455static void
5456mptscsih_fillbuf(char *buffer, int size, int index, int width)
5457{
5458 char *ptr = buffer;
5459 int ii;
5460 char byte;
5461 short val;
5462
5463 switch (index) {
5464 case 0:
5465
5466 if (width) {
5467 /* Pattern: 0000 FFFF 0000 FFFF
5468 */
5469 for (ii=0; ii < size; ii++, ptr++) {
5470 if (ii & 0x02)
5471 *ptr = 0xFF;
5472 else
5473 *ptr = 0x00;
5474 }
5475 } else {
5476 /* Pattern: 00 FF 00 FF
5477 */
5478 for (ii=0; ii < size; ii++, ptr++) {
5479 if (ii & 0x01)
5480 *ptr = 0xFF;
5481 else
5482 *ptr = 0x00;
5483 }
5484 }
5485 break;
5486
5487 case 1:
5488 if (width) {
5489 /* Pattern: 5555 AAAA 5555 AAAA 5555
5490 */
5491 for (ii=0; ii < size; ii++, ptr++) {
5492 if (ii & 0x02)
5493 *ptr = 0xAA;
5494 else
5495 *ptr = 0x55;
5496 }
5497 } else {
5498 /* Pattern: 55 AA 55 AA 55
5499 */
5500 for (ii=0; ii < size; ii++, ptr++) {
5501 if (ii & 0x01)
5502 *ptr = 0xAA;
5503 else
5504 *ptr = 0x55;
5505 }
5506 }
5507 break;
5508
5509 case 2:
5510 /* Pattern: 00 01 02 03 04 05
5511 * ... FE FF 00 01..
5512 */
5513 for (ii=0; ii < size; ii++, ptr++)
5514 *ptr = (char) ii;
5515 break;
5516
5517 case 3:
5518 if (width) {
5519 /* Wide Pattern: FFFE 0001 FFFD 0002
5520 * ... 4000 DFFF 8000 EFFF
5521 */
5522 byte = 0;
5523 for (ii=0; ii < size/2; ii++) {
5524 /* Create the base pattern
5525 */
5526 val = (1 << byte);
5527 /* every 64 (0x40) bytes flip the pattern
5528 * since we fill 2 bytes / iteration,
5529 * test for ii = 0x20
5530 */
5531 if (ii & 0x20)
5532 val = ~(val);
5533
5534 if (ii & 0x01) {
5535 *ptr = (char)( (val & 0xFF00) >> 8);
5536 ptr++;
5537 *ptr = (char)(val & 0xFF);
5538 byte++;
5539 byte &= 0x0F;
5540 } else {
5541 val = ~val;
5542 *ptr = (char)( (val & 0xFF00) >> 8);
5543 ptr++;
5544 *ptr = (char)(val & 0xFF);
5545 }
5546
5547 ptr++;
5548 }
5549 } else {
5550 /* Narrow Pattern: FE 01 FD 02 FB 04
5551 * .. 7F 80 01 FE 02 FD ... 80 7F
5552 */
5553 byte = 0;
5554 for (ii=0; ii < size; ii++, ptr++) {
5555 /* Base pattern - first 32 bytes
5556 */
5557 if (ii & 0x01) {
5558 *ptr = (1 << byte);
5559 byte++;
5560 byte &= 0x07;
5561 } else {
5562 *ptr = (char) (~(1 << byte));
5563 }
5564
5565 /* Flip the pattern every 32 bytes
5566 */
5567 if (ii & 0x20)
5568 *ptr = ~(*ptr);
5569 }
5570 }
5571 break;
5572 }
5573}
5574#endif /* ~MPTSCSIH_ENABLE_DOMAIN_VALIDATION */
5575
0d0c7974
MED
5576EXPORT_SYMBOL(mptscsih_remove);
5577EXPORT_SYMBOL(mptscsih_shutdown);
5578#ifdef CONFIG_PM
5579EXPORT_SYMBOL(mptscsih_suspend);
5580EXPORT_SYMBOL(mptscsih_resume);
5581#endif
5582EXPORT_SYMBOL(mptscsih_proc_info);
5583EXPORT_SYMBOL(mptscsih_info);
5584EXPORT_SYMBOL(mptscsih_qcmd);
5585EXPORT_SYMBOL(mptscsih_slave_alloc);
5586EXPORT_SYMBOL(mptscsih_slave_destroy);
5587EXPORT_SYMBOL(mptscsih_slave_configure);
5588EXPORT_SYMBOL(mptscsih_abort);
5589EXPORT_SYMBOL(mptscsih_dev_reset);
5590EXPORT_SYMBOL(mptscsih_bus_reset);
5591EXPORT_SYMBOL(mptscsih_host_reset);
5592EXPORT_SYMBOL(mptscsih_bios_param);
5593EXPORT_SYMBOL(mptscsih_io_done);
5594EXPORT_SYMBOL(mptscsih_taskmgmt_complete);
5595EXPORT_SYMBOL(mptscsih_scandv_complete);
5596EXPORT_SYMBOL(mptscsih_event_process);
5597EXPORT_SYMBOL(mptscsih_ioc_reset);
5598EXPORT_SYMBOL(mptscsih_store_queue_depth);
5599EXPORT_SYMBOL(mptscsih_timer_expired);
1da177e4 5600
0d0c7974 5601/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
This page took 0.395348 seconds and 5 git commands to generate.