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