Merge branch 'bkl/procfs' of git://git.kernel.org/pub/scm/linux/kernel/git/frederic...
[linux-2.6-block.git] / drivers / message / fusion / mptscsih.c
CommitLineData
1da177e4
LT
1/*
2 * linux/drivers/message/fusion/mptscsih.c
f36789e2
PS
3 * For use with LSI PCI chip/adapter(s)
4 * running LSI Fusion MPT (Message Passing Technology) firmware.
1da177e4 5 *
cddc0ab7 6 * Copyright (c) 1999-2008 LSI Corporation
16d20101 7 * (mailto:DL-MPTFusionLinux@lsi.com)
1da177e4 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
1da177e4
LT
47#include <linux/module.h>
48#include <linux/kernel.h>
5a0e3ad6 49#include <linux/slab.h>
1da177e4
LT
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 */
1da177e4
LT
57#include <linux/workqueue.h>
58
59#include <scsi/scsi.h>
60#include <scsi/scsi_cmnd.h>
61#include <scsi/scsi_device.h>
62#include <scsi/scsi_host.h>
63#include <scsi/scsi_tcq.h>
e0fc15be 64#include <scsi/scsi_dbg.h>
1da177e4
LT
65
66#include "mptbase.h"
67#include "mptscsih.h"
bf451522 68#include "lsi/mpi_log_sas.h"
1da177e4
LT
69
70/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
71#define my_NAME "Fusion MPT SCSI Host driver"
72#define my_VERSION MPT_LINUX_VERSION_COMMON
73#define MYNAM "mptscsih"
74
75MODULE_AUTHOR(MODULEAUTHOR);
76MODULE_DESCRIPTION(my_NAME);
77MODULE_LICENSE("GPL");
9f4203b3 78MODULE_VERSION(my_VERSION);
1da177e4 79
1da177e4 80/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1da177e4
LT
81/*
82 * Other private/forward protos...
83 */
db7051b2 84struct scsi_cmnd *mptscsih_get_scsi_lookup(MPT_ADAPTER *ioc, int i);
e8206381
EM
85static struct scsi_cmnd * mptscsih_getclear_scsi_lookup(MPT_ADAPTER *ioc, int i);
86static void mptscsih_set_scsi_lookup(MPT_ADAPTER *ioc, int i, struct scsi_cmnd *scmd);
87static int SCPNT_TO_LOOKUP_IDX(MPT_ADAPTER *ioc, struct scsi_cmnd *scmd);
0d0c7974 88int mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
1da177e4 89static void mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq);
0d0c7974 90int mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
1da177e4
LT
91
92static int mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt,
93 SCSIIORequest_t *pReq, int req_idx);
94static void mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx);
0d0c7974 95static void mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply);
1da177e4 96
1ba9ab2e
KD
97int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id,
98 int lun, int ctx2abort, ulong timeout);
1da177e4 99
0d0c7974
MED
100int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
101int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
1da177e4 102
e7deff33 103void
1ba9ab2e 104mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code);
37c60f37
KD
105static int mptscsih_get_completion_code(MPT_ADAPTER *ioc,
106 MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply);
0d0c7974 107int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
1da177e4 108static int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd);
c7c82987 109static void mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice);
1da177e4 110
1ba9ab2e
KD
111static int
112mptscsih_taskmgmt_reply(MPT_ADAPTER *ioc, u8 type,
113 SCSITaskMgmtReply_t *pScsiTmReply);
0d0c7974 114void mptscsih_remove(struct pci_dev *);
d18c3db5 115void mptscsih_shutdown(struct pci_dev *);
1da177e4 116#ifdef CONFIG_PM
0d0c7974
MED
117int mptscsih_suspend(struct pci_dev *pdev, pm_message_t state);
118int mptscsih_resume(struct pci_dev *pdev);
1da177e4
LT
119#endif
120
b80ca4f7 121#define SNS_LEN(scp) SCSI_SENSE_BUFFERSIZE
1da177e4 122
1da177e4
LT
123
124/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
125/*
126 * mptscsih_getFreeChainBuffer - Function to get a free chain
127 * from the MPT_SCSI_HOST FreeChainQ.
128 * @ioc: Pointer to MPT_ADAPTER structure
129 * @req_idx: Index of the SCSI IO request frame. (output)
130 *
131 * return SUCCESS or FAILED
132 */
133static inline int
134mptscsih_getFreeChainBuffer(MPT_ADAPTER *ioc, int *retIndex)
135{
136 MPT_FRAME_HDR *chainBuf;
137 unsigned long flags;
138 int rc;
139 int chain_idx;
140
6757d6b4 141 dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT "getFreeChainBuffer called\n",
29dd3609 142 ioc->name));
1da177e4
LT
143 spin_lock_irqsave(&ioc->FreeQlock, flags);
144 if (!list_empty(&ioc->FreeChainQ)) {
145 int offset;
146
147 chainBuf = list_entry(ioc->FreeChainQ.next, MPT_FRAME_HDR,
148 u.frame.linkage.list);
149 list_del(&chainBuf->u.frame.linkage.list);
150 offset = (u8 *)chainBuf - (u8 *)ioc->ChainBuffer;
151 chain_idx = offset / ioc->req_sz;
152 rc = SUCCESS;
29dd3609
EM
153 dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT
154 "getFreeChainBuffer chainBuf=%p ChainBuffer=%p offset=%d chain_idx=%d\n",
155 ioc->name, chainBuf, ioc->ChainBuffer, offset, chain_idx));
1da177e4
LT
156 } else {
157 rc = FAILED;
158 chain_idx = MPT_HOST_NO_CHAIN;
29dd3609
EM
159 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "getFreeChainBuffer failed\n",
160 ioc->name));
1da177e4
LT
161 }
162 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
163
164 *retIndex = chain_idx;
165 return rc;
166} /* mptscsih_getFreeChainBuffer() */
167
168/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
169/*
170 * mptscsih_AddSGE - Add a SGE (plus chain buffers) to the
171 * SCSIIORequest_t Message Frame.
172 * @ioc: Pointer to MPT_ADAPTER structure
173 * @SCpnt: Pointer to scsi_cmnd structure
174 * @pReq: Pointer to SCSIIORequest_t structure
175 *
176 * Returns ...
177 */
178static int
179mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt,
180 SCSIIORequest_t *pReq, int req_idx)
181{
182 char *psge;
183 char *chainSge;
184 struct scatterlist *sg;
185 int frm_sz;
186 int sges_left, sg_done;
187 int chain_idx = MPT_HOST_NO_CHAIN;
188 int sgeOffset;
189 int numSgeSlots, numSgeThisFrame;
190 u32 sgflags, sgdir, thisxfer = 0;
191 int chain_dma_off = 0;
192 int newIndex;
193 int ii;
194 dma_addr_t v2;
195 u32 RequestNB;
196
197 sgdir = le32_to_cpu(pReq->Control) & MPI_SCSIIO_CONTROL_DATADIRECTION_MASK;
198 if (sgdir == MPI_SCSIIO_CONTROL_WRITE) {
199 sgdir = MPT_TRANSFER_HOST_TO_IOC;
200 } else {
201 sgdir = MPT_TRANSFER_IOC_TO_HOST;
202 }
203
204 psge = (char *) &pReq->SGL;
205 frm_sz = ioc->req_sz;
206
207 /* Map the data portion, if any.
208 * sges_left = 0 if no data transfer.
209 */
1928d73f
FT
210 sges_left = scsi_dma_map(SCpnt);
211 if (sges_left < 0)
212 return FAILED;
1da177e4
LT
213
214 /* Handle the SG case.
215 */
1928d73f 216 sg = scsi_sglist(SCpnt);
1da177e4
LT
217 sg_done = 0;
218 sgeOffset = sizeof(SCSIIORequest_t) - sizeof(SGE_IO_UNION);
219 chainSge = NULL;
220
221 /* Prior to entering this loop - the following must be set
222 * current MF: sgeOffset (bytes)
223 * chainSge (Null if original MF is not a chain buffer)
224 * sg_done (num SGE done for this MF)
225 */
226
227nextSGEset:
14d0f0b0 228 numSgeSlots = ((frm_sz - sgeOffset) / ioc->SGE_size);
1da177e4
LT
229 numSgeThisFrame = (sges_left < numSgeSlots) ? sges_left : numSgeSlots;
230
14d0f0b0 231 sgflags = MPT_SGE_FLAGS_SIMPLE_ELEMENT | sgdir;
1da177e4
LT
232
233 /* Get first (num - 1) SG elements
234 * Skip any SG entries with a length of 0
235 * NOTE: at finish, sg and psge pointed to NEXT data/location positions
236 */
237 for (ii=0; ii < (numSgeThisFrame-1); ii++) {
238 thisxfer = sg_dma_len(sg);
239 if (thisxfer == 0) {
2f187862
KD
240 /* Get next SG element from the OS */
241 sg = sg_next(sg);
1da177e4
LT
242 sg_done++;
243 continue;
244 }
245
246 v2 = sg_dma_address(sg);
14d0f0b0 247 ioc->add_sge(psge, sgflags | thisxfer, v2);
1da177e4 248
2f187862
KD
249 /* Get next SG element from the OS */
250 sg = sg_next(sg);
14d0f0b0
KD
251 psge += ioc->SGE_size;
252 sgeOffset += ioc->SGE_size;
1da177e4
LT
253 sg_done++;
254 }
255
256 if (numSgeThisFrame == sges_left) {
257 /* Add last element, end of buffer and end of list flags.
258 */
259 sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT |
260 MPT_SGE_FLAGS_END_OF_BUFFER |
261 MPT_SGE_FLAGS_END_OF_LIST;
262
263 /* Add last SGE and set termination flags.
264 * Note: Last SGE may have a length of 0 - which should be ok.
265 */
266 thisxfer = sg_dma_len(sg);
267
268 v2 = sg_dma_address(sg);
14d0f0b0
KD
269 ioc->add_sge(psge, sgflags | thisxfer, v2);
270 sgeOffset += ioc->SGE_size;
1da177e4
LT
271 sg_done++;
272
273 if (chainSge) {
274 /* The current buffer is a chain buffer,
275 * but there is not another one.
276 * Update the chain element
277 * Offset and Length fields.
278 */
14d0f0b0
KD
279 ioc->add_chain((char *)chainSge, 0, sgeOffset,
280 ioc->ChainBufferDMA + chain_dma_off);
1da177e4
LT
281 } else {
282 /* The current buffer is the original MF
283 * and there is no Chain buffer.
284 */
285 pReq->ChainOffset = 0;
286 RequestNB = (((sgeOffset - 1) >> ioc->NBShiftFactor) + 1) & 0x03;
6757d6b4 287 dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1da177e4
LT
288 "Single Buffer RequestNB=%x, sgeOffset=%d\n", ioc->name, RequestNB, sgeOffset));
289 ioc->RequestNB[req_idx] = RequestNB;
290 }
291 } else {
292 /* At least one chain buffer is needed.
293 * Complete the first MF
294 * - last SGE element, set the LastElement bit
295 * - set ChainOffset (words) for orig MF
296 * (OR finish previous MF chain buffer)
297 * - update MFStructPtr ChainIndex
298 * - Populate chain element
299 * Also
300 * Loop until done.
301 */
302
6757d6b4 303 dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SG: Chain Required! sg done %d\n",
1da177e4
LT
304 ioc->name, sg_done));
305
306 /* Set LAST_ELEMENT flag for last non-chain element
307 * in the buffer. Since psge points at the NEXT
308 * SGE element, go back one SGE element, update the flags
309 * and reset the pointer. (Note: sgflags & thisxfer are already
310 * set properly).
311 */
312 if (sg_done) {
14d0f0b0 313 u32 *ptmp = (u32 *) (psge - ioc->SGE_size);
1da177e4
LT
314 sgflags = le32_to_cpu(*ptmp);
315 sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT;
316 *ptmp = cpu_to_le32(sgflags);
317 }
318
319 if (chainSge) {
320 /* The current buffer is a chain buffer.
321 * chainSge points to the previous Chain Element.
322 * Update its chain element Offset and Length (must
323 * include chain element size) fields.
324 * Old chain element is now complete.
325 */
326 u8 nextChain = (u8) (sgeOffset >> 2);
14d0f0b0
KD
327 sgeOffset += ioc->SGE_size;
328 ioc->add_chain((char *)chainSge, nextChain, sgeOffset,
329 ioc->ChainBufferDMA + chain_dma_off);
1da177e4
LT
330 } else {
331 /* The original MF buffer requires a chain buffer -
332 * set the offset.
333 * Last element in this MF is a chain element.
334 */
335 pReq->ChainOffset = (u8) (sgeOffset >> 2);
336 RequestNB = (((sgeOffset - 1) >> ioc->NBShiftFactor) + 1) & 0x03;
6757d6b4 337 dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Chain Buffer Needed, RequestNB=%x sgeOffset=%d\n", ioc->name, RequestNB, sgeOffset));
1da177e4
LT
338 ioc->RequestNB[req_idx] = RequestNB;
339 }
340
341 sges_left -= sg_done;
342
343
344 /* NOTE: psge points to the beginning of the chain element
345 * in current buffer. Get a chain buffer.
346 */
c6678e0c 347 if ((mptscsih_getFreeChainBuffer(ioc, &newIndex)) == FAILED) {
6757d6b4 348 dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT
c6678e0c
CH
349 "getFreeChainBuffer FAILED SCSI cmd=%02x (%p)\n",
350 ioc->name, pReq->CDB[0], SCpnt));
1da177e4 351 return FAILED;
c6678e0c 352 }
1da177e4
LT
353
354 /* Update the tracking arrays.
355 * If chainSge == NULL, update ReqToChain, else ChainToChain
356 */
357 if (chainSge) {
358 ioc->ChainToChain[chain_idx] = newIndex;
359 } else {
360 ioc->ReqToChain[req_idx] = newIndex;
361 }
362 chain_idx = newIndex;
363 chain_dma_off = ioc->req_sz * chain_idx;
364
365 /* Populate the chainSGE for the current buffer.
366 * - Set chain buffer pointer to psge and fill
367 * out the Address and Flags fields.
368 */
369 chainSge = (char *) psge;
29dd3609
EM
370 dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT " Current buff @ %p (index 0x%x)",
371 ioc->name, psge, req_idx));
1da177e4
LT
372
373 /* Start the SGE for the next buffer
374 */
375 psge = (char *) (ioc->ChainBuffer + chain_dma_off);
376 sgeOffset = 0;
377 sg_done = 0;
378
29dd3609
EM
379 dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT " Chain buff @ %p (index 0x%x)\n",
380 ioc->name, psge, chain_idx));
1da177e4
LT
381
382 /* Start the SGE for the next buffer
383 */
384
385 goto nextSGEset;
386 }
387
388 return SUCCESS;
389} /* mptscsih_AddSGE() */
390
786899b0
EM
391static void
392mptscsih_issue_sep_command(MPT_ADAPTER *ioc, VirtTarget *vtarget,
393 U32 SlotStatus)
394{
395 MPT_FRAME_HDR *mf;
396 SEPRequest_t *SEPMsg;
397
cc78d30a
EM
398 if (ioc->bus_type != SAS)
399 return;
400
401 /* Not supported for hidden raid components
402 */
403 if (vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT)
786899b0
EM
404 return;
405
406 if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) {
6757d6b4 407 dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s: no msg frames!!\n",
cadbd4a5 408 ioc->name,__func__));
786899b0
EM
409 return;
410 }
411
412 SEPMsg = (SEPRequest_t *)mf;
413 SEPMsg->Function = MPI_FUNCTION_SCSI_ENCLOSURE_PROCESSOR;
793955f5
EM
414 SEPMsg->Bus = vtarget->channel;
415 SEPMsg->TargetID = vtarget->id;
786899b0
EM
416 SEPMsg->Action = MPI_SEP_REQ_ACTION_WRITE_STATUS;
417 SEPMsg->SlotStatus = SlotStatus;
6757d6b4 418 devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT
793955f5
EM
419 "Sending SEP cmd=%x channel=%d id=%d\n",
420 ioc->name, SlotStatus, SEPMsg->Bus, SEPMsg->TargetID));
786899b0
EM
421 mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
422}
423
6757d6b4 424#ifdef CONFIG_FUSION_LOGGING
c6c727a1 425/**
6757d6b4 426 * mptscsih_info_scsiio - debug print info on reply frame
c6c727a1 427 * @ioc: Pointer to MPT_ADAPTER structure
c6c727a1 428 * @sc: original scsi cmnd pointer
6757d6b4
PS
429 * @pScsiReply: Pointer to MPT reply frame
430 *
431 * MPT_DEBUG_REPLY needs to be enabled to obtain this info
c6c727a1
EM
432 *
433 * Refer to lsi/mpi.h.
434 **/
435static void
6757d6b4 436mptscsih_info_scsiio(MPT_ADAPTER *ioc, struct scsi_cmnd *sc, SCSIIOReply_t * pScsiReply)
c6c727a1 437{
6757d6b4
PS
438 char *desc = NULL;
439 char *desc1 = NULL;
440 u16 ioc_status;
441 u8 skey, asc, ascq;
442
443 ioc_status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK;
c6c727a1
EM
444
445 switch (ioc_status) {
446
6757d6b4
PS
447 case MPI_IOCSTATUS_SUCCESS:
448 desc = "success";
c6c727a1 449 break;
6757d6b4
PS
450 case MPI_IOCSTATUS_SCSI_INVALID_BUS:
451 desc = "invalid bus";
c6c727a1 452 break;
6757d6b4
PS
453 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID:
454 desc = "invalid target_id";
c6c727a1 455 break;
6757d6b4
PS
456 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
457 desc = "device not there";
c6c727a1 458 break;
6757d6b4
PS
459 case MPI_IOCSTATUS_SCSI_DATA_OVERRUN:
460 desc = "data overrun";
c6c727a1 461 break;
6757d6b4
PS
462 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN:
463 desc = "data underrun";
c6c727a1 464 break;
6757d6b4
PS
465 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR:
466 desc = "I/O data error";
c6c727a1 467 break;
6757d6b4
PS
468 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR:
469 desc = "protocol error";
c6c727a1 470 break;
6757d6b4
PS
471 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED:
472 desc = "task terminated";
c6c727a1 473 break;
6757d6b4
PS
474 case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:
475 desc = "residual mismatch";
476 break;
477 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED:
478 desc = "task management failed";
479 break;
480 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED:
481 desc = "IOC terminated";
482 break;
483 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED:
484 desc = "ext terminated";
c6c727a1 485 break;
6757d6b4
PS
486 default:
487 desc = "";
488 break;
489 }
490
491 switch (pScsiReply->SCSIStatus)
492 {
c6c727a1 493
6757d6b4
PS
494 case MPI_SCSI_STATUS_SUCCESS:
495 desc1 = "success";
496 break;
497 case MPI_SCSI_STATUS_CHECK_CONDITION:
498 desc1 = "check condition";
499 break;
500 case MPI_SCSI_STATUS_CONDITION_MET:
501 desc1 = "condition met";
502 break;
503 case MPI_SCSI_STATUS_BUSY:
504 desc1 = "busy";
505 break;
506 case MPI_SCSI_STATUS_INTERMEDIATE:
507 desc1 = "intermediate";
508 break;
509 case MPI_SCSI_STATUS_INTERMEDIATE_CONDMET:
510 desc1 = "intermediate condmet";
511 break;
512 case MPI_SCSI_STATUS_RESERVATION_CONFLICT:
513 desc1 = "reservation conflict";
514 break;
515 case MPI_SCSI_STATUS_COMMAND_TERMINATED:
516 desc1 = "command terminated";
517 break;
518 case MPI_SCSI_STATUS_TASK_SET_FULL:
519 desc1 = "task set full";
520 break;
521 case MPI_SCSI_STATUS_ACA_ACTIVE:
522 desc1 = "aca active";
523 break;
524 case MPI_SCSI_STATUS_FCPEXT_DEVICE_LOGGED_OUT:
525 desc1 = "fcpext device logged out";
526 break;
527 case MPI_SCSI_STATUS_FCPEXT_NO_LINK:
528 desc1 = "fcpext no link";
529 break;
530 case MPI_SCSI_STATUS_FCPEXT_UNASSIGNED:
531 desc1 = "fcpext unassigned";
532 break;
533 default:
534 desc1 = "";
c6c727a1
EM
535 break;
536 }
537
6757d6b4 538 scsi_print_command(sc);
2f187862
KD
539 printk(MYIOC_s_DEBUG_FMT "\tfw_channel = %d, fw_id = %d, lun = %d\n",
540 ioc->name, pScsiReply->Bus, pScsiReply->TargetID, sc->device->lun);
29dd3609
EM
541 printk(MYIOC_s_DEBUG_FMT "\trequest_len = %d, underflow = %d, "
542 "resid = %d\n", ioc->name, scsi_bufflen(sc), sc->underflow,
543 scsi_get_resid(sc));
544 printk(MYIOC_s_DEBUG_FMT "\ttag = %d, transfer_count = %d, "
545 "sc->result = %08X\n", ioc->name, le16_to_cpu(pScsiReply->TaskTag),
6757d6b4 546 le32_to_cpu(pScsiReply->TransferCount), sc->result);
2f187862 547
29dd3609 548 printk(MYIOC_s_DEBUG_FMT "\tiocstatus = %s (0x%04x), "
6757d6b4 549 "scsi_status = %s (0x%02x), scsi_state = (0x%02x)\n",
29dd3609 550 ioc->name, desc, ioc_status, desc1, pScsiReply->SCSIStatus,
6757d6b4 551 pScsiReply->SCSIState);
c6c727a1 552
6757d6b4
PS
553 if (pScsiReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) {
554 skey = sc->sense_buffer[2] & 0x0F;
555 asc = sc->sense_buffer[12];
556 ascq = sc->sense_buffer[13];
557
29dd3609
EM
558 printk(MYIOC_s_DEBUG_FMT "\t[sense_key,asc,ascq]: "
559 "[0x%02x,0x%02x,0x%02x]\n", ioc->name, skey, asc, ascq);
6757d6b4
PS
560 }
561
562 /*
563 * Look for + dump FCP ResponseInfo[]!
564 */
565 if (pScsiReply->SCSIState & MPI_SCSI_STATE_RESPONSE_INFO_VALID &&
566 pScsiReply->ResponseInfo)
29dd3609
EM
567 printk(MYIOC_s_DEBUG_FMT "response_info = %08xh\n",
568 ioc->name, le32_to_cpu(pScsiReply->ResponseInfo));
c6c727a1
EM
569}
570#endif
571
1da177e4
LT
572/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
573/*
574 * mptscsih_io_done - Main SCSI IO callback routine registered to
575 * Fusion MPT (base) driver
576 * @ioc: Pointer to MPT_ADAPTER structure
577 * @mf: Pointer to original MPT request frame
578 * @r: Pointer to MPT reply frame (NULL if TurboReply)
579 *
580 * This routine is called from mpt.c::mpt_interrupt() at the completion
581 * of any SCSI IO request.
582 * This routine is registered with the Fusion MPT (base) driver at driver
583 * load/init time via the mpt_register() API call.
584 *
585 * Returns 1 indicating alloc'd request frame ptr should be freed.
586 */
0d0c7974 587int
1da177e4
LT
588mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
589{
590 struct scsi_cmnd *sc;
591 MPT_SCSI_HOST *hd;
592 SCSIIORequest_t *pScsiReq;
593 SCSIIOReply_t *pScsiReply;
2254c86d 594 u16 req_idx, req_idx_MR;
a69de507 595 VirtDevice *vdevice;
786899b0 596 VirtTarget *vtarget;
1da177e4 597
e7eae9f6 598 hd = shost_priv(ioc->sh);
1da177e4 599 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
2254c86d
ME
600 req_idx_MR = (mr != NULL) ?
601 le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx) : req_idx;
2f187862
KD
602
603 /* Special case, where already freed message frame is received from
604 * Firmware. It happens with Resetting IOC.
605 * Return immediately. Do not care
606 */
2254c86d 607 if ((req_idx != req_idx_MR) ||
2f187862 608 (le32_to_cpu(mf->u.frame.linkage.arg1) == 0xdeadbeaf))
2254c86d 609 return 0;
2254c86d 610
e8206381 611 sc = mptscsih_getclear_scsi_lookup(ioc, req_idx);
1da177e4
LT
612 if (sc == NULL) {
613 MPIHeader_t *hdr = (MPIHeader_t *)mf;
614
615 /* Remark: writeSDP1 will use the ScsiDoneCtx
616 * If a SCSI I/O cmd, device disabled by OS and
617 * completion done. Cannot touch sc struct. Just free mem.
618 */
619 if (hdr->Function == MPI_FUNCTION_SCSI_IO_REQUEST)
620 printk(MYIOC_s_ERR_FMT "NULL ScsiCmd ptr!\n",
621 ioc->name);
622
623 mptscsih_freeChainBuffers(ioc, req_idx);
624 return 1;
625 }
626
3dc0b03f
EM
627 if ((unsigned char *)mf != sc->host_scribble) {
628 mptscsih_freeChainBuffers(ioc, req_idx);
629 return 1;
630 }
631
fea98403
KD
632 if (ioc->bus_type == SAS) {
633 VirtDevice *vdevice = sc->device->hostdata;
634
635 if (!vdevice || !vdevice->vtarget ||
636 vdevice->vtarget->deleted) {
637 sc->result = DID_NO_CONNECT << 16;
638 goto out;
639 }
640 }
641
3dc0b03f 642 sc->host_scribble = NULL;
1da177e4
LT
643 sc->result = DID_OK << 16; /* Set default reply as OK */
644 pScsiReq = (SCSIIORequest_t *) mf;
645 pScsiReply = (SCSIIOReply_t *) mr;
646
c6678e0c 647 if((ioc->facts.MsgVersion >= MPI_VERSION_01_05) && pScsiReply){
6757d6b4 648 dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT
c6678e0c
CH
649 "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d,task-tag=%d)\n",
650 ioc->name, mf, mr, sc, req_idx, pScsiReply->TaskTag));
651 }else{
6757d6b4 652 dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT
c6678e0c
CH
653 "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d)\n",
654 ioc->name, mf, mr, sc, req_idx));
655 }
656
1da177e4
LT
657 if (pScsiReply == NULL) {
658 /* special context reply handling */
659 ;
660 } else {
661 u32 xfer_cnt;
662 u16 status;
663 u8 scsi_state, scsi_status;
c6c727a1 664 u32 log_info;
1da177e4
LT
665
666 status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK;
667 scsi_state = pScsiReply->SCSIState;
668 scsi_status = pScsiReply->SCSIStatus;
669 xfer_cnt = le32_to_cpu(pScsiReply->TransferCount);
1928d73f 670 scsi_set_resid(sc, scsi_bufflen(sc) - xfer_cnt);
c6c727a1 671 log_info = le32_to_cpu(pScsiReply->IOCLogInfo);
1da177e4 672
466544d8
MED
673 /*
674 * if we get a data underrun indication, yet no data was
675 * transferred and the SCSI status indicates that the
676 * command was never started, change the data underrun
677 * to success
678 */
679 if (status == MPI_IOCSTATUS_SCSI_DATA_UNDERRUN && xfer_cnt == 0 &&
680 (scsi_status == MPI_SCSI_STATUS_BUSY ||
681 scsi_status == MPI_SCSI_STATUS_RESERVATION_CONFLICT ||
682 scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL)) {
683 status = MPI_IOCSTATUS_SUCCESS;
684 }
685
1da177e4 686 if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID)
0d0c7974
MED
687 mptscsih_copy_sense_data(sc, hd, mf, pScsiReply);
688
1da177e4
LT
689 /*
690 * Look for + dump FCP ResponseInfo[]!
691 */
466544d8
MED
692 if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID &&
693 pScsiReply->ResponseInfo) {
29dd3609
EM
694 printk(MYIOC_s_NOTE_FMT "[%d:%d:%d:%d] "
695 "FCP_ResponseInfo=%08xh\n", ioc->name,
c6c727a1
EM
696 sc->device->host->host_no, sc->device->channel,
697 sc->device->id, sc->device->lun,
1da177e4
LT
698 le32_to_cpu(pScsiReply->ResponseInfo));
699 }
700
701 switch(status) {
702 case MPI_IOCSTATUS_BUSY: /* 0x0002 */
d23321b4 703 case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */
1da177e4
LT
704 /* CHECKME!
705 * Maybe: DRIVER_BUSY | SUGGEST_RETRY | DID_SOFT_ERROR (retry)
706 * But not: DID_BUS_BUSY lest one risk
707 * killing interrupt handler:-(
708 */
709 sc->result = SAM_STAT_BUSY;
710 break;
711
712 case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
713 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
714 sc->result = DID_BAD_TARGET << 16;
715 break;
716
717 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
718 /* Spoof to SCSI Selection Timeout! */
65207fed
ME
719 if (ioc->bus_type != FC)
720 sc->result = DID_NO_CONNECT << 16;
721 /* else fibre, just stall until rescan event */
722 else
723 sc->result = DID_REQUEUE << 16;
1da177e4
LT
724
725 if (hd->sel_timeout[pScsiReq->TargetID] < 0xFFFF)
726 hd->sel_timeout[pScsiReq->TargetID]++;
786899b0 727
a69de507
EM
728 vdevice = sc->device->hostdata;
729 if (!vdevice)
786899b0 730 break;
a69de507 731 vtarget = vdevice->vtarget;
786899b0
EM
732 if (vtarget->tflags & MPT_TARGET_FLAGS_LED_ON) {
733 mptscsih_issue_sep_command(ioc, vtarget,
734 MPI_SEP_REQ_SLOTSTATUS_UNCONFIGURED);
735 vtarget->tflags &= ~MPT_TARGET_FLAGS_LED_ON;
736 }
1da177e4
LT
737 break;
738
1da177e4 739 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
bf451522
EM
740 if ( ioc->bus_type == SAS ) {
741 u16 ioc_status = le16_to_cpu(pScsiReply->IOCStatus);
742 if (ioc_status & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
c6c727a1
EM
743 if ((log_info & SAS_LOGINFO_MASK)
744 == SAS_LOGINFO_NEXUS_LOSS) {
bf451522
EM
745 sc->result = (DID_BUS_BUSY << 16);
746 break;
747 }
748 }
86dd4242
EM
749 } else if (ioc->bus_type == FC) {
750 /*
751 * The FC IOC may kill a request for variety of
752 * reasons, some of which may be recovered by a
753 * retry, some which are unlikely to be
754 * recovered. Return DID_ERROR instead of
755 * DID_RESET to permit retry of the command,
756 * just not an infinite number of them
757 */
758 sc->result = DID_ERROR << 16;
759 break;
bf451522
EM
760 }
761
762 /*
763 * Allow non-SAS & non-NEXUS_LOSS to drop into below code
764 */
765
766 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
1da177e4
LT
767 /* Linux handles an unsolicited DID_RESET better
768 * than an unsolicited DID_ABORT.
769 */
770 sc->result = DID_RESET << 16;
771
2f187862
KD
772 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
773 if (ioc->bus_type == FC)
774 sc->result = DID_ERROR << 16;
775 else
776 sc->result = DID_RESET << 16;
1da177e4
LT
777 break;
778
779 case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
1928d73f 780 scsi_set_resid(sc, scsi_bufflen(sc) - xfer_cnt);
466544d8
MED
781 if((xfer_cnt==0)||(sc->underflow > xfer_cnt))
782 sc->result=DID_SOFT_ERROR << 16;
783 else /* Sufficient data transfer occurred */
1da177e4 784 sc->result = (DID_OK << 16) | scsi_status;
29dd3609 785 dreplyprintk(ioc, printk(MYIOC_s_DEBUG_FMT
c6c727a1 786 "RESIDUAL_MISMATCH: result=%x on channel=%d id=%d\n",
29dd3609 787 ioc->name, sc->result, sc->device->channel, sc->device->id));
1da177e4 788 break;
0d0c7974 789
1da177e4
LT
790 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
791 /*
792 * Do upfront check for valid SenseData and give it
793 * precedence!
794 */
795 sc->result = (DID_OK << 16) | scsi_status;
9b53b392
KD
796 if (!(scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID)) {
797
798 /*
799 * For an Errata on LSI53C1030
800 * When the length of request data
801 * and transfer data are different
802 * with result of command (READ or VERIFY),
803 * DID_SOFT_ERROR is set.
1da177e4 804 */
9b53b392
KD
805 if (ioc->bus_type == SPI) {
806 if (pScsiReq->CDB[0] == READ_6 ||
807 pScsiReq->CDB[0] == READ_10 ||
808 pScsiReq->CDB[0] == READ_12 ||
809 pScsiReq->CDB[0] == READ_16 ||
810 pScsiReq->CDB[0] == VERIFY ||
811 pScsiReq->CDB[0] == VERIFY_16) {
812 if (scsi_bufflen(sc) !=
813 xfer_cnt) {
814 sc->result =
815 DID_SOFT_ERROR << 16;
816 printk(KERN_WARNING "Errata"
817 "on LSI53C1030 occurred."
818 "sc->req_bufflen=0x%02x,"
819 "xfer_cnt=0x%02x\n",
820 scsi_bufflen(sc),
821 xfer_cnt);
822 }
823 }
824 }
825
1da177e4 826 if (xfer_cnt < sc->underflow) {
466544d8
MED
827 if (scsi_status == SAM_STAT_BUSY)
828 sc->result = SAM_STAT_BUSY;
829 else
830 sc->result = DID_SOFT_ERROR << 16;
1da177e4
LT
831 }
832 if (scsi_state & (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)) {
833 /* What to do?
834 */
835 sc->result = DID_SOFT_ERROR << 16;
836 }
837 else if (scsi_state & MPI_SCSI_STATE_TERMINATED) {
838 /* Not real sure here either... */
839 sc->result = DID_RESET << 16;
840 }
841 }
842
6757d6b4 843
29dd3609
EM
844 dreplyprintk(ioc, printk(MYIOC_s_DEBUG_FMT
845 " sc->underflow={report ERR if < %02xh bytes xfer'd}\n",
846 ioc->name, sc->underflow));
847 dreplyprintk(ioc, printk(MYIOC_s_DEBUG_FMT
848 " ActBytesXferd=%02xh\n", ioc->name, xfer_cnt));
6757d6b4 849
1da177e4
LT
850 /* Report Queue Full
851 */
852 if (scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL)
853 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
0d0c7974 854
1da177e4
LT
855 break;
856
7e55147f 857 case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
1928d73f 858 scsi_set_resid(sc, 0);
1da177e4
LT
859 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
860 case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */
ad8c31bb 861 sc->result = (DID_OK << 16) | scsi_status;
1da177e4
LT
862 if (scsi_state == 0) {
863 ;
9b53b392
KD
864 } else if (scsi_state &
865 MPI_SCSI_STATE_AUTOSENSE_VALID) {
866
867 /*
868 * For potential trouble on LSI53C1030.
869 * (date:2007.xx.)
870 * It is checked whether the length of
871 * request data is equal to
872 * the length of transfer and residual.
873 * MEDIUM_ERROR is set by incorrect data.
874 */
875 if ((ioc->bus_type == SPI) &&
876 (sc->sense_buffer[2] & 0x20)) {
877 u32 difftransfer;
878 difftransfer =
879 sc->sense_buffer[3] << 24 |
880 sc->sense_buffer[4] << 16 |
881 sc->sense_buffer[5] << 8 |
882 sc->sense_buffer[6];
883 if (((sc->sense_buffer[3] & 0x80) ==
884 0x80) && (scsi_bufflen(sc)
885 != xfer_cnt)) {
886 sc->sense_buffer[2] =
887 MEDIUM_ERROR;
888 sc->sense_buffer[12] = 0xff;
889 sc->sense_buffer[13] = 0xff;
890 printk(KERN_WARNING"Errata"
891 "on LSI53C1030 occurred."
892 "sc->req_bufflen=0x%02x,"
893 "xfer_cnt=0x%02x\n" ,
894 scsi_bufflen(sc),
895 xfer_cnt);
896 }
897 if (((sc->sense_buffer[3] & 0x80)
898 != 0x80) &&
899 (scsi_bufflen(sc) !=
900 xfer_cnt + difftransfer)) {
901 sc->sense_buffer[2] =
902 MEDIUM_ERROR;
903 sc->sense_buffer[12] = 0xff;
904 sc->sense_buffer[13] = 0xff;
905 printk(KERN_WARNING
906 "Errata on LSI53C1030 occurred"
907 "sc->req_bufflen=0x%02x,"
908 " xfer_cnt=0x%02x,"
909 "difftransfer=0x%02x\n",
910 scsi_bufflen(sc),
911 xfer_cnt,
912 difftransfer);
913 }
914 }
915
1da177e4
LT
916 /*
917 * If running against circa 200003dd 909 MPT f/w,
918 * may get this (AUTOSENSE_VALID) for actual TASK_SET_FULL
919 * (QUEUE_FULL) returned from device! --> get 0x0000?128
920 * and with SenseBytes set to 0.
921 */
922 if (pScsiReply->SCSIStatus == MPI_SCSI_STATUS_TASK_SET_FULL)
923 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
924
925 }
926 else if (scsi_state &
927 (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)
928 ) {
929 /*
930 * What to do?
931 */
932 sc->result = DID_SOFT_ERROR << 16;
933 }
934 else if (scsi_state & MPI_SCSI_STATE_TERMINATED) {
935 /* Not real sure here either... */
936 sc->result = DID_RESET << 16;
937 }
938 else if (scsi_state & MPI_SCSI_STATE_QUEUE_TAG_REJECTED) {
939 /* Device Inq. data indicates that it supports
940 * QTags, but rejects QTag messages.
941 * This command completed OK.
942 *
943 * Not real sure here either so do nothing... */
944 }
945
946 if (sc->result == MPI_SCSI_STATUS_TASK_SET_FULL)
947 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
948
949 /* Add handling of:
950 * Reservation Conflict, Busy,
951 * Command Terminated, CHECK
952 */
953 break;
954
955 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
956 sc->result = DID_SOFT_ERROR << 16;
957 break;
958
959 case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */
960 case MPI_IOCSTATUS_INVALID_SGL: /* 0x0003 */
961 case MPI_IOCSTATUS_INTERNAL_ERROR: /* 0x0004 */
962 case MPI_IOCSTATUS_RESERVED: /* 0x0005 */
1da177e4
LT
963 case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */
964 case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */
1da177e4
LT
965 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
966 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
967 default:
968 /*
969 * What to do?
970 */
971 sc->result = DID_SOFT_ERROR << 16;
972 break;
973
974 } /* switch(status) */
975
6757d6b4
PS
976#ifdef CONFIG_FUSION_LOGGING
977 if (sc->result && (ioc->debug_level & MPT_DEBUG_REPLY))
978 mptscsih_info_scsiio(ioc, sc, pScsiReply);
c6c727a1
EM
979#endif
980
1da177e4 981 } /* end of address reply case */
fea98403 982out:
1da177e4 983 /* Unmap the DMA buffers, if any. */
1928d73f 984 scsi_dma_unmap(sc);
1da177e4 985
1da177e4
LT
986 sc->scsi_done(sc); /* Issue the command callback */
987
988 /* Free Chain buffers */
989 mptscsih_freeChainBuffers(ioc, req_idx);
990 return 1;
991}
992
1da177e4
LT
993/*
994 * mptscsih_flush_running_cmds - For each command found, search
995 * Scsi_Host instance taskQ and reply to OS.
996 * Called only if recovering from a FW reload.
997 * @hd: Pointer to a SCSI HOST structure
998 *
999 * Returns: None.
1000 *
1001 * Must be called while new I/Os are being queued.
1002 */
1003static void
1004mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
1005{
1006 MPT_ADAPTER *ioc = hd->ioc;
e8206381
EM
1007 struct scsi_cmnd *sc;
1008 SCSIIORequest_t *mf = NULL;
1da177e4 1009 int ii;
e8206381 1010 int channel, id;
1da177e4 1011
e8206381
EM
1012 for (ii= 0; ii < ioc->req_depth; ii++) {
1013 sc = mptscsih_getclear_scsi_lookup(ioc, ii);
1014 if (!sc)
1015 continue;
1016 mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(ioc, ii);
1017 if (!mf)
1018 continue;
1019 channel = mf->Bus;
1020 id = mf->TargetID;
1021 mptscsih_freeChainBuffers(ioc, ii);
1022 mpt_free_msg_frame(ioc, (MPT_FRAME_HDR *)mf);
1023 if ((unsigned char *)mf != sc->host_scribble)
1024 continue;
1025 scsi_dma_unmap(sc);
1026 sc->result = DID_RESET << 16;
1027 sc->host_scribble = NULL;
2f187862
KD
1028 dtmprintk(ioc, sdev_printk(KERN_INFO, sc->device, MYIOC_s_FMT
1029 "completing cmds: fw_channel %d, fw_id %d, sc=%p, mf = %p, "
1030 "idx=%x\n", ioc->name, channel, id, sc, mf, ii));
e8206381 1031 sc->scsi_done(sc);
1da177e4 1032 }
1da177e4
LT
1033}
1034
1035/*
1036 * mptscsih_search_running_cmds - Delete any commands associated
1037 * with the specified target and lun. Function called only
1038 * when a lun is disable by mid-layer.
1039 * Do NOT access the referenced scsi_cmnd structure or
1040 * members. Will cause either a paging or NULL ptr error.
05e8ec17 1041 * (BUT, BUT, BUT, the code does reference it! - mdr)
c7c82987
MED
1042 * @hd: Pointer to a SCSI HOST structure
1043 * @vdevice: per device private data
1da177e4
LT
1044 *
1045 * Returns: None.
1046 *
1047 * Called from slave_destroy.
1048 */
1049static void
c7c82987 1050mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
1da177e4
LT
1051{
1052 SCSIIORequest_t *mf = NULL;
1053 int ii;
466544d8 1054 struct scsi_cmnd *sc;
793955f5 1055 struct scsi_lun lun;
e80b002b 1056 MPT_ADAPTER *ioc = hd->ioc;
e8206381 1057 unsigned long flags;
1da177e4 1058
e8206381
EM
1059 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
1060 for (ii = 0; ii < ioc->req_depth; ii++) {
1061 if ((sc = ioc->ScsiLookup[ii]) != NULL) {
1da177e4 1062
e80b002b 1063 mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(ioc, ii);
3dc0b03f
EM
1064 if (mf == NULL)
1065 continue;
cc78d30a
EM
1066 /* If the device is a hidden raid component, then its
1067 * expected that the mf->function will be RAID_SCSI_IO
1068 */
1069 if (vdevice->vtarget->tflags &
1070 MPT_TARGET_FLAGS_RAID_COMPONENT && mf->Function !=
1071 MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)
1072 continue;
1073
793955f5
EM
1074 int_to_scsilun(vdevice->lun, &lun);
1075 if ((mf->Bus != vdevice->vtarget->channel) ||
1076 (mf->TargetID != vdevice->vtarget->id) ||
1077 memcmp(lun.scsi_lun, mf->LUN, 8))
1da177e4
LT
1078 continue;
1079
3dc0b03f
EM
1080 if ((unsigned char *)mf != sc->host_scribble)
1081 continue;
e8206381
EM
1082 ioc->ScsiLookup[ii] = NULL;
1083 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
1084 mptscsih_freeChainBuffers(ioc, ii);
1085 mpt_free_msg_frame(ioc, (MPT_FRAME_HDR *)mf);
1928d73f 1086 scsi_dma_unmap(sc);
466544d8
MED
1087 sc->host_scribble = NULL;
1088 sc->result = DID_NO_CONNECT << 16;
2f187862
KD
1089 dtmprintk(ioc, sdev_printk(KERN_INFO, sc->device,
1090 MYIOC_s_FMT "completing cmds: fw_channel %d, "
1091 "fw_id %d, sc=%p, mf = %p, idx=%x\n", ioc->name,
1092 vdevice->vtarget->channel, vdevice->vtarget->id,
1093 sc, mf, ii));
466544d8 1094 sc->scsi_done(sc);
e8206381 1095 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
1da177e4
LT
1096 }
1097 }
e8206381 1098 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
1da177e4
LT
1099 return;
1100}
1101
1102/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1da177e4
LT
1103
1104/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1105/*
1106 * mptscsih_report_queue_full - Report QUEUE_FULL status returned
1107 * from a SCSI target device.
1108 * @sc: Pointer to scsi_cmnd structure
1109 * @pScsiReply: Pointer to SCSIIOReply_t
1110 * @pScsiReq: Pointer to original SCSI request
1111 *
1112 * This routine periodically reports QUEUE_FULL status returned from a
1113 * SCSI target device. It reports this to the console via kernel
1114 * printk() API call, not more than once every 10 seconds.
1115 */
1116static void
1117mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq)
1118{
1119 long time = jiffies;
1da177e4 1120 MPT_SCSI_HOST *hd;
e80b002b 1121 MPT_ADAPTER *ioc;
1da177e4 1122
0d0c7974
MED
1123 if (sc->device == NULL)
1124 return;
1125 if (sc->device->host == NULL)
1126 return;
e7eae9f6 1127 if ((hd = shost_priv(sc->device->host)) == NULL)
0d0c7974 1128 return;
e80b002b 1129 ioc = hd->ioc;
0d0c7974 1130 if (time - hd->last_queue_full > 10 * HZ) {
e80b002b
EM
1131 dprintk(ioc, printk(MYIOC_s_WARN_FMT "Device (%d:%d:%d) reported QUEUE_FULL!\n",
1132 ioc->name, 0, sc->device->id, sc->device->lun));
0d0c7974 1133 hd->last_queue_full = time;
1da177e4 1134 }
1da177e4
LT
1135}
1136
1137/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1138/*
1139 * mptscsih_remove - Removed scsi devices
1140 * @pdev: Pointer to pci_dev structure
1141 *
1142 *
1143 */
0d0c7974 1144void
1da177e4
LT
1145mptscsih_remove(struct pci_dev *pdev)
1146{
1147 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1148 struct Scsi_Host *host = ioc->sh;
1149 MPT_SCSI_HOST *hd;
0d0c7974 1150 int sz1;
1da177e4 1151
466544d8
MED
1152 if(!host) {
1153 mpt_detach(pdev);
1da177e4 1154 return;
466544d8 1155 }
1da177e4
LT
1156
1157 scsi_remove_host(host);
1158
e7eae9f6 1159 if((hd = shost_priv(host)) == NULL)
0d0c7974
MED
1160 return;
1161
d18c3db5 1162 mptscsih_shutdown(pdev);
1da177e4 1163
0d0c7974 1164 sz1=0;
1da177e4 1165
e8206381 1166 if (ioc->ScsiLookup != NULL) {
e80b002b 1167 sz1 = ioc->req_depth * sizeof(void *);
e8206381
EM
1168 kfree(ioc->ScsiLookup);
1169 ioc->ScsiLookup = NULL;
0d0c7974 1170 }
1da177e4 1171
e80b002b 1172 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
0d0c7974 1173 "Free'd ScsiLookup (%d) memory\n",
e80b002b 1174 ioc->name, sz1));
1da177e4 1175
d485eb83 1176 kfree(hd->info_kbuf);
1da177e4 1177
0d0c7974
MED
1178 /* NULL the Scsi_Host pointer
1179 */
e80b002b 1180 ioc->sh = NULL;
1da177e4
LT
1181
1182 scsi_host_put(host);
1da177e4 1183
0d0c7974 1184 mpt_detach(pdev);
c6678e0c 1185
1da177e4
LT
1186}
1187
1188/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1189/*
1190 * mptscsih_shutdown - reboot notifier
1191 *
1192 */
0d0c7974 1193void
d18c3db5 1194mptscsih_shutdown(struct pci_dev *pdev)
1da177e4 1195{
1da177e4
LT
1196}
1197
1198#ifdef CONFIG_PM
1199/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1200/*
0d0c7974 1201 * mptscsih_suspend - Fusion MPT scsi driver suspend routine.
1da177e4
LT
1202 *
1203 *
1204 */
0d0c7974 1205int
8d189f72 1206mptscsih_suspend(struct pci_dev *pdev, pm_message_t state)
1da177e4 1207{
4d4109d0
PS
1208 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1209
1210 scsi_block_requests(ioc->sh);
1211 flush_scheduled_work();
d18c3db5 1212 mptscsih_shutdown(pdev);
0d0c7974 1213 return mpt_suspend(pdev,state);
1da177e4
LT
1214}
1215
1216/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1217/*
1218 * mptscsih_resume - Fusion MPT scsi driver resume routine.
1219 *
1220 *
1221 */
0d0c7974 1222int
1da177e4
LT
1223mptscsih_resume(struct pci_dev *pdev)
1224{
4d4109d0
PS
1225 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1226 int rc;
1227
1228 rc = mpt_resume(pdev);
1229 scsi_unblock_requests(ioc->sh);
1230 return rc;
1da177e4
LT
1231}
1232
1233#endif
1234
1da177e4
LT
1235/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1236/**
1237 * mptscsih_info - Return information about MPT adapter
1238 * @SChost: Pointer to Scsi_Host structure
1239 *
1240 * (linux scsi_host_template.info routine)
1241 *
1242 * Returns pointer to buffer where information was written.
1243 */
0d0c7974 1244const char *
1da177e4
LT
1245mptscsih_info(struct Scsi_Host *SChost)
1246{
1247 MPT_SCSI_HOST *h;
1248 int size = 0;
1249
e7eae9f6 1250 h = shost_priv(SChost);
0d0c7974 1251
1da177e4 1252 if (h) {
0d0c7974
MED
1253 if (h->info_kbuf == NULL)
1254 if ((h->info_kbuf = kmalloc(0x1000 /* 4Kb */, GFP_KERNEL)) == NULL)
1255 return h->info_kbuf;
1256 h->info_kbuf[0] = '\0';
1257
1258 mpt_print_ioc_summary(h->ioc, h->info_kbuf, &size, 0, 0);
1259 h->info_kbuf[size-1] = '\0';
1da177e4
LT
1260 }
1261
0d0c7974 1262 return h->info_kbuf;
1da177e4
LT
1263}
1264
1265struct info_str {
1266 char *buffer;
1267 int length;
1268 int offset;
1269 int pos;
1270};
1271
0d0c7974
MED
1272static void
1273mptscsih_copy_mem_info(struct info_str *info, char *data, int len)
1da177e4
LT
1274{
1275 if (info->pos + len > info->length)
1276 len = info->length - info->pos;
1277
1278 if (info->pos + len < info->offset) {
1279 info->pos += len;
1280 return;
1281 }
1282
1283 if (info->pos < info->offset) {
1284 data += (info->offset - info->pos);
1285 len -= (info->offset - info->pos);
1286 }
1287
1288 if (len > 0) {
1289 memcpy(info->buffer + info->pos, data, len);
1290 info->pos += len;
1291 }
1292}
1293
0d0c7974
MED
1294static int
1295mptscsih_copy_info(struct info_str *info, char *fmt, ...)
1da177e4
LT
1296{
1297 va_list args;
1298 char buf[81];
1299 int len;
1300
1301 va_start(args, fmt);
1302 len = vsprintf(buf, fmt, args);
1303 va_end(args);
1304
0d0c7974 1305 mptscsih_copy_mem_info(info, buf, len);
1da177e4
LT
1306 return len;
1307}
1308
0d0c7974
MED
1309static int
1310mptscsih_host_info(MPT_ADAPTER *ioc, char *pbuf, off_t offset, int len)
1da177e4
LT
1311{
1312 struct info_str info;
1313
1314 info.buffer = pbuf;
1315 info.length = len;
1316 info.offset = offset;
1317 info.pos = 0;
1318
0d0c7974
MED
1319 mptscsih_copy_info(&info, "%s: %s, ", ioc->name, ioc->prod_name);
1320 mptscsih_copy_info(&info, "%s%08xh, ", MPT_FW_REV_MAGIC_ID_STRING, ioc->facts.FWVersion.Word);
1321 mptscsih_copy_info(&info, "Ports=%d, ", ioc->facts.NumberOfPorts);
1322 mptscsih_copy_info(&info, "MaxQ=%d\n", ioc->req_depth);
1da177e4
LT
1323
1324 return ((info.pos > info.offset) ? info.pos - info.offset : 0);
1325}
1326
1327/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1328/**
1329 * mptscsih_proc_info - Return information about MPT adapter
d9489fb6
RD
1330 * @host: scsi host struct
1331 * @buffer: if write, user data; if read, buffer for user
1332 * @start: returns the buffer address
1333 * @offset: if write, 0; if read, the current offset into the buffer from
1334 * the previous read.
1335 * @length: if write, return length;
1336 * @func: write = 1; read = 0
1da177e4
LT
1337 *
1338 * (linux scsi_host_template.info routine)
1da177e4 1339 */
0d0c7974 1340int
1da177e4
LT
1341mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
1342 int length, int func)
1343{
e7eae9f6 1344 MPT_SCSI_HOST *hd = shost_priv(host);
1da177e4
LT
1345 MPT_ADAPTER *ioc = hd->ioc;
1346 int size = 0;
1347
1348 if (func) {
c6678e0c
CH
1349 /*
1350 * write is not supported
1da177e4
LT
1351 */
1352 } else {
1353 if (start)
1354 *start = buffer;
1355
1356 size = mptscsih_host_info(ioc, buffer, offset, length);
1357 }
1358
1359 return size;
1360}
1361
1362/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1363#define ADD_INDEX_LOG(req_ent) do { } while(0)
1364
1365/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1366/**
1367 * mptscsih_qcmd - Primary Fusion MPT SCSI initiator IO start routine.
1368 * @SCpnt: Pointer to scsi_cmnd structure
1369 * @done: Pointer SCSI mid-layer IO completion function
1370 *
1371 * (linux scsi_host_template.queuecommand routine)
1372 * This is the primary SCSI IO start routine. Create a MPI SCSIIORequest
1373 * from a linux scsi_cmnd request and send it to the IOC.
1374 *
1375 * Returns 0. (rtn value discarded by linux scsi mid-layer)
1376 */
0d0c7974 1377int
1da177e4
LT
1378mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
1379{
1380 MPT_SCSI_HOST *hd;
1381 MPT_FRAME_HDR *mf;
1382 SCSIIORequest_t *pScsiReq;
a69de507 1383 VirtDevice *vdevice = SCpnt->device->hostdata;
1da177e4
LT
1384 u32 datalen;
1385 u32 scsictl;
1386 u32 scsidir;
1387 u32 cmd_len;
1388 int my_idx;
1389 int ii;
6757d6b4 1390 MPT_ADAPTER *ioc;
1da177e4 1391
e7eae9f6 1392 hd = shost_priv(SCpnt->device->host);
6757d6b4 1393 ioc = hd->ioc;
1da177e4
LT
1394 SCpnt->scsi_done = done;
1395
6757d6b4
PS
1396 dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "qcmd: SCpnt=%p, done()=%p\n",
1397 ioc->name, SCpnt, done));
1da177e4 1398
e7deff33 1399 if (ioc->taskmgmt_quiesce_io) {
6757d6b4
PS
1400 dtmprintk(ioc, printk(MYIOC_s_WARN_FMT "qcmd: SCpnt=%p timeout + 60HZ\n",
1401 ioc->name, SCpnt));
1da177e4
LT
1402 return SCSI_MLQUEUE_HOST_BUSY;
1403 }
1404
1405 /*
1406 * Put together a MPT SCSI request...
1407 */
e80b002b 1408 if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) {
6757d6b4
PS
1409 dprintk(ioc, printk(MYIOC_s_WARN_FMT "QueueCmd, no msg frames!!\n",
1410 ioc->name));
1da177e4
LT
1411 return SCSI_MLQUEUE_HOST_BUSY;
1412 }
1413
1414 pScsiReq = (SCSIIORequest_t *) mf;
1415
1416 my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
1417
1418 ADD_INDEX_LOG(my_idx);
1419
0d0c7974 1420 /* TUR's being issued with scsictl=0x02000000 (DATA_IN)!
1da177e4
LT
1421 * Seems we may receive a buffer (datalen>0) even when there
1422 * will be no data transfer! GRRRRR...
1423 */
1424 if (SCpnt->sc_data_direction == DMA_FROM_DEVICE) {
1928d73f 1425 datalen = scsi_bufflen(SCpnt);
1da177e4
LT
1426 scsidir = MPI_SCSIIO_CONTROL_READ; /* DATA IN (host<--ioc<--dev) */
1427 } else if (SCpnt->sc_data_direction == DMA_TO_DEVICE) {
1928d73f 1428 datalen = scsi_bufflen(SCpnt);
1da177e4
LT
1429 scsidir = MPI_SCSIIO_CONTROL_WRITE; /* DATA OUT (host-->ioc-->dev) */
1430 } else {
1431 datalen = 0;
1432 scsidir = MPI_SCSIIO_CONTROL_NODATATRANSFER;
1433 }
1434
1435 /* Default to untagged. Once a target structure has been allocated,
1436 * use the Inquiry data to determine if device supports tagged.
1437 */
a69de507
EM
1438 if (vdevice
1439 && (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_Q_YES)
1da177e4
LT
1440 && (SCpnt->device->tagged_supported)) {
1441 scsictl = scsidir | MPI_SCSIIO_CONTROL_SIMPLEQ;
65f89c23
KD
1442 if (SCpnt->request && SCpnt->request->ioprio) {
1443 if (((SCpnt->request->ioprio & 0x7) == 1) ||
1444 !(SCpnt->request->ioprio & 0x7))
1445 scsictl |= MPI_SCSIIO_CONTROL_HEADOFQ;
1446 }
1447 } else
1da177e4 1448 scsictl = scsidir | MPI_SCSIIO_CONTROL_UNTAGGED;
65f89c23 1449
1da177e4
LT
1450
1451 /* Use the above information to set up the message frame
1452 */
a69de507
EM
1453 pScsiReq->TargetID = (u8) vdevice->vtarget->id;
1454 pScsiReq->Bus = vdevice->vtarget->channel;
1da177e4 1455 pScsiReq->ChainOffset = 0;
a69de507 1456 if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT)
c92f222e
JB
1457 pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
1458 else
1459 pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
1da177e4
LT
1460 pScsiReq->CDBLength = SCpnt->cmd_len;
1461 pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
1462 pScsiReq->Reserved = 0;
14d0f0b0 1463 pScsiReq->MsgFlags = mpt_msg_flags(ioc);
793955f5 1464 int_to_scsilun(SCpnt->device->lun, (struct scsi_lun *)pScsiReq->LUN);
1da177e4
LT
1465 pScsiReq->Control = cpu_to_le32(scsictl);
1466
1467 /*
1468 * Write SCSI CDB into the message
1469 */
1470 cmd_len = SCpnt->cmd_len;
1471 for (ii=0; ii < cmd_len; ii++)
1472 pScsiReq->CDB[ii] = SCpnt->cmnd[ii];
1473
1474 for (ii=cmd_len; ii < 16; ii++)
1475 pScsiReq->CDB[ii] = 0;
1476
1477 /* DataLength */
1478 pScsiReq->DataLength = cpu_to_le32(datalen);
1479
1480 /* SenseBuffer low address */
e80b002b 1481 pScsiReq->SenseBufferLowAddr = cpu_to_le32(ioc->sense_buf_low_dma
1da177e4
LT
1482 + (my_idx * MPT_SENSE_BUFFER_ALLOC));
1483
1484 /* Now add the SG list
1485 * Always have a SGE even if null length.
1486 */
1487 if (datalen == 0) {
1488 /* Add a NULL SGE */
14d0f0b0
KD
1489 ioc->add_sge((char *)&pScsiReq->SGL,
1490 MPT_SGE_FLAGS_SSIMPLE_READ | 0,
1da177e4
LT
1491 (dma_addr_t) -1);
1492 } else {
1493 /* Add a 32 or 64 bit SGE */
e80b002b 1494 if (mptscsih_AddSGE(ioc, SCpnt, pScsiReq, my_idx) != SUCCESS)
1da177e4
LT
1495 goto fail;
1496 }
1497
3dc0b03f 1498 SCpnt->host_scribble = (unsigned char *)mf;
e8206381 1499 mptscsih_set_scsi_lookup(ioc, my_idx, SCpnt);
1da177e4 1500
e80b002b 1501 mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
6757d6b4
PS
1502 dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n",
1503 ioc->name, SCpnt, mf, my_idx));
29dd3609 1504 DBG_DUMP_REQUEST_FRAME(ioc, (u32 *)mf);
1da177e4
LT
1505 return 0;
1506
1507 fail:
e80b002b
EM
1508 mptscsih_freeChainBuffers(ioc, my_idx);
1509 mpt_free_msg_frame(ioc, mf);
1da177e4
LT
1510 return SCSI_MLQUEUE_HOST_BUSY;
1511}
1512
1513/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1514/*
1515 * mptscsih_freeChainBuffers - Function to free chain buffers associated
1516 * with a SCSI IO request
1517 * @hd: Pointer to the MPT_SCSI_HOST instance
1518 * @req_idx: Index of the SCSI IO request frame.
1519 *
1520 * Called if SG chain buffer allocation fails and mptscsih callbacks.
1521 * No return.
1522 */
1523static void
1524mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx)
1525{
1526 MPT_FRAME_HDR *chain;
1527 unsigned long flags;
1528 int chain_idx;
1529 int next;
1530
1531 /* Get the first chain index and reset
1532 * tracker state.
1533 */
1534 chain_idx = ioc->ReqToChain[req_idx];
1535 ioc->ReqToChain[req_idx] = MPT_HOST_NO_CHAIN;
1536
1537 while (chain_idx != MPT_HOST_NO_CHAIN) {
1538
1539 /* Save the next chain buffer index */
1540 next = ioc->ChainToChain[chain_idx];
1541
1542 /* Free this chain buffer and reset
1543 * tracker
1544 */
1545 ioc->ChainToChain[chain_idx] = MPT_HOST_NO_CHAIN;
1546
1547 chain = (MPT_FRAME_HDR *) (ioc->ChainBuffer
1548 + (chain_idx * ioc->req_sz));
1549
1550 spin_lock_irqsave(&ioc->FreeQlock, flags);
1551 list_add_tail(&chain->u.frame.linkage.list, &ioc->FreeChainQ);
1552 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
1553
6757d6b4 1554 dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "FreeChainBuffers (index %d)\n",
1da177e4
LT
1555 ioc->name, chain_idx));
1556
1557 /* handle next */
1558 chain_idx = next;
1559 }
1560 return;
1561}
1562
1563/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1564/*
1565 * Reset Handling
1566 */
1567
1568/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
cd2c6191 1569/**
1ba9ab2e
KD
1570 * mptscsih_IssueTaskMgmt - Generic send Task Management function.
1571 * @hd: Pointer to MPT_SCSI_HOST structure
1da177e4 1572 * @type: Task Management type
1544d677 1573 * @channel: channel number for task management
793955f5 1574 * @id: Logical Target ID for reset (if appropriate)
1da177e4
LT
1575 * @lun: Logical Unit for reset (if appropriate)
1576 * @ctx2abort: Context for the task to be aborted (if appropriate)
1544d677
RD
1577 * @timeout: timeout for task management control
1578 *
1ba9ab2e
KD
1579 * Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
1580 * or a non-interrupt thread. In the former, must not call schedule().
1da177e4 1581 *
1ba9ab2e 1582 * Not all fields are meaningfull for all task types.
1da177e4 1583 *
1ba9ab2e 1584 * Returns 0 for SUCCESS, or FAILED.
1da177e4 1585 *
cd2c6191 1586 **/
663e1aa1 1587int
1ba9ab2e
KD
1588mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun,
1589 int ctx2abort, ulong timeout)
1da177e4 1590{
1ba9ab2e
KD
1591 MPT_FRAME_HDR *mf;
1592 SCSITaskMgmt_t *pScsiTm;
1593 int ii;
1594 int retval;
1595 MPT_ADAPTER *ioc = hd->ioc;
1596 unsigned long timeleft;
1597 u8 issue_hard_reset;
1da177e4 1598 u32 ioc_raw_state;
1ba9ab2e 1599 unsigned long time_count;
1da177e4 1600
1ba9ab2e 1601 issue_hard_reset = 0;
e80b002b 1602 ioc_raw_state = mpt_GetIocState(ioc, 0);
1da177e4 1603
1da177e4
LT
1604 if ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) {
1605 printk(MYIOC_s_WARN_FMT
1ba9ab2e 1606 "TaskMgmt type=%x: IOC Not operational (0x%x)!\n",
cd2c6191 1607 ioc->name, type, ioc_raw_state);
1ba9ab2e
KD
1608 printk(MYIOC_s_WARN_FMT "Issuing HardReset from %s!!\n",
1609 ioc->name, __func__);
cd2c6191 1610 if (mpt_HardResetHandler(ioc, CAN_SLEEP) < 0)
1ba9ab2e 1611 printk(MYIOC_s_WARN_FMT "TaskMgmt HardReset "
29dd3609 1612 "FAILED!!\n", ioc->name);
1ba9ab2e 1613 return 0;
1da177e4
LT
1614 }
1615
cd2c6191
EM
1616 if (ioc_raw_state & MPI_DOORBELL_ACTIVE) {
1617 printk(MYIOC_s_WARN_FMT
1ba9ab2e 1618 "TaskMgmt type=%x: ioc_state: "
cd2c6191
EM
1619 "DOORBELL_ACTIVE (0x%x)!\n",
1620 ioc->name, type, ioc_raw_state);
1621 return FAILED;
1da177e4
LT
1622 }
1623
1ba9ab2e
KD
1624 mutex_lock(&ioc->taskmgmt_cmds.mutex);
1625 if (mpt_set_taskmgmt_in_progress_flag(ioc) != 0) {
1626 mf = NULL;
1627 retval = FAILED;
1628 goto out;
1629 }
1da177e4
LT
1630
1631 /* Return Fail to calling function if no message frames available.
1632 */
e80b002b 1633 if ((mf = mpt_get_msg_frame(ioc->TaskCtx, ioc)) == NULL) {
1ba9ab2e
KD
1634 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1635 "TaskMgmt no msg frames!!\n", ioc->name));
1636 retval = FAILED;
1637 mpt_clear_taskmgmt_in_progress_flag(ioc);
1638 goto out;
1da177e4 1639 }
1ba9ab2e 1640 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt request (mf=%p)\n",
e80b002b 1641 ioc->name, mf));
1da177e4
LT
1642
1643 /* Format the Request
1644 */
1645 pScsiTm = (SCSITaskMgmt_t *) mf;
793955f5 1646 pScsiTm->TargetID = id;
1da177e4
LT
1647 pScsiTm->Bus = channel;
1648 pScsiTm->ChainOffset = 0;
1649 pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
1650
1651 pScsiTm->Reserved = 0;
1652 pScsiTm->TaskType = type;
1653 pScsiTm->Reserved1 = 0;
1654 pScsiTm->MsgFlags = (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS)
1655 ? MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION : 0;
1656
793955f5 1657 int_to_scsilun(lun, (struct scsi_lun *)pScsiTm->LUN);
1da177e4
LT
1658
1659 for (ii=0; ii < 7; ii++)
1660 pScsiTm->Reserved2[ii] = 0;
1661
1662 pScsiTm->TaskMsgContext = ctx2abort;
1663
1ba9ab2e
KD
1664 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt: ctx2abort (0x%08x) "
1665 "task_type = 0x%02X, timeout = %ld\n", ioc->name, ctx2abort,
1666 type, timeout));
1da177e4 1667
6757d6b4 1668 DBG_DUMP_TM_REQUEST_FRAME(ioc, (u32 *)pScsiTm);
1da177e4 1669
1ba9ab2e
KD
1670 INITIALIZE_MGMT_STATUS(ioc->taskmgmt_cmds.status)
1671 time_count = jiffies;
e80b002b
EM
1672 if ((ioc->facts.IOCCapabilities & MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q) &&
1673 (ioc->facts.MsgVersion >= MPI_VERSION_01_05))
1674 mpt_put_msg_frame_hi_pri(ioc->TaskCtx, ioc, mf);
7a195f46 1675 else {
e80b002b 1676 retval = mpt_send_handshake_request(ioc->TaskCtx, ioc,
7a195f46
PS
1677 sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP);
1678 if (retval) {
1ba9ab2e
KD
1679 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1680 "TaskMgmt handshake FAILED!(mf=%p, rc=%d) \n",
1681 ioc->name, mf, retval));
1682 mpt_free_msg_frame(ioc, mf);
1683 mpt_clear_taskmgmt_in_progress_flag(ioc);
1684 goto out;
7a195f46 1685 }
1da177e4
LT
1686 }
1687
1ba9ab2e
KD
1688 timeleft = wait_for_completion_timeout(&ioc->taskmgmt_cmds.done,
1689 timeout*HZ);
1690 if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
1691 retval = FAILED;
1692 dtmprintk(ioc, printk(MYIOC_s_ERR_FMT
1693 "TaskMgmt TIMED OUT!(mf=%p)\n", ioc->name, mf));
1694 mpt_clear_taskmgmt_in_progress_flag(ioc);
1695 if (ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET)
1696 goto out;
1697 issue_hard_reset = 1;
1698 goto out;
1da177e4
LT
1699 }
1700
1ba9ab2e
KD
1701 retval = mptscsih_taskmgmt_reply(ioc, type,
1702 (SCSITaskMgmtReply_t *) ioc->taskmgmt_cmds.reply);
cd2c6191 1703
1ba9ab2e
KD
1704 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1705 "TaskMgmt completed (%d seconds)\n",
1706 ioc->name, jiffies_to_msecs(jiffies - time_count)/1000));
cd2c6191 1707
1ba9ab2e 1708 out:
cd2c6191 1709
1ba9ab2e
KD
1710 CLEAR_MGMT_STATUS(ioc->taskmgmt_cmds.status)
1711 if (issue_hard_reset) {
1712 printk(MYIOC_s_WARN_FMT "Issuing Reset from %s!!\n",
1713 ioc->name, __func__);
1714 retval = mpt_HardResetHandler(ioc, CAN_SLEEP);
1715 mpt_free_msg_frame(ioc, mf);
1716 }
1717
1718 retval = (retval == 0) ? 0 : FAILED;
1719 mutex_unlock(&ioc->taskmgmt_cmds.mutex);
1720 return retval;
1da177e4 1721}
1ba9ab2e 1722EXPORT_SYMBOL(mptscsih_IssueTaskMgmt);
1da177e4 1723
d66c7a0f
CH
1724static int
1725mptscsih_get_tm_timeout(MPT_ADAPTER *ioc)
1726{
1727 switch (ioc->bus_type) {
1728 case FC:
1729 return 40;
1730 case SAS:
d66c7a0f
CH
1731 case SPI:
1732 default:
22ab019b 1733 return 10;
d66c7a0f
CH
1734 }
1735}
1736
1da177e4
LT
1737/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1738/**
1739 * mptscsih_abort - Abort linux scsi_cmnd routine, new_eh variant
1740 * @SCpnt: Pointer to scsi_cmnd structure, IO to be aborted
1741 *
1742 * (linux scsi_host_template.eh_abort_handler routine)
1743 *
1744 * Returns SUCCESS or FAILED.
cd2c6191 1745 **/
0d0c7974 1746int
1da177e4
LT
1747mptscsih_abort(struct scsi_cmnd * SCpnt)
1748{
1749 MPT_SCSI_HOST *hd;
1da177e4
LT
1750 MPT_FRAME_HDR *mf;
1751 u32 ctx2abort;
1752 int scpnt_idx;
466544d8 1753 int retval;
958d4a32 1754 VirtDevice *vdevice;
3dc0b03f 1755 ulong sn = SCpnt->serial_number;
958d4a32 1756 MPT_ADAPTER *ioc;
1da177e4
LT
1757
1758 /* If we can't locate our host adapter structure, return FAILED status.
1759 */
e7eae9f6 1760 if ((hd = shost_priv(SCpnt->device->host)) == NULL) {
1da177e4
LT
1761 SCpnt->result = DID_RESET << 16;
1762 SCpnt->scsi_done(SCpnt);
29dd3609
EM
1763 printk(KERN_ERR MYNAM ": task abort: "
1764 "can't locate host! (sc=%p)\n", SCpnt);
1da177e4
LT
1765 return FAILED;
1766 }
1767
958d4a32
EM
1768 ioc = hd->ioc;
1769 printk(MYIOC_s_INFO_FMT "attempting task abort! (sc=%p)\n",
1770 ioc->name, SCpnt);
1771 scsi_print_command(SCpnt);
1772
1773 vdevice = SCpnt->device->hostdata;
1774 if (!vdevice || !vdevice->vtarget) {
29dd3609
EM
1775 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1776 "task abort: device has been deleted (sc=%p)\n",
1777 ioc->name, SCpnt));
958d4a32
EM
1778 SCpnt->result = DID_NO_CONNECT << 16;
1779 SCpnt->scsi_done(SCpnt);
1780 retval = 0;
1781 goto out;
1782 }
1783
cc78d30a
EM
1784 /* Task aborts are not supported for hidden raid components.
1785 */
1786 if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
29dd3609
EM
1787 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1788 "task abort: hidden raid component (sc=%p)\n",
1789 ioc->name, SCpnt));
cc78d30a
EM
1790 SCpnt->result = DID_RESET << 16;
1791 retval = FAILED;
1792 goto out;
1793 }
1794
1da177e4
LT
1795 /* Find this command
1796 */
e8206381 1797 if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(ioc, SCpnt)) < 0) {
466544d8 1798 /* Cmd not found in ScsiLookup.
1da177e4
LT
1799 * Do OS callback.
1800 */
1801 SCpnt->result = DID_RESET << 16;
29dd3609 1802 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "task abort: "
958d4a32
EM
1803 "Command not in the active list! (sc=%p)\n", ioc->name,
1804 SCpnt));
9858ae38 1805 retval = SUCCESS;
958d4a32 1806 goto out;
1da177e4
LT
1807 }
1808
2f187862
KD
1809 if (ioc->timeouts < -1)
1810 ioc->timeouts++;
65207fed 1811
2f4c782c
KD
1812 if (mpt_fwfault_debug)
1813 mpt_halt_firmware(ioc);
1814
1da177e4
LT
1815 /* Most important! Set TaskMsgContext to SCpnt's MsgContext!
1816 * (the IO to be ABORT'd)
1817 *
1818 * NOTE: Since we do not byteswap MsgContext, we do not
1819 * swap it here either. It is an opaque cookie to
1820 * the controller, so it does not matter. -DaveM
1821 */
e80b002b 1822 mf = MPT_INDEX_2_MFPTR(ioc, scpnt_idx);
1da177e4 1823 ctx2abort = mf->u.frame.hwhdr.msgctxu.MsgContext;
1ba9ab2e
KD
1824 retval = mptscsih_IssueTaskMgmt(hd,
1825 MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
1826 vdevice->vtarget->channel,
1827 vdevice->vtarget->id, vdevice->lun,
1828 ctx2abort, mptscsih_get_tm_timeout(ioc));
1da177e4 1829
e8206381 1830 if (SCPNT_TO_LOOKUP_IDX(ioc, SCpnt) == scpnt_idx &&
2f187862
KD
1831 SCpnt->serial_number == sn) {
1832 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1833 "task abort: command still in active list! (sc=%p)\n",
1834 ioc->name, SCpnt));
3dc0b03f 1835 retval = FAILED;
2f187862
KD
1836 } else {
1837 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1838 "task abort: command cleared from active list! (sc=%p)\n",
1839 ioc->name, SCpnt));
1840 retval = SUCCESS;
1841 }
3dc0b03f 1842
958d4a32
EM
1843 out:
1844 printk(MYIOC_s_INFO_FMT "task abort: %s (sc=%p)\n",
2f187862 1845 ioc->name, ((retval == SUCCESS) ? "SUCCESS" : "FAILED"), SCpnt);
1da177e4 1846
2f187862 1847 return retval;
1da177e4
LT
1848}
1849
1850/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1851/**
1852 * mptscsih_dev_reset - Perform a SCSI TARGET_RESET! new_eh variant
1853 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1854 *
1855 * (linux scsi_host_template.eh_dev_reset_handler routine)
1856 *
1857 * Returns SUCCESS or FAILED.
cd2c6191 1858 **/
0d0c7974 1859int
1da177e4
LT
1860mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
1861{
1862 MPT_SCSI_HOST *hd;
466544d8 1863 int retval;
958d4a32
EM
1864 VirtDevice *vdevice;
1865 MPT_ADAPTER *ioc;
1da177e4
LT
1866
1867 /* If we can't locate our host adapter structure, return FAILED status.
1868 */
e7eae9f6 1869 if ((hd = shost_priv(SCpnt->device->host)) == NULL){
29dd3609
EM
1870 printk(KERN_ERR MYNAM ": target reset: "
1871 "Can't locate host! (sc=%p)\n", SCpnt);
1da177e4
LT
1872 return FAILED;
1873 }
1874
958d4a32
EM
1875 ioc = hd->ioc;
1876 printk(MYIOC_s_INFO_FMT "attempting target reset! (sc=%p)\n",
1877 ioc->name, SCpnt);
466544d8 1878 scsi_print_command(SCpnt);
1da177e4 1879
958d4a32
EM
1880 vdevice = SCpnt->device->hostdata;
1881 if (!vdevice || !vdevice->vtarget) {
2f187862 1882 retval = SUCCESS;
958d4a32
EM
1883 goto out;
1884 }
1885
cc78d30a
EM
1886 /* Target reset to hidden raid component is not supported
1887 */
1888 if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
1889 retval = FAILED;
1890 goto out;
1891 }
1892
1ba9ab2e
KD
1893 retval = mptscsih_IssueTaskMgmt(hd,
1894 MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
1895 vdevice->vtarget->channel,
1896 vdevice->vtarget->id, 0, 0,
1897 mptscsih_get_tm_timeout(ioc));
466544d8 1898
958d4a32
EM
1899 out:
1900 printk (MYIOC_s_INFO_FMT "target reset: %s (sc=%p)\n",
1901 ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
466544d8
MED
1902
1903 if (retval == 0)
1904 return SUCCESS;
cd2c6191
EM
1905 else
1906 return FAILED;
1da177e4
LT
1907}
1908
cd2c6191 1909
1da177e4
LT
1910/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1911/**
1912 * mptscsih_bus_reset - Perform a SCSI BUS_RESET! new_eh variant
1913 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1914 *
1915 * (linux scsi_host_template.eh_bus_reset_handler routine)
1916 *
1917 * Returns SUCCESS or FAILED.
cd2c6191 1918 **/
0d0c7974 1919int
1da177e4
LT
1920mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
1921{
1922 MPT_SCSI_HOST *hd;
466544d8 1923 int retval;
a69de507 1924 VirtDevice *vdevice;
958d4a32 1925 MPT_ADAPTER *ioc;
1da177e4
LT
1926
1927 /* If we can't locate our host adapter structure, return FAILED status.
1928 */
e7eae9f6 1929 if ((hd = shost_priv(SCpnt->device->host)) == NULL){
29dd3609
EM
1930 printk(KERN_ERR MYNAM ": bus reset: "
1931 "Can't locate host! (sc=%p)\n", SCpnt);
1da177e4
LT
1932 return FAILED;
1933 }
1934
958d4a32
EM
1935 ioc = hd->ioc;
1936 printk(MYIOC_s_INFO_FMT "attempting bus reset! (sc=%p)\n",
1937 ioc->name, SCpnt);
466544d8 1938 scsi_print_command(SCpnt);
1da177e4 1939
2f187862
KD
1940 if (ioc->timeouts < -1)
1941 ioc->timeouts++;
1da177e4 1942
a69de507 1943 vdevice = SCpnt->device->hostdata;
2f187862
KD
1944 if (!vdevice || !vdevice->vtarget)
1945 return SUCCESS;
1ba9ab2e
KD
1946 retval = mptscsih_IssueTaskMgmt(hd,
1947 MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
1948 vdevice->vtarget->channel, 0, 0, 0,
1949 mptscsih_get_tm_timeout(ioc));
1da177e4 1950
958d4a32
EM
1951 printk(MYIOC_s_INFO_FMT "bus reset: %s (sc=%p)\n",
1952 ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
466544d8
MED
1953
1954 if (retval == 0)
1955 return SUCCESS;
cd2c6191
EM
1956 else
1957 return FAILED;
1da177e4
LT
1958}
1959
1960/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1961/**
d9489fb6 1962 * mptscsih_host_reset - Perform a SCSI host adapter RESET (new_eh variant)
1da177e4
LT
1963 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1964 *
1965 * (linux scsi_host_template.eh_host_reset_handler routine)
1966 *
1967 * Returns SUCCESS or FAILED.
1968 */
0d0c7974 1969int
1da177e4
LT
1970mptscsih_host_reset(struct scsi_cmnd *SCpnt)
1971{
1972 MPT_SCSI_HOST * hd;
2f187862 1973 int status = SUCCESS;
958d4a32 1974 MPT_ADAPTER *ioc;
2f187862 1975 int retval;
1da177e4
LT
1976
1977 /* If we can't locate the host to reset, then we failed. */
e7eae9f6 1978 if ((hd = shost_priv(SCpnt->device->host)) == NULL){
29dd3609
EM
1979 printk(KERN_ERR MYNAM ": host reset: "
1980 "Can't locate host! (sc=%p)\n", SCpnt);
1da177e4
LT
1981 return FAILED;
1982 }
1983
a6da74cb
JB
1984 /* make sure we have no outstanding commands at this stage */
1985 mptscsih_flush_running_cmds(hd);
1986
958d4a32
EM
1987 ioc = hd->ioc;
1988 printk(MYIOC_s_INFO_FMT "attempting host reset! (sc=%p)\n",
1989 ioc->name, SCpnt);
1da177e4
LT
1990
1991 /* If our attempts to reset the host failed, then return a failed
1992 * status. The host will be taken off line by the SCSI mid-layer.
1993 */
2f187862
KD
1994 retval = mpt_HardResetHandler(ioc, CAN_SLEEP);
1995 if (retval < 0)
1996 status = FAILED;
1997 else
1998 status = SUCCESS;
1da177e4 1999
958d4a32
EM
2000 printk(MYIOC_s_INFO_FMT "host reset: %s (sc=%p)\n",
2001 ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
1da177e4 2002
2f187862 2003 return status;
1da177e4
LT
2004}
2005
1da177e4 2006static int
1ba9ab2e
KD
2007mptscsih_taskmgmt_reply(MPT_ADAPTER *ioc, u8 type,
2008 SCSITaskMgmtReply_t *pScsiTmReply)
1da177e4 2009{
1ba9ab2e
KD
2010 u16 iocstatus;
2011 u32 termination_count;
2012 int retval;
1da177e4 2013
1ba9ab2e
KD
2014 if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_RF_VALID)) {
2015 retval = FAILED;
2016 goto out;
2017 }
1da177e4 2018
1ba9ab2e 2019 DBG_DUMP_TM_REPLY_FRAME(ioc, (u32 *)pScsiTmReply);
1da177e4 2020
1ba9ab2e
KD
2021 iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
2022 termination_count = le32_to_cpu(pScsiTmReply->TerminationCount);
1da177e4 2023
1ba9ab2e
KD
2024 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2025 "TaskMgmt fw_channel = %d, fw_id = %d, task_type = 0x%02X,\n"
2026 "\tiocstatus = 0x%04X, loginfo = 0x%08X, response_code = 0x%02X,\n"
2027 "\tterm_cmnds = %d\n", ioc->name, pScsiTmReply->Bus,
2028 pScsiTmReply->TargetID, type, le16_to_cpu(pScsiTmReply->IOCStatus),
2029 le32_to_cpu(pScsiTmReply->IOCLogInfo), pScsiTmReply->ResponseCode,
2030 termination_count));
2031
2032 if (ioc->facts.MsgVersion >= MPI_VERSION_01_05 &&
2033 pScsiTmReply->ResponseCode)
2034 mptscsih_taskmgmt_response_code(ioc,
2035 pScsiTmReply->ResponseCode);
1da177e4 2036
1ba9ab2e
KD
2037 if (iocstatus == MPI_IOCSTATUS_SUCCESS) {
2038 retval = 0;
2039 goto out;
2040 }
2041
2042 retval = FAILED;
2043 if (type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) {
2044 if (termination_count == 1)
2045 retval = 0;
2046 goto out;
2047 }
2048
2049 if (iocstatus == MPI_IOCSTATUS_SCSI_TASK_TERMINATED ||
2050 iocstatus == MPI_IOCSTATUS_SCSI_IOC_TERMINATED)
2051 retval = 0;
2052
2053 out:
2054 return retval;
1da177e4
LT
2055}
2056
9f63bb73 2057/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
e7deff33 2058void
9f63bb73
ME
2059mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code)
2060{
2061 char *desc;
2062
2063 switch (response_code) {
2064 case MPI_SCSITASKMGMT_RSP_TM_COMPLETE:
2065 desc = "The task completed.";
2066 break;
2067 case MPI_SCSITASKMGMT_RSP_INVALID_FRAME:
2068 desc = "The IOC received an invalid frame status.";
2069 break;
2070 case MPI_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED:
2071 desc = "The task type is not supported.";
2072 break;
2073 case MPI_SCSITASKMGMT_RSP_TM_FAILED:
2074 desc = "The requested task failed.";
2075 break;
2076 case MPI_SCSITASKMGMT_RSP_TM_SUCCEEDED:
2077 desc = "The task completed successfully.";
2078 break;
2079 case MPI_SCSITASKMGMT_RSP_TM_INVALID_LUN:
2080 desc = "The LUN request is invalid.";
2081 break;
2082 case MPI_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC:
2083 desc = "The task is in the IOC queue and has not been sent to target.";
2084 break;
2085 default:
2086 desc = "unknown";
2087 break;
2088 }
2089 printk(MYIOC_s_INFO_FMT "Response Code(0x%08x): F/W: %s\n",
2090 ioc->name, response_code, desc);
2091}
e7deff33 2092EXPORT_SYMBOL(mptscsih_taskmgmt_response_code);
9f63bb73 2093
1da177e4
LT
2094/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2095/**
2096 * mptscsih_taskmgmt_complete - Registered with Fusion MPT base driver
2097 * @ioc: Pointer to MPT_ADAPTER structure
2098 * @mf: Pointer to SCSI task mgmt request frame
2099 * @mr: Pointer to SCSI task mgmt reply frame
2100 *
2101 * This routine is called from mptbase.c::mpt_interrupt() at the completion
2102 * of any SCSI task management request.
2103 * This routine is registered with the MPT (base) driver at driver
2104 * load/init time via the mpt_register() API call.
2105 *
2106 * Returns 1 indicating alloc'd request frame ptr should be freed.
cd2c6191 2107 **/
0d0c7974 2108int
1ba9ab2e
KD
2109mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf,
2110 MPT_FRAME_HDR *mr)
1da177e4 2111{
1ba9ab2e
KD
2112 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2113 "TaskMgmt completed (mf=%p, mr=%p)\n", ioc->name, mf, mr));
cd2c6191 2114
1ba9ab2e 2115 ioc->taskmgmt_cmds.status |= MPT_MGMT_STATUS_COMMAND_GOOD;
6757d6b4 2116
1ba9ab2e 2117 if (!mr)
cd2c6191 2118 goto out;
1da177e4 2119
1ba9ab2e
KD
2120 ioc->taskmgmt_cmds.status |= MPT_MGMT_STATUS_RF_VALID;
2121 memcpy(ioc->taskmgmt_cmds.reply, mr,
2122 min(MPT_DEFAULT_FRAME_SIZE, 4 * mr->u.reply.MsgLength));
cd2c6191 2123 out:
1ba9ab2e
KD
2124 if (ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_PENDING) {
2125 mpt_clear_taskmgmt_in_progress_flag(ioc);
2126 ioc->taskmgmt_cmds.status &= ~MPT_MGMT_STATUS_PENDING;
2127 complete(&ioc->taskmgmt_cmds.done);
2128 return 1;
2129 }
2130 return 0;
1da177e4
LT
2131}
2132
2133/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2134/*
2135 * This is anyones guess quite frankly.
2136 */
0d0c7974 2137int
1da177e4
LT
2138mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev,
2139 sector_t capacity, int geom[])
2140{
2141 int heads;
2142 int sectors;
2143 sector_t cylinders;
2144 ulong dummy;
2145
2146 heads = 64;
2147 sectors = 32;
2148
2149 dummy = heads * sectors;
2150 cylinders = capacity;
2151 sector_div(cylinders,dummy);
2152
2153 /*
2154 * Handle extended translation size for logical drives
2155 * > 1Gb
2156 */
2157 if ((ulong)capacity >= 0x200000) {
2158 heads = 255;
2159 sectors = 63;
2160 dummy = heads * sectors;
2161 cylinders = capacity;
2162 sector_div(cylinders,dummy);
2163 }
2164
2165 /* return result */
2166 geom[0] = heads;
2167 geom[1] = sectors;
2168 geom[2] = cylinders;
2169
1da177e4
LT
2170 return 0;
2171}
2172
f44e5461
ME
2173/* Search IOC page 3 to determine if this is hidden physical disk
2174 *
2175 */
2176int
793955f5 2177mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id)
f44e5461 2178{
b506ade9 2179 struct inactive_raid_component_info *component_info;
a7938b0b
KD
2180 int i, j;
2181 RaidPhysDiskPage1_t *phys_disk;
793955f5 2182 int rc = 0;
a7938b0b 2183 int num_paths;
f44e5461 2184
793955f5
EM
2185 if (!ioc->raid_data.pIocPg3)
2186 goto out;
f44e5461 2187 for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
793955f5
EM
2188 if ((id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) &&
2189 (channel == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskBus)) {
2190 rc = 1;
2191 goto out;
2192 }
c92f222e
JB
2193 }
2194
a7938b0b
KD
2195 if (ioc->bus_type != SAS)
2196 goto out;
2197
2198 /*
2199 * Check if dual path
2200 */
2201 for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
2202 num_paths = mpt_raid_phys_disk_get_num_paths(ioc,
2203 ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum);
2204 if (num_paths < 2)
2205 continue;
2206 phys_disk = kzalloc(offsetof(RaidPhysDiskPage1_t, Path) +
2207 (num_paths * sizeof(RAID_PHYS_DISK1_PATH)), GFP_KERNEL);
2208 if (!phys_disk)
2209 continue;
2210 if ((mpt_raid_phys_disk_pg1(ioc,
2211 ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum,
2212 phys_disk))) {
2213 kfree(phys_disk);
2214 continue;
2215 }
2216 for (j = 0; j < num_paths; j++) {
2217 if ((phys_disk->Path[j].Flags &
2218 MPI_RAID_PHYSDISK1_FLAG_INVALID))
2219 continue;
2220 if ((phys_disk->Path[j].Flags &
2221 MPI_RAID_PHYSDISK1_FLAG_BROKEN))
2222 continue;
2223 if ((id == phys_disk->Path[j].PhysDiskID) &&
2224 (channel == phys_disk->Path[j].PhysDiskBus)) {
2225 rc = 1;
2226 kfree(phys_disk);
2227 goto out;
2228 }
2229 }
2230 kfree(phys_disk);
2231 }
2232
2233
b506ade9
EM
2234 /*
2235 * Check inactive list for matching phys disks
2236 */
2237 if (list_empty(&ioc->raid_data.inactive_list))
2238 goto out;
2239
ed5f606f 2240 mutex_lock(&ioc->raid_data.inactive_list_mutex);
b506ade9
EM
2241 list_for_each_entry(component_info, &ioc->raid_data.inactive_list,
2242 list) {
2243 if ((component_info->d.PhysDiskID == id) &&
2244 (component_info->d.PhysDiskBus == channel))
2245 rc = 1;
2246 }
ed5f606f 2247 mutex_unlock(&ioc->raid_data.inactive_list_mutex);
b506ade9 2248
793955f5
EM
2249 out:
2250 return rc;
c7c82987 2251}
793955f5 2252EXPORT_SYMBOL(mptscsih_is_phys_disk);
c7c82987 2253
793955f5
EM
2254u8
2255mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id)
1da177e4 2256{
b506ade9 2257 struct inactive_raid_component_info *component_info;
a7938b0b
KD
2258 int i, j;
2259 RaidPhysDiskPage1_t *phys_disk;
793955f5 2260 int rc = -ENXIO;
a7938b0b 2261 int num_paths;
c92f222e 2262
793955f5
EM
2263 if (!ioc->raid_data.pIocPg3)
2264 goto out;
2265 for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
2266 if ((id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) &&
2267 (channel == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskBus)) {
2268 rc = ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum;
2269 goto out;
1da177e4 2270 }
1da177e4 2271 }
1da177e4 2272
a7938b0b
KD
2273 if (ioc->bus_type != SAS)
2274 goto out;
2275
2276 /*
2277 * Check if dual path
2278 */
2279 for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
2280 num_paths = mpt_raid_phys_disk_get_num_paths(ioc,
2281 ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum);
2282 if (num_paths < 2)
2283 continue;
2284 phys_disk = kzalloc(offsetof(RaidPhysDiskPage1_t, Path) +
2285 (num_paths * sizeof(RAID_PHYS_DISK1_PATH)), GFP_KERNEL);
2286 if (!phys_disk)
2287 continue;
2288 if ((mpt_raid_phys_disk_pg1(ioc,
2289 ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum,
2290 phys_disk))) {
2291 kfree(phys_disk);
2292 continue;
2293 }
2294 for (j = 0; j < num_paths; j++) {
2295 if ((phys_disk->Path[j].Flags &
2296 MPI_RAID_PHYSDISK1_FLAG_INVALID))
2297 continue;
2298 if ((phys_disk->Path[j].Flags &
2299 MPI_RAID_PHYSDISK1_FLAG_BROKEN))
2300 continue;
2301 if ((id == phys_disk->Path[j].PhysDiskID) &&
2302 (channel == phys_disk->Path[j].PhysDiskBus)) {
2303 rc = phys_disk->PhysDiskNum;
2304 kfree(phys_disk);
2305 goto out;
2306 }
2307 }
2308 kfree(phys_disk);
2309 }
2310
b506ade9
EM
2311 /*
2312 * Check inactive list for matching phys disks
2313 */
2314 if (list_empty(&ioc->raid_data.inactive_list))
2315 goto out;
2316
ed5f606f 2317 mutex_lock(&ioc->raid_data.inactive_list_mutex);
b506ade9
EM
2318 list_for_each_entry(component_info, &ioc->raid_data.inactive_list,
2319 list) {
2320 if ((component_info->d.PhysDiskID == id) &&
2321 (component_info->d.PhysDiskBus == channel))
2322 rc = component_info->d.PhysDiskNum;
2323 }
ed5f606f 2324 mutex_unlock(&ioc->raid_data.inactive_list_mutex);
b506ade9 2325
793955f5
EM
2326 out:
2327 return rc;
c7c82987 2328}
793955f5 2329EXPORT_SYMBOL(mptscsih_raid_id_to_num);
1da177e4 2330
c7c82987
MED
2331/*
2332 * OS entry point to allow for host driver to free allocated memory
2333 * Called if no device present or device being unloaded
2334 */
2335void
2336mptscsih_slave_destroy(struct scsi_device *sdev)
2337{
2338 struct Scsi_Host *host = sdev->host;
e7eae9f6 2339 MPT_SCSI_HOST *hd = shost_priv(host);
c7c82987
MED
2340 VirtTarget *vtarget;
2341 VirtDevice *vdevice;
2342 struct scsi_target *starget;
2343
2344 starget = scsi_target(sdev);
2345 vtarget = starget->hostdata;
2346 vdevice = sdev->hostdata;
2347
2348 mptscsih_search_running_cmds(hd, vdevice);
c7c82987 2349 vtarget->num_luns--;
c7c82987
MED
2350 mptscsih_synchronize_cache(hd, vdevice);
2351 kfree(vdevice);
2352 sdev->hostdata = NULL;
1da177e4
LT
2353}
2354
6e3815ba
MED
2355/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2356/*
2357 * mptscsih_change_queue_depth - This function will set a devices queue depth
2358 * @sdev: per scsi_device pointer
2359 * @qdepth: requested queue depth
e881a172 2360 * @reason: calling context
6e3815ba
MED
2361 *
2362 * Adding support for new 'change_queue_depth' api.
2363*/
2364int
e881a172 2365mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason)
1da177e4 2366{
e7eae9f6 2367 MPT_SCSI_HOST *hd = shost_priv(sdev->host);
c7c82987
MED
2368 VirtTarget *vtarget;
2369 struct scsi_target *starget;
2370 int max_depth;
2371 int tagged;
e80b002b 2372 MPT_ADAPTER *ioc = hd->ioc;
1da177e4 2373
c7c82987
MED
2374 starget = scsi_target(sdev);
2375 vtarget = starget->hostdata;
6e3815ba 2376
e881a172
MC
2377 if (reason != SCSI_QDEPTH_DEFAULT)
2378 return -EOPNOTSUPP;
2379
e80b002b 2380 if (ioc->bus_type == SPI) {
c92f222e 2381 if (!(vtarget->tflags & MPT_TARGET_FLAGS_Q_YES))
1da177e4 2382 max_depth = 1;
c92f222e
JB
2383 else if (sdev->type == TYPE_DISK &&
2384 vtarget->minSyncFactor <= MPT_ULTRA160)
2385 max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
2386 else
2387 max_depth = MPT_SCSI_CMD_PER_DEV_LOW;
1da177e4 2388 } else
79a3ec1a
KD
2389 max_depth = ioc->sh->can_queue;
2390
2391 if (!sdev->tagged_supported)
2392 max_depth = 1;
1da177e4
LT
2393
2394 if (qdepth > max_depth)
2395 qdepth = max_depth;
2396 if (qdepth == 1)
2397 tagged = 0;
2398 else
2399 tagged = MSG_SIMPLE_TAG;
2400
6e3815ba
MED
2401 scsi_adjust_queue_depth(sdev, tagged, qdepth);
2402 return sdev->queue_depth;
1da177e4
LT
2403}
2404
1da177e4
LT
2405/*
2406 * OS entry point to adjust the queue_depths on a per-device basis.
2407 * Called once per device the bus scan. Use it to force the queue_depth
2408 * member to 1 if a device does not support Q tags.
2409 * Return non-zero if fails.
2410 */
0d0c7974 2411int
c7c82987 2412mptscsih_slave_configure(struct scsi_device *sdev)
1da177e4 2413{
c7c82987
MED
2414 struct Scsi_Host *sh = sdev->host;
2415 VirtTarget *vtarget;
2416 VirtDevice *vdevice;
2417 struct scsi_target *starget;
e7eae9f6 2418 MPT_SCSI_HOST *hd = shost_priv(sh);
e80b002b 2419 MPT_ADAPTER *ioc = hd->ioc;
1da177e4 2420
c7c82987
MED
2421 starget = scsi_target(sdev);
2422 vtarget = starget->hostdata;
2423 vdevice = sdev->hostdata;
1da177e4 2424
e80b002b 2425 dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
793955f5 2426 "device @ %p, channel=%d, id=%d, lun=%d\n",
e80b002b
EM
2427 ioc->name, sdev, sdev->channel, sdev->id, sdev->lun));
2428 if (ioc->bus_type == SPI)
2429 dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
c7c82987 2430 "sdtr %d wdtr %d ppr %d inq length=%d\n",
e80b002b 2431 ioc->name, sdev->sdtr, sdev->wdtr,
c7c82987
MED
2432 sdev->ppr, sdev->inquiry_len));
2433
793955f5 2434 vdevice->configured_lun = 1;
1da177e4 2435
e80b002b 2436 dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1da177e4 2437 "Queue depth=%d, tflags=%x\n",
e80b002b 2438 ioc->name, sdev->queue_depth, vtarget->tflags));
1da177e4 2439
e80b002b
EM
2440 if (ioc->bus_type == SPI)
2441 dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
c7c82987 2442 "negoFlags=%x, maxOffset=%x, SyncFactor=%x\n",
e80b002b 2443 ioc->name, vtarget->negoFlags, vtarget->maxOffset,
c7c82987 2444 vtarget->minSyncFactor));
1da177e4 2445
e881a172
MC
2446 mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH,
2447 SCSI_QDEPTH_DEFAULT);
e80b002b 2448 dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1da177e4 2449 "tagged %d, simple %d, ordered %d\n",
e80b002b 2450 ioc->name,sdev->tagged_supported, sdev->simple_tags,
c7c82987 2451 sdev->ordered_tags));
1da177e4
LT
2452
2453 return 0;
2454}
2455
1da177e4
LT
2456/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2457/*
2458 * Private routines...
2459 */
2460
2461/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2462/* Utility function to copy sense data from the scsi_cmnd buffer
2463 * to the FC and SCSI target structures.
2464 *
2465 */
2466static void
0d0c7974 2467mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply)
1da177e4 2468{
a69de507 2469 VirtDevice *vdevice;
1da177e4
LT
2470 SCSIIORequest_t *pReq;
2471 u32 sense_count = le32_to_cpu(pScsiReply->SenseCount);
e80b002b 2472 MPT_ADAPTER *ioc = hd->ioc;
1da177e4
LT
2473
2474 /* Get target structure
2475 */
2476 pReq = (SCSIIORequest_t *) mf;
a69de507 2477 vdevice = sc->device->hostdata;
1da177e4
LT
2478
2479 if (sense_count) {
2480 u8 *sense_data;
2481 int req_index;
2482
2483 /* Copy the sense received into the scsi command block. */
2484 req_index = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
e80b002b 2485 sense_data = ((u8 *)ioc->sense_buf_pool + (req_index * MPT_SENSE_BUFFER_ALLOC));
1da177e4
LT
2486 memcpy(sc->sense_buffer, sense_data, SNS_LEN(sc));
2487
2488 /* Log SMART data (asc = 0x5D, non-IM case only) if required.
2489 */
e80b002b 2490 if ((ioc->events) && (ioc->eventTypes & (1 << MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE))) {
a69de507 2491 if ((sense_data[12] == 0x5D) && (vdevice->vtarget->raidVolume == 0)) {
1da177e4 2492 int idx;
1da177e4 2493
5b5ef4f6 2494 idx = ioc->eventContext % MPTCTL_EVENT_LOG_SIZE;
1da177e4
LT
2495 ioc->events[idx].event = MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE;
2496 ioc->events[idx].eventContext = ioc->eventContext;
2497
3d9780b9
DJ
2498 ioc->events[idx].data[0] = (pReq->LUN[1] << 24) |
2499 (MPI_EVENT_SCSI_DEV_STAT_RC_SMART_DATA << 16) |
2500 (sc->device->channel << 8) | sc->device->id;
1da177e4 2501
3d9780b9 2502 ioc->events[idx].data[1] = (sense_data[13] << 8) | sense_data[12];
1da177e4
LT
2503
2504 ioc->eventContext++;
e80b002b 2505 if (ioc->pcidev->vendor ==
786899b0 2506 PCI_VENDOR_ID_IBM) {
e80b002b 2507 mptscsih_issue_sep_command(ioc,
a69de507
EM
2508 vdevice->vtarget, MPI_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT);
2509 vdevice->vtarget->tflags |=
786899b0
EM
2510 MPT_TARGET_FLAGS_LED_ON;
2511 }
1da177e4
LT
2512 }
2513 }
2514 } else {
e80b002b
EM
2515 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Hmmm... SenseData len=0! (?)\n",
2516 ioc->name));
1da177e4
LT
2517 }
2518}
2519
db7051b2
KD
2520/**
2521 * mptscsih_get_scsi_lookup - retrieves scmd entry
2522 * @ioc: Pointer to MPT_ADAPTER structure
2523 * @i: index into the array
2524 *
2525 * Returns the scsi_cmd pointer
2526 */
2527struct scsi_cmnd *
2528mptscsih_get_scsi_lookup(MPT_ADAPTER *ioc, int i)
2529{
2530 unsigned long flags;
2531 struct scsi_cmnd *scmd;
2532
2533 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
2534 scmd = ioc->ScsiLookup[i];
2535 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
2536
2537 return scmd;
2538}
2539EXPORT_SYMBOL(mptscsih_get_scsi_lookup);
e8206381
EM
2540
2541/**
fc847ab4 2542 * mptscsih_getclear_scsi_lookup - retrieves and clears scmd entry from ScsiLookup[] array list
2f187862
KD
2543 * @ioc: Pointer to MPT_ADAPTER structure
2544 * @i: index into the array
2545 *
7105a387 2546 * Returns the scsi_cmd pointer
2f187862 2547 *
e8206381
EM
2548 **/
2549static struct scsi_cmnd *
2550mptscsih_getclear_scsi_lookup(MPT_ADAPTER *ioc, int i)
2551{
2552 unsigned long flags;
2553 struct scsi_cmnd *scmd;
2554
2555 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
2556 scmd = ioc->ScsiLookup[i];
2557 ioc->ScsiLookup[i] = NULL;
2558 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
2559
2560 return scmd;
2561}
2562
2563/**
2564 * mptscsih_set_scsi_lookup
2565 *
2566 * writes a scmd entry into the ScsiLookup[] array list
2567 *
2568 * @ioc: Pointer to MPT_ADAPTER structure
2569 * @i: index into the array
2570 * @scmd: scsi_cmnd pointer
2571 *
2572 **/
2573static void
2574mptscsih_set_scsi_lookup(MPT_ADAPTER *ioc, int i, struct scsi_cmnd *scmd)
2575{
2576 unsigned long flags;
1da177e4 2577
e8206381
EM
2578 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
2579 ioc->ScsiLookup[i] = scmd;
2580 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
2581}
2582
2583/**
23f9b75e 2584 * SCPNT_TO_LOOKUP_IDX - searches for a given scmd in the ScsiLookup[] array list
e8206381 2585 * @ioc: Pointer to MPT_ADAPTER structure
23f9b75e
RD
2586 * @sc: scsi_cmnd pointer
2587 */
e8206381
EM
2588static int
2589SCPNT_TO_LOOKUP_IDX(MPT_ADAPTER *ioc, struct scsi_cmnd *sc)
2590{
2591 unsigned long flags;
2592 int i, index=-1;
1da177e4 2593
e8206381
EM
2594 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
2595 for (i = 0; i < ioc->req_depth; i++) {
2596 if (ioc->ScsiLookup[i] == sc) {
2597 index = i;
2598 goto out;
1da177e4
LT
2599 }
2600 }
2601
e8206381
EM
2602 out:
2603 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
2604 return index;
1da177e4
LT
2605}
2606
2607/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
0d0c7974 2608int
1da177e4
LT
2609mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
2610{
2611 MPT_SCSI_HOST *hd;
1da177e4 2612
e7eae9f6 2613 if (ioc->sh == NULL || shost_priv(ioc->sh) == NULL)
1da177e4 2614 return 0;
1da177e4 2615
37c60f37
KD
2616 hd = shost_priv(ioc->sh);
2617 switch (reset_phase) {
2618 case MPT_IOC_SETUP_RESET:
2619 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2620 "%s: MPT_IOC_SETUP_RESET\n", ioc->name, __func__));
37c60f37
KD
2621 break;
2622 case MPT_IOC_PRE_RESET:
2623 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2624 "%s: MPT_IOC_PRE_RESET\n", ioc->name, __func__));
37c60f37
KD
2625 mptscsih_flush_running_cmds(hd);
2626 break;
2627 case MPT_IOC_POST_RESET:
2628 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2629 "%s: MPT_IOC_POST_RESET\n", ioc->name, __func__));
2630 if (ioc->internal_cmds.status & MPT_MGMT_STATUS_PENDING) {
2631 ioc->internal_cmds.status |=
2632 MPT_MGMT_STATUS_DID_IOCRESET;
2633 complete(&ioc->internal_cmds.done);
1da177e4 2634 }
37c60f37
KD
2635 break;
2636 default:
2637 break;
1da177e4 2638 }
1da177e4
LT
2639 return 1; /* currently means nothing really */
2640}
2641
2642/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
0d0c7974 2643int
1da177e4
LT
2644mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
2645{
1da177e4
LT
2646 u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
2647
37c60f37
KD
2648 devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2649 "MPT event (=%02Xh) routed to SCSI host driver!\n",
2650 ioc->name, event));
1da177e4 2651
2f187862
KD
2652 if ((event == MPI_EVENT_IOC_BUS_RESET ||
2653 event == MPI_EVENT_EXT_BUS_RESET) &&
2654 (ioc->bus_type == SPI) && (ioc->soft_resets < -1))
2655 ioc->soft_resets++;
1da177e4
LT
2656
2657 return 1; /* currently means nothing really */
2658}
2659
1da177e4
LT
2660/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2661/*
2662 * Bus Scan and Domain Validation functionality ...
2663 */
2664
2665/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2666/*
2667 * mptscsih_scandv_complete - Scan and DV callback routine registered
2668 * to Fustion MPT (base) driver.
2669 *
2670 * @ioc: Pointer to MPT_ADAPTER structure
2671 * @mf: Pointer to original MPT request frame
2672 * @mr: Pointer to MPT reply frame (NULL if TurboReply)
2673 *
2674 * This routine is called from mpt.c::mpt_interrupt() at the completion
2675 * of any SCSI IO request.
2676 * This routine is registered with the Fusion MPT (base) driver at driver
2677 * load/init time via the mpt_register() API call.
2678 *
2679 * Returns 1 indicating alloc'd request frame ptr should be freed.
2680 *
2681 * Remark: Sets a completion code and (possibly) saves sense data
2682 * in the IOC member localReply structure.
2683 * Used ONLY for DV and other internal commands.
2684 */
0d0c7974 2685int
37c60f37
KD
2686mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req,
2687 MPT_FRAME_HDR *reply)
1da177e4 2688{
1da177e4 2689 SCSIIORequest_t *pReq;
37c60f37
KD
2690 SCSIIOReply_t *pReply;
2691 u8 cmd;
1da177e4 2692 u16 req_idx;
37c60f37
KD
2693 u8 *sense_data;
2694 int sz;
1da177e4 2695
37c60f37
KD
2696 ioc->internal_cmds.status |= MPT_MGMT_STATUS_COMMAND_GOOD;
2697 ioc->internal_cmds.completion_code = MPT_SCANDV_GOOD;
2698 if (!reply)
2699 goto out;
1da177e4 2700
37c60f37
KD
2701 pReply = (SCSIIOReply_t *) reply;
2702 pReq = (SCSIIORequest_t *) req;
2703 ioc->internal_cmds.completion_code =
2704 mptscsih_get_completion_code(ioc, req, reply);
2705 ioc->internal_cmds.status |= MPT_MGMT_STATUS_RF_VALID;
2706 memcpy(ioc->internal_cmds.reply, reply,
2707 min(MPT_DEFAULT_FRAME_SIZE, 4 * reply->u.reply.MsgLength));
2708 cmd = reply->u.hdr.Function;
2709 if (((cmd == MPI_FUNCTION_SCSI_IO_REQUEST) ||
2710 (cmd == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) &&
2711 (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID)) {
2712 req_idx = le16_to_cpu(req->u.frame.hwhdr.msgctxu.fld.req_idx);
2713 sense_data = ((u8 *)ioc->sense_buf_pool +
2714 (req_idx * MPT_SENSE_BUFFER_ALLOC));
2715 sz = min_t(int, pReq->SenseBufferLength,
2716 MPT_SENSE_BUFFER_ALLOC);
2717 memcpy(ioc->internal_cmds.sense, sense_data, sz);
1da177e4 2718 }
37c60f37
KD
2719 out:
2720 if (!(ioc->internal_cmds.status & MPT_MGMT_STATUS_PENDING))
2721 return 0;
2722 ioc->internal_cmds.status &= ~MPT_MGMT_STATUS_PENDING;
2723 complete(&ioc->internal_cmds.done);
1da177e4
LT
2724 return 1;
2725}
2726
1da177e4 2727
37c60f37
KD
2728/**
2729 * mptscsih_get_completion_code -
2730 * @ioc: Pointer to MPT_ADAPTER structure
9cf46a35
RD
2731 * @req: Pointer to original MPT request frame
2732 * @reply: Pointer to MPT reply frame (NULL if TurboReply)
37c60f37
KD
2733 *
2734 **/
2735static int
2736mptscsih_get_completion_code(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req,
2737 MPT_FRAME_HDR *reply)
2738{
2739 SCSIIOReply_t *pReply;
2740 MpiRaidActionReply_t *pr;
2741 u8 scsi_status;
2742 u16 status;
2743 int completion_code;
2744
2745 pReply = (SCSIIOReply_t *)reply;
2746 status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
2747 scsi_status = pReply->SCSIStatus;
2748
2749 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2750 "IOCStatus=%04xh, SCSIState=%02xh, SCSIStatus=%02xh,"
2751 "IOCLogInfo=%08xh\n", ioc->name, status, pReply->SCSIState,
2752 scsi_status, le32_to_cpu(pReply->IOCLogInfo)));
2753
2754 switch (status) {
2755
2756 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
2757 completion_code = MPT_SCANDV_SELECTION_TIMEOUT;
2758 break;
2759
2760 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
2761 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
2762 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
2763 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
2764 completion_code = MPT_SCANDV_DID_RESET;
2765 break;
2766
2767 case MPI_IOCSTATUS_BUSY:
2768 case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES:
2769 completion_code = MPT_SCANDV_BUSY;
2770 break;
2771
2772 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
2773 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
2774 case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */
2775 if (pReply->Function == MPI_FUNCTION_CONFIG) {
2776 completion_code = MPT_SCANDV_GOOD;
2777 } else if (pReply->Function == MPI_FUNCTION_RAID_ACTION) {
2778 pr = (MpiRaidActionReply_t *)reply;
2779 if (le16_to_cpu(pr->ActionStatus) ==
2780 MPI_RAID_ACTION_ASTATUS_SUCCESS)
2781 completion_code = MPT_SCANDV_GOOD;
2782 else
2783 completion_code = MPT_SCANDV_SOME_ERROR;
2784 } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID)
2785 completion_code = MPT_SCANDV_SENSE;
2786 else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_FAILED) {
2787 if (req->u.scsireq.CDB[0] == INQUIRY)
2788 completion_code = MPT_SCANDV_ISSUE_SENSE;
2789 else
2790 completion_code = MPT_SCANDV_DID_RESET;
2791 } else if (pReply->SCSIState & MPI_SCSI_STATE_NO_SCSI_STATUS)
2792 completion_code = MPT_SCANDV_DID_RESET;
2793 else if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
2794 completion_code = MPT_SCANDV_DID_RESET;
2795 else if (scsi_status == MPI_SCSI_STATUS_BUSY)
2796 completion_code = MPT_SCANDV_BUSY;
2797 else
2798 completion_code = MPT_SCANDV_GOOD;
2799 break;
2800
2801 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
2802 if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
2803 completion_code = MPT_SCANDV_DID_RESET;
2804 else
2805 completion_code = MPT_SCANDV_SOME_ERROR;
2806 break;
2807 default:
2808 completion_code = MPT_SCANDV_SOME_ERROR;
2809 break;
2810
2811 } /* switch(status) */
2812
2813 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2814 " completionCode set to %08xh\n", ioc->name, completion_code));
2815 return completion_code;
2816}
1da177e4
LT
2817
2818/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2819/**
2820 * mptscsih_do_cmd - Do internal command.
2821 * @hd: MPT_SCSI_HOST pointer
2822 * @io: INTERNAL_CMD pointer.
2823 *
2824 * Issue the specified internally generated command and do command
2825 * specific cleanup. For bus scan / DV only.
2826 * NOTES: If command is Inquiry and status is good,
2827 * initialize a target structure, save the data
2828 *
2829 * Remark: Single threaded access only.
2830 *
2831 * Return:
2832 * < 0 if an illegal command or no resources
2833 *
2834 * 0 if good
2835 *
2836 * > 0 if command complete but some type of completion error.
2837 */
2838static int
2839mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
2840{
2841 MPT_FRAME_HDR *mf;
2842 SCSIIORequest_t *pScsiReq;
1da177e4 2843 int my_idx, ii, dir;
37c60f37 2844 int timeout;
1da177e4
LT
2845 char cmdLen;
2846 char CDB[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
37c60f37
KD
2847 u8 cmd = io->cmd;
2848 MPT_ADAPTER *ioc = hd->ioc;
2849 int ret = 0;
2850 unsigned long timeleft;
2851 unsigned long flags;
1da177e4 2852
1ba9ab2e
KD
2853 /* don't send internal command during diag reset */
2854 spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
2855 if (ioc->ioc_reset_in_progress) {
2856 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
2857 dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2858 "%s: busy with host reset\n", ioc->name, __func__));
2859 return MPT_SCANDV_BUSY;
2860 }
2861 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
2862
37c60f37 2863 mutex_lock(&ioc->internal_cmds.mutex);
1da177e4
LT
2864
2865 /* Set command specific information
2866 */
2867 switch (cmd) {
2868 case INQUIRY:
2869 cmdLen = 6;
2870 dir = MPI_SCSIIO_CONTROL_READ;
2871 CDB[0] = cmd;
2872 CDB[4] = io->size;
37c60f37 2873 timeout = 10;
1da177e4
LT
2874 break;
2875
2876 case TEST_UNIT_READY:
2877 cmdLen = 6;
2878 dir = MPI_SCSIIO_CONTROL_READ;
37c60f37 2879 timeout = 10;
1da177e4
LT
2880 break;
2881
2882 case START_STOP:
2883 cmdLen = 6;
2884 dir = MPI_SCSIIO_CONTROL_READ;
2885 CDB[0] = cmd;
2886 CDB[4] = 1; /*Spin up the disk */
37c60f37 2887 timeout = 15;
1da177e4
LT
2888 break;
2889
2890 case REQUEST_SENSE:
2891 cmdLen = 6;
2892 CDB[0] = cmd;
2893 CDB[4] = io->size;
2894 dir = MPI_SCSIIO_CONTROL_READ;
37c60f37 2895 timeout = 10;
1da177e4
LT
2896 break;
2897
2898 case READ_BUFFER:
2899 cmdLen = 10;
2900 dir = MPI_SCSIIO_CONTROL_READ;
2901 CDB[0] = cmd;
2902 if (io->flags & MPT_ICFLAG_ECHO) {
2903 CDB[1] = 0x0A;
2904 } else {
2905 CDB[1] = 0x02;
2906 }
2907
2908 if (io->flags & MPT_ICFLAG_BUF_CAP) {
2909 CDB[1] |= 0x01;
2910 }
2911 CDB[6] = (io->size >> 16) & 0xFF;
2912 CDB[7] = (io->size >> 8) & 0xFF;
2913 CDB[8] = io->size & 0xFF;
37c60f37 2914 timeout = 10;
1da177e4
LT
2915 break;
2916
2917 case WRITE_BUFFER:
2918 cmdLen = 10;
2919 dir = MPI_SCSIIO_CONTROL_WRITE;
2920 CDB[0] = cmd;
2921 if (io->flags & MPT_ICFLAG_ECHO) {
2922 CDB[1] = 0x0A;
2923 } else {
2924 CDB[1] = 0x02;
2925 }
2926 CDB[6] = (io->size >> 16) & 0xFF;
2927 CDB[7] = (io->size >> 8) & 0xFF;
2928 CDB[8] = io->size & 0xFF;
37c60f37 2929 timeout = 10;
1da177e4
LT
2930 break;
2931
2932 case RESERVE:
2933 cmdLen = 6;
2934 dir = MPI_SCSIIO_CONTROL_READ;
2935 CDB[0] = cmd;
37c60f37 2936 timeout = 10;
1da177e4
LT
2937 break;
2938
2939 case RELEASE:
2940 cmdLen = 6;
2941 dir = MPI_SCSIIO_CONTROL_READ;
2942 CDB[0] = cmd;
37c60f37 2943 timeout = 10;
1da177e4
LT
2944 break;
2945
2946 case SYNCHRONIZE_CACHE:
2947 cmdLen = 10;
2948 dir = MPI_SCSIIO_CONTROL_READ;
2949 CDB[0] = cmd;
2950// CDB[1] = 0x02; /* set immediate bit */
37c60f37 2951 timeout = 10;
1da177e4
LT
2952 break;
2953
2954 default:
2955 /* Error Case */
37c60f37
KD
2956 ret = -EFAULT;
2957 goto out;
1da177e4
LT
2958 }
2959
2960 /* Get and Populate a free Frame
37c60f37 2961 * MsgContext set in mpt_get_msg_frame call
1da177e4 2962 */
e80b002b 2963 if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) {
37c60f37
KD
2964 dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s: No msg frames!\n",
2965 ioc->name, __func__));
2966 ret = MPT_SCANDV_BUSY;
2967 goto out;
1da177e4
LT
2968 }
2969
2970 pScsiReq = (SCSIIORequest_t *) mf;
2971
2972 /* Get the request index */
2973 my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
2974 ADD_INDEX_LOG(my_idx); /* for debug */
2975
2976 if (io->flags & MPT_ICFLAG_PHYS_DISK) {
2977 pScsiReq->TargetID = io->physDiskNum;
2978 pScsiReq->Bus = 0;
2979 pScsiReq->ChainOffset = 0;
2980 pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
2981 } else {
2982 pScsiReq->TargetID = io->id;
793955f5 2983 pScsiReq->Bus = io->channel;
1da177e4
LT
2984 pScsiReq->ChainOffset = 0;
2985 pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
2986 }
2987
2988 pScsiReq->CDBLength = cmdLen;
2989 pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
2990
2991 pScsiReq->Reserved = 0;
2992
14d0f0b0 2993 pScsiReq->MsgFlags = mpt_msg_flags(ioc);
1da177e4
LT
2994 /* MsgContext set in mpt_get_msg_fram call */
2995
793955f5 2996 int_to_scsilun(io->lun, (struct scsi_lun *)pScsiReq->LUN);
1da177e4
LT
2997
2998 if (io->flags & MPT_ICFLAG_TAGGED_CMD)
2999 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_SIMPLEQ);
3000 else
3001 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
3002
3003 if (cmd == REQUEST_SENSE) {
3004 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
37c60f37
KD
3005 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3006 "%s: Untagged! 0x%02x\n", ioc->name, __func__, cmd));
1da177e4
LT
3007 }
3008
37c60f37 3009 for (ii = 0; ii < 16; ii++)
1da177e4
LT
3010 pScsiReq->CDB[ii] = CDB[ii];
3011
3012 pScsiReq->DataLength = cpu_to_le32(io->size);
e80b002b 3013 pScsiReq->SenseBufferLowAddr = cpu_to_le32(ioc->sense_buf_low_dma
1da177e4
LT
3014 + (my_idx * MPT_SENSE_BUFFER_ALLOC));
3015
37c60f37
KD
3016 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3017 "%s: Sending Command 0x%02x for fw_channel=%d fw_id=%d lun=%d\n",
3018 ioc->name, __func__, cmd, io->channel, io->id, io->lun));
1da177e4 3019
37c60f37 3020 if (dir == MPI_SCSIIO_CONTROL_READ)
14d0f0b0 3021 ioc->add_sge((char *) &pScsiReq->SGL,
37c60f37
KD
3022 MPT_SGE_FLAGS_SSIMPLE_READ | io->size, io->data_dma);
3023 else
14d0f0b0 3024 ioc->add_sge((char *) &pScsiReq->SGL,
37c60f37 3025 MPT_SGE_FLAGS_SSIMPLE_WRITE | io->size, io->data_dma);
1da177e4 3026
37c60f37 3027 INITIALIZE_MGMT_STATUS(ioc->internal_cmds.status)
e80b002b 3028 mpt_put_msg_frame(ioc->InternalCtx, ioc, mf);
37c60f37
KD
3029 timeleft = wait_for_completion_timeout(&ioc->internal_cmds.done,
3030 timeout*HZ);
3031 if (!(ioc->internal_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
3032 ret = MPT_SCANDV_DID_RESET;
3033 dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3034 "%s: TIMED OUT for cmd=0x%02x\n", ioc->name, __func__,
3035 cmd));
3036 if (ioc->internal_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET) {
3037 mpt_free_msg_frame(ioc, mf);
3038 goto out;
3039 }
3040 if (!timeleft) {
3041 printk(MYIOC_s_WARN_FMT "Issuing Reset from %s!!\n",
3042 ioc->name, __func__);
3043 mpt_HardResetHandler(ioc, CAN_SLEEP);
3044 mpt_free_msg_frame(ioc, mf);
3045 }
3046 goto out;
1da177e4
LT
3047 }
3048
37c60f37
KD
3049 ret = ioc->internal_cmds.completion_code;
3050 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: success, rc=0x%02x\n",
3051 ioc->name, __func__, ret));
3052
3053 out:
3054 CLEAR_MGMT_STATUS(ioc->internal_cmds.status)
3055 mutex_unlock(&ioc->internal_cmds.mutex);
3056 return ret;
1da177e4
LT
3057}
3058
c7c82987
MED
3059/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3060/**
3061 * mptscsih_synchronize_cache - Send SYNCHRONIZE_CACHE to all disks.
3062 * @hd: Pointer to a SCSI HOST structure
d9489fb6 3063 * @vdevice: virtual target device
c7c82987
MED
3064 *
3065 * Uses the ISR, but with special processing.
3066 * MUST be single-threaded.
3067 *
3068 */
3069static void
3070mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
3071{
3072 INTERNAL_CMD iocmd;
1da177e4 3073
cc78d30a
EM
3074 /* Ignore hidden raid components, this is handled when the command
3075 * is sent to the volume
3076 */
3077 if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT)
3078 return;
3079
3080 if (vdevice->vtarget->type != TYPE_DISK || vdevice->vtarget->deleted ||
3081 !vdevice->configured_lun)
3082 return;
3083
c7c82987
MED
3084 /* Following parameters will not change
3085 * in this routine.
3086 */
3087 iocmd.cmd = SYNCHRONIZE_CACHE;
3088 iocmd.flags = 0;
3089 iocmd.physDiskNum = -1;
3090 iocmd.data = NULL;
3091 iocmd.data_dma = -1;
3092 iocmd.size = 0;
3093 iocmd.rsvd = iocmd.rsvd2 = 0;
793955f5
EM
3094 iocmd.channel = vdevice->vtarget->channel;
3095 iocmd.id = vdevice->vtarget->id;
3096 iocmd.lun = vdevice->lun;
1da177e4 3097
cc78d30a 3098 mptscsih_do_cmd(hd, &iocmd);
1da177e4
LT
3099}
3100
edb9068d 3101static ssize_t
ee959b00
TJ
3102mptscsih_version_fw_show(struct device *dev, struct device_attribute *attr,
3103 char *buf)
edb9068d 3104{
ee959b00 3105 struct Scsi_Host *host = class_to_shost(dev);
e7eae9f6 3106 MPT_SCSI_HOST *hd = shost_priv(host);
edb9068d
PS
3107 MPT_ADAPTER *ioc = hd->ioc;
3108
3109 return snprintf(buf, PAGE_SIZE, "%02d.%02d.%02d.%02d\n",
3110 (ioc->facts.FWVersion.Word & 0xFF000000) >> 24,
3111 (ioc->facts.FWVersion.Word & 0x00FF0000) >> 16,
3112 (ioc->facts.FWVersion.Word & 0x0000FF00) >> 8,
3113 ioc->facts.FWVersion.Word & 0x000000FF);
3114}
ee959b00 3115static DEVICE_ATTR(version_fw, S_IRUGO, mptscsih_version_fw_show, NULL);
edb9068d
PS
3116
3117static ssize_t
ee959b00
TJ
3118mptscsih_version_bios_show(struct device *dev, struct device_attribute *attr,
3119 char *buf)
edb9068d 3120{
ee959b00 3121 struct Scsi_Host *host = class_to_shost(dev);
e7eae9f6 3122 MPT_SCSI_HOST *hd = shost_priv(host);
edb9068d
PS
3123 MPT_ADAPTER *ioc = hd->ioc;
3124
3125 return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x.%02x\n",
3126 (ioc->biosVersion & 0xFF000000) >> 24,
3127 (ioc->biosVersion & 0x00FF0000) >> 16,
3128 (ioc->biosVersion & 0x0000FF00) >> 8,
3129 ioc->biosVersion & 0x000000FF);
3130}
ee959b00 3131static DEVICE_ATTR(version_bios, S_IRUGO, mptscsih_version_bios_show, NULL);
edb9068d
PS
3132
3133static ssize_t
ee959b00
TJ
3134mptscsih_version_mpi_show(struct device *dev, struct device_attribute *attr,
3135 char *buf)
edb9068d 3136{
ee959b00 3137 struct Scsi_Host *host = class_to_shost(dev);
e7eae9f6 3138 MPT_SCSI_HOST *hd = shost_priv(host);
edb9068d
PS
3139 MPT_ADAPTER *ioc = hd->ioc;
3140
3141 return snprintf(buf, PAGE_SIZE, "%03x\n", ioc->facts.MsgVersion);
3142}
ee959b00 3143static DEVICE_ATTR(version_mpi, S_IRUGO, mptscsih_version_mpi_show, NULL);
edb9068d
PS
3144
3145static ssize_t
ee959b00
TJ
3146mptscsih_version_product_show(struct device *dev,
3147 struct device_attribute *attr,
3148char *buf)
edb9068d 3149{
ee959b00 3150 struct Scsi_Host *host = class_to_shost(dev);
e7eae9f6 3151 MPT_SCSI_HOST *hd = shost_priv(host);
edb9068d
PS
3152 MPT_ADAPTER *ioc = hd->ioc;
3153
3154 return snprintf(buf, PAGE_SIZE, "%s\n", ioc->prod_name);
3155}
ee959b00 3156static DEVICE_ATTR(version_product, S_IRUGO,
edb9068d
PS
3157 mptscsih_version_product_show, NULL);
3158
3159static ssize_t
ee959b00
TJ
3160mptscsih_version_nvdata_persistent_show(struct device *dev,
3161 struct device_attribute *attr,
3162 char *buf)
edb9068d 3163{
ee959b00 3164 struct Scsi_Host *host = class_to_shost(dev);
e7eae9f6 3165 MPT_SCSI_HOST *hd = shost_priv(host);
edb9068d
PS
3166 MPT_ADAPTER *ioc = hd->ioc;
3167
3168 return snprintf(buf, PAGE_SIZE, "%02xh\n",
3169 ioc->nvdata_version_persistent);
3170}
ee959b00 3171static DEVICE_ATTR(version_nvdata_persistent, S_IRUGO,
edb9068d
PS
3172 mptscsih_version_nvdata_persistent_show, NULL);
3173
3174static ssize_t
ee959b00
TJ
3175mptscsih_version_nvdata_default_show(struct device *dev,
3176 struct device_attribute *attr, char *buf)
edb9068d 3177{
ee959b00 3178 struct Scsi_Host *host = class_to_shost(dev);
e7eae9f6 3179 MPT_SCSI_HOST *hd = shost_priv(host);
edb9068d
PS
3180 MPT_ADAPTER *ioc = hd->ioc;
3181
3182 return snprintf(buf, PAGE_SIZE, "%02xh\n",ioc->nvdata_version_default);
3183}
ee959b00 3184static DEVICE_ATTR(version_nvdata_default, S_IRUGO,
edb9068d
PS
3185 mptscsih_version_nvdata_default_show, NULL);
3186
3187static ssize_t
ee959b00
TJ
3188mptscsih_board_name_show(struct device *dev, struct device_attribute *attr,
3189 char *buf)
edb9068d 3190{
ee959b00 3191 struct Scsi_Host *host = class_to_shost(dev);
e7eae9f6 3192 MPT_SCSI_HOST *hd = shost_priv(host);
edb9068d
PS
3193 MPT_ADAPTER *ioc = hd->ioc;
3194
3195 return snprintf(buf, PAGE_SIZE, "%s\n", ioc->board_name);
3196}
ee959b00 3197static DEVICE_ATTR(board_name, S_IRUGO, mptscsih_board_name_show, NULL);
edb9068d
PS
3198
3199static ssize_t
ee959b00
TJ
3200mptscsih_board_assembly_show(struct device *dev,
3201 struct device_attribute *attr, char *buf)
edb9068d 3202{
ee959b00 3203 struct Scsi_Host *host = class_to_shost(dev);
e7eae9f6 3204 MPT_SCSI_HOST *hd = shost_priv(host);
edb9068d
PS
3205 MPT_ADAPTER *ioc = hd->ioc;
3206
3207 return snprintf(buf, PAGE_SIZE, "%s\n", ioc->board_assembly);
3208}
ee959b00 3209static DEVICE_ATTR(board_assembly, S_IRUGO,
edb9068d
PS
3210 mptscsih_board_assembly_show, NULL);
3211
3212static ssize_t
ee959b00
TJ
3213mptscsih_board_tracer_show(struct device *dev, struct device_attribute *attr,
3214 char *buf)
edb9068d 3215{
ee959b00 3216 struct Scsi_Host *host = class_to_shost(dev);
e7eae9f6 3217 MPT_SCSI_HOST *hd = shost_priv(host);
edb9068d
PS
3218 MPT_ADAPTER *ioc = hd->ioc;
3219
3220 return snprintf(buf, PAGE_SIZE, "%s\n", ioc->board_tracer);
3221}
ee959b00 3222static DEVICE_ATTR(board_tracer, S_IRUGO,
edb9068d
PS
3223 mptscsih_board_tracer_show, NULL);
3224
3225static ssize_t
ee959b00
TJ
3226mptscsih_io_delay_show(struct device *dev, struct device_attribute *attr,
3227 char *buf)
edb9068d 3228{
ee959b00 3229 struct Scsi_Host *host = class_to_shost(dev);
e7eae9f6 3230 MPT_SCSI_HOST *hd = shost_priv(host);
edb9068d
PS
3231 MPT_ADAPTER *ioc = hd->ioc;
3232
3233 return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->io_missing_delay);
3234}
ee959b00 3235static DEVICE_ATTR(io_delay, S_IRUGO,
edb9068d
PS
3236 mptscsih_io_delay_show, NULL);
3237
3238static ssize_t
ee959b00
TJ
3239mptscsih_device_delay_show(struct device *dev, struct device_attribute *attr,
3240 char *buf)
edb9068d 3241{
ee959b00 3242 struct Scsi_Host *host = class_to_shost(dev);
e7eae9f6 3243 MPT_SCSI_HOST *hd = shost_priv(host);
edb9068d
PS
3244 MPT_ADAPTER *ioc = hd->ioc;
3245
3246 return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->device_missing_delay);
3247}
ee959b00 3248static DEVICE_ATTR(device_delay, S_IRUGO,
edb9068d
PS
3249 mptscsih_device_delay_show, NULL);
3250
6757d6b4 3251static ssize_t
ee959b00
TJ
3252mptscsih_debug_level_show(struct device *dev, struct device_attribute *attr,
3253 char *buf)
6757d6b4 3254{
ee959b00 3255 struct Scsi_Host *host = class_to_shost(dev);
e7eae9f6 3256 MPT_SCSI_HOST *hd = shost_priv(host);
6757d6b4
PS
3257 MPT_ADAPTER *ioc = hd->ioc;
3258
3259 return snprintf(buf, PAGE_SIZE, "%08xh\n", ioc->debug_level);
3260}
3261static ssize_t
ee959b00
TJ
3262mptscsih_debug_level_store(struct device *dev, struct device_attribute *attr,
3263 const char *buf, size_t count)
6757d6b4 3264{
ee959b00 3265 struct Scsi_Host *host = class_to_shost(dev);
e7eae9f6 3266 MPT_SCSI_HOST *hd = shost_priv(host);
6757d6b4
PS
3267 MPT_ADAPTER *ioc = hd->ioc;
3268 int val = 0;
3269
3270 if (sscanf(buf, "%x", &val) != 1)
3271 return -EINVAL;
3272
3273 ioc->debug_level = val;
3274 printk(MYIOC_s_INFO_FMT "debug_level=%08xh\n",
3275 ioc->name, ioc->debug_level);
3276 return strlen(buf);
3277}
ee959b00
TJ
3278static DEVICE_ATTR(debug_level, S_IRUGO | S_IWUSR,
3279 mptscsih_debug_level_show, mptscsih_debug_level_store);
3280
3281struct device_attribute *mptscsih_host_attrs[] = {
3282 &dev_attr_version_fw,
3283 &dev_attr_version_bios,
3284 &dev_attr_version_mpi,
3285 &dev_attr_version_product,
3286 &dev_attr_version_nvdata_persistent,
3287 &dev_attr_version_nvdata_default,
3288 &dev_attr_board_name,
3289 &dev_attr_board_assembly,
3290 &dev_attr_board_tracer,
3291 &dev_attr_io_delay,
3292 &dev_attr_device_delay,
3293 &dev_attr_debug_level,
edb9068d
PS
3294 NULL,
3295};
37c60f37 3296
edb9068d
PS
3297EXPORT_SYMBOL(mptscsih_host_attrs);
3298
0d0c7974
MED
3299EXPORT_SYMBOL(mptscsih_remove);
3300EXPORT_SYMBOL(mptscsih_shutdown);
3301#ifdef CONFIG_PM
3302EXPORT_SYMBOL(mptscsih_suspend);
3303EXPORT_SYMBOL(mptscsih_resume);
3304#endif
3305EXPORT_SYMBOL(mptscsih_proc_info);
3306EXPORT_SYMBOL(mptscsih_info);
3307EXPORT_SYMBOL(mptscsih_qcmd);
0d0c7974
MED
3308EXPORT_SYMBOL(mptscsih_slave_destroy);
3309EXPORT_SYMBOL(mptscsih_slave_configure);
3310EXPORT_SYMBOL(mptscsih_abort);
3311EXPORT_SYMBOL(mptscsih_dev_reset);
3312EXPORT_SYMBOL(mptscsih_bus_reset);
3313EXPORT_SYMBOL(mptscsih_host_reset);
3314EXPORT_SYMBOL(mptscsih_bios_param);
3315EXPORT_SYMBOL(mptscsih_io_done);
3316EXPORT_SYMBOL(mptscsih_taskmgmt_complete);
3317EXPORT_SYMBOL(mptscsih_scandv_complete);
3318EXPORT_SYMBOL(mptscsih_event_process);
3319EXPORT_SYMBOL(mptscsih_ioc_reset);
6e3815ba 3320EXPORT_SYMBOL(mptscsih_change_queue_depth);
1da177e4 3321
0d0c7974 3322/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/