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