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