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