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