[SCSI] fusion: MODULE_VERSION support
[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 *
9f4203b3 6 * Copyright (c) 1999-2007 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"
bf451522 69#include "lsi/mpi_log_sas.h"
1da177e4
LT
70
71/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
72#define my_NAME "Fusion MPT SCSI Host driver"
73#define my_VERSION MPT_LINUX_VERSION_COMMON
74#define MYNAM "mptscsih"
75
76MODULE_AUTHOR(MODULEAUTHOR);
77MODULE_DESCRIPTION(my_NAME);
78MODULE_LICENSE("GPL");
9f4203b3 79MODULE_VERSION(my_VERSION);
1da177e4 80
1da177e4
LT
81/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
82
83typedef struct _BIG_SENSE_BUF {
84 u8 data[MPT_SENSE_BUFFER_ALLOC];
85} BIG_SENSE_BUF;
86
87#define MPT_SCANDV_GOOD (0x00000000) /* must be 0 */
88#define MPT_SCANDV_DID_RESET (0x00000001)
89#define MPT_SCANDV_SENSE (0x00000002)
90#define MPT_SCANDV_SOME_ERROR (0x00000004)
91#define MPT_SCANDV_SELECTION_TIMEOUT (0x00000008)
92#define MPT_SCANDV_ISSUE_SENSE (0x00000010)
93#define MPT_SCANDV_FALLBACK (0x00000020)
94
95#define MPT_SCANDV_MAX_RETRIES (10)
96
97#define MPT_ICFLAG_BUF_CAP 0x01 /* ReadBuffer Read Capacity format */
98#define MPT_ICFLAG_ECHO 0x02 /* ReadBuffer Echo buffer format */
466544d8
MED
99#define MPT_ICFLAG_EBOS 0x04 /* ReadBuffer Echo buffer has EBOS */
100#define MPT_ICFLAG_PHYS_DISK 0x08 /* Any SCSI IO but do Phys Disk Format */
101#define MPT_ICFLAG_TAGGED_CMD 0x10 /* Do tagged IO */
1da177e4
LT
102#define MPT_ICFLAG_DID_RESET 0x20 /* Bus Reset occurred with this command */
103#define MPT_ICFLAG_RESERVED 0x40 /* Reserved has been issued */
104
105typedef struct _internal_cmd {
106 char *data; /* data pointer */
107 dma_addr_t data_dma; /* data dma address */
108 int size; /* transfer size */
109 u8 cmd; /* SCSI Op Code */
110 u8 bus; /* bus number */
111 u8 id; /* SCSI ID (virtual) */
112 u8 lun;
113 u8 flags; /* Bit Field - See above */
114 u8 physDiskNum; /* Phys disk number, -1 else */
115 u8 rsvd2;
116 u8 rsvd;
117} INTERNAL_CMD;
118
1da177e4
LT
119/*
120 * Other private/forward protos...
121 */
0d0c7974 122int mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
1da177e4 123static void mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq);
0d0c7974 124int mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
1da177e4
LT
125
126static int mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt,
127 SCSIIORequest_t *pReq, int req_idx);
128static void mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx);
0d0c7974 129static void mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply);
1da177e4
LT
130static int mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd);
131static int mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout );
3dc0b03f 132static int SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc);
1da177e4 133
1da177e4
LT
134static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout);
135
0d0c7974
MED
136int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
137int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
1da177e4 138
c92f222e
JB
139static void mptscsih_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget, struct scsi_device *sdev);
140static void mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *vtarget, struct scsi_device *sdev);
1da177e4 141static int mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus);
0d0c7974 142int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
1da177e4 143static int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd);
c7c82987 144static void mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice);
1da177e4 145
0d0c7974 146void mptscsih_remove(struct pci_dev *);
d18c3db5 147void mptscsih_shutdown(struct pci_dev *);
1da177e4 148#ifdef CONFIG_PM
0d0c7974
MED
149int mptscsih_suspend(struct pci_dev *pdev, pm_message_t state);
150int mptscsih_resume(struct pci_dev *pdev);
1da177e4
LT
151#endif
152
1da177e4
LT
153#define SNS_LEN(scp) sizeof((scp)->sense_buffer)
154
1da177e4
LT
155/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
156/**
157 * mptscsih_add_sge - Place a simple SGE at address pAddr.
158 * @pAddr: virtual address for SGE
159 * @flagslength: SGE flags and data transfer length
160 * @dma_addr: Physical address
161 *
162 * This routine places a MPT request frame back on the MPT adapter's
163 * FreeQ.
164 */
165static inline void
166mptscsih_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr)
167{
168 if (sizeof(dma_addr_t) == sizeof(u64)) {
169 SGESimple64_t *pSge = (SGESimple64_t *) pAddr;
170 u32 tmp = dma_addr & 0xFFFFFFFF;
171
172 pSge->FlagsLength = cpu_to_le32(flagslength);
173 pSge->Address.Low = cpu_to_le32(tmp);
174 tmp = (u32) ((u64)dma_addr >> 32);
175 pSge->Address.High = cpu_to_le32(tmp);
176
177 } else {
178 SGESimple32_t *pSge = (SGESimple32_t *) pAddr;
179 pSge->FlagsLength = cpu_to_le32(flagslength);
180 pSge->Address = cpu_to_le32(dma_addr);
181 }
182} /* mptscsih_add_sge() */
183
184/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
185/**
186 * mptscsih_add_chain - Place a chain SGE at address pAddr.
187 * @pAddr: virtual address for SGE
188 * @next: nextChainOffset value (u32's)
189 * @length: length of next SGL segment
190 * @dma_addr: Physical address
191 *
192 * This routine places a MPT request frame back on the MPT adapter's
193 * FreeQ.
194 */
195static inline void
196mptscsih_add_chain(char *pAddr, u8 next, u16 length, dma_addr_t dma_addr)
197{
198 if (sizeof(dma_addr_t) == sizeof(u64)) {
199 SGEChain64_t *pChain = (SGEChain64_t *) pAddr;
200 u32 tmp = dma_addr & 0xFFFFFFFF;
201
202 pChain->Length = cpu_to_le16(length);
203 pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();
204
205 pChain->NextChainOffset = next;
206
207 pChain->Address.Low = cpu_to_le32(tmp);
208 tmp = (u32) ((u64)dma_addr >> 32);
209 pChain->Address.High = cpu_to_le32(tmp);
210 } else {
211 SGEChain32_t *pChain = (SGEChain32_t *) pAddr;
212 pChain->Length = cpu_to_le16(length);
213 pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();
214 pChain->NextChainOffset = next;
215 pChain->Address = cpu_to_le32(dma_addr);
216 }
217} /* mptscsih_add_chain() */
218
219/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
220/*
221 * mptscsih_getFreeChainBuffer - Function to get a free chain
222 * from the MPT_SCSI_HOST FreeChainQ.
223 * @ioc: Pointer to MPT_ADAPTER structure
224 * @req_idx: Index of the SCSI IO request frame. (output)
225 *
226 * return SUCCESS or FAILED
227 */
228static inline int
229mptscsih_getFreeChainBuffer(MPT_ADAPTER *ioc, int *retIndex)
230{
231 MPT_FRAME_HDR *chainBuf;
232 unsigned long flags;
233 int rc;
234 int chain_idx;
235
236 dsgprintk((MYIOC_s_INFO_FMT "getFreeChainBuffer called\n",
237 ioc->name));
238 spin_lock_irqsave(&ioc->FreeQlock, flags);
239 if (!list_empty(&ioc->FreeChainQ)) {
240 int offset;
241
242 chainBuf = list_entry(ioc->FreeChainQ.next, MPT_FRAME_HDR,
243 u.frame.linkage.list);
244 list_del(&chainBuf->u.frame.linkage.list);
245 offset = (u8 *)chainBuf - (u8 *)ioc->ChainBuffer;
246 chain_idx = offset / ioc->req_sz;
247 rc = SUCCESS;
c6678e0c
CH
248 dsgprintk((MYIOC_s_ERR_FMT "getFreeChainBuffer chainBuf=%p ChainBuffer=%p offset=%d chain_idx=%d\n",
249 ioc->name, chainBuf, ioc->ChainBuffer, offset, chain_idx));
1da177e4
LT
250 } else {
251 rc = FAILED;
252 chain_idx = MPT_HOST_NO_CHAIN;
c6678e0c 253 dfailprintk((MYIOC_s_INFO_FMT "getFreeChainBuffer failed\n",
1da177e4
LT
254 ioc->name));
255 }
256 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
257
258 *retIndex = chain_idx;
259 return rc;
260} /* mptscsih_getFreeChainBuffer() */
261
262/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
263/*
264 * mptscsih_AddSGE - Add a SGE (plus chain buffers) to the
265 * SCSIIORequest_t Message Frame.
266 * @ioc: Pointer to MPT_ADAPTER structure
267 * @SCpnt: Pointer to scsi_cmnd structure
268 * @pReq: Pointer to SCSIIORequest_t structure
269 *
270 * Returns ...
271 */
272static int
273mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt,
274 SCSIIORequest_t *pReq, int req_idx)
275{
276 char *psge;
277 char *chainSge;
278 struct scatterlist *sg;
279 int frm_sz;
280 int sges_left, sg_done;
281 int chain_idx = MPT_HOST_NO_CHAIN;
282 int sgeOffset;
283 int numSgeSlots, numSgeThisFrame;
284 u32 sgflags, sgdir, thisxfer = 0;
285 int chain_dma_off = 0;
286 int newIndex;
287 int ii;
288 dma_addr_t v2;
289 u32 RequestNB;
290
291 sgdir = le32_to_cpu(pReq->Control) & MPI_SCSIIO_CONTROL_DATADIRECTION_MASK;
292 if (sgdir == MPI_SCSIIO_CONTROL_WRITE) {
293 sgdir = MPT_TRANSFER_HOST_TO_IOC;
294 } else {
295 sgdir = MPT_TRANSFER_IOC_TO_HOST;
296 }
297
298 psge = (char *) &pReq->SGL;
299 frm_sz = ioc->req_sz;
300
301 /* Map the data portion, if any.
302 * sges_left = 0 if no data transfer.
303 */
304 if ( (sges_left = SCpnt->use_sg) ) {
305 sges_left = pci_map_sg(ioc->pcidev,
306 (struct scatterlist *) SCpnt->request_buffer,
307 SCpnt->use_sg,
308 SCpnt->sc_data_direction);
309 if (sges_left == 0)
310 return FAILED;
311 } else if (SCpnt->request_bufflen) {
312 SCpnt->SCp.dma_handle = pci_map_single(ioc->pcidev,
313 SCpnt->request_buffer,
314 SCpnt->request_bufflen,
315 SCpnt->sc_data_direction);
316 dsgprintk((MYIOC_s_INFO_FMT "SG: non-SG for %p, len=%d\n",
317 ioc->name, SCpnt, SCpnt->request_bufflen));
318 mptscsih_add_sge((char *) &pReq->SGL,
319 0xD1000000|MPT_SGE_FLAGS_ADDRESSING|sgdir|SCpnt->request_bufflen,
320 SCpnt->SCp.dma_handle);
321
322 return SUCCESS;
323 }
324
325 /* Handle the SG case.
326 */
327 sg = (struct scatterlist *) SCpnt->request_buffer;
328 sg_done = 0;
329 sgeOffset = sizeof(SCSIIORequest_t) - sizeof(SGE_IO_UNION);
330 chainSge = NULL;
331
332 /* Prior to entering this loop - the following must be set
333 * current MF: sgeOffset (bytes)
334 * chainSge (Null if original MF is not a chain buffer)
335 * sg_done (num SGE done for this MF)
336 */
337
338nextSGEset:
339 numSgeSlots = ((frm_sz - sgeOffset) / (sizeof(u32) + sizeof(dma_addr_t)) );
340 numSgeThisFrame = (sges_left < numSgeSlots) ? sges_left : numSgeSlots;
341
342 sgflags = MPT_SGE_FLAGS_SIMPLE_ELEMENT | MPT_SGE_FLAGS_ADDRESSING | sgdir;
343
344 /* Get first (num - 1) SG elements
345 * Skip any SG entries with a length of 0
346 * NOTE: at finish, sg and psge pointed to NEXT data/location positions
347 */
348 for (ii=0; ii < (numSgeThisFrame-1); ii++) {
349 thisxfer = sg_dma_len(sg);
350 if (thisxfer == 0) {
351 sg ++; /* Get next SG element from the OS */
352 sg_done++;
353 continue;
354 }
355
356 v2 = sg_dma_address(sg);
357 mptscsih_add_sge(psge, sgflags | thisxfer, v2);
358
359 sg++; /* Get next SG element from the OS */
360 psge += (sizeof(u32) + sizeof(dma_addr_t));
361 sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
362 sg_done++;
363 }
364
365 if (numSgeThisFrame == sges_left) {
366 /* Add last element, end of buffer and end of list flags.
367 */
368 sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT |
369 MPT_SGE_FLAGS_END_OF_BUFFER |
370 MPT_SGE_FLAGS_END_OF_LIST;
371
372 /* Add last SGE and set termination flags.
373 * Note: Last SGE may have a length of 0 - which should be ok.
374 */
375 thisxfer = sg_dma_len(sg);
376
377 v2 = sg_dma_address(sg);
378 mptscsih_add_sge(psge, sgflags | thisxfer, v2);
379 /*
380 sg++;
381 psge += (sizeof(u32) + sizeof(dma_addr_t));
382 */
383 sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
384 sg_done++;
385
386 if (chainSge) {
387 /* The current buffer is a chain buffer,
388 * but there is not another one.
389 * Update the chain element
390 * Offset and Length fields.
391 */
392 mptscsih_add_chain((char *)chainSge, 0, sgeOffset, ioc->ChainBufferDMA + chain_dma_off);
393 } else {
394 /* The current buffer is the original MF
395 * and there is no Chain buffer.
396 */
397 pReq->ChainOffset = 0;
398 RequestNB = (((sgeOffset - 1) >> ioc->NBShiftFactor) + 1) & 0x03;
c6678e0c 399 dsgprintk((MYIOC_s_INFO_FMT
1da177e4
LT
400 "Single Buffer RequestNB=%x, sgeOffset=%d\n", ioc->name, RequestNB, sgeOffset));
401 ioc->RequestNB[req_idx] = RequestNB;
402 }
403 } else {
404 /* At least one chain buffer is needed.
405 * Complete the first MF
406 * - last SGE element, set the LastElement bit
407 * - set ChainOffset (words) for orig MF
408 * (OR finish previous MF chain buffer)
409 * - update MFStructPtr ChainIndex
410 * - Populate chain element
411 * Also
412 * Loop until done.
413 */
414
415 dsgprintk((MYIOC_s_INFO_FMT "SG: Chain Required! sg done %d\n",
416 ioc->name, sg_done));
417
418 /* Set LAST_ELEMENT flag for last non-chain element
419 * in the buffer. Since psge points at the NEXT
420 * SGE element, go back one SGE element, update the flags
421 * and reset the pointer. (Note: sgflags & thisxfer are already
422 * set properly).
423 */
424 if (sg_done) {
425 u32 *ptmp = (u32 *) (psge - (sizeof(u32) + sizeof(dma_addr_t)));
426 sgflags = le32_to_cpu(*ptmp);
427 sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT;
428 *ptmp = cpu_to_le32(sgflags);
429 }
430
431 if (chainSge) {
432 /* The current buffer is a chain buffer.
433 * chainSge points to the previous Chain Element.
434 * Update its chain element Offset and Length (must
435 * include chain element size) fields.
436 * Old chain element is now complete.
437 */
438 u8 nextChain = (u8) (sgeOffset >> 2);
439 sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
440 mptscsih_add_chain((char *)chainSge, nextChain, sgeOffset, ioc->ChainBufferDMA + chain_dma_off);
441 } else {
442 /* The original MF buffer requires a chain buffer -
443 * set the offset.
444 * Last element in this MF is a chain element.
445 */
446 pReq->ChainOffset = (u8) (sgeOffset >> 2);
447 RequestNB = (((sgeOffset - 1) >> ioc->NBShiftFactor) + 1) & 0x03;
448 dsgprintk((MYIOC_s_ERR_FMT "Chain Buffer Needed, RequestNB=%x sgeOffset=%d\n", ioc->name, RequestNB, sgeOffset));
449 ioc->RequestNB[req_idx] = RequestNB;
450 }
451
452 sges_left -= sg_done;
453
454
455 /* NOTE: psge points to the beginning of the chain element
456 * in current buffer. Get a chain buffer.
457 */
c6678e0c
CH
458 if ((mptscsih_getFreeChainBuffer(ioc, &newIndex)) == FAILED) {
459 dfailprintk((MYIOC_s_INFO_FMT
460 "getFreeChainBuffer FAILED SCSI cmd=%02x (%p)\n",
461 ioc->name, pReq->CDB[0], SCpnt));
1da177e4 462 return FAILED;
c6678e0c 463 }
1da177e4
LT
464
465 /* Update the tracking arrays.
466 * If chainSge == NULL, update ReqToChain, else ChainToChain
467 */
468 if (chainSge) {
469 ioc->ChainToChain[chain_idx] = newIndex;
470 } else {
471 ioc->ReqToChain[req_idx] = newIndex;
472 }
473 chain_idx = newIndex;
474 chain_dma_off = ioc->req_sz * chain_idx;
475
476 /* Populate the chainSGE for the current buffer.
477 * - Set chain buffer pointer to psge and fill
478 * out the Address and Flags fields.
479 */
480 chainSge = (char *) psge;
481 dsgprintk((KERN_INFO " Current buff @ %p (index 0x%x)",
482 psge, req_idx));
483
484 /* Start the SGE for the next buffer
485 */
486 psge = (char *) (ioc->ChainBuffer + chain_dma_off);
487 sgeOffset = 0;
488 sg_done = 0;
489
490 dsgprintk((KERN_INFO " Chain buff @ %p (index 0x%x)\n",
491 psge, chain_idx));
492
493 /* Start the SGE for the next buffer
494 */
495
496 goto nextSGEset;
497 }
498
499 return SUCCESS;
500} /* mptscsih_AddSGE() */
501
786899b0
EM
502static void
503mptscsih_issue_sep_command(MPT_ADAPTER *ioc, VirtTarget *vtarget,
504 U32 SlotStatus)
505{
506 MPT_FRAME_HDR *mf;
507 SEPRequest_t *SEPMsg;
508
509 if (ioc->bus_type == FC)
510 return;
511
512 if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) {
513 dfailprintk((MYIOC_s_WARN_FMT "%s: no msg frames!!\n",
514 ioc->name,__FUNCTION__));
515 return;
516 }
517
518 SEPMsg = (SEPRequest_t *)mf;
519 SEPMsg->Function = MPI_FUNCTION_SCSI_ENCLOSURE_PROCESSOR;
520 SEPMsg->Bus = vtarget->bus_id;
521 SEPMsg->TargetID = vtarget->target_id;
522 SEPMsg->Action = MPI_SEP_REQ_ACTION_WRITE_STATUS;
523 SEPMsg->SlotStatus = SlotStatus;
524 devtverboseprintk((MYIOC_s_WARN_FMT
525 "Sending SEP cmd=%x id=%d bus=%d\n",
526 ioc->name, SlotStatus, SEPMsg->TargetID, SEPMsg->Bus));
527 mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
528}
529
1da177e4
LT
530/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
531/*
532 * mptscsih_io_done - Main SCSI IO callback routine registered to
533 * Fusion MPT (base) driver
534 * @ioc: Pointer to MPT_ADAPTER structure
535 * @mf: Pointer to original MPT request frame
536 * @r: Pointer to MPT reply frame (NULL if TurboReply)
537 *
538 * This routine is called from mpt.c::mpt_interrupt() at the completion
539 * of any SCSI IO request.
540 * This routine is registered with the Fusion MPT (base) driver at driver
541 * load/init time via the mpt_register() API call.
542 *
543 * Returns 1 indicating alloc'd request frame ptr should be freed.
544 */
0d0c7974 545int
1da177e4
LT
546mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
547{
548 struct scsi_cmnd *sc;
549 MPT_SCSI_HOST *hd;
550 SCSIIORequest_t *pScsiReq;
551 SCSIIOReply_t *pScsiReply;
2254c86d 552 u16 req_idx, req_idx_MR;
786899b0
EM
553 VirtDevice *vdev;
554 VirtTarget *vtarget;
1da177e4
LT
555
556 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
557
558 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
2254c86d
ME
559 req_idx_MR = (mr != NULL) ?
560 le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx) : req_idx;
561 if ((req_idx != req_idx_MR) ||
562 (mf->u.frame.linkage.arg1 == 0xdeadbeaf)) {
563 printk(MYIOC_s_ERR_FMT "Received a mf that was already freed\n",
564 ioc->name);
565 printk (MYIOC_s_ERR_FMT
566 "req_idx=%x req_idx_MR=%x mf=%p mr=%p sc=%p\n",
567 ioc->name, req_idx, req_idx_MR, mf, mr,
568 hd->ScsiLookup[req_idx_MR]);
569 return 0;
570 }
571
1da177e4 572 sc = hd->ScsiLookup[req_idx];
3dc0b03f 573 hd->ScsiLookup[req_idx] = NULL;
1da177e4
LT
574 if (sc == NULL) {
575 MPIHeader_t *hdr = (MPIHeader_t *)mf;
576
577 /* Remark: writeSDP1 will use the ScsiDoneCtx
578 * If a SCSI I/O cmd, device disabled by OS and
579 * completion done. Cannot touch sc struct. Just free mem.
580 */
581 if (hdr->Function == MPI_FUNCTION_SCSI_IO_REQUEST)
582 printk(MYIOC_s_ERR_FMT "NULL ScsiCmd ptr!\n",
583 ioc->name);
584
585 mptscsih_freeChainBuffers(ioc, req_idx);
586 return 1;
587 }
588
3dc0b03f
EM
589 if ((unsigned char *)mf != sc->host_scribble) {
590 mptscsih_freeChainBuffers(ioc, req_idx);
591 return 1;
592 }
593
594 sc->host_scribble = NULL;
1da177e4
LT
595 sc->result = DID_OK << 16; /* Set default reply as OK */
596 pScsiReq = (SCSIIORequest_t *) mf;
597 pScsiReply = (SCSIIOReply_t *) mr;
598
c6678e0c
CH
599 if((ioc->facts.MsgVersion >= MPI_VERSION_01_05) && pScsiReply){
600 dmfprintk((MYIOC_s_INFO_FMT
601 "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d,task-tag=%d)\n",
602 ioc->name, mf, mr, sc, req_idx, pScsiReply->TaskTag));
603 }else{
604 dmfprintk((MYIOC_s_INFO_FMT
605 "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d)\n",
606 ioc->name, mf, mr, sc, req_idx));
607 }
608
1da177e4
LT
609 if (pScsiReply == NULL) {
610 /* special context reply handling */
611 ;
612 } else {
613 u32 xfer_cnt;
614 u16 status;
615 u8 scsi_state, scsi_status;
616
617 status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK;
618 scsi_state = pScsiReply->SCSIState;
619 scsi_status = pScsiReply->SCSIStatus;
620 xfer_cnt = le32_to_cpu(pScsiReply->TransferCount);
621 sc->resid = sc->request_bufflen - xfer_cnt;
622
466544d8
MED
623 /*
624 * if we get a data underrun indication, yet no data was
625 * transferred and the SCSI status indicates that the
626 * command was never started, change the data underrun
627 * to success
628 */
629 if (status == MPI_IOCSTATUS_SCSI_DATA_UNDERRUN && xfer_cnt == 0 &&
630 (scsi_status == MPI_SCSI_STATUS_BUSY ||
631 scsi_status == MPI_SCSI_STATUS_RESERVATION_CONFLICT ||
632 scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL)) {
633 status = MPI_IOCSTATUS_SUCCESS;
634 }
635
1da177e4
LT
636 dreplyprintk((KERN_NOTICE "Reply ha=%d id=%d lun=%d:\n"
637 "IOCStatus=%04xh SCSIState=%02xh SCSIStatus=%02xh\n"
638 "resid=%d bufflen=%d xfer_cnt=%d\n",
c7c82987 639 ioc->id, sc->device->id, sc->device->lun,
466544d8 640 status, scsi_state, scsi_status, sc->resid,
1da177e4
LT
641 sc->request_bufflen, xfer_cnt));
642
643 if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID)
0d0c7974
MED
644 mptscsih_copy_sense_data(sc, hd, mf, pScsiReply);
645
1da177e4
LT
646 /*
647 * Look for + dump FCP ResponseInfo[]!
648 */
466544d8
MED
649 if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID &&
650 pScsiReply->ResponseInfo) {
651 printk(KERN_NOTICE "ha=%d id=%d lun=%d: "
652 "FCP_ResponseInfo=%08xh\n",
c7c82987 653 ioc->id, sc->device->id, sc->device->lun,
1da177e4
LT
654 le32_to_cpu(pScsiReply->ResponseInfo));
655 }
656
657 switch(status) {
658 case MPI_IOCSTATUS_BUSY: /* 0x0002 */
659 /* CHECKME!
660 * Maybe: DRIVER_BUSY | SUGGEST_RETRY | DID_SOFT_ERROR (retry)
661 * But not: DID_BUS_BUSY lest one risk
662 * killing interrupt handler:-(
663 */
664 sc->result = SAM_STAT_BUSY;
665 break;
666
667 case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
668 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
669 sc->result = DID_BAD_TARGET << 16;
670 break;
671
672 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
673 /* Spoof to SCSI Selection Timeout! */
65207fed
ME
674 if (ioc->bus_type != FC)
675 sc->result = DID_NO_CONNECT << 16;
676 /* else fibre, just stall until rescan event */
677 else
678 sc->result = DID_REQUEUE << 16;
1da177e4
LT
679
680 if (hd->sel_timeout[pScsiReq->TargetID] < 0xFFFF)
681 hd->sel_timeout[pScsiReq->TargetID]++;
786899b0
EM
682
683 vdev = sc->device->hostdata;
684 if (!vdev)
685 break;
686 vtarget = vdev->vtarget;
687 if (vtarget->tflags & MPT_TARGET_FLAGS_LED_ON) {
688 mptscsih_issue_sep_command(ioc, vtarget,
689 MPI_SEP_REQ_SLOTSTATUS_UNCONFIGURED);
690 vtarget->tflags &= ~MPT_TARGET_FLAGS_LED_ON;
691 }
1da177e4
LT
692 break;
693
1da177e4 694 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
bf451522
EM
695 if ( ioc->bus_type == SAS ) {
696 u16 ioc_status = le16_to_cpu(pScsiReply->IOCStatus);
697 if (ioc_status & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
698 u32 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo);
699 log_info &=SAS_LOGINFO_MASK;
700 if (log_info == SAS_LOGINFO_NEXUS_LOSS) {
701 sc->result = (DID_BUS_BUSY << 16);
702 break;
703 }
704 }
86dd4242
EM
705 } else if (ioc->bus_type == FC) {
706 /*
707 * The FC IOC may kill a request for variety of
708 * reasons, some of which may be recovered by a
709 * retry, some which are unlikely to be
710 * recovered. Return DID_ERROR instead of
711 * DID_RESET to permit retry of the command,
712 * just not an infinite number of them
713 */
714 sc->result = DID_ERROR << 16;
715 break;
bf451522
EM
716 }
717
718 /*
719 * Allow non-SAS & non-NEXUS_LOSS to drop into below code
720 */
721
722 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
1da177e4
LT
723 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
724 /* Linux handles an unsolicited DID_RESET better
725 * than an unsolicited DID_ABORT.
726 */
727 sc->result = DID_RESET << 16;
728
1da177e4
LT
729 break;
730
731 case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
466544d8
MED
732 sc->resid = sc->request_bufflen - xfer_cnt;
733 if((xfer_cnt==0)||(sc->underflow > xfer_cnt))
734 sc->result=DID_SOFT_ERROR << 16;
735 else /* Sufficient data transfer occurred */
1da177e4 736 sc->result = (DID_OK << 16) | scsi_status;
3dc0b03f 737 dreplyprintk((KERN_NOTICE
466544d8 738 "RESIDUAL_MISMATCH: result=%x on id=%d\n", sc->result, sc->device->id));
1da177e4 739 break;
0d0c7974 740
1da177e4
LT
741 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
742 /*
743 * Do upfront check for valid SenseData and give it
744 * precedence!
745 */
746 sc->result = (DID_OK << 16) | scsi_status;
747 if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
748 /* Have already saved the status and sense data
749 */
750 ;
751 } else {
752 if (xfer_cnt < sc->underflow) {
466544d8
MED
753 if (scsi_status == SAM_STAT_BUSY)
754 sc->result = SAM_STAT_BUSY;
755 else
756 sc->result = DID_SOFT_ERROR << 16;
1da177e4
LT
757 }
758 if (scsi_state & (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)) {
759 /* What to do?
760 */
761 sc->result = DID_SOFT_ERROR << 16;
762 }
763 else if (scsi_state & MPI_SCSI_STATE_TERMINATED) {
764 /* Not real sure here either... */
765 sc->result = DID_RESET << 16;
766 }
767 }
768
769 dreplyprintk((KERN_NOTICE " sc->underflow={report ERR if < %02xh bytes xfer'd}\n",
770 sc->underflow));
771 dreplyprintk((KERN_NOTICE " ActBytesXferd=%02xh\n", xfer_cnt));
772 /* Report Queue Full
773 */
774 if (scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL)
775 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
0d0c7974 776
1da177e4
LT
777 break;
778
7e55147f
ME
779 case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
780 sc->resid=0;
1da177e4
LT
781 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
782 case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */
466544d8
MED
783 if (scsi_status == MPI_SCSI_STATUS_BUSY)
784 sc->result = (DID_BUS_BUSY << 16) | scsi_status;
785 else
786 sc->result = (DID_OK << 16) | scsi_status;
1da177e4
LT
787 if (scsi_state == 0) {
788 ;
789 } else if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
790 /*
791 * If running against circa 200003dd 909 MPT f/w,
792 * may get this (AUTOSENSE_VALID) for actual TASK_SET_FULL
793 * (QUEUE_FULL) returned from device! --> get 0x0000?128
794 * and with SenseBytes set to 0.
795 */
796 if (pScsiReply->SCSIStatus == MPI_SCSI_STATUS_TASK_SET_FULL)
797 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
798
799 }
800 else if (scsi_state &
801 (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)
802 ) {
803 /*
804 * What to do?
805 */
806 sc->result = DID_SOFT_ERROR << 16;
807 }
808 else if (scsi_state & MPI_SCSI_STATE_TERMINATED) {
809 /* Not real sure here either... */
810 sc->result = DID_RESET << 16;
811 }
812 else if (scsi_state & MPI_SCSI_STATE_QUEUE_TAG_REJECTED) {
813 /* Device Inq. data indicates that it supports
814 * QTags, but rejects QTag messages.
815 * This command completed OK.
816 *
817 * Not real sure here either so do nothing... */
818 }
819
820 if (sc->result == MPI_SCSI_STATUS_TASK_SET_FULL)
821 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
822
823 /* Add handling of:
824 * Reservation Conflict, Busy,
825 * Command Terminated, CHECK
826 */
827 break;
828
829 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
830 sc->result = DID_SOFT_ERROR << 16;
831 break;
832
833 case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */
834 case MPI_IOCSTATUS_INVALID_SGL: /* 0x0003 */
835 case MPI_IOCSTATUS_INTERNAL_ERROR: /* 0x0004 */
836 case MPI_IOCSTATUS_RESERVED: /* 0x0005 */
837 case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */
838 case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */
839 case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */
1da177e4
LT
840 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
841 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
842 default:
843 /*
844 * What to do?
845 */
846 sc->result = DID_SOFT_ERROR << 16;
847 break;
848
849 } /* switch(status) */
850
851 dreplyprintk((KERN_NOTICE " sc->result is %08xh\n", sc->result));
852 } /* end of address reply case */
853
854 /* Unmap the DMA buffers, if any. */
855 if (sc->use_sg) {
856 pci_unmap_sg(ioc->pcidev, (struct scatterlist *) sc->request_buffer,
857 sc->use_sg, sc->sc_data_direction);
858 } else if (sc->request_bufflen) {
859 pci_unmap_single(ioc->pcidev, sc->SCp.dma_handle,
860 sc->request_bufflen, sc->sc_data_direction);
861 }
862
1da177e4
LT
863 sc->scsi_done(sc); /* Issue the command callback */
864
865 /* Free Chain buffers */
866 mptscsih_freeChainBuffers(ioc, req_idx);
867 return 1;
868}
869
1da177e4
LT
870/*
871 * mptscsih_flush_running_cmds - For each command found, search
872 * Scsi_Host instance taskQ and reply to OS.
873 * Called only if recovering from a FW reload.
874 * @hd: Pointer to a SCSI HOST structure
875 *
876 * Returns: None.
877 *
878 * Must be called while new I/Os are being queued.
879 */
880static void
881mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
882{
883 MPT_ADAPTER *ioc = hd->ioc;
884 struct scsi_cmnd *SCpnt;
885 MPT_FRAME_HDR *mf;
886 int ii;
887 int max = ioc->req_depth;
888
889 dprintk((KERN_INFO MYNAM ": flush_ScsiLookup called\n"));
890 for (ii= 0; ii < max; ii++) {
891 if ((SCpnt = hd->ScsiLookup[ii]) != NULL) {
892
893 /* Command found.
894 */
895
896 /* Null ScsiLookup index
897 */
898 hd->ScsiLookup[ii] = NULL;
899
900 mf = MPT_INDEX_2_MFPTR(ioc, ii);
901 dmfprintk(( "flush: ScsiDone (mf=%p,sc=%p)\n",
902 mf, SCpnt));
903
3dc0b03f
EM
904 /* Free Chain buffers */
905 mptscsih_freeChainBuffers(ioc, ii);
906
907 /* Free Message frames */
908 mpt_free_msg_frame(ioc, mf);
909
910 if ((unsigned char *)mf != SCpnt->host_scribble)
911 continue;
912
1da177e4
LT
913 /* Set status, free OS resources (SG DMA buffers)
914 * Do OS callback
1da177e4 915 */
0d0c7974
MED
916 if (SCpnt->use_sg) {
917 pci_unmap_sg(ioc->pcidev,
918 (struct scatterlist *) SCpnt->request_buffer,
919 SCpnt->use_sg,
920 SCpnt->sc_data_direction);
921 } else if (SCpnt->request_bufflen) {
922 pci_unmap_single(ioc->pcidev,
923 SCpnt->SCp.dma_handle,
924 SCpnt->request_bufflen,
925 SCpnt->sc_data_direction);
1da177e4
LT
926 }
927 SCpnt->result = DID_RESET << 16;
928 SCpnt->host_scribble = NULL;
929
1da177e4
LT
930 SCpnt->scsi_done(SCpnt); /* Issue the command callback */
931 }
932 }
933
934 return;
935}
936
937/*
938 * mptscsih_search_running_cmds - Delete any commands associated
939 * with the specified target and lun. Function called only
940 * when a lun is disable by mid-layer.
941 * Do NOT access the referenced scsi_cmnd structure or
942 * members. Will cause either a paging or NULL ptr error.
05e8ec17 943 * (BUT, BUT, BUT, the code does reference it! - mdr)
c7c82987
MED
944 * @hd: Pointer to a SCSI HOST structure
945 * @vdevice: per device private data
1da177e4
LT
946 *
947 * Returns: None.
948 *
949 * Called from slave_destroy.
950 */
951static void
c7c82987 952mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
1da177e4
LT
953{
954 SCSIIORequest_t *mf = NULL;
955 int ii;
956 int max = hd->ioc->req_depth;
466544d8 957 struct scsi_cmnd *sc;
1da177e4
LT
958
959 dsprintk((KERN_INFO MYNAM ": search_running target %d lun %d max %d\n",
bd23e94c 960 vdevice->vtarget->target_id, vdevice->lun, max));
1da177e4
LT
961
962 for (ii=0; ii < max; ii++) {
466544d8 963 if ((sc = hd->ScsiLookup[ii]) != NULL) {
1da177e4
LT
964
965 mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(hd->ioc, ii);
3dc0b03f
EM
966 if (mf == NULL)
967 continue;
1da177e4
LT
968 dsprintk(( "search_running: found (sc=%p, mf = %p) target %d, lun %d \n",
969 hd->ScsiLookup[ii], mf, mf->TargetID, mf->LUN[1]));
914c2d8e 970 if ((mf->TargetID != ((u8)vdevice->vtarget->target_id)) || (mf->LUN[1] != ((u8) vdevice->lun)))
1da177e4
LT
971 continue;
972
973 /* Cleanup
974 */
975 hd->ScsiLookup[ii] = NULL;
976 mptscsih_freeChainBuffers(hd->ioc, ii);
977 mpt_free_msg_frame(hd->ioc, (MPT_FRAME_HDR *)mf);
3dc0b03f
EM
978 if ((unsigned char *)mf != sc->host_scribble)
979 continue;
466544d8
MED
980 if (sc->use_sg) {
981 pci_unmap_sg(hd->ioc->pcidev,
982 (struct scatterlist *) sc->request_buffer,
983 sc->use_sg,
984 sc->sc_data_direction);
985 } else if (sc->request_bufflen) {
986 pci_unmap_single(hd->ioc->pcidev,
987 sc->SCp.dma_handle,
988 sc->request_bufflen,
989 sc->sc_data_direction);
990 }
991 sc->host_scribble = NULL;
992 sc->result = DID_NO_CONNECT << 16;
993 sc->scsi_done(sc);
1da177e4
LT
994 }
995 }
1da177e4
LT
996 return;
997}
998
999/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1da177e4
LT
1000
1001/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1002/*
1003 * mptscsih_report_queue_full - Report QUEUE_FULL status returned
1004 * from a SCSI target device.
1005 * @sc: Pointer to scsi_cmnd structure
1006 * @pScsiReply: Pointer to SCSIIOReply_t
1007 * @pScsiReq: Pointer to original SCSI request
1008 *
1009 * This routine periodically reports QUEUE_FULL status returned from a
1010 * SCSI target device. It reports this to the console via kernel
1011 * printk() API call, not more than once every 10 seconds.
1012 */
1013static void
1014mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq)
1015{
1016 long time = jiffies;
1da177e4 1017 MPT_SCSI_HOST *hd;
1da177e4 1018
0d0c7974
MED
1019 if (sc->device == NULL)
1020 return;
1021 if (sc->device->host == NULL)
1022 return;
1023 if ((hd = (MPT_SCSI_HOST *)sc->device->host->hostdata) == NULL)
1024 return;
1da177e4 1025
0d0c7974
MED
1026 if (time - hd->last_queue_full > 10 * HZ) {
1027 dprintk((MYIOC_s_WARN_FMT "Device (%d:%d:%d) reported QUEUE_FULL!\n",
1028 hd->ioc->name, 0, sc->device->id, sc->device->lun));
1029 hd->last_queue_full = time;
1da177e4 1030 }
1da177e4
LT
1031}
1032
1033/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1034/*
1035 * mptscsih_remove - Removed scsi devices
1036 * @pdev: Pointer to pci_dev structure
1037 *
1038 *
1039 */
0d0c7974 1040void
1da177e4
LT
1041mptscsih_remove(struct pci_dev *pdev)
1042{
1043 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1044 struct Scsi_Host *host = ioc->sh;
1045 MPT_SCSI_HOST *hd;
0d0c7974 1046 int sz1;
1da177e4 1047
466544d8
MED
1048 if(!host) {
1049 mpt_detach(pdev);
1da177e4 1050 return;
466544d8 1051 }
1da177e4
LT
1052
1053 scsi_remove_host(host);
1054
0d0c7974
MED
1055 if((hd = (MPT_SCSI_HOST *)host->hostdata) == NULL)
1056 return;
1057
d18c3db5 1058 mptscsih_shutdown(pdev);
1da177e4 1059
0d0c7974 1060 sz1=0;
1da177e4 1061
0d0c7974
MED
1062 if (hd->ScsiLookup != NULL) {
1063 sz1 = hd->ioc->req_depth * sizeof(void *);
1064 kfree(hd->ScsiLookup);
1065 hd->ScsiLookup = NULL;
1066 }
1da177e4 1067
d485eb83
MED
1068 /*
1069 * Free pointer array.
1070 */
1071 kfree(hd->Targets);
1072 hd->Targets = NULL;
1da177e4 1073
0d0c7974
MED
1074 dprintk((MYIOC_s_INFO_FMT
1075 "Free'd ScsiLookup (%d) memory\n",
1076 hd->ioc->name, sz1));
1da177e4 1077
d485eb83 1078 kfree(hd->info_kbuf);
1da177e4 1079
0d0c7974
MED
1080 /* NULL the Scsi_Host pointer
1081 */
1082 hd->ioc->sh = NULL;
1da177e4
LT
1083
1084 scsi_host_put(host);
1da177e4 1085
0d0c7974 1086 mpt_detach(pdev);
c6678e0c 1087
1da177e4
LT
1088}
1089
1090/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1091/*
1092 * mptscsih_shutdown - reboot notifier
1093 *
1094 */
0d0c7974 1095void
d18c3db5 1096mptscsih_shutdown(struct pci_dev *pdev)
1da177e4 1097{
d18c3db5 1098 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1da177e4
LT
1099 struct Scsi_Host *host = ioc->sh;
1100 MPT_SCSI_HOST *hd;
1101
1102 if(!host)
1103 return;
1104
1105 hd = (MPT_SCSI_HOST *)host->hostdata;
1106
1da177e4
LT
1107}
1108
1109#ifdef CONFIG_PM
1110/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1111/*
0d0c7974 1112 * mptscsih_suspend - Fusion MPT scsi driver suspend routine.
1da177e4
LT
1113 *
1114 *
1115 */
0d0c7974 1116int
8d189f72 1117mptscsih_suspend(struct pci_dev *pdev, pm_message_t state)
1da177e4 1118{
d18c3db5 1119 mptscsih_shutdown(pdev);
0d0c7974 1120 return mpt_suspend(pdev,state);
1da177e4
LT
1121}
1122
1123/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1124/*
1125 * mptscsih_resume - Fusion MPT scsi driver resume routine.
1126 *
1127 *
1128 */
0d0c7974 1129int
1da177e4
LT
1130mptscsih_resume(struct pci_dev *pdev)
1131{
1132 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1133 struct Scsi_Host *host = ioc->sh;
1134 MPT_SCSI_HOST *hd;
1135
0d0c7974 1136 mpt_resume(pdev);
c6678e0c 1137
1da177e4
LT
1138 if(!host)
1139 return 0;
1140
1141 hd = (MPT_SCSI_HOST *)host->hostdata;
1142 if(!hd)
1143 return 0;
1144
1da177e4
LT
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
d9489fb6
RD
1245 * @host: scsi host struct
1246 * @buffer: if write, user data; if read, buffer for user
1247 * @start: returns the buffer address
1248 * @offset: if write, 0; if read, the current offset into the buffer from
1249 * the previous read.
1250 * @length: if write, return length;
1251 * @func: write = 1; read = 0
1da177e4
LT
1252 *
1253 * (linux scsi_host_template.info routine)
1da177e4 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
f44e5461
ME
1320 if ((hd->ioc->bus_type == SPI) &&
1321 vdev->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT &&
c92f222e
JB
1322 mptscsih_raid_id_to_num(hd, SCpnt->device->id) < 0) {
1323 SCpnt->result = DID_NO_CONNECT << 16;
1324 done(SCpnt);
1325 return 0;
1326 }
1327
1da177e4
LT
1328 /*
1329 * Put together a MPT SCSI request...
1330 */
0d0c7974 1331 if ((mf = mpt_get_msg_frame(hd->ioc->DoneCtx, hd->ioc)) == NULL) {
1da177e4
LT
1332 dprintk((MYIOC_s_WARN_FMT "QueueCmd, no msg frames!!\n",
1333 hd->ioc->name));
1334 return SCSI_MLQUEUE_HOST_BUSY;
1335 }
1336
1337 pScsiReq = (SCSIIORequest_t *) mf;
1338
1339 my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
1340
1341 ADD_INDEX_LOG(my_idx);
1342
0d0c7974 1343 /* TUR's being issued with scsictl=0x02000000 (DATA_IN)!
1da177e4
LT
1344 * Seems we may receive a buffer (datalen>0) even when there
1345 * will be no data transfer! GRRRRR...
1346 */
1347 if (SCpnt->sc_data_direction == DMA_FROM_DEVICE) {
1348 datalen = SCpnt->request_bufflen;
1349 scsidir = MPI_SCSIIO_CONTROL_READ; /* DATA IN (host<--ioc<--dev) */
1350 } else if (SCpnt->sc_data_direction == DMA_TO_DEVICE) {
1351 datalen = SCpnt->request_bufflen;
1352 scsidir = MPI_SCSIIO_CONTROL_WRITE; /* DATA OUT (host-->ioc-->dev) */
1353 } else {
1354 datalen = 0;
1355 scsidir = MPI_SCSIIO_CONTROL_NODATATRANSFER;
1356 }
1357
1358 /* Default to untagged. Once a target structure has been allocated,
1359 * use the Inquiry data to determine if device supports tagged.
1360 */
c7c82987
MED
1361 if (vdev
1362 && (vdev->vtarget->tflags & MPT_TARGET_FLAGS_Q_YES)
1da177e4
LT
1363 && (SCpnt->device->tagged_supported)) {
1364 scsictl = scsidir | MPI_SCSIIO_CONTROL_SIMPLEQ;
1365 } else {
1366 scsictl = scsidir | MPI_SCSIIO_CONTROL_UNTAGGED;
1367 }
1368
1369 /* Use the above information to set up the message frame
1370 */
914c2d8e
ME
1371 pScsiReq->TargetID = (u8) vdev->vtarget->target_id;
1372 pScsiReq->Bus = vdev->vtarget->bus_id;
1da177e4 1373 pScsiReq->ChainOffset = 0;
c92f222e
JB
1374 if (vdev->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT)
1375 pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
1376 else
1377 pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
1da177e4
LT
1378 pScsiReq->CDBLength = SCpnt->cmd_len;
1379 pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
1380 pScsiReq->Reserved = 0;
1381 pScsiReq->MsgFlags = mpt_msg_flags();
1382 pScsiReq->LUN[0] = 0;
1383 pScsiReq->LUN[1] = lun;
1384 pScsiReq->LUN[2] = 0;
1385 pScsiReq->LUN[3] = 0;
1386 pScsiReq->LUN[4] = 0;
1387 pScsiReq->LUN[5] = 0;
1388 pScsiReq->LUN[6] = 0;
1389 pScsiReq->LUN[7] = 0;
1390 pScsiReq->Control = cpu_to_le32(scsictl);
1391
1392 /*
1393 * Write SCSI CDB into the message
1394 */
1395 cmd_len = SCpnt->cmd_len;
1396 for (ii=0; ii < cmd_len; ii++)
1397 pScsiReq->CDB[ii] = SCpnt->cmnd[ii];
1398
1399 for (ii=cmd_len; ii < 16; ii++)
1400 pScsiReq->CDB[ii] = 0;
1401
1402 /* DataLength */
1403 pScsiReq->DataLength = cpu_to_le32(datalen);
1404
1405 /* SenseBuffer low address */
1406 pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma
1407 + (my_idx * MPT_SENSE_BUFFER_ALLOC));
1408
1409 /* Now add the SG list
1410 * Always have a SGE even if null length.
1411 */
1412 if (datalen == 0) {
1413 /* Add a NULL SGE */
1414 mptscsih_add_sge((char *)&pScsiReq->SGL, MPT_SGE_FLAGS_SSIMPLE_READ | 0,
1415 (dma_addr_t) -1);
1416 } else {
1417 /* Add a 32 or 64 bit SGE */
1418 if (mptscsih_AddSGE(hd->ioc, SCpnt, pScsiReq, my_idx) != SUCCESS)
1419 goto fail;
1420 }
1421
3dc0b03f 1422 SCpnt->host_scribble = (unsigned char *)mf;
1da177e4 1423 hd->ScsiLookup[my_idx] = SCpnt;
1da177e4 1424
0d0c7974 1425 mpt_put_msg_frame(hd->ioc->DoneCtx, hd->ioc, mf);
1da177e4
LT
1426 dmfprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n",
1427 hd->ioc->name, SCpnt, mf, my_idx));
1428 DBG_DUMP_REQUEST_FRAME(mf)
1429 return 0;
1430
1431 fail:
466544d8 1432 hd->ScsiLookup[my_idx] = NULL;
1da177e4
LT
1433 mptscsih_freeChainBuffers(hd->ioc, my_idx);
1434 mpt_free_msg_frame(hd->ioc, mf);
1435 return SCSI_MLQUEUE_HOST_BUSY;
1436}
1437
1438/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1439/*
1440 * mptscsih_freeChainBuffers - Function to free chain buffers associated
1441 * with a SCSI IO request
1442 * @hd: Pointer to the MPT_SCSI_HOST instance
1443 * @req_idx: Index of the SCSI IO request frame.
1444 *
1445 * Called if SG chain buffer allocation fails and mptscsih callbacks.
1446 * No return.
1447 */
1448static void
1449mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx)
1450{
1451 MPT_FRAME_HDR *chain;
1452 unsigned long flags;
1453 int chain_idx;
1454 int next;
1455
1456 /* Get the first chain index and reset
1457 * tracker state.
1458 */
1459 chain_idx = ioc->ReqToChain[req_idx];
1460 ioc->ReqToChain[req_idx] = MPT_HOST_NO_CHAIN;
1461
1462 while (chain_idx != MPT_HOST_NO_CHAIN) {
1463
1464 /* Save the next chain buffer index */
1465 next = ioc->ChainToChain[chain_idx];
1466
1467 /* Free this chain buffer and reset
1468 * tracker
1469 */
1470 ioc->ChainToChain[chain_idx] = MPT_HOST_NO_CHAIN;
1471
1472 chain = (MPT_FRAME_HDR *) (ioc->ChainBuffer
1473 + (chain_idx * ioc->req_sz));
1474
1475 spin_lock_irqsave(&ioc->FreeQlock, flags);
1476 list_add_tail(&chain->u.frame.linkage.list, &ioc->FreeChainQ);
1477 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
1478
1479 dmfprintk((MYIOC_s_INFO_FMT "FreeChainBuffers (index %d)\n",
1480 ioc->name, chain_idx));
1481
1482 /* handle next */
1483 chain_idx = next;
1484 }
1485 return;
1486}
1487
1488/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1489/*
1490 * Reset Handling
1491 */
1492
1493/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1494/*
1495 * mptscsih_TMHandler - Generic handler for SCSI Task Management.
1496 * Fall through to mpt_HardResetHandler if: not operational, too many
1497 * failed TM requests or handshake failure.
1498 *
1499 * @ioc: Pointer to MPT_ADAPTER structure
1500 * @type: Task Management type
1501 * @target: Logical Target ID for reset (if appropriate)
1502 * @lun: Logical Unit for reset (if appropriate)
1503 * @ctx2abort: Context for the task to be aborted (if appropriate)
1504 *
1505 * Remark: Currently invoked from a non-interrupt thread (_bh).
1506 *
1507 * Remark: With old EH code, at most 1 SCSI TaskMgmt function per IOC
1508 * will be active.
1509 *
1510 * Returns 0 for SUCCESS or -1 if FAILED.
1511 */
663e1aa1 1512int
1da177e4
LT
1513mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout)
1514{
1515 MPT_ADAPTER *ioc;
1516 int rc = -1;
1517 int doTask = 1;
1518 u32 ioc_raw_state;
1519 unsigned long flags;
1520
1521 /* If FW is being reloaded currently, return success to
1522 * the calling function.
1523 */
1524 if (hd == NULL)
1525 return 0;
1526
1527 ioc = hd->ioc;
1528 if (ioc == NULL) {
1529 printk(KERN_ERR MYNAM " TMHandler" " NULL ioc!\n");
1530 return FAILED;
1531 }
1532 dtmprintk((MYIOC_s_INFO_FMT "TMHandler Entered!\n", ioc->name));
1533
1534 // SJR - CHECKME - Can we avoid this here?
1535 // (mpt_HardResetHandler has this check...)
1536 spin_lock_irqsave(&ioc->diagLock, flags);
1537 if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)) {
1538 spin_unlock_irqrestore(&ioc->diagLock, flags);
1539 return FAILED;
1540 }
1541 spin_unlock_irqrestore(&ioc->diagLock, flags);
1542
1543 /* Wait a fixed amount of time for the TM pending flag to be cleared.
1544 * If we time out and not bus reset, then we return a FAILED status to the caller.
1545 * The call to mptscsih_tm_pending_wait() will set the pending flag if we are
1546 * successful. Otherwise, reload the FW.
1547 */
1548 if (mptscsih_tm_pending_wait(hd) == FAILED) {
1549 if (type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) {
c6678e0c 1550 dtmprintk((KERN_INFO MYNAM ": %s: TMHandler abort: "
1da177e4
LT
1551 "Timed out waiting for last TM (%d) to complete! \n",
1552 hd->ioc->name, hd->tmPending));
1553 return FAILED;
1554 } else if (type == MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET) {
c6678e0c 1555 dtmprintk((KERN_INFO MYNAM ": %s: TMHandler target reset: "
1da177e4
LT
1556 "Timed out waiting for last TM (%d) to complete! \n",
1557 hd->ioc->name, hd->tmPending));
1558 return FAILED;
1559 } else if (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
c6678e0c 1560 dtmprintk((KERN_INFO MYNAM ": %s: TMHandler bus reset: "
1da177e4
LT
1561 "Timed out waiting for last TM (%d) to complete! \n",
1562 hd->ioc->name, hd->tmPending));
1563 if (hd->tmPending & (1 << MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS))
1564 return FAILED;
1565
1566 doTask = 0;
1567 }
1568 } else {
1569 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
1570 hd->tmPending |= (1 << type);
1571 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
1572 }
1573
1574 /* Is operational?
1575 */
1576 ioc_raw_state = mpt_GetIocState(hd->ioc, 0);
1577
1578#ifdef MPT_DEBUG_RESET
1579 if ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) {
1580 printk(MYIOC_s_WARN_FMT
1581 "TM Handler: IOC Not operational(0x%x)!\n",
1582 hd->ioc->name, ioc_raw_state);
1583 }
1584#endif
1585
1586 if (doTask && ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL)
1587 && !(ioc_raw_state & MPI_DOORBELL_ACTIVE)) {
1588
1589 /* Isse the Task Mgmt request.
1590 */
1591 if (hd->hard_resets < -1)
1592 hd->hard_resets++;
1593 rc = mptscsih_IssueTaskMgmt(hd, type, channel, target, lun, ctx2abort, timeout);
1594 if (rc) {
1595 printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n", hd->ioc->name);
1596 } else {
1597 dtmprintk((MYIOC_s_INFO_FMT "Issue of TaskMgmt Successful!\n", hd->ioc->name));
1598 }
1599 }
1600
1601 /* Only fall through to the HRH if this is a bus reset
1602 */
1603 if ((type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) && (rc ||
1604 ioc->reload_fw || (ioc->alt_ioc && ioc->alt_ioc->reload_fw))) {
1605 dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
1606 hd->ioc->name));
1607 rc = mpt_HardResetHandler(hd->ioc, CAN_SLEEP);
1608 }
1609
3dc0b03f
EM
1610 /*
1611 * Check IOCStatus from TM reply message
1612 */
1613 if (hd->tm_iocstatus != MPI_IOCSTATUS_SUCCESS)
1614 rc = FAILED;
1615
1da177e4
LT
1616 dtmprintk((MYIOC_s_INFO_FMT "TMHandler rc = %d!\n", hd->ioc->name, rc));
1617
1618 return rc;
1619}
1620
1621
1622/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1623/*
1624 * mptscsih_IssueTaskMgmt - Generic send Task Management function.
1625 * @hd: Pointer to MPT_SCSI_HOST structure
1626 * @type: Task Management type
1627 * @target: Logical Target ID for reset (if appropriate)
1628 * @lun: Logical Unit for reset (if appropriate)
1629 * @ctx2abort: Context for the task to be aborted (if appropriate)
1630 *
1631 * Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
1632 * or a non-interrupt thread. In the former, must not call schedule().
1633 *
1634 * Not all fields are meaningfull for all task types.
1635 *
1636 * Returns 0 for SUCCESS, -999 for "no msg frames",
1637 * else other non-zero value returned.
1638 */
1639static int
1640mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout)
1641{
1642 MPT_FRAME_HDR *mf;
1643 SCSITaskMgmt_t *pScsiTm;
1644 int ii;
1645 int retval;
1646
1647 /* Return Fail to calling function if no message frames available.
1648 */
0d0c7974 1649 if ((mf = mpt_get_msg_frame(hd->ioc->TaskCtx, hd->ioc)) == NULL) {
1da177e4
LT
1650 dfailprintk((MYIOC_s_ERR_FMT "IssueTaskMgmt, no msg frames!!\n",
1651 hd->ioc->name));
c6678e0c 1652 return FAILED;
1da177e4
LT
1653 }
1654 dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt request @ %p\n",
1655 hd->ioc->name, mf));
1656
1657 /* Format the Request
1658 */
1659 pScsiTm = (SCSITaskMgmt_t *) mf;
1660 pScsiTm->TargetID = target;
1661 pScsiTm->Bus = channel;
1662 pScsiTm->ChainOffset = 0;
1663 pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
1664
1665 pScsiTm->Reserved = 0;
1666 pScsiTm->TaskType = type;
1667 pScsiTm->Reserved1 = 0;
1668 pScsiTm->MsgFlags = (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS)
1669 ? MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION : 0;
1670
1671 for (ii= 0; ii < 8; ii++) {
1672 pScsiTm->LUN[ii] = 0;
1673 }
1674 pScsiTm->LUN[1] = lun;
1675
1676 for (ii=0; ii < 7; ii++)
1677 pScsiTm->Reserved2[ii] = 0;
1678
1679 pScsiTm->TaskMsgContext = ctx2abort;
1680
c6678e0c
CH
1681 dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt: ctx2abort (0x%08x) type=%d\n",
1682 hd->ioc->name, ctx2abort, type));
1da177e4
LT
1683
1684 DBG_DUMP_TM_REQUEST_FRAME((u32 *)pScsiTm);
1685
0d0c7974 1686 if ((retval = mpt_send_handshake_request(hd->ioc->TaskCtx, hd->ioc,
1da177e4
LT
1687 sizeof(SCSITaskMgmt_t), (u32*)pScsiTm,
1688 CAN_SLEEP)) != 0) {
1689 dfailprintk((MYIOC_s_ERR_FMT "_send_handshake FAILED!"
1690 " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd,
1691 hd->ioc, mf));
1692 mpt_free_msg_frame(hd->ioc, mf);
1693 return retval;
1694 }
1695
1696 if(mptscsih_tm_wait_for_completion(hd, timeout) == FAILED) {
1697 dfailprintk((MYIOC_s_ERR_FMT "_wait_for_completion FAILED!"
1698 " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd,
1699 hd->ioc, mf));
1700 mpt_free_msg_frame(hd->ioc, mf);
1701 dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
1702 hd->ioc->name));
1703 retval = mpt_HardResetHandler(hd->ioc, CAN_SLEEP);
1704 }
1705
1706 return retval;
1707}
1708
d66c7a0f
CH
1709static int
1710mptscsih_get_tm_timeout(MPT_ADAPTER *ioc)
1711{
1712 switch (ioc->bus_type) {
1713 case FC:
1714 return 40;
1715 case SAS:
1716 return 10;
1717 case SPI:
1718 default:
1719 return 2;
1720 }
1721}
1722
1da177e4
LT
1723/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1724/**
1725 * mptscsih_abort - Abort linux scsi_cmnd routine, new_eh variant
1726 * @SCpnt: Pointer to scsi_cmnd structure, IO to be aborted
1727 *
1728 * (linux scsi_host_template.eh_abort_handler routine)
1729 *
1730 * Returns SUCCESS or FAILED.
1731 */
0d0c7974 1732int
1da177e4
LT
1733mptscsih_abort(struct scsi_cmnd * SCpnt)
1734{
1735 MPT_SCSI_HOST *hd;
1da177e4
LT
1736 MPT_FRAME_HDR *mf;
1737 u32 ctx2abort;
1738 int scpnt_idx;
466544d8 1739 int retval;
c7c82987 1740 VirtDevice *vdev;
3dc0b03f 1741 ulong sn = SCpnt->serial_number;
1da177e4
LT
1742
1743 /* If we can't locate our host adapter structure, return FAILED status.
1744 */
1745 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL) {
1746 SCpnt->result = DID_RESET << 16;
1747 SCpnt->scsi_done(SCpnt);
466544d8 1748 dfailprintk((KERN_INFO MYNAM ": mptscsih_abort: "
1da177e4
LT
1749 "Can't locate host! (sc=%p)\n",
1750 SCpnt));
1751 return FAILED;
1752 }
1753
1da177e4
LT
1754 /* Find this command
1755 */
1756 if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) {
466544d8 1757 /* Cmd not found in ScsiLookup.
1da177e4
LT
1758 * Do OS callback.
1759 */
1760 SCpnt->result = DID_RESET << 16;
466544d8 1761 dtmprintk((KERN_INFO MYNAM ": %s: mptscsih_abort: "
1da177e4
LT
1762 "Command not in the active list! (sc=%p)\n",
1763 hd->ioc->name, SCpnt));
1764 return SUCCESS;
1765 }
1766
65207fed
ME
1767 if (hd->resetPending) {
1768 return FAILED;
1769 }
1770
1771 if (hd->timeouts < -1)
1772 hd->timeouts++;
1773
466544d8
MED
1774 printk(KERN_WARNING MYNAM ": %s: attempting task abort! (sc=%p)\n",
1775 hd->ioc->name, SCpnt);
1776 scsi_print_command(SCpnt);
1777
1da177e4
LT
1778 /* Most important! Set TaskMsgContext to SCpnt's MsgContext!
1779 * (the IO to be ABORT'd)
1780 *
1781 * NOTE: Since we do not byteswap MsgContext, we do not
1782 * swap it here either. It is an opaque cookie to
1783 * the controller, so it does not matter. -DaveM
1784 */
1785 mf = MPT_INDEX_2_MFPTR(hd->ioc, scpnt_idx);
1786 ctx2abort = mf->u.frame.hwhdr.msgctxu.MsgContext;
1787
1788 hd->abortSCpnt = SCpnt;
1789
c7c82987 1790 vdev = SCpnt->device->hostdata;
466544d8 1791 retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
914c2d8e 1792 vdev->vtarget->bus_id, vdev->vtarget->target_id, vdev->lun,
65207fed 1793 ctx2abort, mptscsih_get_tm_timeout(hd->ioc));
1da177e4 1794
3dc0b03f
EM
1795 if (SCPNT_TO_LOOKUP_IDX(SCpnt) == scpnt_idx &&
1796 SCpnt->serial_number == sn) {
1797 retval = FAILED;
1798 }
1799
466544d8
MED
1800 printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n",
1801 hd->ioc->name,
1802 ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
1da177e4 1803
466544d8
MED
1804 if (retval == 0)
1805 return SUCCESS;
1806
1807 if(retval != FAILED ) {
1da177e4
LT
1808 hd->tmPending = 0;
1809 hd->tmState = TM_STATE_NONE;
1da177e4 1810 }
466544d8 1811 return FAILED;
1da177e4
LT
1812}
1813
1814/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1815/**
1816 * mptscsih_dev_reset - Perform a SCSI TARGET_RESET! new_eh variant
1817 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1818 *
1819 * (linux scsi_host_template.eh_dev_reset_handler routine)
1820 *
1821 * Returns SUCCESS or FAILED.
1822 */
0d0c7974 1823int
1da177e4
LT
1824mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
1825{
1826 MPT_SCSI_HOST *hd;
466544d8 1827 int retval;
c7c82987 1828 VirtDevice *vdev;
1da177e4
LT
1829
1830 /* If we can't locate our host adapter structure, return FAILED status.
1831 */
1832 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
466544d8 1833 dtmprintk((KERN_INFO MYNAM ": mptscsih_dev_reset: "
1da177e4
LT
1834 "Can't locate host! (sc=%p)\n",
1835 SCpnt));
1836 return FAILED;
1837 }
1838
1839 if (hd->resetPending)
1840 return FAILED;
1841
466544d8 1842 printk(KERN_WARNING MYNAM ": %s: attempting target reset! (sc=%p)\n",
1da177e4 1843 hd->ioc->name, SCpnt);
466544d8 1844 scsi_print_command(SCpnt);
1da177e4 1845
c7c82987 1846 vdev = SCpnt->device->hostdata;
466544d8 1847 retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
914c2d8e 1848 vdev->vtarget->bus_id, vdev->vtarget->target_id,
d66c7a0f 1849 0, 0, mptscsih_get_tm_timeout(hd->ioc));
466544d8
MED
1850
1851 printk (KERN_WARNING MYNAM ": %s: target reset: %s (sc=%p)\n",
1852 hd->ioc->name,
1853 ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
1854
1855 if (retval == 0)
1856 return SUCCESS;
1857
1858 if(retval != FAILED ) {
1da177e4
LT
1859 hd->tmPending = 0;
1860 hd->tmState = TM_STATE_NONE;
1da177e4 1861 }
466544d8 1862 return FAILED;
1da177e4
LT
1863}
1864
1865/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1866/**
1867 * mptscsih_bus_reset - Perform a SCSI BUS_RESET! new_eh variant
1868 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1869 *
1870 * (linux scsi_host_template.eh_bus_reset_handler routine)
1871 *
1872 * Returns SUCCESS or FAILED.
1873 */
0d0c7974 1874int
1da177e4
LT
1875mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
1876{
1877 MPT_SCSI_HOST *hd;
466544d8 1878 int retval;
c7c82987 1879 VirtDevice *vdev;
1da177e4
LT
1880
1881 /* If we can't locate our host adapter structure, return FAILED status.
1882 */
1883 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
466544d8 1884 dtmprintk((KERN_INFO MYNAM ": mptscsih_bus_reset: "
1da177e4
LT
1885 "Can't locate host! (sc=%p)\n",
1886 SCpnt ) );
1887 return FAILED;
1888 }
1889
466544d8 1890 printk(KERN_WARNING MYNAM ": %s: attempting bus reset! (sc=%p)\n",
1da177e4 1891 hd->ioc->name, SCpnt);
466544d8 1892 scsi_print_command(SCpnt);
1da177e4
LT
1893
1894 if (hd->timeouts < -1)
1895 hd->timeouts++;
1896
c7c82987 1897 vdev = SCpnt->device->hostdata;
466544d8 1898 retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
914c2d8e 1899 vdev->vtarget->bus_id, 0, 0, 0, mptscsih_get_tm_timeout(hd->ioc));
1da177e4 1900
466544d8
MED
1901 printk (KERN_WARNING MYNAM ": %s: bus reset: %s (sc=%p)\n",
1902 hd->ioc->name,
1903 ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
1904
1905 if (retval == 0)
1906 return SUCCESS;
1907
1908 if(retval != FAILED ) {
1da177e4
LT
1909 hd->tmPending = 0;
1910 hd->tmState = TM_STATE_NONE;
1da177e4 1911 }
466544d8 1912 return FAILED;
1da177e4
LT
1913}
1914
1915/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1916/**
d9489fb6 1917 * mptscsih_host_reset - Perform a SCSI host adapter RESET (new_eh variant)
1da177e4
LT
1918 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1919 *
1920 * (linux scsi_host_template.eh_host_reset_handler routine)
1921 *
1922 * Returns SUCCESS or FAILED.
1923 */
0d0c7974 1924int
1da177e4
LT
1925mptscsih_host_reset(struct scsi_cmnd *SCpnt)
1926{
1927 MPT_SCSI_HOST * hd;
1928 int status = SUCCESS;
1da177e4
LT
1929
1930 /* If we can't locate the host to reset, then we failed. */
1931 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
c6678e0c 1932 dtmprintk( ( KERN_INFO MYNAM ": mptscsih_host_reset: "
1da177e4
LT
1933 "Can't locate host! (sc=%p)\n",
1934 SCpnt ) );
1935 return FAILED;
1936 }
1937
c6678e0c 1938 printk(KERN_WARNING MYNAM ": %s: Attempting host reset! (sc=%p)\n",
1da177e4
LT
1939 hd->ioc->name, SCpnt);
1940
1941 /* If our attempts to reset the host failed, then return a failed
1942 * status. The host will be taken off line by the SCSI mid-layer.
1943 */
1da177e4
LT
1944 if (mpt_HardResetHandler(hd->ioc, CAN_SLEEP) < 0){
1945 status = FAILED;
1946 } else {
1947 /* Make sure TM pending is cleared and TM state is set to
1948 * NONE.
1949 */
1950 hd->tmPending = 0;
1951 hd->tmState = TM_STATE_NONE;
1952 }
1da177e4 1953
c6678e0c 1954 dtmprintk( ( KERN_INFO MYNAM ": mptscsih_host_reset: "
1da177e4
LT
1955 "Status = %s\n",
1956 (status == SUCCESS) ? "SUCCESS" : "FAILED" ) );
1957
1958 return status;
1959}
1960
1961/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1962/**
d9489fb6 1963 * mptscsih_tm_pending_wait - wait for pending task management request to complete
1da177e4
LT
1964 * @hd: Pointer to MPT host structure.
1965 *
1966 * Returns {SUCCESS,FAILED}.
1967 */
1968static int
1969mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd)
1970{
1971 unsigned long flags;
1972 int loop_count = 4 * 10; /* Wait 10 seconds */
1973 int status = FAILED;
1974
1975 do {
1976 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
1977 if (hd->tmState == TM_STATE_NONE) {
1978 hd->tmState = TM_STATE_IN_PROGRESS;
1979 hd->tmPending = 1;
1da177e4 1980 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
c6678e0c 1981 status = SUCCESS;
1da177e4
LT
1982 break;
1983 }
1984 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
1985 msleep(250);
1986 } while (--loop_count);
1987
1988 return status;
1989}
1990
1991/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1992/**
1993 * mptscsih_tm_wait_for_completion - wait for completion of TM task
1994 * @hd: Pointer to MPT host structure.
d9489fb6 1995 * @timeout: timeout in seconds
1da177e4
LT
1996 *
1997 * Returns {SUCCESS,FAILED}.
1998 */
1999static int
2000mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout )
2001{
2002 unsigned long flags;
2003 int loop_count = 4 * timeout;
2004 int status = FAILED;
2005
2006 do {
2007 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
2008 if(hd->tmPending == 0) {
2009 status = SUCCESS;
c6678e0c 2010 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
1da177e4
LT
2011 break;
2012 }
2013 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
d6be06c8 2014 msleep(250);
1da177e4
LT
2015 } while (--loop_count);
2016
2017 return status;
2018}
2019
9f63bb73
ME
2020/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2021static void
2022mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code)
2023{
2024 char *desc;
2025
2026 switch (response_code) {
2027 case MPI_SCSITASKMGMT_RSP_TM_COMPLETE:
2028 desc = "The task completed.";
2029 break;
2030 case MPI_SCSITASKMGMT_RSP_INVALID_FRAME:
2031 desc = "The IOC received an invalid frame status.";
2032 break;
2033 case MPI_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED:
2034 desc = "The task type is not supported.";
2035 break;
2036 case MPI_SCSITASKMGMT_RSP_TM_FAILED:
2037 desc = "The requested task failed.";
2038 break;
2039 case MPI_SCSITASKMGMT_RSP_TM_SUCCEEDED:
2040 desc = "The task completed successfully.";
2041 break;
2042 case MPI_SCSITASKMGMT_RSP_TM_INVALID_LUN:
2043 desc = "The LUN request is invalid.";
2044 break;
2045 case MPI_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC:
2046 desc = "The task is in the IOC queue and has not been sent to target.";
2047 break;
2048 default:
2049 desc = "unknown";
2050 break;
2051 }
2052 printk(MYIOC_s_INFO_FMT "Response Code(0x%08x): F/W: %s\n",
2053 ioc->name, response_code, desc);
2054}
2055
1da177e4
LT
2056/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2057/**
2058 * mptscsih_taskmgmt_complete - Registered with Fusion MPT base driver
2059 * @ioc: Pointer to MPT_ADAPTER structure
2060 * @mf: Pointer to SCSI task mgmt request frame
2061 * @mr: Pointer to SCSI task mgmt reply frame
2062 *
2063 * This routine is called from mptbase.c::mpt_interrupt() at the completion
2064 * of any SCSI task management request.
2065 * This routine is registered with the MPT (base) driver at driver
2066 * load/init time via the mpt_register() API call.
2067 *
2068 * Returns 1 indicating alloc'd request frame ptr should be freed.
2069 */
0d0c7974 2070int
1da177e4
LT
2071mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
2072{
2073 SCSITaskMgmtReply_t *pScsiTmReply;
2074 SCSITaskMgmt_t *pScsiTmReq;
2075 MPT_SCSI_HOST *hd;
2076 unsigned long flags;
2077 u16 iocstatus;
2078 u8 tmType;
2079
2080 dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt completed (mf=%p,mr=%p)\n",
2081 ioc->name, mf, mr));
2082 if (ioc->sh) {
2083 /* Depending on the thread, a timer is activated for
2084 * the TM request. Delete this timer on completion of TM.
2085 * Decrement count of outstanding TM requests.
2086 */
2087 hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
2088 } else {
2089 dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt Complete: NULL Scsi Host Ptr\n",
2090 ioc->name));
2091 return 1;
2092 }
2093
2094 if (mr == NULL) {
2095 dtmprintk((MYIOC_s_WARN_FMT "ERROR! TaskMgmt Reply: NULL Request %p\n",
2096 ioc->name, mf));
2097 return 1;
2098 } else {
2099 pScsiTmReply = (SCSITaskMgmtReply_t*)mr;
2100 pScsiTmReq = (SCSITaskMgmt_t*)mf;
2101
2102 /* Figure out if this was ABORT_TASK, TARGET_RESET, or BUS_RESET! */
2103 tmType = pScsiTmReq->TaskType;
2104
9f63bb73
ME
2105 if (ioc->facts.MsgVersion >= MPI_VERSION_01_05 &&
2106 pScsiTmReply->ResponseCode)
2107 mptscsih_taskmgmt_response_code(ioc,
2108 pScsiTmReply->ResponseCode);
2109
1da177e4
LT
2110 dtmprintk((MYIOC_s_WARN_FMT " TaskType = %d, TerminationCount=%d\n",
2111 ioc->name, tmType, le32_to_cpu(pScsiTmReply->TerminationCount)));
2112 DBG_DUMP_TM_REPLY_FRAME((u32 *)pScsiTmReply);
2113
2114 iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
3dc0b03f 2115 hd->tm_iocstatus = iocstatus;
1da177e4
LT
2116 dtmprintk((MYIOC_s_WARN_FMT " SCSI TaskMgmt (%d) IOCStatus=%04x IOCLogInfo=%08x\n",
2117 ioc->name, tmType, iocstatus, le32_to_cpu(pScsiTmReply->IOCLogInfo)));
2118 /* Error? (anything non-zero?) */
2119 if (iocstatus) {
2120
2121 /* clear flags and continue.
2122 */
2123 if (tmType == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK)
2124 hd->abortSCpnt = NULL;
2125
2126 /* If an internal command is present
2127 * or the TM failed - reload the FW.
2128 * FC FW may respond FAILED to an ABORT
2129 */
2130 if (tmType == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
2131 if ((hd->cmdPtr) ||
2132 (iocstatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED)) {
2133 if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0) {
2134 printk((KERN_WARNING
2135 " Firmware Reload FAILED!!\n"));
2136 }
2137 }
2138 }
2139 } else {
2140 dtmprintk((MYIOC_s_WARN_FMT " TaskMgmt SUCCESS\n", ioc->name));
2141
2142 hd->abortSCpnt = NULL;
2143
2144 }
2145 }
2146
2147 spin_lock_irqsave(&ioc->FreeQlock, flags);
2148 hd->tmPending = 0;
2149 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
2150 hd->tmState = TM_STATE_NONE;
2151
2152 return 1;
2153}
2154
2155/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2156/*
2157 * This is anyones guess quite frankly.
2158 */
0d0c7974 2159int
1da177e4
LT
2160mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev,
2161 sector_t capacity, int geom[])
2162{
2163 int heads;
2164 int sectors;
2165 sector_t cylinders;
2166 ulong dummy;
2167
2168 heads = 64;
2169 sectors = 32;
2170
2171 dummy = heads * sectors;
2172 cylinders = capacity;
2173 sector_div(cylinders,dummy);
2174
2175 /*
2176 * Handle extended translation size for logical drives
2177 * > 1Gb
2178 */
2179 if ((ulong)capacity >= 0x200000) {
2180 heads = 255;
2181 sectors = 63;
2182 dummy = heads * sectors;
2183 cylinders = capacity;
2184 sector_div(cylinders,dummy);
2185 }
2186
2187 /* return result */
2188 geom[0] = heads;
2189 geom[1] = sectors;
2190 geom[2] = cylinders;
2191
2192 dprintk((KERN_NOTICE
2193 ": bios_param: Id=%i Lun=%i Channel=%i CHS=%i/%i/%i\n",
2194 sdev->id, sdev->lun,sdev->channel,(int)cylinders,heads,sectors));
2195
2196 return 0;
2197}
2198
f44e5461
ME
2199/* Search IOC page 3 to determine if this is hidden physical disk
2200 *
2201 */
2202int
2203mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id)
2204{
2205 int i;
2206
2207 if (!ioc->raid_data.isRaid || !ioc->raid_data.pIocPg3)
2208 return 0;
2209 for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
2210 if (id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID)
2211 return 1;
2212 }
2213 return 0;
2214}
2215EXPORT_SYMBOL(mptscsih_is_phys_disk);
2216
c92f222e
JB
2217int
2218mptscsih_raid_id_to_num(MPT_SCSI_HOST *hd, uint physdiskid)
2219{
2220 int i;
2221
2222 if (!hd->ioc->raid_data.isRaid || !hd->ioc->raid_data.pIocPg3)
2223 return -ENXIO;
2224
2225 for (i = 0; i < hd->ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
2226 if (physdiskid ==
2227 hd->ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID)
2228 return hd->ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum;
2229 }
2230
2231 return -ENXIO;
2232}
2233EXPORT_SYMBOL(mptscsih_raid_id_to_num);
2234
c7c82987
MED
2235/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2236/*
2237 * OS entry point to allow host driver to alloc memory
2238 * for each scsi target. Called once per device the bus scan.
2239 * Return non-zero if allocation fails.
2240 */
2241int
2242mptscsih_target_alloc(struct scsi_target *starget)
2243{
2244 VirtTarget *vtarget;
2245
1ca00bb7 2246 vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
c7c82987
MED
2247 if (!vtarget)
2248 return -ENOMEM;
c7c82987 2249 starget->hostdata = vtarget;
c92f222e 2250 vtarget->starget = starget;
c7c82987
MED
2251 return 0;
2252}
2253
1da177e4
LT
2254/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2255/*
2256 * OS entry point to allow host driver to alloc memory
2257 * for each scsi device. Called once per device the bus scan.
2258 * Return non-zero if allocation fails.
1da177e4 2259 */
0d0c7974 2260int
c7c82987 2261mptscsih_slave_alloc(struct scsi_device *sdev)
1da177e4 2262{
c7c82987 2263 struct Scsi_Host *host = sdev->host;
1da177e4 2264 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
c7c82987 2265 VirtTarget *vtarget;
1da177e4 2266 VirtDevice *vdev;
c7c82987 2267 struct scsi_target *starget;
1da177e4 2268
1ca00bb7 2269 vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
1da177e4
LT
2270 if (!vdev) {
2271 printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
2272 hd->ioc->name, sizeof(VirtDevice));
2273 return -ENOMEM;
2274 }
2275
c7c82987
MED
2276 vdev->lun = sdev->lun;
2277 sdev->hostdata = vdev;
2278
2279 starget = scsi_target(sdev);
2280 vtarget = starget->hostdata;
c92f222e 2281
c7c82987
MED
2282 vdev->vtarget = vtarget;
2283
2284 if (vtarget->num_luns == 0) {
2285 hd->Targets[sdev->id] = vtarget;
2286 vtarget->ioc_id = hd->ioc->id;
2287 vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
2288 vtarget->target_id = sdev->id;
2289 vtarget->bus_id = sdev->channel;
c92f222e
JB
2290 if (hd->ioc->bus_type == SPI && sdev->channel == 0 &&
2291 hd->ioc->raid_data.isRaid & (1 << sdev->id)) {
2292 vtarget->raidVolume = 1;
2293 ddvtprintk((KERN_INFO
c7c82987 2294 "RAID Volume @ id %d\n", sdev->id));
1da177e4 2295 }
1da177e4 2296 }
c7c82987 2297 vtarget->num_luns++;
1da177e4
LT
2298 return 0;
2299}
2300
1da177e4
LT
2301/*
2302 * OS entry point to allow for host driver to free allocated memory
2303 * Called if no device present or device being unloaded
2304 */
0d0c7974 2305void
c7c82987 2306mptscsih_target_destroy(struct scsi_target *starget)
1da177e4 2307{
c7c82987
MED
2308 if (starget->hostdata)
2309 kfree(starget->hostdata);
2310 starget->hostdata = NULL;
2311}
1da177e4 2312
c7c82987
MED
2313/*
2314 * OS entry point to allow for host driver to free allocated memory
2315 * Called if no device present or device being unloaded
2316 */
2317void
2318mptscsih_slave_destroy(struct scsi_device *sdev)
2319{
2320 struct Scsi_Host *host = sdev->host;
2321 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
2322 VirtTarget *vtarget;
2323 VirtDevice *vdevice;
2324 struct scsi_target *starget;
2325
2326 starget = scsi_target(sdev);
2327 vtarget = starget->hostdata;
2328 vdevice = sdev->hostdata;
2329
2330 mptscsih_search_running_cmds(hd, vdevice);
2331 vtarget->luns[0] &= ~(1 << vdevice->lun);
2332 vtarget->num_luns--;
2333 if (vtarget->num_luns == 0) {
c7c82987 2334 hd->Targets[sdev->id] = NULL;
1da177e4 2335 }
c7c82987
MED
2336 mptscsih_synchronize_cache(hd, vdevice);
2337 kfree(vdevice);
2338 sdev->hostdata = NULL;
1da177e4
LT
2339}
2340
6e3815ba
MED
2341/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2342/*
2343 * mptscsih_change_queue_depth - This function will set a devices queue depth
2344 * @sdev: per scsi_device pointer
2345 * @qdepth: requested queue depth
2346 *
2347 * Adding support for new 'change_queue_depth' api.
2348*/
2349int
2350mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
1da177e4 2351{
c7c82987
MED
2352 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sdev->host->hostdata;
2353 VirtTarget *vtarget;
2354 struct scsi_target *starget;
2355 int max_depth;
2356 int tagged;
1da177e4 2357
c7c82987
MED
2358 starget = scsi_target(sdev);
2359 vtarget = starget->hostdata;
6e3815ba 2360
a9b2937a 2361 if (hd->ioc->bus_type == SPI) {
c92f222e 2362 if (!(vtarget->tflags & MPT_TARGET_FLAGS_Q_YES))
1da177e4 2363 max_depth = 1;
c92f222e
JB
2364 else if (sdev->type == TYPE_DISK &&
2365 vtarget->minSyncFactor <= MPT_ULTRA160)
2366 max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
2367 else
2368 max_depth = MPT_SCSI_CMD_PER_DEV_LOW;
1da177e4
LT
2369 } else
2370 max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
2371
2372 if (qdepth > max_depth)
2373 qdepth = max_depth;
2374 if (qdepth == 1)
2375 tagged = 0;
2376 else
2377 tagged = MSG_SIMPLE_TAG;
2378
6e3815ba
MED
2379 scsi_adjust_queue_depth(sdev, tagged, qdepth);
2380 return sdev->queue_depth;
1da177e4
LT
2381}
2382
1da177e4
LT
2383/*
2384 * OS entry point to adjust the queue_depths on a per-device basis.
2385 * Called once per device the bus scan. Use it to force the queue_depth
2386 * member to 1 if a device does not support Q tags.
2387 * Return non-zero if fails.
2388 */
0d0c7974 2389int
c7c82987 2390mptscsih_slave_configure(struct scsi_device *sdev)
1da177e4 2391{
c7c82987
MED
2392 struct Scsi_Host *sh = sdev->host;
2393 VirtTarget *vtarget;
2394 VirtDevice *vdevice;
2395 struct scsi_target *starget;
1da177e4 2396 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sh->hostdata;
c7c82987 2397 int indexed_lun, lun_index;
1da177e4 2398
c7c82987
MED
2399 starget = scsi_target(sdev);
2400 vtarget = starget->hostdata;
2401 vdevice = sdev->hostdata;
1da177e4
LT
2402
2403 dsprintk((MYIOC_s_INFO_FMT
2404 "device @ %p, id=%d, LUN=%d, channel=%d\n",
c7c82987
MED
2405 hd->ioc->name, sdev, sdev->id, sdev->lun, sdev->channel));
2406 if (hd->ioc->bus_type == SPI)
2407 dsprintk((MYIOC_s_INFO_FMT
2408 "sdtr %d wdtr %d ppr %d inq length=%d\n",
2409 hd->ioc->name, sdev->sdtr, sdev->wdtr,
2410 sdev->ppr, sdev->inquiry_len));
2411
2412 if (sdev->id > sh->max_id) {
1da177e4 2413 /* error case, should never happen */
c7c82987 2414 scsi_adjust_queue_depth(sdev, 0, 1);
1da177e4
LT
2415 goto slave_configure_exit;
2416 }
2417
c7c82987
MED
2418 vdevice->configured_lun=1;
2419 lun_index = (vdevice->lun >> 5); /* 32 luns per lun_index */
2420 indexed_lun = (vdevice->lun % 32);
2421 vtarget->luns[lun_index] |= (1 << indexed_lun);
c92f222e 2422 mptscsih_initTarget(hd, vtarget, sdev);
c7c82987 2423 mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH);
1da177e4
LT
2424
2425 dsprintk((MYIOC_s_INFO_FMT
2426 "Queue depth=%d, tflags=%x\n",
c7c82987 2427 hd->ioc->name, sdev->queue_depth, vtarget->tflags));
1da177e4 2428
c7c82987
MED
2429 if (hd->ioc->bus_type == SPI)
2430 dsprintk((MYIOC_s_INFO_FMT
2431 "negoFlags=%x, maxOffset=%x, SyncFactor=%x\n",
2432 hd->ioc->name, vtarget->negoFlags, vtarget->maxOffset,
2433 vtarget->minSyncFactor));
1da177e4
LT
2434
2435slave_configure_exit:
2436
2437 dsprintk((MYIOC_s_INFO_FMT
2438 "tagged %d, simple %d, ordered %d\n",
c7c82987
MED
2439 hd->ioc->name,sdev->tagged_supported, sdev->simple_tags,
2440 sdev->ordered_tags));
1da177e4
LT
2441
2442 return 0;
2443}
2444
1da177e4
LT
2445/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2446/*
2447 * Private routines...
2448 */
2449
2450/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2451/* Utility function to copy sense data from the scsi_cmnd buffer
2452 * to the FC and SCSI target structures.
2453 *
2454 */
2455static void
0d0c7974 2456mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply)
1da177e4 2457{
c7c82987 2458 VirtDevice *vdev;
1da177e4
LT
2459 SCSIIORequest_t *pReq;
2460 u32 sense_count = le32_to_cpu(pScsiReply->SenseCount);
1da177e4
LT
2461
2462 /* Get target structure
2463 */
2464 pReq = (SCSIIORequest_t *) mf;
c7c82987 2465 vdev = sc->device->hostdata;
1da177e4
LT
2466
2467 if (sense_count) {
2468 u8 *sense_data;
2469 int req_index;
2470
2471 /* Copy the sense received into the scsi command block. */
2472 req_index = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
2473 sense_data = ((u8 *)hd->ioc->sense_buf_pool + (req_index * MPT_SENSE_BUFFER_ALLOC));
2474 memcpy(sc->sense_buffer, sense_data, SNS_LEN(sc));
2475
2476 /* Log SMART data (asc = 0x5D, non-IM case only) if required.
2477 */
2478 if ((hd->ioc->events) && (hd->ioc->eventTypes & (1 << MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE))) {
c7c82987 2479 if ((sense_data[12] == 0x5D) && (vdev->vtarget->raidVolume == 0)) {
1da177e4
LT
2480 int idx;
2481 MPT_ADAPTER *ioc = hd->ioc;
2482
5b5ef4f6 2483 idx = ioc->eventContext % MPTCTL_EVENT_LOG_SIZE;
1da177e4
LT
2484 ioc->events[idx].event = MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE;
2485 ioc->events[idx].eventContext = ioc->eventContext;
2486
2487 ioc->events[idx].data[0] = (pReq->LUN[1] << 24) ||
2488 (MPI_EVENT_SCSI_DEV_STAT_RC_SMART_DATA << 16) ||
c7c82987 2489 (sc->device->channel << 8) || sc->device->id;
1da177e4
LT
2490
2491 ioc->events[idx].data[1] = (sense_data[13] << 8) || sense_data[12];
2492
2493 ioc->eventContext++;
786899b0
EM
2494 if (hd->ioc->pcidev->vendor ==
2495 PCI_VENDOR_ID_IBM) {
2496 mptscsih_issue_sep_command(hd->ioc,
2497 vdev->vtarget, MPI_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT);
2498 vdev->vtarget->tflags |=
2499 MPT_TARGET_FLAGS_LED_ON;
2500 }
1da177e4
LT
2501 }
2502 }
2503 } else {
2504 dprintk((MYIOC_s_INFO_FMT "Hmmm... SenseData len=0! (?)\n",
2505 hd->ioc->name));
2506 }
2507}
2508
3dc0b03f 2509static int
1da177e4
LT
2510SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc)
2511{
2512 MPT_SCSI_HOST *hd;
2513 int i;
2514
2515 hd = (MPT_SCSI_HOST *) sc->device->host->hostdata;
2516
2517 for (i = 0; i < hd->ioc->req_depth; i++) {
2518 if (hd->ScsiLookup[i] == sc) {
2519 return i;
2520 }
2521 }
2522
2523 return -1;
2524}
2525
2526/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
0d0c7974 2527int
1da177e4
LT
2528mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
2529{
2530 MPT_SCSI_HOST *hd;
2531 unsigned long flags;
466544d8 2532 int ii;
1da177e4
LT
2533
2534 dtmprintk((KERN_WARNING MYNAM
2535 ": IOC %s_reset routed to SCSI host driver!\n",
2536 reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
2537 reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
2538
2539 /* If a FW reload request arrives after base installed but
2540 * before all scsi hosts have been attached, then an alt_ioc
2541 * may have a NULL sh pointer.
2542 */
2543 if ((ioc->sh == NULL) || (ioc->sh->hostdata == NULL))
2544 return 0;
2545 else
2546 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
2547
2548 if (reset_phase == MPT_IOC_SETUP_RESET) {
2549 dtmprintk((MYIOC_s_WARN_FMT "Setup-Diag Reset\n", ioc->name));
2550
2551 /* Clean Up:
2552 * 1. Set Hard Reset Pending Flag
2553 * All new commands go to doneQ
2554 */
2555 hd->resetPending = 1;
2556
2557 } else if (reset_phase == MPT_IOC_PRE_RESET) {
2558 dtmprintk((MYIOC_s_WARN_FMT "Pre-Diag Reset\n", ioc->name));
2559
2560 /* 2. Flush running commands
2561 * Clean ScsiLookup (and associated memory)
2562 * AND clean mytaskQ
2563 */
2564
2565 /* 2b. Reply to OS all known outstanding I/O commands.
2566 */
2567 mptscsih_flush_running_cmds(hd);
2568
2569 /* 2c. If there was an internal command that
2570 * has not completed, configuration or io request,
2571 * free these resources.
2572 */
2573 if (hd->cmdPtr) {
2574 del_timer(&hd->timer);
2575 mpt_free_msg_frame(ioc, hd->cmdPtr);
2576 }
2577
2578 dtmprintk((MYIOC_s_WARN_FMT "Pre-Reset complete.\n", ioc->name));
2579
2580 } else {
2581 dtmprintk((MYIOC_s_WARN_FMT "Post-Diag Reset\n", ioc->name));
2582
2583 /* Once a FW reload begins, all new OS commands are
2584 * redirected to the doneQ w/ a reset status.
2585 * Init all control structures.
2586 */
2587
2588 /* ScsiLookup initialization
2589 */
466544d8
MED
2590 for (ii=0; ii < hd->ioc->req_depth; ii++)
2591 hd->ScsiLookup[ii] = NULL;
1da177e4
LT
2592
2593 /* 2. Chain Buffer initialization
2594 */
2595
a9b2937a 2596 /* 4. Renegotiate to all devices, if SPI
1da177e4 2597 */
1da177e4
LT
2598
2599 /* 5. Enable new commands to be posted
2600 */
2601 spin_lock_irqsave(&ioc->FreeQlock, flags);
2602 hd->tmPending = 0;
2603 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
2604 hd->resetPending = 0;
2605 hd->tmState = TM_STATE_NONE;
2606
2607 /* 6. If there was an internal command,
2608 * wake this process up.
2609 */
2610 if (hd->cmdPtr) {
2611 /*
2612 * Wake up the original calling thread
2613 */
2614 hd->pLocal = &hd->localReply;
2615 hd->pLocal->completion = MPT_SCANDV_DID_RESET;
0d0c7974
MED
2616 hd->scandv_wait_done = 1;
2617 wake_up(&hd->scandv_waitq);
1da177e4
LT
2618 hd->cmdPtr = NULL;
2619 }
2620
1da177e4
LT
2621 dtmprintk((MYIOC_s_WARN_FMT "Post-Reset complete.\n", ioc->name));
2622
2623 }
2624
2625 return 1; /* currently means nothing really */
2626}
2627
2628/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
0d0c7974 2629int
1da177e4
LT
2630mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
2631{
2632 MPT_SCSI_HOST *hd;
2633 u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
2634
3a892bef 2635 devtverboseprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
1da177e4
LT
2636 ioc->name, event));
2637
466544d8
MED
2638 if (ioc->sh == NULL ||
2639 ((hd = (MPT_SCSI_HOST *)ioc->sh->hostdata) == NULL))
2640 return 1;
2641
1da177e4
LT
2642 switch (event) {
2643 case MPI_EVENT_UNIT_ATTENTION: /* 03 */
2644 /* FIXME! */
2645 break;
2646 case MPI_EVENT_IOC_BUS_RESET: /* 04 */
2647 case MPI_EVENT_EXT_BUS_RESET: /* 05 */
a9b2937a 2648 if (hd && (ioc->bus_type == SPI) && (hd->soft_resets < -1))
466544d8 2649 hd->soft_resets++;
1da177e4
LT
2650 break;
2651 case MPI_EVENT_LOGOUT: /* 09 */
2652 /* FIXME! */
2653 break;
2654
05e8ec17 2655 case MPI_EVENT_RESCAN: /* 06 */
05e8ec17
MR
2656 break;
2657
1da177e4
LT
2658 /*
2659 * CHECKME! Don't think we need to do
2660 * anything for these, but...
2661 */
1da177e4
LT
2662 case MPI_EVENT_LINK_STATUS_CHANGE: /* 07 */
2663 case MPI_EVENT_LOOP_STATE_CHANGE: /* 08 */
2664 /*
2665 * CHECKME! Falling thru...
2666 */
2667 break;
2668
2669 case MPI_EVENT_INTEGRATED_RAID: /* 0B */
466544d8 2670 break;
1da177e4 2671
1da177e4
LT
2672 case MPI_EVENT_NONE: /* 00 */
2673 case MPI_EVENT_LOG_DATA: /* 01 */
2674 case MPI_EVENT_STATE_CHANGE: /* 02 */
2675 case MPI_EVENT_EVENT_CHANGE: /* 0A */
2676 default:
2677 dprintk((KERN_INFO " Ignoring event (=%02Xh)\n", event));
2678 break;
2679 }
2680
2681 return 1; /* currently means nothing really */
2682}
2683
1da177e4
LT
2684/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2685/*
2686 * mptscsih_initTarget - Target, LUN alloc/free functionality.
2687 * @hd: Pointer to MPT_SCSI_HOST structure
c7c82987 2688 * @vtarget: per target private data
c92f222e 2689 * @sdev: SCSI device
1da177e4
LT
2690 *
2691 * NOTE: It's only SAFE to call this routine if data points to
2692 * sane & valid STANDARD INQUIRY data!
2693 *
2694 * Allocate and initialize memory for this target.
2695 * Save inquiry data.
2696 *
2697 */
2698static void
c92f222e
JB
2699mptscsih_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget,
2700 struct scsi_device *sdev)
1da177e4 2701{
1da177e4 2702 dinitprintk((MYIOC_s_INFO_FMT "initTarget bus=%d id=%d lun=%d hd=%p\n",
f99be43b
EM
2703 hd->ioc->name, vtarget->bus_id, vtarget->target_id,
2704 sdev->lun, hd));
1da177e4 2705
1da177e4
LT
2706 /* Is LUN supported? If so, upper 2 bits will be 0
2707 * in first byte of inquiry data.
2708 */
c92f222e 2709 if (sdev->inq_periph_qual != 0)
1da177e4
LT
2710 return;
2711
c7c82987 2712 if (vtarget == NULL)
1da177e4 2713 return;
1da177e4 2714
c92f222e 2715 vtarget->type = sdev->type;
1da177e4 2716
c7c82987
MED
2717 if (hd->ioc->bus_type != SPI)
2718 return;
2719
c92f222e 2720 if ((sdev->type == TYPE_PROCESSOR) && (hd->ioc->spi_data.Saf_Te)) {
c7c82987
MED
2721 /* Treat all Processors as SAF-TE if
2722 * command line option is set */
2723 vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
2724 mptscsih_writeIOCPage4(hd, vtarget->target_id, vtarget->bus_id);
c92f222e 2725 }else if ((sdev->type == TYPE_PROCESSOR) &&
c7c82987 2726 !(vtarget->tflags & MPT_TARGET_FLAGS_SAF_TE_ISSUED )) {
c92f222e
JB
2727 if (sdev->inquiry_len > 49 ) {
2728 if (sdev->inquiry[44] == 'S' &&
2729 sdev->inquiry[45] == 'A' &&
2730 sdev->inquiry[46] == 'F' &&
2731 sdev->inquiry[47] == '-' &&
2732 sdev->inquiry[48] == 'T' &&
2733 sdev->inquiry[49] == 'E' ) {
c7c82987
MED
2734 vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
2735 mptscsih_writeIOCPage4(hd, vtarget->target_id, vtarget->bus_id);
1da177e4
LT
2736 }
2737 }
c7c82987 2738 }
c92f222e 2739 mptscsih_setTargetNegoParms(hd, vtarget, sdev);
1da177e4
LT
2740}
2741
2742/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2743/*
2744 * Update the target negotiation parameters based on the
2745 * the Inquiry data, adapter capabilities, and NVRAM settings.
2746 *
2747 */
2748static void
c92f222e
JB
2749mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target,
2750 struct scsi_device *sdev)
1da177e4 2751{
466544d8 2752 SpiCfgData *pspi_data = &hd->ioc->spi_data;
1da177e4
LT
2753 int id = (int) target->target_id;
2754 int nvram;
1da177e4
LT
2755 u8 width = MPT_NARROW;
2756 u8 factor = MPT_ASYNC;
2757 u8 offset = 0;
c92f222e 2758 u8 nfactor;
1da177e4
LT
2759 u8 noQas = 1;
2760
2761 target->negoFlags = pspi_data->noQas;
2762
c92f222e 2763 /* noQas == 0 => device supports QAS. */
1da177e4 2764
c92f222e 2765 if (sdev->scsi_level < SCSI_2) {
1da177e4
LT
2766 width = 0;
2767 factor = MPT_ULTRA2;
2768 offset = pspi_data->maxSyncOffset;
2769 target->tflags &= ~MPT_TARGET_FLAGS_Q_YES;
2770 } else {
c92f222e 2771 if (scsi_device_wide(sdev)) {
1da177e4
LT
2772 width = 1;
2773 }
2774
c92f222e 2775 if (scsi_device_sync(sdev)) {
1da177e4 2776 factor = pspi_data->minSyncFactor;
c92f222e 2777 if (!scsi_device_dt(sdev))
1da177e4 2778 factor = MPT_ULTRA2;
c92f222e
JB
2779 else {
2780 if (!scsi_device_ius(sdev) &&
2781 !scsi_device_qas(sdev))
2782 factor = MPT_ULTRA160;
1da177e4 2783 else {
c92f222e
JB
2784 factor = MPT_ULTRA320;
2785 if (scsi_device_qas(sdev)) {
f99be43b 2786 ddvtprintk((KERN_INFO "Enabling QAS due to byte56=%02x on id=%d!\n", scsi_device_qas(sdev), id));
c92f222e 2787 noQas = 0;
1da177e4 2788 }
c92f222e
JB
2789 if (sdev->type == TYPE_TAPE &&
2790 scsi_device_ius(sdev))
2791 target->negoFlags |= MPT_TAPE_NEGO_IDP;
1da177e4 2792 }
1da177e4 2793 }
1da177e4
LT
2794 offset = pspi_data->maxSyncOffset;
2795
2796 /* If RAID, never disable QAS
2797 * else if non RAID, do not disable
2798 * QAS if bit 1 is set
2799 * bit 1 QAS support, non-raid only
2800 * bit 0 IU support
2801 */
2802 if (target->raidVolume == 1) {
2803 noQas = 0;
2804 }
2805 } else {
2806 factor = MPT_ASYNC;
2807 offset = 0;
2808 }
2809 }
2810
c92f222e 2811 if (!sdev->tagged_supported) {
1da177e4
LT
2812 target->tflags &= ~MPT_TARGET_FLAGS_Q_YES;
2813 }
2814
2815 /* Update tflags based on NVRAM settings. (SCSI only)
2816 */
2817 if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) {
2818 nvram = pspi_data->nvram[id];
2819 nfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8;
2820
2821 if (width)
2822 width = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
2823
2824 if (offset > 0) {
2825 /* Ensure factor is set to the
2826 * maximum of: adapter, nvram, inquiry
2827 */
2828 if (nfactor) {
2829 if (nfactor < pspi_data->minSyncFactor )
2830 nfactor = pspi_data->minSyncFactor;
2831
2832 factor = max(factor, nfactor);
2833 if (factor == MPT_ASYNC)
2834 offset = 0;
2835 } else {
2836 offset = 0;
2837 factor = MPT_ASYNC;
2838 }
2839 } else {
2840 factor = MPT_ASYNC;
2841 }
2842 }
2843
2844 /* Make sure data is consistent
2845 */
2846 if ((!width) && (factor < MPT_ULTRA2)) {
2847 factor = MPT_ULTRA2;
2848 }
2849
2850 /* Save the data to the target structure.
2851 */
2852 target->minSyncFactor = factor;
2853 target->maxOffset = offset;
2854 target->maxWidth = width;
2855
2856 target->tflags |= MPT_TARGET_FLAGS_VALID_NEGO;
2857
2858 /* Disable unused features.
2859 */
2860 if (!width)
2861 target->negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
2862
2863 if (!offset)
2864 target->negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
2865
2866 if ( factor > MPT_ULTRA320 )
2867 noQas = 0;
2868
c92f222e
JB
2869 if (noQas && (pspi_data->noQas == 0)) {
2870 pspi_data->noQas |= MPT_TARGET_NO_NEGO_QAS;
2871 target->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
1da177e4 2872
c92f222e
JB
2873 /* Disable QAS in a mixed configuration case
2874 */
2875
2876 ddvtprintk((KERN_INFO "Disabling QAS due to noQas=%02x on id=%d!\n", noQas, id));
1da177e4
LT
2877 }
2878}
2879
1da177e4 2880/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1da177e4
LT
2881
2882/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2883/*
2884 * SCSI Config Page functionality ...
2885 */
1da177e4 2886
1da177e4
LT
2887/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2888/* mptscsih_writeIOCPage4 - write IOC Page 4
2889 * @hd: Pointer to a SCSI Host Structure
2890 * @target_id: write IOC Page4 for this ID & Bus
2891 *
2892 * Return: -EAGAIN if unable to obtain a Message Frame
2893 * or 0 if success.
2894 *
2895 * Remark: We do not wait for a return, write pages sequentially.
2896 */
2897static int
2898mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus)
2899{
2900 MPT_ADAPTER *ioc = hd->ioc;
2901 Config_t *pReq;
2902 IOCPage4_t *IOCPage4Ptr;
2903 MPT_FRAME_HDR *mf;
2904 dma_addr_t dataDma;
2905 u16 req_idx;
2906 u32 frameOffset;
2907 u32 flagsLength;
2908 int ii;
2909
2910 /* Get a MF for this command.
2911 */
0d0c7974 2912 if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) {
c6678e0c 2913 dfailprintk((MYIOC_s_WARN_FMT "writeIOCPage4 : no msg frames!\n",
1da177e4
LT
2914 ioc->name));
2915 return -EAGAIN;
2916 }
2917
2918 /* Set the request and the data pointers.
2919 * Place data at end of MF.
2920 */
2921 pReq = (Config_t *)mf;
2922
2923 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
2924 frameOffset = ioc->req_sz - sizeof(IOCPage4_t);
2925
2926 /* Complete the request frame (same for all requests).
2927 */
2928 pReq->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
2929 pReq->Reserved = 0;
2930 pReq->ChainOffset = 0;
2931 pReq->Function = MPI_FUNCTION_CONFIG;
2932 pReq->ExtPageLength = 0;
2933 pReq->ExtPageType = 0;
2934 pReq->MsgFlags = 0;
2935 for (ii=0; ii < 8; ii++) {
2936 pReq->Reserved2[ii] = 0;
2937 }
2938
2939 IOCPage4Ptr = ioc->spi_data.pIocPg4;
2940 dataDma = ioc->spi_data.IocPg4_dma;
2941 ii = IOCPage4Ptr->ActiveSEP++;
2942 IOCPage4Ptr->SEP[ii].SEPTargetID = target_id;
2943 IOCPage4Ptr->SEP[ii].SEPBus = bus;
2944 pReq->Header = IOCPage4Ptr->Header;
2945 pReq->PageAddress = cpu_to_le32(target_id | (bus << 8 ));
2946
2947 /* Add a SGE to the config request.
2948 */
2949 flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE |
2950 (IOCPage4Ptr->Header.PageLength + ii) * 4;
2951
2952 mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma);
2953
2954 dinitprintk((MYIOC_s_INFO_FMT
2955 "writeIOCPage4: MaxSEP=%d ActiveSEP=%d id=%d bus=%d\n",
2956 ioc->name, IOCPage4Ptr->MaxSEP, IOCPage4Ptr->ActiveSEP, target_id, bus));
2957
0d0c7974 2958 mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
1da177e4
LT
2959
2960 return 0;
2961}
2962
2963/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2964/*
2965 * Bus Scan and Domain Validation functionality ...
2966 */
2967
2968/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2969/*
2970 * mptscsih_scandv_complete - Scan and DV callback routine registered
2971 * to Fustion MPT (base) driver.
2972 *
2973 * @ioc: Pointer to MPT_ADAPTER structure
2974 * @mf: Pointer to original MPT request frame
2975 * @mr: Pointer to MPT reply frame (NULL if TurboReply)
2976 *
2977 * This routine is called from mpt.c::mpt_interrupt() at the completion
2978 * of any SCSI IO request.
2979 * This routine is registered with the Fusion MPT (base) driver at driver
2980 * load/init time via the mpt_register() API call.
2981 *
2982 * Returns 1 indicating alloc'd request frame ptr should be freed.
2983 *
2984 * Remark: Sets a completion code and (possibly) saves sense data
2985 * in the IOC member localReply structure.
2986 * Used ONLY for DV and other internal commands.
2987 */
0d0c7974 2988int
1da177e4
LT
2989mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
2990{
2991 MPT_SCSI_HOST *hd;
2992 SCSIIORequest_t *pReq;
2993 int completionCode;
2994 u16 req_idx;
2995
0d0c7974
MED
2996 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
2997
1da177e4
LT
2998 if ((mf == NULL) ||
2999 (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) {
3000 printk(MYIOC_s_ERR_FMT
3001 "ScanDvComplete, %s req frame ptr! (=%p)\n",
3002 ioc->name, mf?"BAD":"NULL", (void *) mf);
3003 goto wakeup;
3004 }
3005
1da177e4
LT
3006 del_timer(&hd->timer);
3007 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
3008 hd->ScsiLookup[req_idx] = NULL;
3009 pReq = (SCSIIORequest_t *) mf;
3010
3011 if (mf != hd->cmdPtr) {
3012 printk(MYIOC_s_WARN_FMT "ScanDvComplete (mf=%p, cmdPtr=%p, idx=%d)\n",
3013 hd->ioc->name, (void *)mf, (void *) hd->cmdPtr, req_idx);
3014 }
3015 hd->cmdPtr = NULL;
3016
3017 ddvprintk((MYIOC_s_INFO_FMT "ScanDvComplete (mf=%p,mr=%p,idx=%d)\n",
3018 hd->ioc->name, mf, mr, req_idx));
3019
3020 hd->pLocal = &hd->localReply;
3021 hd->pLocal->scsiStatus = 0;
3022
3023 /* If target struct exists, clear sense valid flag.
3024 */
3025 if (mr == NULL) {
3026 completionCode = MPT_SCANDV_GOOD;
3027 } else {
3028 SCSIIOReply_t *pReply;
3029 u16 status;
3030 u8 scsi_status;
3031
3032 pReply = (SCSIIOReply_t *) mr;
3033
3034 status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
3035 scsi_status = pReply->SCSIStatus;
3036
3037 ddvtprintk((KERN_NOTICE " IOCStatus=%04xh, SCSIState=%02xh, SCSIStatus=%02xh, IOCLogInfo=%08xh\n",
3038 status, pReply->SCSIState, scsi_status,
3039 le32_to_cpu(pReply->IOCLogInfo)));
3040
3041 switch(status) {
3042
3043 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
3044 completionCode = MPT_SCANDV_SELECTION_TIMEOUT;
3045 break;
3046
3047 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
3048 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
3049 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
3050 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
3051 completionCode = MPT_SCANDV_DID_RESET;
3052 break;
3053
3054 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
3055 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
3056 case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */
3057 if (pReply->Function == MPI_FUNCTION_CONFIG) {
3058 ConfigReply_t *pr = (ConfigReply_t *)mr;
3059 completionCode = MPT_SCANDV_GOOD;
3060 hd->pLocal->header.PageVersion = pr->Header.PageVersion;
3061 hd->pLocal->header.PageLength = pr->Header.PageLength;
3062 hd->pLocal->header.PageNumber = pr->Header.PageNumber;
3063 hd->pLocal->header.PageType = pr->Header.PageType;
3064
3065 } else if (pReply->Function == MPI_FUNCTION_RAID_ACTION) {
3066 /* If the RAID Volume request is successful,
3067 * return GOOD, else indicate that
3068 * some type of error occurred.
3069 */
3070 MpiRaidActionReply_t *pr = (MpiRaidActionReply_t *)mr;
637fa99b 3071 if (le16_to_cpu(pr->ActionStatus) == MPI_RAID_ACTION_ASTATUS_SUCCESS)
1da177e4
LT
3072 completionCode = MPT_SCANDV_GOOD;
3073 else
3074 completionCode = MPT_SCANDV_SOME_ERROR;
c92f222e 3075 memcpy(hd->pLocal->sense, pr, sizeof(hd->pLocal->sense));
1da177e4
LT
3076
3077 } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) {
3078 u8 *sense_data;
3079 int sz;
3080
3081 /* save sense data in global structure
3082 */
3083 completionCode = MPT_SCANDV_SENSE;
3084 hd->pLocal->scsiStatus = scsi_status;
3085 sense_data = ((u8 *)hd->ioc->sense_buf_pool +
3086 (req_idx * MPT_SENSE_BUFFER_ALLOC));
3087
3088 sz = min_t(int, pReq->SenseBufferLength,
3089 SCSI_STD_SENSE_BYTES);
3090 memcpy(hd->pLocal->sense, sense_data, sz);
3091
3092 ddvprintk((KERN_NOTICE " Check Condition, sense ptr %p\n",
3093 sense_data));
3094 } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_FAILED) {
3095 if (pReq->CDB[0] == INQUIRY)
3096 completionCode = MPT_SCANDV_ISSUE_SENSE;
3097 else
3098 completionCode = MPT_SCANDV_DID_RESET;
3099 }
3100 else if (pReply->SCSIState & MPI_SCSI_STATE_NO_SCSI_STATUS)
3101 completionCode = MPT_SCANDV_DID_RESET;
3102 else if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
3103 completionCode = MPT_SCANDV_DID_RESET;
3104 else {
3105 completionCode = MPT_SCANDV_GOOD;
3106 hd->pLocal->scsiStatus = scsi_status;
3107 }
3108 break;
3109
3110 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
3111 if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
3112 completionCode = MPT_SCANDV_DID_RESET;
3113 else
3114 completionCode = MPT_SCANDV_SOME_ERROR;
3115 break;
3116
3117 default:
3118 completionCode = MPT_SCANDV_SOME_ERROR;
3119 break;
3120
3121 } /* switch(status) */
3122
3123 ddvtprintk((KERN_NOTICE " completionCode set to %08xh\n",
3124 completionCode));
3125 } /* end of address reply case */
3126
3127 hd->pLocal->completion = completionCode;
3128
3129 /* MF and RF are freed in mpt_interrupt
3130 */
3131wakeup:
3132 /* Free Chain buffers (will never chain) in scan or dv */
3133 //mptscsih_freeChainBuffers(ioc, req_idx);
3134
3135 /*
3136 * Wake up the original calling thread
3137 */
0d0c7974
MED
3138 hd->scandv_wait_done = 1;
3139 wake_up(&hd->scandv_waitq);
1da177e4
LT
3140
3141 return 1;
3142}
3143
3144/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3145/* mptscsih_timer_expired - Call back for timer process.
3146 * Used only for dv functionality.
3147 * @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
3148 *
3149 */
0d0c7974
MED
3150void
3151mptscsih_timer_expired(unsigned long data)
1da177e4
LT
3152{
3153 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) data;
3154
3155 ddvprintk((MYIOC_s_WARN_FMT "Timer Expired! Cmd %p\n", hd->ioc->name, hd->cmdPtr));
3156
3157 if (hd->cmdPtr) {
3158 MPIHeader_t *cmd = (MPIHeader_t *)hd->cmdPtr;
3159
3160 if (cmd->Function == MPI_FUNCTION_SCSI_IO_REQUEST) {
3161 /* Desire to issue a task management request here.
3162 * TM requests MUST be single threaded.
3163 * If old eh code and no TM current, issue request.
3164 * If new eh code, do nothing. Wait for OS cmd timeout
3165 * for bus reset.
3166 */
3167 ddvtprintk((MYIOC_s_NOTE_FMT "DV Cmd Timeout: NoOp\n", hd->ioc->name));
3168 } else {
3169 /* Perform a FW reload */
3170 if (mpt_HardResetHandler(hd->ioc, NO_SLEEP) < 0) {
3171 printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", hd->ioc->name);
3172 }
3173 }
3174 } else {
3175 /* This should NEVER happen */
3176 printk(MYIOC_s_WARN_FMT "Null cmdPtr!!!!\n", hd->ioc->name);
3177 }
3178
3179 /* No more processing.
3180 * TM call will generate an interrupt for SCSI TM Management.
3181 * The FW will reply to all outstanding commands, callback will finish cleanup.
3182 * Hard reset clean-up will free all resources.
3183 */
3184 ddvprintk((MYIOC_s_WARN_FMT "Timer Expired Complete!\n", hd->ioc->name));
3185
3186 return;
3187}
3188
1da177e4
LT
3189
3190/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3191/**
3192 * mptscsih_do_cmd - Do internal command.
3193 * @hd: MPT_SCSI_HOST pointer
3194 * @io: INTERNAL_CMD pointer.
3195 *
3196 * Issue the specified internally generated command and do command
3197 * specific cleanup. For bus scan / DV only.
3198 * NOTES: If command is Inquiry and status is good,
3199 * initialize a target structure, save the data
3200 *
3201 * Remark: Single threaded access only.
3202 *
3203 * Return:
3204 * < 0 if an illegal command or no resources
3205 *
3206 * 0 if good
3207 *
3208 * > 0 if command complete but some type of completion error.
3209 */
3210static int
3211mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
3212{
3213 MPT_FRAME_HDR *mf;
3214 SCSIIORequest_t *pScsiReq;
3215 SCSIIORequest_t ReqCopy;
3216 int my_idx, ii, dir;
3217 int rc, cmdTimeout;
3218 int in_isr;
3219 char cmdLen;
3220 char CDB[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
3221 char cmd = io->cmd;
3222
3223 in_isr = in_interrupt();
3224 if (in_isr) {
3225 dprintk((MYIOC_s_WARN_FMT "Internal SCSI IO request not allowed in ISR context!\n",
3226 hd->ioc->name));
3227 return -EPERM;
3228 }
3229
3230
3231 /* Set command specific information
3232 */
3233 switch (cmd) {
3234 case INQUIRY:
3235 cmdLen = 6;
3236 dir = MPI_SCSIIO_CONTROL_READ;
3237 CDB[0] = cmd;
3238 CDB[4] = io->size;
3239 cmdTimeout = 10;
3240 break;
3241
3242 case TEST_UNIT_READY:
3243 cmdLen = 6;
3244 dir = MPI_SCSIIO_CONTROL_READ;
3245 cmdTimeout = 10;
3246 break;
3247
3248 case START_STOP:
3249 cmdLen = 6;
3250 dir = MPI_SCSIIO_CONTROL_READ;
3251 CDB[0] = cmd;
3252 CDB[4] = 1; /*Spin up the disk */
3253 cmdTimeout = 15;
3254 break;
3255
3256 case REQUEST_SENSE:
3257 cmdLen = 6;
3258 CDB[0] = cmd;
3259 CDB[4] = io->size;
3260 dir = MPI_SCSIIO_CONTROL_READ;
3261 cmdTimeout = 10;
3262 break;
3263
3264 case READ_BUFFER:
3265 cmdLen = 10;
3266 dir = MPI_SCSIIO_CONTROL_READ;
3267 CDB[0] = cmd;
3268 if (io->flags & MPT_ICFLAG_ECHO) {
3269 CDB[1] = 0x0A;
3270 } else {
3271 CDB[1] = 0x02;
3272 }
3273
3274 if (io->flags & MPT_ICFLAG_BUF_CAP) {
3275 CDB[1] |= 0x01;
3276 }
3277 CDB[6] = (io->size >> 16) & 0xFF;
3278 CDB[7] = (io->size >> 8) & 0xFF;
3279 CDB[8] = io->size & 0xFF;
3280 cmdTimeout = 10;
3281 break;
3282
3283 case WRITE_BUFFER:
3284 cmdLen = 10;
3285 dir = MPI_SCSIIO_CONTROL_WRITE;
3286 CDB[0] = cmd;
3287 if (io->flags & MPT_ICFLAG_ECHO) {
3288 CDB[1] = 0x0A;
3289 } else {
3290 CDB[1] = 0x02;
3291 }
3292 CDB[6] = (io->size >> 16) & 0xFF;
3293 CDB[7] = (io->size >> 8) & 0xFF;
3294 CDB[8] = io->size & 0xFF;
3295 cmdTimeout = 10;
3296 break;
3297
3298 case RESERVE:
3299 cmdLen = 6;
3300 dir = MPI_SCSIIO_CONTROL_READ;
3301 CDB[0] = cmd;
3302 cmdTimeout = 10;
3303 break;
3304
3305 case RELEASE:
3306 cmdLen = 6;
3307 dir = MPI_SCSIIO_CONTROL_READ;
3308 CDB[0] = cmd;
3309 cmdTimeout = 10;
3310 break;
3311
3312 case SYNCHRONIZE_CACHE:
3313 cmdLen = 10;
3314 dir = MPI_SCSIIO_CONTROL_READ;
3315 CDB[0] = cmd;
3316// CDB[1] = 0x02; /* set immediate bit */
3317 cmdTimeout = 10;
3318 break;
3319
3320 default:
3321 /* Error Case */
3322 return -EFAULT;
3323 }
3324
3325 /* Get and Populate a free Frame
3326 */
0d0c7974 3327 if ((mf = mpt_get_msg_frame(hd->ioc->InternalCtx, hd->ioc)) == NULL) {
1da177e4
LT
3328 ddvprintk((MYIOC_s_WARN_FMT "No msg frames!\n",
3329 hd->ioc->name));
3330 return -EBUSY;
3331 }
3332
3333 pScsiReq = (SCSIIORequest_t *) mf;
3334
3335 /* Get the request index */
3336 my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
3337 ADD_INDEX_LOG(my_idx); /* for debug */
3338
3339 if (io->flags & MPT_ICFLAG_PHYS_DISK) {
3340 pScsiReq->TargetID = io->physDiskNum;
3341 pScsiReq->Bus = 0;
3342 pScsiReq->ChainOffset = 0;
3343 pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
3344 } else {
3345 pScsiReq->TargetID = io->id;
3346 pScsiReq->Bus = io->bus;
3347 pScsiReq->ChainOffset = 0;
3348 pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
3349 }
3350
3351 pScsiReq->CDBLength = cmdLen;
3352 pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
3353
3354 pScsiReq->Reserved = 0;
3355
3356 pScsiReq->MsgFlags = mpt_msg_flags();
3357 /* MsgContext set in mpt_get_msg_fram call */
3358
3359 for (ii=0; ii < 8; ii++)
3360 pScsiReq->LUN[ii] = 0;
3361 pScsiReq->LUN[1] = io->lun;
3362
3363 if (io->flags & MPT_ICFLAG_TAGGED_CMD)
3364 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_SIMPLEQ);
3365 else
3366 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
3367
3368 if (cmd == REQUEST_SENSE) {
3369 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
3370 ddvprintk((MYIOC_s_INFO_FMT "Untagged! 0x%2x\n",
3371 hd->ioc->name, cmd));
3372 }
3373
3374 for (ii=0; ii < 16; ii++)
3375 pScsiReq->CDB[ii] = CDB[ii];
3376
3377 pScsiReq->DataLength = cpu_to_le32(io->size);
3378 pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma
3379 + (my_idx * MPT_SENSE_BUFFER_ALLOC));
3380
3381 ddvprintk((MYIOC_s_INFO_FMT "Sending Command 0x%x for (%d:%d:%d)\n",
3382 hd->ioc->name, cmd, io->bus, io->id, io->lun));
3383
3384 if (dir == MPI_SCSIIO_CONTROL_READ) {
3385 mpt_add_sge((char *) &pScsiReq->SGL,
3386 MPT_SGE_FLAGS_SSIMPLE_READ | io->size,
3387 io->data_dma);
3388 } else {
3389 mpt_add_sge((char *) &pScsiReq->SGL,
3390 MPT_SGE_FLAGS_SSIMPLE_WRITE | io->size,
3391 io->data_dma);
3392 }
3393
3394 /* The ISR will free the request frame, but we need
3395 * the information to initialize the target. Duplicate.
3396 */
3397 memcpy(&ReqCopy, pScsiReq, sizeof(SCSIIORequest_t));
3398
3399 /* Issue this command after:
3400 * finish init
3401 * add timer
3402 * Wait until the reply has been received
3403 * ScsiScanDvCtx callback function will
3404 * set hd->pLocal;
3405 * set scandv_wait_done and call wake_up
3406 */
3407 hd->pLocal = NULL;
3408 hd->timer.expires = jiffies + HZ*cmdTimeout;
0d0c7974 3409 hd->scandv_wait_done = 0;
1da177e4
LT
3410
3411 /* Save cmd pointer, for resource free if timeout or
3412 * FW reload occurs
3413 */
3414 hd->cmdPtr = mf;
3415
3416 add_timer(&hd->timer);
0d0c7974
MED
3417 mpt_put_msg_frame(hd->ioc->InternalCtx, hd->ioc, mf);
3418 wait_event(hd->scandv_waitq, hd->scandv_wait_done);
1da177e4
LT
3419
3420 if (hd->pLocal) {
3421 rc = hd->pLocal->completion;
3422 hd->pLocal->skip = 0;
3423
3424 /* Always set fatal error codes in some cases.
3425 */
3426 if (rc == MPT_SCANDV_SELECTION_TIMEOUT)
3427 rc = -ENXIO;
3428 else if (rc == MPT_SCANDV_SOME_ERROR)
3429 rc = -rc;
3430 } else {
3431 rc = -EFAULT;
3432 /* This should never happen. */
3433 ddvprintk((MYIOC_s_INFO_FMT "_do_cmd: Null pLocal!!!\n",
3434 hd->ioc->name));
3435 }
3436
3437 return rc;
3438}
3439
c7c82987
MED
3440/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3441/**
3442 * mptscsih_synchronize_cache - Send SYNCHRONIZE_CACHE to all disks.
3443 * @hd: Pointer to a SCSI HOST structure
d9489fb6 3444 * @vdevice: virtual target device
c7c82987
MED
3445 *
3446 * Uses the ISR, but with special processing.
3447 * MUST be single-threaded.
3448 *
3449 */
3450static void
3451mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
3452{
3453 INTERNAL_CMD iocmd;
1da177e4 3454
c7c82987
MED
3455 /* Following parameters will not change
3456 * in this routine.
3457 */
3458 iocmd.cmd = SYNCHRONIZE_CACHE;
3459 iocmd.flags = 0;
3460 iocmd.physDiskNum = -1;
3461 iocmd.data = NULL;
3462 iocmd.data_dma = -1;
3463 iocmd.size = 0;
3464 iocmd.rsvd = iocmd.rsvd2 = 0;
914c2d8e
ME
3465 iocmd.bus = vdevice->vtarget->bus_id;
3466 iocmd.id = vdevice->vtarget->target_id;
c7c82987 3467 iocmd.lun = (u8)vdevice->lun;
1da177e4 3468
c92f222e 3469 if ((vdevice->vtarget->type == TYPE_DISK) &&
c7c82987
MED
3470 (vdevice->configured_lun))
3471 mptscsih_do_cmd(hd, &iocmd);
1da177e4
LT
3472}
3473
0d0c7974
MED
3474EXPORT_SYMBOL(mptscsih_remove);
3475EXPORT_SYMBOL(mptscsih_shutdown);
3476#ifdef CONFIG_PM
3477EXPORT_SYMBOL(mptscsih_suspend);
3478EXPORT_SYMBOL(mptscsih_resume);
3479#endif
3480EXPORT_SYMBOL(mptscsih_proc_info);
3481EXPORT_SYMBOL(mptscsih_info);
3482EXPORT_SYMBOL(mptscsih_qcmd);
c7c82987 3483EXPORT_SYMBOL(mptscsih_target_alloc);
0d0c7974 3484EXPORT_SYMBOL(mptscsih_slave_alloc);
c7c82987 3485EXPORT_SYMBOL(mptscsih_target_destroy);
0d0c7974
MED
3486EXPORT_SYMBOL(mptscsih_slave_destroy);
3487EXPORT_SYMBOL(mptscsih_slave_configure);
3488EXPORT_SYMBOL(mptscsih_abort);
3489EXPORT_SYMBOL(mptscsih_dev_reset);
3490EXPORT_SYMBOL(mptscsih_bus_reset);
3491EXPORT_SYMBOL(mptscsih_host_reset);
3492EXPORT_SYMBOL(mptscsih_bios_param);
3493EXPORT_SYMBOL(mptscsih_io_done);
3494EXPORT_SYMBOL(mptscsih_taskmgmt_complete);
3495EXPORT_SYMBOL(mptscsih_scandv_complete);
3496EXPORT_SYMBOL(mptscsih_event_process);
3497EXPORT_SYMBOL(mptscsih_ioc_reset);
6e3815ba 3498EXPORT_SYMBOL(mptscsih_change_queue_depth);
0d0c7974 3499EXPORT_SYMBOL(mptscsih_timer_expired);
663e1aa1 3500EXPORT_SYMBOL(mptscsih_TMHandler);
1da177e4 3501
0d0c7974 3502/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/