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