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