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