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