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