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