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