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