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