]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/message/fusion/mptbase.c
[SCSI] fusion: spi bus reset when driver loads
[net-next-2.6.git] / drivers / message / fusion / mptbase.c
CommitLineData
1da177e4
LT
1/*
2 * linux/drivers/message/fusion/mptbase.c
1da177e4
LT
3 * This is the Fusion MPT base driver which supports multiple
4 * (SCSI + LAN) specialized protocol drivers.
7fadc87e 5 * For use with LSI Logic PCI chip/adapter(s)
1da177e4
LT
6 * running LSI Logic Fusion MPT (Message Passing Technology) firmware.
7 *
7fadc87e 8 * Copyright (c) 1999-2005 LSI Logic Corporation
1da177e4
LT
9 * (mailto:mpt_linux_developer@lsil.com)
10 *
1da177e4
LT
11 */
12/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
13/*
14 This program is free software; you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation; version 2 of the License.
17
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
22
23 NO WARRANTY
24 THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
25 CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
26 LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
27 MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
28 solely responsible for determining the appropriateness of using and
29 distributing the Program and assumes all risks associated with its
30 exercise of rights under this Agreement, including but not limited to
31 the risks and costs of program errors, damage to or loss of data,
32 programs or equipment, and unavailability or interruption of operations.
33
34 DISCLAIMER OF LIABILITY
35 NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
36 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
38 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
39 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
40 USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
41 HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
42
43 You should have received a copy of the GNU General Public License
44 along with this program; if not, write to the Free Software
45 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
46*/
47/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
48
49#include <linux/config.h>
1da177e4
LT
50#include <linux/kernel.h>
51#include <linux/module.h>
52#include <linux/errno.h>
53#include <linux/init.h>
54#include <linux/slab.h>
55#include <linux/types.h>
56#include <linux/pci.h>
57#include <linux/kdev_t.h>
58#include <linux/blkdev.h>
59#include <linux/delay.h>
60#include <linux/interrupt.h> /* needed for in_interrupt() proto */
7fadc87e 61#include <linux/dma-mapping.h>
1da177e4
LT
62#include <asm/io.h>
63#ifdef CONFIG_MTRR
64#include <asm/mtrr.h>
65#endif
66#ifdef __sparc__
67#include <asm/irq.h> /* needed for __irq_itoa() proto */
68#endif
69
70#include "mptbase.h"
71
72/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
73#define my_NAME "Fusion MPT base driver"
74#define my_VERSION MPT_LINUX_VERSION_COMMON
75#define MYNAM "mptbase"
76
77MODULE_AUTHOR(MODULEAUTHOR);
78MODULE_DESCRIPTION(my_NAME);
79MODULE_LICENSE("GPL");
80
81/*
82 * cmd line parameters
83 */
84#ifdef MFCNT
85static int mfcounter = 0;
86#define PRINT_MF_COUNT 20000
87#endif
88
89/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
90/*
91 * Public data...
92 */
93int mpt_lan_index = -1;
f747307e 94int mpt_stm_index = -1;
1da177e4 95
f747307e 96struct proc_dir_entry *mpt_proc_root_dir;
1da177e4
LT
97
98#define WHOINIT_UNKNOWN 0xAA
99
100/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
101/*
102 * Private data...
103 */
104 /* Adapter link list */
105LIST_HEAD(ioc_list);
106 /* Callback lookup table */
107static MPT_CALLBACK MptCallbacks[MPT_MAX_PROTOCOL_DRIVERS];
108 /* Protocol driver class lookup table */
109static int MptDriverClass[MPT_MAX_PROTOCOL_DRIVERS];
110 /* Event handler lookup table */
111static MPT_EVHANDLER MptEvHandlers[MPT_MAX_PROTOCOL_DRIVERS];
112 /* Reset handler lookup table */
113static MPT_RESETHANDLER MptResetHandlers[MPT_MAX_PROTOCOL_DRIVERS];
114static struct mpt_pci_driver *MptDeviceDriverHandlers[MPT_MAX_PROTOCOL_DRIVERS];
115
116static int mpt_base_index = -1;
117static int last_drv_idx = -1;
118
119static DECLARE_WAIT_QUEUE_HEAD(mpt_waitq);
120
121/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
122/*
123 * Forward protos...
124 */
125static irqreturn_t mpt_interrupt(int irq, void *bus_id, struct pt_regs *r);
126static int mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply);
127static int mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes,
128 u32 *req, int replyBytes, u16 *u16reply, int maxwait,
129 int sleepFlag);
130static int mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag);
131static void mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev);
132static void mpt_adapter_disable(MPT_ADAPTER *ioc);
133static void mpt_adapter_dispose(MPT_ADAPTER *ioc);
134
135static void MptDisplayIocCapabilities(MPT_ADAPTER *ioc);
136static int MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag);
1da177e4
LT
137static int GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason);
138static int GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag);
139static int SendIocInit(MPT_ADAPTER *ioc, int sleepFlag);
140static int SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag);
141static int mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag);
82ffb671 142static int mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag);
1da177e4
LT
143static int mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag);
144static int KickStart(MPT_ADAPTER *ioc, int ignore, int sleepFlag);
145static int SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag);
146static int PrimeIocFifos(MPT_ADAPTER *ioc);
147static int WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
148static int WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
149static int WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
150static int GetLanConfigPages(MPT_ADAPTER *ioc);
1da177e4 151static int GetIoUnitPage2(MPT_ADAPTER *ioc);
82ffb671 152int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode);
1da177e4
LT
153static int mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum);
154static int mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum);
155static void mpt_read_ioc_pg_1(MPT_ADAPTER *ioc);
156static void mpt_read_ioc_pg_4(MPT_ADAPTER *ioc);
157static void mpt_timer_expired(unsigned long data);
158static int SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch);
159static int SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp);
82ffb671
CH
160static int mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag);
161static int mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init);
1da177e4
LT
162
163#ifdef CONFIG_PROC_FS
164static int procmpt_summary_read(char *buf, char **start, off_t offset,
165 int request, int *eof, void *data);
166static int procmpt_version_read(char *buf, char **start, off_t offset,
167 int request, int *eof, void *data);
168static int procmpt_iocinfo_read(char *buf, char **start, off_t offset,
169 int request, int *eof, void *data);
170#endif
171static void mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc);
172
173//int mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag);
174static int ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *evReply, int *evHandlers);
175static void mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf);
176static void mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info);
177static void mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info);
466544d8 178static void mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info);
1da177e4
LT
179
180/* module entry point */
1da177e4
LT
181static int __init fusion_init (void);
182static void __exit fusion_exit (void);
183
1da177e4
LT
184#define CHIPREG_READ32(addr) readl_relaxed(addr)
185#define CHIPREG_READ32_dmasync(addr) readl(addr)
186#define CHIPREG_WRITE32(addr,val) writel(val, addr)
187#define CHIPREG_PIO_WRITE32(addr,val) outl(val, (unsigned long)addr)
188#define CHIPREG_PIO_READ32(addr) inl((unsigned long)addr)
189
3fadc59d
MED
190static void
191pci_disable_io_access(struct pci_dev *pdev)
192{
193 u16 command_reg;
194
195 pci_read_config_word(pdev, PCI_COMMAND, &command_reg);
196 command_reg &= ~1;
197 pci_write_config_word(pdev, PCI_COMMAND, command_reg);
198}
199
200static void
201pci_enable_io_access(struct pci_dev *pdev)
202{
203 u16 command_reg;
204
205 pci_read_config_word(pdev, PCI_COMMAND, &command_reg);
206 command_reg |= 1;
207 pci_write_config_word(pdev, PCI_COMMAND, command_reg);
208}
209
466544d8
MED
210/*
211 * Process turbo (context) reply...
212 */
213static void
214mpt_turbo_reply(MPT_ADAPTER *ioc, u32 pa)
215{
216 MPT_FRAME_HDR *mf = NULL;
217 MPT_FRAME_HDR *mr = NULL;
218 int req_idx = 0;
219 int cb_idx;
220
221 dmfprintk((MYIOC_s_INFO_FMT "Got TURBO reply req_idx=%08x\n",
222 ioc->name, pa));
223
224 switch (pa >> MPI_CONTEXT_REPLY_TYPE_SHIFT) {
225 case MPI_CONTEXT_REPLY_TYPE_SCSI_INIT:
226 req_idx = pa & 0x0000FFFF;
227 cb_idx = (pa & 0x00FF0000) >> 16;
228 mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
229 break;
230 case MPI_CONTEXT_REPLY_TYPE_LAN:
231 cb_idx = mpt_lan_index;
232 /*
233 * Blind set of mf to NULL here was fatal
234 * after lan_reply says "freeme"
235 * Fix sort of combined with an optimization here;
236 * added explicit check for case where lan_reply
237 * was just returning 1 and doing nothing else.
238 * For this case skip the callback, but set up
239 * proper mf value first here:-)
240 */
241 if ((pa & 0x58000000) == 0x58000000) {
242 req_idx = pa & 0x0000FFFF;
243 mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
244 mpt_free_msg_frame(ioc, mf);
245 mb();
246 return;
247 break;
248 }
249 mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
250 break;
251 case MPI_CONTEXT_REPLY_TYPE_SCSI_TARGET:
252 cb_idx = mpt_stm_index;
253 mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
254 break;
255 default:
256 cb_idx = 0;
257 BUG();
258 }
259
260 /* Check for (valid) IO callback! */
261 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS ||
262 MptCallbacks[cb_idx] == NULL) {
263 printk(MYIOC_s_WARN_FMT "%s: Invalid cb_idx (%d)!\n",
264 __FUNCTION__, ioc->name, cb_idx);
265 goto out;
266 }
267
268 if (MptCallbacks[cb_idx](ioc, mf, mr))
269 mpt_free_msg_frame(ioc, mf);
270 out:
271 mb();
272}
273
274static void
275mpt_reply(MPT_ADAPTER *ioc, u32 pa)
276{
277 MPT_FRAME_HDR *mf;
278 MPT_FRAME_HDR *mr;
279 int req_idx;
280 int cb_idx;
281 int freeme;
282
283 u32 reply_dma_low;
284 u16 ioc_stat;
285
286 /* non-TURBO reply! Hmmm, something may be up...
287 * Newest turbo reply mechanism; get address
288 * via left shift 1 (get rid of MPI_ADDRESS_REPLY_A_BIT)!
289 */
290
291 /* Map DMA address of reply header to cpu address.
292 * pa is 32 bits - but the dma address may be 32 or 64 bits
293 * get offset based only only the low addresses
294 */
295
296 reply_dma_low = (pa <<= 1);
297 mr = (MPT_FRAME_HDR *)((u8 *)ioc->reply_frames +
298 (reply_dma_low - ioc->reply_frames_low_dma));
299
300 req_idx = le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx);
301 cb_idx = mr->u.frame.hwhdr.msgctxu.fld.cb_idx;
302 mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
303
304 dmfprintk((MYIOC_s_INFO_FMT "Got non-TURBO reply=%p req_idx=%x cb_idx=%x Function=%x\n",
305 ioc->name, mr, req_idx, cb_idx, mr->u.hdr.Function));
306 DBG_DUMP_REPLY_FRAME(mr)
307
308 /* Check/log IOC log info
309 */
310 ioc_stat = le16_to_cpu(mr->u.reply.IOCStatus);
311 if (ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
312 u32 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo);
313 if (ioc->bus_type == FC)
314 mpt_fc_log_info(ioc, log_info);
a9b2937a 315 else if (ioc->bus_type == SPI)
466544d8
MED
316 mpt_sp_log_info(ioc, log_info);
317 else if (ioc->bus_type == SAS)
318 mpt_sas_log_info(ioc, log_info);
319 }
320 if (ioc_stat & MPI_IOCSTATUS_MASK) {
a9b2937a 321 if (ioc->bus_type == SPI &&
466544d8
MED
322 cb_idx != mpt_stm_index &&
323 cb_idx != mpt_lan_index)
324 mpt_sp_ioc_info(ioc, (u32)ioc_stat, mf);
325 }
326
327
328 /* Check for (valid) IO callback! */
329 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS ||
330 MptCallbacks[cb_idx] == NULL) {
331 printk(MYIOC_s_WARN_FMT "%s: Invalid cb_idx (%d)!\n",
332 __FUNCTION__, ioc->name, cb_idx);
333 freeme = 0;
334 goto out;
335 }
336
337 freeme = MptCallbacks[cb_idx](ioc, mf, mr);
338
339 out:
340 /* Flush (non-TURBO) reply with a WRITE! */
341 CHIPREG_WRITE32(&ioc->chip->ReplyFifo, pa);
342
343 if (freeme)
344 mpt_free_msg_frame(ioc, mf);
345 mb();
346}
347
1da177e4
LT
348/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
349/*
350 * mpt_interrupt - MPT adapter (IOC) specific interrupt handler.
351 * @irq: irq number (not used)
352 * @bus_id: bus identifier cookie == pointer to MPT_ADAPTER structure
353 * @r: pt_regs pointer (not used)
354 *
355 * This routine is registered via the request_irq() kernel API call,
356 * and handles all interrupts generated from a specific MPT adapter
357 * (also referred to as a IO Controller or IOC).
358 * This routine must clear the interrupt from the adapter and does
359 * so by reading the reply FIFO. Multiple replies may be processed
c6678e0c 360 * per single call to this routine.
1da177e4
LT
361 *
362 * This routine handles register-level access of the adapter but
363 * dispatches (calls) a protocol-specific callback routine to handle
364 * the protocol-specific details of the MPT request completion.
365 */
366static irqreturn_t
367mpt_interrupt(int irq, void *bus_id, struct pt_regs *r)
368{
466544d8
MED
369 MPT_ADAPTER *ioc = bus_id;
370 u32 pa;
1da177e4
LT
371
372 /*
373 * Drain the reply FIFO!
1da177e4
LT
374 */
375 while (1) {
466544d8
MED
376 pa = CHIPREG_READ32_dmasync(&ioc->chip->ReplyFifo);
377 if (pa == 0xFFFFFFFF)
1da177e4 378 return IRQ_HANDLED;
466544d8
MED
379 else if (pa & MPI_ADDRESS_REPLY_A_BIT)
380 mpt_reply(ioc, pa);
381 else
382 mpt_turbo_reply(ioc, pa);
383 }
1da177e4
LT
384
385 return IRQ_HANDLED;
386}
387
388/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
389/*
390 * mpt_base_reply - MPT base driver's callback routine; all base driver
391 * "internal" request/reply processing is routed here.
392 * Currently used for EventNotification and EventAck handling.
393 * @ioc: Pointer to MPT_ADAPTER structure
394 * @mf: Pointer to original MPT request frame
395 * @reply: Pointer to MPT reply frame (NULL if TurboReply)
396 *
c6678e0c 397 * Returns 1 indicating original alloc'd request frame ptr
1da177e4
LT
398 * should be freed, or 0 if it shouldn't.
399 */
400static int
401mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
402{
403 int freereq = 1;
404 u8 func;
405
c6678e0c 406 dmfprintk((MYIOC_s_INFO_FMT "mpt_base_reply() called\n", ioc->name));
1da177e4 407
c6678e0c 408#if defined(MPT_DEBUG_MSG_FRAME)
1da177e4
LT
409 if (!(reply->u.hdr.MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY)) {
410 dmfprintk((KERN_INFO MYNAM ": Original request frame (@%p) header\n", mf));
411 DBG_DUMP_REQUEST_FRAME_HDR(mf)
412 }
c6678e0c 413#endif
1da177e4
LT
414
415 func = reply->u.hdr.Function;
c6678e0c 416 dmfprintk((MYIOC_s_INFO_FMT "mpt_base_reply, Function=%02Xh\n",
1da177e4
LT
417 ioc->name, func));
418
419 if (func == MPI_FUNCTION_EVENT_NOTIFICATION) {
420 EventNotificationReply_t *pEvReply = (EventNotificationReply_t *) reply;
421 int evHandlers = 0;
422 int results;
423
424 results = ProcessEventNotification(ioc, pEvReply, &evHandlers);
425 if (results != evHandlers) {
426 /* CHECKME! Any special handling needed here? */
427 devtprintk((MYIOC_s_WARN_FMT "Called %d event handlers, sum results = %d\n",
428 ioc->name, evHandlers, results));
429 }
430
431 /*
432 * Hmmm... It seems that EventNotificationReply is an exception
433 * to the rule of one reply per request.
434 */
c6678e0c 435 if (pEvReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY) {
1da177e4 436 freereq = 0;
c6678e0c
CH
437 devtprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p does not return Request frame\n",
438 ioc->name, pEvReply));
439 } else {
440 devtprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p returns Request frame\n",
441 ioc->name, pEvReply));
442 }
1da177e4
LT
443
444#ifdef CONFIG_PROC_FS
445// LogEvent(ioc, pEvReply);
446#endif
447
448 } else if (func == MPI_FUNCTION_EVENT_ACK) {
449 dprintk((MYIOC_s_INFO_FMT "mpt_base_reply, EventAck reply received\n",
450 ioc->name));
451 } else if (func == MPI_FUNCTION_CONFIG ||
452 func == MPI_FUNCTION_TOOLBOX) {
453 CONFIGPARMS *pCfg;
454 unsigned long flags;
455
456 dcprintk((MYIOC_s_INFO_FMT "config_complete (mf=%p,mr=%p)\n",
457 ioc->name, mf, reply));
458
459 pCfg = * ((CONFIGPARMS **)((u8 *) mf + ioc->req_sz - sizeof(void *)));
460
461 if (pCfg) {
462 /* disable timer and remove from linked list */
463 del_timer(&pCfg->timer);
464
465 spin_lock_irqsave(&ioc->FreeQlock, flags);
466 list_del(&pCfg->linkage);
467 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
468
469 /*
470 * If IOC Status is SUCCESS, save the header
471 * and set the status code to GOOD.
472 */
473 pCfg->status = MPT_CONFIG_ERROR;
474 if (reply) {
475 ConfigReply_t *pReply = (ConfigReply_t *)reply;
476 u16 status;
477
478 status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
479 dcprintk((KERN_NOTICE " IOCStatus=%04xh, IOCLogInfo=%08xh\n",
480 status, le32_to_cpu(pReply->IOCLogInfo)));
481
482 pCfg->status = status;
483 if (status == MPI_IOCSTATUS_SUCCESS) {
69218ee5
CH
484 if ((pReply->Header.PageType &
485 MPI_CONFIG_PAGETYPE_MASK) ==
486 MPI_CONFIG_PAGETYPE_EXTENDED) {
487 pCfg->cfghdr.ehdr->ExtPageLength =
488 le16_to_cpu(pReply->ExtPageLength);
489 pCfg->cfghdr.ehdr->ExtPageType =
490 pReply->ExtPageType;
491 }
492 pCfg->cfghdr.hdr->PageVersion = pReply->Header.PageVersion;
493
494 /* If this is a regular header, save PageLength. */
495 /* LMP Do this better so not using a reserved field! */
496 pCfg->cfghdr.hdr->PageLength = pReply->Header.PageLength;
497 pCfg->cfghdr.hdr->PageNumber = pReply->Header.PageNumber;
498 pCfg->cfghdr.hdr->PageType = pReply->Header.PageType;
1da177e4
LT
499 }
500 }
501
502 /*
503 * Wake up the original calling thread
504 */
505 pCfg->wait_done = 1;
506 wake_up(&mpt_waitq);
507 }
82ffb671
CH
508 } else if (func == MPI_FUNCTION_SAS_IO_UNIT_CONTROL) {
509 /* we should be always getting a reply frame */
510 memcpy(ioc->persist_reply_frame, reply,
511 min(MPT_DEFAULT_FRAME_SIZE,
512 4*reply->u.reply.MsgLength));
513 del_timer(&ioc->persist_timer);
514 ioc->persist_wait_done = 1;
515 wake_up(&mpt_waitq);
1da177e4
LT
516 } else {
517 printk(MYIOC_s_ERR_FMT "Unexpected msg function (=%02Xh) reply received!\n",
518 ioc->name, func);
519 }
520
521 /*
522 * Conditionally tell caller to free the original
523 * EventNotification/EventAck/unexpected request frame!
524 */
525 return freereq;
526}
527
528/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
529/**
530 * mpt_register - Register protocol-specific main callback handler.
531 * @cbfunc: callback function pointer
532 * @dclass: Protocol driver's class (%MPT_DRIVER_CLASS enum value)
533 *
534 * This routine is called by a protocol-specific driver (SCSI host,
535 * LAN, SCSI target) to register it's reply callback routine. Each
536 * protocol-specific driver must do this before it will be able to
537 * use any IOC resources, such as obtaining request frames.
538 *
539 * NOTES: The SCSI protocol driver currently calls this routine thrice
540 * in order to register separate callbacks; one for "normal" SCSI IO;
541 * one for MptScsiTaskMgmt requests; one for Scan/DV requests.
542 *
543 * Returns a positive integer valued "handle" in the
544 * range (and S.O.D. order) {N,...,7,6,5,...,1} if successful.
545 * Any non-positive return value (including zero!) should be considered
546 * an error by the caller.
547 */
548int
549mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass)
550{
551 int i;
552
553 last_drv_idx = -1;
554
555 /*
556 * Search for empty callback slot in this order: {N,...,7,6,5,...,1}
557 * (slot/handle 0 is reserved!)
558 */
559 for (i = MPT_MAX_PROTOCOL_DRIVERS-1; i; i--) {
560 if (MptCallbacks[i] == NULL) {
561 MptCallbacks[i] = cbfunc;
562 MptDriverClass[i] = dclass;
563 MptEvHandlers[i] = NULL;
564 last_drv_idx = i;
565 break;
566 }
567 }
568
569 return last_drv_idx;
570}
571
572/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
573/**
574 * mpt_deregister - Deregister a protocol drivers resources.
575 * @cb_idx: previously registered callback handle
576 *
577 * Each protocol-specific driver should call this routine when it's
578 * module is unloaded.
579 */
580void
581mpt_deregister(int cb_idx)
582{
583 if ((cb_idx >= 0) && (cb_idx < MPT_MAX_PROTOCOL_DRIVERS)) {
584 MptCallbacks[cb_idx] = NULL;
585 MptDriverClass[cb_idx] = MPTUNKNOWN_DRIVER;
586 MptEvHandlers[cb_idx] = NULL;
587
588 last_drv_idx++;
589 }
590}
591
592/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
593/**
594 * mpt_event_register - Register protocol-specific event callback
595 * handler.
596 * @cb_idx: previously registered (via mpt_register) callback handle
597 * @ev_cbfunc: callback function
598 *
599 * This routine can be called by one or more protocol-specific drivers
600 * if/when they choose to be notified of MPT events.
601 *
602 * Returns 0 for success.
603 */
604int
605mpt_event_register(int cb_idx, MPT_EVHANDLER ev_cbfunc)
606{
607 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
608 return -1;
609
610 MptEvHandlers[cb_idx] = ev_cbfunc;
611 return 0;
612}
613
614/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
615/**
616 * mpt_event_deregister - Deregister protocol-specific event callback
617 * handler.
618 * @cb_idx: previously registered callback handle
619 *
620 * Each protocol-specific driver should call this routine
621 * when it does not (or can no longer) handle events,
622 * or when it's module is unloaded.
623 */
624void
625mpt_event_deregister(int cb_idx)
626{
627 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
628 return;
629
630 MptEvHandlers[cb_idx] = NULL;
631}
632
633/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
634/**
635 * mpt_reset_register - Register protocol-specific IOC reset handler.
636 * @cb_idx: previously registered (via mpt_register) callback handle
637 * @reset_func: reset function
638 *
639 * This routine can be called by one or more protocol-specific drivers
640 * if/when they choose to be notified of IOC resets.
641 *
642 * Returns 0 for success.
643 */
644int
645mpt_reset_register(int cb_idx, MPT_RESETHANDLER reset_func)
646{
647 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
648 return -1;
649
650 MptResetHandlers[cb_idx] = reset_func;
651 return 0;
652}
653
654/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
655/**
656 * mpt_reset_deregister - Deregister protocol-specific IOC reset handler.
657 * @cb_idx: previously registered callback handle
658 *
659 * Each protocol-specific driver should call this routine
660 * when it does not (or can no longer) handle IOC reset handling,
661 * or when it's module is unloaded.
662 */
663void
664mpt_reset_deregister(int cb_idx)
665{
666 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
667 return;
668
669 MptResetHandlers[cb_idx] = NULL;
670}
671
672/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
673/**
674 * mpt_device_driver_register - Register device driver hooks
675 */
676int
677mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, int cb_idx)
678{
679 MPT_ADAPTER *ioc;
1da177e4
LT
680
681 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) {
7fadc87e 682 return -EINVAL;
1da177e4
LT
683 }
684
685 MptDeviceDriverHandlers[cb_idx] = dd_cbfunc;
686
687 /* call per pci device probe entry point */
688 list_for_each_entry(ioc, &ioc_list, list) {
689 if(dd_cbfunc->probe) {
7fadc87e 690 dd_cbfunc->probe(ioc->pcidev,
1da177e4 691 ioc->pcidev->driver->id_table);
1da177e4
LT
692 }
693 }
694
7fadc87e 695 return 0;
1da177e4
LT
696}
697
698/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
699/**
700 * mpt_device_driver_deregister - DeRegister device driver hooks
701 */
702void
703mpt_device_driver_deregister(int cb_idx)
704{
705 struct mpt_pci_driver *dd_cbfunc;
706 MPT_ADAPTER *ioc;
707
708 if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
709 return;
710
711 dd_cbfunc = MptDeviceDriverHandlers[cb_idx];
712
713 list_for_each_entry(ioc, &ioc_list, list) {
714 if (dd_cbfunc->remove)
715 dd_cbfunc->remove(ioc->pcidev);
716 }
c6678e0c 717
1da177e4
LT
718 MptDeviceDriverHandlers[cb_idx] = NULL;
719}
720
721
722/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
723/**
724 * mpt_get_msg_frame - Obtain a MPT request frame from the pool (of 1024)
725 * allocated per MPT adapter.
726 * @handle: Handle of registered MPT protocol driver
727 * @ioc: Pointer to MPT adapter structure
728 *
729 * Returns pointer to a MPT request frame or %NULL if none are available
730 * or IOC is not active.
731 */
732MPT_FRAME_HDR*
733mpt_get_msg_frame(int handle, MPT_ADAPTER *ioc)
734{
735 MPT_FRAME_HDR *mf;
736 unsigned long flags;
737 u16 req_idx; /* Request index */
738
739 /* validate handle and ioc identifier */
740
741#ifdef MFCNT
742 if (!ioc->active)
743 printk(KERN_WARNING "IOC Not Active! mpt_get_msg_frame returning NULL!\n");
744#endif
745
746 /* If interrupts are not attached, do not return a request frame */
747 if (!ioc->active)
748 return NULL;
749
750 spin_lock_irqsave(&ioc->FreeQlock, flags);
751 if (!list_empty(&ioc->FreeQ)) {
752 int req_offset;
753
754 mf = list_entry(ioc->FreeQ.next, MPT_FRAME_HDR,
755 u.frame.linkage.list);
756 list_del(&mf->u.frame.linkage.list);
82ffb671 757 mf->u.frame.linkage.arg1 = 0;
1da177e4
LT
758 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; /* byte */
759 req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
760 /* u16! */
d335cc38
MED
761 req_idx = req_offset / ioc->req_sz;
762 mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx);
1da177e4
LT
763 mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
764 ioc->RequestNB[req_idx] = ioc->NB_for_64_byte_frame; /* Default, will be changed if necessary in SG generation */
765#ifdef MFCNT
766 ioc->mfcnt++;
767#endif
768 }
769 else
770 mf = NULL;
771 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
772
773#ifdef MFCNT
774 if (mf == NULL)
775 printk(KERN_WARNING "IOC Active. No free Msg Frames! Count 0x%x Max 0x%x\n", ioc->mfcnt, ioc->req_depth);
776 mfcounter++;
777 if (mfcounter == PRINT_MF_COUNT)
778 printk(KERN_INFO "MF Count 0x%x Max 0x%x \n", ioc->mfcnt, ioc->req_depth);
779#endif
780
781 dmfprintk((KERN_INFO MYNAM ": %s: mpt_get_msg_frame(%d,%d), got mf=%p\n",
782 ioc->name, handle, ioc->id, mf));
783 return mf;
784}
785
786/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
787/**
788 * mpt_put_msg_frame - Send a protocol specific MPT request frame
789 * to a IOC.
790 * @handle: Handle of registered MPT protocol driver
791 * @ioc: Pointer to MPT adapter structure
792 * @mf: Pointer to MPT request frame
793 *
794 * This routine posts a MPT request frame to the request post FIFO of a
795 * specific MPT adapter.
796 */
797void
798mpt_put_msg_frame(int handle, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
799{
800 u32 mf_dma_addr;
801 int req_offset;
802 u16 req_idx; /* Request index */
803
804 /* ensure values are reset properly! */
805 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; /* byte */
806 req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
807 /* u16! */
d335cc38
MED
808 req_idx = req_offset / ioc->req_sz;
809 mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx);
1da177e4
LT
810 mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
811
812#ifdef MPT_DEBUG_MSG_FRAME
813 {
814 u32 *m = mf->u.frame.hwhdr.__hdr;
815 int ii, n;
816
817 printk(KERN_INFO MYNAM ": %s: About to Put msg frame @ %p:\n" KERN_INFO " ",
818 ioc->name, m);
819 n = ioc->req_sz/4 - 1;
820 while (m[n] == 0)
821 n--;
822 for (ii=0; ii<=n; ii++) {
823 if (ii && ((ii%8)==0))
824 printk("\n" KERN_INFO " ");
825 printk(" %08x", le32_to_cpu(m[ii]));
826 }
827 printk("\n");
828 }
829#endif
830
c6678e0c 831 mf_dma_addr = (ioc->req_frames_low_dma + req_offset) | ioc->RequestNB[req_idx];
1da177e4
LT
832 dsgprintk((MYIOC_s_INFO_FMT "mf_dma_addr=%x req_idx=%d RequestNB=%x\n", ioc->name, mf_dma_addr, req_idx, ioc->RequestNB[req_idx]));
833 CHIPREG_WRITE32(&ioc->chip->RequestFifo, mf_dma_addr);
834}
835
836/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
837/**
838 * mpt_free_msg_frame - Place MPT request frame back on FreeQ.
839 * @handle: Handle of registered MPT protocol driver
840 * @ioc: Pointer to MPT adapter structure
841 * @mf: Pointer to MPT request frame
842 *
843 * This routine places a MPT request frame back on the MPT adapter's
844 * FreeQ.
845 */
846void
847mpt_free_msg_frame(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
848{
849 unsigned long flags;
850
851 /* Put Request back on FreeQ! */
852 spin_lock_irqsave(&ioc->FreeQlock, flags);
82ffb671 853 mf->u.frame.linkage.arg1 = 0xdeadbeaf; /* signature to know if this mf is freed */
1da177e4
LT
854 list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ);
855#ifdef MFCNT
856 ioc->mfcnt--;
857#endif
858 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
859}
860
861/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
862/**
863 * mpt_add_sge - Place a simple SGE at address pAddr.
864 * @pAddr: virtual address for SGE
865 * @flagslength: SGE flags and data transfer length
866 * @dma_addr: Physical address
867 *
868 * This routine places a MPT request frame back on the MPT adapter's
869 * FreeQ.
870 */
871void
872mpt_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr)
873{
874 if (sizeof(dma_addr_t) == sizeof(u64)) {
875 SGESimple64_t *pSge = (SGESimple64_t *) pAddr;
876 u32 tmp = dma_addr & 0xFFFFFFFF;
877
878 pSge->FlagsLength = cpu_to_le32(flagslength);
879 pSge->Address.Low = cpu_to_le32(tmp);
880 tmp = (u32) ((u64)dma_addr >> 32);
881 pSge->Address.High = cpu_to_le32(tmp);
882
883 } else {
884 SGESimple32_t *pSge = (SGESimple32_t *) pAddr;
885 pSge->FlagsLength = cpu_to_le32(flagslength);
886 pSge->Address = cpu_to_le32(dma_addr);
887 }
888}
889
890/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
891/**
892 * mpt_send_handshake_request - Send MPT request via doorbell
893 * handshake method.
894 * @handle: Handle of registered MPT protocol driver
895 * @ioc: Pointer to MPT adapter structure
896 * @reqBytes: Size of the request in bytes
897 * @req: Pointer to MPT request frame
898 * @sleepFlag: Use schedule if CAN_SLEEP else use udelay.
899 *
900 * This routine is used exclusively to send MptScsiTaskMgmt
901 * requests since they are required to be sent via doorbell handshake.
902 *
903 * NOTE: It is the callers responsibility to byte-swap fields in the
904 * request which are greater than 1 byte in size.
905 *
906 * Returns 0 for success, non-zero for failure.
907 */
908int
909mpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes, u32 *req, int sleepFlag)
910{
911 int r = 0;
912 u8 *req_as_bytes;
913 int ii;
914
915 /* State is known to be good upon entering
916 * this function so issue the bus reset
917 * request.
918 */
919
920 /*
921 * Emulate what mpt_put_msg_frame() does /wrt to sanity
922 * setting cb_idx/req_idx. But ONLY if this request
923 * is in proper (pre-alloc'd) request buffer range...
924 */
925 ii = MFPTR_2_MPT_INDEX(ioc,(MPT_FRAME_HDR*)req);
926 if (reqBytes >= 12 && ii >= 0 && ii < ioc->req_depth) {
927 MPT_FRAME_HDR *mf = (MPT_FRAME_HDR*)req;
928 mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(ii);
929 mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle;
930 }
931
932 /* Make sure there are no doorbells */
933 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
c6678e0c 934
1da177e4
LT
935 CHIPREG_WRITE32(&ioc->chip->Doorbell,
936 ((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
937 ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
938
939 /* Wait for IOC doorbell int */
940 if ((ii = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0) {
941 return ii;
942 }
943
944 /* Read doorbell and check for active bit */
945 if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
946 return -5;
947
948 dhsprintk((KERN_INFO MYNAM ": %s: mpt_send_handshake_request start, WaitCnt=%d\n",
c6678e0c 949 ioc->name, ii));
1da177e4
LT
950
951 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
952
953 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
954 return -2;
955 }
c6678e0c 956
1da177e4
LT
957 /* Send request via doorbell handshake */
958 req_as_bytes = (u8 *) req;
959 for (ii = 0; ii < reqBytes/4; ii++) {
960 u32 word;
961
962 word = ((req_as_bytes[(ii*4) + 0] << 0) |
963 (req_as_bytes[(ii*4) + 1] << 8) |
964 (req_as_bytes[(ii*4) + 2] << 16) |
965 (req_as_bytes[(ii*4) + 3] << 24));
966 CHIPREG_WRITE32(&ioc->chip->Doorbell, word);
967 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
968 r = -3;
969 break;
970 }
971 }
972
973 if (r >= 0 && WaitForDoorbellInt(ioc, 10, sleepFlag) >= 0)
974 r = 0;
975 else
976 r = -4;
977
978 /* Make sure there are no doorbells */
979 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
82ffb671 980
1da177e4
LT
981 return r;
982}
983
82ffb671
CH
984/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
985/**
986 * mpt_host_page_access_control - provides mechanism for the host
987 * driver to control the IOC's Host Page Buffer access.
988 * @ioc: Pointer to MPT adapter structure
989 * @access_control_value: define bits below
990 *
991 * Access Control Value - bits[15:12]
992 * 0h Reserved
993 * 1h Enable Access { MPI_DB_HPBAC_ENABLE_ACCESS }
994 * 2h Disable Access { MPI_DB_HPBAC_DISABLE_ACCESS }
995 * 3h Free Buffer { MPI_DB_HPBAC_FREE_BUFFER }
996 *
997 * Returns 0 for success, non-zero for failure.
998 */
999
1000static int
1001mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag)
1002{
1003 int r = 0;
1004
1005 /* return if in use */
1006 if (CHIPREG_READ32(&ioc->chip->Doorbell)
1007 & MPI_DOORBELL_ACTIVE)
1008 return -1;
1009
1010 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1011
1012 CHIPREG_WRITE32(&ioc->chip->Doorbell,
1013 ((MPI_FUNCTION_HOST_PAGEBUF_ACCESS_CONTROL
1014 <<MPI_DOORBELL_FUNCTION_SHIFT) |
1015 (access_control_value<<12)));
1016
1017 /* Wait for IOC to clear Doorbell Status bit */
1018 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
1019 return -2;
1020 }else
1021 return 0;
1022}
1023
1024/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1025/**
1026 * mpt_host_page_alloc - allocate system memory for the fw
1027 * If we already allocated memory in past, then resend the same pointer.
1028 * ioc@: Pointer to pointer to IOC adapter
1029 * ioc_init@: Pointer to ioc init config page
1030 *
1031 * Returns 0 for success, non-zero for failure.
1032 */
1033static int
1034mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init)
1035{
1036 char *psge;
1037 int flags_length;
1038 u32 host_page_buffer_sz=0;
1039
1040 if(!ioc->HostPageBuffer) {
1041
1042 host_page_buffer_sz =
1043 le32_to_cpu(ioc->facts.HostPageBufferSGE.FlagsLength) & 0xFFFFFF;
1044
1045 if(!host_page_buffer_sz)
1046 return 0; /* fw doesn't need any host buffers */
1047
1048 /* spin till we get enough memory */
1049 while(host_page_buffer_sz > 0) {
1050
1051 if((ioc->HostPageBuffer = pci_alloc_consistent(
1052 ioc->pcidev,
1053 host_page_buffer_sz,
1054 &ioc->HostPageBuffer_dma)) != NULL) {
1055
1056 dinitprintk((MYIOC_s_INFO_FMT
1057 "host_page_buffer @ %p, dma @ %x, sz=%d bytes\n",
1058 ioc->name,
1059 ioc->HostPageBuffer,
1060 ioc->HostPageBuffer_dma,
466544d8 1061 host_page_buffer_sz));
82ffb671
CH
1062 ioc->alloc_total += host_page_buffer_sz;
1063 ioc->HostPageBuffer_sz = host_page_buffer_sz;
1064 break;
1065 }
1066
1067 host_page_buffer_sz -= (4*1024);
1068 }
1069 }
1070
1071 if(!ioc->HostPageBuffer) {
1072 printk(MYIOC_s_ERR_FMT
1073 "Failed to alloc memory for host_page_buffer!\n",
1074 ioc->name);
1075 return -999;
1076 }
1077
1078 psge = (char *)&ioc_init->HostPageBufferSGE;
1079 flags_length = MPI_SGE_FLAGS_SIMPLE_ELEMENT |
1080 MPI_SGE_FLAGS_SYSTEM_ADDRESS |
1081 MPI_SGE_FLAGS_32_BIT_ADDRESSING |
1082 MPI_SGE_FLAGS_HOST_TO_IOC |
1083 MPI_SGE_FLAGS_END_OF_BUFFER;
1084 if (sizeof(dma_addr_t) == sizeof(u64)) {
1085 flags_length |= MPI_SGE_FLAGS_64_BIT_ADDRESSING;
1086 }
1087 flags_length = flags_length << MPI_SGE_FLAGS_SHIFT;
1088 flags_length |= ioc->HostPageBuffer_sz;
1089 mpt_add_sge(psge, flags_length, ioc->HostPageBuffer_dma);
1090 ioc->facts.HostPageBufferSGE = ioc_init->HostPageBufferSGE;
1091
1092return 0;
1093}
1094
1da177e4
LT
1095/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1096/**
1097 * mpt_verify_adapter - Given a unique IOC identifier, set pointer to
1098 * the associated MPT adapter structure.
1099 * @iocid: IOC unique identifier (integer)
1100 * @iocpp: Pointer to pointer to IOC adapter
1101 *
1102 * Returns iocid and sets iocpp.
1103 */
1104int
1105mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp)
1106{
1107 MPT_ADAPTER *ioc;
1108
1109 list_for_each_entry(ioc,&ioc_list,list) {
1110 if (ioc->id == iocid) {
1111 *iocpp =ioc;
1112 return iocid;
c6678e0c 1113 }
1da177e4 1114 }
c6678e0c 1115
1da177e4
LT
1116 *iocpp = NULL;
1117 return -1;
1118}
1119
2a238ea5
MED
1120int
1121mpt_alt_ioc_wait(MPT_ADAPTER *ioc)
1122{
1123 int loop_count = 30 * 4; /* Wait 30 seconds */
1124 int status = -1; /* -1 means failed to get board READY */
1125
1126 do {
1127 spin_lock(&ioc->initializing_hba_lock);
1128 if (ioc->initializing_hba_lock_flag == 0) {
1129 ioc->initializing_hba_lock_flag=1;
1130 spin_unlock(&ioc->initializing_hba_lock);
1131 status = 0;
1132 break;
1133 }
1134 spin_unlock(&ioc->initializing_hba_lock);
1135 set_current_state(TASK_INTERRUPTIBLE);
1136 schedule_timeout(HZ/4);
1137 } while (--loop_count);
1138
1139 return status;
1140}
1141
1142/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1143/*
1144 * mpt_bringup_adapter - This is a wrapper function for mpt_do_ioc_recovery
1145 * @ioc: Pointer to MPT adapter structure
1146 * @sleepFlag: Use schedule if CAN_SLEEP else use udelay.
1147 *
1148 * This routine performs all the steps necessary to bring the IOC
1149 * to a OPERATIONAL state.
1150 *
1151 * Special Note: This function was added with spin lock's so as to allow
1152 * the dv(domain validation) work thread to succeed on the other channel
1153 * that maybe occuring at the same time when this function is called.
1154 * Without this lock, the dv would fail when message frames were
1155 * requested during hba bringup on the alternate ioc.
1156 */
1157static int
1158mpt_bringup_adapter(MPT_ADAPTER *ioc, int sleepFlag)
1159{
1160 int r;
1161
1162 if(ioc->alt_ioc) {
1163 if((r=mpt_alt_ioc_wait(ioc->alt_ioc)!=0))
1164 return r;
1165 }
1166
1167 r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP,
1168 CAN_SLEEP);
1169
1170 if(ioc->alt_ioc) {
1171 spin_lock(&ioc->alt_ioc->initializing_hba_lock);
1172 ioc->alt_ioc->initializing_hba_lock_flag=0;
1173 spin_unlock(&ioc->alt_ioc->initializing_hba_lock);
1174 }
1175
1176return r;
1177}
1178
1da177e4
LT
1179/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1180/*
7fadc87e 1181 * mpt_attach - Install a PCI intelligent MPT adapter.
1da177e4
LT
1182 * @pdev: Pointer to pci_dev structure
1183 *
1184 * This routine performs all the steps necessary to bring the IOC of
1185 * a MPT adapter to a OPERATIONAL state. This includes registering
1186 * memory regions, registering the interrupt, and allocating request
1187 * and reply memory pools.
1188 *
1189 * This routine also pre-fetches the LAN MAC address of a Fibre Channel
1190 * MPT adapter.
1191 *
1192 * Returns 0 for success, non-zero for failure.
1193 *
1194 * TODO: Add support for polled controllers
1195 */
7fadc87e
MED
1196int
1197mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
1da177e4
LT
1198{
1199 MPT_ADAPTER *ioc;
1200 u8 __iomem *mem;
1201 unsigned long mem_phys;
1202 unsigned long port;
1203 u32 msize;
1204 u32 psize;
1205 int ii;
1206 int r = -ENODEV;
1da177e4
LT
1207 u8 revision;
1208 u8 pcixcmd;
1209 static int mpt_ids = 0;
1210#ifdef CONFIG_PROC_FS
1211 struct proc_dir_entry *dent, *ent;
1212#endif
1213
1214 if (pci_enable_device(pdev))
1215 return r;
c6678e0c 1216
1da177e4 1217 dinitprintk((KERN_WARNING MYNAM ": mpt_adapter_install\n"));
c6678e0c 1218
7fadc87e 1219 if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
1da177e4
LT
1220 dprintk((KERN_INFO MYNAM
1221 ": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n"));
7fadc87e 1222 } else if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
1da177e4
LT
1223 printk(KERN_WARNING MYNAM ": 32 BIT PCI BUS DMA ADDRESSING NOT SUPPORTED\n");
1224 return r;
1225 }
1226
7fadc87e 1227 if (!pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK))
1da177e4
LT
1228 dprintk((KERN_INFO MYNAM
1229 ": Using 64 bit consistent mask\n"));
1230 else
1231 dprintk((KERN_INFO MYNAM
1232 ": Not using 64 bit consistent mask\n"));
1233
1ca00bb7 1234 ioc = kzalloc(sizeof(MPT_ADAPTER), GFP_ATOMIC);
1da177e4
LT
1235 if (ioc == NULL) {
1236 printk(KERN_ERR MYNAM ": ERROR - Insufficient memory to add adapter!\n");
1237 return -ENOMEM;
1238 }
1da177e4
LT
1239 ioc->alloc_total = sizeof(MPT_ADAPTER);
1240 ioc->req_sz = MPT_DEFAULT_FRAME_SIZE; /* avoid div by zero! */
1241 ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
c6678e0c 1242
1da177e4
LT
1243 ioc->pcidev = pdev;
1244 ioc->diagPending = 0;
1245 spin_lock_init(&ioc->diagLock);
05e8ec17
MR
1246 spin_lock_init(&ioc->fc_rescan_work_lock);
1247 spin_lock_init(&ioc->fc_rport_lock);
2a238ea5 1248 spin_lock_init(&ioc->initializing_hba_lock);
1da177e4
LT
1249
1250 /* Initialize the event logging.
1251 */
1252 ioc->eventTypes = 0; /* None */
1253 ioc->eventContext = 0;
1254 ioc->eventLogSize = 0;
1255 ioc->events = NULL;
1256
1257#ifdef MFCNT
1258 ioc->mfcnt = 0;
1259#endif
1260
1261 ioc->cached_fw = NULL;
1262
1263 /* Initilize SCSI Config Data structure
1264 */
466544d8 1265 memset(&ioc->spi_data, 0, sizeof(SpiCfgData));
1da177e4
LT
1266
1267 /* Initialize the running configQ head.
1268 */
1269 INIT_LIST_HEAD(&ioc->configQ);
1270
05e8ec17
MR
1271 /* Initialize the fc rport list head.
1272 */
1273 INIT_LIST_HEAD(&ioc->fc_rports);
1274
1da177e4
LT
1275 /* Find lookup slot. */
1276 INIT_LIST_HEAD(&ioc->list);
1277 ioc->id = mpt_ids++;
c6678e0c 1278
1da177e4
LT
1279 mem_phys = msize = 0;
1280 port = psize = 0;
1281 for (ii=0; ii < DEVICE_COUNT_RESOURCE; ii++) {
1282 if (pci_resource_flags(pdev, ii) & PCI_BASE_ADDRESS_SPACE_IO) {
1283 /* Get I/O space! */
1284 port = pci_resource_start(pdev, ii);
1285 psize = pci_resource_len(pdev,ii);
1286 } else {
1287 /* Get memmap */
1288 mem_phys = pci_resource_start(pdev, ii);
1289 msize = pci_resource_len(pdev,ii);
1290 break;
1291 }
1292 }
1293 ioc->mem_size = msize;
1294
1295 if (ii == DEVICE_COUNT_RESOURCE) {
1296 printk(KERN_ERR MYNAM ": ERROR - MPT adapter has no memory regions defined!\n");
1297 kfree(ioc);
1298 return -EINVAL;
1299 }
1300
1301 dinitprintk((KERN_INFO MYNAM ": MPT adapter @ %lx, msize=%dd bytes\n", mem_phys, msize));
1302 dinitprintk((KERN_INFO MYNAM ": (port i/o @ %lx, psize=%dd bytes)\n", port, psize));
1303
1304 mem = NULL;
1305 /* Get logical ptr for PciMem0 space */
1306 /*mem = ioremap(mem_phys, msize);*/
1307 mem = ioremap(mem_phys, 0x100);
1308 if (mem == NULL) {
1309 printk(KERN_ERR MYNAM ": ERROR - Unable to map adapter memory!\n");
1310 kfree(ioc);
1311 return -EINVAL;
1312 }
1313 ioc->memmap = mem;
1314 dinitprintk((KERN_INFO MYNAM ": mem = %p, mem_phys = %lx\n", mem, mem_phys));
1315
1316 dinitprintk((KERN_INFO MYNAM ": facts @ %p, pfacts[0] @ %p\n",
1317 &ioc->facts, &ioc->pfacts[0]));
1318
1319 ioc->mem_phys = mem_phys;
1320 ioc->chip = (SYSIF_REGS __iomem *)mem;
1321
1322 /* Save Port IO values in case we need to do downloadboot */
1323 {
1324 u8 *pmem = (u8*)port;
1325 ioc->pio_mem_phys = port;
1326 ioc->pio_chip = (SYSIF_REGS __iomem *)pmem;
1327 }
1328
1329 if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC909) {
1330 ioc->prod_name = "LSIFC909";
1331 ioc->bus_type = FC;
1332 }
c6678e0c 1333 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929) {
1da177e4
LT
1334 ioc->prod_name = "LSIFC929";
1335 ioc->bus_type = FC;
1336 }
1337 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC919) {
1338 ioc->prod_name = "LSIFC919";
1339 ioc->bus_type = FC;
1340 }
1341 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929X) {
1342 pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
1343 ioc->bus_type = FC;
1344 if (revision < XL_929) {
1345 ioc->prod_name = "LSIFC929X";
1346 /* 929X Chip Fix. Set Split transactions level
1347 * for PCIX. Set MOST bits to zero.
1348 */
1349 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1350 pcixcmd &= 0x8F;
1351 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1352 } else {
1353 ioc->prod_name = "LSIFC929XL";
1354 /* 929XL Chip Fix. Set MMRBC to 0x08.
1355 */
1356 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1357 pcixcmd |= 0x08;
1358 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1359 }
1360 }
1361 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC919X) {
1362 ioc->prod_name = "LSIFC919X";
1363 ioc->bus_type = FC;
1364 /* 919X Chip Fix. Set Split transactions level
1365 * for PCIX. Set MOST bits to zero.
1366 */
1367 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1368 pcixcmd &= 0x8F;
1369 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1370 }
3fadc59d
MED
1371 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC939X) {
1372 ioc->prod_name = "LSIFC939X";
1373 ioc->bus_type = FC;
1374 ioc->errata_flag_1064 = 1;
1375 }
1376 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC949X) {
1377 ioc->prod_name = "LSIFC949X";
1378 ioc->bus_type = FC;
1379 ioc->errata_flag_1064 = 1;
1380 }
6d5b0c31
ME
1381 else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC949E) {
1382 ioc->prod_name = "LSIFC949E";
1383 ioc->bus_type = FC;
1384 }
1da177e4
LT
1385 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_53C1030) {
1386 ioc->prod_name = "LSI53C1030";
a9b2937a 1387 ioc->bus_type = SPI;
1da177e4
LT
1388 /* 1030 Chip Fix. Disable Split transactions
1389 * for PCIX. Set MOST bits to zero if Rev < C0( = 8).
1390 */
1391 pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
1392 if (revision < C0_1030) {
1393 pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1394 pcixcmd &= 0x8F;
1395 pci_write_config_byte(pdev, 0x6a, pcixcmd);
1396 }
1397 }
1398 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_1030_53C1035) {
1399 ioc->prod_name = "LSI53C1035";
a9b2937a 1400 ioc->bus_type = SPI;
1da177e4 1401 }
82ffb671
CH
1402 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1064) {
1403 ioc->prod_name = "LSISAS1064";
1404 ioc->bus_type = SAS;
1405 ioc->errata_flag_1064 = 1;
1406 }
1407 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1066) {
1408 ioc->prod_name = "LSISAS1066";
1409 ioc->bus_type = SAS;
1410 ioc->errata_flag_1064 = 1;
1411 }
1412 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1068) {
1413 ioc->prod_name = "LSISAS1068";
1414 ioc->bus_type = SAS;
1415 ioc->errata_flag_1064 = 1;
1416 }
1417 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1064E) {
1418 ioc->prod_name = "LSISAS1064E";
1419 ioc->bus_type = SAS;
1420 }
1421 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1066E) {
1422 ioc->prod_name = "LSISAS1066E";
1423 ioc->bus_type = SAS;
1424 }
1425 else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1068E) {
1426 ioc->prod_name = "LSISAS1068E";
1427 ioc->bus_type = SAS;
1428 }
1da177e4 1429
3fadc59d
MED
1430 if (ioc->errata_flag_1064)
1431 pci_disable_io_access(pdev);
1432
1da177e4
LT
1433 sprintf(ioc->name, "ioc%d", ioc->id);
1434
1435 spin_lock_init(&ioc->FreeQlock);
1436
1437 /* Disable all! */
1438 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1439 ioc->active = 0;
1440 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1441
1442 /* Set lookup ptr. */
1443 list_add_tail(&ioc->list, &ioc_list);
1444
1445 ioc->pci_irq = -1;
1446 if (pdev->irq) {
1447 r = request_irq(pdev->irq, mpt_interrupt, SA_SHIRQ, ioc->name, ioc);
1448
1449 if (r < 0) {
1450#ifndef __sparc__
1451 printk(MYIOC_s_ERR_FMT "Unable to allocate interrupt %d!\n",
1452 ioc->name, pdev->irq);
1453#else
1454 printk(MYIOC_s_ERR_FMT "Unable to allocate interrupt %s!\n",
1455 ioc->name, __irq_itoa(pdev->irq));
1456#endif
1457 list_del(&ioc->list);
1458 iounmap(mem);
1459 kfree(ioc);
1460 return -EBUSY;
1461 }
1462
1463 ioc->pci_irq = pdev->irq;
1464
1465 pci_set_master(pdev); /* ?? */
1466 pci_set_drvdata(pdev, ioc);
1467
1468#ifndef __sparc__
1469 dprintk((KERN_INFO MYNAM ": %s installed at interrupt %d\n", ioc->name, pdev->irq));
1470#else
1471 dprintk((KERN_INFO MYNAM ": %s installed at interrupt %s\n", ioc->name, __irq_itoa(pdev->irq)));
1472#endif
1473 }
1474
7fadc87e 1475 /* Check for "bound ports" (929, 929X, 1030, 1035) to reduce redundant resets.
1da177e4
LT
1476 */
1477 mpt_detect_bound_ports(ioc, pdev);
1478
2a238ea5 1479 if ((r = mpt_bringup_adapter(ioc, CAN_SLEEP)) != 0){
1da177e4
LT
1480 printk(KERN_WARNING MYNAM
1481 ": WARNING - %s did not initialize properly! (%d)\n",
1482 ioc->name, r);
1483
1484 list_del(&ioc->list);
1485 free_irq(ioc->pci_irq, ioc);
1486 iounmap(mem);
1487 kfree(ioc);
1488 pci_set_drvdata(pdev, NULL);
1489 return r;
1490 }
1491
1492 /* call per device driver probe entry point */
1493 for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
1494 if(MptDeviceDriverHandlers[ii] &&
1495 MptDeviceDriverHandlers[ii]->probe) {
1496 MptDeviceDriverHandlers[ii]->probe(pdev,id);
1497 }
1498 }
1499
1500#ifdef CONFIG_PROC_FS
1501 /*
1502 * Create "/proc/mpt/iocN" subdirectory entry for each MPT adapter.
1503 */
1504 dent = proc_mkdir(ioc->name, mpt_proc_root_dir);
1505 if (dent) {
1506 ent = create_proc_entry("info", S_IFREG|S_IRUGO, dent);
1507 if (ent) {
1508 ent->read_proc = procmpt_iocinfo_read;
1509 ent->data = ioc;
1510 }
1511 ent = create_proc_entry("summary", S_IFREG|S_IRUGO, dent);
1512 if (ent) {
1513 ent->read_proc = procmpt_summary_read;
1514 ent->data = ioc;
1515 }
1516 }
1517#endif
1518
1519 return 0;
1520}
1521
1522/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1523/*
7fadc87e 1524 * mpt_detach - Remove a PCI intelligent MPT adapter.
1da177e4
LT
1525 * @pdev: Pointer to pci_dev structure
1526 *
1527 */
1528
7fadc87e
MED
1529void
1530mpt_detach(struct pci_dev *pdev)
1da177e4
LT
1531{
1532 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1533 char pname[32];
1534 int ii;
1535
1536 sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/summary", ioc->name);
1537 remove_proc_entry(pname, NULL);
1538 sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/info", ioc->name);
1539 remove_proc_entry(pname, NULL);
1540 sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s", ioc->name);
1541 remove_proc_entry(pname, NULL);
c6678e0c 1542
1da177e4
LT
1543 /* call per device driver remove entry point */
1544 for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
1545 if(MptDeviceDriverHandlers[ii] &&
1546 MptDeviceDriverHandlers[ii]->remove) {
1547 MptDeviceDriverHandlers[ii]->remove(pdev);
1548 }
1549 }
c6678e0c 1550
1da177e4
LT
1551 /* Disable interrupts! */
1552 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1553
1554 ioc->active = 0;
1555 synchronize_irq(pdev->irq);
1556
1557 /* Clear any lingering interrupt */
1558 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1559
1560 CHIPREG_READ32(&ioc->chip->IntStatus);
1561
1562 mpt_adapter_dispose(ioc);
1563
1564 pci_set_drvdata(pdev, NULL);
1565}
1566
1da177e4
LT
1567/**************************************************************************
1568 * Power Management
1569 */
1570#ifdef CONFIG_PM
1571/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1572/*
7fadc87e 1573 * mpt_suspend - Fusion MPT base driver suspend routine.
1da177e4
LT
1574 *
1575 *
1576 */
7fadc87e
MED
1577int
1578mpt_suspend(struct pci_dev *pdev, pm_message_t state)
1da177e4
LT
1579{
1580 u32 device_state;
1581 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1da177e4 1582
2a569579 1583 device_state=pci_choose_state(pdev, state);
1da177e4
LT
1584
1585 printk(MYIOC_s_INFO_FMT
1586 "pci-suspend: pdev=0x%p, slot=%s, Entering operating state [D%d]\n",
1587 ioc->name, pdev, pci_name(pdev), device_state);
1588
1da177e4
LT
1589 pci_save_state(pdev);
1590
1591 /* put ioc into READY_STATE */
1592 if(SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, CAN_SLEEP)) {
1593 printk(MYIOC_s_ERR_FMT
1594 "pci-suspend: IOC msg unit reset failed!\n", ioc->name);
1595 }
1596
1597 /* disable interrupts */
1598 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1599 ioc->active = 0;
1600
1601 /* Clear any lingering interrupt */
1602 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1603
1604 pci_disable_device(pdev);
1605 pci_set_power_state(pdev, device_state);
1606
1607 return 0;
1608}
1609
1610/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1611/*
7fadc87e 1612 * mpt_resume - Fusion MPT base driver resume routine.
1da177e4
LT
1613 *
1614 *
1615 */
7fadc87e
MED
1616int
1617mpt_resume(struct pci_dev *pdev)
1da177e4
LT
1618{
1619 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1620 u32 device_state = pdev->current_state;
1621 int recovery_state;
1622 int ii;
c6678e0c 1623
1da177e4
LT
1624 printk(MYIOC_s_INFO_FMT
1625 "pci-resume: pdev=0x%p, slot=%s, Previous operating state [D%d]\n",
1626 ioc->name, pdev, pci_name(pdev), device_state);
1627
1628 pci_set_power_state(pdev, 0);
1629 pci_restore_state(pdev);
1630 pci_enable_device(pdev);
1631
1632 /* enable interrupts */
569b11dc 1633 CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
1da177e4
LT
1634 ioc->active = 1;
1635
1636 /* F/W not running */
1637 if(!CHIPREG_READ32(&ioc->chip->Doorbell)) {
1638 /* enable domain validation flags */
1639 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
1640 ioc->spi_data.dvStatus[ii] |= MPT_SCSICFG_NEED_DV;
1641 }
1642 }
1643
1644 printk(MYIOC_s_INFO_FMT
1645 "pci-resume: ioc-state=0x%x,doorbell=0x%x\n",
1646 ioc->name,
1647 (mpt_GetIocState(ioc, 1) >> MPI_IOC_STATE_SHIFT),
1648 CHIPREG_READ32(&ioc->chip->Doorbell));
1649
1650 /* bring ioc to operational state */
1651 if ((recovery_state = mpt_do_ioc_recovery(ioc,
1652 MPT_HOSTEVENT_IOC_RECOVER, CAN_SLEEP)) != 0) {
1653 printk(MYIOC_s_INFO_FMT
1654 "pci-resume: Cannot recover, error:[%x]\n",
1655 ioc->name, recovery_state);
1656 } else {
1657 printk(MYIOC_s_INFO_FMT
1658 "pci-resume: success\n", ioc->name);
1659 }
1660
1da177e4
LT
1661 return 0;
1662}
1663#endif
1664
1665/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1666/*
1667 * mpt_do_ioc_recovery - Initialize or recover MPT adapter.
1668 * @ioc: Pointer to MPT adapter structure
1669 * @reason: Event word / reason
1670 * @sleepFlag: Use schedule if CAN_SLEEP else use udelay.
1671 *
1672 * This routine performs all the steps necessary to bring the IOC
1673 * to a OPERATIONAL state.
1674 *
1675 * This routine also pre-fetches the LAN MAC address of a Fibre Channel
1676 * MPT adapter.
1677 *
1678 * Returns:
1679 * 0 for success
1680 * -1 if failed to get board READY
1681 * -2 if READY but IOCFacts Failed
1682 * -3 if READY but PrimeIOCFifos Failed
1683 * -4 if READY but IOCInit Failed
1684 */
1685static int
1686mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
1687{
1688 int hard_reset_done = 0;
1689 int alt_ioc_ready = 0;
1690 int hard;
1691 int rc=0;
1692 int ii;
1693 int handlers;
1694 int ret = 0;
1695 int reset_alt_ioc_active = 0;
1696
1697 printk(KERN_INFO MYNAM ": Initiating %s %s\n",
1698 ioc->name, reason==MPT_HOSTEVENT_IOC_BRINGUP ? "bringup" : "recovery");
1699
1700 /* Disable reply interrupts (also blocks FreeQ) */
1701 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1702 ioc->active = 0;
1703
1704 if (ioc->alt_ioc) {
1705 if (ioc->alt_ioc->active)
1706 reset_alt_ioc_active = 1;
1707
1708 /* Disable alt-IOC's reply interrupts (and FreeQ) for a bit ... */
1709 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, 0xFFFFFFFF);
1710 ioc->alt_ioc->active = 0;
1711 }
1712
1713 hard = 1;
1714 if (reason == MPT_HOSTEVENT_IOC_BRINGUP)
1715 hard = 0;
1716
1717 if ((hard_reset_done = MakeIocReady(ioc, hard, sleepFlag)) < 0) {
1718 if (hard_reset_done == -4) {
1719 printk(KERN_WARNING MYNAM ": %s Owned by PEER..skipping!\n",
1720 ioc->name);
1721
1722 if (reset_alt_ioc_active && ioc->alt_ioc) {
1723 /* (re)Enable alt-IOC! (reply interrupt, FreeQ) */
1724 dprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
1725 ioc->alt_ioc->name));
569b11dc 1726 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
1da177e4
LT
1727 ioc->alt_ioc->active = 1;
1728 }
1729
1730 } else {
1731 printk(KERN_WARNING MYNAM ": %s NOT READY WARNING!\n",
1732 ioc->name);
1733 }
1734 return -1;
1735 }
1736
1737 /* hard_reset_done = 0 if a soft reset was performed
1738 * and 1 if a hard reset was performed.
1739 */
1740 if (hard_reset_done && reset_alt_ioc_active && ioc->alt_ioc) {
1741 if ((rc = MakeIocReady(ioc->alt_ioc, 0, sleepFlag)) == 0)
1742 alt_ioc_ready = 1;
1743 else
1744 printk(KERN_WARNING MYNAM
1745 ": alt-%s: Not ready WARNING!\n",
1746 ioc->alt_ioc->name);
1747 }
1748
1749 for (ii=0; ii<5; ii++) {
1750 /* Get IOC facts! Allow 5 retries */
1751 if ((rc = GetIocFacts(ioc, sleepFlag, reason)) == 0)
1752 break;
1753 }
c6678e0c 1754
1da177e4
LT
1755
1756 if (ii == 5) {
1757 dinitprintk((MYIOC_s_INFO_FMT "Retry IocFacts failed rc=%x\n", ioc->name, rc));
1758 ret = -2;
1759 } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
1760 MptDisplayIocCapabilities(ioc);
1761 }
c6678e0c 1762
1da177e4
LT
1763 if (alt_ioc_ready) {
1764 if ((rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason)) != 0) {
1765 dinitprintk((MYIOC_s_INFO_FMT "Initial Alt IocFacts failed rc=%x\n", ioc->name, rc));
1766 /* Retry - alt IOC was initialized once
1767 */
1768 rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason);
1769 }
1770 if (rc) {
1771 dinitprintk((MYIOC_s_INFO_FMT "Retry Alt IocFacts failed rc=%x\n", ioc->name, rc));
1772 alt_ioc_ready = 0;
1773 reset_alt_ioc_active = 0;
1774 } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
1775 MptDisplayIocCapabilities(ioc->alt_ioc);
1776 }
1777 }
1778
1779 /* Prime reply & request queues!
1780 * (mucho alloc's) Must be done prior to
1781 * init as upper addresses are needed for init.
1782 * If fails, continue with alt-ioc processing
1783 */
1784 if ((ret == 0) && ((rc = PrimeIocFifos(ioc)) != 0))
1785 ret = -3;
1786
1787 /* May need to check/upload firmware & data here!
1788 * If fails, continue with alt-ioc processing
1789 */
1790 if ((ret == 0) && ((rc = SendIocInit(ioc, sleepFlag)) != 0))
1791 ret = -4;
1792// NEW!
1793 if (alt_ioc_ready && ((rc = PrimeIocFifos(ioc->alt_ioc)) != 0)) {
1794 printk(KERN_WARNING MYNAM ": alt-%s: (%d) FIFO mgmt alloc WARNING!\n",
1795 ioc->alt_ioc->name, rc);
1796 alt_ioc_ready = 0;
1797 reset_alt_ioc_active = 0;
1798 }
1799
1800 if (alt_ioc_ready) {
1801 if ((rc = SendIocInit(ioc->alt_ioc, sleepFlag)) != 0) {
1802 alt_ioc_ready = 0;
1803 reset_alt_ioc_active = 0;
1804 printk(KERN_WARNING MYNAM
1805 ": alt-%s: (%d) init failure WARNING!\n",
1806 ioc->alt_ioc->name, rc);
1807 }
1808 }
1809
1810 if (reason == MPT_HOSTEVENT_IOC_BRINGUP){
1811 if (ioc->upload_fw) {
1812 ddlprintk((MYIOC_s_INFO_FMT
1813 "firmware upload required!\n", ioc->name));
1814
1815 /* Controller is not operational, cannot do upload
1816 */
1817 if (ret == 0) {
1818 rc = mpt_do_upload(ioc, sleepFlag);
466544d8
MED
1819 if (rc == 0) {
1820 if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) {
1821 /*
1822 * Maintain only one pointer to FW memory
1823 * so there will not be two attempt to
1824 * downloadboot onboard dual function
1825 * chips (mpt_adapter_disable,
1826 * mpt_diag_reset)
1827 */
1828 ioc->cached_fw = NULL;
1829 ddlprintk((MYIOC_s_INFO_FMT ": mpt_upload: alt_%s has cached_fw=%p \n",
1830 ioc->name, ioc->alt_ioc->name, ioc->alt_ioc->cached_fw));
1831 }
1832 } else {
1da177e4 1833 printk(KERN_WARNING MYNAM ": firmware upload failure!\n");
466544d8
MED
1834 ret = -5;
1835 }
1da177e4
LT
1836 }
1837 }
1838 }
1839
1840 if (ret == 0) {
1841 /* Enable! (reply interrupt) */
569b11dc 1842 CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
1da177e4
LT
1843 ioc->active = 1;
1844 }
1845
1846 if (reset_alt_ioc_active && ioc->alt_ioc) {
1847 /* (re)Enable alt-IOC! (reply interrupt) */
c6678e0c 1848 dinitprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
1da177e4 1849 ioc->alt_ioc->name));
569b11dc 1850 CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
1da177e4
LT
1851 ioc->alt_ioc->active = 1;
1852 }
1853
7fadc87e 1854 /* Enable MPT base driver management of EventNotification
1da177e4
LT
1855 * and EventAck handling.
1856 */
1857 if ((ret == 0) && (!ioc->facts.EventState))
1858 (void) SendEventNotification(ioc, 1); /* 1=Enable EventNotification */
1859
1860 if (ioc->alt_ioc && alt_ioc_ready && !ioc->alt_ioc->facts.EventState)
1861 (void) SendEventNotification(ioc->alt_ioc, 1); /* 1=Enable EventNotification */
1862
7fadc87e 1863 /* Add additional "reason" check before call to GetLanConfigPages
1da177e4
LT
1864 * (combined with GetIoUnitPage2 call). This prevents a somewhat
1865 * recursive scenario; GetLanConfigPages times out, timer expired
1866 * routine calls HardResetHandler, which calls into here again,
1867 * and we try GetLanConfigPages again...
1868 */
1869 if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) {
82ffb671
CH
1870 if (ioc->bus_type == SAS) {
1871
1872 /* clear persistency table */
1873 if(ioc->facts.IOCExceptions &
1874 MPI_IOCFACTS_EXCEPT_PERSISTENT_TABLE_FULL) {
1875 ret = mptbase_sas_persist_operation(ioc,
1876 MPI_SAS_OP_CLEAR_NOT_PRESENT);
1877 if(ret != 0)
1878 return -1;
1879 }
1880
1881 /* Find IM volumes
1882 */
1883 mpt_findImVolumes(ioc);
1884
1885 } else if (ioc->bus_type == FC) {
1da177e4
LT
1886 /*
1887 * Pre-fetch FC port WWN and stuff...
1888 * (FCPortPage0_t stuff)
1889 */
1890 for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
05e8ec17 1891 (void) mptbase_GetFcPortPage0(ioc, ii);
1da177e4
LT
1892 }
1893
1894 if ((ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) &&
1895 (ioc->lan_cnfg_page0.Header.PageLength == 0)) {
1896 /*
1897 * Pre-fetch the ports LAN MAC address!
1898 * (LANPage1_t stuff)
1899 */
1900 (void) GetLanConfigPages(ioc);
1901#ifdef MPT_DEBUG
1902 {
1903 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
1904 dprintk((MYIOC_s_INFO_FMT "LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
1905 ioc->name, a[5], a[4], a[3], a[2], a[1], a[0] ));
1906 }
1907#endif
1908 }
1909 } else {
1910 /* Get NVRAM and adapter maximums from SPP 0 and 2
1911 */
1912 mpt_GetScsiPortSettings(ioc, 0);
1913
1914 /* Get version and length of SDP 1
1915 */
1916 mpt_readScsiDevicePageHeaders(ioc, 0);
1917
1918 /* Find IM volumes
1919 */
c6678e0c 1920 if (ioc->facts.MsgVersion >= MPI_VERSION_01_02)
1da177e4
LT
1921 mpt_findImVolumes(ioc);
1922
1923 /* Check, and possibly reset, the coalescing value
1924 */
1925 mpt_read_ioc_pg_1(ioc);
1926
1927 mpt_read_ioc_pg_4(ioc);
1928 }
1929
1930 GetIoUnitPage2(ioc);
1931 }
1932
1933 /*
1934 * Call each currently registered protocol IOC reset handler
1935 * with post-reset indication.
1936 * NOTE: If we're doing _IOC_BRINGUP, there can be no
1937 * MptResetHandlers[] registered yet.
1938 */
1939 if (hard_reset_done) {
1940 rc = handlers = 0;
1941 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
1942 if ((ret == 0) && MptResetHandlers[ii]) {
1943 dprintk((MYIOC_s_INFO_FMT "Calling IOC post_reset handler #%d\n",
1944 ioc->name, ii));
1945 rc += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_POST_RESET);
1946 handlers++;
1947 }
1948
1949 if (alt_ioc_ready && MptResetHandlers[ii]) {
c6678e0c 1950 drsprintk((MYIOC_s_INFO_FMT "Calling alt-%s post_reset handler #%d\n",
1da177e4
LT
1951 ioc->name, ioc->alt_ioc->name, ii));
1952 rc += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_POST_RESET);
1953 handlers++;
1954 }
1955 }
1956 /* FIXME? Examine results here? */
1957 }
1958
1959 return ret;
1960}
1961
1962/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1963/*
1964 * mpt_detect_bound_ports - Search for PCI bus/dev_function
1965 * which matches PCI bus/dev_function (+/-1) for newly discovered 929,
1966 * 929X, 1030 or 1035.
1967 * @ioc: Pointer to MPT adapter structure
1968 * @pdev: Pointer to (struct pci_dev) structure
1969 *
1970 * If match on PCI dev_function +/-1 is found, bind the two MPT adapters
1971 * using alt_ioc pointer fields in their %MPT_ADAPTER structures.
1972 */
1973static void
1974mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev)
1975{
7fadc87e
MED
1976 struct pci_dev *peer=NULL;
1977 unsigned int slot = PCI_SLOT(pdev->devfn);
1978 unsigned int func = PCI_FUNC(pdev->devfn);
1da177e4
LT
1979 MPT_ADAPTER *ioc_srch;
1980
7fadc87e
MED
1981 dprintk((MYIOC_s_INFO_FMT "PCI device %s devfn=%x/%x,"
1982 " searching for devfn match on %x or %x\n",
c6678e0c
CH
1983 ioc->name, pci_name(pdev), pdev->bus->number,
1984 pdev->devfn, func-1, func+1));
7fadc87e
MED
1985
1986 peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func-1));
1987 if (!peer) {
1988 peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func+1));
1989 if (!peer)
1990 return;
1991 }
1da177e4
LT
1992
1993 list_for_each_entry(ioc_srch, &ioc_list, list) {
1994 struct pci_dev *_pcidev = ioc_srch->pcidev;
7fadc87e 1995 if (_pcidev == peer) {
1da177e4
LT
1996 /* Paranoia checks */
1997 if (ioc->alt_ioc != NULL) {
1998 printk(KERN_WARNING MYNAM ": Oops, already bound (%s <==> %s)!\n",
7fadc87e 1999 ioc->name, ioc->alt_ioc->name);
1da177e4
LT
2000 break;
2001 } else if (ioc_srch->alt_ioc != NULL) {
2002 printk(KERN_WARNING MYNAM ": Oops, already bound (%s <==> %s)!\n",
7fadc87e 2003 ioc_srch->name, ioc_srch->alt_ioc->name);
1da177e4
LT
2004 break;
2005 }
2006 dprintk((KERN_INFO MYNAM ": FOUND! binding %s <==> %s\n",
7fadc87e 2007 ioc->name, ioc_srch->name));
1da177e4
LT
2008 ioc_srch->alt_ioc = ioc;
2009 ioc->alt_ioc = ioc_srch;
1da177e4
LT
2010 }
2011 }
7fadc87e 2012 pci_dev_put(peer);
1da177e4
LT
2013}
2014
2015/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2016/*
2017 * mpt_adapter_disable - Disable misbehaving MPT adapter.
2018 * @this: Pointer to MPT adapter structure
2019 */
2020static void
2021mpt_adapter_disable(MPT_ADAPTER *ioc)
2022{
2023 int sz;
2024 int ret;
2025
2026 if (ioc->cached_fw != NULL) {
2027 ddlprintk((KERN_INFO MYNAM ": mpt_adapter_disable: Pushing FW onto adapter\n"));
82ffb671 2028 if ((ret = mpt_downloadboot(ioc, (MpiFwHeader_t *)ioc->cached_fw, NO_SLEEP)) < 0) {
1da177e4
LT
2029 printk(KERN_WARNING MYNAM
2030 ": firmware downloadboot failure (%d)!\n", ret);
2031 }
2032 }
2033
2034 /* Disable adapter interrupts! */
2035 CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
2036 ioc->active = 0;
2037 /* Clear any lingering interrupt */
2038 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
2039
2040 if (ioc->alloc != NULL) {
2041 sz = ioc->alloc_sz;
2042 dexitprintk((KERN_INFO MYNAM ": %s.free @ %p, sz=%d bytes\n",
2043 ioc->name, ioc->alloc, ioc->alloc_sz));
2044 pci_free_consistent(ioc->pcidev, sz,
2045 ioc->alloc, ioc->alloc_dma);
2046 ioc->reply_frames = NULL;
2047 ioc->req_frames = NULL;
2048 ioc->alloc = NULL;
2049 ioc->alloc_total -= sz;
2050 }
2051
2052 if (ioc->sense_buf_pool != NULL) {
2053 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
2054 pci_free_consistent(ioc->pcidev, sz,
2055 ioc->sense_buf_pool, ioc->sense_buf_pool_dma);
2056 ioc->sense_buf_pool = NULL;
2057 ioc->alloc_total -= sz;
2058 }
2059
2060 if (ioc->events != NULL){
2061 sz = MPTCTL_EVENT_LOG_SIZE * sizeof(MPT_IOCTL_EVENTS);
2062 kfree(ioc->events);
2063 ioc->events = NULL;
2064 ioc->alloc_total -= sz;
2065 }
2066
2067 if (ioc->cached_fw != NULL) {
2068 sz = ioc->facts.FWImageSize;
2069 pci_free_consistent(ioc->pcidev, sz,
2070 ioc->cached_fw, ioc->cached_fw_dma);
2071 ioc->cached_fw = NULL;
2072 ioc->alloc_total -= sz;
2073 }
2074
d485eb83 2075 kfree(ioc->spi_data.nvram);
466544d8 2076 kfree(ioc->raid_data.pIocPg3);
d485eb83 2077 ioc->spi_data.nvram = NULL;
466544d8 2078 ioc->raid_data.pIocPg3 = NULL;
1da177e4
LT
2079
2080 if (ioc->spi_data.pIocPg4 != NULL) {
2081 sz = ioc->spi_data.IocPg4Sz;
2082 pci_free_consistent(ioc->pcidev, sz,
2083 ioc->spi_data.pIocPg4,
2084 ioc->spi_data.IocPg4_dma);
2085 ioc->spi_data.pIocPg4 = NULL;
2086 ioc->alloc_total -= sz;
2087 }
2088
2089 if (ioc->ReqToChain != NULL) {
2090 kfree(ioc->ReqToChain);
2091 kfree(ioc->RequestNB);
2092 ioc->ReqToChain = NULL;
2093 }
2094
d485eb83
MED
2095 kfree(ioc->ChainToChain);
2096 ioc->ChainToChain = NULL;
82ffb671
CH
2097
2098 if (ioc->HostPageBuffer != NULL) {
2099 if((ret = mpt_host_page_access_control(ioc,
2100 MPI_DB_HPBAC_FREE_BUFFER, NO_SLEEP)) != 0) {
2101 printk(KERN_ERR MYNAM
2102 ": %s: host page buffers free failed (%d)!\n",
2103 __FUNCTION__, ret);
2104 }
2105 dexitprintk((KERN_INFO MYNAM ": %s HostPageBuffer free @ %p, sz=%d bytes\n",
2106 ioc->name, ioc->HostPageBuffer, ioc->HostPageBuffer_sz));
2107 pci_free_consistent(ioc->pcidev, ioc->HostPageBuffer_sz,
2108 ioc->HostPageBuffer,
2109 ioc->HostPageBuffer_dma);
2110 ioc->HostPageBuffer = NULL;
2111 ioc->HostPageBuffer_sz = 0;
2112 ioc->alloc_total -= ioc->HostPageBuffer_sz;
2113 }
1da177e4
LT
2114}
2115
2116/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2117/*
2118 * mpt_adapter_dispose - Free all resources associated with a MPT
2119 * adapter.
2120 * @ioc: Pointer to MPT adapter structure
2121 *
2122 * This routine unregisters h/w resources and frees all alloc'd memory
2123 * associated with a MPT adapter structure.
2124 */
2125static void
2126mpt_adapter_dispose(MPT_ADAPTER *ioc)
2127{
c6678e0c 2128 int sz_first, sz_last;
1da177e4 2129
c6678e0c
CH
2130 if (ioc == NULL)
2131 return;
1da177e4 2132
c6678e0c 2133 sz_first = ioc->alloc_total;
1da177e4 2134
c6678e0c 2135 mpt_adapter_disable(ioc);
1da177e4 2136
c6678e0c
CH
2137 if (ioc->pci_irq != -1) {
2138 free_irq(ioc->pci_irq, ioc);
2139 ioc->pci_irq = -1;
2140 }
2141
2142 if (ioc->memmap != NULL) {
2143 iounmap(ioc->memmap);
2144 ioc->memmap = NULL;
2145 }
1da177e4
LT
2146
2147#if defined(CONFIG_MTRR) && 0
c6678e0c
CH
2148 if (ioc->mtrr_reg > 0) {
2149 mtrr_del(ioc->mtrr_reg, 0, 0);
2150 dprintk((KERN_INFO MYNAM ": %s: MTRR region de-registered\n", ioc->name));
2151 }
1da177e4
LT
2152#endif
2153
c6678e0c
CH
2154 /* Zap the adapter lookup ptr! */
2155 list_del(&ioc->list);
1da177e4 2156
c6678e0c
CH
2157 sz_last = ioc->alloc_total;
2158 dprintk((KERN_INFO MYNAM ": %s: free'd %d of %d bytes\n",
2159 ioc->name, sz_first-sz_last+(int)sizeof(*ioc), sz_first));
2160 kfree(ioc);
1da177e4
LT
2161}
2162
2163/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2164/*
2165 * MptDisplayIocCapabilities - Disply IOC's capacilities.
2166 * @ioc: Pointer to MPT adapter structure
2167 */
2168static void
2169MptDisplayIocCapabilities(MPT_ADAPTER *ioc)
2170{
2171 int i = 0;
2172
2173 printk(KERN_INFO "%s: ", ioc->name);
2174 if (ioc->prod_name && strlen(ioc->prod_name) > 3)
2175 printk("%s: ", ioc->prod_name+3);
2176 printk("Capabilities={");
2177
2178 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR) {
2179 printk("Initiator");
2180 i++;
2181 }
2182
2183 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) {
2184 printk("%sTarget", i ? "," : "");
2185 i++;
2186 }
2187
2188 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
2189 printk("%sLAN", i ? "," : "");
2190 i++;
2191 }
2192
2193#if 0
2194 /*
2195 * This would probably evoke more questions than it's worth
2196 */
2197 if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) {
2198 printk("%sLogBusAddr", i ? "," : "");
2199 i++;
2200 }
2201#endif
2202
2203 printk("}\n");
2204}
2205
2206/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2207/*
2208 * MakeIocReady - Get IOC to a READY state, using KickStart if needed.
2209 * @ioc: Pointer to MPT_ADAPTER structure
2210 * @force: Force hard KickStart of IOC
2211 * @sleepFlag: Specifies whether the process can sleep
2212 *
2213 * Returns:
2214 * 1 - DIAG reset and READY
2215 * 0 - READY initially OR soft reset and READY
2216 * -1 - Any failure on KickStart
2217 * -2 - Msg Unit Reset Failed
2218 * -3 - IO Unit Reset Failed
2219 * -4 - IOC owned by a PEER
2220 */
2221static int
2222MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag)
2223{
2224 u32 ioc_state;
2225 int statefault = 0;
2226 int cntdn;
2227 int hard_reset_done = 0;
2228 int r;
2229 int ii;
2230 int whoinit;
2231
2232 /* Get current [raw] IOC state */
2233 ioc_state = mpt_GetIocState(ioc, 0);
2234 dhsprintk((KERN_INFO MYNAM "::MakeIocReady, %s [raw] state=%08x\n", ioc->name, ioc_state));
2235
2236 /*
2237 * Check to see if IOC got left/stuck in doorbell handshake
2238 * grip of death. If so, hard reset the IOC.
2239 */
2240 if (ioc_state & MPI_DOORBELL_ACTIVE) {
2241 statefault = 1;
2242 printk(MYIOC_s_WARN_FMT "Unexpected doorbell active!\n",
2243 ioc->name);
2244 }
2245
2246 /* Is it already READY? */
c6678e0c 2247 if (!statefault && (ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY)
1da177e4
LT
2248 return 0;
2249
2250 /*
2251 * Check to see if IOC is in FAULT state.
2252 */
2253 if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) {
2254 statefault = 2;
2255 printk(MYIOC_s_WARN_FMT "IOC is in FAULT state!!!\n",
2256 ioc->name);
2257 printk(KERN_WARNING " FAULT code = %04xh\n",
2258 ioc_state & MPI_DOORBELL_DATA_MASK);
2259 }
2260
2261 /*
2262 * Hmmm... Did it get left operational?
2263 */
2264 if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL) {
c6678e0c 2265 dinitprintk((MYIOC_s_INFO_FMT "IOC operational unexpected\n",
1da177e4
LT
2266 ioc->name));
2267
2268 /* Check WhoInit.
2269 * If PCI Peer, exit.
2270 * Else, if no fault conditions are present, issue a MessageUnitReset
2271 * Else, fall through to KickStart case
2272 */
2273 whoinit = (ioc_state & MPI_DOORBELL_WHO_INIT_MASK) >> MPI_DOORBELL_WHO_INIT_SHIFT;
c6678e0c
CH
2274 dinitprintk((KERN_INFO MYNAM
2275 ": whoinit 0x%x statefault %d force %d\n",
1da177e4
LT
2276 whoinit, statefault, force));
2277 if (whoinit == MPI_WHOINIT_PCI_PEER)
2278 return -4;
2279 else {
2280 if ((statefault == 0 ) && (force == 0)) {
2281 if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) == 0)
2282 return 0;
2283 }
2284 statefault = 3;
2285 }
2286 }
2287
2288 hard_reset_done = KickStart(ioc, statefault||force, sleepFlag);
2289 if (hard_reset_done < 0)
2290 return -1;
2291
2292 /*
2293 * Loop here waiting for IOC to come READY.
2294 */
2295 ii = 0;
82ffb671 2296 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 5; /* 5 seconds */
1da177e4
LT
2297
2298 while ((ioc_state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
2299 if (ioc_state == MPI_IOC_STATE_OPERATIONAL) {
2300 /*
2301 * BIOS or previous driver load left IOC in OP state.
2302 * Reset messaging FIFOs.
2303 */
2304 if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) != 0) {
2305 printk(MYIOC_s_ERR_FMT "IOC msg unit reset failed!\n", ioc->name);
2306 return -2;
2307 }
2308 } else if (ioc_state == MPI_IOC_STATE_RESET) {
2309 /*
2310 * Something is wrong. Try to get IOC back
2311 * to a known state.
2312 */
2313 if ((r = SendIocReset(ioc, MPI_FUNCTION_IO_UNIT_RESET, sleepFlag)) != 0) {
2314 printk(MYIOC_s_ERR_FMT "IO unit reset failed!\n", ioc->name);
2315 return -3;
2316 }
2317 }
2318
2319 ii++; cntdn--;
2320 if (!cntdn) {
2321 printk(MYIOC_s_ERR_FMT "Wait IOC_READY state timeout(%d)!\n",
2322 ioc->name, (int)((ii+5)/HZ));
2323 return -ETIME;
2324 }
2325
2326 if (sleepFlag == CAN_SLEEP) {
2327 msleep_interruptible(1);
2328 } else {
2329 mdelay (1); /* 1 msec delay */
2330 }
2331
2332 }
2333
2334 if (statefault < 3) {
2335 printk(MYIOC_s_INFO_FMT "Recovered from %s\n",
2336 ioc->name,
2337 statefault==1 ? "stuck handshake" : "IOC FAULT");
2338 }
2339
2340 return hard_reset_done;
2341}
2342
2343/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2344/*
2345 * mpt_GetIocState - Get the current state of a MPT adapter.
2346 * @ioc: Pointer to MPT_ADAPTER structure
2347 * @cooked: Request raw or cooked IOC state
2348 *
2349 * Returns all IOC Doorbell register bits if cooked==0, else just the
2350 * Doorbell bits in MPI_IOC_STATE_MASK.
2351 */
2352u32
2353mpt_GetIocState(MPT_ADAPTER *ioc, int cooked)
2354{
2355 u32 s, sc;
2356
2357 /* Get! */
2358 s = CHIPREG_READ32(&ioc->chip->Doorbell);
2359// dprintk((MYIOC_s_INFO_FMT "raw state = %08x\n", ioc->name, s));
2360 sc = s & MPI_IOC_STATE_MASK;
2361
2362 /* Save! */
2363 ioc->last_state = sc;
2364
2365 return cooked ? sc : s;
2366}
2367
2368/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2369/*
2370 * GetIocFacts - Send IOCFacts request to MPT adapter.
2371 * @ioc: Pointer to MPT_ADAPTER structure
2372 * @sleepFlag: Specifies whether the process can sleep
2373 * @reason: If recovery, only update facts.
2374 *
2375 * Returns 0 for success, non-zero for failure.
2376 */
2377static int
2378GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
2379{
2380 IOCFacts_t get_facts;
2381 IOCFactsReply_t *facts;
2382 int r;
2383 int req_sz;
2384 int reply_sz;
2385 int sz;
2386 u32 status, vv;
2387 u8 shiftFactor=1;
2388
2389 /* IOC *must* NOT be in RESET state! */
2390 if (ioc->last_state == MPI_IOC_STATE_RESET) {
2391 printk(KERN_ERR MYNAM ": ERROR - Can't get IOCFacts, %s NOT READY! (%08x)\n",
2392 ioc->name,
2393 ioc->last_state );
2394 return -44;
2395 }
2396
2397 facts = &ioc->facts;
2398
2399 /* Destination (reply area)... */
2400 reply_sz = sizeof(*facts);
2401 memset(facts, 0, reply_sz);
2402
2403 /* Request area (get_facts on the stack right now!) */
2404 req_sz = sizeof(get_facts);
2405 memset(&get_facts, 0, req_sz);
2406
2407 get_facts.Function = MPI_FUNCTION_IOC_FACTS;
2408 /* Assert: All other get_facts fields are zero! */
2409
c6678e0c
CH
2410 dinitprintk((MYIOC_s_INFO_FMT
2411 "Sending get IocFacts request req_sz=%d reply_sz=%d\n",
1da177e4
LT
2412 ioc->name, req_sz, reply_sz));
2413
2414 /* No non-zero fields in the get_facts request are greater than
2415 * 1 byte in size, so we can just fire it off as is.
2416 */
2417 r = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&get_facts,
2418 reply_sz, (u16*)facts, 5 /*seconds*/, sleepFlag);
2419 if (r != 0)
2420 return r;
2421
2422 /*
2423 * Now byte swap (GRRR) the necessary fields before any further
2424 * inspection of reply contents.
2425 *
2426 * But need to do some sanity checks on MsgLength (byte) field
2427 * to make sure we don't zero IOC's req_sz!
2428 */
2429 /* Did we get a valid reply? */
2430 if (facts->MsgLength > offsetof(IOCFactsReply_t, RequestFrameSize)/sizeof(u32)) {
2431 if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
2432 /*
2433 * If not been here, done that, save off first WhoInit value
2434 */
2435 if (ioc->FirstWhoInit == WHOINIT_UNKNOWN)
2436 ioc->FirstWhoInit = facts->WhoInit;
2437 }
2438
2439 facts->MsgVersion = le16_to_cpu(facts->MsgVersion);
2440 facts->MsgContext = le32_to_cpu(facts->MsgContext);
2441 facts->IOCExceptions = le16_to_cpu(facts->IOCExceptions);
2442 facts->IOCStatus = le16_to_cpu(facts->IOCStatus);
2443 facts->IOCLogInfo = le32_to_cpu(facts->IOCLogInfo);
637fa99b 2444 status = le16_to_cpu(facts->IOCStatus) & MPI_IOCSTATUS_MASK;
1da177e4
LT
2445 /* CHECKME! IOCStatus, IOCLogInfo */
2446
2447 facts->ReplyQueueDepth = le16_to_cpu(facts->ReplyQueueDepth);
2448 facts->RequestFrameSize = le16_to_cpu(facts->RequestFrameSize);
2449
2450 /*
2451 * FC f/w version changed between 1.1 and 1.2
2452 * Old: u16{Major(4),Minor(4),SubMinor(8)}
2453 * New: u32{Major(8),Minor(8),Unit(8),Dev(8)}
2454 */
2455 if (facts->MsgVersion < 0x0102) {
2456 /*
2457 * Handle old FC f/w style, convert to new...
2458 */
2459 u16 oldv = le16_to_cpu(facts->Reserved_0101_FWVersion);
2460 facts->FWVersion.Word =
2461 ((oldv<<12) & 0xFF000000) |
2462 ((oldv<<8) & 0x000FFF00);
2463 } else
2464 facts->FWVersion.Word = le32_to_cpu(facts->FWVersion.Word);
2465
2466 facts->ProductID = le16_to_cpu(facts->ProductID);
2467 facts->CurrentHostMfaHighAddr =
2468 le32_to_cpu(facts->CurrentHostMfaHighAddr);
2469 facts->GlobalCredits = le16_to_cpu(facts->GlobalCredits);
2470 facts->CurrentSenseBufferHighAddr =
2471 le32_to_cpu(facts->CurrentSenseBufferHighAddr);
2472 facts->CurReplyFrameSize =
2473 le16_to_cpu(facts->CurReplyFrameSize);
82ffb671 2474 facts->IOCCapabilities = le32_to_cpu(facts->IOCCapabilities);
1da177e4
LT
2475
2476 /*
2477 * Handle NEW (!) IOCFactsReply fields in MPI-1.01.xx
2478 * Older MPI-1.00.xx struct had 13 dwords, and enlarged
2479 * to 14 in MPI-1.01.0x.
2480 */
2481 if (facts->MsgLength >= (offsetof(IOCFactsReply_t,FWImageSize) + 7)/4 &&
2482 facts->MsgVersion > 0x0100) {
2483 facts->FWImageSize = le32_to_cpu(facts->FWImageSize);
2484 }
2485
2486 sz = facts->FWImageSize;
2487 if ( sz & 0x01 )
2488 sz += 1;
2489 if ( sz & 0x02 )
2490 sz += 2;
2491 facts->FWImageSize = sz;
c6678e0c 2492
1da177e4
LT
2493 if (!facts->RequestFrameSize) {
2494 /* Something is wrong! */
2495 printk(MYIOC_s_ERR_FMT "IOC reported invalid 0 request size!\n",
2496 ioc->name);
2497 return -55;
2498 }
2499
7fadc87e 2500 r = sz = facts->BlockSize;
1da177e4
LT
2501 vv = ((63 / (sz * 4)) + 1) & 0x03;
2502 ioc->NB_for_64_byte_frame = vv;
2503 while ( sz )
2504 {
2505 shiftFactor++;
2506 sz = sz >> 1;
2507 }
2508 ioc->NBShiftFactor = shiftFactor;
2509 dinitprintk((MYIOC_s_INFO_FMT "NB_for_64_byte_frame=%x NBShiftFactor=%x BlockSize=%x\n",
2510 ioc->name, vv, shiftFactor, r));
c6678e0c 2511
1da177e4
LT
2512 if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
2513 /*
2514 * Set values for this IOC's request & reply frame sizes,
2515 * and request & reply queue depths...
2516 */
2517 ioc->req_sz = min(MPT_DEFAULT_FRAME_SIZE, facts->RequestFrameSize * 4);
2518 ioc->req_depth = min_t(int, MPT_MAX_REQ_DEPTH, facts->GlobalCredits);
2519 ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
2520 ioc->reply_depth = min_t(int, MPT_DEFAULT_REPLY_DEPTH, facts->ReplyQueueDepth);
2521
2522 dinitprintk((MYIOC_s_INFO_FMT "reply_sz=%3d, reply_depth=%4d\n",
2523 ioc->name, ioc->reply_sz, ioc->reply_depth));
2524 dinitprintk((MYIOC_s_INFO_FMT "req_sz =%3d, req_depth =%4d\n",
2525 ioc->name, ioc->req_sz, ioc->req_depth));
2526
2527 /* Get port facts! */
2528 if ( (r = GetPortFacts(ioc, 0, sleepFlag)) != 0 )
2529 return r;
2530 }
2531 } else {
c6678e0c 2532 printk(MYIOC_s_ERR_FMT
1da177e4
LT
2533 "Invalid IOC facts reply, msgLength=%d offsetof=%zd!\n",
2534 ioc->name, facts->MsgLength, (offsetof(IOCFactsReply_t,
2535 RequestFrameSize)/sizeof(u32)));
2536 return -66;
2537 }
2538
2539 return 0;
2540}
2541
2542/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2543/*
2544 * GetPortFacts - Send PortFacts request to MPT adapter.
2545 * @ioc: Pointer to MPT_ADAPTER structure
2546 * @portnum: Port number
2547 * @sleepFlag: Specifies whether the process can sleep
2548 *
2549 * Returns 0 for success, non-zero for failure.
2550 */
2551static int
2552GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
2553{
2554 PortFacts_t get_pfacts;
2555 PortFactsReply_t *pfacts;
2556 int ii;
2557 int req_sz;
2558 int reply_sz;
2559
2560 /* IOC *must* NOT be in RESET state! */
2561 if (ioc->last_state == MPI_IOC_STATE_RESET) {
2562 printk(KERN_ERR MYNAM ": ERROR - Can't get PortFacts, %s NOT READY! (%08x)\n",
2563 ioc->name,
2564 ioc->last_state );
2565 return -4;
2566 }
2567
2568 pfacts = &ioc->pfacts[portnum];
2569
2570 /* Destination (reply area)... */
2571 reply_sz = sizeof(*pfacts);
2572 memset(pfacts, 0, reply_sz);
2573
2574 /* Request area (get_pfacts on the stack right now!) */
2575 req_sz = sizeof(get_pfacts);
2576 memset(&get_pfacts, 0, req_sz);
2577
2578 get_pfacts.Function = MPI_FUNCTION_PORT_FACTS;
2579 get_pfacts.PortNumber = portnum;
2580 /* Assert: All other get_pfacts fields are zero! */
2581
2582 dinitprintk((MYIOC_s_INFO_FMT "Sending get PortFacts(%d) request\n",
2583 ioc->name, portnum));
2584
2585 /* No non-zero fields in the get_pfacts request are greater than
2586 * 1 byte in size, so we can just fire it off as is.
2587 */
2588 ii = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&get_pfacts,
2589 reply_sz, (u16*)pfacts, 5 /*seconds*/, sleepFlag);
2590 if (ii != 0)
2591 return ii;
2592
2593 /* Did we get a valid reply? */
2594
2595 /* Now byte swap the necessary fields in the response. */
2596 pfacts->MsgContext = le32_to_cpu(pfacts->MsgContext);
2597 pfacts->IOCStatus = le16_to_cpu(pfacts->IOCStatus);
2598 pfacts->IOCLogInfo = le32_to_cpu(pfacts->IOCLogInfo);
2599 pfacts->MaxDevices = le16_to_cpu(pfacts->MaxDevices);
2600 pfacts->PortSCSIID = le16_to_cpu(pfacts->PortSCSIID);
2601 pfacts->ProtocolFlags = le16_to_cpu(pfacts->ProtocolFlags);
2602 pfacts->MaxPostedCmdBuffers = le16_to_cpu(pfacts->MaxPostedCmdBuffers);
2603 pfacts->MaxPersistentIDs = le16_to_cpu(pfacts->MaxPersistentIDs);
2604 pfacts->MaxLanBuckets = le16_to_cpu(pfacts->MaxLanBuckets);
2605
2606 return 0;
2607}
2608
2609/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2610/*
2611 * SendIocInit - Send IOCInit request to MPT adapter.
2612 * @ioc: Pointer to MPT_ADAPTER structure
2613 * @sleepFlag: Specifies whether the process can sleep
2614 *
2615 * Send IOCInit followed by PortEnable to bring IOC to OPERATIONAL state.
2616 *
2617 * Returns 0 for success, non-zero for failure.
2618 */
2619static int
2620SendIocInit(MPT_ADAPTER *ioc, int sleepFlag)
2621{
2622 IOCInit_t ioc_init;
2623 MPIDefaultReply_t init_reply;
2624 u32 state;
2625 int r;
2626 int count;
2627 int cntdn;
2628
2629 memset(&ioc_init, 0, sizeof(ioc_init));
2630 memset(&init_reply, 0, sizeof(init_reply));
2631
2632 ioc_init.WhoInit = MPI_WHOINIT_HOST_DRIVER;
2633 ioc_init.Function = MPI_FUNCTION_IOC_INIT;
2634
2635 /* If we are in a recovery mode and we uploaded the FW image,
2636 * then this pointer is not NULL. Skip the upload a second time.
2637 * Set this flag if cached_fw set for either IOC.
2638 */
2639 if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)
2640 ioc->upload_fw = 1;
2641 else
2642 ioc->upload_fw = 0;
2643 ddlprintk((MYIOC_s_INFO_FMT "upload_fw %d facts.Flags=%x\n",
2644 ioc->name, ioc->upload_fw, ioc->facts.Flags));
2645
82ffb671
CH
2646 if(ioc->bus_type == SAS)
2647 ioc_init.MaxDevices = ioc->facts.MaxDevices;
2648 else if(ioc->bus_type == FC)
1da177e4
LT
2649 ioc_init.MaxDevices = MPT_MAX_FC_DEVICES;
2650 else
2651 ioc_init.MaxDevices = MPT_MAX_SCSI_DEVICES;
1da177e4 2652 ioc_init.MaxBuses = MPT_MAX_BUS;
82ffb671
CH
2653 dinitprintk((MYIOC_s_INFO_FMT "facts.MsgVersion=%x\n",
2654 ioc->name, ioc->facts.MsgVersion));
2655 if (ioc->facts.MsgVersion >= MPI_VERSION_01_05) {
2656 // set MsgVersion and HeaderVersion host driver was built with
2657 ioc_init.MsgVersion = cpu_to_le16(MPI_VERSION);
2658 ioc_init.HeaderVersion = cpu_to_le16(MPI_HEADER_VERSION);
2659
2660 if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_HOST_PAGE_BUFFER_PERSISTENT) {
2661 ioc_init.HostPageBufferSGE = ioc->facts.HostPageBufferSGE;
2662 } else if(mpt_host_page_alloc(ioc, &ioc_init))
2663 return -99;
2664 }
1da177e4
LT
2665 ioc_init.ReplyFrameSize = cpu_to_le16(ioc->reply_sz); /* in BYTES */
2666
2667 if (sizeof(dma_addr_t) == sizeof(u64)) {
2668 /* Save the upper 32-bits of the request
2669 * (reply) and sense buffers.
2670 */
2671 ioc_init.HostMfaHighAddr = cpu_to_le32((u32)((u64)ioc->alloc_dma >> 32));
2672 ioc_init.SenseBufferHighAddr = cpu_to_le32((u32)((u64)ioc->sense_buf_pool_dma >> 32));
2673 } else {
2674 /* Force 32-bit addressing */
2675 ioc_init.HostMfaHighAddr = cpu_to_le32(0);
2676 ioc_init.SenseBufferHighAddr = cpu_to_le32(0);
2677 }
82ffb671 2678
1da177e4
LT
2679 ioc->facts.CurrentHostMfaHighAddr = ioc_init.HostMfaHighAddr;
2680 ioc->facts.CurrentSenseBufferHighAddr = ioc_init.SenseBufferHighAddr;
82ffb671
CH
2681 ioc->facts.MaxDevices = ioc_init.MaxDevices;
2682 ioc->facts.MaxBuses = ioc_init.MaxBuses;
1da177e4
LT
2683
2684 dhsprintk((MYIOC_s_INFO_FMT "Sending IOCInit (req @ %p)\n",
2685 ioc->name, &ioc_init));
2686
2687 r = mpt_handshake_req_reply_wait(ioc, sizeof(IOCInit_t), (u32*)&ioc_init,
2688 sizeof(MPIDefaultReply_t), (u16*)&init_reply, 10 /*seconds*/, sleepFlag);
82ffb671
CH
2689 if (r != 0) {
2690 printk(MYIOC_s_ERR_FMT "Sending IOCInit failed(%d)!\n",ioc->name, r);
1da177e4 2691 return r;
82ffb671 2692 }
1da177e4
LT
2693
2694 /* No need to byte swap the multibyte fields in the reply
2695 * since we don't even look at it's contents.
2696 */
2697
2698 dhsprintk((MYIOC_s_INFO_FMT "Sending PortEnable (req @ %p)\n",
2699 ioc->name, &ioc_init));
c6678e0c
CH
2700
2701 if ((r = SendPortEnable(ioc, 0, sleepFlag)) != 0) {
2702 printk(MYIOC_s_ERR_FMT "Sending PortEnable failed(%d)!\n",ioc->name, r);
1da177e4 2703 return r;
c6678e0c 2704 }
1da177e4
LT
2705
2706 /* YIKES! SUPER IMPORTANT!!!
2707 * Poll IocState until _OPERATIONAL while IOC is doing
2708 * LoopInit and TargetDiscovery!
2709 */
2710 count = 0;
2711 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 60; /* 60 seconds */
2712 state = mpt_GetIocState(ioc, 1);
2713 while (state != MPI_IOC_STATE_OPERATIONAL && --cntdn) {
2714 if (sleepFlag == CAN_SLEEP) {
2715 msleep_interruptible(1);
2716 } else {
2717 mdelay(1);
2718 }
2719
2720 if (!cntdn) {
2721 printk(MYIOC_s_ERR_FMT "Wait IOC_OP state timeout(%d)!\n",
2722 ioc->name, (int)((count+5)/HZ));
2723 return -9;
2724 }
2725
2726 state = mpt_GetIocState(ioc, 1);
2727 count++;
2728 }
c6678e0c 2729 dinitprintk((MYIOC_s_INFO_FMT "INFO - Wait IOC_OPERATIONAL state (cnt=%d)\n",
1da177e4
LT
2730 ioc->name, count));
2731
2732 return r;
2733}
2734
2735/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2736/*
2737 * SendPortEnable - Send PortEnable request to MPT adapter port.
2738 * @ioc: Pointer to MPT_ADAPTER structure
2739 * @portnum: Port number to enable
2740 * @sleepFlag: Specifies whether the process can sleep
2741 *
2742 * Send PortEnable to bring IOC to OPERATIONAL state.
2743 *
2744 * Returns 0 for success, non-zero for failure.
2745 */
2746static int
2747SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
2748{
2749 PortEnable_t port_enable;
2750 MPIDefaultReply_t reply_buf;
82ffb671 2751 int rc;
1da177e4
LT
2752 int req_sz;
2753 int reply_sz;
2754
2755 /* Destination... */
2756 reply_sz = sizeof(MPIDefaultReply_t);
2757 memset(&reply_buf, 0, reply_sz);
2758
2759 req_sz = sizeof(PortEnable_t);
2760 memset(&port_enable, 0, req_sz);
2761
2762 port_enable.Function = MPI_FUNCTION_PORT_ENABLE;
2763 port_enable.PortNumber = portnum;
2764/* port_enable.ChainOffset = 0; */
2765/* port_enable.MsgFlags = 0; */
2766/* port_enable.MsgContext = 0; */
2767
2768 dinitprintk((MYIOC_s_INFO_FMT "Sending Port(%d)Enable (req @ %p)\n",
2769 ioc->name, portnum, &port_enable));
2770
2771 /* RAID FW may take a long time to enable
2772 */
82ffb671
CH
2773 if ( (ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK)
2774 > MPI_FW_HEADER_PID_PROD_TARGET_SCSI ) {
2775 rc = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&port_enable,
1da177e4 2776 reply_sz, (u16*)&reply_buf, 300 /*seconds*/, sleepFlag);
82ffb671
CH
2777 } else {
2778 rc = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&port_enable,
2779 reply_sz, (u16*)&reply_buf, 30 /*seconds*/, sleepFlag);
1da177e4 2780 }
82ffb671 2781 return rc;
1da177e4
LT
2782}
2783
2784/*
2785 * ioc: Pointer to MPT_ADAPTER structure
2786 * size - total FW bytes
2787 */
2788void
2789mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size)
2790{
2791 if (ioc->cached_fw)
2792 return; /* use already allocated memory */
2793 if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) {
2794 ioc->cached_fw = ioc->alt_ioc->cached_fw; /* use alt_ioc's memory */
2795 ioc->cached_fw_dma = ioc->alt_ioc->cached_fw_dma;
2796 } else {
2797 if ( (ioc->cached_fw = pci_alloc_consistent(ioc->pcidev, size, &ioc->cached_fw_dma) ) )
2798 ioc->alloc_total += size;
2799 }
2800}
2801/*
2802 * If alt_img is NULL, delete from ioc structure.
2803 * Else, delete a secondary image in same format.
2804 */
2805void
2806mpt_free_fw_memory(MPT_ADAPTER *ioc)
2807{
2808 int sz;
2809
2810 sz = ioc->facts.FWImageSize;
c6678e0c 2811 dinitprintk((KERN_INFO MYNAM "free_fw_memory: FW Image @ %p[%p], sz=%d[%x] bytes\n",
1da177e4
LT
2812 ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
2813 pci_free_consistent(ioc->pcidev, sz,
2814 ioc->cached_fw, ioc->cached_fw_dma);
2815 ioc->cached_fw = NULL;
2816
2817 return;
2818}
2819
2820
2821/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2822/*
2823 * mpt_do_upload - Construct and Send FWUpload request to MPT adapter port.
2824 * @ioc: Pointer to MPT_ADAPTER structure
2825 * @sleepFlag: Specifies whether the process can sleep
2826 *
2827 * Returns 0 for success, >0 for handshake failure
2828 * <0 for fw upload failure.
2829 *
2830 * Remark: If bound IOC and a successful FWUpload was performed
2831 * on the bound IOC, the second image is discarded
2832 * and memory is free'd. Both channels must upload to prevent
2833 * IOC from running in degraded mode.
2834 */
2835static int
2836mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag)
2837{
2838 u8 request[ioc->req_sz];
2839 u8 reply[sizeof(FWUploadReply_t)];
2840 FWUpload_t *prequest;
2841 FWUploadReply_t *preply;
2842 FWUploadTCSGE_t *ptcsge;
2843 int sgeoffset;
2844 u32 flagsLength;
2845 int ii, sz, reply_sz;
2846 int cmdStatus;
2847
2848 /* If the image size is 0, we are done.
2849 */
2850 if ((sz = ioc->facts.FWImageSize) == 0)
2851 return 0;
2852
2853 mpt_alloc_fw_memory(ioc, sz);
2854
c6678e0c 2855 dinitprintk((KERN_INFO MYNAM ": FW Image @ %p[%p], sz=%d[%x] bytes\n",
1da177e4 2856 ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
c6678e0c 2857
1da177e4
LT
2858 if (ioc->cached_fw == NULL) {
2859 /* Major Failure.
2860 */
2861 return -ENOMEM;
2862 }
2863
2864 prequest = (FWUpload_t *)&request;
2865 preply = (FWUploadReply_t *)&reply;
2866
2867 /* Destination... */
2868 memset(prequest, 0, ioc->req_sz);
2869
2870 reply_sz = sizeof(reply);
2871 memset(preply, 0, reply_sz);
2872
2873 prequest->ImageType = MPI_FW_UPLOAD_ITYPE_FW_IOC_MEM;
2874 prequest->Function = MPI_FUNCTION_FW_UPLOAD;
2875
2876 ptcsge = (FWUploadTCSGE_t *) &prequest->SGL;
2877 ptcsge->DetailsLength = 12;
2878 ptcsge->Flags = MPI_SGE_FLAGS_TRANSACTION_ELEMENT;
2879 ptcsge->ImageSize = cpu_to_le32(sz);
2880
2881 sgeoffset = sizeof(FWUpload_t) - sizeof(SGE_MPI_UNION) + sizeof(FWUploadTCSGE_t);
2882
2883 flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ | sz;
2884 mpt_add_sge(&request[sgeoffset], flagsLength, ioc->cached_fw_dma);
2885
2886 sgeoffset += sizeof(u32) + sizeof(dma_addr_t);
c6678e0c 2887 dinitprintk((KERN_INFO MYNAM ": Sending FW Upload (req @ %p) sgeoffset=%d \n",
1da177e4
LT
2888 prequest, sgeoffset));
2889 DBG_DUMP_FW_REQUEST_FRAME(prequest)
2890
2891 ii = mpt_handshake_req_reply_wait(ioc, sgeoffset, (u32*)prequest,
2892 reply_sz, (u16*)preply, 65 /*seconds*/, sleepFlag);
2893
c6678e0c 2894 dinitprintk((KERN_INFO MYNAM ": FW Upload completed rc=%x \n", ii));
1da177e4
LT
2895
2896 cmdStatus = -EFAULT;
2897 if (ii == 0) {
2898 /* Handshake transfer was complete and successful.
2899 * Check the Reply Frame.
2900 */
2901 int status, transfer_sz;
2902 status = le16_to_cpu(preply->IOCStatus);
2903 if (status == MPI_IOCSTATUS_SUCCESS) {
2904 transfer_sz = le32_to_cpu(preply->ActualImageSize);
2905 if (transfer_sz == sz)
2906 cmdStatus = 0;
2907 }
2908 }
c6678e0c 2909 dinitprintk((MYIOC_s_INFO_FMT ": do_upload cmdStatus=%d \n",
1da177e4
LT
2910 ioc->name, cmdStatus));
2911
c6678e0c 2912
1da177e4
LT
2913 if (cmdStatus) {
2914
2915 ddlprintk((MYIOC_s_INFO_FMT ": fw upload failed, freeing image \n",
2916 ioc->name));
2917 mpt_free_fw_memory(ioc);
2918 }
2919
2920 return cmdStatus;
2921}
2922
2923/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2924/*
2925 * mpt_downloadboot - DownloadBoot code
2926 * @ioc: Pointer to MPT_ADAPTER structure
2927 * @flag: Specify which part of IOC memory is to be uploaded.
2928 * @sleepFlag: Specifies whether the process can sleep
2929 *
2930 * FwDownloadBoot requires Programmed IO access.
2931 *
2932 * Returns 0 for success
2933 * -1 FW Image size is 0
2934 * -2 No valid cached_fw Pointer
2935 * <0 for fw upload failure.
2936 */
2937static int
82ffb671 2938mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag)
1da177e4 2939{
1da177e4
LT
2940 MpiExtImageHeader_t *pExtImage;
2941 u32 fwSize;
2942 u32 diag0val;
2943 int count;
2944 u32 *ptrFw;
2945 u32 diagRwData;
2946 u32 nextImage;
2947 u32 load_addr;
2948 u32 ioc_state=0;
2949
82ffb671
CH
2950 ddlprintk((MYIOC_s_INFO_FMT "downloadboot: fw size 0x%x (%d), FW Ptr %p\n",
2951 ioc->name, pFwHeader->ImageSize, pFwHeader->ImageSize, pFwHeader));
3fadc59d 2952
1da177e4
LT
2953 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
2954 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
2955 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
2956 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
2957 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
2958 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
2959
2960 CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM));
2961
2962 /* wait 1 msec */
2963 if (sleepFlag == CAN_SLEEP) {
2964 msleep_interruptible(1);
2965 } else {
2966 mdelay (1);
2967 }
2968
2969 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
2970 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER);
2971
2972 for (count = 0; count < 30; count ++) {
2973 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
2974 if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
2975 ddlprintk((MYIOC_s_INFO_FMT "RESET_ADAPTER cleared, count=%d\n",
2976 ioc->name, count));
2977 break;
2978 }
82ffb671 2979 /* wait .1 sec */
1da177e4 2980 if (sleepFlag == CAN_SLEEP) {
82ffb671 2981 msleep_interruptible (100);
1da177e4 2982 } else {
82ffb671 2983 mdelay (100);
1da177e4
LT
2984 }
2985 }
2986
2987 if ( count == 30 ) {
82ffb671
CH
2988 ddlprintk((MYIOC_s_INFO_FMT "downloadboot failed! "
2989 "Unable to get MPI_DIAG_DRWE mode, diag0val=%x\n",
1da177e4
LT
2990 ioc->name, diag0val));
2991 return -3;
2992 }
2993
2994 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
2995 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
2996 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
2997 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
2998 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
2999 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3000
3001 /* Set the DiagRwEn and Disable ARM bits */
3002 CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM));
3003
1da177e4
LT
3004 fwSize = (pFwHeader->ImageSize + 3)/4;
3005 ptrFw = (u32 *) pFwHeader;
3006
3007 /* Write the LoadStartAddress to the DiagRw Address Register
3008 * using Programmed IO
3009 */
3fadc59d
MED
3010 if (ioc->errata_flag_1064)
3011 pci_enable_io_access(ioc->pcidev);
3012
1da177e4
LT
3013 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->LoadStartAddress);
3014 ddlprintk((MYIOC_s_INFO_FMT "LoadStart addr written 0x%x \n",
3015 ioc->name, pFwHeader->LoadStartAddress));
3016
3017 ddlprintk((MYIOC_s_INFO_FMT "Write FW Image: 0x%x bytes @ %p\n",
3018 ioc->name, fwSize*4, ptrFw));
3019 while (fwSize--) {
3020 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++);
3021 }
3022
3023 nextImage = pFwHeader->NextImageHeaderOffset;
3024 while (nextImage) {
3025 pExtImage = (MpiExtImageHeader_t *) ((char *)pFwHeader + nextImage);
3026
3027 load_addr = pExtImage->LoadStartAddress;
3028
3029 fwSize = (pExtImage->ImageSize + 3) >> 2;
3030 ptrFw = (u32 *)pExtImage;
3031
c6678e0c
CH
3032 ddlprintk((MYIOC_s_INFO_FMT "Write Ext Image: 0x%x (%d) bytes @ %p load_addr=%x\n",
3033 ioc->name, fwSize*4, fwSize*4, ptrFw, load_addr));
1da177e4
LT
3034 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, load_addr);
3035
3036 while (fwSize--) {
3037 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++);
3038 }
3039 nextImage = pExtImage->NextImageHeaderOffset;
3040 }
3041
3042 /* Write the IopResetVectorRegAddr */
3043 ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Addr=%x! \n", ioc->name, pFwHeader->IopResetRegAddr));
3044 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->IopResetRegAddr);
3045
3046 /* Write the IopResetVectorValue */
3047 ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Value=%x! \n", ioc->name, pFwHeader->IopResetVectorValue));
3048 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, pFwHeader->IopResetVectorValue);
3049
3050 /* Clear the internal flash bad bit - autoincrementing register,
3051 * so must do two writes.
3052 */
a9b2937a 3053 if (ioc->bus_type == SPI) {
82ffb671
CH
3054 /*
3055 * 1030 and 1035 H/W errata, workaround to access
3056 * the ClearFlashBadSignatureBit
3057 */
3058 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
3059 diagRwData = CHIPREG_PIO_READ32(&ioc->pio_chip->DiagRwData);
3060 diagRwData |= 0x40000000;
3061 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
3062 CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, diagRwData);
3063
3064 } else /* if((ioc->bus_type == SAS) || (ioc->bus_type == FC)) */ {
3065 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3066 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val |
3067 MPI_DIAG_CLEAR_FLASH_BAD_SIG);
3068
3069 /* wait 1 msec */
3070 if (sleepFlag == CAN_SLEEP) {
3071 msleep_interruptible (1);
3072 } else {
3073 mdelay (1);
3074 }
3075 }
1da177e4 3076
3fadc59d
MED
3077 if (ioc->errata_flag_1064)
3078 pci_disable_io_access(ioc->pcidev);
3079
1da177e4 3080 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
82ffb671
CH
3081 ddlprintk((MYIOC_s_INFO_FMT "downloadboot diag0val=%x, "
3082 "turning off PREVENT_IOC_BOOT, DISABLE_ARM, RW_ENABLE\n",
1da177e4 3083 ioc->name, diag0val));
82ffb671 3084 diag0val &= ~(MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM | MPI_DIAG_RW_ENABLE);
1da177e4
LT
3085 ddlprintk((MYIOC_s_INFO_FMT "downloadboot now diag0val=%x\n",
3086 ioc->name, diag0val));
3087 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
3088
3089 /* Write 0xFF to reset the sequencer */
3090 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3091
82ffb671
CH
3092 if (ioc->bus_type == SAS) {
3093 ioc_state = mpt_GetIocState(ioc, 0);
3094 if ( (GetIocFacts(ioc, sleepFlag,
3095 MPT_HOSTEVENT_IOC_BRINGUP)) != 0 ) {
3096 ddlprintk((MYIOC_s_INFO_FMT "GetIocFacts failed: IocState=%x\n",
3097 ioc->name, ioc_state));
3098 return -EFAULT;
3099 }
3100 }
3101
1da177e4
LT
3102 for (count=0; count<HZ*20; count++) {
3103 if ((ioc_state = mpt_GetIocState(ioc, 0)) & MPI_IOC_STATE_READY) {
3104 ddlprintk((MYIOC_s_INFO_FMT "downloadboot successful! (count=%d) IocState=%x\n",
3105 ioc->name, count, ioc_state));
82ffb671
CH
3106 if (ioc->bus_type == SAS) {
3107 return 0;
3108 }
1da177e4
LT
3109 if ((SendIocInit(ioc, sleepFlag)) != 0) {
3110 ddlprintk((MYIOC_s_INFO_FMT "downloadboot: SendIocInit failed\n",
3111 ioc->name));
3112 return -EFAULT;
3113 }
3114 ddlprintk((MYIOC_s_INFO_FMT "downloadboot: SendIocInit successful\n",
3115 ioc->name));
3116 return 0;
3117 }
3118 if (sleepFlag == CAN_SLEEP) {
3119 msleep_interruptible (10);
3120 } else {
3121 mdelay (10);
3122 }
3123 }
3124 ddlprintk((MYIOC_s_INFO_FMT "downloadboot failed! IocState=%x\n",
3125 ioc->name, ioc_state));
3126 return -EFAULT;
3127}
3128
3129/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3130/*
3131 * KickStart - Perform hard reset of MPT adapter.
3132 * @ioc: Pointer to MPT_ADAPTER structure
3133 * @force: Force hard reset
3134 * @sleepFlag: Specifies whether the process can sleep
3135 *
3136 * This routine places MPT adapter in diagnostic mode via the
3137 * WriteSequence register, and then performs a hard reset of adapter
3138 * via the Diagnostic register.
3139 *
3140 * Inputs: sleepflag - CAN_SLEEP (non-interrupt thread)
3141 * or NO_SLEEP (interrupt thread, use mdelay)
3142 * force - 1 if doorbell active, board fault state
3143 * board operational, IOC_RECOVERY or
3144 * IOC_BRINGUP and there is an alt_ioc.
3145 * 0 else
3146 *
3147 * Returns:
c6678e0c
CH
3148 * 1 - hard reset, READY
3149 * 0 - no reset due to History bit, READY
3150 * -1 - no reset due to History bit but not READY
1da177e4
LT
3151 * OR reset but failed to come READY
3152 * -2 - no reset, could not enter DIAG mode
3153 * -3 - reset but bad FW bit
3154 */
3155static int
3156KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag)
3157{
3158 int hard_reset_done = 0;
3159 u32 ioc_state=0;
3160 int cnt,cntdn;
3161
3162 dinitprintk((KERN_WARNING MYNAM ": KickStarting %s!\n", ioc->name));
a9b2937a 3163 if (ioc->bus_type == SPI) {
1da177e4
LT
3164 /* Always issue a Msg Unit Reset first. This will clear some
3165 * SCSI bus hang conditions.
3166 */
3167 SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag);
3168
3169 if (sleepFlag == CAN_SLEEP) {
3170 msleep_interruptible (1000);
3171 } else {
3172 mdelay (1000);
3173 }
3174 }
3175
3176 hard_reset_done = mpt_diag_reset(ioc, force, sleepFlag);
3177 if (hard_reset_done < 0)
3178 return hard_reset_done;
3179
3180 dinitprintk((MYIOC_s_INFO_FMT "Diagnostic reset successful!\n",
3181 ioc->name));
3182
3183 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 2; /* 2 seconds */
3184 for (cnt=0; cnt<cntdn; cnt++) {
3185 ioc_state = mpt_GetIocState(ioc, 1);
3186 if ((ioc_state == MPI_IOC_STATE_READY) || (ioc_state == MPI_IOC_STATE_OPERATIONAL)) {
3187 dinitprintk((MYIOC_s_INFO_FMT "KickStart successful! (cnt=%d)\n",
3188 ioc->name, cnt));
3189 return hard_reset_done;
3190 }
3191 if (sleepFlag == CAN_SLEEP) {
3192 msleep_interruptible (10);
3193 } else {
3194 mdelay (10);
3195 }
3196 }
3197
3198 printk(MYIOC_s_ERR_FMT "Failed to come READY after reset! IocState=%x\n",
3199 ioc->name, ioc_state);
3200 return -1;
3201}
3202
3203/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3204/*
3205 * mpt_diag_reset - Perform hard reset of the adapter.
3206 * @ioc: Pointer to MPT_ADAPTER structure
3207 * @ignore: Set if to honor and clear to ignore
3208 * the reset history bit
3209 * @sleepflag: CAN_SLEEP if called in a non-interrupt thread,
3210 * else set to NO_SLEEP (use mdelay instead)
3211 *
3212 * This routine places the adapter in diagnostic mode via the
3213 * WriteSequence register and then performs a hard reset of adapter
3214 * via the Diagnostic register. Adapter should be in ready state
3215 * upon successful completion.
3216 *
3217 * Returns: 1 hard reset successful
3218 * 0 no reset performed because reset history bit set
3219 * -2 enabling diagnostic mode failed
3220 * -3 diagnostic reset failed
3221 */
3222static int
3223mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
3224{
3225 u32 diag0val;
3226 u32 doorbell;
3227 int hard_reset_done = 0;
3228 int count = 0;
3229#ifdef MPT_DEBUG
3230 u32 diag1val = 0;
3231#endif
3232
3233 /* Clear any existing interrupts */
3234 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3235
3236 /* Use "Diagnostic reset" method! (only thing available!) */
3237 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3238
3239#ifdef MPT_DEBUG
3240 if (ioc->alt_ioc)
3241 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3242 dprintk((MYIOC_s_INFO_FMT "DbG1: diag0=%08x, diag1=%08x\n",
3243 ioc->name, diag0val, diag1val));
3244#endif
3245
3246 /* Do the reset if we are told to ignore the reset history
3247 * or if the reset history is 0
3248 */
3249 if (ignore || !(diag0val & MPI_DIAG_RESET_HISTORY)) {
3250 while ((diag0val & MPI_DIAG_DRWE) == 0) {
3251 /* Write magic sequence to WriteSequence register
3252 * Loop until in diagnostic mode
3253 */
3254 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3255 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
3256 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
3257 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
3258 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
3259 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3260
3261 /* wait 100 msec */
3262 if (sleepFlag == CAN_SLEEP) {
3263 msleep_interruptible (100);
3264 } else {
3265 mdelay (100);
3266 }
3267
3268 count++;
3269 if (count > 20) {
3270 printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n",
3271 ioc->name, diag0val);
3272 return -2;
3273
3274 }
3275
3276 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3277
3278 dprintk((MYIOC_s_INFO_FMT "Wrote magic DiagWriteEn sequence (%x)\n",
3279 ioc->name, diag0val));
3280 }
3281
3282#ifdef MPT_DEBUG
3283 if (ioc->alt_ioc)
3284 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3285 dprintk((MYIOC_s_INFO_FMT "DbG2: diag0=%08x, diag1=%08x\n",
3286 ioc->name, diag0val, diag1val));
3287#endif
3288 /*
3289 * Disable the ARM (Bug fix)
3290 *
3291 */
3292 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_DISABLE_ARM);
c6678e0c 3293 mdelay(1);
1da177e4
LT
3294
3295 /*
3296 * Now hit the reset bit in the Diagnostic register
3297 * (THE BIG HAMMER!) (Clears DRWE bit).
3298 */
3299 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER);
3300 hard_reset_done = 1;
3301 dprintk((MYIOC_s_INFO_FMT "Diagnostic reset performed\n",
3302 ioc->name));
3303
3304 /*
3305 * Call each currently registered protocol IOC reset handler
3306 * with pre-reset indication.
3307 * NOTE: If we're doing _IOC_BRINGUP, there can be no
3308 * MptResetHandlers[] registered yet.
3309 */
3310 {
3311 int ii;
3312 int r = 0;
3313
3314 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
3315 if (MptResetHandlers[ii]) {
3316 dprintk((MYIOC_s_INFO_FMT "Calling IOC pre_reset handler #%d\n",
3317 ioc->name, ii));
3318 r += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_PRE_RESET);
3319 if (ioc->alt_ioc) {
3320 dprintk((MYIOC_s_INFO_FMT "Calling alt-%s pre_reset handler #%d\n",
3321 ioc->name, ioc->alt_ioc->name, ii));
3322 r += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_PRE_RESET);
3323 }
3324 }
3325 }
3326 /* FIXME? Examine results here? */
3327 }
3328
3329 if (ioc->cached_fw) {
3330 /* If the DownloadBoot operation fails, the
3331 * IOC will be left unusable. This is a fatal error
3332 * case. _diag_reset will return < 0
3333 */
3334 for (count = 0; count < 30; count ++) {
3335 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3336 if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
3337 break;
3338 }
3339
3340 /* wait 1 sec */
3341 if (sleepFlag == CAN_SLEEP) {
82ffb671 3342 msleep_interruptible (1000);
1da177e4
LT
3343 } else {
3344 mdelay (1000);
3345 }
3346 }
82ffb671
CH
3347 if ((count = mpt_downloadboot(ioc,
3348 (MpiFwHeader_t *)ioc->cached_fw, sleepFlag)) < 0) {
1da177e4
LT
3349 printk(KERN_WARNING MYNAM
3350 ": firmware downloadboot failure (%d)!\n", count);
3351 }
3352
3353 } else {
3354 /* Wait for FW to reload and for board
3355 * to go to the READY state.
3356 * Maximum wait is 60 seconds.
3357 * If fail, no error will check again
3358 * with calling program.
3359 */
3360 for (count = 0; count < 60; count ++) {
3361 doorbell = CHIPREG_READ32(&ioc->chip->Doorbell);
3362 doorbell &= MPI_IOC_STATE_MASK;
3363
3364 if (doorbell == MPI_IOC_STATE_READY) {
3365 break;
3366 }
3367
3368 /* wait 1 sec */
3369 if (sleepFlag == CAN_SLEEP) {
3370 msleep_interruptible (1000);
3371 } else {
3372 mdelay (1000);
3373 }
3374 }
3375 }
3376 }
3377
3378 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3379#ifdef MPT_DEBUG
3380 if (ioc->alt_ioc)
3381 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3382 dprintk((MYIOC_s_INFO_FMT "DbG3: diag0=%08x, diag1=%08x\n",
3383 ioc->name, diag0val, diag1val));
3384#endif
3385
3386 /* Clear RESET_HISTORY bit! Place board in the
3387 * diagnostic mode to update the diag register.
3388 */
3389 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3390 count = 0;
3391 while ((diag0val & MPI_DIAG_DRWE) == 0) {
3392 /* Write magic sequence to WriteSequence register
3393 * Loop until in diagnostic mode
3394 */
3395 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3396 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
3397 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
3398 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
3399 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
3400 CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3401
3402 /* wait 100 msec */
3403 if (sleepFlag == CAN_SLEEP) {
3404 msleep_interruptible (100);
3405 } else {
3406 mdelay (100);
3407 }
3408
3409 count++;
3410 if (count > 20) {
3411 printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n",
3412 ioc->name, diag0val);
3413 break;
3414 }
3415 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3416 }
3417 diag0val &= ~MPI_DIAG_RESET_HISTORY;
3418 CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
3419 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3420 if (diag0val & MPI_DIAG_RESET_HISTORY) {
3421 printk(MYIOC_s_WARN_FMT "ResetHistory bit failed to clear!\n",
3422 ioc->name);
3423 }
3424
3425 /* Disable Diagnostic Mode
3426 */
3427 CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFFFFFFFF);
3428
3429 /* Check FW reload status flags.
3430 */
3431 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3432 if (diag0val & (MPI_DIAG_FLASH_BAD_SIG | MPI_DIAG_RESET_ADAPTER | MPI_DIAG_DISABLE_ARM)) {
3433 printk(MYIOC_s_ERR_FMT "Diagnostic reset FAILED! (%02xh)\n",
3434 ioc->name, diag0val);
3435 return -3;
3436 }
3437
3438#ifdef MPT_DEBUG
3439 if (ioc->alt_ioc)
3440 diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3441 dprintk((MYIOC_s_INFO_FMT "DbG4: diag0=%08x, diag1=%08x\n",
3442 ioc->name, diag0val, diag1val));
3443#endif
3444
3445 /*
3446 * Reset flag that says we've enabled event notification
3447 */
3448 ioc->facts.EventState = 0;
3449
3450 if (ioc->alt_ioc)
3451 ioc->alt_ioc->facts.EventState = 0;
3452
3453 return hard_reset_done;
3454}
3455
3456/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3457/*
3458 * SendIocReset - Send IOCReset request to MPT adapter.
3459 * @ioc: Pointer to MPT_ADAPTER structure
3460 * @reset_type: reset type, expected values are
3461 * %MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET or %MPI_FUNCTION_IO_UNIT_RESET
3462 *
3463 * Send IOCReset request to the MPT adapter.
3464 *
3465 * Returns 0 for success, non-zero for failure.
3466 */
3467static int
3468SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag)
3469{
3470 int r;
3471 u32 state;
3472 int cntdn, count;
3473
c6678e0c 3474 drsprintk((KERN_INFO MYNAM ": %s: Sending IOC reset(0x%02x)!\n",
1da177e4
LT
3475 ioc->name, reset_type));
3476 CHIPREG_WRITE32(&ioc->chip->Doorbell, reset_type<<MPI_DOORBELL_FUNCTION_SHIFT);
3477 if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
3478 return r;
3479
3480 /* FW ACK'd request, wait for READY state
3481 */
3482 count = 0;
3483 cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 15; /* 15 seconds */
3484
3485 while ((state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
3486 cntdn--;
3487 count++;
3488 if (!cntdn) {
3489 if (sleepFlag != CAN_SLEEP)
3490 count *= 10;
3491
3492 printk(KERN_ERR MYNAM ": %s: ERROR - Wait IOC_READY state timeout(%d)!\n",
3493 ioc->name, (int)((count+5)/HZ));
3494 return -ETIME;
3495 }
3496
3497 if (sleepFlag == CAN_SLEEP) {
3498 msleep_interruptible(1);
3499 } else {
3500 mdelay (1); /* 1 msec delay */
3501 }
3502 }
3503
3504 /* TODO!
3505 * Cleanup all event stuff for this IOC; re-issue EventNotification
3506 * request if needed.
3507 */
3508 if (ioc->facts.Function)
3509 ioc->facts.EventState = 0;
3510
3511 return 0;
3512}
3513
3514/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3515/*
3516 * initChainBuffers - Allocate memory for and initialize
3517 * chain buffers, chain buffer control arrays and spinlock.
3518 * @hd: Pointer to MPT_SCSI_HOST structure
3519 * @init: If set, initialize the spin lock.
3520 */
3521static int
3522initChainBuffers(MPT_ADAPTER *ioc)
3523{
3524 u8 *mem;
3525 int sz, ii, num_chain;
3526 int scale, num_sge, numSGE;
3527
3528 /* ReqToChain size must equal the req_depth
3529 * index = req_idx
3530 */
3531 if (ioc->ReqToChain == NULL) {
3532 sz = ioc->req_depth * sizeof(int);
3533 mem = kmalloc(sz, GFP_ATOMIC);
3534 if (mem == NULL)
3535 return -1;
3536
3537 ioc->ReqToChain = (int *) mem;
3538 dinitprintk((KERN_INFO MYNAM ": %s ReqToChain alloc @ %p, sz=%d bytes\n",
3539 ioc->name, mem, sz));
3540 mem = kmalloc(sz, GFP_ATOMIC);
3541 if (mem == NULL)
3542 return -1;
3543
3544 ioc->RequestNB = (int *) mem;
3545 dinitprintk((KERN_INFO MYNAM ": %s RequestNB alloc @ %p, sz=%d bytes\n",
3546 ioc->name, mem, sz));
3547 }
3548 for (ii = 0; ii < ioc->req_depth; ii++) {
3549 ioc->ReqToChain[ii] = MPT_HOST_NO_CHAIN;
3550 }
3551
3552 /* ChainToChain size must equal the total number
3553 * of chain buffers to be allocated.
3554 * index = chain_idx
3555 *
3556 * Calculate the number of chain buffers needed(plus 1) per I/O
3557 * then multiply the the maximum number of simultaneous cmds
3558 *
3559 * num_sge = num sge in request frame + last chain buffer
3560 * scale = num sge per chain buffer if no chain element
3561 */
3562 scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
3563 if (sizeof(dma_addr_t) == sizeof(u64))
3564 num_sge = scale + (ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
3565 else
3566 num_sge = 1+ scale + (ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
3567
3568 if (sizeof(dma_addr_t) == sizeof(u64)) {
3569 numSGE = (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale +
3570 (ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
3571 } else {
3572 numSGE = 1 + (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale +
3573 (ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
3574 }
3575 dinitprintk((KERN_INFO MYNAM ": %s num_sge=%d numSGE=%d\n",
3576 ioc->name, num_sge, numSGE));
3577
3578 if ( numSGE > MPT_SCSI_SG_DEPTH )
3579 numSGE = MPT_SCSI_SG_DEPTH;
3580
3581 num_chain = 1;
3582 while (numSGE - num_sge > 0) {
3583 num_chain++;
3584 num_sge += (scale - 1);
3585 }
3586 num_chain++;
3587
3588 dinitprintk((KERN_INFO MYNAM ": %s Now numSGE=%d num_sge=%d num_chain=%d\n",
3589 ioc->name, numSGE, num_sge, num_chain));
3590
a9b2937a 3591 if (ioc->bus_type == SPI)
1da177e4
LT
3592 num_chain *= MPT_SCSI_CAN_QUEUE;
3593 else
3594 num_chain *= MPT_FC_CAN_QUEUE;
3595
3596 ioc->num_chain = num_chain;
3597
3598 sz = num_chain * sizeof(int);
3599 if (ioc->ChainToChain == NULL) {
3600 mem = kmalloc(sz, GFP_ATOMIC);
3601 if (mem == NULL)
3602 return -1;
3603
3604 ioc->ChainToChain = (int *) mem;
3605 dinitprintk((KERN_INFO MYNAM ": %s ChainToChain alloc @ %p, sz=%d bytes\n",
3606 ioc->name, mem, sz));
3607 } else {
3608 mem = (u8 *) ioc->ChainToChain;
3609 }
3610 memset(mem, 0xFF, sz);
3611 return num_chain;
3612}
3613
3614/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3615/*
3616 * PrimeIocFifos - Initialize IOC request and reply FIFOs.
3617 * @ioc: Pointer to MPT_ADAPTER structure
3618 *
3619 * This routine allocates memory for the MPT reply and request frame
3620 * pools (if necessary), and primes the IOC reply FIFO with
3621 * reply frames.
3622 *
3623 * Returns 0 for success, non-zero for failure.
3624 */
3625static int
3626PrimeIocFifos(MPT_ADAPTER *ioc)
3627{
3628 MPT_FRAME_HDR *mf;
3629 unsigned long flags;
3630 dma_addr_t alloc_dma;
3631 u8 *mem;
3632 int i, reply_sz, sz, total_size, num_chain;
3633
3634 /* Prime reply FIFO... */
3635
3636 if (ioc->reply_frames == NULL) {
3637 if ( (num_chain = initChainBuffers(ioc)) < 0)
3638 return -1;
3639
3640 total_size = reply_sz = (ioc->reply_sz * ioc->reply_depth);
3641 dinitprintk((KERN_INFO MYNAM ": %s.ReplyBuffer sz=%d bytes, ReplyDepth=%d\n",
3642 ioc->name, ioc->reply_sz, ioc->reply_depth));
3643 dinitprintk((KERN_INFO MYNAM ": %s.ReplyBuffer sz=%d[%x] bytes\n",
3644 ioc->name, reply_sz, reply_sz));
3645
3646 sz = (ioc->req_sz * ioc->req_depth);
3647 dinitprintk((KERN_INFO MYNAM ": %s.RequestBuffer sz=%d bytes, RequestDepth=%d\n",
3648 ioc->name, ioc->req_sz, ioc->req_depth));
3649 dinitprintk((KERN_INFO MYNAM ": %s.RequestBuffer sz=%d[%x] bytes\n",
3650 ioc->name, sz, sz));
3651 total_size += sz;
3652
3653 sz = num_chain * ioc->req_sz; /* chain buffer pool size */
3654 dinitprintk((KERN_INFO MYNAM ": %s.ChainBuffer sz=%d bytes, ChainDepth=%d\n",
3655 ioc->name, ioc->req_sz, num_chain));
3656 dinitprintk((KERN_INFO MYNAM ": %s.ChainBuffer sz=%d[%x] bytes num_chain=%d\n",
3657 ioc->name, sz, sz, num_chain));
3658
3659 total_size += sz;
3660 mem = pci_alloc_consistent(ioc->pcidev, total_size, &alloc_dma);
3661 if (mem == NULL) {
3662 printk(MYIOC_s_ERR_FMT "Unable to allocate Reply, Request, Chain Buffers!\n",
3663 ioc->name);
3664 goto out_fail;
3665 }
3666
3667 dinitprintk((KERN_INFO MYNAM ": %s.Total alloc @ %p[%p], sz=%d[%x] bytes\n",
3668 ioc->name, mem, (void *)(ulong)alloc_dma, total_size, total_size));
3669
3670 memset(mem, 0, total_size);
3671 ioc->alloc_total += total_size;
3672 ioc->alloc = mem;
3673 ioc->alloc_dma = alloc_dma;
3674 ioc->alloc_sz = total_size;
3675 ioc->reply_frames = (MPT_FRAME_HDR *) mem;
3676 ioc->reply_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF);
3677
c6678e0c
CH
3678 dinitprintk((KERN_INFO MYNAM ": %s ReplyBuffers @ %p[%p]\n",
3679 ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma));
3680
1da177e4
LT
3681 alloc_dma += reply_sz;
3682 mem += reply_sz;
3683
3684 /* Request FIFO - WE manage this! */
3685
3686 ioc->req_frames = (MPT_FRAME_HDR *) mem;
3687 ioc->req_frames_dma = alloc_dma;
3688
c6678e0c 3689 dinitprintk((KERN_INFO MYNAM ": %s RequestBuffers @ %p[%p]\n",
1da177e4
LT
3690 ioc->name, mem, (void *)(ulong)alloc_dma));
3691
3692 ioc->req_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF);
3693
3694#if defined(CONFIG_MTRR) && 0
3695 /*
3696 * Enable Write Combining MTRR for IOC's memory region.
3697 * (at least as much as we can; "size and base must be
3698 * multiples of 4 kiB"
3699 */
3700 ioc->mtrr_reg = mtrr_add(ioc->req_frames_dma,
3701 sz,
3702 MTRR_TYPE_WRCOMB, 1);
3703 dprintk((MYIOC_s_INFO_FMT "MTRR region registered (base:size=%08x:%x)\n",
3704 ioc->name, ioc->req_frames_dma, sz));
3705#endif
3706
3707 for (i = 0; i < ioc->req_depth; i++) {
3708 alloc_dma += ioc->req_sz;
3709 mem += ioc->req_sz;
3710 }
3711
3712 ioc->ChainBuffer = mem;
3713 ioc->ChainBufferDMA = alloc_dma;
3714
c6678e0c 3715 dinitprintk((KERN_INFO MYNAM " :%s ChainBuffers @ %p(%p)\n",
1da177e4
LT
3716 ioc->name, ioc->ChainBuffer, (void *)(ulong)ioc->ChainBufferDMA));
3717
3718 /* Initialize the free chain Q.
3719 */
3720
3721 INIT_LIST_HEAD(&ioc->FreeChainQ);
3722
3723 /* Post the chain buffers to the FreeChainQ.
3724 */
3725 mem = (u8 *)ioc->ChainBuffer;
3726 for (i=0; i < num_chain; i++) {
3727 mf = (MPT_FRAME_HDR *) mem;
3728 list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeChainQ);
3729 mem += ioc->req_sz;
3730 }
3731
3732 /* Initialize Request frames linked list
3733 */
3734 alloc_dma = ioc->req_frames_dma;
3735 mem = (u8 *) ioc->req_frames;
3736
3737 spin_lock_irqsave(&ioc->FreeQlock, flags);
3738 INIT_LIST_HEAD(&ioc->FreeQ);
3739 for (i = 0; i < ioc->req_depth; i++) {
3740 mf = (MPT_FRAME_HDR *) mem;
3741
3742 /* Queue REQUESTs *internally*! */
3743 list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ);
3744
3745 mem += ioc->req_sz;
3746 }
3747 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
3748
3749 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
3750 ioc->sense_buf_pool =
3751 pci_alloc_consistent(ioc->pcidev, sz, &ioc->sense_buf_pool_dma);
3752 if (ioc->sense_buf_pool == NULL) {
3753 printk(MYIOC_s_ERR_FMT "Unable to allocate Sense Buffers!\n",
3754 ioc->name);
3755 goto out_fail;
3756 }
3757
3758 ioc->sense_buf_low_dma = (u32) (ioc->sense_buf_pool_dma & 0xFFFFFFFF);
3759 ioc->alloc_total += sz;
3760 dinitprintk((KERN_INFO MYNAM ": %s.SenseBuffers @ %p[%p]\n",
3761 ioc->name, ioc->sense_buf_pool, (void *)(ulong)ioc->sense_buf_pool_dma));
3762
3763 }
3764
3765 /* Post Reply frames to FIFO
3766 */
3767 alloc_dma = ioc->alloc_dma;
3768 dinitprintk((KERN_INFO MYNAM ": %s.ReplyBuffers @ %p[%p]\n",
3769 ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma));
3770
3771 for (i = 0; i < ioc->reply_depth; i++) {
3772 /* Write each address to the IOC! */
3773 CHIPREG_WRITE32(&ioc->chip->ReplyFifo, alloc_dma);
3774 alloc_dma += ioc->reply_sz;
3775 }
3776
3777 return 0;
3778
3779out_fail:
3780 if (ioc->alloc != NULL) {
3781 sz = ioc->alloc_sz;
3782 pci_free_consistent(ioc->pcidev,
3783 sz,
3784 ioc->alloc, ioc->alloc_dma);
3785 ioc->reply_frames = NULL;
3786 ioc->req_frames = NULL;
3787 ioc->alloc_total -= sz;
3788 }
3789 if (ioc->sense_buf_pool != NULL) {
3790 sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
3791 pci_free_consistent(ioc->pcidev,
3792 sz,
3793 ioc->sense_buf_pool, ioc->sense_buf_pool_dma);
3794 ioc->sense_buf_pool = NULL;
3795 }
3796 return -1;
3797}
3798
3799/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3800/**
3801 * mpt_handshake_req_reply_wait - Send MPT request to and receive reply
3802 * from IOC via doorbell handshake method.
3803 * @ioc: Pointer to MPT_ADAPTER structure
3804 * @reqBytes: Size of the request in bytes
3805 * @req: Pointer to MPT request frame
3806 * @replyBytes: Expected size of the reply in bytes
3807 * @u16reply: Pointer to area where reply should be written
3808 * @maxwait: Max wait time for a reply (in seconds)
3809 * @sleepFlag: Specifies whether the process can sleep
3810 *
3811 * NOTES: It is the callers responsibility to byte-swap fields in the
3812 * request which are greater than 1 byte in size. It is also the
3813 * callers responsibility to byte-swap response fields which are
3814 * greater than 1 byte in size.
3815 *
3816 * Returns 0 for success, non-zero for failure.
3817 */
3818static int
3819mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req,
c6678e0c 3820 int replyBytes, u16 *u16reply, int maxwait, int sleepFlag)
1da177e4
LT
3821{
3822 MPIDefaultReply_t *mptReply;
3823 int failcnt = 0;
3824 int t;
3825
3826 /*
3827 * Get ready to cache a handshake reply
3828 */
3829 ioc->hs_reply_idx = 0;
3830 mptReply = (MPIDefaultReply_t *) ioc->hs_reply;
3831 mptReply->MsgLength = 0;
3832
3833 /*
3834 * Make sure there are no doorbells (WRITE 0 to IntStatus reg),
3835 * then tell IOC that we want to handshake a request of N words.
3836 * (WRITE u32val to Doorbell reg).
3837 */
3838 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3839 CHIPREG_WRITE32(&ioc->chip->Doorbell,
3840 ((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
3841 ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
3842
3843 /*
3844 * Wait for IOC's doorbell handshake int
3845 */
3846 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
3847 failcnt++;
3848
3849 dhsprintk((MYIOC_s_INFO_FMT "HandShake request start reqBytes=%d, WaitCnt=%d%s\n",
3850 ioc->name, reqBytes, t, failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
3851
3852 /* Read doorbell and check for active bit */
3853 if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
3854 return -1;
3855
3856 /*
3857 * Clear doorbell int (WRITE 0 to IntStatus reg),
3858 * then wait for IOC to ACKnowledge that it's ready for
3859 * our handshake request.
3860 */
3861 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3862 if (!failcnt && (t = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
3863 failcnt++;
3864
3865 if (!failcnt) {
3866 int ii;
3867 u8 *req_as_bytes = (u8 *) req;
3868
3869 /*
3870 * Stuff request words via doorbell handshake,
3871 * with ACK from IOC for each.
3872 */
3873 for (ii = 0; !failcnt && ii < reqBytes/4; ii++) {
3874 u32 word = ((req_as_bytes[(ii*4) + 0] << 0) |
3875 (req_as_bytes[(ii*4) + 1] << 8) |
3876 (req_as_bytes[(ii*4) + 2] << 16) |
3877 (req_as_bytes[(ii*4) + 3] << 24));
3878
3879 CHIPREG_WRITE32(&ioc->chip->Doorbell, word);
3880 if ((t = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
3881 failcnt++;
3882 }
3883
3884 dhsprintk((KERN_INFO MYNAM ": Handshake request frame (@%p) header\n", req));
3885 DBG_DUMP_REQUEST_FRAME_HDR(req)
3886
3887 dhsprintk((MYIOC_s_INFO_FMT "HandShake request post done, WaitCnt=%d%s\n",
3888 ioc->name, t, failcnt ? " - MISSING DOORBELL ACK!" : ""));
3889
3890 /*
3891 * Wait for completion of doorbell handshake reply from the IOC
3892 */
3893 if (!failcnt && (t = WaitForDoorbellReply(ioc, maxwait, sleepFlag)) < 0)
3894 failcnt++;
c6678e0c 3895
1da177e4
LT
3896 dhsprintk((MYIOC_s_INFO_FMT "HandShake reply count=%d%s\n",
3897 ioc->name, t, failcnt ? " - MISSING DOORBELL REPLY!" : ""));
3898
3899 /*
3900 * Copy out the cached reply...
3901 */
3902 for (ii=0; ii < min(replyBytes/2,mptReply->MsgLength*2); ii++)
3903 u16reply[ii] = ioc->hs_reply[ii];
3904 } else {
3905 return -99;
3906 }
3907
3908 return -failcnt;
3909}
3910
3911/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3912/*
3913 * WaitForDoorbellAck - Wait for IOC to clear the IOP_DOORBELL_STATUS bit
3914 * in it's IntStatus register.
3915 * @ioc: Pointer to MPT_ADAPTER structure
3916 * @howlong: How long to wait (in seconds)
3917 * @sleepFlag: Specifies whether the process can sleep
3918 *
3919 * This routine waits (up to ~2 seconds max) for IOC doorbell
3920 * handshake ACKnowledge.
3921 *
3922 * Returns a negative value on failure, else wait loop count.
3923 */
3924static int
3925WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
3926{
3927 int cntdn;
3928 int count = 0;
3929 u32 intstat=0;
3930
466544d8 3931 cntdn = 1000 * howlong;
1da177e4
LT
3932
3933 if (sleepFlag == CAN_SLEEP) {
3934 while (--cntdn) {
3935 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
3936 if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
3937 break;
3938 msleep_interruptible (1);
3939 count++;
3940 }
3941 } else {
3942 while (--cntdn) {
3943 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
3944 if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
3945 break;
3946 mdelay (1);
3947 count++;
3948 }
3949 }
3950
3951 if (cntdn) {
3952 dprintk((MYIOC_s_INFO_FMT "WaitForDoorbell ACK (count=%d)\n",
3953 ioc->name, count));
3954 return count;
3955 }
3956
3957 printk(MYIOC_s_ERR_FMT "Doorbell ACK timeout (count=%d), IntStatus=%x!\n",
3958 ioc->name, count, intstat);
3959 return -1;
3960}
3961
3962/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3963/*
3964 * WaitForDoorbellInt - Wait for IOC to set the HIS_DOORBELL_INTERRUPT bit
3965 * in it's IntStatus register.
3966 * @ioc: Pointer to MPT_ADAPTER structure
3967 * @howlong: How long to wait (in seconds)
3968 * @sleepFlag: Specifies whether the process can sleep
3969 *
3970 * This routine waits (up to ~2 seconds max) for IOC doorbell interrupt.
3971 *
3972 * Returns a negative value on failure, else wait loop count.
3973 */
3974static int
3975WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
3976{
3977 int cntdn;
3978 int count = 0;
3979 u32 intstat=0;
3980
466544d8 3981 cntdn = 1000 * howlong;
1da177e4
LT
3982 if (sleepFlag == CAN_SLEEP) {
3983 while (--cntdn) {
3984 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
3985 if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
3986 break;
3987 msleep_interruptible(1);
3988 count++;
3989 }
3990 } else {
3991 while (--cntdn) {
3992 intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
3993 if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
3994 break;
3995 mdelay(1);
3996 count++;
3997 }
3998 }
3999
4000 if (cntdn) {
4001 dprintk((MYIOC_s_INFO_FMT "WaitForDoorbell INT (cnt=%d) howlong=%d\n",
4002 ioc->name, count, howlong));
4003 return count;
4004 }
4005
4006 printk(MYIOC_s_ERR_FMT "Doorbell INT timeout (count=%d), IntStatus=%x!\n",
4007 ioc->name, count, intstat);
4008 return -1;
4009}
4010
4011/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4012/*
4013 * WaitForDoorbellReply - Wait for and capture a IOC handshake reply.
4014 * @ioc: Pointer to MPT_ADAPTER structure
4015 * @howlong: How long to wait (in seconds)
4016 * @sleepFlag: Specifies whether the process can sleep
4017 *
4018 * This routine polls the IOC for a handshake reply, 16 bits at a time.
4019 * Reply is cached to IOC private area large enough to hold a maximum
4020 * of 128 bytes of reply data.
4021 *
4022 * Returns a negative value on failure, else size of reply in WORDS.
4023 */
4024static int
4025WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
4026{
4027 int u16cnt = 0;
4028 int failcnt = 0;
4029 int t;
4030 u16 *hs_reply = ioc->hs_reply;
4031 volatile MPIDefaultReply_t *mptReply = (MPIDefaultReply_t *) ioc->hs_reply;
4032 u16 hword;
4033
4034 hs_reply[0] = hs_reply[1] = hs_reply[7] = 0;
4035
4036 /*
4037 * Get first two u16's so we can look at IOC's intended reply MsgLength
4038 */
4039 u16cnt=0;
4040 if ((t = WaitForDoorbellInt(ioc, howlong, sleepFlag)) < 0) {
4041 failcnt++;
4042 } else {
4043 hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4044 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4045 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4046 failcnt++;
4047 else {
4048 hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4049 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4050 }
4051 }
4052
4053 dhsprintk((MYIOC_s_INFO_FMT "WaitCnt=%d First handshake reply word=%08x%s\n",
c6678e0c 4054 ioc->name, t, le32_to_cpu(*(u32 *)hs_reply),
1da177e4
LT
4055 failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
4056
4057 /*
4058 * If no error (and IOC said MsgLength is > 0), piece together
4059 * reply 16 bits at a time.
4060 */
4061 for (u16cnt=2; !failcnt && u16cnt < (2 * mptReply->MsgLength); u16cnt++) {
4062 if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4063 failcnt++;
4064 hword = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4065 /* don't overflow our IOC hs_reply[] buffer! */
4066 if (u16cnt < sizeof(ioc->hs_reply) / sizeof(ioc->hs_reply[0]))
4067 hs_reply[u16cnt] = hword;
4068 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4069 }
4070
4071 if (!failcnt && (t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4072 failcnt++;
4073 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4074
4075 if (failcnt) {
4076 printk(MYIOC_s_ERR_FMT "Handshake reply failure!\n",
4077 ioc->name);
4078 return -failcnt;
4079 }
4080#if 0
4081 else if (u16cnt != (2 * mptReply->MsgLength)) {
4082 return -101;
4083 }
4084 else if ((mptReply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
4085 return -102;
4086 }
4087#endif
4088
4089 dhsprintk((MYIOC_s_INFO_FMT "Got Handshake reply:\n", ioc->name));
4090 DBG_DUMP_REPLY_FRAME(mptReply)
4091
4092 dhsprintk((MYIOC_s_INFO_FMT "WaitForDoorbell REPLY WaitCnt=%d (sz=%d)\n",
4093 ioc->name, t, u16cnt/2));
4094 return u16cnt/2;
4095}
4096
4097/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4098/*
4099 * GetLanConfigPages - Fetch LANConfig pages.
4100 * @ioc: Pointer to MPT_ADAPTER structure
4101 *
4102 * Return: 0 for success
4103 * -ENOMEM if no memory available
4104 * -EPERM if not allowed due to ISR context
4105 * -EAGAIN if no msg frames currently available
4106 * -EFAULT for non-successful reply or no reply (timeout)
4107 */
4108static int
4109GetLanConfigPages(MPT_ADAPTER *ioc)
4110{
4111 ConfigPageHeader_t hdr;
4112 CONFIGPARMS cfg;
4113 LANPage0_t *ppage0_alloc;
4114 dma_addr_t page0_dma;
4115 LANPage1_t *ppage1_alloc;
4116 dma_addr_t page1_dma;
4117 int rc = 0;
4118 int data_sz;
4119 int copy_sz;
4120
4121 /* Get LAN Page 0 header */
4122 hdr.PageVersion = 0;
4123 hdr.PageLength = 0;
4124 hdr.PageNumber = 0;
4125 hdr.PageType = MPI_CONFIG_PAGETYPE_LAN;
69218ee5 4126 cfg.cfghdr.hdr = &hdr;
1da177e4
LT
4127 cfg.physAddr = -1;
4128 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4129 cfg.dir = 0;
4130 cfg.pageAddr = 0;
4131 cfg.timeout = 0;
4132
4133 if ((rc = mpt_config(ioc, &cfg)) != 0)
4134 return rc;
4135
4136 if (hdr.PageLength > 0) {
4137 data_sz = hdr.PageLength * 4;
4138 ppage0_alloc = (LANPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma);
4139 rc = -ENOMEM;
4140 if (ppage0_alloc) {
4141 memset((u8 *)ppage0_alloc, 0, data_sz);
4142 cfg.physAddr = page0_dma;
4143 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4144
4145 if ((rc = mpt_config(ioc, &cfg)) == 0) {
4146 /* save the data */
4147 copy_sz = min_t(int, sizeof(LANPage0_t), data_sz);
4148 memcpy(&ioc->lan_cnfg_page0, ppage0_alloc, copy_sz);
4149
4150 }
4151
4152 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);
4153
4154 /* FIXME!
4155 * Normalize endianness of structure data,
4156 * by byte-swapping all > 1 byte fields!
4157 */
4158
4159 }
4160
4161 if (rc)
4162 return rc;
4163 }
4164
4165 /* Get LAN Page 1 header */
4166 hdr.PageVersion = 0;
4167 hdr.PageLength = 0;
4168 hdr.PageNumber = 1;
4169 hdr.PageType = MPI_CONFIG_PAGETYPE_LAN;
69218ee5 4170 cfg.cfghdr.hdr = &hdr;
1da177e4
LT
4171 cfg.physAddr = -1;
4172 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4173 cfg.dir = 0;
4174 cfg.pageAddr = 0;
4175
4176 if ((rc = mpt_config(ioc, &cfg)) != 0)
4177 return rc;
4178
4179 if (hdr.PageLength == 0)
4180 return 0;
4181
4182 data_sz = hdr.PageLength * 4;
4183 rc = -ENOMEM;
4184 ppage1_alloc = (LANPage1_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page1_dma);
4185 if (ppage1_alloc) {
4186 memset((u8 *)ppage1_alloc, 0, data_sz);
4187 cfg.physAddr = page1_dma;
4188 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4189
4190 if ((rc = mpt_config(ioc, &cfg)) == 0) {
4191 /* save the data */
4192 copy_sz = min_t(int, sizeof(LANPage1_t), data_sz);
4193 memcpy(&ioc->lan_cnfg_page1, ppage1_alloc, copy_sz);
4194 }
4195
4196 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage1_alloc, page1_dma);
4197
4198 /* FIXME!
4199 * Normalize endianness of structure data,
4200 * by byte-swapping all > 1 byte fields!
4201 */
4202
4203 }
4204
4205 return rc;
4206}
4207
4208/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4209/*
05e8ec17 4210 * mptbase_GetFcPortPage0 - Fetch FCPort config Page0.
1da177e4
LT
4211 * @ioc: Pointer to MPT_ADAPTER structure
4212 * @portnum: IOC Port number
4213 *
4214 * Return: 0 for success
4215 * -ENOMEM if no memory available
4216 * -EPERM if not allowed due to ISR context
4217 * -EAGAIN if no msg frames currently available
4218 * -EFAULT for non-successful reply or no reply (timeout)
4219 */
05e8ec17
MR
4220int
4221mptbase_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
1da177e4
LT
4222{
4223 ConfigPageHeader_t hdr;
4224 CONFIGPARMS cfg;
4225 FCPortPage0_t *ppage0_alloc;
4226 FCPortPage0_t *pp0dest;
4227 dma_addr_t page0_dma;
4228 int data_sz;
4229 int copy_sz;
4230 int rc;
05e8ec17
MR
4231 int count = 400;
4232
1da177e4
LT
4233
4234 /* Get FCPort Page 0 header */
4235 hdr.PageVersion = 0;
4236 hdr.PageLength = 0;
4237 hdr.PageNumber = 0;
4238 hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT;
69218ee5 4239 cfg.cfghdr.hdr = &hdr;
1da177e4
LT
4240 cfg.physAddr = -1;
4241 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4242 cfg.dir = 0;
4243 cfg.pageAddr = portnum;
4244 cfg.timeout = 0;
4245
4246 if ((rc = mpt_config(ioc, &cfg)) != 0)
4247 return rc;
4248
4249 if (hdr.PageLength == 0)
4250 return 0;
4251
4252 data_sz = hdr.PageLength * 4;
4253 rc = -ENOMEM;
4254 ppage0_alloc = (FCPortPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma);
4255 if (ppage0_alloc) {
05e8ec17
MR
4256
4257 try_again:
1da177e4
LT
4258 memset((u8 *)ppage0_alloc, 0, data_sz);
4259 cfg.physAddr = page0_dma;
4260 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4261
4262 if ((rc = mpt_config(ioc, &cfg)) == 0) {
4263 /* save the data */
4264 pp0dest = &ioc->fc_port_page0[portnum];
4265 copy_sz = min_t(int, sizeof(FCPortPage0_t), data_sz);
4266 memcpy(pp0dest, ppage0_alloc, copy_sz);
4267
4268 /*
4269 * Normalize endianness of structure data,
4270 * by byte-swapping all > 1 byte fields!
4271 */
4272 pp0dest->Flags = le32_to_cpu(pp0dest->Flags);
4273 pp0dest->PortIdentifier = le32_to_cpu(pp0dest->PortIdentifier);
4274 pp0dest->WWNN.Low = le32_to_cpu(pp0dest->WWNN.Low);
4275 pp0dest->WWNN.High = le32_to_cpu(pp0dest->WWNN.High);
4276 pp0dest->WWPN.Low = le32_to_cpu(pp0dest->WWPN.Low);
4277 pp0dest->WWPN.High = le32_to_cpu(pp0dest->WWPN.High);
4278 pp0dest->SupportedServiceClass = le32_to_cpu(pp0dest->SupportedServiceClass);
4279 pp0dest->SupportedSpeeds = le32_to_cpu(pp0dest->SupportedSpeeds);
4280 pp0dest->CurrentSpeed = le32_to_cpu(pp0dest->CurrentSpeed);
4281 pp0dest->MaxFrameSize = le32_to_cpu(pp0dest->MaxFrameSize);
4282 pp0dest->FabricWWNN.Low = le32_to_cpu(pp0dest->FabricWWNN.Low);
4283 pp0dest->FabricWWNN.High = le32_to_cpu(pp0dest->FabricWWNN.High);
4284 pp0dest->FabricWWPN.Low = le32_to_cpu(pp0dest->FabricWWPN.Low);
4285 pp0dest->FabricWWPN.High = le32_to_cpu(pp0dest->FabricWWPN.High);
4286 pp0dest->DiscoveredPortsCount = le32_to_cpu(pp0dest->DiscoveredPortsCount);
4287 pp0dest->MaxInitiators = le32_to_cpu(pp0dest->MaxInitiators);
4288
05e8ec17
MR
4289 /*
4290 * if still doing discovery,
4291 * hang loose a while until finished
4292 */
4293 if (pp0dest->PortState == MPI_FCPORTPAGE0_PORTSTATE_UNKNOWN) {
4294 if (count-- > 0) {
4295 msleep_interruptible(100);
4296 goto try_again;
4297 }
4298 printk(MYIOC_s_INFO_FMT "Firmware discovery not"
4299 " complete.\n",
4300 ioc->name);
4301 }
1da177e4
LT
4302 }
4303
4304 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);
4305 }
4306
4307 return rc;
4308}
4309
82ffb671
CH
4310/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4311/*
4312 * mptbase_sas_persist_operation - Perform operation on SAS Persitent Table
4313 * @ioc: Pointer to MPT_ADAPTER structure
4314 * @sas_address: 64bit SAS Address for operation.
4315 * @target_id: specified target for operation
4316 * @bus: specified bus for operation
4317 * @persist_opcode: see below
4318 *
4319 * MPI_SAS_OP_CLEAR_NOT_PRESENT - Free all persist TargetID mappings for
4320 * devices not currently present.
4321 * MPI_SAS_OP_CLEAR_ALL_PERSISTENT - Clear al persist TargetID mappings
4322 *
4323 * NOTE: Don't use not this function during interrupt time.
4324 *
4325 * Returns: 0 for success, non-zero error
4326 */
4327
4328/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4329int
4330mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode)
4331{
4332 SasIoUnitControlRequest_t *sasIoUnitCntrReq;
4333 SasIoUnitControlReply_t *sasIoUnitCntrReply;
4334 MPT_FRAME_HDR *mf = NULL;
4335 MPIHeader_t *mpi_hdr;
4336
4337
4338 /* insure garbage is not sent to fw */
4339 switch(persist_opcode) {
4340
4341 case MPI_SAS_OP_CLEAR_NOT_PRESENT:
4342 case MPI_SAS_OP_CLEAR_ALL_PERSISTENT:
4343 break;
4344
4345 default:
4346 return -1;
4347 break;
4348 }
4349
4350 printk("%s: persist_opcode=%x\n",__FUNCTION__, persist_opcode);
4351
4352 /* Get a MF for this command.
4353 */
4354 if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
4355 printk("%s: no msg frames!\n",__FUNCTION__);
4356 return -1;
4357 }
4358
4359 mpi_hdr = (MPIHeader_t *) mf;
4360 sasIoUnitCntrReq = (SasIoUnitControlRequest_t *)mf;
4361 memset(sasIoUnitCntrReq,0,sizeof(SasIoUnitControlRequest_t));
4362 sasIoUnitCntrReq->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
4363 sasIoUnitCntrReq->MsgContext = mpi_hdr->MsgContext;
4364 sasIoUnitCntrReq->Operation = persist_opcode;
4365
4366 init_timer(&ioc->persist_timer);
4367 ioc->persist_timer.data = (unsigned long) ioc;
4368 ioc->persist_timer.function = mpt_timer_expired;
4369 ioc->persist_timer.expires = jiffies + HZ*10 /* 10 sec */;
4370 ioc->persist_wait_done=0;
4371 add_timer(&ioc->persist_timer);
4372 mpt_put_msg_frame(mpt_base_index, ioc, mf);
4373 wait_event(mpt_waitq, ioc->persist_wait_done);
4374
4375 sasIoUnitCntrReply =
4376 (SasIoUnitControlReply_t *)ioc->persist_reply_frame;
4377 if (le16_to_cpu(sasIoUnitCntrReply->IOCStatus) != MPI_IOCSTATUS_SUCCESS) {
4378 printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
4379 __FUNCTION__,
4380 sasIoUnitCntrReply->IOCStatus,
4381 sasIoUnitCntrReply->IOCLogInfo);
4382 return -1;
4383 }
4384
4385 printk("%s: success\n",__FUNCTION__);
4386 return 0;
4387}
4388
1da177e4
LT
4389/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4390/*
4391 * GetIoUnitPage2 - Retrieve BIOS version and boot order information.
4392 * @ioc: Pointer to MPT_ADAPTER structure
4393 *
4394 * Returns: 0 for success
4395 * -ENOMEM if no memory available
4396 * -EPERM if not allowed due to ISR context
4397 * -EAGAIN if no msg frames currently available
4398 * -EFAULT for non-successful reply or no reply (timeout)
4399 */
4400static int
4401GetIoUnitPage2(MPT_ADAPTER *ioc)
4402{
4403 ConfigPageHeader_t hdr;
4404 CONFIGPARMS cfg;
4405 IOUnitPage2_t *ppage_alloc;
4406 dma_addr_t page_dma;
4407 int data_sz;
4408 int rc;
4409
4410 /* Get the page header */
4411 hdr.PageVersion = 0;
4412 hdr.PageLength = 0;
4413 hdr.PageNumber = 2;
4414 hdr.PageType = MPI_CONFIG_PAGETYPE_IO_UNIT;
69218ee5 4415 cfg.cfghdr.hdr = &hdr;
1da177e4
LT
4416 cfg.physAddr = -1;
4417 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4418 cfg.dir = 0;
4419 cfg.pageAddr = 0;
4420 cfg.timeout = 0;
4421
4422 if ((rc = mpt_config(ioc, &cfg)) != 0)
4423 return rc;
4424
4425 if (hdr.PageLength == 0)
4426 return 0;
4427
4428 /* Read the config page */
4429 data_sz = hdr.PageLength * 4;
4430 rc = -ENOMEM;
4431 ppage_alloc = (IOUnitPage2_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page_dma);
4432 if (ppage_alloc) {
4433 memset((u8 *)ppage_alloc, 0, data_sz);
4434 cfg.physAddr = page_dma;
4435 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4436
4437 /* If Good, save data */
4438 if ((rc = mpt_config(ioc, &cfg)) == 0)
4439 ioc->biosVersion = le32_to_cpu(ppage_alloc->BiosVersion);
4440
4441 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage_alloc, page_dma);
4442 }
4443
4444 return rc;
4445}
4446
4447/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4448/* mpt_GetScsiPortSettings - read SCSI Port Page 0 and 2
4449 * @ioc: Pointer to a Adapter Strucutre
4450 * @portnum: IOC port number
4451 *
4452 * Return: -EFAULT if read of config page header fails
4453 * or if no nvram
4454 * If read of SCSI Port Page 0 fails,
4455 * NVRAM = MPT_HOST_NVRAM_INVALID (0xFFFFFFFF)
4456 * Adapter settings: async, narrow
4457 * Return 1
4458 * If read of SCSI Port Page 2 fails,
4459 * Adapter settings valid
4460 * NVRAM = MPT_HOST_NVRAM_INVALID (0xFFFFFFFF)
4461 * Return 1
4462 * Else
4463 * Both valid
4464 * Return 0
4465 * CHECK - what type of locking mechanisms should be used????
4466 */
4467static int
4468mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum)
4469{
4470 u8 *pbuf;
4471 dma_addr_t buf_dma;
4472 CONFIGPARMS cfg;
4473 ConfigPageHeader_t header;
4474 int ii;
4475 int data, rc = 0;
4476
4477 /* Allocate memory
4478 */
4479 if (!ioc->spi_data.nvram) {
4480 int sz;
4481 u8 *mem;
4482 sz = MPT_MAX_SCSI_DEVICES * sizeof(int);
4483 mem = kmalloc(sz, GFP_ATOMIC);
4484 if (mem == NULL)
4485 return -EFAULT;
4486
4487 ioc->spi_data.nvram = (int *) mem;
4488
4489 dprintk((MYIOC_s_INFO_FMT "SCSI device NVRAM settings @ %p, sz=%d\n",
4490 ioc->name, ioc->spi_data.nvram, sz));
4491 }
4492
4493 /* Invalidate NVRAM information
4494 */
4495 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
4496 ioc->spi_data.nvram[ii] = MPT_HOST_NVRAM_INVALID;
4497 }
4498
4499 /* Read SPP0 header, allocate memory, then read page.
4500 */
4501 header.PageVersion = 0;
4502 header.PageLength = 0;
4503 header.PageNumber = 0;
4504 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT;
69218ee5 4505 cfg.cfghdr.hdr = &header;
1da177e4
LT
4506 cfg.physAddr = -1;
4507 cfg.pageAddr = portnum;
4508 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4509 cfg.dir = 0;
4510 cfg.timeout = 0; /* use default */
4511 if (mpt_config(ioc, &cfg) != 0)
4512 return -EFAULT;
4513
4514 if (header.PageLength > 0) {
4515 pbuf = pci_alloc_consistent(ioc->pcidev, header.PageLength * 4, &buf_dma);
4516 if (pbuf) {
4517 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4518 cfg.physAddr = buf_dma;
4519 if (mpt_config(ioc, &cfg) != 0) {
4520 ioc->spi_data.maxBusWidth = MPT_NARROW;
4521 ioc->spi_data.maxSyncOffset = 0;
4522 ioc->spi_data.minSyncFactor = MPT_ASYNC;
4523 ioc->spi_data.busType = MPT_HOST_BUS_UNKNOWN;
4524 rc = 1;
c6678e0c
CH
4525 ddvprintk((MYIOC_s_INFO_FMT "Unable to read PortPage0 minSyncFactor=%x\n",
4526 ioc->name, ioc->spi_data.minSyncFactor));
1da177e4
LT
4527 } else {
4528 /* Save the Port Page 0 data
4529 */
4530 SCSIPortPage0_t *pPP0 = (SCSIPortPage0_t *) pbuf;
4531 pPP0->Capabilities = le32_to_cpu(pPP0->Capabilities);
4532 pPP0->PhysicalInterface = le32_to_cpu(pPP0->PhysicalInterface);
4533
4534 if ( (pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_QAS) == 0 ) {
4535 ioc->spi_data.noQas |= MPT_TARGET_NO_NEGO_QAS;
c6678e0c 4536 ddvprintk((KERN_INFO MYNAM " :%s noQas due to Capabilities=%x\n",
1da177e4
LT
4537 ioc->name, pPP0->Capabilities));
4538 }
4539 ioc->spi_data.maxBusWidth = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_WIDE ? 1 : 0;
4540 data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MAX_SYNC_OFFSET_MASK;
4541 if (data) {
4542 ioc->spi_data.maxSyncOffset = (u8) (data >> 16);
4543 data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MIN_SYNC_PERIOD_MASK;
4544 ioc->spi_data.minSyncFactor = (u8) (data >> 8);
c6678e0c
CH
4545 ddvprintk((MYIOC_s_INFO_FMT "PortPage0 minSyncFactor=%x\n",
4546 ioc->name, ioc->spi_data.minSyncFactor));
1da177e4
LT
4547 } else {
4548 ioc->spi_data.maxSyncOffset = 0;
4549 ioc->spi_data.minSyncFactor = MPT_ASYNC;
4550 }
4551
4552 ioc->spi_data.busType = pPP0->PhysicalInterface & MPI_SCSIPORTPAGE0_PHY_SIGNAL_TYPE_MASK;
4553
4554 /* Update the minSyncFactor based on bus type.
4555 */
4556 if ((ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_HVD) ||
4557 (ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_SE)) {
4558
c6678e0c 4559 if (ioc->spi_data.minSyncFactor < MPT_ULTRA) {
1da177e4 4560 ioc->spi_data.minSyncFactor = MPT_ULTRA;
c6678e0c
CH
4561 ddvprintk((MYIOC_s_INFO_FMT "HVD or SE detected, minSyncFactor=%x\n",
4562 ioc->name, ioc->spi_data.minSyncFactor));
4563 }
1da177e4
LT
4564 }
4565 }
4566 if (pbuf) {
4567 pci_free_consistent(ioc->pcidev, header.PageLength * 4, pbuf, buf_dma);
4568 }
4569 }
4570 }
4571
4572 /* SCSI Port Page 2 - Read the header then the page.
4573 */
4574 header.PageVersion = 0;
4575 header.PageLength = 0;
4576 header.PageNumber = 2;
4577 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT;
69218ee5 4578 cfg.cfghdr.hdr = &header;
1da177e4
LT
4579 cfg.physAddr = -1;
4580 cfg.pageAddr = portnum;
4581 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4582 cfg.dir = 0;
4583 if (mpt_config(ioc, &cfg) != 0)
4584 return -EFAULT;
4585
4586 if (header.PageLength > 0) {
4587 /* Allocate memory and read SCSI Port Page 2
4588 */
4589 pbuf = pci_alloc_consistent(ioc->pcidev, header.PageLength * 4, &buf_dma);
4590 if (pbuf) {
4591 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_NVRAM;
4592 cfg.physAddr = buf_dma;
4593 if (mpt_config(ioc, &cfg) != 0) {
4594 /* Nvram data is left with INVALID mark
4595 */
4596 rc = 1;
4597 } else {
4598 SCSIPortPage2_t *pPP2 = (SCSIPortPage2_t *) pbuf;
4599 MpiDeviceInfo_t *pdevice = NULL;
4600
d8e925dc
ME
4601 /*
4602 * Save "Set to Avoid SCSI Bus Resets" flag
4603 */
4604 ioc->spi_data.bus_reset =
4605 (le32_to_cpu(pPP2->PortFlags) &
4606 MPI_SCSIPORTPAGE2_PORT_FLAGS_AVOID_SCSI_RESET) ?
4607 0 : 1 ;
4608
1da177e4
LT
4609 /* Save the Port Page 2 data
4610 * (reformat into a 32bit quantity)
4611 */
4612 data = le32_to_cpu(pPP2->PortFlags) & MPI_SCSIPORTPAGE2_PORT_FLAGS_DV_MASK;
4613 ioc->spi_data.PortFlags = data;
4614 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
4615 pdevice = &pPP2->DeviceSettings[ii];
4616 data = (le16_to_cpu(pdevice->DeviceFlags) << 16) |
4617 (pdevice->SyncFactor << 8) | pdevice->Timeout;
4618 ioc->spi_data.nvram[ii] = data;
4619 }
4620 }
4621
4622 pci_free_consistent(ioc->pcidev, header.PageLength * 4, pbuf, buf_dma);
4623 }
4624 }
4625
4626 /* Update Adapter limits with those from NVRAM
4627 * Comment: Don't need to do this. Target performance
4628 * parameters will never exceed the adapters limits.
4629 */
4630
4631 return rc;
4632}
4633
4634/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4635/* mpt_readScsiDevicePageHeaders - save version and length of SDP1
4636 * @ioc: Pointer to a Adapter Strucutre
4637 * @portnum: IOC port number
4638 *
4639 * Return: -EFAULT if read of config page header fails
4640 * or 0 if success.
4641 */
4642static int
4643mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum)
4644{
4645 CONFIGPARMS cfg;
4646 ConfigPageHeader_t header;
4647
4648 /* Read the SCSI Device Page 1 header
4649 */
4650 header.PageVersion = 0;
4651 header.PageLength = 0;
4652 header.PageNumber = 1;
4653 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
69218ee5 4654 cfg.cfghdr.hdr = &header;
1da177e4
LT
4655 cfg.physAddr = -1;
4656 cfg.pageAddr = portnum;
4657 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4658 cfg.dir = 0;
4659 cfg.timeout = 0;
4660 if (mpt_config(ioc, &cfg) != 0)
4661 return -EFAULT;
4662
69218ee5
CH
4663 ioc->spi_data.sdp1version = cfg.cfghdr.hdr->PageVersion;
4664 ioc->spi_data.sdp1length = cfg.cfghdr.hdr->PageLength;
1da177e4
LT
4665
4666 header.PageVersion = 0;
4667 header.PageLength = 0;
4668 header.PageNumber = 0;
4669 header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
4670 if (mpt_config(ioc, &cfg) != 0)
4671 return -EFAULT;
4672
69218ee5
CH
4673 ioc->spi_data.sdp0version = cfg.cfghdr.hdr->PageVersion;
4674 ioc->spi_data.sdp0length = cfg.cfghdr.hdr->PageLength;
1da177e4
LT
4675
4676 dcprintk((MYIOC_s_INFO_FMT "Headers: 0: version %d length %d\n",
4677 ioc->name, ioc->spi_data.sdp0version, ioc->spi_data.sdp0length));
4678
4679 dcprintk((MYIOC_s_INFO_FMT "Headers: 1: version %d length %d\n",
4680 ioc->name, ioc->spi_data.sdp1version, ioc->spi_data.sdp1length));
4681 return 0;
4682}
4683
4684/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4685/**
4686 * mpt_findImVolumes - Identify IDs of hidden disks and RAID Volumes
4687 * @ioc: Pointer to a Adapter Strucutre
4688 * @portnum: IOC port number
4689 *
4690 * Return:
4691 * 0 on success
4692 * -EFAULT if read of config page header fails or data pointer not NULL
4693 * -ENOMEM if pci_alloc failed
4694 */
4695int
4696mpt_findImVolumes(MPT_ADAPTER *ioc)
4697{
4698 IOCPage2_t *pIoc2;
4699 u8 *mem;
4700 ConfigPageIoc2RaidVol_t *pIocRv;
4701 dma_addr_t ioc2_dma;
4702 CONFIGPARMS cfg;
4703 ConfigPageHeader_t header;
4704 int jj;
4705 int rc = 0;
4706 int iocpage2sz;
4707 u8 nVols, nPhys;
4708 u8 vid, vbus, vioc;
4709
4710 /* Read IOCP2 header then the page.
4711 */
4712 header.PageVersion = 0;
4713 header.PageLength = 0;
4714 header.PageNumber = 2;
4715 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
69218ee5 4716 cfg.cfghdr.hdr = &header;
1da177e4
LT
4717 cfg.physAddr = -1;
4718 cfg.pageAddr = 0;
4719 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4720 cfg.dir = 0;
4721 cfg.timeout = 0;
4722 if (mpt_config(ioc, &cfg) != 0)
4723 return -EFAULT;
4724
4725 if (header.PageLength == 0)
4726 return -EFAULT;
4727
4728 iocpage2sz = header.PageLength * 4;
4729 pIoc2 = pci_alloc_consistent(ioc->pcidev, iocpage2sz, &ioc2_dma);
4730 if (!pIoc2)
4731 return -ENOMEM;
4732
4733 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4734 cfg.physAddr = ioc2_dma;
4735 if (mpt_config(ioc, &cfg) != 0)
4736 goto done_and_free;
4737
466544d8 4738 if ( (mem = (u8 *)ioc->raid_data.pIocPg2) == NULL ) {
1da177e4
LT
4739 mem = kmalloc(iocpage2sz, GFP_ATOMIC);
4740 if (mem) {
466544d8 4741 ioc->raid_data.pIocPg2 = (IOCPage2_t *) mem;
1da177e4
LT
4742 } else {
4743 goto done_and_free;
4744 }
4745 }
4746 memcpy(mem, (u8 *)pIoc2, iocpage2sz);
4747
4748 /* Identify RAID Volume Id's */
4749 nVols = pIoc2->NumActiveVolumes;
4750 if ( nVols == 0) {
4751 /* No RAID Volume.
4752 */
4753 goto done_and_free;
4754 } else {
4755 /* At least 1 RAID Volume
4756 */
4757 pIocRv = pIoc2->RaidVolume;
466544d8 4758 ioc->raid_data.isRaid = 0;
1da177e4
LT
4759 for (jj = 0; jj < nVols; jj++, pIocRv++) {
4760 vid = pIocRv->VolumeID;
4761 vbus = pIocRv->VolumeBus;
4762 vioc = pIocRv->VolumeIOC;
4763
4764 /* find the match
4765 */
4766 if (vbus == 0) {
466544d8 4767 ioc->raid_data.isRaid |= (1 << vid);
1da177e4
LT
4768 } else {
4769 /* Error! Always bus 0
4770 */
4771 }
4772 }
4773 }
4774
4775 /* Identify Hidden Physical Disk Id's */
4776 nPhys = pIoc2->NumActivePhysDisks;
4777 if (nPhys == 0) {
4778 /* No physical disks.
4779 */
4780 } else {
4781 mpt_read_ioc_pg_3(ioc);
4782 }
4783
4784done_and_free:
4785 pci_free_consistent(ioc->pcidev, iocpage2sz, pIoc2, ioc2_dma);
4786
4787 return rc;
4788}
4789
4790int
4791mpt_read_ioc_pg_3(MPT_ADAPTER *ioc)
4792{
4793 IOCPage3_t *pIoc3;
4794 u8 *mem;
4795 CONFIGPARMS cfg;
4796 ConfigPageHeader_t header;
4797 dma_addr_t ioc3_dma;
4798 int iocpage3sz = 0;
4799
4800 /* Free the old page
4801 */
466544d8
MED
4802 kfree(ioc->raid_data.pIocPg3);
4803 ioc->raid_data.pIocPg3 = NULL;
1da177e4
LT
4804
4805 /* There is at least one physical disk.
4806 * Read and save IOC Page 3
4807 */
4808 header.PageVersion = 0;
4809 header.PageLength = 0;
4810 header.PageNumber = 3;
4811 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
69218ee5 4812 cfg.cfghdr.hdr = &header;
1da177e4
LT
4813 cfg.physAddr = -1;
4814 cfg.pageAddr = 0;
4815 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4816 cfg.dir = 0;
4817 cfg.timeout = 0;
4818 if (mpt_config(ioc, &cfg) != 0)
4819 return 0;
4820
4821 if (header.PageLength == 0)
4822 return 0;
4823
4824 /* Read Header good, alloc memory
4825 */
4826 iocpage3sz = header.PageLength * 4;
4827 pIoc3 = pci_alloc_consistent(ioc->pcidev, iocpage3sz, &ioc3_dma);
4828 if (!pIoc3)
4829 return 0;
4830
4831 /* Read the Page and save the data
4832 * into malloc'd memory.
4833 */
4834 cfg.physAddr = ioc3_dma;
4835 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4836 if (mpt_config(ioc, &cfg) == 0) {
4837 mem = kmalloc(iocpage3sz, GFP_ATOMIC);
4838 if (mem) {
4839 memcpy(mem, (u8 *)pIoc3, iocpage3sz);
466544d8 4840 ioc->raid_data.pIocPg3 = (IOCPage3_t *) mem;
1da177e4
LT
4841 }
4842 }
4843
4844 pci_free_consistent(ioc->pcidev, iocpage3sz, pIoc3, ioc3_dma);
4845
4846 return 0;
4847}
4848
4849static void
4850mpt_read_ioc_pg_4(MPT_ADAPTER *ioc)
4851{
4852 IOCPage4_t *pIoc4;
4853 CONFIGPARMS cfg;
4854 ConfigPageHeader_t header;
4855 dma_addr_t ioc4_dma;
4856 int iocpage4sz;
4857
4858 /* Read and save IOC Page 4
4859 */
4860 header.PageVersion = 0;
4861 header.PageLength = 0;
4862 header.PageNumber = 4;
4863 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
69218ee5 4864 cfg.cfghdr.hdr = &header;
1da177e4
LT
4865 cfg.physAddr = -1;
4866 cfg.pageAddr = 0;
4867 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4868 cfg.dir = 0;
4869 cfg.timeout = 0;
4870 if (mpt_config(ioc, &cfg) != 0)
4871 return;
4872
4873 if (header.PageLength == 0)
4874 return;
4875
4876 if ( (pIoc4 = ioc->spi_data.pIocPg4) == NULL ) {
4877 iocpage4sz = (header.PageLength + 4) * 4; /* Allow 4 additional SEP's */
4878 pIoc4 = pci_alloc_consistent(ioc->pcidev, iocpage4sz, &ioc4_dma);
4879 if (!pIoc4)
4880 return;
4881 } else {
4882 ioc4_dma = ioc->spi_data.IocPg4_dma;
4883 iocpage4sz = ioc->spi_data.IocPg4Sz;
4884 }
4885
4886 /* Read the Page into dma memory.
4887 */
4888 cfg.physAddr = ioc4_dma;
4889 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4890 if (mpt_config(ioc, &cfg) == 0) {
4891 ioc->spi_data.pIocPg4 = (IOCPage4_t *) pIoc4;
4892 ioc->spi_data.IocPg4_dma = ioc4_dma;
4893 ioc->spi_data.IocPg4Sz = iocpage4sz;
4894 } else {
4895 pci_free_consistent(ioc->pcidev, iocpage4sz, pIoc4, ioc4_dma);
4896 ioc->spi_data.pIocPg4 = NULL;
4897 }
4898}
4899
4900static void
4901mpt_read_ioc_pg_1(MPT_ADAPTER *ioc)
4902{
4903 IOCPage1_t *pIoc1;
4904 CONFIGPARMS cfg;
4905 ConfigPageHeader_t header;
4906 dma_addr_t ioc1_dma;
4907 int iocpage1sz = 0;
4908 u32 tmp;
4909
4910 /* Check the Coalescing Timeout in IOC Page 1
4911 */
4912 header.PageVersion = 0;
4913 header.PageLength = 0;
4914 header.PageNumber = 1;
4915 header.PageType = MPI_CONFIG_PAGETYPE_IOC;
69218ee5 4916 cfg.cfghdr.hdr = &header;
1da177e4
LT
4917 cfg.physAddr = -1;
4918 cfg.pageAddr = 0;
4919 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4920 cfg.dir = 0;
4921 cfg.timeout = 0;
4922 if (mpt_config(ioc, &cfg) != 0)
4923 return;
4924
4925 if (header.PageLength == 0)
4926 return;
4927
4928 /* Read Header good, alloc memory
4929 */
4930 iocpage1sz = header.PageLength * 4;
4931 pIoc1 = pci_alloc_consistent(ioc->pcidev, iocpage1sz, &ioc1_dma);
4932 if (!pIoc1)
4933 return;
4934
4935 /* Read the Page and check coalescing timeout
4936 */
4937 cfg.physAddr = ioc1_dma;
4938 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4939 if (mpt_config(ioc, &cfg) == 0) {
4940
4941 tmp = le32_to_cpu(pIoc1->Flags) & MPI_IOCPAGE1_REPLY_COALESCING;
4942 if (tmp == MPI_IOCPAGE1_REPLY_COALESCING) {
4943 tmp = le32_to_cpu(pIoc1->CoalescingTimeout);
4944
4945 dprintk((MYIOC_s_INFO_FMT "Coalescing Enabled Timeout = %d\n",
4946 ioc->name, tmp));
4947
4948 if (tmp > MPT_COALESCING_TIMEOUT) {
4949 pIoc1->CoalescingTimeout = cpu_to_le32(MPT_COALESCING_TIMEOUT);
4950
4951 /* Write NVRAM and current
4952 */
4953 cfg.dir = 1;
4954 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
4955 if (mpt_config(ioc, &cfg) == 0) {
4956 dprintk((MYIOC_s_INFO_FMT "Reset Current Coalescing Timeout to = %d\n",
4957 ioc->name, MPT_COALESCING_TIMEOUT));
4958
4959 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM;
4960 if (mpt_config(ioc, &cfg) == 0) {
4961 dprintk((MYIOC_s_INFO_FMT "Reset NVRAM Coalescing Timeout to = %d\n",
4962 ioc->name, MPT_COALESCING_TIMEOUT));
4963 } else {
4964 dprintk((MYIOC_s_INFO_FMT "Reset NVRAM Coalescing Timeout Failed\n",
4965 ioc->name));
4966 }
4967
4968 } else {
4969 dprintk((MYIOC_s_WARN_FMT "Reset of Current Coalescing Timeout Failed!\n",
4970 ioc->name));
4971 }
4972 }
4973
4974 } else {
4975 dprintk((MYIOC_s_WARN_FMT "Coalescing Disabled\n", ioc->name));
4976 }
4977 }
4978
4979 pci_free_consistent(ioc->pcidev, iocpage1sz, pIoc1, ioc1_dma);
4980
4981 return;
4982}
4983
4984/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4985/*
4986 * SendEventNotification - Send EventNotification (on or off) request
4987 * to MPT adapter.
4988 * @ioc: Pointer to MPT_ADAPTER structure
4989 * @EvSwitch: Event switch flags
4990 */
4991static int
4992SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch)
4993{
4994 EventNotification_t *evnp;
4995
4996 evnp = (EventNotification_t *) mpt_get_msg_frame(mpt_base_index, ioc);
4997 if (evnp == NULL) {
c6678e0c 4998 devtprintk((MYIOC_s_WARN_FMT "Unable to allocate event request frame!\n",
1da177e4
LT
4999 ioc->name));
5000 return 0;
5001 }
5002 memset(evnp, 0, sizeof(*evnp));
5003
c6678e0c 5004 devtprintk((MYIOC_s_INFO_FMT "Sending EventNotification (%d) request %p\n", ioc->name, EvSwitch, evnp));
1da177e4
LT
5005
5006 evnp->Function = MPI_FUNCTION_EVENT_NOTIFICATION;
5007 evnp->ChainOffset = 0;
5008 evnp->MsgFlags = 0;
5009 evnp->Switch = EvSwitch;
5010
5011 mpt_put_msg_frame(mpt_base_index, ioc, (MPT_FRAME_HDR *)evnp);
5012
5013 return 0;
5014}
5015
5016/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5017/**
5018 * SendEventAck - Send EventAck request to MPT adapter.
5019 * @ioc: Pointer to MPT_ADAPTER structure
5020 * @evnp: Pointer to original EventNotification request
5021 */
5022static int
5023SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp)
5024{
5025 EventAck_t *pAck;
5026
5027 if ((pAck = (EventAck_t *) mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
c6678e0c
CH
5028 printk(MYIOC_s_WARN_FMT "Unable to allocate event ACK "
5029 "request frame for Event=%x EventContext=%x EventData=%x!\n",
5030 ioc->name, evnp->Event, le32_to_cpu(evnp->EventContext),
5031 le32_to_cpu(evnp->Data[0]));
1da177e4
LT
5032 return -1;
5033 }
5034 memset(pAck, 0, sizeof(*pAck));
5035
5036 dprintk((MYIOC_s_INFO_FMT "Sending EventAck\n", ioc->name));
5037
5038 pAck->Function = MPI_FUNCTION_EVENT_ACK;
5039 pAck->ChainOffset = 0;
5040 pAck->MsgFlags = 0;
5041 pAck->Event = evnp->Event;
5042 pAck->EventContext = evnp->EventContext;
5043
5044 mpt_put_msg_frame(mpt_base_index, ioc, (MPT_FRAME_HDR *)pAck);
5045
5046 return 0;
5047}
5048
5049/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5050/**
5051 * mpt_config - Generic function to issue config message
5052 * @ioc - Pointer to an adapter structure
5053 * @cfg - Pointer to a configuration structure. Struct contains
5054 * action, page address, direction, physical address
5055 * and pointer to a configuration page header
5056 * Page header is updated.
5057 *
5058 * Returns 0 for success
5059 * -EPERM if not allowed due to ISR context
5060 * -EAGAIN if no msg frames currently available
5061 * -EFAULT for non-successful reply or no reply (timeout)
5062 */
5063int
5064mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
5065{
5066 Config_t *pReq;
69218ee5 5067 ConfigExtendedPageHeader_t *pExtHdr = NULL;
1da177e4
LT
5068 MPT_FRAME_HDR *mf;
5069 unsigned long flags;
5070 int ii, rc;
69218ee5 5071 int flagsLength;
1da177e4
LT
5072 int in_isr;
5073
7fadc87e 5074 /* Prevent calling wait_event() (below), if caller happens
1da177e4
LT
5075 * to be in ISR context, because that is fatal!
5076 */
5077 in_isr = in_interrupt();
5078 if (in_isr) {
5079 dcprintk((MYIOC_s_WARN_FMT "Config request not allowed in ISR context!\n",
5080 ioc->name));
5081 return -EPERM;
5082 }
5083
5084 /* Get and Populate a free Frame
5085 */
5086 if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
5087 dcprintk((MYIOC_s_WARN_FMT "mpt_config: no msg frames!\n",
5088 ioc->name));
5089 return -EAGAIN;
5090 }
5091 pReq = (Config_t *)mf;
5092 pReq->Action = pCfg->action;
5093 pReq->Reserved = 0;
5094 pReq->ChainOffset = 0;
5095 pReq->Function = MPI_FUNCTION_CONFIG;
69218ee5
CH
5096
5097 /* Assume page type is not extended and clear "reserved" fields. */
1da177e4
LT
5098 pReq->ExtPageLength = 0;
5099 pReq->ExtPageType = 0;
5100 pReq->MsgFlags = 0;
69218ee5 5101
1da177e4
LT
5102 for (ii=0; ii < 8; ii++)
5103 pReq->Reserved2[ii] = 0;
5104
69218ee5
CH
5105 pReq->Header.PageVersion = pCfg->cfghdr.hdr->PageVersion;
5106 pReq->Header.PageLength = pCfg->cfghdr.hdr->PageLength;
5107 pReq->Header.PageNumber = pCfg->cfghdr.hdr->PageNumber;
5108 pReq->Header.PageType = (pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK);
5109
5110 if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == MPI_CONFIG_PAGETYPE_EXTENDED) {
5111 pExtHdr = (ConfigExtendedPageHeader_t *)pCfg->cfghdr.ehdr;
5112 pReq->ExtPageLength = cpu_to_le16(pExtHdr->ExtPageLength);
5113 pReq->ExtPageType = pExtHdr->ExtPageType;
5114 pReq->Header.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
5115
5116 /* Page Length must be treated as a reserved field for the extended header. */
5117 pReq->Header.PageLength = 0;
5118 }
5119
1da177e4
LT
5120 pReq->PageAddress = cpu_to_le32(pCfg->pageAddr);
5121
5122 /* Add a SGE to the config request.
5123 */
5124 if (pCfg->dir)
5125 flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE;
5126 else
5127 flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
5128
69218ee5
CH
5129 if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == MPI_CONFIG_PAGETYPE_EXTENDED) {
5130 flagsLength |= pExtHdr->ExtPageLength * 4;
1da177e4 5131
69218ee5
CH
5132 dcprintk((MYIOC_s_INFO_FMT "Sending Config request type %d, page %d and action %d\n",
5133 ioc->name, pReq->ExtPageType, pReq->Header.PageNumber, pReq->Action));
5134 }
5135 else {
5136 flagsLength |= pCfg->cfghdr.hdr->PageLength * 4;
1da177e4 5137
69218ee5
CH
5138 dcprintk((MYIOC_s_INFO_FMT "Sending Config request type %d, page %d and action %d\n",
5139 ioc->name, pReq->Header.PageType, pReq->Header.PageNumber, pReq->Action));
5140 }
5141
5142 mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, pCfg->physAddr);
1da177e4
LT
5143
5144 /* Append pCfg pointer to end of mf
5145 */
5146 *((void **) (((u8 *) mf) + (ioc->req_sz - sizeof(void *)))) = (void *) pCfg;
5147
5148 /* Initalize the timer
5149 */
5150 init_timer(&pCfg->timer);
5151 pCfg->timer.data = (unsigned long) ioc;
5152 pCfg->timer.function = mpt_timer_expired;
5153 pCfg->wait_done = 0;
5154
5155 /* Set the timer; ensure 10 second minimum */
5156 if (pCfg->timeout < 10)
5157 pCfg->timer.expires = jiffies + HZ*10;
5158 else
5159 pCfg->timer.expires = jiffies + HZ*pCfg->timeout;
5160
5161 /* Add to end of Q, set timer and then issue this command */
5162 spin_lock_irqsave(&ioc->FreeQlock, flags);
5163 list_add_tail(&pCfg->linkage, &ioc->configQ);
5164 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5165
5166 add_timer(&pCfg->timer);
5167 mpt_put_msg_frame(mpt_base_index, ioc, mf);
5168 wait_event(mpt_waitq, pCfg->wait_done);
5169
5170 /* mf has been freed - do not access */
5171
5172 rc = pCfg->status;
5173
5174 return rc;
5175}
5176
5177/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5178/**
5179 * mpt_toolbox - Generic function to issue toolbox message
5180 * @ioc - Pointer to an adapter structure
5181 * @cfg - Pointer to a toolbox structure. Struct contains
5182 * action, page address, direction, physical address
5183 * and pointer to a configuration page header
5184 * Page header is updated.
5185 *
5186 * Returns 0 for success
5187 * -EPERM if not allowed due to ISR context
5188 * -EAGAIN if no msg frames currently available
5189 * -EFAULT for non-successful reply or no reply (timeout)
5190 */
5191int
5192mpt_toolbox(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
5193{
5194 ToolboxIstwiReadWriteRequest_t *pReq;
5195 MPT_FRAME_HDR *mf;
5196 struct pci_dev *pdev;
5197 unsigned long flags;
5198 int rc;
5199 u32 flagsLength;
5200 int in_isr;
5201
7fadc87e 5202 /* Prevent calling wait_event() (below), if caller happens
1da177e4
LT
5203 * to be in ISR context, because that is fatal!
5204 */
5205 in_isr = in_interrupt();
5206 if (in_isr) {
5207 dcprintk((MYIOC_s_WARN_FMT "toobox request not allowed in ISR context!\n",
5208 ioc->name));
5209 return -EPERM;
5210 }
5211
5212 /* Get and Populate a free Frame
5213 */
5214 if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
5215 dcprintk((MYIOC_s_WARN_FMT "mpt_toolbox: no msg frames!\n",
5216 ioc->name));
5217 return -EAGAIN;
5218 }
5219 pReq = (ToolboxIstwiReadWriteRequest_t *)mf;
5220 pReq->Tool = pCfg->action;
5221 pReq->Reserved = 0;
5222 pReq->ChainOffset = 0;
5223 pReq->Function = MPI_FUNCTION_TOOLBOX;
5224 pReq->Reserved1 = 0;
5225 pReq->Reserved2 = 0;
5226 pReq->MsgFlags = 0;
5227 pReq->Flags = pCfg->dir;
5228 pReq->BusNum = 0;
5229 pReq->Reserved3 = 0;
5230 pReq->NumAddressBytes = 0x01;
5231 pReq->Reserved4 = 0;
637fa99b
CH
5232 pReq->DataLength = cpu_to_le16(0x04);
5233 pdev = ioc->pcidev;
1da177e4
LT
5234 if (pdev->devfn & 1)
5235 pReq->DeviceAddr = 0xB2;
5236 else
5237 pReq->DeviceAddr = 0xB0;
5238 pReq->Addr1 = 0;
5239 pReq->Addr2 = 0;
5240 pReq->Addr3 = 0;
5241 pReq->Reserved5 = 0;
5242
5243 /* Add a SGE to the config request.
5244 */
5245
5246 flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ | 4;
5247
5248 mpt_add_sge((char *)&pReq->SGL, flagsLength, pCfg->physAddr);
5249
5250 dcprintk((MYIOC_s_INFO_FMT "Sending Toolbox request, Tool=%x\n",
5251 ioc->name, pReq->Tool));
5252
5253 /* Append pCfg pointer to end of mf
5254 */
5255 *((void **) (((u8 *) mf) + (ioc->req_sz - sizeof(void *)))) = (void *) pCfg;
5256
5257 /* Initalize the timer
5258 */
5259 init_timer(&pCfg->timer);
5260 pCfg->timer.data = (unsigned long) ioc;
5261 pCfg->timer.function = mpt_timer_expired;
5262 pCfg->wait_done = 0;
5263
5264 /* Set the timer; ensure 10 second minimum */
5265 if (pCfg->timeout < 10)
5266 pCfg->timer.expires = jiffies + HZ*10;
5267 else
5268 pCfg->timer.expires = jiffies + HZ*pCfg->timeout;
5269
5270 /* Add to end of Q, set timer and then issue this command */
5271 spin_lock_irqsave(&ioc->FreeQlock, flags);
5272 list_add_tail(&pCfg->linkage, &ioc->configQ);
5273 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5274
5275 add_timer(&pCfg->timer);
5276 mpt_put_msg_frame(mpt_base_index, ioc, mf);
5277 wait_event(mpt_waitq, pCfg->wait_done);
5278
5279 /* mf has been freed - do not access */
5280
5281 rc = pCfg->status;
5282
5283 return rc;
5284}
5285
5286/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5287/*
5288 * mpt_timer_expired - Call back for timer process.
5289 * Used only internal config functionality.
5290 * @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
5291 */
5292static void
5293mpt_timer_expired(unsigned long data)
5294{
5295 MPT_ADAPTER *ioc = (MPT_ADAPTER *) data;
5296
5297 dcprintk((MYIOC_s_WARN_FMT "mpt_timer_expired! \n", ioc->name));
5298
5299 /* Perform a FW reload */
5300 if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0)
5301 printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", ioc->name);
5302
5303 /* No more processing.
5304 * Hard reset clean-up will wake up
5305 * process and free all resources.
5306 */
5307 dcprintk((MYIOC_s_WARN_FMT "mpt_timer_expired complete!\n", ioc->name));
5308
5309 return;
5310}
5311
5312/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5313/*
5314 * mpt_ioc_reset - Base cleanup for hard reset
5315 * @ioc: Pointer to the adapter structure
5316 * @reset_phase: Indicates pre- or post-reset functionality
5317 *
5318 * Remark: Free's resources with internally generated commands.
5319 */
5320static int
5321mpt_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
5322{
5323 CONFIGPARMS *pCfg;
5324 unsigned long flags;
5325
5326 dprintk((KERN_WARNING MYNAM
5327 ": IOC %s_reset routed to MPT base driver!\n",
5328 reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
5329 reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
5330
5331 if (reset_phase == MPT_IOC_SETUP_RESET) {
5332 ;
5333 } else if (reset_phase == MPT_IOC_PRE_RESET) {
5334 /* If the internal config Q is not empty -
5335 * delete timer. MF resources will be freed when
5336 * the FIFO's are primed.
5337 */
5338 spin_lock_irqsave(&ioc->FreeQlock, flags);
5339 list_for_each_entry(pCfg, &ioc->configQ, linkage)
5340 del_timer(&pCfg->timer);
5341 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5342
5343 } else {
5344 CONFIGPARMS *pNext;
5345
5346 /* Search the configQ for internal commands.
5347 * Flush the Q, and wake up all suspended threads.
5348 */
5349 spin_lock_irqsave(&ioc->FreeQlock, flags);
5350 list_for_each_entry_safe(pCfg, pNext, &ioc->configQ, linkage) {
5351 list_del(&pCfg->linkage);
5352
5353 pCfg->status = MPT_CONFIG_ERROR;
5354 pCfg->wait_done = 1;
5355 wake_up(&mpt_waitq);
5356 }
5357 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5358 }
5359
5360 return 1; /* currently means nothing really */
5361}
5362
5363
5364#ifdef CONFIG_PROC_FS /* { */
5365/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5366/*
5367 * procfs (%MPT_PROCFS_MPTBASEDIR/...) support stuff...
5368 */
5369/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5370/*
5371 * procmpt_create - Create %MPT_PROCFS_MPTBASEDIR entries.
5372 *
5373 * Returns 0 for success, non-zero for failure.
5374 */
5375static int
5376procmpt_create(void)
5377{
5378 struct proc_dir_entry *ent;
5379
5380 mpt_proc_root_dir = proc_mkdir(MPT_PROCFS_MPTBASEDIR, NULL);
5381 if (mpt_proc_root_dir == NULL)
5382 return -ENOTDIR;
5383
5384 ent = create_proc_entry("summary", S_IFREG|S_IRUGO, mpt_proc_root_dir);
5385 if (ent)
5386 ent->read_proc = procmpt_summary_read;
5387
5388 ent = create_proc_entry("version", S_IFREG|S_IRUGO, mpt_proc_root_dir);
5389 if (ent)
5390 ent->read_proc = procmpt_version_read;
5391
5392 return 0;
5393}
5394
5395/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5396/*
5397 * procmpt_destroy - Tear down %MPT_PROCFS_MPTBASEDIR entries.
5398 *
5399 * Returns 0 for success, non-zero for failure.
5400 */
5401static void
5402procmpt_destroy(void)
5403{
5404 remove_proc_entry("version", mpt_proc_root_dir);
5405 remove_proc_entry("summary", mpt_proc_root_dir);
5406 remove_proc_entry(MPT_PROCFS_MPTBASEDIR, NULL);
5407}
5408
5409/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5410/*
5411 * procmpt_summary_read - Handle read request from /proc/mpt/summary
5412 * or from /proc/mpt/iocN/summary.
5413 * @buf: Pointer to area to write information
5414 * @start: Pointer to start pointer
5415 * @offset: Offset to start writing
5416 * @request:
5417 * @eof: Pointer to EOF integer
5418 * @data: Pointer
5419 *
5420 * Returns number of characters written to process performing the read.
5421 */
5422static int
5423procmpt_summary_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
5424{
5425 MPT_ADAPTER *ioc;
5426 char *out = buf;
5427 int len;
5428
5429 if (data) {
5430 int more = 0;
5431
5432 ioc = data;
5433 mpt_print_ioc_summary(ioc, out, &more, 0, 1);
5434
5435 out += more;
5436 } else {
5437 list_for_each_entry(ioc, &ioc_list, list) {
5438 int more = 0;
5439
5440 mpt_print_ioc_summary(ioc, out, &more, 0, 1);
5441
5442 out += more;
5443 if ((out-buf) >= request)
5444 break;
5445 }
5446 }
5447
5448 len = out - buf;
5449
5450 MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
5451}
5452
5453/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5454/*
5455 * procmpt_version_read - Handle read request from /proc/mpt/version.
5456 * @buf: Pointer to area to write information
5457 * @start: Pointer to start pointer
5458 * @offset: Offset to start writing
5459 * @request:
5460 * @eof: Pointer to EOF integer
5461 * @data: Pointer
5462 *
5463 * Returns number of characters written to process performing the read.
5464 */
5465static int
5466procmpt_version_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
5467{
5468 int ii;
7fadc87e 5469 int scsi, fc, sas, lan, ctl, targ, dmp;
1da177e4
LT
5470 char *drvname;
5471 int len;
5472
5473 len = sprintf(buf, "%s-%s\n", "mptlinux", MPT_LINUX_VERSION_COMMON);
5474 len += sprintf(buf+len, " Fusion MPT base driver\n");
5475
7fadc87e 5476 scsi = fc = sas = lan = ctl = targ = dmp = 0;
1da177e4
LT
5477 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
5478 drvname = NULL;
5479 if (MptCallbacks[ii]) {
5480 switch (MptDriverClass[ii]) {
7fadc87e
MED
5481 case MPTSPI_DRIVER:
5482 if (!scsi++) drvname = "SPI host";
5483 break;
5484 case MPTFC_DRIVER:
5485 if (!fc++) drvname = "FC host";
5486 break;
5487 case MPTSAS_DRIVER:
5488 if (!sas++) drvname = "SAS host";
1da177e4
LT
5489 break;
5490 case MPTLAN_DRIVER:
5491 if (!lan++) drvname = "LAN";
5492 break;
5493 case MPTSTM_DRIVER:
5494 if (!targ++) drvname = "SCSI target";
5495 break;
5496 case MPTCTL_DRIVER:
5497 if (!ctl++) drvname = "ioctl";
5498 break;
5499 }
5500
5501 if (drvname)
5502 len += sprintf(buf+len, " Fusion MPT %s driver\n", drvname);
5503 }
5504 }
5505
5506 MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
5507}
5508
5509/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5510/*
5511 * procmpt_iocinfo_read - Handle read request from /proc/mpt/iocN/info.
5512 * @buf: Pointer to area to write information
5513 * @start: Pointer to start pointer
5514 * @offset: Offset to start writing
5515 * @request:
5516 * @eof: Pointer to EOF integer
5517 * @data: Pointer
5518 *
5519 * Returns number of characters written to process performing the read.
5520 */
5521static int
5522procmpt_iocinfo_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
5523{
5524 MPT_ADAPTER *ioc = data;
5525 int len;
5526 char expVer[32];
5527 int sz;
5528 int p;
5529
5530 mpt_get_fw_exp_ver(expVer, ioc);
5531
5532 len = sprintf(buf, "%s:", ioc->name);
5533 if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)
5534 len += sprintf(buf+len, " (f/w download boot flag set)");
5535// if (ioc->facts.IOCExceptions & MPI_IOCFACTS_EXCEPT_CONFIG_CHECKSUM_FAIL)
5536// len += sprintf(buf+len, " CONFIG_CHECKSUM_FAIL!");
5537
5538 len += sprintf(buf+len, "\n ProductID = 0x%04x (%s)\n",
5539 ioc->facts.ProductID,
5540 ioc->prod_name);
5541 len += sprintf(buf+len, " FWVersion = 0x%08x%s", ioc->facts.FWVersion.Word, expVer);
5542 if (ioc->facts.FWImageSize)
5543 len += sprintf(buf+len, " (fw_size=%d)", ioc->facts.FWImageSize);
5544 len += sprintf(buf+len, "\n MsgVersion = 0x%04x\n", ioc->facts.MsgVersion);
5545 len += sprintf(buf+len, " FirstWhoInit = 0x%02x\n", ioc->FirstWhoInit);
5546 len += sprintf(buf+len, " EventState = 0x%02x\n", ioc->facts.EventState);
5547
5548 len += sprintf(buf+len, " CurrentHostMfaHighAddr = 0x%08x\n",
5549 ioc->facts.CurrentHostMfaHighAddr);
5550 len += sprintf(buf+len, " CurrentSenseBufferHighAddr = 0x%08x\n",
5551 ioc->facts.CurrentSenseBufferHighAddr);
5552
5553 len += sprintf(buf+len, " MaxChainDepth = 0x%02x frames\n", ioc->facts.MaxChainDepth);
5554 len += sprintf(buf+len, " MinBlockSize = 0x%02x bytes\n", 4*ioc->facts.BlockSize);
5555
5556 len += sprintf(buf+len, " RequestFrames @ 0x%p (Dma @ 0x%p)\n",
5557 (void *)ioc->req_frames, (void *)(ulong)ioc->req_frames_dma);
5558 /*
5559 * Rounding UP to nearest 4-kB boundary here...
5560 */
5561 sz = (ioc->req_sz * ioc->req_depth) + 128;
5562 sz = ((sz + 0x1000UL - 1UL) / 0x1000) * 0x1000;
5563 len += sprintf(buf+len, " {CurReqSz=%d} x {CurReqDepth=%d} = %d bytes ^= 0x%x\n",
5564 ioc->req_sz, ioc->req_depth, ioc->req_sz*ioc->req_depth, sz);
5565 len += sprintf(buf+len, " {MaxReqSz=%d} {MaxReqDepth=%d}\n",
5566 4*ioc->facts.RequestFrameSize,
5567 ioc->facts.GlobalCredits);
5568
5569 len += sprintf(buf+len, " Frames @ 0x%p (Dma @ 0x%p)\n",
5570 (void *)ioc->alloc, (void *)(ulong)ioc->alloc_dma);
5571 sz = (ioc->reply_sz * ioc->reply_depth) + 128;
5572 len += sprintf(buf+len, " {CurRepSz=%d} x {CurRepDepth=%d} = %d bytes ^= 0x%x\n",
5573 ioc->reply_sz, ioc->reply_depth, ioc->reply_sz*ioc->reply_depth, sz);
5574 len += sprintf(buf+len, " {MaxRepSz=%d} {MaxRepDepth=%d}\n",
5575 ioc->facts.CurReplyFrameSize,
5576 ioc->facts.ReplyQueueDepth);
5577
5578 len += sprintf(buf+len, " MaxDevices = %d\n",
5579 (ioc->facts.MaxDevices==0) ? 255 : ioc->facts.MaxDevices);
5580 len += sprintf(buf+len, " MaxBuses = %d\n", ioc->facts.MaxBuses);
5581
5582 /* per-port info */
5583 for (p=0; p < ioc->facts.NumberOfPorts; p++) {
5584 len += sprintf(buf+len, " PortNumber = %d (of %d)\n",
5585 p+1,
5586 ioc->facts.NumberOfPorts);
5587 if (ioc->bus_type == FC) {
5588 if (ioc->pfacts[p].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
5589 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
5590 len += sprintf(buf+len, " LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
5591 a[5], a[4], a[3], a[2], a[1], a[0]);
5592 }
5593 len += sprintf(buf+len, " WWN = %08X%08X:%08X%08X\n",
5594 ioc->fc_port_page0[p].WWNN.High,
5595 ioc->fc_port_page0[p].WWNN.Low,
5596 ioc->fc_port_page0[p].WWPN.High,
5597 ioc->fc_port_page0[p].WWPN.Low);
5598 }
5599 }
5600
5601 MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
5602}
5603
5604#endif /* CONFIG_PROC_FS } */
5605
5606/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5607static void
5608mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc)
5609{
5610 buf[0] ='\0';
5611 if ((ioc->facts.FWVersion.Word >> 24) == 0x0E) {
5612 sprintf(buf, " (Exp %02d%02d)",
5613 (ioc->facts.FWVersion.Word >> 16) & 0x00FF, /* Month */
5614 (ioc->facts.FWVersion.Word >> 8) & 0x1F); /* Day */
5615
5616 /* insider hack! */
5617 if ((ioc->facts.FWVersion.Word >> 8) & 0x80)
5618 strcat(buf, " [MDBG]");
5619 }
5620}
5621
5622/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5623/**
5624 * mpt_print_ioc_summary - Write ASCII summary of IOC to a buffer.
5625 * @ioc: Pointer to MPT_ADAPTER structure
5626 * @buffer: Pointer to buffer where IOC summary info should be written
5627 * @size: Pointer to number of bytes we wrote (set by this routine)
5628 * @len: Offset at which to start writing in buffer
5629 * @showlan: Display LAN stuff?
5630 *
5631 * This routine writes (english readable) ASCII text, which represents
5632 * a summary of IOC information, to a buffer.
5633 */
5634void
5635mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buffer, int *size, int len, int showlan)
5636{
5637 char expVer[32];
5638 int y;
5639
5640 mpt_get_fw_exp_ver(expVer, ioc);
5641
5642 /*
5643 * Shorter summary of attached ioc's...
5644 */
5645 y = sprintf(buffer+len, "%s: %s, %s%08xh%s, Ports=%d, MaxQ=%d",
5646 ioc->name,
5647 ioc->prod_name,
5648 MPT_FW_REV_MAGIC_ID_STRING, /* "FwRev=" or somesuch */
5649 ioc->facts.FWVersion.Word,
5650 expVer,
5651 ioc->facts.NumberOfPorts,
5652 ioc->req_depth);
5653
5654 if (showlan && (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN)) {
5655 u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
5656 y += sprintf(buffer+len+y, ", LanAddr=%02X:%02X:%02X:%02X:%02X:%02X",
5657 a[5], a[4], a[3], a[2], a[1], a[0]);
5658 }
5659
5660#ifndef __sparc__
5661 y += sprintf(buffer+len+y, ", IRQ=%d", ioc->pci_irq);
5662#else
5663 y += sprintf(buffer+len+y, ", IRQ=%s", __irq_itoa(ioc->pci_irq));
5664#endif
5665
5666 if (!ioc->active)
5667 y += sprintf(buffer+len+y, " (disabled)");
5668
5669 y += sprintf(buffer+len+y, "\n");
5670
5671 *size = y;
5672}
5673
5674/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5675/*
5676 * Reset Handling
5677 */
5678/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5679/**
5680 * mpt_HardResetHandler - Generic reset handler, issue SCSI Task
5681 * Management call based on input arg values. If TaskMgmt fails,
5682 * return associated SCSI request.
5683 * @ioc: Pointer to MPT_ADAPTER structure
5684 * @sleepFlag: Indicates if sleep or schedule must be called.
5685 *
5686 * Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
5687 * or a non-interrupt thread. In the former, must not call schedule().
5688 *
5689 * Remark: A return of -1 is a FATAL error case, as it means a
5690 * FW reload/initialization failed.
5691 *
5692 * Returns 0 for SUCCESS or -1 if FAILED.
5693 */
5694int
5695mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
5696{
5697 int rc;
5698 unsigned long flags;
5699
5700 dtmprintk((MYIOC_s_INFO_FMT "HardResetHandler Entered!\n", ioc->name));
5701#ifdef MFCNT
5702 printk(MYIOC_s_INFO_FMT "HardResetHandler Entered!\n", ioc->name);
5703 printk("MF count 0x%x !\n", ioc->mfcnt);
5704#endif
5705
5706 /* Reset the adapter. Prevent more than 1 call to
5707 * mpt_do_ioc_recovery at any instant in time.
5708 */
5709 spin_lock_irqsave(&ioc->diagLock, flags);
5710 if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)){
5711 spin_unlock_irqrestore(&ioc->diagLock, flags);
5712 return 0;
5713 } else {
5714 ioc->diagPending = 1;
5715 }
5716 spin_unlock_irqrestore(&ioc->diagLock, flags);
5717
5718 /* FIXME: If do_ioc_recovery fails, repeat....
5719 */
5720
5721 /* The SCSI driver needs to adjust timeouts on all current
5722 * commands prior to the diagnostic reset being issued.
5723 * Prevents timeouts occuring during a diagnostic reset...very bad.
5724 * For all other protocol drivers, this is a no-op.
5725 */
5726 {
5727 int ii;
5728 int r = 0;
5729
5730 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
5731 if (MptResetHandlers[ii]) {
5732 dtmprintk((MYIOC_s_INFO_FMT "Calling IOC reset_setup handler #%d\n",
5733 ioc->name, ii));
5734 r += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_SETUP_RESET);
5735 if (ioc->alt_ioc) {
5736 dtmprintk((MYIOC_s_INFO_FMT "Calling alt-%s setup reset handler #%d\n",
5737 ioc->name, ioc->alt_ioc->name, ii));
5738 r += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_SETUP_RESET);
5739 }
5740 }
5741 }
5742 }
5743
5744 if ((rc = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_RECOVER, sleepFlag)) != 0) {
5745 printk(KERN_WARNING MYNAM ": WARNING - (%d) Cannot recover %s\n",
5746 rc, ioc->name);
5747 }
5748 ioc->reload_fw = 0;
5749 if (ioc->alt_ioc)
5750 ioc->alt_ioc->reload_fw = 0;
5751
5752 spin_lock_irqsave(&ioc->diagLock, flags);
5753 ioc->diagPending = 0;
5754 if (ioc->alt_ioc)
5755 ioc->alt_ioc->diagPending = 0;
5756 spin_unlock_irqrestore(&ioc->diagLock, flags);
5757
5758 dtmprintk((MYIOC_s_INFO_FMT "HardResetHandler rc = %d!\n", ioc->name, rc));
5759
5760 return rc;
5761}
5762
5763/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
82ffb671
CH
5764static void
5765EventDescriptionStr(u8 event, u32 evData0, char *evStr)
1da177e4
LT
5766{
5767 char *ds;
5768
5769 switch(event) {
5770 case MPI_EVENT_NONE:
5771 ds = "None";
5772 break;
5773 case MPI_EVENT_LOG_DATA:
5774 ds = "Log Data";
5775 break;
5776 case MPI_EVENT_STATE_CHANGE:
5777 ds = "State Change";
5778 break;
5779 case MPI_EVENT_UNIT_ATTENTION:
5780 ds = "Unit Attention";
5781 break;
5782 case MPI_EVENT_IOC_BUS_RESET:
5783 ds = "IOC Bus Reset";
5784 break;
5785 case MPI_EVENT_EXT_BUS_RESET:
5786 ds = "External Bus Reset";
5787 break;
5788 case MPI_EVENT_RESCAN:
5789 ds = "Bus Rescan Event";
5790 /* Ok, do we need to do anything here? As far as
5791 I can tell, this is when a new device gets added
5792 to the loop. */
5793 break;
5794 case MPI_EVENT_LINK_STATUS_CHANGE:
5795 if (evData0 == MPI_EVENT_LINK_STATUS_FAILURE)
5796 ds = "Link Status(FAILURE) Change";
5797 else
5798 ds = "Link Status(ACTIVE) Change";
5799 break;
5800 case MPI_EVENT_LOOP_STATE_CHANGE:
5801 if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LIP)
5802 ds = "Loop State(LIP) Change";
5803 else if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LPE)
5804 ds = "Loop State(LPE) Change"; /* ??? */
5805 else
5806 ds = "Loop State(LPB) Change"; /* ??? */
5807 break;
5808 case MPI_EVENT_LOGOUT:
5809 ds = "Logout";
5810 break;
5811 case MPI_EVENT_EVENT_CHANGE:
5812 if (evData0)
5813 ds = "Events(ON) Change";
5814 else
5815 ds = "Events(OFF) Change";
5816 break;
5817 case MPI_EVENT_INTEGRATED_RAID:
82ffb671
CH
5818 {
5819 u8 ReasonCode = (u8)(evData0 >> 16);
5820 switch (ReasonCode) {
5821 case MPI_EVENT_RAID_RC_VOLUME_CREATED :
5822 ds = "Integrated Raid: Volume Created";
5823 break;
5824 case MPI_EVENT_RAID_RC_VOLUME_DELETED :
5825 ds = "Integrated Raid: Volume Deleted";
5826 break;
5827 case MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED :
5828 ds = "Integrated Raid: Volume Settings Changed";
5829 break;
5830 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED :
5831 ds = "Integrated Raid: Volume Status Changed";
5832 break;
5833 case MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED :
5834 ds = "Integrated Raid: Volume Physdisk Changed";
5835 break;
5836 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED :
5837 ds = "Integrated Raid: Physdisk Created";
5838 break;
5839 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED :
5840 ds = "Integrated Raid: Physdisk Deleted";
5841 break;
5842 case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED :
5843 ds = "Integrated Raid: Physdisk Settings Changed";
5844 break;
5845 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED :
5846 ds = "Integrated Raid: Physdisk Status Changed";
5847 break;
5848 case MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED :
5849 ds = "Integrated Raid: Domain Validation Needed";
5850 break;
5851 case MPI_EVENT_RAID_RC_SMART_DATA :
5852 ds = "Integrated Raid; Smart Data";
5853 break;
5854 case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED :
5855 ds = "Integrated Raid: Replace Action Started";
5856 break;
5857 default:
5858 ds = "Integrated Raid";
1da177e4 5859 break;
82ffb671
CH
5860 }
5861 break;
5862 }
5863 case MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE:
5864 ds = "SCSI Device Status Change";
5865 break;
5866 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
5867 {
5868 u8 ReasonCode = (u8)(evData0 >> 16);
5869 switch (ReasonCode) {
5870 case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
5871 ds = "SAS Device Status Change: Added";
5872 break;
5873 case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
5874 ds = "SAS Device Status Change: Deleted";
5875 break;
5876 case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
5877 ds = "SAS Device Status Change: SMART Data";
5878 break;
5879 case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
5880 ds = "SAS Device Status Change: No Persistancy Added";
5881 break;
5882 default:
5883 ds = "SAS Device Status Change: Unknown";
5884 break;
5885 }
5886 break;
5887 }
5888 case MPI_EVENT_ON_BUS_TIMER_EXPIRED:
5889 ds = "Bus Timer Expired";
5890 break;
5891 case MPI_EVENT_QUEUE_FULL:
5892 ds = "Queue Full";
5893 break;
5894 case MPI_EVENT_SAS_SES:
5895 ds = "SAS SES Event";
5896 break;
5897 case MPI_EVENT_PERSISTENT_TABLE_FULL:
5898 ds = "Persistent Table Full";
5899 break;
5900 case MPI_EVENT_SAS_PHY_LINK_STATUS:
5901 ds = "SAS PHY Link Status";
5902 break;
5903 case MPI_EVENT_SAS_DISCOVERY_ERROR:
5904 ds = "SAS Discovery Error";
5905 break;
5906
1da177e4
LT
5907 /*
5908 * MPT base "custom" events may be added here...
5909 */
5910 default:
5911 ds = "Unknown";
5912 break;
5913 }
82ffb671 5914 strcpy(evStr,ds);
1da177e4
LT
5915}
5916
5917/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5918/*
5919 * ProcessEventNotification - Route a received EventNotificationReply to
5920 * all currently regeistered event handlers.
5921 * @ioc: Pointer to MPT_ADAPTER structure
5922 * @pEventReply: Pointer to EventNotification reply frame
5923 * @evHandlers: Pointer to integer, number of event handlers
5924 *
5925 * Returns sum of event handlers return values.
5926 */
5927static int
5928ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply, int *evHandlers)
5929{
5930 u16 evDataLen;
5931 u32 evData0 = 0;
5932// u32 evCtx;
5933 int ii;
5934 int r = 0;
5935 int handlers = 0;
82ffb671 5936 char evStr[100];
1da177e4
LT
5937 u8 event;
5938
5939 /*
5940 * Do platform normalization of values
5941 */
5942 event = le32_to_cpu(pEventReply->Event) & 0xFF;
5943// evCtx = le32_to_cpu(pEventReply->EventContext);
5944 evDataLen = le16_to_cpu(pEventReply->EventDataLength);
5945 if (evDataLen) {
5946 evData0 = le32_to_cpu(pEventReply->Data[0]);
5947 }
5948
82ffb671 5949 EventDescriptionStr(event, evData0, evStr);
1da177e4
LT
5950 devtprintk((MYIOC_s_INFO_FMT "MPT event (%s=%02Xh) detected!\n",
5951 ioc->name,
5952 evStr,
5953 event));
5954
5955#if defined(MPT_DEBUG) || defined(MPT_DEBUG_EVENTS)
5956 printk(KERN_INFO MYNAM ": Event data:\n" KERN_INFO);
5957 for (ii = 0; ii < evDataLen; ii++)
5958 printk(" %08x", le32_to_cpu(pEventReply->Data[ii]));
5959 printk("\n");
5960#endif
5961
5962 /*
5963 * Do general / base driver event processing
5964 */
5965 switch(event) {
1da177e4
LT
5966 case MPI_EVENT_EVENT_CHANGE: /* 0A */
5967 if (evDataLen) {
5968 u8 evState = evData0 & 0xFF;
5969
5970 /* CHECKME! What if evState unexpectedly says OFF (0)? */
5971
5972 /* Update EventState field in cached IocFacts */
5973 if (ioc->facts.Function) {
5974 ioc->facts.EventState = evState;
5975 }
5976 }
5977 break;
82ffb671
CH
5978 default:
5979 break;
1da177e4
LT
5980 }
5981
5982 /*
5983 * Should this event be logged? Events are written sequentially.
5984 * When buffer is full, start again at the top.
5985 */
5986 if (ioc->events && (ioc->eventTypes & ( 1 << event))) {
5987 int idx;
5988
5989 idx = ioc->eventContext % ioc->eventLogSize;
5990
5991 ioc->events[idx].event = event;
5992 ioc->events[idx].eventContext = ioc->eventContext;
5993
5994 for (ii = 0; ii < 2; ii++) {
5995 if (ii < evDataLen)
5996 ioc->events[idx].data[ii] = le32_to_cpu(pEventReply->Data[ii]);
5997 else
5998 ioc->events[idx].data[ii] = 0;
5999 }
6000
6001 ioc->eventContext++;
6002 }
6003
6004
6005 /*
6006 * Call each currently registered protocol event handler.
6007 */
6008 for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
6009 if (MptEvHandlers[ii]) {
6010 devtprintk((MYIOC_s_INFO_FMT "Routing Event to event handler #%d\n",
6011 ioc->name, ii));
6012 r += (*(MptEvHandlers[ii]))(ioc, pEventReply);
6013 handlers++;
6014 }
6015 }
6016 /* FIXME? Examine results here? */
6017
6018 /*
6019 * If needed, send (a single) EventAck.
6020 */
6021 if (pEventReply->AckRequired == MPI_EVENT_NOTIFICATION_ACK_REQUIRED) {
c6678e0c
CH
6022 devtprintk((MYIOC_s_WARN_FMT
6023 "EventAck required\n",ioc->name));
1da177e4
LT
6024 if ((ii = SendEventAck(ioc, pEventReply)) != 0) {
6025 devtprintk((MYIOC_s_WARN_FMT "SendEventAck returned %d\n",
6026 ioc->name, ii));
6027 }
6028 }
6029
6030 *evHandlers = handlers;
6031 return r;
6032}
6033
6034/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6035/*
6036 * mpt_fc_log_info - Log information returned from Fibre Channel IOC.
6037 * @ioc: Pointer to MPT_ADAPTER structure
6038 * @log_info: U32 LogInfo reply word from the IOC
6039 *
6040 * Refer to lsi/fc_log.h.
6041 */
6042static void
6043mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info)
6044{
6045 static char *subcl_str[8] = {
6046 "FCP Initiator", "FCP Target", "LAN", "MPI Message Layer",
6047 "FC Link", "Context Manager", "Invalid Field Offset", "State Change Info"
6048 };
6049 u8 subcl = (log_info >> 24) & 0x7;
6050
6051 printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): SubCl={%s}\n",
6052 ioc->name, log_info, subcl_str[subcl]);
6053}
6054
6055/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6056/*
6057 * mpt_sp_log_info - Log information returned from SCSI Parallel IOC.
6058 * @ioc: Pointer to MPT_ADAPTER structure
6059 * @mr: Pointer to MPT reply frame
6060 * @log_info: U32 LogInfo word from the IOC
6061 *
6062 * Refer to lsi/sp_log.h.
6063 */
6064static void
6065mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info)
6066{
6067 u32 info = log_info & 0x00FF0000;
6068 char *desc = "unknown";
6069
6070 switch (info) {
6071 case 0x00010000:
6072 desc = "bug! MID not found";
6073 if (ioc->reload_fw == 0)
6074 ioc->reload_fw++;
6075 break;
6076
6077 case 0x00020000:
6078 desc = "Parity Error";
6079 break;
6080
6081 case 0x00030000:
6082 desc = "ASYNC Outbound Overrun";
6083 break;
6084
6085 case 0x00040000:
6086 desc = "SYNC Offset Error";
6087 break;
6088
6089 case 0x00050000:
6090 desc = "BM Change";
6091 break;
6092
6093 case 0x00060000:
6094 desc = "Msg In Overflow";
6095 break;
6096
6097 case 0x00070000:
6098 desc = "DMA Error";
6099 break;
6100
6101 case 0x00080000:
6102 desc = "Outbound DMA Overrun";
6103 break;
c6678e0c 6104
1da177e4
LT
6105 case 0x00090000:
6106 desc = "Task Management";
6107 break;
6108
6109 case 0x000A0000:
6110 desc = "Device Problem";
6111 break;
6112
6113 case 0x000B0000:
6114 desc = "Invalid Phase Change";
6115 break;
6116
6117 case 0x000C0000:
6118 desc = "Untagged Table Size";
6119 break;
c6678e0c 6120
1da177e4
LT
6121 }
6122
6123 printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): F/W: %s\n", ioc->name, log_info, desc);
6124}
6125
466544d8
MED
6126/* strings for sas loginfo */
6127 static char *originator_str[] = {
6128 "IOP", /* 00h */
6129 "PL", /* 01h */
6130 "IR" /* 02h */
6131 };
6132 static char *iop_code_str[] = {
6133 NULL, /* 00h */
6134 "Invalid SAS Address", /* 01h */
6135 NULL, /* 02h */
6136 "Invalid Page", /* 03h */
6137 NULL, /* 04h */
6138 "Task Terminated" /* 05h */
6139 };
6140 static char *pl_code_str[] = {
6141 NULL, /* 00h */
6142 "Open Failure", /* 01h */
6143 "Invalid Scatter Gather List", /* 02h */
6144 "Wrong Relative Offset or Frame Length", /* 03h */
6145 "Frame Transfer Error", /* 04h */
6146 "Transmit Frame Connected Low", /* 05h */
6147 "SATA Non-NCQ RW Error Bit Set", /* 06h */
6148 "SATA Read Log Receive Data Error", /* 07h */
6149 "SATA NCQ Fail All Commands After Error", /* 08h */
6150 "SATA Error in Receive Set Device Bit FIS", /* 09h */
6151 "Receive Frame Invalid Message", /* 0Ah */
6152 "Receive Context Message Valid Error", /* 0Bh */
6153 "Receive Frame Current Frame Error", /* 0Ch */
6154 "SATA Link Down", /* 0Dh */
6155 "Discovery SATA Init W IOS", /* 0Eh */
6156 "Config Invalid Page", /* 0Fh */
6157 "Discovery SATA Init Timeout", /* 10h */
6158 "Reset", /* 11h */
6159 "Abort", /* 12h */
6160 "IO Not Yet Executed", /* 13h */
6161 "IO Executed", /* 14h */
6162 NULL, /* 15h */
6163 NULL, /* 16h */
6164 NULL, /* 17h */
6165 NULL, /* 18h */
6166 NULL, /* 19h */
6167 NULL, /* 1Ah */
6168 NULL, /* 1Bh */
6169 NULL, /* 1Ch */
6170 NULL, /* 1Dh */
6171 NULL, /* 1Eh */
6172 NULL, /* 1Fh */
6173 "Enclosure Management" /* 20h */
6174 };
6175
6176/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6177/*
6178 * mpt_sas_log_info - Log information returned from SAS IOC.
6179 * @ioc: Pointer to MPT_ADAPTER structure
6180 * @log_info: U32 LogInfo reply word from the IOC
6181 *
6182 * Refer to lsi/mpi_log_sas.h.
6183 */
6184static void
6185mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info)
6186{
6187union loginfo_type {
6188 u32 loginfo;
6189 struct {
6190 u32 subcode:16;
6191 u32 code:8;
6192 u32 originator:4;
6193 u32 bus_type:4;
6194 }dw;
6195};
6196 union loginfo_type sas_loginfo;
6197 char *code_desc = NULL;
6198
6199 sas_loginfo.loginfo = log_info;
6200 if ((sas_loginfo.dw.bus_type != 3 /*SAS*/) &&
6201 (sas_loginfo.dw.originator < sizeof(originator_str)/sizeof(char*)))
6202 return;
6203 if ((sas_loginfo.dw.originator == 0 /*IOP*/) &&
6204 (sas_loginfo.dw.code < sizeof(iop_code_str)/sizeof(char*))) {
6205 code_desc = iop_code_str[sas_loginfo.dw.code];
6206 }else if ((sas_loginfo.dw.originator == 1 /*PL*/) &&
6207 (sas_loginfo.dw.code < sizeof(pl_code_str)/sizeof(char*) )) {
6208 code_desc = pl_code_str[sas_loginfo.dw.code];
6209 }
6210
6211 if (code_desc != NULL)
6212 printk(MYIOC_s_INFO_FMT
6213 "LogInfo(0x%08x): Originator={%s}, Code={%s},"
6214 " SubCode(0x%04x)\n",
6215 ioc->name,
6216 log_info,
6217 originator_str[sas_loginfo.dw.originator],
6218 code_desc,
6219 sas_loginfo.dw.subcode);
6220 else
6221 printk(MYIOC_s_INFO_FMT
6222 "LogInfo(0x%08x): Originator={%s}, Code=(0x%02x),"
6223 " SubCode(0x%04x)\n",
6224 ioc->name,
6225 log_info,
6226 originator_str[sas_loginfo.dw.originator],
6227 sas_loginfo.dw.code,
6228 sas_loginfo.dw.subcode);
6229}
6230
1da177e4
LT
6231/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6232/*
6233 * mpt_sp_ioc_info - IOC information returned from SCSI Parallel IOC.
6234 * @ioc: Pointer to MPT_ADAPTER structure
6235 * @ioc_status: U32 IOCStatus word from IOC
6236 * @mf: Pointer to MPT request frame
6237 *
6238 * Refer to lsi/mpi.h.
6239 */
6240static void
6241mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
6242{
6243 u32 status = ioc_status & MPI_IOCSTATUS_MASK;
6244 char *desc = "";
6245
6246 switch (status) {
6247 case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */
6248 desc = "Invalid Function";
6249 break;
6250
6251 case MPI_IOCSTATUS_BUSY: /* 0x0002 */
6252 desc = "Busy";
6253 break;
6254
6255 case MPI_IOCSTATUS_INVALID_SGL: /* 0x0003 */
6256 desc = "Invalid SGL";
6257 break;
6258
6259 case MPI_IOCSTATUS_INTERNAL_ERROR: /* 0x0004 */
6260 desc = "Internal Error";
6261 break;
6262
6263 case MPI_IOCSTATUS_RESERVED: /* 0x0005 */
6264 desc = "Reserved";
6265 break;
6266
6267 case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */
6268 desc = "Insufficient Resources";
6269 break;
6270
6271 case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */
6272 desc = "Invalid Field";
6273 break;
6274
6275 case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */
6276 desc = "Invalid State";
6277 break;
6278
6279 case MPI_IOCSTATUS_CONFIG_INVALID_ACTION: /* 0x0020 */
6280 case MPI_IOCSTATUS_CONFIG_INVALID_TYPE: /* 0x0021 */
6281 case MPI_IOCSTATUS_CONFIG_INVALID_PAGE: /* 0x0022 */
6282 case MPI_IOCSTATUS_CONFIG_INVALID_DATA: /* 0x0023 */
6283 case MPI_IOCSTATUS_CONFIG_NO_DEFAULTS: /* 0x0024 */
6284 case MPI_IOCSTATUS_CONFIG_CANT_COMMIT: /* 0x0025 */
6285 /* No message for Config IOCStatus values */
6286 break;
6287
6288 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
6289 /* No message for recovered error
6290 desc = "SCSI Recovered Error";
6291 */
6292 break;
6293
6294 case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
6295 desc = "SCSI Invalid Bus";
6296 break;
6297
6298 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
6299 desc = "SCSI Invalid TargetID";
6300 break;
6301
6302 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
6303 {
6304 SCSIIORequest_t *pScsiReq = (SCSIIORequest_t *) mf;
6305 U8 cdb = pScsiReq->CDB[0];
6306 if (cdb != 0x12) { /* Inquiry is issued for device scanning */
6307 desc = "SCSI Device Not There";
6308 }
6309 break;
6310 }
6311
6312 case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
6313 desc = "SCSI Data Overrun";
6314 break;
6315
6316 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
c6678e0c 6317 /* This error is checked in scsi_io_done(). Skip.
1da177e4
LT
6318 desc = "SCSI Data Underrun";
6319 */
6320 break;
6321
6322 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
6323 desc = "SCSI I/O Data Error";
6324 break;
6325
6326 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
6327 desc = "SCSI Protocol Error";
6328 break;
6329
6330 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
6331 desc = "SCSI Task Terminated";
6332 break;
6333
6334 case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
6335 desc = "SCSI Residual Mismatch";
6336 break;
6337
6338 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
6339 desc = "SCSI Task Management Failed";
6340 break;
6341
6342 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
6343 desc = "SCSI IOC Terminated";
6344 break;
6345
6346 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
6347 desc = "SCSI Ext Terminated";
6348 break;
6349
6350 default:
6351 desc = "Others";
6352 break;
6353 }
6354 if (desc != "")
6355 printk(MYIOC_s_INFO_FMT "IOCStatus(0x%04x): %s\n", ioc->name, status, desc);
6356}
6357
6358/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7fadc87e
MED
6359EXPORT_SYMBOL(mpt_attach);
6360EXPORT_SYMBOL(mpt_detach);
6361#ifdef CONFIG_PM
6362EXPORT_SYMBOL(mpt_resume);
6363EXPORT_SYMBOL(mpt_suspend);
6364#endif
1da177e4 6365EXPORT_SYMBOL(ioc_list);
f747307e 6366EXPORT_SYMBOL(mpt_proc_root_dir);
1da177e4
LT
6367EXPORT_SYMBOL(mpt_register);
6368EXPORT_SYMBOL(mpt_deregister);
6369EXPORT_SYMBOL(mpt_event_register);
6370EXPORT_SYMBOL(mpt_event_deregister);
6371EXPORT_SYMBOL(mpt_reset_register);
6372EXPORT_SYMBOL(mpt_reset_deregister);
6373EXPORT_SYMBOL(mpt_device_driver_register);
6374EXPORT_SYMBOL(mpt_device_driver_deregister);
6375EXPORT_SYMBOL(mpt_get_msg_frame);
6376EXPORT_SYMBOL(mpt_put_msg_frame);
6377EXPORT_SYMBOL(mpt_free_msg_frame);
6378EXPORT_SYMBOL(mpt_add_sge);
6379EXPORT_SYMBOL(mpt_send_handshake_request);
6380EXPORT_SYMBOL(mpt_verify_adapter);
6381EXPORT_SYMBOL(mpt_GetIocState);
6382EXPORT_SYMBOL(mpt_print_ioc_summary);
6383EXPORT_SYMBOL(mpt_lan_index);
f747307e 6384EXPORT_SYMBOL(mpt_stm_index);
1da177e4
LT
6385EXPORT_SYMBOL(mpt_HardResetHandler);
6386EXPORT_SYMBOL(mpt_config);
6387EXPORT_SYMBOL(mpt_toolbox);
6388EXPORT_SYMBOL(mpt_findImVolumes);
6389EXPORT_SYMBOL(mpt_read_ioc_pg_3);
6390EXPORT_SYMBOL(mpt_alloc_fw_memory);
6391EXPORT_SYMBOL(mpt_free_fw_memory);
82ffb671 6392EXPORT_SYMBOL(mptbase_sas_persist_operation);
2a238ea5 6393EXPORT_SYMBOL(mpt_alt_ioc_wait);
05e8ec17 6394EXPORT_SYMBOL(mptbase_GetFcPortPage0);
1da177e4 6395
1da177e4
LT
6396
6397/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6398/*
6399 * fusion_init - Fusion MPT base driver initialization routine.
6400 *
6401 * Returns 0 for success, non-zero for failure.
6402 */
6403static int __init
6404fusion_init(void)
6405{
6406 int i;
1da177e4
LT
6407
6408 show_mptmod_ver(my_NAME, my_VERSION);
6409 printk(KERN_INFO COPYRIGHT "\n");
6410
6411 for (i = 0; i < MPT_MAX_PROTOCOL_DRIVERS; i++) {
6412 MptCallbacks[i] = NULL;
6413 MptDriverClass[i] = MPTUNKNOWN_DRIVER;
6414 MptEvHandlers[i] = NULL;
6415 MptResetHandlers[i] = NULL;
6416 }
6417
7fadc87e 6418 /* Register ourselves (mptbase) in order to facilitate
1da177e4
LT
6419 * EventNotification handling.
6420 */
6421 mpt_base_index = mpt_register(mpt_base_reply, MPTBASE_DRIVER);
6422
6423 /* Register for hard reset handling callbacks.
6424 */
6425 if (mpt_reset_register(mpt_base_index, mpt_ioc_reset) == 0) {
6426 dprintk((KERN_INFO MYNAM ": Register for IOC reset notification\n"));
6427 } else {
6428 /* FIXME! */
6429 }
6430
6431#ifdef CONFIG_PROC_FS
6432 (void) procmpt_create();
6433#endif
7fadc87e 6434 return 0;
1da177e4
LT
6435}
6436
6437/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6438/*
6439 * fusion_exit - Perform driver unload cleanup.
6440 *
6441 * This routine frees all resources associated with each MPT adapter
6442 * and removes all %MPT_PROCFS_MPTBASEDIR entries.
6443 */
6444static void __exit
6445fusion_exit(void)
6446{
6447
6448 dexitprintk((KERN_INFO MYNAM ": fusion_exit() called!\n"));
6449
1da177e4
LT
6450 mpt_reset_deregister(mpt_base_index);
6451
6452#ifdef CONFIG_PROC_FS
6453 procmpt_destroy();
6454#endif
6455}
6456
1da177e4
LT
6457module_init(fusion_init);
6458module_exit(fusion_exit);