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