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