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