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