[SCSI] mptsas : Removed mptscsih_timer_expired.
[linux-2.6-block.git] / drivers / message / fusion / mptscsih.c
CommitLineData
1da177e4
LT
1/*
2 * linux/drivers/message/fusion/mptscsih.c
f36789e2
PS
3 * For use with LSI PCI chip/adapter(s)
4 * running LSI Fusion MPT (Message Passing Technology) firmware.
1da177e4 5 *
cddc0ab7 6 * Copyright (c) 1999-2008 LSI Corporation
16d20101 7 * (mailto:DL-MPTFusionLinux@lsi.com)
1da177e4 8 *
1da177e4
LT
9 */
10/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
11/*
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; version 2 of the License.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 NO WARRANTY
22 THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
23 CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
24 LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
25 MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
26 solely responsible for determining the appropriateness of using and
27 distributing the Program and assumes all risks associated with its
28 exercise of rights under this Agreement, including but not limited to
29 the risks and costs of program errors, damage to or loss of data,
30 programs or equipment, and unavailability or interruption of operations.
31
32 DISCLAIMER OF LIABILITY
33 NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
34 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35 DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
36 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
37 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
38 USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
39 HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
40
41 You should have received a copy of the GNU General Public License
42 along with this program; if not, write to the Free Software
43 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
44*/
45/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
46
1da177e4
LT
47#include <linux/module.h>
48#include <linux/kernel.h>
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
631 sc->host_scribble = NULL;
1da177e4
LT
632 sc->result = DID_OK << 16; /* Set default reply as OK */
633 pScsiReq = (SCSIIORequest_t *) mf;
634 pScsiReply = (SCSIIOReply_t *) mr;
635
c6678e0c 636 if((ioc->facts.MsgVersion >= MPI_VERSION_01_05) && pScsiReply){
6757d6b4 637 dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT
c6678e0c
CH
638 "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d,task-tag=%d)\n",
639 ioc->name, mf, mr, sc, req_idx, pScsiReply->TaskTag));
640 }else{
6757d6b4 641 dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT
c6678e0c
CH
642 "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d)\n",
643 ioc->name, mf, mr, sc, req_idx));
644 }
645
1da177e4
LT
646 if (pScsiReply == NULL) {
647 /* special context reply handling */
648 ;
649 } else {
650 u32 xfer_cnt;
651 u16 status;
652 u8 scsi_state, scsi_status;
c6c727a1 653 u32 log_info;
1da177e4
LT
654
655 status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK;
656 scsi_state = pScsiReply->SCSIState;
657 scsi_status = pScsiReply->SCSIStatus;
658 xfer_cnt = le32_to_cpu(pScsiReply->TransferCount);
1928d73f 659 scsi_set_resid(sc, scsi_bufflen(sc) - xfer_cnt);
c6c727a1 660 log_info = le32_to_cpu(pScsiReply->IOCLogInfo);
1da177e4 661
466544d8
MED
662 /*
663 * if we get a data underrun indication, yet no data was
664 * transferred and the SCSI status indicates that the
665 * command was never started, change the data underrun
666 * to success
667 */
668 if (status == MPI_IOCSTATUS_SCSI_DATA_UNDERRUN && xfer_cnt == 0 &&
669 (scsi_status == MPI_SCSI_STATUS_BUSY ||
670 scsi_status == MPI_SCSI_STATUS_RESERVATION_CONFLICT ||
671 scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL)) {
672 status = MPI_IOCSTATUS_SUCCESS;
673 }
674
1da177e4 675 if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID)
0d0c7974
MED
676 mptscsih_copy_sense_data(sc, hd, mf, pScsiReply);
677
1da177e4
LT
678 /*
679 * Look for + dump FCP ResponseInfo[]!
680 */
466544d8
MED
681 if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID &&
682 pScsiReply->ResponseInfo) {
29dd3609
EM
683 printk(MYIOC_s_NOTE_FMT "[%d:%d:%d:%d] "
684 "FCP_ResponseInfo=%08xh\n", ioc->name,
c6c727a1
EM
685 sc->device->host->host_no, sc->device->channel,
686 sc->device->id, sc->device->lun,
1da177e4
LT
687 le32_to_cpu(pScsiReply->ResponseInfo));
688 }
689
690 switch(status) {
691 case MPI_IOCSTATUS_BUSY: /* 0x0002 */
692 /* CHECKME!
693 * Maybe: DRIVER_BUSY | SUGGEST_RETRY | DID_SOFT_ERROR (retry)
694 * But not: DID_BUS_BUSY lest one risk
695 * killing interrupt handler:-(
696 */
697 sc->result = SAM_STAT_BUSY;
698 break;
699
700 case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
701 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
702 sc->result = DID_BAD_TARGET << 16;
703 break;
704
705 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
706 /* Spoof to SCSI Selection Timeout! */
65207fed
ME
707 if (ioc->bus_type != FC)
708 sc->result = DID_NO_CONNECT << 16;
709 /* else fibre, just stall until rescan event */
710 else
711 sc->result = DID_REQUEUE << 16;
1da177e4
LT
712
713 if (hd->sel_timeout[pScsiReq->TargetID] < 0xFFFF)
714 hd->sel_timeout[pScsiReq->TargetID]++;
786899b0 715
a69de507
EM
716 vdevice = sc->device->hostdata;
717 if (!vdevice)
786899b0 718 break;
a69de507 719 vtarget = vdevice->vtarget;
786899b0
EM
720 if (vtarget->tflags & MPT_TARGET_FLAGS_LED_ON) {
721 mptscsih_issue_sep_command(ioc, vtarget,
722 MPI_SEP_REQ_SLOTSTATUS_UNCONFIGURED);
723 vtarget->tflags &= ~MPT_TARGET_FLAGS_LED_ON;
724 }
1da177e4
LT
725 break;
726
1da177e4 727 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
bf451522
EM
728 if ( ioc->bus_type == SAS ) {
729 u16 ioc_status = le16_to_cpu(pScsiReply->IOCStatus);
730 if (ioc_status & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
c6c727a1
EM
731 if ((log_info & SAS_LOGINFO_MASK)
732 == SAS_LOGINFO_NEXUS_LOSS) {
bf451522
EM
733 sc->result = (DID_BUS_BUSY << 16);
734 break;
735 }
736 }
86dd4242
EM
737 } else if (ioc->bus_type == FC) {
738 /*
739 * The FC IOC may kill a request for variety of
740 * reasons, some of which may be recovered by a
741 * retry, some which are unlikely to be
742 * recovered. Return DID_ERROR instead of
743 * DID_RESET to permit retry of the command,
744 * just not an infinite number of them
745 */
746 sc->result = DID_ERROR << 16;
747 break;
bf451522
EM
748 }
749
750 /*
751 * Allow non-SAS & non-NEXUS_LOSS to drop into below code
752 */
753
754 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
1da177e4
LT
755 /* Linux handles an unsolicited DID_RESET better
756 * than an unsolicited DID_ABORT.
757 */
758 sc->result = DID_RESET << 16;
759
2f187862
KD
760 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
761 if (ioc->bus_type == FC)
762 sc->result = DID_ERROR << 16;
763 else
764 sc->result = DID_RESET << 16;
1da177e4
LT
765 break;
766
767 case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
1928d73f 768 scsi_set_resid(sc, scsi_bufflen(sc) - xfer_cnt);
466544d8
MED
769 if((xfer_cnt==0)||(sc->underflow > xfer_cnt))
770 sc->result=DID_SOFT_ERROR << 16;
771 else /* Sufficient data transfer occurred */
1da177e4 772 sc->result = (DID_OK << 16) | scsi_status;
29dd3609 773 dreplyprintk(ioc, printk(MYIOC_s_DEBUG_FMT
c6c727a1 774 "RESIDUAL_MISMATCH: result=%x on channel=%d id=%d\n",
29dd3609 775 ioc->name, sc->result, sc->device->channel, sc->device->id));
1da177e4 776 break;
0d0c7974 777
1da177e4
LT
778 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
779 /*
780 * Do upfront check for valid SenseData and give it
781 * precedence!
782 */
783 sc->result = (DID_OK << 16) | scsi_status;
784 if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
785 /* Have already saved the status and sense data
786 */
787 ;
788 } else {
789 if (xfer_cnt < sc->underflow) {
466544d8
MED
790 if (scsi_status == SAM_STAT_BUSY)
791 sc->result = SAM_STAT_BUSY;
792 else
793 sc->result = DID_SOFT_ERROR << 16;
1da177e4
LT
794 }
795 if (scsi_state & (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)) {
796 /* What to do?
797 */
798 sc->result = DID_SOFT_ERROR << 16;
799 }
800 else if (scsi_state & MPI_SCSI_STATE_TERMINATED) {
801 /* Not real sure here either... */
802 sc->result = DID_RESET << 16;
803 }
804 }
805
6757d6b4 806
29dd3609
EM
807 dreplyprintk(ioc, printk(MYIOC_s_DEBUG_FMT
808 " sc->underflow={report ERR if < %02xh bytes xfer'd}\n",
809 ioc->name, sc->underflow));
810 dreplyprintk(ioc, printk(MYIOC_s_DEBUG_FMT
811 " ActBytesXferd=%02xh\n", ioc->name, xfer_cnt));
6757d6b4 812
1da177e4
LT
813 /* Report Queue Full
814 */
815 if (scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL)
816 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
0d0c7974 817
1da177e4
LT
818 break;
819
7e55147f 820 case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
1928d73f 821 scsi_set_resid(sc, 0);
1da177e4
LT
822 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
823 case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */
ad8c31bb 824 sc->result = (DID_OK << 16) | scsi_status;
1da177e4
LT
825 if (scsi_state == 0) {
826 ;
827 } else if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
828 /*
829 * If running against circa 200003dd 909 MPT f/w,
830 * may get this (AUTOSENSE_VALID) for actual TASK_SET_FULL
831 * (QUEUE_FULL) returned from device! --> get 0x0000?128
832 * and with SenseBytes set to 0.
833 */
834 if (pScsiReply->SCSIStatus == MPI_SCSI_STATUS_TASK_SET_FULL)
835 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
836
837 }
838 else if (scsi_state &
839 (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)
840 ) {
841 /*
842 * What to do?
843 */
844 sc->result = DID_SOFT_ERROR << 16;
845 }
846 else if (scsi_state & MPI_SCSI_STATE_TERMINATED) {
847 /* Not real sure here either... */
848 sc->result = DID_RESET << 16;
849 }
850 else if (scsi_state & MPI_SCSI_STATE_QUEUE_TAG_REJECTED) {
851 /* Device Inq. data indicates that it supports
852 * QTags, but rejects QTag messages.
853 * This command completed OK.
854 *
855 * Not real sure here either so do nothing... */
856 }
857
858 if (sc->result == MPI_SCSI_STATUS_TASK_SET_FULL)
859 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
860
861 /* Add handling of:
862 * Reservation Conflict, Busy,
863 * Command Terminated, CHECK
864 */
865 break;
866
867 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
868 sc->result = DID_SOFT_ERROR << 16;
869 break;
870
871 case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */
872 case MPI_IOCSTATUS_INVALID_SGL: /* 0x0003 */
873 case MPI_IOCSTATUS_INTERNAL_ERROR: /* 0x0004 */
874 case MPI_IOCSTATUS_RESERVED: /* 0x0005 */
875 case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */
876 case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */
877 case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */
1da177e4
LT
878 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
879 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
880 default:
881 /*
882 * What to do?
883 */
884 sc->result = DID_SOFT_ERROR << 16;
885 break;
886
887 } /* switch(status) */
888
6757d6b4
PS
889#ifdef CONFIG_FUSION_LOGGING
890 if (sc->result && (ioc->debug_level & MPT_DEBUG_REPLY))
891 mptscsih_info_scsiio(ioc, sc, pScsiReply);
c6c727a1
EM
892#endif
893
1da177e4
LT
894 } /* end of address reply case */
895
896 /* Unmap the DMA buffers, if any. */
1928d73f 897 scsi_dma_unmap(sc);
1da177e4 898
1da177e4
LT
899 sc->scsi_done(sc); /* Issue the command callback */
900
901 /* Free Chain buffers */
902 mptscsih_freeChainBuffers(ioc, req_idx);
903 return 1;
904}
905
1da177e4
LT
906/*
907 * mptscsih_flush_running_cmds - For each command found, search
908 * Scsi_Host instance taskQ and reply to OS.
909 * Called only if recovering from a FW reload.
910 * @hd: Pointer to a SCSI HOST structure
911 *
912 * Returns: None.
913 *
914 * Must be called while new I/Os are being queued.
915 */
916static void
917mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
918{
919 MPT_ADAPTER *ioc = hd->ioc;
e8206381
EM
920 struct scsi_cmnd *sc;
921 SCSIIORequest_t *mf = NULL;
1da177e4 922 int ii;
e8206381 923 int channel, id;
1da177e4 924
e8206381
EM
925 for (ii= 0; ii < ioc->req_depth; ii++) {
926 sc = mptscsih_getclear_scsi_lookup(ioc, ii);
927 if (!sc)
928 continue;
929 mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(ioc, ii);
930 if (!mf)
931 continue;
932 channel = mf->Bus;
933 id = mf->TargetID;
934 mptscsih_freeChainBuffers(ioc, ii);
935 mpt_free_msg_frame(ioc, (MPT_FRAME_HDR *)mf);
936 if ((unsigned char *)mf != sc->host_scribble)
937 continue;
938 scsi_dma_unmap(sc);
939 sc->result = DID_RESET << 16;
940 sc->host_scribble = NULL;
2f187862
KD
941 dtmprintk(ioc, sdev_printk(KERN_INFO, sc->device, MYIOC_s_FMT
942 "completing cmds: fw_channel %d, fw_id %d, sc=%p, mf = %p, "
943 "idx=%x\n", ioc->name, channel, id, sc, mf, ii));
e8206381 944 sc->scsi_done(sc);
1da177e4 945 }
1da177e4
LT
946}
947
948/*
949 * mptscsih_search_running_cmds - Delete any commands associated
950 * with the specified target and lun. Function called only
951 * when a lun is disable by mid-layer.
952 * Do NOT access the referenced scsi_cmnd structure or
953 * members. Will cause either a paging or NULL ptr error.
05e8ec17 954 * (BUT, BUT, BUT, the code does reference it! - mdr)
c7c82987
MED
955 * @hd: Pointer to a SCSI HOST structure
956 * @vdevice: per device private data
1da177e4
LT
957 *
958 * Returns: None.
959 *
960 * Called from slave_destroy.
961 */
962static void
c7c82987 963mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
1da177e4
LT
964{
965 SCSIIORequest_t *mf = NULL;
966 int ii;
466544d8 967 struct scsi_cmnd *sc;
793955f5 968 struct scsi_lun lun;
e80b002b 969 MPT_ADAPTER *ioc = hd->ioc;
e8206381 970 unsigned long flags;
1da177e4 971
e8206381
EM
972 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
973 for (ii = 0; ii < ioc->req_depth; ii++) {
974 if ((sc = ioc->ScsiLookup[ii]) != NULL) {
1da177e4 975
e80b002b 976 mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(ioc, ii);
3dc0b03f
EM
977 if (mf == NULL)
978 continue;
cc78d30a
EM
979 /* If the device is a hidden raid component, then its
980 * expected that the mf->function will be RAID_SCSI_IO
981 */
982 if (vdevice->vtarget->tflags &
983 MPT_TARGET_FLAGS_RAID_COMPONENT && mf->Function !=
984 MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)
985 continue;
986
793955f5
EM
987 int_to_scsilun(vdevice->lun, &lun);
988 if ((mf->Bus != vdevice->vtarget->channel) ||
989 (mf->TargetID != vdevice->vtarget->id) ||
990 memcmp(lun.scsi_lun, mf->LUN, 8))
1da177e4
LT
991 continue;
992
3dc0b03f
EM
993 if ((unsigned char *)mf != sc->host_scribble)
994 continue;
e8206381
EM
995 ioc->ScsiLookup[ii] = NULL;
996 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
997 mptscsih_freeChainBuffers(ioc, ii);
998 mpt_free_msg_frame(ioc, (MPT_FRAME_HDR *)mf);
1928d73f 999 scsi_dma_unmap(sc);
466544d8
MED
1000 sc->host_scribble = NULL;
1001 sc->result = DID_NO_CONNECT << 16;
2f187862
KD
1002 dtmprintk(ioc, sdev_printk(KERN_INFO, sc->device,
1003 MYIOC_s_FMT "completing cmds: fw_channel %d, "
1004 "fw_id %d, sc=%p, mf = %p, idx=%x\n", ioc->name,
1005 vdevice->vtarget->channel, vdevice->vtarget->id,
1006 sc, mf, ii));
466544d8 1007 sc->scsi_done(sc);
e8206381 1008 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
1da177e4
LT
1009 }
1010 }
e8206381 1011 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
1da177e4
LT
1012 return;
1013}
1014
1015/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1da177e4
LT
1016
1017/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1018/*
1019 * mptscsih_report_queue_full - Report QUEUE_FULL status returned
1020 * from a SCSI target device.
1021 * @sc: Pointer to scsi_cmnd structure
1022 * @pScsiReply: Pointer to SCSIIOReply_t
1023 * @pScsiReq: Pointer to original SCSI request
1024 *
1025 * This routine periodically reports QUEUE_FULL status returned from a
1026 * SCSI target device. It reports this to the console via kernel
1027 * printk() API call, not more than once every 10 seconds.
1028 */
1029static void
1030mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq)
1031{
1032 long time = jiffies;
1da177e4 1033 MPT_SCSI_HOST *hd;
e80b002b 1034 MPT_ADAPTER *ioc;
1da177e4 1035
0d0c7974
MED
1036 if (sc->device == NULL)
1037 return;
1038 if (sc->device->host == NULL)
1039 return;
e7eae9f6 1040 if ((hd = shost_priv(sc->device->host)) == NULL)
0d0c7974 1041 return;
e80b002b 1042 ioc = hd->ioc;
0d0c7974 1043 if (time - hd->last_queue_full > 10 * HZ) {
e80b002b
EM
1044 dprintk(ioc, printk(MYIOC_s_WARN_FMT "Device (%d:%d:%d) reported QUEUE_FULL!\n",
1045 ioc->name, 0, sc->device->id, sc->device->lun));
0d0c7974 1046 hd->last_queue_full = time;
1da177e4 1047 }
1da177e4
LT
1048}
1049
1050/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1051/*
1052 * mptscsih_remove - Removed scsi devices
1053 * @pdev: Pointer to pci_dev structure
1054 *
1055 *
1056 */
0d0c7974 1057void
1da177e4
LT
1058mptscsih_remove(struct pci_dev *pdev)
1059{
1060 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1061 struct Scsi_Host *host = ioc->sh;
1062 MPT_SCSI_HOST *hd;
0d0c7974 1063 int sz1;
1da177e4 1064
466544d8
MED
1065 if(!host) {
1066 mpt_detach(pdev);
1da177e4 1067 return;
466544d8 1068 }
1da177e4
LT
1069
1070 scsi_remove_host(host);
1071
e7eae9f6 1072 if((hd = shost_priv(host)) == NULL)
0d0c7974
MED
1073 return;
1074
d18c3db5 1075 mptscsih_shutdown(pdev);
1da177e4 1076
0d0c7974 1077 sz1=0;
1da177e4 1078
e8206381 1079 if (ioc->ScsiLookup != NULL) {
e80b002b 1080 sz1 = ioc->req_depth * sizeof(void *);
e8206381
EM
1081 kfree(ioc->ScsiLookup);
1082 ioc->ScsiLookup = NULL;
0d0c7974 1083 }
1da177e4 1084
e80b002b 1085 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
0d0c7974 1086 "Free'd ScsiLookup (%d) memory\n",
e80b002b 1087 ioc->name, sz1));
1da177e4 1088
d485eb83 1089 kfree(hd->info_kbuf);
1da177e4 1090
0d0c7974
MED
1091 /* NULL the Scsi_Host pointer
1092 */
e80b002b 1093 ioc->sh = NULL;
1da177e4
LT
1094
1095 scsi_host_put(host);
1da177e4 1096
0d0c7974 1097 mpt_detach(pdev);
c6678e0c 1098
1da177e4
LT
1099}
1100
1101/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1102/*
1103 * mptscsih_shutdown - reboot notifier
1104 *
1105 */
0d0c7974 1106void
d18c3db5 1107mptscsih_shutdown(struct pci_dev *pdev)
1da177e4 1108{
1da177e4
LT
1109}
1110
1111#ifdef CONFIG_PM
1112/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1113/*
0d0c7974 1114 * mptscsih_suspend - Fusion MPT scsi driver suspend routine.
1da177e4
LT
1115 *
1116 *
1117 */
0d0c7974 1118int
8d189f72 1119mptscsih_suspend(struct pci_dev *pdev, pm_message_t state)
1da177e4 1120{
4d4109d0
PS
1121 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1122
1123 scsi_block_requests(ioc->sh);
1124 flush_scheduled_work();
d18c3db5 1125 mptscsih_shutdown(pdev);
0d0c7974 1126 return mpt_suspend(pdev,state);
1da177e4
LT
1127}
1128
1129/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1130/*
1131 * mptscsih_resume - Fusion MPT scsi driver resume routine.
1132 *
1133 *
1134 */
0d0c7974 1135int
1da177e4
LT
1136mptscsih_resume(struct pci_dev *pdev)
1137{
4d4109d0
PS
1138 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1139 int rc;
1140
1141 rc = mpt_resume(pdev);
1142 scsi_unblock_requests(ioc->sh);
1143 return rc;
1da177e4
LT
1144}
1145
1146#endif
1147
1da177e4
LT
1148/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1149/**
1150 * mptscsih_info - Return information about MPT adapter
1151 * @SChost: Pointer to Scsi_Host structure
1152 *
1153 * (linux scsi_host_template.info routine)
1154 *
1155 * Returns pointer to buffer where information was written.
1156 */
0d0c7974 1157const char *
1da177e4
LT
1158mptscsih_info(struct Scsi_Host *SChost)
1159{
1160 MPT_SCSI_HOST *h;
1161 int size = 0;
1162
e7eae9f6 1163 h = shost_priv(SChost);
0d0c7974 1164
1da177e4 1165 if (h) {
0d0c7974
MED
1166 if (h->info_kbuf == NULL)
1167 if ((h->info_kbuf = kmalloc(0x1000 /* 4Kb */, GFP_KERNEL)) == NULL)
1168 return h->info_kbuf;
1169 h->info_kbuf[0] = '\0';
1170
1171 mpt_print_ioc_summary(h->ioc, h->info_kbuf, &size, 0, 0);
1172 h->info_kbuf[size-1] = '\0';
1da177e4
LT
1173 }
1174
0d0c7974 1175 return h->info_kbuf;
1da177e4
LT
1176}
1177
1178struct info_str {
1179 char *buffer;
1180 int length;
1181 int offset;
1182 int pos;
1183};
1184
0d0c7974
MED
1185static void
1186mptscsih_copy_mem_info(struct info_str *info, char *data, int len)
1da177e4
LT
1187{
1188 if (info->pos + len > info->length)
1189 len = info->length - info->pos;
1190
1191 if (info->pos + len < info->offset) {
1192 info->pos += len;
1193 return;
1194 }
1195
1196 if (info->pos < info->offset) {
1197 data += (info->offset - info->pos);
1198 len -= (info->offset - info->pos);
1199 }
1200
1201 if (len > 0) {
1202 memcpy(info->buffer + info->pos, data, len);
1203 info->pos += len;
1204 }
1205}
1206
0d0c7974
MED
1207static int
1208mptscsih_copy_info(struct info_str *info, char *fmt, ...)
1da177e4
LT
1209{
1210 va_list args;
1211 char buf[81];
1212 int len;
1213
1214 va_start(args, fmt);
1215 len = vsprintf(buf, fmt, args);
1216 va_end(args);
1217
0d0c7974 1218 mptscsih_copy_mem_info(info, buf, len);
1da177e4
LT
1219 return len;
1220}
1221
0d0c7974
MED
1222static int
1223mptscsih_host_info(MPT_ADAPTER *ioc, char *pbuf, off_t offset, int len)
1da177e4
LT
1224{
1225 struct info_str info;
1226
1227 info.buffer = pbuf;
1228 info.length = len;
1229 info.offset = offset;
1230 info.pos = 0;
1231
0d0c7974
MED
1232 mptscsih_copy_info(&info, "%s: %s, ", ioc->name, ioc->prod_name);
1233 mptscsih_copy_info(&info, "%s%08xh, ", MPT_FW_REV_MAGIC_ID_STRING, ioc->facts.FWVersion.Word);
1234 mptscsih_copy_info(&info, "Ports=%d, ", ioc->facts.NumberOfPorts);
1235 mptscsih_copy_info(&info, "MaxQ=%d\n", ioc->req_depth);
1da177e4
LT
1236
1237 return ((info.pos > info.offset) ? info.pos - info.offset : 0);
1238}
1239
1240/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1241/**
1242 * mptscsih_proc_info - Return information about MPT adapter
d9489fb6
RD
1243 * @host: scsi host struct
1244 * @buffer: if write, user data; if read, buffer for user
1245 * @start: returns the buffer address
1246 * @offset: if write, 0; if read, the current offset into the buffer from
1247 * the previous read.
1248 * @length: if write, return length;
1249 * @func: write = 1; read = 0
1da177e4
LT
1250 *
1251 * (linux scsi_host_template.info routine)
1da177e4 1252 */
0d0c7974 1253int
1da177e4
LT
1254mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
1255 int length, int func)
1256{
e7eae9f6 1257 MPT_SCSI_HOST *hd = shost_priv(host);
1da177e4
LT
1258 MPT_ADAPTER *ioc = hd->ioc;
1259 int size = 0;
1260
1261 if (func) {
c6678e0c
CH
1262 /*
1263 * write is not supported
1da177e4
LT
1264 */
1265 } else {
1266 if (start)
1267 *start = buffer;
1268
1269 size = mptscsih_host_info(ioc, buffer, offset, length);
1270 }
1271
1272 return size;
1273}
1274
1275/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1276#define ADD_INDEX_LOG(req_ent) do { } while(0)
1277
1278/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1279/**
1280 * mptscsih_qcmd - Primary Fusion MPT SCSI initiator IO start routine.
1281 * @SCpnt: Pointer to scsi_cmnd structure
1282 * @done: Pointer SCSI mid-layer IO completion function
1283 *
1284 * (linux scsi_host_template.queuecommand routine)
1285 * This is the primary SCSI IO start routine. Create a MPI SCSIIORequest
1286 * from a linux scsi_cmnd request and send it to the IOC.
1287 *
1288 * Returns 0. (rtn value discarded by linux scsi mid-layer)
1289 */
0d0c7974 1290int
1da177e4
LT
1291mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
1292{
1293 MPT_SCSI_HOST *hd;
1294 MPT_FRAME_HDR *mf;
1295 SCSIIORequest_t *pScsiReq;
a69de507 1296 VirtDevice *vdevice = SCpnt->device->hostdata;
1da177e4
LT
1297 u32 datalen;
1298 u32 scsictl;
1299 u32 scsidir;
1300 u32 cmd_len;
1301 int my_idx;
1302 int ii;
6757d6b4 1303 MPT_ADAPTER *ioc;
1da177e4 1304
e7eae9f6 1305 hd = shost_priv(SCpnt->device->host);
6757d6b4 1306 ioc = hd->ioc;
1da177e4
LT
1307 SCpnt->scsi_done = done;
1308
6757d6b4
PS
1309 dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "qcmd: SCpnt=%p, done()=%p\n",
1310 ioc->name, SCpnt, done));
1da177e4 1311
e7deff33 1312 if (ioc->taskmgmt_quiesce_io) {
6757d6b4
PS
1313 dtmprintk(ioc, printk(MYIOC_s_WARN_FMT "qcmd: SCpnt=%p timeout + 60HZ\n",
1314 ioc->name, SCpnt));
1da177e4
LT
1315 return SCSI_MLQUEUE_HOST_BUSY;
1316 }
1317
1318 /*
1319 * Put together a MPT SCSI request...
1320 */
e80b002b 1321 if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) {
6757d6b4
PS
1322 dprintk(ioc, printk(MYIOC_s_WARN_FMT "QueueCmd, no msg frames!!\n",
1323 ioc->name));
1da177e4
LT
1324 return SCSI_MLQUEUE_HOST_BUSY;
1325 }
1326
1327 pScsiReq = (SCSIIORequest_t *) mf;
1328
1329 my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
1330
1331 ADD_INDEX_LOG(my_idx);
1332
0d0c7974 1333 /* TUR's being issued with scsictl=0x02000000 (DATA_IN)!
1da177e4
LT
1334 * Seems we may receive a buffer (datalen>0) even when there
1335 * will be no data transfer! GRRRRR...
1336 */
1337 if (SCpnt->sc_data_direction == DMA_FROM_DEVICE) {
1928d73f 1338 datalen = scsi_bufflen(SCpnt);
1da177e4
LT
1339 scsidir = MPI_SCSIIO_CONTROL_READ; /* DATA IN (host<--ioc<--dev) */
1340 } else if (SCpnt->sc_data_direction == DMA_TO_DEVICE) {
1928d73f 1341 datalen = scsi_bufflen(SCpnt);
1da177e4
LT
1342 scsidir = MPI_SCSIIO_CONTROL_WRITE; /* DATA OUT (host-->ioc-->dev) */
1343 } else {
1344 datalen = 0;
1345 scsidir = MPI_SCSIIO_CONTROL_NODATATRANSFER;
1346 }
1347
1348 /* Default to untagged. Once a target structure has been allocated,
1349 * use the Inquiry data to determine if device supports tagged.
1350 */
a69de507
EM
1351 if (vdevice
1352 && (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_Q_YES)
1da177e4
LT
1353 && (SCpnt->device->tagged_supported)) {
1354 scsictl = scsidir | MPI_SCSIIO_CONTROL_SIMPLEQ;
1355 } else {
1356 scsictl = scsidir | MPI_SCSIIO_CONTROL_UNTAGGED;
1357 }
1358
1359 /* Use the above information to set up the message frame
1360 */
a69de507
EM
1361 pScsiReq->TargetID = (u8) vdevice->vtarget->id;
1362 pScsiReq->Bus = vdevice->vtarget->channel;
1da177e4 1363 pScsiReq->ChainOffset = 0;
a69de507 1364 if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT)
c92f222e
JB
1365 pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
1366 else
1367 pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
1da177e4
LT
1368 pScsiReq->CDBLength = SCpnt->cmd_len;
1369 pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
1370 pScsiReq->Reserved = 0;
14d0f0b0 1371 pScsiReq->MsgFlags = mpt_msg_flags(ioc);
793955f5 1372 int_to_scsilun(SCpnt->device->lun, (struct scsi_lun *)pScsiReq->LUN);
1da177e4
LT
1373 pScsiReq->Control = cpu_to_le32(scsictl);
1374
1375 /*
1376 * Write SCSI CDB into the message
1377 */
1378 cmd_len = SCpnt->cmd_len;
1379 for (ii=0; ii < cmd_len; ii++)
1380 pScsiReq->CDB[ii] = SCpnt->cmnd[ii];
1381
1382 for (ii=cmd_len; ii < 16; ii++)
1383 pScsiReq->CDB[ii] = 0;
1384
1385 /* DataLength */
1386 pScsiReq->DataLength = cpu_to_le32(datalen);
1387
1388 /* SenseBuffer low address */
e80b002b 1389 pScsiReq->SenseBufferLowAddr = cpu_to_le32(ioc->sense_buf_low_dma
1da177e4
LT
1390 + (my_idx * MPT_SENSE_BUFFER_ALLOC));
1391
1392 /* Now add the SG list
1393 * Always have a SGE even if null length.
1394 */
1395 if (datalen == 0) {
1396 /* Add a NULL SGE */
14d0f0b0
KD
1397 ioc->add_sge((char *)&pScsiReq->SGL,
1398 MPT_SGE_FLAGS_SSIMPLE_READ | 0,
1da177e4
LT
1399 (dma_addr_t) -1);
1400 } else {
1401 /* Add a 32 or 64 bit SGE */
e80b002b 1402 if (mptscsih_AddSGE(ioc, SCpnt, pScsiReq, my_idx) != SUCCESS)
1da177e4
LT
1403 goto fail;
1404 }
1405
3dc0b03f 1406 SCpnt->host_scribble = (unsigned char *)mf;
e8206381 1407 mptscsih_set_scsi_lookup(ioc, my_idx, SCpnt);
1da177e4 1408
e80b002b 1409 mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
6757d6b4
PS
1410 dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n",
1411 ioc->name, SCpnt, mf, my_idx));
29dd3609 1412 DBG_DUMP_REQUEST_FRAME(ioc, (u32 *)mf);
1da177e4
LT
1413 return 0;
1414
1415 fail:
e80b002b
EM
1416 mptscsih_freeChainBuffers(ioc, my_idx);
1417 mpt_free_msg_frame(ioc, mf);
1da177e4
LT
1418 return SCSI_MLQUEUE_HOST_BUSY;
1419}
1420
1421/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1422/*
1423 * mptscsih_freeChainBuffers - Function to free chain buffers associated
1424 * with a SCSI IO request
1425 * @hd: Pointer to the MPT_SCSI_HOST instance
1426 * @req_idx: Index of the SCSI IO request frame.
1427 *
1428 * Called if SG chain buffer allocation fails and mptscsih callbacks.
1429 * No return.
1430 */
1431static void
1432mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx)
1433{
1434 MPT_FRAME_HDR *chain;
1435 unsigned long flags;
1436 int chain_idx;
1437 int next;
1438
1439 /* Get the first chain index and reset
1440 * tracker state.
1441 */
1442 chain_idx = ioc->ReqToChain[req_idx];
1443 ioc->ReqToChain[req_idx] = MPT_HOST_NO_CHAIN;
1444
1445 while (chain_idx != MPT_HOST_NO_CHAIN) {
1446
1447 /* Save the next chain buffer index */
1448 next = ioc->ChainToChain[chain_idx];
1449
1450 /* Free this chain buffer and reset
1451 * tracker
1452 */
1453 ioc->ChainToChain[chain_idx] = MPT_HOST_NO_CHAIN;
1454
1455 chain = (MPT_FRAME_HDR *) (ioc->ChainBuffer
1456 + (chain_idx * ioc->req_sz));
1457
1458 spin_lock_irqsave(&ioc->FreeQlock, flags);
1459 list_add_tail(&chain->u.frame.linkage.list, &ioc->FreeChainQ);
1460 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
1461
6757d6b4 1462 dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "FreeChainBuffers (index %d)\n",
1da177e4
LT
1463 ioc->name, chain_idx));
1464
1465 /* handle next */
1466 chain_idx = next;
1467 }
1468 return;
1469}
1470
1471/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1472/*
1473 * Reset Handling
1474 */
1475
1476/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
cd2c6191 1477/**
1ba9ab2e
KD
1478 * mptscsih_IssueTaskMgmt - Generic send Task Management function.
1479 * @hd: Pointer to MPT_SCSI_HOST structure
1da177e4 1480 * @type: Task Management type
1544d677 1481 * @channel: channel number for task management
793955f5 1482 * @id: Logical Target ID for reset (if appropriate)
1da177e4
LT
1483 * @lun: Logical Unit for reset (if appropriate)
1484 * @ctx2abort: Context for the task to be aborted (if appropriate)
1544d677
RD
1485 * @timeout: timeout for task management control
1486 *
1ba9ab2e
KD
1487 * Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
1488 * or a non-interrupt thread. In the former, must not call schedule().
1da177e4 1489 *
1ba9ab2e 1490 * Not all fields are meaningfull for all task types.
1da177e4 1491 *
1ba9ab2e 1492 * Returns 0 for SUCCESS, or FAILED.
1da177e4 1493 *
cd2c6191 1494 **/
663e1aa1 1495int
1ba9ab2e
KD
1496mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun,
1497 int ctx2abort, ulong timeout)
1da177e4 1498{
1ba9ab2e
KD
1499 MPT_FRAME_HDR *mf;
1500 SCSITaskMgmt_t *pScsiTm;
1501 int ii;
1502 int retval;
1503 MPT_ADAPTER *ioc = hd->ioc;
1504 unsigned long timeleft;
1505 u8 issue_hard_reset;
1da177e4 1506 u32 ioc_raw_state;
1ba9ab2e 1507 unsigned long time_count;
1da177e4 1508
1ba9ab2e 1509 issue_hard_reset = 0;
e80b002b 1510 ioc_raw_state = mpt_GetIocState(ioc, 0);
1da177e4 1511
1da177e4
LT
1512 if ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) {
1513 printk(MYIOC_s_WARN_FMT
1ba9ab2e 1514 "TaskMgmt type=%x: IOC Not operational (0x%x)!\n",
cd2c6191 1515 ioc->name, type, ioc_raw_state);
1ba9ab2e
KD
1516 printk(MYIOC_s_WARN_FMT "Issuing HardReset from %s!!\n",
1517 ioc->name, __func__);
cd2c6191 1518 if (mpt_HardResetHandler(ioc, CAN_SLEEP) < 0)
1ba9ab2e 1519 printk(MYIOC_s_WARN_FMT "TaskMgmt HardReset "
29dd3609 1520 "FAILED!!\n", ioc->name);
1ba9ab2e 1521 return 0;
1da177e4
LT
1522 }
1523
cd2c6191
EM
1524 if (ioc_raw_state & MPI_DOORBELL_ACTIVE) {
1525 printk(MYIOC_s_WARN_FMT
1ba9ab2e 1526 "TaskMgmt type=%x: ioc_state: "
cd2c6191
EM
1527 "DOORBELL_ACTIVE (0x%x)!\n",
1528 ioc->name, type, ioc_raw_state);
1529 return FAILED;
1da177e4
LT
1530 }
1531
1ba9ab2e
KD
1532 mutex_lock(&ioc->taskmgmt_cmds.mutex);
1533 if (mpt_set_taskmgmt_in_progress_flag(ioc) != 0) {
1534 mf = NULL;
1535 retval = FAILED;
1536 goto out;
1537 }
1da177e4
LT
1538
1539 /* Return Fail to calling function if no message frames available.
1540 */
e80b002b 1541 if ((mf = mpt_get_msg_frame(ioc->TaskCtx, ioc)) == NULL) {
1ba9ab2e
KD
1542 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1543 "TaskMgmt no msg frames!!\n", ioc->name));
1544 retval = FAILED;
1545 mpt_clear_taskmgmt_in_progress_flag(ioc);
1546 goto out;
1da177e4 1547 }
1ba9ab2e 1548 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt request (mf=%p)\n",
e80b002b 1549 ioc->name, mf));
1da177e4
LT
1550
1551 /* Format the Request
1552 */
1553 pScsiTm = (SCSITaskMgmt_t *) mf;
793955f5 1554 pScsiTm->TargetID = id;
1da177e4
LT
1555 pScsiTm->Bus = channel;
1556 pScsiTm->ChainOffset = 0;
1557 pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
1558
1559 pScsiTm->Reserved = 0;
1560 pScsiTm->TaskType = type;
1561 pScsiTm->Reserved1 = 0;
1562 pScsiTm->MsgFlags = (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS)
1563 ? MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION : 0;
1564
793955f5 1565 int_to_scsilun(lun, (struct scsi_lun *)pScsiTm->LUN);
1da177e4
LT
1566
1567 for (ii=0; ii < 7; ii++)
1568 pScsiTm->Reserved2[ii] = 0;
1569
1570 pScsiTm->TaskMsgContext = ctx2abort;
1571
1ba9ab2e
KD
1572 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt: ctx2abort (0x%08x) "
1573 "task_type = 0x%02X, timeout = %ld\n", ioc->name, ctx2abort,
1574 type, timeout));
1da177e4 1575
6757d6b4 1576 DBG_DUMP_TM_REQUEST_FRAME(ioc, (u32 *)pScsiTm);
1da177e4 1577
1ba9ab2e
KD
1578 INITIALIZE_MGMT_STATUS(ioc->taskmgmt_cmds.status)
1579 time_count = jiffies;
e80b002b
EM
1580 if ((ioc->facts.IOCCapabilities & MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q) &&
1581 (ioc->facts.MsgVersion >= MPI_VERSION_01_05))
1582 mpt_put_msg_frame_hi_pri(ioc->TaskCtx, ioc, mf);
7a195f46 1583 else {
e80b002b 1584 retval = mpt_send_handshake_request(ioc->TaskCtx, ioc,
7a195f46
PS
1585 sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP);
1586 if (retval) {
1ba9ab2e
KD
1587 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1588 "TaskMgmt handshake FAILED!(mf=%p, rc=%d) \n",
1589 ioc->name, mf, retval));
1590 mpt_free_msg_frame(ioc, mf);
1591 mpt_clear_taskmgmt_in_progress_flag(ioc);
1592 goto out;
7a195f46 1593 }
1da177e4
LT
1594 }
1595
1ba9ab2e
KD
1596 timeleft = wait_for_completion_timeout(&ioc->taskmgmt_cmds.done,
1597 timeout*HZ);
1598 if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
1599 retval = FAILED;
1600 dtmprintk(ioc, printk(MYIOC_s_ERR_FMT
1601 "TaskMgmt TIMED OUT!(mf=%p)\n", ioc->name, mf));
1602 mpt_clear_taskmgmt_in_progress_flag(ioc);
1603 if (ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET)
1604 goto out;
1605 issue_hard_reset = 1;
1606 goto out;
1da177e4
LT
1607 }
1608
1ba9ab2e
KD
1609 retval = mptscsih_taskmgmt_reply(ioc, type,
1610 (SCSITaskMgmtReply_t *) ioc->taskmgmt_cmds.reply);
cd2c6191 1611
1ba9ab2e
KD
1612 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1613 "TaskMgmt completed (%d seconds)\n",
1614 ioc->name, jiffies_to_msecs(jiffies - time_count)/1000));
cd2c6191 1615
1ba9ab2e 1616 out:
cd2c6191 1617
1ba9ab2e
KD
1618 CLEAR_MGMT_STATUS(ioc->taskmgmt_cmds.status)
1619 if (issue_hard_reset) {
1620 printk(MYIOC_s_WARN_FMT "Issuing Reset from %s!!\n",
1621 ioc->name, __func__);
1622 retval = mpt_HardResetHandler(ioc, CAN_SLEEP);
1623 mpt_free_msg_frame(ioc, mf);
1624 }
1625
1626 retval = (retval == 0) ? 0 : FAILED;
1627 mutex_unlock(&ioc->taskmgmt_cmds.mutex);
1628 return retval;
1da177e4 1629}
1ba9ab2e 1630EXPORT_SYMBOL(mptscsih_IssueTaskMgmt);
1da177e4 1631
d66c7a0f
CH
1632static int
1633mptscsih_get_tm_timeout(MPT_ADAPTER *ioc)
1634{
1635 switch (ioc->bus_type) {
1636 case FC:
1637 return 40;
1638 case SAS:
d66c7a0f
CH
1639 case SPI:
1640 default:
22ab019b 1641 return 10;
d66c7a0f
CH
1642 }
1643}
1644
1da177e4
LT
1645/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1646/**
1647 * mptscsih_abort - Abort linux scsi_cmnd routine, new_eh variant
1648 * @SCpnt: Pointer to scsi_cmnd structure, IO to be aborted
1649 *
1650 * (linux scsi_host_template.eh_abort_handler routine)
1651 *
1652 * Returns SUCCESS or FAILED.
cd2c6191 1653 **/
0d0c7974 1654int
1da177e4
LT
1655mptscsih_abort(struct scsi_cmnd * SCpnt)
1656{
1657 MPT_SCSI_HOST *hd;
1da177e4
LT
1658 MPT_FRAME_HDR *mf;
1659 u32 ctx2abort;
1660 int scpnt_idx;
466544d8 1661 int retval;
958d4a32 1662 VirtDevice *vdevice;
3dc0b03f 1663 ulong sn = SCpnt->serial_number;
958d4a32 1664 MPT_ADAPTER *ioc;
1da177e4
LT
1665
1666 /* If we can't locate our host adapter structure, return FAILED status.
1667 */
e7eae9f6 1668 if ((hd = shost_priv(SCpnt->device->host)) == NULL) {
1da177e4
LT
1669 SCpnt->result = DID_RESET << 16;
1670 SCpnt->scsi_done(SCpnt);
29dd3609
EM
1671 printk(KERN_ERR MYNAM ": task abort: "
1672 "can't locate host! (sc=%p)\n", SCpnt);
1da177e4
LT
1673 return FAILED;
1674 }
1675
958d4a32
EM
1676 ioc = hd->ioc;
1677 printk(MYIOC_s_INFO_FMT "attempting task abort! (sc=%p)\n",
1678 ioc->name, SCpnt);
1679 scsi_print_command(SCpnt);
1680
1681 vdevice = SCpnt->device->hostdata;
1682 if (!vdevice || !vdevice->vtarget) {
29dd3609
EM
1683 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1684 "task abort: device has been deleted (sc=%p)\n",
1685 ioc->name, SCpnt));
958d4a32
EM
1686 SCpnt->result = DID_NO_CONNECT << 16;
1687 SCpnt->scsi_done(SCpnt);
1688 retval = 0;
1689 goto out;
1690 }
1691
cc78d30a
EM
1692 /* Task aborts are not supported for hidden raid components.
1693 */
1694 if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
29dd3609
EM
1695 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1696 "task abort: hidden raid component (sc=%p)\n",
1697 ioc->name, SCpnt));
cc78d30a
EM
1698 SCpnt->result = DID_RESET << 16;
1699 retval = FAILED;
1700 goto out;
1701 }
1702
1da177e4
LT
1703 /* Find this command
1704 */
e8206381 1705 if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(ioc, SCpnt)) < 0) {
466544d8 1706 /* Cmd not found in ScsiLookup.
1da177e4
LT
1707 * Do OS callback.
1708 */
1709 SCpnt->result = DID_RESET << 16;
29dd3609 1710 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "task abort: "
958d4a32
EM
1711 "Command not in the active list! (sc=%p)\n", ioc->name,
1712 SCpnt));
1713 retval = 0;
1714 goto out;
1da177e4
LT
1715 }
1716
2f187862
KD
1717 if (ioc->timeouts < -1)
1718 ioc->timeouts++;
65207fed 1719
2f4c782c
KD
1720 if (mpt_fwfault_debug)
1721 mpt_halt_firmware(ioc);
1722
1da177e4
LT
1723 /* Most important! Set TaskMsgContext to SCpnt's MsgContext!
1724 * (the IO to be ABORT'd)
1725 *
1726 * NOTE: Since we do not byteswap MsgContext, we do not
1727 * swap it here either. It is an opaque cookie to
1728 * the controller, so it does not matter. -DaveM
1729 */
e80b002b 1730 mf = MPT_INDEX_2_MFPTR(ioc, scpnt_idx);
1da177e4 1731 ctx2abort = mf->u.frame.hwhdr.msgctxu.MsgContext;
1ba9ab2e
KD
1732 retval = mptscsih_IssueTaskMgmt(hd,
1733 MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
1734 vdevice->vtarget->channel,
1735 vdevice->vtarget->id, vdevice->lun,
1736 ctx2abort, mptscsih_get_tm_timeout(ioc));
1da177e4 1737
e8206381 1738 if (SCPNT_TO_LOOKUP_IDX(ioc, SCpnt) == scpnt_idx &&
2f187862
KD
1739 SCpnt->serial_number == sn) {
1740 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1741 "task abort: command still in active list! (sc=%p)\n",
1742 ioc->name, SCpnt));
3dc0b03f 1743 retval = FAILED;
2f187862
KD
1744 } else {
1745 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1746 "task abort: command cleared from active list! (sc=%p)\n",
1747 ioc->name, SCpnt));
1748 retval = SUCCESS;
1749 }
3dc0b03f 1750
958d4a32
EM
1751 out:
1752 printk(MYIOC_s_INFO_FMT "task abort: %s (sc=%p)\n",
2f187862 1753 ioc->name, ((retval == SUCCESS) ? "SUCCESS" : "FAILED"), SCpnt);
1da177e4 1754
2f187862 1755 return retval;
1da177e4
LT
1756}
1757
1758/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1759/**
1760 * mptscsih_dev_reset - Perform a SCSI TARGET_RESET! new_eh variant
1761 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1762 *
1763 * (linux scsi_host_template.eh_dev_reset_handler routine)
1764 *
1765 * Returns SUCCESS or FAILED.
cd2c6191 1766 **/
0d0c7974 1767int
1da177e4
LT
1768mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
1769{
1770 MPT_SCSI_HOST *hd;
466544d8 1771 int retval;
958d4a32
EM
1772 VirtDevice *vdevice;
1773 MPT_ADAPTER *ioc;
1da177e4
LT
1774
1775 /* If we can't locate our host adapter structure, return FAILED status.
1776 */
e7eae9f6 1777 if ((hd = shost_priv(SCpnt->device->host)) == NULL){
29dd3609
EM
1778 printk(KERN_ERR MYNAM ": target reset: "
1779 "Can't locate host! (sc=%p)\n", SCpnt);
1da177e4
LT
1780 return FAILED;
1781 }
1782
958d4a32
EM
1783 ioc = hd->ioc;
1784 printk(MYIOC_s_INFO_FMT "attempting target reset! (sc=%p)\n",
1785 ioc->name, SCpnt);
466544d8 1786 scsi_print_command(SCpnt);
1da177e4 1787
958d4a32
EM
1788 vdevice = SCpnt->device->hostdata;
1789 if (!vdevice || !vdevice->vtarget) {
2f187862 1790 retval = SUCCESS;
958d4a32
EM
1791 goto out;
1792 }
1793
cc78d30a
EM
1794 /* Target reset to hidden raid component is not supported
1795 */
1796 if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
1797 retval = FAILED;
1798 goto out;
1799 }
1800
1ba9ab2e
KD
1801 retval = mptscsih_IssueTaskMgmt(hd,
1802 MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
1803 vdevice->vtarget->channel,
1804 vdevice->vtarget->id, 0, 0,
1805 mptscsih_get_tm_timeout(ioc));
466544d8 1806
958d4a32
EM
1807 out:
1808 printk (MYIOC_s_INFO_FMT "target reset: %s (sc=%p)\n",
1809 ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
466544d8
MED
1810
1811 if (retval == 0)
1812 return SUCCESS;
cd2c6191
EM
1813 else
1814 return FAILED;
1da177e4
LT
1815}
1816
cd2c6191 1817
1da177e4
LT
1818/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1819/**
1820 * mptscsih_bus_reset - Perform a SCSI BUS_RESET! new_eh variant
1821 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1822 *
1823 * (linux scsi_host_template.eh_bus_reset_handler routine)
1824 *
1825 * Returns SUCCESS or FAILED.
cd2c6191 1826 **/
0d0c7974 1827int
1da177e4
LT
1828mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
1829{
1830 MPT_SCSI_HOST *hd;
466544d8 1831 int retval;
a69de507 1832 VirtDevice *vdevice;
958d4a32 1833 MPT_ADAPTER *ioc;
1da177e4
LT
1834
1835 /* If we can't locate our host adapter structure, return FAILED status.
1836 */
e7eae9f6 1837 if ((hd = shost_priv(SCpnt->device->host)) == NULL){
29dd3609
EM
1838 printk(KERN_ERR MYNAM ": bus reset: "
1839 "Can't locate host! (sc=%p)\n", SCpnt);
1da177e4
LT
1840 return FAILED;
1841 }
1842
958d4a32
EM
1843 ioc = hd->ioc;
1844 printk(MYIOC_s_INFO_FMT "attempting bus reset! (sc=%p)\n",
1845 ioc->name, SCpnt);
466544d8 1846 scsi_print_command(SCpnt);
1da177e4 1847
2f187862
KD
1848 if (ioc->timeouts < -1)
1849 ioc->timeouts++;
1da177e4 1850
a69de507 1851 vdevice = SCpnt->device->hostdata;
2f187862
KD
1852 if (!vdevice || !vdevice->vtarget)
1853 return SUCCESS;
1ba9ab2e
KD
1854 retval = mptscsih_IssueTaskMgmt(hd,
1855 MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
1856 vdevice->vtarget->channel, 0, 0, 0,
1857 mptscsih_get_tm_timeout(ioc));
1da177e4 1858
958d4a32
EM
1859 printk(MYIOC_s_INFO_FMT "bus reset: %s (sc=%p)\n",
1860 ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
466544d8
MED
1861
1862 if (retval == 0)
1863 return SUCCESS;
cd2c6191
EM
1864 else
1865 return FAILED;
1da177e4
LT
1866}
1867
1868/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1869/**
d9489fb6 1870 * mptscsih_host_reset - Perform a SCSI host adapter RESET (new_eh variant)
1da177e4
LT
1871 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1872 *
1873 * (linux scsi_host_template.eh_host_reset_handler routine)
1874 *
1875 * Returns SUCCESS or FAILED.
1876 */
0d0c7974 1877int
1da177e4
LT
1878mptscsih_host_reset(struct scsi_cmnd *SCpnt)
1879{
1880 MPT_SCSI_HOST * hd;
2f187862 1881 int status = SUCCESS;
958d4a32 1882 MPT_ADAPTER *ioc;
2f187862 1883 int retval;
1da177e4
LT
1884
1885 /* If we can't locate the host to reset, then we failed. */
e7eae9f6 1886 if ((hd = shost_priv(SCpnt->device->host)) == NULL){
29dd3609
EM
1887 printk(KERN_ERR MYNAM ": host reset: "
1888 "Can't locate host! (sc=%p)\n", SCpnt);
1da177e4
LT
1889 return FAILED;
1890 }
1891
a6da74cb
JB
1892 /* make sure we have no outstanding commands at this stage */
1893 mptscsih_flush_running_cmds(hd);
1894
958d4a32
EM
1895 ioc = hd->ioc;
1896 printk(MYIOC_s_INFO_FMT "attempting host reset! (sc=%p)\n",
1897 ioc->name, SCpnt);
1da177e4
LT
1898
1899 /* If our attempts to reset the host failed, then return a failed
1900 * status. The host will be taken off line by the SCSI mid-layer.
1901 */
2f187862
KD
1902 retval = mpt_HardResetHandler(ioc, CAN_SLEEP);
1903 if (retval < 0)
1904 status = FAILED;
1905 else
1906 status = SUCCESS;
1da177e4 1907
958d4a32
EM
1908 printk(MYIOC_s_INFO_FMT "host reset: %s (sc=%p)\n",
1909 ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
1da177e4 1910
2f187862 1911 return status;
1da177e4
LT
1912}
1913
1da177e4 1914static int
1ba9ab2e
KD
1915mptscsih_taskmgmt_reply(MPT_ADAPTER *ioc, u8 type,
1916 SCSITaskMgmtReply_t *pScsiTmReply)
1da177e4 1917{
1ba9ab2e
KD
1918 u16 iocstatus;
1919 u32 termination_count;
1920 int retval;
1da177e4 1921
1ba9ab2e
KD
1922 if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_RF_VALID)) {
1923 retval = FAILED;
1924 goto out;
1925 }
1da177e4 1926
1ba9ab2e 1927 DBG_DUMP_TM_REPLY_FRAME(ioc, (u32 *)pScsiTmReply);
1da177e4 1928
1ba9ab2e
KD
1929 iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
1930 termination_count = le32_to_cpu(pScsiTmReply->TerminationCount);
1da177e4 1931
1ba9ab2e
KD
1932 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1933 "TaskMgmt fw_channel = %d, fw_id = %d, task_type = 0x%02X,\n"
1934 "\tiocstatus = 0x%04X, loginfo = 0x%08X, response_code = 0x%02X,\n"
1935 "\tterm_cmnds = %d\n", ioc->name, pScsiTmReply->Bus,
1936 pScsiTmReply->TargetID, type, le16_to_cpu(pScsiTmReply->IOCStatus),
1937 le32_to_cpu(pScsiTmReply->IOCLogInfo), pScsiTmReply->ResponseCode,
1938 termination_count));
1939
1940 if (ioc->facts.MsgVersion >= MPI_VERSION_01_05 &&
1941 pScsiTmReply->ResponseCode)
1942 mptscsih_taskmgmt_response_code(ioc,
1943 pScsiTmReply->ResponseCode);
1da177e4 1944
1ba9ab2e
KD
1945 if (iocstatus == MPI_IOCSTATUS_SUCCESS) {
1946 retval = 0;
1947 goto out;
1948 }
1949
1950 retval = FAILED;
1951 if (type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) {
1952 if (termination_count == 1)
1953 retval = 0;
1954 goto out;
1955 }
1956
1957 if (iocstatus == MPI_IOCSTATUS_SCSI_TASK_TERMINATED ||
1958 iocstatus == MPI_IOCSTATUS_SCSI_IOC_TERMINATED)
1959 retval = 0;
1960
1961 out:
1962 return retval;
1da177e4
LT
1963}
1964
9f63bb73 1965/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
e7deff33 1966void
9f63bb73
ME
1967mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code)
1968{
1969 char *desc;
1970
1971 switch (response_code) {
1972 case MPI_SCSITASKMGMT_RSP_TM_COMPLETE:
1973 desc = "The task completed.";
1974 break;
1975 case MPI_SCSITASKMGMT_RSP_INVALID_FRAME:
1976 desc = "The IOC received an invalid frame status.";
1977 break;
1978 case MPI_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED:
1979 desc = "The task type is not supported.";
1980 break;
1981 case MPI_SCSITASKMGMT_RSP_TM_FAILED:
1982 desc = "The requested task failed.";
1983 break;
1984 case MPI_SCSITASKMGMT_RSP_TM_SUCCEEDED:
1985 desc = "The task completed successfully.";
1986 break;
1987 case MPI_SCSITASKMGMT_RSP_TM_INVALID_LUN:
1988 desc = "The LUN request is invalid.";
1989 break;
1990 case MPI_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC:
1991 desc = "The task is in the IOC queue and has not been sent to target.";
1992 break;
1993 default:
1994 desc = "unknown";
1995 break;
1996 }
1997 printk(MYIOC_s_INFO_FMT "Response Code(0x%08x): F/W: %s\n",
1998 ioc->name, response_code, desc);
1999}
e7deff33 2000EXPORT_SYMBOL(mptscsih_taskmgmt_response_code);
9f63bb73 2001
1da177e4
LT
2002/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2003/**
2004 * mptscsih_taskmgmt_complete - Registered with Fusion MPT base driver
2005 * @ioc: Pointer to MPT_ADAPTER structure
2006 * @mf: Pointer to SCSI task mgmt request frame
2007 * @mr: Pointer to SCSI task mgmt reply frame
2008 *
2009 * This routine is called from mptbase.c::mpt_interrupt() at the completion
2010 * of any SCSI task management request.
2011 * This routine is registered with the MPT (base) driver at driver
2012 * load/init time via the mpt_register() API call.
2013 *
2014 * Returns 1 indicating alloc'd request frame ptr should be freed.
cd2c6191 2015 **/
0d0c7974 2016int
1ba9ab2e
KD
2017mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf,
2018 MPT_FRAME_HDR *mr)
1da177e4 2019{
1ba9ab2e
KD
2020 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2021 "TaskMgmt completed (mf=%p, mr=%p)\n", ioc->name, mf, mr));
cd2c6191 2022
1ba9ab2e 2023 ioc->taskmgmt_cmds.status |= MPT_MGMT_STATUS_COMMAND_GOOD;
6757d6b4 2024
1ba9ab2e 2025 if (!mr)
cd2c6191 2026 goto out;
1da177e4 2027
1ba9ab2e
KD
2028 ioc->taskmgmt_cmds.status |= MPT_MGMT_STATUS_RF_VALID;
2029 memcpy(ioc->taskmgmt_cmds.reply, mr,
2030 min(MPT_DEFAULT_FRAME_SIZE, 4 * mr->u.reply.MsgLength));
cd2c6191 2031 out:
1ba9ab2e
KD
2032 if (ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_PENDING) {
2033 mpt_clear_taskmgmt_in_progress_flag(ioc);
2034 ioc->taskmgmt_cmds.status &= ~MPT_MGMT_STATUS_PENDING;
2035 complete(&ioc->taskmgmt_cmds.done);
2036 return 1;
2037 }
2038 return 0;
1da177e4
LT
2039}
2040
2041/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2042/*
2043 * This is anyones guess quite frankly.
2044 */
0d0c7974 2045int
1da177e4
LT
2046mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev,
2047 sector_t capacity, int geom[])
2048{
2049 int heads;
2050 int sectors;
2051 sector_t cylinders;
2052 ulong dummy;
2053
2054 heads = 64;
2055 sectors = 32;
2056
2057 dummy = heads * sectors;
2058 cylinders = capacity;
2059 sector_div(cylinders,dummy);
2060
2061 /*
2062 * Handle extended translation size for logical drives
2063 * > 1Gb
2064 */
2065 if ((ulong)capacity >= 0x200000) {
2066 heads = 255;
2067 sectors = 63;
2068 dummy = heads * sectors;
2069 cylinders = capacity;
2070 sector_div(cylinders,dummy);
2071 }
2072
2073 /* return result */
2074 geom[0] = heads;
2075 geom[1] = sectors;
2076 geom[2] = cylinders;
2077
1da177e4
LT
2078 return 0;
2079}
2080
f44e5461
ME
2081/* Search IOC page 3 to determine if this is hidden physical disk
2082 *
2083 */
2084int
793955f5 2085mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id)
f44e5461 2086{
b506ade9 2087 struct inactive_raid_component_info *component_info;
a7938b0b
KD
2088 int i, j;
2089 RaidPhysDiskPage1_t *phys_disk;
793955f5 2090 int rc = 0;
a7938b0b 2091 int num_paths;
f44e5461 2092
793955f5
EM
2093 if (!ioc->raid_data.pIocPg3)
2094 goto out;
f44e5461 2095 for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
793955f5
EM
2096 if ((id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) &&
2097 (channel == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskBus)) {
2098 rc = 1;
2099 goto out;
2100 }
c92f222e
JB
2101 }
2102
a7938b0b
KD
2103 if (ioc->bus_type != SAS)
2104 goto out;
2105
2106 /*
2107 * Check if dual path
2108 */
2109 for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
2110 num_paths = mpt_raid_phys_disk_get_num_paths(ioc,
2111 ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum);
2112 if (num_paths < 2)
2113 continue;
2114 phys_disk = kzalloc(offsetof(RaidPhysDiskPage1_t, Path) +
2115 (num_paths * sizeof(RAID_PHYS_DISK1_PATH)), GFP_KERNEL);
2116 if (!phys_disk)
2117 continue;
2118 if ((mpt_raid_phys_disk_pg1(ioc,
2119 ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum,
2120 phys_disk))) {
2121 kfree(phys_disk);
2122 continue;
2123 }
2124 for (j = 0; j < num_paths; j++) {
2125 if ((phys_disk->Path[j].Flags &
2126 MPI_RAID_PHYSDISK1_FLAG_INVALID))
2127 continue;
2128 if ((phys_disk->Path[j].Flags &
2129 MPI_RAID_PHYSDISK1_FLAG_BROKEN))
2130 continue;
2131 if ((id == phys_disk->Path[j].PhysDiskID) &&
2132 (channel == phys_disk->Path[j].PhysDiskBus)) {
2133 rc = 1;
2134 kfree(phys_disk);
2135 goto out;
2136 }
2137 }
2138 kfree(phys_disk);
2139 }
2140
2141
b506ade9
EM
2142 /*
2143 * Check inactive list for matching phys disks
2144 */
2145 if (list_empty(&ioc->raid_data.inactive_list))
2146 goto out;
2147
ed5f606f 2148 mutex_lock(&ioc->raid_data.inactive_list_mutex);
b506ade9
EM
2149 list_for_each_entry(component_info, &ioc->raid_data.inactive_list,
2150 list) {
2151 if ((component_info->d.PhysDiskID == id) &&
2152 (component_info->d.PhysDiskBus == channel))
2153 rc = 1;
2154 }
ed5f606f 2155 mutex_unlock(&ioc->raid_data.inactive_list_mutex);
b506ade9 2156
793955f5
EM
2157 out:
2158 return rc;
c7c82987 2159}
793955f5 2160EXPORT_SYMBOL(mptscsih_is_phys_disk);
c7c82987 2161
793955f5
EM
2162u8
2163mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id)
1da177e4 2164{
b506ade9 2165 struct inactive_raid_component_info *component_info;
a7938b0b
KD
2166 int i, j;
2167 RaidPhysDiskPage1_t *phys_disk;
793955f5 2168 int rc = -ENXIO;
a7938b0b 2169 int num_paths;
c92f222e 2170
793955f5
EM
2171 if (!ioc->raid_data.pIocPg3)
2172 goto out;
2173 for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
2174 if ((id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) &&
2175 (channel == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskBus)) {
2176 rc = ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum;
2177 goto out;
1da177e4 2178 }
1da177e4 2179 }
1da177e4 2180
a7938b0b
KD
2181 if (ioc->bus_type != SAS)
2182 goto out;
2183
2184 /*
2185 * Check if dual path
2186 */
2187 for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
2188 num_paths = mpt_raid_phys_disk_get_num_paths(ioc,
2189 ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum);
2190 if (num_paths < 2)
2191 continue;
2192 phys_disk = kzalloc(offsetof(RaidPhysDiskPage1_t, Path) +
2193 (num_paths * sizeof(RAID_PHYS_DISK1_PATH)), GFP_KERNEL);
2194 if (!phys_disk)
2195 continue;
2196 if ((mpt_raid_phys_disk_pg1(ioc,
2197 ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum,
2198 phys_disk))) {
2199 kfree(phys_disk);
2200 continue;
2201 }
2202 for (j = 0; j < num_paths; j++) {
2203 if ((phys_disk->Path[j].Flags &
2204 MPI_RAID_PHYSDISK1_FLAG_INVALID))
2205 continue;
2206 if ((phys_disk->Path[j].Flags &
2207 MPI_RAID_PHYSDISK1_FLAG_BROKEN))
2208 continue;
2209 if ((id == phys_disk->Path[j].PhysDiskID) &&
2210 (channel == phys_disk->Path[j].PhysDiskBus)) {
2211 rc = phys_disk->PhysDiskNum;
2212 kfree(phys_disk);
2213 goto out;
2214 }
2215 }
2216 kfree(phys_disk);
2217 }
2218
b506ade9
EM
2219 /*
2220 * Check inactive list for matching phys disks
2221 */
2222 if (list_empty(&ioc->raid_data.inactive_list))
2223 goto out;
2224
ed5f606f 2225 mutex_lock(&ioc->raid_data.inactive_list_mutex);
b506ade9
EM
2226 list_for_each_entry(component_info, &ioc->raid_data.inactive_list,
2227 list) {
2228 if ((component_info->d.PhysDiskID == id) &&
2229 (component_info->d.PhysDiskBus == channel))
2230 rc = component_info->d.PhysDiskNum;
2231 }
ed5f606f 2232 mutex_unlock(&ioc->raid_data.inactive_list_mutex);
b506ade9 2233
793955f5
EM
2234 out:
2235 return rc;
c7c82987 2236}
793955f5 2237EXPORT_SYMBOL(mptscsih_raid_id_to_num);
1da177e4 2238
c7c82987
MED
2239/*
2240 * OS entry point to allow for host driver to free allocated memory
2241 * Called if no device present or device being unloaded
2242 */
2243void
2244mptscsih_slave_destroy(struct scsi_device *sdev)
2245{
2246 struct Scsi_Host *host = sdev->host;
e7eae9f6 2247 MPT_SCSI_HOST *hd = shost_priv(host);
c7c82987
MED
2248 VirtTarget *vtarget;
2249 VirtDevice *vdevice;
2250 struct scsi_target *starget;
2251
2252 starget = scsi_target(sdev);
2253 vtarget = starget->hostdata;
2254 vdevice = sdev->hostdata;
2255
2256 mptscsih_search_running_cmds(hd, vdevice);
c7c82987 2257 vtarget->num_luns--;
c7c82987
MED
2258 mptscsih_synchronize_cache(hd, vdevice);
2259 kfree(vdevice);
2260 sdev->hostdata = NULL;
1da177e4
LT
2261}
2262
6e3815ba
MED
2263/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2264/*
2265 * mptscsih_change_queue_depth - This function will set a devices queue depth
2266 * @sdev: per scsi_device pointer
2267 * @qdepth: requested queue depth
2268 *
2269 * Adding support for new 'change_queue_depth' api.
2270*/
2271int
2272mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
1da177e4 2273{
e7eae9f6 2274 MPT_SCSI_HOST *hd = shost_priv(sdev->host);
c7c82987
MED
2275 VirtTarget *vtarget;
2276 struct scsi_target *starget;
2277 int max_depth;
2278 int tagged;
e80b002b 2279 MPT_ADAPTER *ioc = hd->ioc;
1da177e4 2280
c7c82987
MED
2281 starget = scsi_target(sdev);
2282 vtarget = starget->hostdata;
6e3815ba 2283
e80b002b 2284 if (ioc->bus_type == SPI) {
c92f222e 2285 if (!(vtarget->tflags & MPT_TARGET_FLAGS_Q_YES))
1da177e4 2286 max_depth = 1;
c92f222e
JB
2287 else if (sdev->type == TYPE_DISK &&
2288 vtarget->minSyncFactor <= MPT_ULTRA160)
2289 max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
2290 else
2291 max_depth = MPT_SCSI_CMD_PER_DEV_LOW;
1da177e4
LT
2292 } else
2293 max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
2294
2295 if (qdepth > max_depth)
2296 qdepth = max_depth;
2297 if (qdepth == 1)
2298 tagged = 0;
2299 else
2300 tagged = MSG_SIMPLE_TAG;
2301
6e3815ba
MED
2302 scsi_adjust_queue_depth(sdev, tagged, qdepth);
2303 return sdev->queue_depth;
1da177e4
LT
2304}
2305
1da177e4
LT
2306/*
2307 * OS entry point to adjust the queue_depths on a per-device basis.
2308 * Called once per device the bus scan. Use it to force the queue_depth
2309 * member to 1 if a device does not support Q tags.
2310 * Return non-zero if fails.
2311 */
0d0c7974 2312int
c7c82987 2313mptscsih_slave_configure(struct scsi_device *sdev)
1da177e4 2314{
c7c82987
MED
2315 struct Scsi_Host *sh = sdev->host;
2316 VirtTarget *vtarget;
2317 VirtDevice *vdevice;
2318 struct scsi_target *starget;
e7eae9f6 2319 MPT_SCSI_HOST *hd = shost_priv(sh);
e80b002b 2320 MPT_ADAPTER *ioc = hd->ioc;
1da177e4 2321
c7c82987
MED
2322 starget = scsi_target(sdev);
2323 vtarget = starget->hostdata;
2324 vdevice = sdev->hostdata;
1da177e4 2325
e80b002b 2326 dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
793955f5 2327 "device @ %p, channel=%d, id=%d, lun=%d\n",
e80b002b
EM
2328 ioc->name, sdev, sdev->channel, sdev->id, sdev->lun));
2329 if (ioc->bus_type == SPI)
2330 dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
c7c82987 2331 "sdtr %d wdtr %d ppr %d inq length=%d\n",
e80b002b 2332 ioc->name, sdev->sdtr, sdev->wdtr,
c7c82987
MED
2333 sdev->ppr, sdev->inquiry_len));
2334
793955f5 2335 vdevice->configured_lun = 1;
1da177e4 2336
e80b002b 2337 dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1da177e4 2338 "Queue depth=%d, tflags=%x\n",
e80b002b 2339 ioc->name, sdev->queue_depth, vtarget->tflags));
1da177e4 2340
e80b002b
EM
2341 if (ioc->bus_type == SPI)
2342 dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
c7c82987 2343 "negoFlags=%x, maxOffset=%x, SyncFactor=%x\n",
e80b002b 2344 ioc->name, vtarget->negoFlags, vtarget->maxOffset,
c7c82987 2345 vtarget->minSyncFactor));
1da177e4 2346
2f187862 2347 mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH);
e80b002b 2348 dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1da177e4 2349 "tagged %d, simple %d, ordered %d\n",
e80b002b 2350 ioc->name,sdev->tagged_supported, sdev->simple_tags,
c7c82987 2351 sdev->ordered_tags));
1da177e4
LT
2352
2353 return 0;
2354}
2355
1da177e4
LT
2356/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2357/*
2358 * Private routines...
2359 */
2360
2361/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2362/* Utility function to copy sense data from the scsi_cmnd buffer
2363 * to the FC and SCSI target structures.
2364 *
2365 */
2366static void
0d0c7974 2367mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply)
1da177e4 2368{
a69de507 2369 VirtDevice *vdevice;
1da177e4
LT
2370 SCSIIORequest_t *pReq;
2371 u32 sense_count = le32_to_cpu(pScsiReply->SenseCount);
e80b002b 2372 MPT_ADAPTER *ioc = hd->ioc;
1da177e4
LT
2373
2374 /* Get target structure
2375 */
2376 pReq = (SCSIIORequest_t *) mf;
a69de507 2377 vdevice = sc->device->hostdata;
1da177e4
LT
2378
2379 if (sense_count) {
2380 u8 *sense_data;
2381 int req_index;
2382
2383 /* Copy the sense received into the scsi command block. */
2384 req_index = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
e80b002b 2385 sense_data = ((u8 *)ioc->sense_buf_pool + (req_index * MPT_SENSE_BUFFER_ALLOC));
1da177e4
LT
2386 memcpy(sc->sense_buffer, sense_data, SNS_LEN(sc));
2387
2388 /* Log SMART data (asc = 0x5D, non-IM case only) if required.
2389 */
e80b002b 2390 if ((ioc->events) && (ioc->eventTypes & (1 << MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE))) {
a69de507 2391 if ((sense_data[12] == 0x5D) && (vdevice->vtarget->raidVolume == 0)) {
1da177e4 2392 int idx;
1da177e4 2393
5b5ef4f6 2394 idx = ioc->eventContext % MPTCTL_EVENT_LOG_SIZE;
1da177e4
LT
2395 ioc->events[idx].event = MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE;
2396 ioc->events[idx].eventContext = ioc->eventContext;
2397
3d9780b9
DJ
2398 ioc->events[idx].data[0] = (pReq->LUN[1] << 24) |
2399 (MPI_EVENT_SCSI_DEV_STAT_RC_SMART_DATA << 16) |
2400 (sc->device->channel << 8) | sc->device->id;
1da177e4 2401
3d9780b9 2402 ioc->events[idx].data[1] = (sense_data[13] << 8) | sense_data[12];
1da177e4
LT
2403
2404 ioc->eventContext++;
e80b002b 2405 if (ioc->pcidev->vendor ==
786899b0 2406 PCI_VENDOR_ID_IBM) {
e80b002b 2407 mptscsih_issue_sep_command(ioc,
a69de507
EM
2408 vdevice->vtarget, MPI_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT);
2409 vdevice->vtarget->tflags |=
786899b0
EM
2410 MPT_TARGET_FLAGS_LED_ON;
2411 }
1da177e4
LT
2412 }
2413 }
2414 } else {
e80b002b
EM
2415 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Hmmm... SenseData len=0! (?)\n",
2416 ioc->name));
1da177e4
LT
2417 }
2418}
2419
db7051b2
KD
2420/**
2421 * mptscsih_get_scsi_lookup - retrieves scmd entry
2422 * @ioc: Pointer to MPT_ADAPTER structure
2423 * @i: index into the array
2424 *
2425 * Returns the scsi_cmd pointer
2426 */
2427struct scsi_cmnd *
2428mptscsih_get_scsi_lookup(MPT_ADAPTER *ioc, int i)
2429{
2430 unsigned long flags;
2431 struct scsi_cmnd *scmd;
2432
2433 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
2434 scmd = ioc->ScsiLookup[i];
2435 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
2436
2437 return scmd;
2438}
2439EXPORT_SYMBOL(mptscsih_get_scsi_lookup);
e8206381
EM
2440
2441/**
fc847ab4 2442 * mptscsih_getclear_scsi_lookup - retrieves and clears scmd entry from ScsiLookup[] array list
2f187862
KD
2443 * @ioc: Pointer to MPT_ADAPTER structure
2444 * @i: index into the array
2445 *
7105a387 2446 * Returns the scsi_cmd pointer
2f187862 2447 *
e8206381
EM
2448 **/
2449static struct scsi_cmnd *
2450mptscsih_getclear_scsi_lookup(MPT_ADAPTER *ioc, int i)
2451{
2452 unsigned long flags;
2453 struct scsi_cmnd *scmd;
2454
2455 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
2456 scmd = ioc->ScsiLookup[i];
2457 ioc->ScsiLookup[i] = NULL;
2458 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
2459
2460 return scmd;
2461}
2462
2463/**
2464 * mptscsih_set_scsi_lookup
2465 *
2466 * writes a scmd entry into the ScsiLookup[] array list
2467 *
2468 * @ioc: Pointer to MPT_ADAPTER structure
2469 * @i: index into the array
2470 * @scmd: scsi_cmnd pointer
2471 *
2472 **/
2473static void
2474mptscsih_set_scsi_lookup(MPT_ADAPTER *ioc, int i, struct scsi_cmnd *scmd)
2475{
2476 unsigned long flags;
1da177e4 2477
e8206381
EM
2478 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
2479 ioc->ScsiLookup[i] = scmd;
2480 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
2481}
2482
2483/**
23f9b75e 2484 * SCPNT_TO_LOOKUP_IDX - searches for a given scmd in the ScsiLookup[] array list
e8206381 2485 * @ioc: Pointer to MPT_ADAPTER structure
23f9b75e
RD
2486 * @sc: scsi_cmnd pointer
2487 */
e8206381
EM
2488static int
2489SCPNT_TO_LOOKUP_IDX(MPT_ADAPTER *ioc, struct scsi_cmnd *sc)
2490{
2491 unsigned long flags;
2492 int i, index=-1;
1da177e4 2493
e8206381
EM
2494 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
2495 for (i = 0; i < ioc->req_depth; i++) {
2496 if (ioc->ScsiLookup[i] == sc) {
2497 index = i;
2498 goto out;
1da177e4
LT
2499 }
2500 }
2501
e8206381
EM
2502 out:
2503 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
2504 return index;
1da177e4
LT
2505}
2506
2507/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
0d0c7974 2508int
1da177e4
LT
2509mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
2510{
2511 MPT_SCSI_HOST *hd;
1da177e4 2512
e7eae9f6 2513 if (ioc->sh == NULL || shost_priv(ioc->sh) == NULL)
1da177e4 2514 return 0;
1da177e4 2515
37c60f37
KD
2516 hd = shost_priv(ioc->sh);
2517 switch (reset_phase) {
2518 case MPT_IOC_SETUP_RESET:
2519 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2520 "%s: MPT_IOC_SETUP_RESET\n", ioc->name, __func__));
37c60f37
KD
2521 break;
2522 case MPT_IOC_PRE_RESET:
2523 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2524 "%s: MPT_IOC_PRE_RESET\n", ioc->name, __func__));
37c60f37
KD
2525 mptscsih_flush_running_cmds(hd);
2526 break;
2527 case MPT_IOC_POST_RESET:
2528 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2529 "%s: MPT_IOC_POST_RESET\n", ioc->name, __func__));
2530 if (ioc->internal_cmds.status & MPT_MGMT_STATUS_PENDING) {
2531 ioc->internal_cmds.status |=
2532 MPT_MGMT_STATUS_DID_IOCRESET;
2533 complete(&ioc->internal_cmds.done);
1da177e4 2534 }
37c60f37
KD
2535 break;
2536 default:
2537 break;
1da177e4 2538 }
1da177e4
LT
2539 return 1; /* currently means nothing really */
2540}
2541
2542/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
0d0c7974 2543int
1da177e4
LT
2544mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
2545{
1da177e4
LT
2546 u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
2547
37c60f37
KD
2548 devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2549 "MPT event (=%02Xh) routed to SCSI host driver!\n",
2550 ioc->name, event));
1da177e4 2551
2f187862
KD
2552 if ((event == MPI_EVENT_IOC_BUS_RESET ||
2553 event == MPI_EVENT_EXT_BUS_RESET) &&
2554 (ioc->bus_type == SPI) && (ioc->soft_resets < -1))
2555 ioc->soft_resets++;
1da177e4
LT
2556
2557 return 1; /* currently means nothing really */
2558}
2559
1da177e4
LT
2560/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2561/*
2562 * Bus Scan and Domain Validation functionality ...
2563 */
2564
2565/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2566/*
2567 * mptscsih_scandv_complete - Scan and DV callback routine registered
2568 * to Fustion MPT (base) driver.
2569 *
2570 * @ioc: Pointer to MPT_ADAPTER structure
2571 * @mf: Pointer to original MPT request frame
2572 * @mr: Pointer to MPT reply frame (NULL if TurboReply)
2573 *
2574 * This routine is called from mpt.c::mpt_interrupt() at the completion
2575 * of any SCSI IO request.
2576 * This routine is registered with the Fusion MPT (base) driver at driver
2577 * load/init time via the mpt_register() API call.
2578 *
2579 * Returns 1 indicating alloc'd request frame ptr should be freed.
2580 *
2581 * Remark: Sets a completion code and (possibly) saves sense data
2582 * in the IOC member localReply structure.
2583 * Used ONLY for DV and other internal commands.
2584 */
0d0c7974 2585int
37c60f37
KD
2586mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req,
2587 MPT_FRAME_HDR *reply)
1da177e4 2588{
1da177e4 2589 SCSIIORequest_t *pReq;
37c60f37
KD
2590 SCSIIOReply_t *pReply;
2591 u8 cmd;
1da177e4 2592 u16 req_idx;
37c60f37
KD
2593 u8 *sense_data;
2594 int sz;
1da177e4 2595
37c60f37
KD
2596 ioc->internal_cmds.status |= MPT_MGMT_STATUS_COMMAND_GOOD;
2597 ioc->internal_cmds.completion_code = MPT_SCANDV_GOOD;
2598 if (!reply)
2599 goto out;
1da177e4 2600
37c60f37
KD
2601 pReply = (SCSIIOReply_t *) reply;
2602 pReq = (SCSIIORequest_t *) req;
2603 ioc->internal_cmds.completion_code =
2604 mptscsih_get_completion_code(ioc, req, reply);
2605 ioc->internal_cmds.status |= MPT_MGMT_STATUS_RF_VALID;
2606 memcpy(ioc->internal_cmds.reply, reply,
2607 min(MPT_DEFAULT_FRAME_SIZE, 4 * reply->u.reply.MsgLength));
2608 cmd = reply->u.hdr.Function;
2609 if (((cmd == MPI_FUNCTION_SCSI_IO_REQUEST) ||
2610 (cmd == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) &&
2611 (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID)) {
2612 req_idx = le16_to_cpu(req->u.frame.hwhdr.msgctxu.fld.req_idx);
2613 sense_data = ((u8 *)ioc->sense_buf_pool +
2614 (req_idx * MPT_SENSE_BUFFER_ALLOC));
2615 sz = min_t(int, pReq->SenseBufferLength,
2616 MPT_SENSE_BUFFER_ALLOC);
2617 memcpy(ioc->internal_cmds.sense, sense_data, sz);
1da177e4 2618 }
37c60f37
KD
2619 out:
2620 if (!(ioc->internal_cmds.status & MPT_MGMT_STATUS_PENDING))
2621 return 0;
2622 ioc->internal_cmds.status &= ~MPT_MGMT_STATUS_PENDING;
2623 complete(&ioc->internal_cmds.done);
1da177e4
LT
2624 return 1;
2625}
2626
1da177e4 2627
37c60f37
KD
2628/**
2629 * mptscsih_get_completion_code -
2630 * @ioc: Pointer to MPT_ADAPTER structure
9cf46a35
RD
2631 * @req: Pointer to original MPT request frame
2632 * @reply: Pointer to MPT reply frame (NULL if TurboReply)
37c60f37
KD
2633 *
2634 **/
2635static int
2636mptscsih_get_completion_code(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req,
2637 MPT_FRAME_HDR *reply)
2638{
2639 SCSIIOReply_t *pReply;
2640 MpiRaidActionReply_t *pr;
2641 u8 scsi_status;
2642 u16 status;
2643 int completion_code;
2644
2645 pReply = (SCSIIOReply_t *)reply;
2646 status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
2647 scsi_status = pReply->SCSIStatus;
2648
2649 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2650 "IOCStatus=%04xh, SCSIState=%02xh, SCSIStatus=%02xh,"
2651 "IOCLogInfo=%08xh\n", ioc->name, status, pReply->SCSIState,
2652 scsi_status, le32_to_cpu(pReply->IOCLogInfo)));
2653
2654 switch (status) {
2655
2656 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
2657 completion_code = MPT_SCANDV_SELECTION_TIMEOUT;
2658 break;
2659
2660 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
2661 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
2662 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
2663 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
2664 completion_code = MPT_SCANDV_DID_RESET;
2665 break;
2666
2667 case MPI_IOCSTATUS_BUSY:
2668 case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES:
2669 completion_code = MPT_SCANDV_BUSY;
2670 break;
2671
2672 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
2673 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
2674 case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */
2675 if (pReply->Function == MPI_FUNCTION_CONFIG) {
2676 completion_code = MPT_SCANDV_GOOD;
2677 } else if (pReply->Function == MPI_FUNCTION_RAID_ACTION) {
2678 pr = (MpiRaidActionReply_t *)reply;
2679 if (le16_to_cpu(pr->ActionStatus) ==
2680 MPI_RAID_ACTION_ASTATUS_SUCCESS)
2681 completion_code = MPT_SCANDV_GOOD;
2682 else
2683 completion_code = MPT_SCANDV_SOME_ERROR;
2684 } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID)
2685 completion_code = MPT_SCANDV_SENSE;
2686 else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_FAILED) {
2687 if (req->u.scsireq.CDB[0] == INQUIRY)
2688 completion_code = MPT_SCANDV_ISSUE_SENSE;
2689 else
2690 completion_code = MPT_SCANDV_DID_RESET;
2691 } else if (pReply->SCSIState & MPI_SCSI_STATE_NO_SCSI_STATUS)
2692 completion_code = MPT_SCANDV_DID_RESET;
2693 else if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
2694 completion_code = MPT_SCANDV_DID_RESET;
2695 else if (scsi_status == MPI_SCSI_STATUS_BUSY)
2696 completion_code = MPT_SCANDV_BUSY;
2697 else
2698 completion_code = MPT_SCANDV_GOOD;
2699 break;
2700
2701 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
2702 if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
2703 completion_code = MPT_SCANDV_DID_RESET;
2704 else
2705 completion_code = MPT_SCANDV_SOME_ERROR;
2706 break;
2707 default:
2708 completion_code = MPT_SCANDV_SOME_ERROR;
2709 break;
2710
2711 } /* switch(status) */
2712
2713 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2714 " completionCode set to %08xh\n", ioc->name, completion_code));
2715 return completion_code;
2716}
1da177e4
LT
2717
2718/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2719/**
2720 * mptscsih_do_cmd - Do internal command.
2721 * @hd: MPT_SCSI_HOST pointer
2722 * @io: INTERNAL_CMD pointer.
2723 *
2724 * Issue the specified internally generated command and do command
2725 * specific cleanup. For bus scan / DV only.
2726 * NOTES: If command is Inquiry and status is good,
2727 * initialize a target structure, save the data
2728 *
2729 * Remark: Single threaded access only.
2730 *
2731 * Return:
2732 * < 0 if an illegal command or no resources
2733 *
2734 * 0 if good
2735 *
2736 * > 0 if command complete but some type of completion error.
2737 */
2738static int
2739mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
2740{
2741 MPT_FRAME_HDR *mf;
2742 SCSIIORequest_t *pScsiReq;
1da177e4 2743 int my_idx, ii, dir;
37c60f37 2744 int timeout;
1da177e4
LT
2745 char cmdLen;
2746 char CDB[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
37c60f37
KD
2747 u8 cmd = io->cmd;
2748 MPT_ADAPTER *ioc = hd->ioc;
2749 int ret = 0;
2750 unsigned long timeleft;
2751 unsigned long flags;
1da177e4 2752
1ba9ab2e
KD
2753 /* don't send internal command during diag reset */
2754 spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
2755 if (ioc->ioc_reset_in_progress) {
2756 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
2757 dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2758 "%s: busy with host reset\n", ioc->name, __func__));
2759 return MPT_SCANDV_BUSY;
2760 }
2761 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
2762
37c60f37 2763 mutex_lock(&ioc->internal_cmds.mutex);
1da177e4
LT
2764
2765 /* Set command specific information
2766 */
2767 switch (cmd) {
2768 case INQUIRY:
2769 cmdLen = 6;
2770 dir = MPI_SCSIIO_CONTROL_READ;
2771 CDB[0] = cmd;
2772 CDB[4] = io->size;
37c60f37 2773 timeout = 10;
1da177e4
LT
2774 break;
2775
2776 case TEST_UNIT_READY:
2777 cmdLen = 6;
2778 dir = MPI_SCSIIO_CONTROL_READ;
37c60f37 2779 timeout = 10;
1da177e4
LT
2780 break;
2781
2782 case START_STOP:
2783 cmdLen = 6;
2784 dir = MPI_SCSIIO_CONTROL_READ;
2785 CDB[0] = cmd;
2786 CDB[4] = 1; /*Spin up the disk */
37c60f37 2787 timeout = 15;
1da177e4
LT
2788 break;
2789
2790 case REQUEST_SENSE:
2791 cmdLen = 6;
2792 CDB[0] = cmd;
2793 CDB[4] = io->size;
2794 dir = MPI_SCSIIO_CONTROL_READ;
37c60f37 2795 timeout = 10;
1da177e4
LT
2796 break;
2797
2798 case READ_BUFFER:
2799 cmdLen = 10;
2800 dir = MPI_SCSIIO_CONTROL_READ;
2801 CDB[0] = cmd;
2802 if (io->flags & MPT_ICFLAG_ECHO) {
2803 CDB[1] = 0x0A;
2804 } else {
2805 CDB[1] = 0x02;
2806 }
2807
2808 if (io->flags & MPT_ICFLAG_BUF_CAP) {
2809 CDB[1] |= 0x01;
2810 }
2811 CDB[6] = (io->size >> 16) & 0xFF;
2812 CDB[7] = (io->size >> 8) & 0xFF;
2813 CDB[8] = io->size & 0xFF;
37c60f37 2814 timeout = 10;
1da177e4
LT
2815 break;
2816
2817 case WRITE_BUFFER:
2818 cmdLen = 10;
2819 dir = MPI_SCSIIO_CONTROL_WRITE;
2820 CDB[0] = cmd;
2821 if (io->flags & MPT_ICFLAG_ECHO) {
2822 CDB[1] = 0x0A;
2823 } else {
2824 CDB[1] = 0x02;
2825 }
2826 CDB[6] = (io->size >> 16) & 0xFF;
2827 CDB[7] = (io->size >> 8) & 0xFF;
2828 CDB[8] = io->size & 0xFF;
37c60f37 2829 timeout = 10;
1da177e4
LT
2830 break;
2831
2832 case RESERVE:
2833 cmdLen = 6;
2834 dir = MPI_SCSIIO_CONTROL_READ;
2835 CDB[0] = cmd;
37c60f37 2836 timeout = 10;
1da177e4
LT
2837 break;
2838
2839 case RELEASE:
2840 cmdLen = 6;
2841 dir = MPI_SCSIIO_CONTROL_READ;
2842 CDB[0] = cmd;
37c60f37 2843 timeout = 10;
1da177e4
LT
2844 break;
2845
2846 case SYNCHRONIZE_CACHE:
2847 cmdLen = 10;
2848 dir = MPI_SCSIIO_CONTROL_READ;
2849 CDB[0] = cmd;
2850// CDB[1] = 0x02; /* set immediate bit */
37c60f37 2851 timeout = 10;
1da177e4
LT
2852 break;
2853
2854 default:
2855 /* Error Case */
37c60f37
KD
2856 ret = -EFAULT;
2857 goto out;
1da177e4
LT
2858 }
2859
2860 /* Get and Populate a free Frame
37c60f37 2861 * MsgContext set in mpt_get_msg_frame call
1da177e4 2862 */
e80b002b 2863 if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) {
37c60f37
KD
2864 dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s: No msg frames!\n",
2865 ioc->name, __func__));
2866 ret = MPT_SCANDV_BUSY;
2867 goto out;
1da177e4
LT
2868 }
2869
2870 pScsiReq = (SCSIIORequest_t *) mf;
2871
2872 /* Get the request index */
2873 my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
2874 ADD_INDEX_LOG(my_idx); /* for debug */
2875
2876 if (io->flags & MPT_ICFLAG_PHYS_DISK) {
2877 pScsiReq->TargetID = io->physDiskNum;
2878 pScsiReq->Bus = 0;
2879 pScsiReq->ChainOffset = 0;
2880 pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
2881 } else {
2882 pScsiReq->TargetID = io->id;
793955f5 2883 pScsiReq->Bus = io->channel;
1da177e4
LT
2884 pScsiReq->ChainOffset = 0;
2885 pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
2886 }
2887
2888 pScsiReq->CDBLength = cmdLen;
2889 pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
2890
2891 pScsiReq->Reserved = 0;
2892
14d0f0b0 2893 pScsiReq->MsgFlags = mpt_msg_flags(ioc);
1da177e4
LT
2894 /* MsgContext set in mpt_get_msg_fram call */
2895
793955f5 2896 int_to_scsilun(io->lun, (struct scsi_lun *)pScsiReq->LUN);
1da177e4
LT
2897
2898 if (io->flags & MPT_ICFLAG_TAGGED_CMD)
2899 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_SIMPLEQ);
2900 else
2901 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
2902
2903 if (cmd == REQUEST_SENSE) {
2904 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
37c60f37
KD
2905 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2906 "%s: Untagged! 0x%02x\n", ioc->name, __func__, cmd));
1da177e4
LT
2907 }
2908
37c60f37 2909 for (ii = 0; ii < 16; ii++)
1da177e4
LT
2910 pScsiReq->CDB[ii] = CDB[ii];
2911
2912 pScsiReq->DataLength = cpu_to_le32(io->size);
e80b002b 2913 pScsiReq->SenseBufferLowAddr = cpu_to_le32(ioc->sense_buf_low_dma
1da177e4
LT
2914 + (my_idx * MPT_SENSE_BUFFER_ALLOC));
2915
37c60f37
KD
2916 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2917 "%s: Sending Command 0x%02x for fw_channel=%d fw_id=%d lun=%d\n",
2918 ioc->name, __func__, cmd, io->channel, io->id, io->lun));
1da177e4 2919
37c60f37 2920 if (dir == MPI_SCSIIO_CONTROL_READ)
14d0f0b0 2921 ioc->add_sge((char *) &pScsiReq->SGL,
37c60f37
KD
2922 MPT_SGE_FLAGS_SSIMPLE_READ | io->size, io->data_dma);
2923 else
14d0f0b0 2924 ioc->add_sge((char *) &pScsiReq->SGL,
37c60f37 2925 MPT_SGE_FLAGS_SSIMPLE_WRITE | io->size, io->data_dma);
1da177e4 2926
37c60f37 2927 INITIALIZE_MGMT_STATUS(ioc->internal_cmds.status)
e80b002b 2928 mpt_put_msg_frame(ioc->InternalCtx, ioc, mf);
37c60f37
KD
2929 timeleft = wait_for_completion_timeout(&ioc->internal_cmds.done,
2930 timeout*HZ);
2931 if (!(ioc->internal_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
2932 ret = MPT_SCANDV_DID_RESET;
2933 dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2934 "%s: TIMED OUT for cmd=0x%02x\n", ioc->name, __func__,
2935 cmd));
2936 if (ioc->internal_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET) {
2937 mpt_free_msg_frame(ioc, mf);
2938 goto out;
2939 }
2940 if (!timeleft) {
2941 printk(MYIOC_s_WARN_FMT "Issuing Reset from %s!!\n",
2942 ioc->name, __func__);
2943 mpt_HardResetHandler(ioc, CAN_SLEEP);
2944 mpt_free_msg_frame(ioc, mf);
2945 }
2946 goto out;
1da177e4
LT
2947 }
2948
37c60f37
KD
2949 ret = ioc->internal_cmds.completion_code;
2950 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: success, rc=0x%02x\n",
2951 ioc->name, __func__, ret));
2952
2953 out:
2954 CLEAR_MGMT_STATUS(ioc->internal_cmds.status)
2955 mutex_unlock(&ioc->internal_cmds.mutex);
2956 return ret;
1da177e4
LT
2957}
2958
c7c82987
MED
2959/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2960/**
2961 * mptscsih_synchronize_cache - Send SYNCHRONIZE_CACHE to all disks.
2962 * @hd: Pointer to a SCSI HOST structure
d9489fb6 2963 * @vdevice: virtual target device
c7c82987
MED
2964 *
2965 * Uses the ISR, but with special processing.
2966 * MUST be single-threaded.
2967 *
2968 */
2969static void
2970mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
2971{
2972 INTERNAL_CMD iocmd;
1da177e4 2973
cc78d30a
EM
2974 /* Ignore hidden raid components, this is handled when the command
2975 * is sent to the volume
2976 */
2977 if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT)
2978 return;
2979
2980 if (vdevice->vtarget->type != TYPE_DISK || vdevice->vtarget->deleted ||
2981 !vdevice->configured_lun)
2982 return;
2983
c7c82987
MED
2984 /* Following parameters will not change
2985 * in this routine.
2986 */
2987 iocmd.cmd = SYNCHRONIZE_CACHE;
2988 iocmd.flags = 0;
2989 iocmd.physDiskNum = -1;
2990 iocmd.data = NULL;
2991 iocmd.data_dma = -1;
2992 iocmd.size = 0;
2993 iocmd.rsvd = iocmd.rsvd2 = 0;
793955f5
EM
2994 iocmd.channel = vdevice->vtarget->channel;
2995 iocmd.id = vdevice->vtarget->id;
2996 iocmd.lun = vdevice->lun;
1da177e4 2997
cc78d30a 2998 mptscsih_do_cmd(hd, &iocmd);
1da177e4
LT
2999}
3000
edb9068d 3001static ssize_t
ee959b00
TJ
3002mptscsih_version_fw_show(struct device *dev, struct device_attribute *attr,
3003 char *buf)
edb9068d 3004{
ee959b00 3005 struct Scsi_Host *host = class_to_shost(dev);
e7eae9f6 3006 MPT_SCSI_HOST *hd = shost_priv(host);
edb9068d
PS
3007 MPT_ADAPTER *ioc = hd->ioc;
3008
3009 return snprintf(buf, PAGE_SIZE, "%02d.%02d.%02d.%02d\n",
3010 (ioc->facts.FWVersion.Word & 0xFF000000) >> 24,
3011 (ioc->facts.FWVersion.Word & 0x00FF0000) >> 16,
3012 (ioc->facts.FWVersion.Word & 0x0000FF00) >> 8,
3013 ioc->facts.FWVersion.Word & 0x000000FF);
3014}
ee959b00 3015static DEVICE_ATTR(version_fw, S_IRUGO, mptscsih_version_fw_show, NULL);
edb9068d
PS
3016
3017static ssize_t
ee959b00
TJ
3018mptscsih_version_bios_show(struct device *dev, struct device_attribute *attr,
3019 char *buf)
edb9068d 3020{
ee959b00 3021 struct Scsi_Host *host = class_to_shost(dev);
e7eae9f6 3022 MPT_SCSI_HOST *hd = shost_priv(host);
edb9068d
PS
3023 MPT_ADAPTER *ioc = hd->ioc;
3024
3025 return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x.%02x\n",
3026 (ioc->biosVersion & 0xFF000000) >> 24,
3027 (ioc->biosVersion & 0x00FF0000) >> 16,
3028 (ioc->biosVersion & 0x0000FF00) >> 8,
3029 ioc->biosVersion & 0x000000FF);
3030}
ee959b00 3031static DEVICE_ATTR(version_bios, S_IRUGO, mptscsih_version_bios_show, NULL);
edb9068d
PS
3032
3033static ssize_t
ee959b00
TJ
3034mptscsih_version_mpi_show(struct device *dev, struct device_attribute *attr,
3035 char *buf)
edb9068d 3036{
ee959b00 3037 struct Scsi_Host *host = class_to_shost(dev);
e7eae9f6 3038 MPT_SCSI_HOST *hd = shost_priv(host);
edb9068d
PS
3039 MPT_ADAPTER *ioc = hd->ioc;
3040
3041 return snprintf(buf, PAGE_SIZE, "%03x\n", ioc->facts.MsgVersion);
3042}
ee959b00 3043static DEVICE_ATTR(version_mpi, S_IRUGO, mptscsih_version_mpi_show, NULL);
edb9068d
PS
3044
3045static ssize_t
ee959b00
TJ
3046mptscsih_version_product_show(struct device *dev,
3047 struct device_attribute *attr,
3048char *buf)
edb9068d 3049{
ee959b00 3050 struct Scsi_Host *host = class_to_shost(dev);
e7eae9f6 3051 MPT_SCSI_HOST *hd = shost_priv(host);
edb9068d
PS
3052 MPT_ADAPTER *ioc = hd->ioc;
3053
3054 return snprintf(buf, PAGE_SIZE, "%s\n", ioc->prod_name);
3055}
ee959b00 3056static DEVICE_ATTR(version_product, S_IRUGO,
edb9068d
PS
3057 mptscsih_version_product_show, NULL);
3058
3059static ssize_t
ee959b00
TJ
3060mptscsih_version_nvdata_persistent_show(struct device *dev,
3061 struct device_attribute *attr,
3062 char *buf)
edb9068d 3063{
ee959b00 3064 struct Scsi_Host *host = class_to_shost(dev);
e7eae9f6 3065 MPT_SCSI_HOST *hd = shost_priv(host);
edb9068d
PS
3066 MPT_ADAPTER *ioc = hd->ioc;
3067
3068 return snprintf(buf, PAGE_SIZE, "%02xh\n",
3069 ioc->nvdata_version_persistent);
3070}
ee959b00 3071static DEVICE_ATTR(version_nvdata_persistent, S_IRUGO,
edb9068d
PS
3072 mptscsih_version_nvdata_persistent_show, NULL);
3073
3074static ssize_t
ee959b00
TJ
3075mptscsih_version_nvdata_default_show(struct device *dev,
3076 struct device_attribute *attr, char *buf)
edb9068d 3077{
ee959b00 3078 struct Scsi_Host *host = class_to_shost(dev);
e7eae9f6 3079 MPT_SCSI_HOST *hd = shost_priv(host);
edb9068d
PS
3080 MPT_ADAPTER *ioc = hd->ioc;
3081
3082 return snprintf(buf, PAGE_SIZE, "%02xh\n",ioc->nvdata_version_default);
3083}
ee959b00 3084static DEVICE_ATTR(version_nvdata_default, S_IRUGO,
edb9068d
PS
3085 mptscsih_version_nvdata_default_show, NULL);
3086
3087static ssize_t
ee959b00
TJ
3088mptscsih_board_name_show(struct device *dev, struct device_attribute *attr,
3089 char *buf)
edb9068d 3090{
ee959b00 3091 struct Scsi_Host *host = class_to_shost(dev);
e7eae9f6 3092 MPT_SCSI_HOST *hd = shost_priv(host);
edb9068d
PS
3093 MPT_ADAPTER *ioc = hd->ioc;
3094
3095 return snprintf(buf, PAGE_SIZE, "%s\n", ioc->board_name);
3096}
ee959b00 3097static DEVICE_ATTR(board_name, S_IRUGO, mptscsih_board_name_show, NULL);
edb9068d
PS
3098
3099static ssize_t
ee959b00
TJ
3100mptscsih_board_assembly_show(struct device *dev,
3101 struct device_attribute *attr, char *buf)
edb9068d 3102{
ee959b00 3103 struct Scsi_Host *host = class_to_shost(dev);
e7eae9f6 3104 MPT_SCSI_HOST *hd = shost_priv(host);
edb9068d
PS
3105 MPT_ADAPTER *ioc = hd->ioc;
3106
3107 return snprintf(buf, PAGE_SIZE, "%s\n", ioc->board_assembly);
3108}
ee959b00 3109static DEVICE_ATTR(board_assembly, S_IRUGO,
edb9068d
PS
3110 mptscsih_board_assembly_show, NULL);
3111
3112static ssize_t
ee959b00
TJ
3113mptscsih_board_tracer_show(struct device *dev, struct device_attribute *attr,
3114 char *buf)
edb9068d 3115{
ee959b00 3116 struct Scsi_Host *host = class_to_shost(dev);
e7eae9f6 3117 MPT_SCSI_HOST *hd = shost_priv(host);
edb9068d
PS
3118 MPT_ADAPTER *ioc = hd->ioc;
3119
3120 return snprintf(buf, PAGE_SIZE, "%s\n", ioc->board_tracer);
3121}
ee959b00 3122static DEVICE_ATTR(board_tracer, S_IRUGO,
edb9068d
PS
3123 mptscsih_board_tracer_show, NULL);
3124
3125static ssize_t
ee959b00
TJ
3126mptscsih_io_delay_show(struct device *dev, struct device_attribute *attr,
3127 char *buf)
edb9068d 3128{
ee959b00 3129 struct Scsi_Host *host = class_to_shost(dev);
e7eae9f6 3130 MPT_SCSI_HOST *hd = shost_priv(host);
edb9068d
PS
3131 MPT_ADAPTER *ioc = hd->ioc;
3132
3133 return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->io_missing_delay);
3134}
ee959b00 3135static DEVICE_ATTR(io_delay, S_IRUGO,
edb9068d
PS
3136 mptscsih_io_delay_show, NULL);
3137
3138static ssize_t
ee959b00
TJ
3139mptscsih_device_delay_show(struct device *dev, struct device_attribute *attr,
3140 char *buf)
edb9068d 3141{
ee959b00 3142 struct Scsi_Host *host = class_to_shost(dev);
e7eae9f6 3143 MPT_SCSI_HOST *hd = shost_priv(host);
edb9068d
PS
3144 MPT_ADAPTER *ioc = hd->ioc;
3145
3146 return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->device_missing_delay);
3147}
ee959b00 3148static DEVICE_ATTR(device_delay, S_IRUGO,
edb9068d
PS
3149 mptscsih_device_delay_show, NULL);
3150
6757d6b4 3151static ssize_t
ee959b00
TJ
3152mptscsih_debug_level_show(struct device *dev, struct device_attribute *attr,
3153 char *buf)
6757d6b4 3154{
ee959b00 3155 struct Scsi_Host *host = class_to_shost(dev);
e7eae9f6 3156 MPT_SCSI_HOST *hd = shost_priv(host);
6757d6b4
PS
3157 MPT_ADAPTER *ioc = hd->ioc;
3158
3159 return snprintf(buf, PAGE_SIZE, "%08xh\n", ioc->debug_level);
3160}
3161static ssize_t
ee959b00
TJ
3162mptscsih_debug_level_store(struct device *dev, struct device_attribute *attr,
3163 const char *buf, size_t count)
6757d6b4 3164{
ee959b00 3165 struct Scsi_Host *host = class_to_shost(dev);
e7eae9f6 3166 MPT_SCSI_HOST *hd = shost_priv(host);
6757d6b4
PS
3167 MPT_ADAPTER *ioc = hd->ioc;
3168 int val = 0;
3169
3170 if (sscanf(buf, "%x", &val) != 1)
3171 return -EINVAL;
3172
3173 ioc->debug_level = val;
3174 printk(MYIOC_s_INFO_FMT "debug_level=%08xh\n",
3175 ioc->name, ioc->debug_level);
3176 return strlen(buf);
3177}
ee959b00
TJ
3178static DEVICE_ATTR(debug_level, S_IRUGO | S_IWUSR,
3179 mptscsih_debug_level_show, mptscsih_debug_level_store);
3180
3181struct device_attribute *mptscsih_host_attrs[] = {
3182 &dev_attr_version_fw,
3183 &dev_attr_version_bios,
3184 &dev_attr_version_mpi,
3185 &dev_attr_version_product,
3186 &dev_attr_version_nvdata_persistent,
3187 &dev_attr_version_nvdata_default,
3188 &dev_attr_board_name,
3189 &dev_attr_board_assembly,
3190 &dev_attr_board_tracer,
3191 &dev_attr_io_delay,
3192 &dev_attr_device_delay,
3193 &dev_attr_debug_level,
edb9068d
PS
3194 NULL,
3195};
37c60f37 3196
edb9068d
PS
3197EXPORT_SYMBOL(mptscsih_host_attrs);
3198
0d0c7974
MED
3199EXPORT_SYMBOL(mptscsih_remove);
3200EXPORT_SYMBOL(mptscsih_shutdown);
3201#ifdef CONFIG_PM
3202EXPORT_SYMBOL(mptscsih_suspend);
3203EXPORT_SYMBOL(mptscsih_resume);
3204#endif
3205EXPORT_SYMBOL(mptscsih_proc_info);
3206EXPORT_SYMBOL(mptscsih_info);
3207EXPORT_SYMBOL(mptscsih_qcmd);
0d0c7974
MED
3208EXPORT_SYMBOL(mptscsih_slave_destroy);
3209EXPORT_SYMBOL(mptscsih_slave_configure);
3210EXPORT_SYMBOL(mptscsih_abort);
3211EXPORT_SYMBOL(mptscsih_dev_reset);
3212EXPORT_SYMBOL(mptscsih_bus_reset);
3213EXPORT_SYMBOL(mptscsih_host_reset);
3214EXPORT_SYMBOL(mptscsih_bios_param);
3215EXPORT_SYMBOL(mptscsih_io_done);
3216EXPORT_SYMBOL(mptscsih_taskmgmt_complete);
3217EXPORT_SYMBOL(mptscsih_scandv_complete);
3218EXPORT_SYMBOL(mptscsih_event_process);
3219EXPORT_SYMBOL(mptscsih_ioc_reset);
6e3815ba 3220EXPORT_SYMBOL(mptscsih_change_queue_depth);
1da177e4 3221
0d0c7974 3222/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/