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