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