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