xref: /openbmc/linux/drivers/scsi/aacraid/src.c (revision 09624645)
1e8b12f0fSMahesh Rajashekhara /*
2e8b12f0fSMahesh Rajashekhara  *	Adaptec AAC series RAID controller driver
3e8b12f0fSMahesh Rajashekhara  *	(c) Copyright 2001 Red Hat Inc.
4e8b12f0fSMahesh Rajashekhara  *
5e8b12f0fSMahesh Rajashekhara  * based on the old aacraid driver that is..
6e8b12f0fSMahesh Rajashekhara  * Adaptec aacraid device driver for Linux.
7e8b12f0fSMahesh Rajashekhara  *
8e8b12f0fSMahesh Rajashekhara  * Copyright (c) 2000-2010 Adaptec, Inc.
9f4babba0SRaghava Aditya Renukunta  *               2010-2015 PMC-Sierra, Inc. (aacraid@pmc-sierra.com)
10f4babba0SRaghava Aditya Renukunta  *		 2016-2017 Microsemi Corp. (aacraid@microsemi.com)
11e8b12f0fSMahesh Rajashekhara  *
12e8b12f0fSMahesh Rajashekhara  * This program is free software; you can redistribute it and/or modify
13e8b12f0fSMahesh Rajashekhara  * it under the terms of the GNU General Public License as published by
14e8b12f0fSMahesh Rajashekhara  * the Free Software Foundation; either version 2, or (at your option)
15e8b12f0fSMahesh Rajashekhara  * any later version.
16e8b12f0fSMahesh Rajashekhara  *
17e8b12f0fSMahesh Rajashekhara  * This program is distributed in the hope that it will be useful,
18e8b12f0fSMahesh Rajashekhara  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19e8b12f0fSMahesh Rajashekhara  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20e8b12f0fSMahesh Rajashekhara  * GNU General Public License for more details.
21e8b12f0fSMahesh Rajashekhara  *
22e8b12f0fSMahesh Rajashekhara  * You should have received a copy of the GNU General Public License
23e8b12f0fSMahesh Rajashekhara  * along with this program; see the file COPYING.  If not, write to
24e8b12f0fSMahesh Rajashekhara  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
25e8b12f0fSMahesh Rajashekhara  *
26e8b12f0fSMahesh Rajashekhara  * Module Name:
27e8b12f0fSMahesh Rajashekhara  *  src.c
28e8b12f0fSMahesh Rajashekhara  *
29e8b12f0fSMahesh Rajashekhara  * Abstract: Hardware Device Interface for PMC SRC based controllers
30e8b12f0fSMahesh Rajashekhara  *
31e8b12f0fSMahesh Rajashekhara  */
32e8b12f0fSMahesh Rajashekhara 
33e8b12f0fSMahesh Rajashekhara #include <linux/kernel.h>
34e8b12f0fSMahesh Rajashekhara #include <linux/init.h>
35e8b12f0fSMahesh Rajashekhara #include <linux/types.h>
36e8b12f0fSMahesh Rajashekhara #include <linux/pci.h>
37e8b12f0fSMahesh Rajashekhara #include <linux/spinlock.h>
38e8b12f0fSMahesh Rajashekhara #include <linux/slab.h>
39e8b12f0fSMahesh Rajashekhara #include <linux/blkdev.h>
40e8b12f0fSMahesh Rajashekhara #include <linux/delay.h>
41e8b12f0fSMahesh Rajashekhara #include <linux/completion.h>
42e8b12f0fSMahesh Rajashekhara #include <linux/time.h>
43e8b12f0fSMahesh Rajashekhara #include <linux/interrupt.h>
44e8b12f0fSMahesh Rajashekhara #include <scsi/scsi_host.h>
45e8b12f0fSMahesh Rajashekhara 
46e8b12f0fSMahesh Rajashekhara #include "aacraid.h"
47e8b12f0fSMahesh Rajashekhara 
48495c0217SMahesh Rajashekhara static int aac_src_get_sync_status(struct aac_dev *dev);
49495c0217SMahesh Rajashekhara 
50305974feSkbuild test robot static irqreturn_t aac_src_intr_message(int irq, void *dev_id)
51e8b12f0fSMahesh Rajashekhara {
52495c0217SMahesh Rajashekhara 	struct aac_msix_ctx *ctx;
53495c0217SMahesh Rajashekhara 	struct aac_dev *dev;
54e8b12f0fSMahesh Rajashekhara 	unsigned long bellbits, bellbits_shifted;
55495c0217SMahesh Rajashekhara 	int vector_no;
56495c0217SMahesh Rajashekhara 	int isFastResponse, mode;
57e8b12f0fSMahesh Rajashekhara 	u32 index, handle;
58e8b12f0fSMahesh Rajashekhara 
59495c0217SMahesh Rajashekhara 	ctx = (struct aac_msix_ctx *)dev_id;
60495c0217SMahesh Rajashekhara 	dev = ctx->dev;
61495c0217SMahesh Rajashekhara 	vector_no = ctx->vector_no;
62495c0217SMahesh Rajashekhara 
63495c0217SMahesh Rajashekhara 	if (dev->msi_enabled) {
64495c0217SMahesh Rajashekhara 		mode = AAC_INT_MODE_MSI;
65495c0217SMahesh Rajashekhara 		if (vector_no == 0) {
66495c0217SMahesh Rajashekhara 			bellbits = src_readl(dev, MUnit.ODR_MSI);
67495c0217SMahesh Rajashekhara 			if (bellbits & 0x40000)
68495c0217SMahesh Rajashekhara 				mode |= AAC_INT_MODE_AIF;
69495c0217SMahesh Rajashekhara 			if (bellbits & 0x1000)
70495c0217SMahesh Rajashekhara 				mode |= AAC_INT_MODE_SYNC;
71495c0217SMahesh Rajashekhara 		}
72495c0217SMahesh Rajashekhara 	} else {
73495c0217SMahesh Rajashekhara 		mode = AAC_INT_MODE_INTX;
74e8b12f0fSMahesh Rajashekhara 		bellbits = src_readl(dev, MUnit.ODR_R);
75e8b12f0fSMahesh Rajashekhara 		if (bellbits & PmDoorBellResponseSent) {
76e8b12f0fSMahesh Rajashekhara 			bellbits = PmDoorBellResponseSent;
7785d22bbfSMahesh Rajashekhara 			src_writel(dev, MUnit.ODR_C, bellbits);
7885d22bbfSMahesh Rajashekhara 			src_readl(dev, MUnit.ODR_C);
79e8b12f0fSMahesh Rajashekhara 		} else {
80e8b12f0fSMahesh Rajashekhara 			bellbits_shifted = (bellbits >> SRC_ODR_SHIFT);
8185d22bbfSMahesh Rajashekhara 			src_writel(dev, MUnit.ODR_C, bellbits);
8285d22bbfSMahesh Rajashekhara 			src_readl(dev, MUnit.ODR_C);
83495c0217SMahesh Rajashekhara 
84495c0217SMahesh Rajashekhara 			if (bellbits_shifted & DoorBellAifPending)
85495c0217SMahesh Rajashekhara 				mode |= AAC_INT_MODE_AIF;
86495c0217SMahesh Rajashekhara 			else if (bellbits_shifted & OUTBOUNDDOORBELL_0)
87495c0217SMahesh Rajashekhara 				mode |= AAC_INT_MODE_SYNC;
88495c0217SMahesh Rajashekhara 		}
89495c0217SMahesh Rajashekhara 	}
90495c0217SMahesh Rajashekhara 
91495c0217SMahesh Rajashekhara 	if (mode & AAC_INT_MODE_SYNC) {
9211604612SMahesh Rajashekhara 		unsigned long sflags;
9311604612SMahesh Rajashekhara 		struct list_head *entry;
9411604612SMahesh Rajashekhara 		int send_it = 0;
9585d22bbfSMahesh Rajashekhara 		extern int aac_sync_mode;
9685d22bbfSMahesh Rajashekhara 
97495c0217SMahesh Rajashekhara 		if (!aac_sync_mode && !dev->msi_enabled) {
98c5bebd82SMahesh Rajashekhara 			src_writel(dev, MUnit.ODR_C, bellbits);
99c5bebd82SMahesh Rajashekhara 			src_readl(dev, MUnit.ODR_C);
10085d22bbfSMahesh Rajashekhara 		}
10111604612SMahesh Rajashekhara 
10211604612SMahesh Rajashekhara 		if (dev->sync_fib) {
10311604612SMahesh Rajashekhara 			if (dev->sync_fib->callback)
10411604612SMahesh Rajashekhara 				dev->sync_fib->callback(dev->sync_fib->callback_data,
10511604612SMahesh Rajashekhara 					dev->sync_fib);
10611604612SMahesh Rajashekhara 			spin_lock_irqsave(&dev->sync_fib->event_lock, sflags);
10711604612SMahesh Rajashekhara 			if (dev->sync_fib->flags & FIB_CONTEXT_FLAG_WAIT) {
10811604612SMahesh Rajashekhara 				dev->management_fib_count--;
10911604612SMahesh Rajashekhara 				up(&dev->sync_fib->event_wait);
11011604612SMahesh Rajashekhara 			}
111495c0217SMahesh Rajashekhara 			spin_unlock_irqrestore(&dev->sync_fib->event_lock,
112495c0217SMahesh Rajashekhara 						sflags);
11311604612SMahesh Rajashekhara 			spin_lock_irqsave(&dev->sync_lock, sflags);
11411604612SMahesh Rajashekhara 			if (!list_empty(&dev->sync_fib_list)) {
11511604612SMahesh Rajashekhara 				entry = dev->sync_fib_list.next;
116495c0217SMahesh Rajashekhara 				dev->sync_fib = list_entry(entry,
117495c0217SMahesh Rajashekhara 							   struct fib,
118495c0217SMahesh Rajashekhara 							   fiblink);
11911604612SMahesh Rajashekhara 				list_del(entry);
12011604612SMahesh Rajashekhara 				send_it = 1;
12111604612SMahesh Rajashekhara 			} else {
12211604612SMahesh Rajashekhara 				dev->sync_fib = NULL;
12311604612SMahesh Rajashekhara 			}
12411604612SMahesh Rajashekhara 			spin_unlock_irqrestore(&dev->sync_lock, sflags);
12511604612SMahesh Rajashekhara 			if (send_it) {
12611604612SMahesh Rajashekhara 				aac_adapter_sync_cmd(dev, SEND_SYNCHRONOUS_FIB,
127495c0217SMahesh Rajashekhara 					(u32)dev->sync_fib->hw_fib_pa,
128495c0217SMahesh Rajashekhara 					0, 0, 0, 0, 0,
12911604612SMahesh Rajashekhara 					NULL, NULL, NULL, NULL, NULL);
13011604612SMahesh Rajashekhara 			}
13111604612SMahesh Rajashekhara 		}
132495c0217SMahesh Rajashekhara 		if (!dev->msi_enabled)
133495c0217SMahesh Rajashekhara 			mode = 0;
134495c0217SMahesh Rajashekhara 
135e8b12f0fSMahesh Rajashekhara 	}
136e8b12f0fSMahesh Rajashekhara 
137495c0217SMahesh Rajashekhara 	if (mode & AAC_INT_MODE_AIF) {
138495c0217SMahesh Rajashekhara 		/* handle AIF */
1393ffd6c5aSRaghava Aditya Renukunta 		if (dev->sa_firmware) {
1403ffd6c5aSRaghava Aditya Renukunta 			u32 events = src_readl(dev, MUnit.SCR0);
1413ffd6c5aSRaghava Aditya Renukunta 
1423ffd6c5aSRaghava Aditya Renukunta 			aac_intr_normal(dev, events, 1, 0, NULL);
1433ffd6c5aSRaghava Aditya Renukunta 			writel(events, &dev->IndexRegs->Mailbox[0]);
1443ffd6c5aSRaghava Aditya Renukunta 			src_writel(dev, MUnit.IDR, 1 << 23);
1453ffd6c5aSRaghava Aditya Renukunta 		} else {
1469cb62fa2SRaghava Aditya Renukunta 			if (dev->aif_thread && dev->fsa_dev)
147495c0217SMahesh Rajashekhara 				aac_intr_normal(dev, 0, 2, 0, NULL);
1483ffd6c5aSRaghava Aditya Renukunta 		}
149495c0217SMahesh Rajashekhara 		if (dev->msi_enabled)
150495c0217SMahesh Rajashekhara 			aac_src_access_devreg(dev, AAC_CLEAR_AIF_BIT);
151495c0217SMahesh Rajashekhara 		mode = 0;
152e8b12f0fSMahesh Rajashekhara 	}
153495c0217SMahesh Rajashekhara 
154495c0217SMahesh Rajashekhara 	if (mode) {
155495c0217SMahesh Rajashekhara 		index = dev->host_rrq_idx[vector_no];
156495c0217SMahesh Rajashekhara 
157495c0217SMahesh Rajashekhara 		for (;;) {
158495c0217SMahesh Rajashekhara 			isFastResponse = 0;
159495c0217SMahesh Rajashekhara 			/* remove toggle bit (31) */
1603ffd6c5aSRaghava Aditya Renukunta 			handle = le32_to_cpu((dev->host_rrq[index])
1613ffd6c5aSRaghava Aditya Renukunta 				& 0x7fffffff);
1623ffd6c5aSRaghava Aditya Renukunta 			/* check fast response bits (30, 1) */
163495c0217SMahesh Rajashekhara 			if (handle & 0x40000000)
164495c0217SMahesh Rajashekhara 				isFastResponse = 1;
165495c0217SMahesh Rajashekhara 			handle &= 0x0000ffff;
166495c0217SMahesh Rajashekhara 			if (handle == 0)
167495c0217SMahesh Rajashekhara 				break;
1683ffd6c5aSRaghava Aditya Renukunta 			handle >>= 2;
169495c0217SMahesh Rajashekhara 			if (dev->msi_enabled && dev->max_msix > 1)
170495c0217SMahesh Rajashekhara 				atomic_dec(&dev->rrq_outstanding[vector_no]);
1713ffd6c5aSRaghava Aditya Renukunta 			aac_intr_normal(dev, handle, 0, isFastResponse, NULL);
172495c0217SMahesh Rajashekhara 			dev->host_rrq[index++] = 0;
173495c0217SMahesh Rajashekhara 			if (index == (vector_no + 1) * dev->vector_cap)
174495c0217SMahesh Rajashekhara 				index = vector_no * dev->vector_cap;
175495c0217SMahesh Rajashekhara 			dev->host_rrq_idx[vector_no] = index;
176495c0217SMahesh Rajashekhara 		}
177495c0217SMahesh Rajashekhara 		mode = 0;
178495c0217SMahesh Rajashekhara 	}
179495c0217SMahesh Rajashekhara 
180495c0217SMahesh Rajashekhara 	return IRQ_HANDLED;
181e8b12f0fSMahesh Rajashekhara }
182e8b12f0fSMahesh Rajashekhara 
183e8b12f0fSMahesh Rajashekhara /**
184e8b12f0fSMahesh Rajashekhara  *	aac_src_disable_interrupt	-	Disable interrupts
185e8b12f0fSMahesh Rajashekhara  *	@dev: Adapter
186e8b12f0fSMahesh Rajashekhara  */
187e8b12f0fSMahesh Rajashekhara 
188e8b12f0fSMahesh Rajashekhara static void aac_src_disable_interrupt(struct aac_dev *dev)
189e8b12f0fSMahesh Rajashekhara {
190e8b12f0fSMahesh Rajashekhara 	src_writel(dev, MUnit.OIMR, dev->OIMR = 0xffffffff);
191e8b12f0fSMahesh Rajashekhara }
192e8b12f0fSMahesh Rajashekhara 
193e8b12f0fSMahesh Rajashekhara /**
194e8b12f0fSMahesh Rajashekhara  *	aac_src_enable_interrupt_message	-	Enable interrupts
195e8b12f0fSMahesh Rajashekhara  *	@dev: Adapter
196e8b12f0fSMahesh Rajashekhara  */
197e8b12f0fSMahesh Rajashekhara 
198e8b12f0fSMahesh Rajashekhara static void aac_src_enable_interrupt_message(struct aac_dev *dev)
199e8b12f0fSMahesh Rajashekhara {
200495c0217SMahesh Rajashekhara 	aac_src_access_devreg(dev, AAC_ENABLE_INTERRUPT);
201e8b12f0fSMahesh Rajashekhara }
202e8b12f0fSMahesh Rajashekhara 
203e8b12f0fSMahesh Rajashekhara /**
204e8b12f0fSMahesh Rajashekhara  *	src_sync_cmd	-	send a command and wait
205e8b12f0fSMahesh Rajashekhara  *	@dev: Adapter
206e8b12f0fSMahesh Rajashekhara  *	@command: Command to execute
207e8b12f0fSMahesh Rajashekhara  *	@p1: first parameter
208e8b12f0fSMahesh Rajashekhara  *	@ret: adapter status
209e8b12f0fSMahesh Rajashekhara  *
210e8b12f0fSMahesh Rajashekhara  *	This routine will send a synchronous command to the adapter and wait
211e8b12f0fSMahesh Rajashekhara  *	for its	completion.
212e8b12f0fSMahesh Rajashekhara  */
213e8b12f0fSMahesh Rajashekhara 
214e8b12f0fSMahesh Rajashekhara static int src_sync_cmd(struct aac_dev *dev, u32 command,
215e8b12f0fSMahesh Rajashekhara 	u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6,
216e8b12f0fSMahesh Rajashekhara 	u32 *status, u32 * r1, u32 * r2, u32 * r3, u32 * r4)
217e8b12f0fSMahesh Rajashekhara {
218e8b12f0fSMahesh Rajashekhara 	unsigned long start;
219dafde947SMahesh Rajashekhara 	unsigned long delay;
220e8b12f0fSMahesh Rajashekhara 	int ok;
221e8b12f0fSMahesh Rajashekhara 
222e8b12f0fSMahesh Rajashekhara 	/*
223e8b12f0fSMahesh Rajashekhara 	 *	Write the command into Mailbox 0
224e8b12f0fSMahesh Rajashekhara 	 */
225e8b12f0fSMahesh Rajashekhara 	writel(command, &dev->IndexRegs->Mailbox[0]);
226e8b12f0fSMahesh Rajashekhara 	/*
227e8b12f0fSMahesh Rajashekhara 	 *	Write the parameters into Mailboxes 1 - 6
228e8b12f0fSMahesh Rajashekhara 	 */
229e8b12f0fSMahesh Rajashekhara 	writel(p1, &dev->IndexRegs->Mailbox[1]);
230e8b12f0fSMahesh Rajashekhara 	writel(p2, &dev->IndexRegs->Mailbox[2]);
231e8b12f0fSMahesh Rajashekhara 	writel(p3, &dev->IndexRegs->Mailbox[3]);
232e8b12f0fSMahesh Rajashekhara 	writel(p4, &dev->IndexRegs->Mailbox[4]);
233e8b12f0fSMahesh Rajashekhara 
234e8b12f0fSMahesh Rajashekhara 	/*
235e8b12f0fSMahesh Rajashekhara 	 *	Clear the synch command doorbell to start on a clean slate.
236e8b12f0fSMahesh Rajashekhara 	 */
237495c0217SMahesh Rajashekhara 	if (!dev->msi_enabled)
238495c0217SMahesh Rajashekhara 		src_writel(dev,
239495c0217SMahesh Rajashekhara 			   MUnit.ODR_C,
240495c0217SMahesh Rajashekhara 			   OUTBOUNDDOORBELL_0 << SRC_ODR_SHIFT);
241e8b12f0fSMahesh Rajashekhara 
242e8b12f0fSMahesh Rajashekhara 	/*
243e8b12f0fSMahesh Rajashekhara 	 *	Disable doorbell interrupts
244e8b12f0fSMahesh Rajashekhara 	 */
245e8b12f0fSMahesh Rajashekhara 	src_writel(dev, MUnit.OIMR, dev->OIMR = 0xffffffff);
246e8b12f0fSMahesh Rajashekhara 
247e8b12f0fSMahesh Rajashekhara 	/*
248e8b12f0fSMahesh Rajashekhara 	 *	Force the completion of the mask register write before issuing
249e8b12f0fSMahesh Rajashekhara 	 *	the interrupt.
250e8b12f0fSMahesh Rajashekhara 	 */
251e8b12f0fSMahesh Rajashekhara 	src_readl(dev, MUnit.OIMR);
252e8b12f0fSMahesh Rajashekhara 
253e8b12f0fSMahesh Rajashekhara 	/*
254e8b12f0fSMahesh Rajashekhara 	 *	Signal that there is a new synch command
255e8b12f0fSMahesh Rajashekhara 	 */
256e8b12f0fSMahesh Rajashekhara 	src_writel(dev, MUnit.IDR, INBOUNDDOORBELL_0 << SRC_IDR_SHIFT);
257e8b12f0fSMahesh Rajashekhara 
25811604612SMahesh Rajashekhara 	if (!dev->sync_mode || command != SEND_SYNCHRONOUS_FIB) {
259e8b12f0fSMahesh Rajashekhara 		ok = 0;
260e8b12f0fSMahesh Rajashekhara 		start = jiffies;
261e8b12f0fSMahesh Rajashekhara 
262dafde947SMahesh Rajashekhara 		if (command == IOP_RESET_ALWAYS) {
263dafde947SMahesh Rajashekhara 			/* Wait up to 10 sec */
264dafde947SMahesh Rajashekhara 			delay = 10*HZ;
265dafde947SMahesh Rajashekhara 		} else {
266dafde947SMahesh Rajashekhara 			/* Wait up to 5 minutes */
267dafde947SMahesh Rajashekhara 			delay = 300*HZ;
268dafde947SMahesh Rajashekhara 		}
269dafde947SMahesh Rajashekhara 		while (time_before(jiffies, start+delay)) {
27011604612SMahesh Rajashekhara 			udelay(5);	/* Delay 5 microseconds to let Mon960 get info. */
27111604612SMahesh Rajashekhara 			/*
27211604612SMahesh Rajashekhara 			 *	Mon960 will set doorbell0 bit when it has completed the command.
273e8b12f0fSMahesh Rajashekhara 			 */
274495c0217SMahesh Rajashekhara 			if (aac_src_get_sync_status(dev) & OUTBOUNDDOORBELL_0) {
27511604612SMahesh Rajashekhara 				/*
27611604612SMahesh Rajashekhara 				 *	Clear the doorbell.
27711604612SMahesh Rajashekhara 				 */
278495c0217SMahesh Rajashekhara 				if (dev->msi_enabled)
279495c0217SMahesh Rajashekhara 					aac_src_access_devreg(dev,
280495c0217SMahesh Rajashekhara 						AAC_CLEAR_SYNC_BIT);
281495c0217SMahesh Rajashekhara 				else
282495c0217SMahesh Rajashekhara 					src_writel(dev,
283495c0217SMahesh Rajashekhara 						MUnit.ODR_C,
284495c0217SMahesh Rajashekhara 						OUTBOUNDDOORBELL_0 << SRC_ODR_SHIFT);
285e8b12f0fSMahesh Rajashekhara 				ok = 1;
286e8b12f0fSMahesh Rajashekhara 				break;
287e8b12f0fSMahesh Rajashekhara 			}
28811604612SMahesh Rajashekhara 			/*
28911604612SMahesh Rajashekhara 			 *	Yield the processor in case we are slow
29011604612SMahesh Rajashekhara 			 */
291e8b12f0fSMahesh Rajashekhara 			msleep(1);
292e8b12f0fSMahesh Rajashekhara 		}
293e8b12f0fSMahesh Rajashekhara 		if (unlikely(ok != 1)) {
29411604612SMahesh Rajashekhara 			/*
29511604612SMahesh Rajashekhara 			 *	Restore interrupt mask even though we timed out
29611604612SMahesh Rajashekhara 			 */
297e8b12f0fSMahesh Rajashekhara 			aac_adapter_enable_int(dev);
298e8b12f0fSMahesh Rajashekhara 			return -ETIMEDOUT;
299e8b12f0fSMahesh Rajashekhara 		}
30011604612SMahesh Rajashekhara 		/*
30111604612SMahesh Rajashekhara 		 *	Pull the synch status from Mailbox 0.
30211604612SMahesh Rajashekhara 		 */
303e8b12f0fSMahesh Rajashekhara 		if (status)
304e8b12f0fSMahesh Rajashekhara 			*status = readl(&dev->IndexRegs->Mailbox[0]);
305e8b12f0fSMahesh Rajashekhara 		if (r1)
306e8b12f0fSMahesh Rajashekhara 			*r1 = readl(&dev->IndexRegs->Mailbox[1]);
307e8b12f0fSMahesh Rajashekhara 		if (r2)
308e8b12f0fSMahesh Rajashekhara 			*r2 = readl(&dev->IndexRegs->Mailbox[2]);
309e8b12f0fSMahesh Rajashekhara 		if (r3)
310e8b12f0fSMahesh Rajashekhara 			*r3 = readl(&dev->IndexRegs->Mailbox[3]);
311e8b12f0fSMahesh Rajashekhara 		if (r4)
312e8b12f0fSMahesh Rajashekhara 			*r4 = readl(&dev->IndexRegs->Mailbox[4]);
313495c0217SMahesh Rajashekhara 		if (command == GET_COMM_PREFERRED_SETTINGS)
314495c0217SMahesh Rajashekhara 			dev->max_msix =
315495c0217SMahesh Rajashekhara 				readl(&dev->IndexRegs->Mailbox[5]) & 0xFFFF;
31611604612SMahesh Rajashekhara 		/*
31711604612SMahesh Rajashekhara 		 *	Clear the synch command doorbell.
31811604612SMahesh Rajashekhara 		 */
319495c0217SMahesh Rajashekhara 		if (!dev->msi_enabled)
320495c0217SMahesh Rajashekhara 			src_writel(dev,
321495c0217SMahesh Rajashekhara 				MUnit.ODR_C,
322495c0217SMahesh Rajashekhara 				OUTBOUNDDOORBELL_0 << SRC_ODR_SHIFT);
32311604612SMahesh Rajashekhara 	}
324e8b12f0fSMahesh Rajashekhara 
32511604612SMahesh Rajashekhara 	/*
32611604612SMahesh Rajashekhara 	 *	Restore interrupt mask
32711604612SMahesh Rajashekhara 	 */
328e8b12f0fSMahesh Rajashekhara 	aac_adapter_enable_int(dev);
329e8b12f0fSMahesh Rajashekhara 	return 0;
330e8b12f0fSMahesh Rajashekhara }
331e8b12f0fSMahesh Rajashekhara 
332e8b12f0fSMahesh Rajashekhara /**
333e8b12f0fSMahesh Rajashekhara  *	aac_src_interrupt_adapter	-	interrupt adapter
334e8b12f0fSMahesh Rajashekhara  *	@dev: Adapter
335e8b12f0fSMahesh Rajashekhara  *
336e8b12f0fSMahesh Rajashekhara  *	Send an interrupt to the i960 and breakpoint it.
337e8b12f0fSMahesh Rajashekhara  */
338e8b12f0fSMahesh Rajashekhara 
339e8b12f0fSMahesh Rajashekhara static void aac_src_interrupt_adapter(struct aac_dev *dev)
340e8b12f0fSMahesh Rajashekhara {
341e8b12f0fSMahesh Rajashekhara 	src_sync_cmd(dev, BREAKPOINT_REQUEST,
342e8b12f0fSMahesh Rajashekhara 		0, 0, 0, 0, 0, 0,
343e8b12f0fSMahesh Rajashekhara 		NULL, NULL, NULL, NULL, NULL);
344e8b12f0fSMahesh Rajashekhara }
345e8b12f0fSMahesh Rajashekhara 
346e8b12f0fSMahesh Rajashekhara /**
347e8b12f0fSMahesh Rajashekhara  *	aac_src_notify_adapter		-	send an event to the adapter
348e8b12f0fSMahesh Rajashekhara  *	@dev: Adapter
349e8b12f0fSMahesh Rajashekhara  *	@event: Event to send
350e8b12f0fSMahesh Rajashekhara  *
351e8b12f0fSMahesh Rajashekhara  *	Notify the i960 that something it probably cares about has
352e8b12f0fSMahesh Rajashekhara  *	happened.
353e8b12f0fSMahesh Rajashekhara  */
354e8b12f0fSMahesh Rajashekhara 
355e8b12f0fSMahesh Rajashekhara static void aac_src_notify_adapter(struct aac_dev *dev, u32 event)
356e8b12f0fSMahesh Rajashekhara {
357e8b12f0fSMahesh Rajashekhara 	switch (event) {
358e8b12f0fSMahesh Rajashekhara 
359e8b12f0fSMahesh Rajashekhara 	case AdapNormCmdQue:
360e8b12f0fSMahesh Rajashekhara 		src_writel(dev, MUnit.ODR_C,
361e8b12f0fSMahesh Rajashekhara 			INBOUNDDOORBELL_1 << SRC_ODR_SHIFT);
362e8b12f0fSMahesh Rajashekhara 		break;
363e8b12f0fSMahesh Rajashekhara 	case HostNormRespNotFull:
364e8b12f0fSMahesh Rajashekhara 		src_writel(dev, MUnit.ODR_C,
365e8b12f0fSMahesh Rajashekhara 			INBOUNDDOORBELL_4 << SRC_ODR_SHIFT);
366e8b12f0fSMahesh Rajashekhara 		break;
367e8b12f0fSMahesh Rajashekhara 	case AdapNormRespQue:
368e8b12f0fSMahesh Rajashekhara 		src_writel(dev, MUnit.ODR_C,
369e8b12f0fSMahesh Rajashekhara 			INBOUNDDOORBELL_2 << SRC_ODR_SHIFT);
370e8b12f0fSMahesh Rajashekhara 		break;
371e8b12f0fSMahesh Rajashekhara 	case HostNormCmdNotFull:
372e8b12f0fSMahesh Rajashekhara 		src_writel(dev, MUnit.ODR_C,
373e8b12f0fSMahesh Rajashekhara 			INBOUNDDOORBELL_3 << SRC_ODR_SHIFT);
374e8b12f0fSMahesh Rajashekhara 		break;
375e8b12f0fSMahesh Rajashekhara 	case FastIo:
376e8b12f0fSMahesh Rajashekhara 		src_writel(dev, MUnit.ODR_C,
377e8b12f0fSMahesh Rajashekhara 			INBOUNDDOORBELL_6 << SRC_ODR_SHIFT);
378e8b12f0fSMahesh Rajashekhara 		break;
379e8b12f0fSMahesh Rajashekhara 	case AdapPrintfDone:
380e8b12f0fSMahesh Rajashekhara 		src_writel(dev, MUnit.ODR_C,
381e8b12f0fSMahesh Rajashekhara 			INBOUNDDOORBELL_5 << SRC_ODR_SHIFT);
382e8b12f0fSMahesh Rajashekhara 		break;
383e8b12f0fSMahesh Rajashekhara 	default:
384e8b12f0fSMahesh Rajashekhara 		BUG();
385e8b12f0fSMahesh Rajashekhara 		break;
386e8b12f0fSMahesh Rajashekhara 	}
387e8b12f0fSMahesh Rajashekhara }
388e8b12f0fSMahesh Rajashekhara 
389e8b12f0fSMahesh Rajashekhara /**
390e8b12f0fSMahesh Rajashekhara  *	aac_src_start_adapter		-	activate adapter
391e8b12f0fSMahesh Rajashekhara  *	@dev:	Adapter
392e8b12f0fSMahesh Rajashekhara  *
393e8b12f0fSMahesh Rajashekhara  *	Start up processing on an i960 based AAC adapter
394e8b12f0fSMahesh Rajashekhara  */
395e8b12f0fSMahesh Rajashekhara 
396e8b12f0fSMahesh Rajashekhara static void aac_src_start_adapter(struct aac_dev *dev)
397e8b12f0fSMahesh Rajashekhara {
398d1ef4da8SRaghava Aditya Renukunta 	union aac_init *init;
399495c0217SMahesh Rajashekhara 	int i;
400e8b12f0fSMahesh Rajashekhara 
40185d22bbfSMahesh Rajashekhara 	 /* reset host_rrq_idx first */
402495c0217SMahesh Rajashekhara 	for (i = 0; i < dev->max_msix; i++) {
403495c0217SMahesh Rajashekhara 		dev->host_rrq_idx[i] = i * dev->vector_cap;
404495c0217SMahesh Rajashekhara 		atomic_set(&dev->rrq_outstanding[i], 0);
405495c0217SMahesh Rajashekhara 	}
4063ffd6c5aSRaghava Aditya Renukunta 	atomic_set(&dev->msix_counter, 0);
407495c0217SMahesh Rajashekhara 	dev->fibs_pushed_no = 0;
40885d22bbfSMahesh Rajashekhara 
409e8b12f0fSMahesh Rajashekhara 	init = dev->init;
410d1ef4da8SRaghava Aditya Renukunta 	if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE3) {
411d1ef4da8SRaghava Aditya Renukunta 		init->r8.host_elapsed_seconds = cpu_to_le32(get_seconds());
412d1ef4da8SRaghava Aditya Renukunta 		src_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS,
41380a94bb3SArnd Bergmann 			lower_32_bits(dev->init_pa),
41480a94bb3SArnd Bergmann 			upper_32_bits(dev->init_pa),
415d1ef4da8SRaghava Aditya Renukunta 			sizeof(struct _r8) +
416d1ef4da8SRaghava Aditya Renukunta 			(AAC_MAX_HRRQ - 1) * sizeof(struct _rrq),
417d1ef4da8SRaghava Aditya Renukunta 			0, 0, 0, NULL, NULL, NULL, NULL, NULL);
418d1ef4da8SRaghava Aditya Renukunta 	} else {
419d1ef4da8SRaghava Aditya Renukunta 		init->r7.host_elapsed_seconds = cpu_to_le32(get_seconds());
420d1ef4da8SRaghava Aditya Renukunta 		// We can only use a 32 bit address here
421d1ef4da8SRaghava Aditya Renukunta 		src_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS,
422d1ef4da8SRaghava Aditya Renukunta 			(u32)(ulong)dev->init_pa, 0, 0, 0, 0, 0,
423d1ef4da8SRaghava Aditya Renukunta 			NULL, NULL, NULL, NULL, NULL);
424d1ef4da8SRaghava Aditya Renukunta 	}
425e8b12f0fSMahesh Rajashekhara 
426e8b12f0fSMahesh Rajashekhara }
427e8b12f0fSMahesh Rajashekhara 
428e8b12f0fSMahesh Rajashekhara /**
429e8b12f0fSMahesh Rajashekhara  *	aac_src_check_health
430e8b12f0fSMahesh Rajashekhara  *	@dev: device to check if healthy
431e8b12f0fSMahesh Rajashekhara  *
432e8b12f0fSMahesh Rajashekhara  *	Will attempt to determine if the specified adapter is alive and
433e8b12f0fSMahesh Rajashekhara  *	capable of handling requests, returning 0 if alive.
434e8b12f0fSMahesh Rajashekhara  */
435e8b12f0fSMahesh Rajashekhara static int aac_src_check_health(struct aac_dev *dev)
436e8b12f0fSMahesh Rajashekhara {
437e8b12f0fSMahesh Rajashekhara 	u32 status = src_readl(dev, MUnit.OMR);
438e8b12f0fSMahesh Rajashekhara 
439e8b12f0fSMahesh Rajashekhara 	/*
440e8b12f0fSMahesh Rajashekhara 	 *	Check to see if the board panic'd.
441e8b12f0fSMahesh Rajashekhara 	 */
442e8b12f0fSMahesh Rajashekhara 	if (unlikely(status & KERNEL_PANIC))
443c421530bSRaghava Aditya Renukunta 		goto err_blink;
444c421530bSRaghava Aditya Renukunta 
445c421530bSRaghava Aditya Renukunta 	/*
446c421530bSRaghava Aditya Renukunta 	 *	Check to see if the board failed any self tests.
447c421530bSRaghava Aditya Renukunta 	 */
448c421530bSRaghava Aditya Renukunta 	if (unlikely(status & SELF_TEST_FAILED))
449c421530bSRaghava Aditya Renukunta 		goto err_out;
450c421530bSRaghava Aditya Renukunta 
451c421530bSRaghava Aditya Renukunta 	/*
452c421530bSRaghava Aditya Renukunta 	 *	Check to see if the board failed any self tests.
453c421530bSRaghava Aditya Renukunta 	 */
454c421530bSRaghava Aditya Renukunta 	if (unlikely(status & MONITOR_PANIC))
455c421530bSRaghava Aditya Renukunta 		goto err_out;
456c421530bSRaghava Aditya Renukunta 
457e8b12f0fSMahesh Rajashekhara 	/*
458e8b12f0fSMahesh Rajashekhara 	 *	Wait for the adapter to be up and running.
459e8b12f0fSMahesh Rajashekhara 	 */
460e8b12f0fSMahesh Rajashekhara 	if (unlikely(!(status & KERNEL_UP_AND_RUNNING)))
461e8b12f0fSMahesh Rajashekhara 		return -3;
462e8b12f0fSMahesh Rajashekhara 	/*
463e8b12f0fSMahesh Rajashekhara 	 *	Everything is OK
464e8b12f0fSMahesh Rajashekhara 	 */
465e8b12f0fSMahesh Rajashekhara 	return 0;
466c421530bSRaghava Aditya Renukunta 
467c421530bSRaghava Aditya Renukunta err_out:
468c421530bSRaghava Aditya Renukunta 	return -1;
469c421530bSRaghava Aditya Renukunta 
470c421530bSRaghava Aditya Renukunta err_blink:
471c421530bSRaghava Aditya Renukunta 	return (status > 16) & 0xFF;
472e8b12f0fSMahesh Rajashekhara }
473e8b12f0fSMahesh Rajashekhara 
474423400e6SRaghava Aditya Renukunta static inline u32 aac_get_vector(struct aac_dev *dev)
475423400e6SRaghava Aditya Renukunta {
476423400e6SRaghava Aditya Renukunta 	return atomic_inc_return(&dev->msix_counter)%dev->max_msix;
477423400e6SRaghava Aditya Renukunta }
478423400e6SRaghava Aditya Renukunta 
479e8b12f0fSMahesh Rajashekhara /**
480e8b12f0fSMahesh Rajashekhara  *	aac_src_deliver_message
481e8b12f0fSMahesh Rajashekhara  *	@fib: fib to issue
482e8b12f0fSMahesh Rajashekhara  *
483e8b12f0fSMahesh Rajashekhara  *	Will send a fib, returning 0 if successful.
484e8b12f0fSMahesh Rajashekhara  */
485e8b12f0fSMahesh Rajashekhara static int aac_src_deliver_message(struct fib *fib)
486e8b12f0fSMahesh Rajashekhara {
487e8b12f0fSMahesh Rajashekhara 	struct aac_dev *dev = fib->dev;
488e8b12f0fSMahesh Rajashekhara 	struct aac_queue *q = &dev->queues->queue[AdapNormCmdQueue];
489e8b12f0fSMahesh Rajashekhara 	u32 fibsize;
490b5f1758fSBen Collins 	dma_addr_t address;
491e8b12f0fSMahesh Rajashekhara 	struct aac_fib_xporthdr *pFibX;
492423400e6SRaghava Aditya Renukunta 	int native_hba;
493c6992781SMahesh Rajashekhara #if !defined(writeq)
494c6992781SMahesh Rajashekhara 	unsigned long flags;
495c6992781SMahesh Rajashekhara #endif
496c6992781SMahesh Rajashekhara 
4973f4ce057SRaghava Aditya Renukunta 	u16 vector_no;
498e8b12f0fSMahesh Rajashekhara 
499ef616233SMahesh Rajashekhara 	atomic_inc(&q->numpending);
500e8b12f0fSMahesh Rajashekhara 
501423400e6SRaghava Aditya Renukunta 	native_hba = (fib->flags & FIB_CONTEXT_FLAG_NATIVE_HBA) ? 1 : 0;
502423400e6SRaghava Aditya Renukunta 
503423400e6SRaghava Aditya Renukunta 
504423400e6SRaghava Aditya Renukunta 	if (dev->msi_enabled && dev->max_msix > 1 &&
505423400e6SRaghava Aditya Renukunta 		(native_hba || fib->hw_fib_va->header.Command != AifRequest)) {
506423400e6SRaghava Aditya Renukunta 
507423400e6SRaghava Aditya Renukunta 		if ((dev->comm_interface == AAC_COMM_MESSAGE_TYPE3)
508423400e6SRaghava Aditya Renukunta 			&& dev->sa_firmware)
509423400e6SRaghava Aditya Renukunta 			vector_no = aac_get_vector(dev);
510423400e6SRaghava Aditya Renukunta 		else
5113f4ce057SRaghava Aditya Renukunta 			vector_no = fib->vector_no;
512423400e6SRaghava Aditya Renukunta 
513423400e6SRaghava Aditya Renukunta 		if (native_hba) {
514954b2b5aSRaghava Aditya Renukunta 			if (fib->flags & FIB_CONTEXT_FLAG_NATIVE_HBA_TMF) {
515954b2b5aSRaghava Aditya Renukunta 				struct aac_hba_tm_req *tm_req;
516954b2b5aSRaghava Aditya Renukunta 
517954b2b5aSRaghava Aditya Renukunta 				tm_req = (struct aac_hba_tm_req *)
518954b2b5aSRaghava Aditya Renukunta 						fib->hw_fib_va;
519954b2b5aSRaghava Aditya Renukunta 				if (tm_req->iu_type ==
520954b2b5aSRaghava Aditya Renukunta 					HBA_IU_TYPE_SCSI_TM_REQ) {
521954b2b5aSRaghava Aditya Renukunta 					((struct aac_hba_tm_req *)
522954b2b5aSRaghava Aditya Renukunta 						fib->hw_fib_va)->reply_qid
523423400e6SRaghava Aditya Renukunta 							= vector_no;
524954b2b5aSRaghava Aditya Renukunta 					((struct aac_hba_tm_req *)
525954b2b5aSRaghava Aditya Renukunta 						fib->hw_fib_va)->request_id
526423400e6SRaghava Aditya Renukunta 							+= (vector_no << 16);
527423400e6SRaghava Aditya Renukunta 				} else {
528954b2b5aSRaghava Aditya Renukunta 					((struct aac_hba_reset_req *)
529954b2b5aSRaghava Aditya Renukunta 						fib->hw_fib_va)->reply_qid
530954b2b5aSRaghava Aditya Renukunta 							= vector_no;
531954b2b5aSRaghava Aditya Renukunta 					((struct aac_hba_reset_req *)
532954b2b5aSRaghava Aditya Renukunta 						fib->hw_fib_va)->request_id
533954b2b5aSRaghava Aditya Renukunta 							+= (vector_no << 16);
534954b2b5aSRaghava Aditya Renukunta 				}
535954b2b5aSRaghava Aditya Renukunta 			} else {
536954b2b5aSRaghava Aditya Renukunta 				((struct aac_hba_cmd_req *)
537954b2b5aSRaghava Aditya Renukunta 					fib->hw_fib_va)->reply_qid
538954b2b5aSRaghava Aditya Renukunta 						= vector_no;
539954b2b5aSRaghava Aditya Renukunta 				((struct aac_hba_cmd_req *)
540954b2b5aSRaghava Aditya Renukunta 					fib->hw_fib_va)->request_id
541954b2b5aSRaghava Aditya Renukunta 						+= (vector_no << 16);
542954b2b5aSRaghava Aditya Renukunta 			}
543954b2b5aSRaghava Aditya Renukunta 		} else {
544495c0217SMahesh Rajashekhara 			fib->hw_fib_va->header.Handle += (vector_no << 16);
545423400e6SRaghava Aditya Renukunta 		}
5463f4ce057SRaghava Aditya Renukunta 	} else {
5473f4ce057SRaghava Aditya Renukunta 		vector_no = 0;
548495c0217SMahesh Rajashekhara 	}
549495c0217SMahesh Rajashekhara 
5503f4ce057SRaghava Aditya Renukunta 	atomic_inc(&dev->rrq_outstanding[vector_no]);
5513f4ce057SRaghava Aditya Renukunta 
552423400e6SRaghava Aditya Renukunta 	if (native_hba) {
553423400e6SRaghava Aditya Renukunta 		address = fib->hw_fib_pa;
554423400e6SRaghava Aditya Renukunta 		fibsize = (fib->hbacmd_size + 127) / 128 - 1;
555423400e6SRaghava Aditya Renukunta 		if (fibsize > 31)
556423400e6SRaghava Aditya Renukunta 			fibsize = 31;
557423400e6SRaghava Aditya Renukunta 		address |= fibsize;
558423400e6SRaghava Aditya Renukunta #if defined(writeq)
559423400e6SRaghava Aditya Renukunta 		src_writeq(dev, MUnit.IQN_L, (u64)address);
560423400e6SRaghava Aditya Renukunta #else
561423400e6SRaghava Aditya Renukunta 		spin_lock_irqsave(&fib->dev->iq_lock, flags);
562423400e6SRaghava Aditya Renukunta 		src_writel(dev, MUnit.IQN_H,
563423400e6SRaghava Aditya Renukunta 			upper_32_bits(address) & 0xffffffff);
564423400e6SRaghava Aditya Renukunta 		src_writel(dev, MUnit.IQN_L, address & 0xffffffff);
565423400e6SRaghava Aditya Renukunta 		spin_unlock_irqrestore(&fib->dev->iq_lock, flags);
566423400e6SRaghava Aditya Renukunta #endif
567423400e6SRaghava Aditya Renukunta 	} else {
568423400e6SRaghava Aditya Renukunta 		if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE2 ||
569423400e6SRaghava Aditya Renukunta 			dev->comm_interface == AAC_COMM_MESSAGE_TYPE3) {
57085d22bbfSMahesh Rajashekhara 			/* Calculate the amount to the fibsize bits */
571423400e6SRaghava Aditya Renukunta 			fibsize = (le16_to_cpu(fib->hw_fib_va->header.Size)
572423400e6SRaghava Aditya Renukunta 				+ 127) / 128 - 1;
57385d22bbfSMahesh Rajashekhara 			/* New FIB header, 32-bit */
57485d22bbfSMahesh Rajashekhara 			address = fib->hw_fib_pa;
57585d22bbfSMahesh Rajashekhara 			fib->hw_fib_va->header.StructType = FIB_MAGIC2;
576423400e6SRaghava Aditya Renukunta 			fib->hw_fib_va->header.SenderFibAddress =
577423400e6SRaghava Aditya Renukunta 				cpu_to_le32((u32)address);
57885d22bbfSMahesh Rajashekhara 			fib->hw_fib_va->header.u.TimeStamp = 0;
57980a94bb3SArnd Bergmann 			WARN_ON(upper_32_bits(address) != 0L);
58085d22bbfSMahesh Rajashekhara 		} else {
581e8b12f0fSMahesh Rajashekhara 			/* Calculate the amount to the fibsize bits */
582423400e6SRaghava Aditya Renukunta 			fibsize = (sizeof(struct aac_fib_xporthdr) +
583423400e6SRaghava Aditya Renukunta 				le16_to_cpu(fib->hw_fib_va->header.Size)
584423400e6SRaghava Aditya Renukunta 				+ 127) / 128 - 1;
585e8b12f0fSMahesh Rajashekhara 			/* Fill XPORT header */
586423400e6SRaghava Aditya Renukunta 			pFibX = (struct aac_fib_xporthdr *)
587423400e6SRaghava Aditya Renukunta 				((unsigned char *)fib->hw_fib_va -
588423400e6SRaghava Aditya Renukunta 				sizeof(struct aac_fib_xporthdr));
589423400e6SRaghava Aditya Renukunta 			pFibX->Handle = fib->hw_fib_va->header.Handle;
590423400e6SRaghava Aditya Renukunta 			pFibX->HostAddress =
591423400e6SRaghava Aditya Renukunta 				cpu_to_le64((u64)fib->hw_fib_pa);
592423400e6SRaghava Aditya Renukunta 			pFibX->Size = cpu_to_le32(
593423400e6SRaghava Aditya Renukunta 				le16_to_cpu(fib->hw_fib_va->header.Size));
594423400e6SRaghava Aditya Renukunta 			address = fib->hw_fib_pa -
595423400e6SRaghava Aditya Renukunta 				(u64)sizeof(struct aac_fib_xporthdr);
59685d22bbfSMahesh Rajashekhara 		}
597423400e6SRaghava Aditya Renukunta 		if (fibsize > 31)
598423400e6SRaghava Aditya Renukunta 			fibsize = 31;
599423400e6SRaghava Aditya Renukunta 		address |= fibsize;
600423400e6SRaghava Aditya Renukunta 
601c6992781SMahesh Rajashekhara #if defined(writeq)
602c6992781SMahesh Rajashekhara 		src_writeq(dev, MUnit.IQ_L, (u64)address);
603c6992781SMahesh Rajashekhara #else
604c6992781SMahesh Rajashekhara 		spin_lock_irqsave(&fib->dev->iq_lock, flags);
605423400e6SRaghava Aditya Renukunta 		src_writel(dev, MUnit.IQ_H,
606423400e6SRaghava Aditya Renukunta 			upper_32_bits(address) & 0xffffffff);
607b5f1758fSBen Collins 		src_writel(dev, MUnit.IQ_L, address & 0xffffffff);
608c6992781SMahesh Rajashekhara 		spin_unlock_irqrestore(&fib->dev->iq_lock, flags);
609c6992781SMahesh Rajashekhara #endif
610423400e6SRaghava Aditya Renukunta 	}
611e8b12f0fSMahesh Rajashekhara 	return 0;
612e8b12f0fSMahesh Rajashekhara }
613e8b12f0fSMahesh Rajashekhara 
614e8b12f0fSMahesh Rajashekhara /**
615e8b12f0fSMahesh Rajashekhara  *	aac_src_ioremap
616e8b12f0fSMahesh Rajashekhara  *	@size: mapping resize request
617e8b12f0fSMahesh Rajashekhara  *
618e8b12f0fSMahesh Rajashekhara  */
619e8b12f0fSMahesh Rajashekhara static int aac_src_ioremap(struct aac_dev *dev, u32 size)
620e8b12f0fSMahesh Rajashekhara {
621e8b12f0fSMahesh Rajashekhara 	if (!size) {
62271552505STomas Henzl 		iounmap(dev->regs.src.bar1);
62371552505STomas Henzl 		dev->regs.src.bar1 = NULL;
624e8b12f0fSMahesh Rajashekhara 		iounmap(dev->regs.src.bar0);
62511604612SMahesh Rajashekhara 		dev->base = dev->regs.src.bar0 = NULL;
626e8b12f0fSMahesh Rajashekhara 		return 0;
627e8b12f0fSMahesh Rajashekhara 	}
628e8b12f0fSMahesh Rajashekhara 	dev->regs.src.bar1 = ioremap(pci_resource_start(dev->pdev, 2),
629e8b12f0fSMahesh Rajashekhara 		AAC_MIN_SRC_BAR1_SIZE);
630e8b12f0fSMahesh Rajashekhara 	dev->base = NULL;
631e8b12f0fSMahesh Rajashekhara 	if (dev->regs.src.bar1 == NULL)
632e8b12f0fSMahesh Rajashekhara 		return -1;
633ff08784bSBen Collins 	dev->base = dev->regs.src.bar0 = ioremap(dev->base_start, size);
634e8b12f0fSMahesh Rajashekhara 	if (dev->base == NULL) {
635e8b12f0fSMahesh Rajashekhara 		iounmap(dev->regs.src.bar1);
636e8b12f0fSMahesh Rajashekhara 		dev->regs.src.bar1 = NULL;
637e8b12f0fSMahesh Rajashekhara 		return -1;
638e8b12f0fSMahesh Rajashekhara 	}
639e8b12f0fSMahesh Rajashekhara 	dev->IndexRegs = &((struct src_registers __iomem *)
64011604612SMahesh Rajashekhara 		dev->base)->u.tupelo.IndexRegs;
64111604612SMahesh Rajashekhara 	return 0;
64211604612SMahesh Rajashekhara }
64311604612SMahesh Rajashekhara 
64411604612SMahesh Rajashekhara /**
64511604612SMahesh Rajashekhara  *  aac_srcv_ioremap
64611604612SMahesh Rajashekhara  *	@size: mapping resize request
64711604612SMahesh Rajashekhara  *
64811604612SMahesh Rajashekhara  */
64911604612SMahesh Rajashekhara static int aac_srcv_ioremap(struct aac_dev *dev, u32 size)
65011604612SMahesh Rajashekhara {
65111604612SMahesh Rajashekhara 	if (!size) {
65211604612SMahesh Rajashekhara 		iounmap(dev->regs.src.bar0);
65311604612SMahesh Rajashekhara 		dev->base = dev->regs.src.bar0 = NULL;
65411604612SMahesh Rajashekhara 		return 0;
65511604612SMahesh Rajashekhara 	}
6563ffd6c5aSRaghava Aditya Renukunta 
6573ffd6c5aSRaghava Aditya Renukunta 	dev->regs.src.bar1 =
6583ffd6c5aSRaghava Aditya Renukunta 	ioremap(pci_resource_start(dev->pdev, 2), AAC_MIN_SRCV_BAR1_SIZE);
6593ffd6c5aSRaghava Aditya Renukunta 	dev->base = NULL;
6603ffd6c5aSRaghava Aditya Renukunta 	if (dev->regs.src.bar1 == NULL)
66111604612SMahesh Rajashekhara 		return -1;
6623ffd6c5aSRaghava Aditya Renukunta 	dev->base = dev->regs.src.bar0 = ioremap(dev->base_start, size);
6633ffd6c5aSRaghava Aditya Renukunta 	if (dev->base == NULL) {
6643ffd6c5aSRaghava Aditya Renukunta 		iounmap(dev->regs.src.bar1);
6653ffd6c5aSRaghava Aditya Renukunta 		dev->regs.src.bar1 = NULL;
6663ffd6c5aSRaghava Aditya Renukunta 		return -1;
6673ffd6c5aSRaghava Aditya Renukunta 	}
66811604612SMahesh Rajashekhara 	dev->IndexRegs = &((struct src_registers __iomem *)
66911604612SMahesh Rajashekhara 		dev->base)->u.denali.IndexRegs;
670e8b12f0fSMahesh Rajashekhara 	return 0;
671e8b12f0fSMahesh Rajashekhara }
672e8b12f0fSMahesh Rajashekhara 
673a7e2c642SRaghava Aditya Renukunta void aac_set_intx_mode(struct aac_dev *dev)
67431364329SRaghava Aditya Renukunta {
67531364329SRaghava Aditya Renukunta 	if (dev->msi_enabled) {
67631364329SRaghava Aditya Renukunta 		aac_src_access_devreg(dev, AAC_ENABLE_INTX);
67731364329SRaghava Aditya Renukunta 		dev->msi_enabled = 0;
67831364329SRaghava Aditya Renukunta 		msleep(5000); /* Delay 5 seconds */
67931364329SRaghava Aditya Renukunta 	}
68031364329SRaghava Aditya Renukunta }
68131364329SRaghava Aditya Renukunta 
68209624645SRaghava Aditya Renukunta static void aac_dump_fw_fib_iop_reset(struct aac_dev *dev)
68309624645SRaghava Aditya Renukunta {
68409624645SRaghava Aditya Renukunta 	__le32 supported_options3;
68509624645SRaghava Aditya Renukunta 
68609624645SRaghava Aditya Renukunta 	if (!aac_fib_dump)
68709624645SRaghava Aditya Renukunta 		return;
68809624645SRaghava Aditya Renukunta 
68909624645SRaghava Aditya Renukunta 	supported_options3  = dev->supplement_adapter_info.supported_options3;
69009624645SRaghava Aditya Renukunta 	if (!(supported_options3 & AAC_OPTION_SUPPORTED3_IOP_RESET_FIB_DUMP))
69109624645SRaghava Aditya Renukunta 		return;
69209624645SRaghava Aditya Renukunta 
69309624645SRaghava Aditya Renukunta 	aac_adapter_sync_cmd(dev, IOP_RESET_FW_FIB_DUMP,
69409624645SRaghava Aditya Renukunta 			0, 0, 0,  0, 0, 0, NULL, NULL, NULL, NULL, NULL);
69509624645SRaghava Aditya Renukunta }
69609624645SRaghava Aditya Renukunta 
69731364329SRaghava Aditya Renukunta static void aac_send_iop_reset(struct aac_dev *dev, int bled)
698e8b12f0fSMahesh Rajashekhara {
699e8b12f0fSMahesh Rajashekhara 	u32 var, reset_mask;
700e8b12f0fSMahesh Rajashekhara 
70109624645SRaghava Aditya Renukunta 	aac_dump_fw_fib_iop_reset(dev);
70209624645SRaghava Aditya Renukunta 
703e8b12f0fSMahesh Rajashekhara 	bled = aac_adapter_sync_cmd(dev, IOP_RESET_ALWAYS,
70431364329SRaghava Aditya Renukunta 				    0, 0, 0, 0, 0, 0, &var,
70531364329SRaghava Aditya Renukunta 				    &reset_mask, NULL, NULL, NULL);
70631364329SRaghava Aditya Renukunta 
70731364329SRaghava Aditya Renukunta 	if ((bled || var != 0x00000001) && !dev->doorbell_mask)
70831364329SRaghava Aditya Renukunta 		bled = -EINVAL;
709dafde947SMahesh Rajashekhara 	else if (dev->doorbell_mask) {
710dafde947SMahesh Rajashekhara 		reset_mask = dev->doorbell_mask;
711dafde947SMahesh Rajashekhara 		bled = 0;
712dafde947SMahesh Rajashekhara 		var = 0x00000001;
713dafde947SMahesh Rajashekhara 	}
714495c0217SMahesh Rajashekhara 
71531364329SRaghava Aditya Renukunta 	aac_set_intx_mode(dev);
716495c0217SMahesh Rajashekhara 
7171c68856eSRaghava Aditya Renukunta 	if (!bled && (dev->supplement_adapter_info.supported_options2 &
718dafde947SMahesh Rajashekhara 	    AAC_OPTION_DOORBELL_RESET)) {
719e8b12f0fSMahesh Rajashekhara 		src_writel(dev, MUnit.IDR, reset_mask);
720dafde947SMahesh Rajashekhara 	} else {
721dafde947SMahesh Rajashekhara 		src_writel(dev, MUnit.IDR, 0x100);
722e8b12f0fSMahesh Rajashekhara 	}
72331364329SRaghava Aditya Renukunta 	msleep(30000);
724e8b12f0fSMahesh Rajashekhara }
725e8b12f0fSMahesh Rajashekhara 
72631364329SRaghava Aditya Renukunta static void aac_send_hardware_soft_reset(struct aac_dev *dev)
72731364329SRaghava Aditya Renukunta {
72831364329SRaghava Aditya Renukunta 	u_int32_t val;
72931364329SRaghava Aditya Renukunta 
73031364329SRaghava Aditya Renukunta 	val = readl(((char *)(dev->base) + IBW_SWR_OFFSET));
73131364329SRaghava Aditya Renukunta 	val |= 0x01;
73231364329SRaghava Aditya Renukunta 	writel(val, ((char *)(dev->base) + IBW_SWR_OFFSET));
73331364329SRaghava Aditya Renukunta 	msleep_interruptible(20000);
73431364329SRaghava Aditya Renukunta }
73531364329SRaghava Aditya Renukunta 
73631364329SRaghava Aditya Renukunta static int aac_src_restart_adapter(struct aac_dev *dev, int bled, u8 reset_type)
73731364329SRaghava Aditya Renukunta {
73831364329SRaghava Aditya Renukunta 	unsigned long status, start;
73931364329SRaghava Aditya Renukunta 
74031364329SRaghava Aditya Renukunta 	if (bled < 0)
74131364329SRaghava Aditya Renukunta 		goto invalid_out;
74231364329SRaghava Aditya Renukunta 
74331364329SRaghava Aditya Renukunta 	if (bled)
74431364329SRaghava Aditya Renukunta 		pr_err("%s%d: adapter kernel panic'd %x.\n",
74531364329SRaghava Aditya Renukunta 				dev->name, dev->id, bled);
74631364329SRaghava Aditya Renukunta 
747146aa178SRaghava Aditya Renukunta 	/*
748146aa178SRaghava Aditya Renukunta 	 * When there is a BlinkLED, IOP_RESET has not effect
749146aa178SRaghava Aditya Renukunta 	 */
750146aa178SRaghava Aditya Renukunta 	if (bled >= 2 && dev->sa_firmware && reset_type & HW_IOP_RESET)
751146aa178SRaghava Aditya Renukunta 		reset_type &= ~HW_IOP_RESET;
752146aa178SRaghava Aditya Renukunta 
75331364329SRaghava Aditya Renukunta 	dev->a_ops.adapter_enable_int = aac_src_disable_interrupt;
75431364329SRaghava Aditya Renukunta 
75531364329SRaghava Aditya Renukunta 	switch (reset_type) {
75631364329SRaghava Aditya Renukunta 	case IOP_HWSOFT_RESET:
75731364329SRaghava Aditya Renukunta 		aac_send_iop_reset(dev, bled);
75831364329SRaghava Aditya Renukunta 		/*
75931364329SRaghava Aditya Renukunta 		 * Check to see if KERNEL_UP_AND_RUNNING
76031364329SRaghava Aditya Renukunta 		 * Wait for the adapter to be up and running.
76131364329SRaghava Aditya Renukunta 		 * If !KERNEL_UP_AND_RUNNING issue HW Soft Reset
76231364329SRaghava Aditya Renukunta 		 */
76331364329SRaghava Aditya Renukunta 		status = src_readl(dev, MUnit.OMR);
76431364329SRaghava Aditya Renukunta 		if (dev->sa_firmware
76531364329SRaghava Aditya Renukunta 		 && !(status & KERNEL_UP_AND_RUNNING)) {
76631364329SRaghava Aditya Renukunta 			start = jiffies;
76731364329SRaghava Aditya Renukunta 			do {
76831364329SRaghava Aditya Renukunta 				status = src_readl(dev, MUnit.OMR);
76931364329SRaghava Aditya Renukunta 				if (time_after(jiffies,
77031364329SRaghava Aditya Renukunta 				 start+HZ*SOFT_RESET_TIME)) {
77131364329SRaghava Aditya Renukunta 					aac_send_hardware_soft_reset(dev);
77231364329SRaghava Aditya Renukunta 					start = jiffies;
77331364329SRaghava Aditya Renukunta 				}
77431364329SRaghava Aditya Renukunta 			} while (!(status & KERNEL_UP_AND_RUNNING));
77531364329SRaghava Aditya Renukunta 		}
77631364329SRaghava Aditya Renukunta 		break;
77731364329SRaghava Aditya Renukunta 	case HW_SOFT_RESET:
77831364329SRaghava Aditya Renukunta 		if (dev->sa_firmware) {
77931364329SRaghava Aditya Renukunta 			aac_send_hardware_soft_reset(dev);
78031364329SRaghava Aditya Renukunta 			aac_set_intx_mode(dev);
78131364329SRaghava Aditya Renukunta 		}
78231364329SRaghava Aditya Renukunta 		break;
78331364329SRaghava Aditya Renukunta 	default:
78431364329SRaghava Aditya Renukunta 		aac_send_iop_reset(dev, bled);
78531364329SRaghava Aditya Renukunta 		break;
78631364329SRaghava Aditya Renukunta 	}
78731364329SRaghava Aditya Renukunta 
78831364329SRaghava Aditya Renukunta invalid_out:
78931364329SRaghava Aditya Renukunta 
790e8b12f0fSMahesh Rajashekhara 	if (src_readl(dev, MUnit.OMR) & KERNEL_PANIC)
791e8b12f0fSMahesh Rajashekhara 		return -ENODEV;
792e8b12f0fSMahesh Rajashekhara 
793e8b12f0fSMahesh Rajashekhara 	if (startup_timeout < 300)
794e8b12f0fSMahesh Rajashekhara 		startup_timeout = 300;
795e8b12f0fSMahesh Rajashekhara 
796e8b12f0fSMahesh Rajashekhara 	return 0;
797e8b12f0fSMahesh Rajashekhara }
798e8b12f0fSMahesh Rajashekhara 
799e8b12f0fSMahesh Rajashekhara /**
800e8b12f0fSMahesh Rajashekhara  *	aac_src_select_comm	-	Select communications method
801e8b12f0fSMahesh Rajashekhara  *	@dev: Adapter
802e8b12f0fSMahesh Rajashekhara  *	@comm: communications method
803e8b12f0fSMahesh Rajashekhara  */
804a44199eeSBaoyou Xie static int aac_src_select_comm(struct aac_dev *dev, int comm)
805e8b12f0fSMahesh Rajashekhara {
806e8b12f0fSMahesh Rajashekhara 	switch (comm) {
807e8b12f0fSMahesh Rajashekhara 	case AAC_COMM_MESSAGE:
808e8b12f0fSMahesh Rajashekhara 		dev->a_ops.adapter_intr = aac_src_intr_message;
809e8b12f0fSMahesh Rajashekhara 		dev->a_ops.adapter_deliver = aac_src_deliver_message;
810e8b12f0fSMahesh Rajashekhara 		break;
811e8b12f0fSMahesh Rajashekhara 	default:
812e8b12f0fSMahesh Rajashekhara 		return 1;
813e8b12f0fSMahesh Rajashekhara 	}
814e8b12f0fSMahesh Rajashekhara 	return 0;
815e8b12f0fSMahesh Rajashekhara }
816e8b12f0fSMahesh Rajashekhara 
817e8b12f0fSMahesh Rajashekhara /**
818e8b12f0fSMahesh Rajashekhara  *  aac_src_init	-	initialize an Cardinal Frey Bar card
819e8b12f0fSMahesh Rajashekhara  *  @dev: device to configure
820e8b12f0fSMahesh Rajashekhara  *
821e8b12f0fSMahesh Rajashekhara  */
822e8b12f0fSMahesh Rajashekhara 
823e8b12f0fSMahesh Rajashekhara int aac_src_init(struct aac_dev *dev)
824e8b12f0fSMahesh Rajashekhara {
825e8b12f0fSMahesh Rajashekhara 	unsigned long start;
826e8b12f0fSMahesh Rajashekhara 	unsigned long status;
827e8b12f0fSMahesh Rajashekhara 	int restart = 0;
828e8b12f0fSMahesh Rajashekhara 	int instance = dev->id;
829e8b12f0fSMahesh Rajashekhara 	const char *name = dev->name;
830e8b12f0fSMahesh Rajashekhara 
831e8b12f0fSMahesh Rajashekhara 	dev->a_ops.adapter_ioremap = aac_src_ioremap;
832e8b12f0fSMahesh Rajashekhara 	dev->a_ops.adapter_comm = aac_src_select_comm;
833e8b12f0fSMahesh Rajashekhara 
834e8b12f0fSMahesh Rajashekhara 	dev->base_size = AAC_MIN_SRC_BAR0_SIZE;
835e8b12f0fSMahesh Rajashekhara 	if (aac_adapter_ioremap(dev, dev->base_size)) {
836e8b12f0fSMahesh Rajashekhara 		printk(KERN_WARNING "%s: unable to map adapter.\n", name);
837e8b12f0fSMahesh Rajashekhara 		goto error_iounmap;
838e8b12f0fSMahesh Rajashekhara 	}
839e8b12f0fSMahesh Rajashekhara 
840e8b12f0fSMahesh Rajashekhara 	/* Failure to reset here is an option ... */
841e8b12f0fSMahesh Rajashekhara 	dev->a_ops.adapter_sync_cmd = src_sync_cmd;
842e8b12f0fSMahesh Rajashekhara 	dev->a_ops.adapter_enable_int = aac_src_disable_interrupt;
843e8b12f0fSMahesh Rajashekhara 	if ((aac_reset_devices || reset_devices) &&
84431364329SRaghava Aditya Renukunta 		!aac_src_restart_adapter(dev, 0, IOP_HWSOFT_RESET))
845e8b12f0fSMahesh Rajashekhara 		++restart;
846e8b12f0fSMahesh Rajashekhara 	/*
847e8b12f0fSMahesh Rajashekhara 	 *	Check to see if the board panic'd while booting.
848e8b12f0fSMahesh Rajashekhara 	 */
849e8b12f0fSMahesh Rajashekhara 	status = src_readl(dev, MUnit.OMR);
850e8b12f0fSMahesh Rajashekhara 	if (status & KERNEL_PANIC) {
85131364329SRaghava Aditya Renukunta 		if (aac_src_restart_adapter(dev,
85231364329SRaghava Aditya Renukunta 			aac_src_check_health(dev), IOP_HWSOFT_RESET))
853e8b12f0fSMahesh Rajashekhara 			goto error_iounmap;
854e8b12f0fSMahesh Rajashekhara 		++restart;
855e8b12f0fSMahesh Rajashekhara 	}
856e8b12f0fSMahesh Rajashekhara 	/*
857e8b12f0fSMahesh Rajashekhara 	 *	Check to see if the board failed any self tests.
858e8b12f0fSMahesh Rajashekhara 	 */
859e8b12f0fSMahesh Rajashekhara 	status = src_readl(dev, MUnit.OMR);
860e8b12f0fSMahesh Rajashekhara 	if (status & SELF_TEST_FAILED) {
861e8b12f0fSMahesh Rajashekhara 		printk(KERN_ERR "%s%d: adapter self-test failed.\n",
862e8b12f0fSMahesh Rajashekhara 			dev->name, instance);
863e8b12f0fSMahesh Rajashekhara 		goto error_iounmap;
864e8b12f0fSMahesh Rajashekhara 	}
865e8b12f0fSMahesh Rajashekhara 	/*
866e8b12f0fSMahesh Rajashekhara 	 *	Check to see if the monitor panic'd while booting.
867e8b12f0fSMahesh Rajashekhara 	 */
868e8b12f0fSMahesh Rajashekhara 	if (status & MONITOR_PANIC) {
869e8b12f0fSMahesh Rajashekhara 		printk(KERN_ERR "%s%d: adapter monitor panic.\n",
870e8b12f0fSMahesh Rajashekhara 			dev->name, instance);
871e8b12f0fSMahesh Rajashekhara 		goto error_iounmap;
872e8b12f0fSMahesh Rajashekhara 	}
873e8b12f0fSMahesh Rajashekhara 	start = jiffies;
874e8b12f0fSMahesh Rajashekhara 	/*
875e8b12f0fSMahesh Rajashekhara 	 *	Wait for the adapter to be up and running. Wait up to 3 minutes
876e8b12f0fSMahesh Rajashekhara 	 */
877e8b12f0fSMahesh Rajashekhara 	while (!((status = src_readl(dev, MUnit.OMR)) &
878e8b12f0fSMahesh Rajashekhara 		KERNEL_UP_AND_RUNNING)) {
879e8b12f0fSMahesh Rajashekhara 		if ((restart &&
880e8b12f0fSMahesh Rajashekhara 		  (status & (KERNEL_PANIC|SELF_TEST_FAILED|MONITOR_PANIC))) ||
881e8b12f0fSMahesh Rajashekhara 		  time_after(jiffies, start+HZ*startup_timeout)) {
882e8b12f0fSMahesh Rajashekhara 			printk(KERN_ERR "%s%d: adapter kernel failed to start, init status = %lx.\n",
883e8b12f0fSMahesh Rajashekhara 					dev->name, instance, status);
884e8b12f0fSMahesh Rajashekhara 			goto error_iounmap;
885e8b12f0fSMahesh Rajashekhara 		}
886e8b12f0fSMahesh Rajashekhara 		if (!restart &&
887e8b12f0fSMahesh Rajashekhara 		  ((status & (KERNEL_PANIC|SELF_TEST_FAILED|MONITOR_PANIC)) ||
888e8b12f0fSMahesh Rajashekhara 		  time_after(jiffies, start + HZ *
889e8b12f0fSMahesh Rajashekhara 		  ((startup_timeout > 60)
890e8b12f0fSMahesh Rajashekhara 		    ? (startup_timeout - 60)
891e8b12f0fSMahesh Rajashekhara 		    : (startup_timeout / 2))))) {
892e8b12f0fSMahesh Rajashekhara 			if (likely(!aac_src_restart_adapter(dev,
89331364329SRaghava Aditya Renukunta 				aac_src_check_health(dev), IOP_HWSOFT_RESET)))
894e8b12f0fSMahesh Rajashekhara 				start = jiffies;
895e8b12f0fSMahesh Rajashekhara 			++restart;
896e8b12f0fSMahesh Rajashekhara 		}
897e8b12f0fSMahesh Rajashekhara 		msleep(1);
898e8b12f0fSMahesh Rajashekhara 	}
899e8b12f0fSMahesh Rajashekhara 	if (restart && aac_commit)
900e8b12f0fSMahesh Rajashekhara 		aac_commit = 1;
901e8b12f0fSMahesh Rajashekhara 	/*
902e8b12f0fSMahesh Rajashekhara 	 *	Fill in the common function dispatch table.
903e8b12f0fSMahesh Rajashekhara 	 */
904e8b12f0fSMahesh Rajashekhara 	dev->a_ops.adapter_interrupt = aac_src_interrupt_adapter;
905e8b12f0fSMahesh Rajashekhara 	dev->a_ops.adapter_disable_int = aac_src_disable_interrupt;
906dafde947SMahesh Rajashekhara 	dev->a_ops.adapter_enable_int = aac_src_disable_interrupt;
907e8b12f0fSMahesh Rajashekhara 	dev->a_ops.adapter_notify = aac_src_notify_adapter;
908e8b12f0fSMahesh Rajashekhara 	dev->a_ops.adapter_sync_cmd = src_sync_cmd;
909e8b12f0fSMahesh Rajashekhara 	dev->a_ops.adapter_check_health = aac_src_check_health;
910e8b12f0fSMahesh Rajashekhara 	dev->a_ops.adapter_restart = aac_src_restart_adapter;
911de665f28SMahesh Rajashekhara 	dev->a_ops.adapter_start = aac_src_start_adapter;
912e8b12f0fSMahesh Rajashekhara 
913e8b12f0fSMahesh Rajashekhara 	/*
914e8b12f0fSMahesh Rajashekhara 	 *	First clear out all interrupts.  Then enable the one's that we
915e8b12f0fSMahesh Rajashekhara 	 *	can handle.
916e8b12f0fSMahesh Rajashekhara 	 */
917e8b12f0fSMahesh Rajashekhara 	aac_adapter_comm(dev, AAC_COMM_MESSAGE);
918e8b12f0fSMahesh Rajashekhara 	aac_adapter_disable_int(dev);
919e8b12f0fSMahesh Rajashekhara 	src_writel(dev, MUnit.ODR_C, 0xffffffff);
920e8b12f0fSMahesh Rajashekhara 	aac_adapter_enable_int(dev);
921e8b12f0fSMahesh Rajashekhara 
922e8b12f0fSMahesh Rajashekhara 	if (aac_init_adapter(dev) == NULL)
923e8b12f0fSMahesh Rajashekhara 		goto error_iounmap;
924e8b12f0fSMahesh Rajashekhara 	if (dev->comm_interface != AAC_COMM_MESSAGE_TYPE1)
925e8b12f0fSMahesh Rajashekhara 		goto error_iounmap;
926e8b12f0fSMahesh Rajashekhara 
9279022d375SMahesh Rajashekhara 	dev->msi = !pci_enable_msi(dev->pdev);
928e8b12f0fSMahesh Rajashekhara 
929495c0217SMahesh Rajashekhara 	dev->aac_msix[0].vector_no = 0;
930495c0217SMahesh Rajashekhara 	dev->aac_msix[0].dev = dev;
931495c0217SMahesh Rajashekhara 
932e8b12f0fSMahesh Rajashekhara 	if (request_irq(dev->pdev->irq, dev->a_ops.adapter_intr,
933495c0217SMahesh Rajashekhara 			IRQF_SHARED, "aacraid", &(dev->aac_msix[0]))  < 0) {
934e8b12f0fSMahesh Rajashekhara 
935e8b12f0fSMahesh Rajashekhara 		if (dev->msi)
936e8b12f0fSMahesh Rajashekhara 			pci_disable_msi(dev->pdev);
937e8b12f0fSMahesh Rajashekhara 
938e8b12f0fSMahesh Rajashekhara 		printk(KERN_ERR "%s%d: Interrupt unavailable.\n",
939e8b12f0fSMahesh Rajashekhara 			name, instance);
940e8b12f0fSMahesh Rajashekhara 		goto error_iounmap;
941e8b12f0fSMahesh Rajashekhara 	}
942e8b12f0fSMahesh Rajashekhara 	dev->dbg_base = pci_resource_start(dev->pdev, 2);
943e8b12f0fSMahesh Rajashekhara 	dev->dbg_base_mapped = dev->regs.src.bar1;
944e8b12f0fSMahesh Rajashekhara 	dev->dbg_size = AAC_MIN_SRC_BAR1_SIZE;
945dafde947SMahesh Rajashekhara 	dev->a_ops.adapter_enable_int = aac_src_enable_interrupt_message;
946e8b12f0fSMahesh Rajashekhara 
947e8b12f0fSMahesh Rajashekhara 	aac_adapter_enable_int(dev);
94811604612SMahesh Rajashekhara 
94911604612SMahesh Rajashekhara 	if (!dev->sync_mode) {
950e8b12f0fSMahesh Rajashekhara 		/*
951e8b12f0fSMahesh Rajashekhara 		 * Tell the adapter that all is configured, and it can
952e8b12f0fSMahesh Rajashekhara 		 * start accepting requests
953e8b12f0fSMahesh Rajashekhara 		 */
954e8b12f0fSMahesh Rajashekhara 		aac_src_start_adapter(dev);
95511604612SMahesh Rajashekhara 	}
956e8b12f0fSMahesh Rajashekhara 	return 0;
957e8b12f0fSMahesh Rajashekhara 
958e8b12f0fSMahesh Rajashekhara error_iounmap:
959e8b12f0fSMahesh Rajashekhara 
960e8b12f0fSMahesh Rajashekhara 	return -1;
961e8b12f0fSMahesh Rajashekhara }
96211604612SMahesh Rajashekhara 
96311604612SMahesh Rajashekhara /**
96411604612SMahesh Rajashekhara  *  aac_srcv_init	-	initialize an SRCv card
96511604612SMahesh Rajashekhara  *  @dev: device to configure
96611604612SMahesh Rajashekhara  *
96711604612SMahesh Rajashekhara  */
96811604612SMahesh Rajashekhara 
96911604612SMahesh Rajashekhara int aac_srcv_init(struct aac_dev *dev)
97011604612SMahesh Rajashekhara {
97111604612SMahesh Rajashekhara 	unsigned long start;
97211604612SMahesh Rajashekhara 	unsigned long status;
97311604612SMahesh Rajashekhara 	int restart = 0;
97411604612SMahesh Rajashekhara 	int instance = dev->id;
97511604612SMahesh Rajashekhara 	const char *name = dev->name;
97611604612SMahesh Rajashekhara 
97711604612SMahesh Rajashekhara 	dev->a_ops.adapter_ioremap = aac_srcv_ioremap;
97811604612SMahesh Rajashekhara 	dev->a_ops.adapter_comm = aac_src_select_comm;
97911604612SMahesh Rajashekhara 
98011604612SMahesh Rajashekhara 	dev->base_size = AAC_MIN_SRCV_BAR0_SIZE;
98111604612SMahesh Rajashekhara 	if (aac_adapter_ioremap(dev, dev->base_size)) {
98211604612SMahesh Rajashekhara 		printk(KERN_WARNING "%s: unable to map adapter.\n", name);
98311604612SMahesh Rajashekhara 		goto error_iounmap;
98411604612SMahesh Rajashekhara 	}
98511604612SMahesh Rajashekhara 
98611604612SMahesh Rajashekhara 	/* Failure to reset here is an option ... */
98711604612SMahesh Rajashekhara 	dev->a_ops.adapter_sync_cmd = src_sync_cmd;
98811604612SMahesh Rajashekhara 	dev->a_ops.adapter_enable_int = aac_src_disable_interrupt;
98911604612SMahesh Rajashekhara 	if ((aac_reset_devices || reset_devices) &&
99031364329SRaghava Aditya Renukunta 		!aac_src_restart_adapter(dev, 0, IOP_HWSOFT_RESET))
99111604612SMahesh Rajashekhara 		++restart;
99211604612SMahesh Rajashekhara 	/*
9932c10cd43SMahesh Rajashekhara 	 *	Check to see if flash update is running.
9942c10cd43SMahesh Rajashekhara 	 *	Wait for the adapter to be up and running. Wait up to 5 minutes
9952c10cd43SMahesh Rajashekhara 	 */
9962c10cd43SMahesh Rajashekhara 	status = src_readl(dev, MUnit.OMR);
9972c10cd43SMahesh Rajashekhara 	if (status & FLASH_UPD_PENDING) {
9982c10cd43SMahesh Rajashekhara 		start = jiffies;
9992c10cd43SMahesh Rajashekhara 		do {
10002c10cd43SMahesh Rajashekhara 			status = src_readl(dev, MUnit.OMR);
10012c10cd43SMahesh Rajashekhara 			if (time_after(jiffies, start+HZ*FWUPD_TIMEOUT)) {
10022c10cd43SMahesh Rajashekhara 				printk(KERN_ERR "%s%d: adapter flash update failed.\n",
10032c10cd43SMahesh Rajashekhara 					dev->name, instance);
10042c10cd43SMahesh Rajashekhara 				goto error_iounmap;
10052c10cd43SMahesh Rajashekhara 			}
10062c10cd43SMahesh Rajashekhara 		} while (!(status & FLASH_UPD_SUCCESS) &&
10072c10cd43SMahesh Rajashekhara 			 !(status & FLASH_UPD_FAILED));
10082c10cd43SMahesh Rajashekhara 		/* Delay 10 seconds.
10092c10cd43SMahesh Rajashekhara 		 * Because right now FW is doing a soft reset,
10102c10cd43SMahesh Rajashekhara 		 * do not read scratch pad register at this time
10112c10cd43SMahesh Rajashekhara 		 */
10122c10cd43SMahesh Rajashekhara 		ssleep(10);
10132c10cd43SMahesh Rajashekhara 	}
10142c10cd43SMahesh Rajashekhara 	/*
101511604612SMahesh Rajashekhara 	 *	Check to see if the board panic'd while booting.
101611604612SMahesh Rajashekhara 	 */
101711604612SMahesh Rajashekhara 	status = src_readl(dev, MUnit.OMR);
101811604612SMahesh Rajashekhara 	if (status & KERNEL_PANIC) {
101931364329SRaghava Aditya Renukunta 		if (aac_src_restart_adapter(dev,
102031364329SRaghava Aditya Renukunta 			aac_src_check_health(dev), IOP_HWSOFT_RESET))
102111604612SMahesh Rajashekhara 			goto error_iounmap;
102211604612SMahesh Rajashekhara 		++restart;
102311604612SMahesh Rajashekhara 	}
102411604612SMahesh Rajashekhara 	/*
102511604612SMahesh Rajashekhara 	 *	Check to see if the board failed any self tests.
102611604612SMahesh Rajashekhara 	 */
102711604612SMahesh Rajashekhara 	status = src_readl(dev, MUnit.OMR);
102811604612SMahesh Rajashekhara 	if (status & SELF_TEST_FAILED) {
102911604612SMahesh Rajashekhara 		printk(KERN_ERR "%s%d: adapter self-test failed.\n", dev->name, instance);
103011604612SMahesh Rajashekhara 		goto error_iounmap;
103111604612SMahesh Rajashekhara 	}
103211604612SMahesh Rajashekhara 	/*
103311604612SMahesh Rajashekhara 	 *	Check to see if the monitor panic'd while booting.
103411604612SMahesh Rajashekhara 	 */
103511604612SMahesh Rajashekhara 	if (status & MONITOR_PANIC) {
103611604612SMahesh Rajashekhara 		printk(KERN_ERR "%s%d: adapter monitor panic.\n", dev->name, instance);
103711604612SMahesh Rajashekhara 		goto error_iounmap;
103811604612SMahesh Rajashekhara 	}
103911604612SMahesh Rajashekhara 	start = jiffies;
104011604612SMahesh Rajashekhara 	/*
104111604612SMahesh Rajashekhara 	 *	Wait for the adapter to be up and running. Wait up to 3 minutes
104211604612SMahesh Rajashekhara 	 */
10432c10cd43SMahesh Rajashekhara 	while (!((status = src_readl(dev, MUnit.OMR)) &
10442c10cd43SMahesh Rajashekhara 		KERNEL_UP_AND_RUNNING) ||
10452c10cd43SMahesh Rajashekhara 		status == 0xffffffff) {
104611604612SMahesh Rajashekhara 		if ((restart &&
104711604612SMahesh Rajashekhara 		  (status & (KERNEL_PANIC|SELF_TEST_FAILED|MONITOR_PANIC))) ||
104811604612SMahesh Rajashekhara 		  time_after(jiffies, start+HZ*startup_timeout)) {
104911604612SMahesh Rajashekhara 			printk(KERN_ERR "%s%d: adapter kernel failed to start, init status = %lx.\n",
105011604612SMahesh Rajashekhara 					dev->name, instance, status);
105111604612SMahesh Rajashekhara 			goto error_iounmap;
105211604612SMahesh Rajashekhara 		}
105311604612SMahesh Rajashekhara 		if (!restart &&
105411604612SMahesh Rajashekhara 		  ((status & (KERNEL_PANIC|SELF_TEST_FAILED|MONITOR_PANIC)) ||
105511604612SMahesh Rajashekhara 		  time_after(jiffies, start + HZ *
105611604612SMahesh Rajashekhara 		  ((startup_timeout > 60)
105711604612SMahesh Rajashekhara 		    ? (startup_timeout - 60)
105811604612SMahesh Rajashekhara 		    : (startup_timeout / 2))))) {
105931364329SRaghava Aditya Renukunta 			if (likely(!aac_src_restart_adapter(dev,
106031364329SRaghava Aditya Renukunta 				aac_src_check_health(dev), IOP_HWSOFT_RESET)))
106111604612SMahesh Rajashekhara 				start = jiffies;
106211604612SMahesh Rajashekhara 			++restart;
106311604612SMahesh Rajashekhara 		}
106411604612SMahesh Rajashekhara 		msleep(1);
106511604612SMahesh Rajashekhara 	}
106611604612SMahesh Rajashekhara 	if (restart && aac_commit)
106711604612SMahesh Rajashekhara 		aac_commit = 1;
106811604612SMahesh Rajashekhara 	/*
106911604612SMahesh Rajashekhara 	 *	Fill in the common function dispatch table.
107011604612SMahesh Rajashekhara 	 */
107111604612SMahesh Rajashekhara 	dev->a_ops.adapter_interrupt = aac_src_interrupt_adapter;
107211604612SMahesh Rajashekhara 	dev->a_ops.adapter_disable_int = aac_src_disable_interrupt;
1073dafde947SMahesh Rajashekhara 	dev->a_ops.adapter_enable_int = aac_src_disable_interrupt;
107411604612SMahesh Rajashekhara 	dev->a_ops.adapter_notify = aac_src_notify_adapter;
107511604612SMahesh Rajashekhara 	dev->a_ops.adapter_sync_cmd = src_sync_cmd;
107611604612SMahesh Rajashekhara 	dev->a_ops.adapter_check_health = aac_src_check_health;
107711604612SMahesh Rajashekhara 	dev->a_ops.adapter_restart = aac_src_restart_adapter;
1078de665f28SMahesh Rajashekhara 	dev->a_ops.adapter_start = aac_src_start_adapter;
107911604612SMahesh Rajashekhara 
108011604612SMahesh Rajashekhara 	/*
108111604612SMahesh Rajashekhara 	 *	First clear out all interrupts.  Then enable the one's that we
108211604612SMahesh Rajashekhara 	 *	can handle.
108311604612SMahesh Rajashekhara 	 */
108411604612SMahesh Rajashekhara 	aac_adapter_comm(dev, AAC_COMM_MESSAGE);
108511604612SMahesh Rajashekhara 	aac_adapter_disable_int(dev);
108611604612SMahesh Rajashekhara 	src_writel(dev, MUnit.ODR_C, 0xffffffff);
108711604612SMahesh Rajashekhara 	aac_adapter_enable_int(dev);
108811604612SMahesh Rajashekhara 
108911604612SMahesh Rajashekhara 	if (aac_init_adapter(dev) == NULL)
109011604612SMahesh Rajashekhara 		goto error_iounmap;
1091d1ef4da8SRaghava Aditya Renukunta 	if ((dev->comm_interface != AAC_COMM_MESSAGE_TYPE2) &&
1092d1ef4da8SRaghava Aditya Renukunta 		(dev->comm_interface != AAC_COMM_MESSAGE_TYPE3))
109311604612SMahesh Rajashekhara 		goto error_iounmap;
1094495c0217SMahesh Rajashekhara 	if (dev->msi_enabled)
1095495c0217SMahesh Rajashekhara 		aac_src_access_devreg(dev, AAC_ENABLE_MSIX);
1096495c0217SMahesh Rajashekhara 
10978b1462e0SMahesh Rajashekhara 	if (aac_acquire_irq(dev))
1098495c0217SMahesh Rajashekhara 		goto error_iounmap;
1099495c0217SMahesh Rajashekhara 
11003ffd6c5aSRaghava Aditya Renukunta 	dev->dbg_base = pci_resource_start(dev->pdev, 2);
11013ffd6c5aSRaghava Aditya Renukunta 	dev->dbg_base_mapped = dev->regs.src.bar1;
11023ffd6c5aSRaghava Aditya Renukunta 	dev->dbg_size = AAC_MIN_SRCV_BAR1_SIZE;
1103dafde947SMahesh Rajashekhara 	dev->a_ops.adapter_enable_int = aac_src_enable_interrupt_message;
110411604612SMahesh Rajashekhara 
110511604612SMahesh Rajashekhara 	aac_adapter_enable_int(dev);
110611604612SMahesh Rajashekhara 
110711604612SMahesh Rajashekhara 	if (!dev->sync_mode) {
110811604612SMahesh Rajashekhara 		/*
110911604612SMahesh Rajashekhara 		 * Tell the adapter that all is configured, and it can
111011604612SMahesh Rajashekhara 		 * start accepting requests
111111604612SMahesh Rajashekhara 		 */
111211604612SMahesh Rajashekhara 		aac_src_start_adapter(dev);
111311604612SMahesh Rajashekhara 	}
111411604612SMahesh Rajashekhara 	return 0;
111511604612SMahesh Rajashekhara 
111611604612SMahesh Rajashekhara error_iounmap:
111711604612SMahesh Rajashekhara 
111811604612SMahesh Rajashekhara 	return -1;
111911604612SMahesh Rajashekhara }
112011604612SMahesh Rajashekhara 
1121495c0217SMahesh Rajashekhara void aac_src_access_devreg(struct aac_dev *dev, int mode)
1122495c0217SMahesh Rajashekhara {
1123495c0217SMahesh Rajashekhara 	u_int32_t val;
1124495c0217SMahesh Rajashekhara 
1125495c0217SMahesh Rajashekhara 	switch (mode) {
1126495c0217SMahesh Rajashekhara 	case AAC_ENABLE_INTERRUPT:
1127495c0217SMahesh Rajashekhara 		src_writel(dev,
1128495c0217SMahesh Rajashekhara 			   MUnit.OIMR,
1129495c0217SMahesh Rajashekhara 			   dev->OIMR = (dev->msi_enabled ?
1130495c0217SMahesh Rajashekhara 					AAC_INT_ENABLE_TYPE1_MSIX :
1131495c0217SMahesh Rajashekhara 					AAC_INT_ENABLE_TYPE1_INTX));
1132495c0217SMahesh Rajashekhara 		break;
1133495c0217SMahesh Rajashekhara 
1134495c0217SMahesh Rajashekhara 	case AAC_DISABLE_INTERRUPT:
1135495c0217SMahesh Rajashekhara 		src_writel(dev,
1136495c0217SMahesh Rajashekhara 			   MUnit.OIMR,
1137495c0217SMahesh Rajashekhara 			   dev->OIMR = AAC_INT_DISABLE_ALL);
1138495c0217SMahesh Rajashekhara 		break;
1139495c0217SMahesh Rajashekhara 
1140495c0217SMahesh Rajashekhara 	case AAC_ENABLE_MSIX:
1141495c0217SMahesh Rajashekhara 		/* set bit 6 */
1142495c0217SMahesh Rajashekhara 		val = src_readl(dev, MUnit.IDR);
1143495c0217SMahesh Rajashekhara 		val |= 0x40;
1144495c0217SMahesh Rajashekhara 		src_writel(dev,  MUnit.IDR, val);
1145495c0217SMahesh Rajashekhara 		src_readl(dev, MUnit.IDR);
1146495c0217SMahesh Rajashekhara 		/* unmask int. */
1147495c0217SMahesh Rajashekhara 		val = PMC_ALL_INTERRUPT_BITS;
1148495c0217SMahesh Rajashekhara 		src_writel(dev, MUnit.IOAR, val);
1149495c0217SMahesh Rajashekhara 		val = src_readl(dev, MUnit.OIMR);
1150495c0217SMahesh Rajashekhara 		src_writel(dev,
1151495c0217SMahesh Rajashekhara 			   MUnit.OIMR,
1152495c0217SMahesh Rajashekhara 			   val & (~(PMC_GLOBAL_INT_BIT2 | PMC_GLOBAL_INT_BIT0)));
1153495c0217SMahesh Rajashekhara 		break;
1154495c0217SMahesh Rajashekhara 
1155495c0217SMahesh Rajashekhara 	case AAC_DISABLE_MSIX:
1156495c0217SMahesh Rajashekhara 		/* reset bit 6 */
1157495c0217SMahesh Rajashekhara 		val = src_readl(dev, MUnit.IDR);
1158495c0217SMahesh Rajashekhara 		val &= ~0x40;
1159495c0217SMahesh Rajashekhara 		src_writel(dev, MUnit.IDR, val);
1160495c0217SMahesh Rajashekhara 		src_readl(dev, MUnit.IDR);
1161495c0217SMahesh Rajashekhara 		break;
1162495c0217SMahesh Rajashekhara 
1163495c0217SMahesh Rajashekhara 	case AAC_CLEAR_AIF_BIT:
1164495c0217SMahesh Rajashekhara 		/* set bit 5 */
1165495c0217SMahesh Rajashekhara 		val = src_readl(dev, MUnit.IDR);
1166495c0217SMahesh Rajashekhara 		val |= 0x20;
1167495c0217SMahesh Rajashekhara 		src_writel(dev, MUnit.IDR, val);
1168495c0217SMahesh Rajashekhara 		src_readl(dev, MUnit.IDR);
1169495c0217SMahesh Rajashekhara 		break;
1170495c0217SMahesh Rajashekhara 
1171495c0217SMahesh Rajashekhara 	case AAC_CLEAR_SYNC_BIT:
1172495c0217SMahesh Rajashekhara 		/* set bit 4 */
1173495c0217SMahesh Rajashekhara 		val = src_readl(dev, MUnit.IDR);
1174495c0217SMahesh Rajashekhara 		val |= 0x10;
1175495c0217SMahesh Rajashekhara 		src_writel(dev, MUnit.IDR, val);
1176495c0217SMahesh Rajashekhara 		src_readl(dev, MUnit.IDR);
1177495c0217SMahesh Rajashekhara 		break;
1178495c0217SMahesh Rajashekhara 
1179495c0217SMahesh Rajashekhara 	case AAC_ENABLE_INTX:
1180495c0217SMahesh Rajashekhara 		/* set bit 7 */
1181495c0217SMahesh Rajashekhara 		val = src_readl(dev, MUnit.IDR);
1182495c0217SMahesh Rajashekhara 		val |= 0x80;
1183495c0217SMahesh Rajashekhara 		src_writel(dev, MUnit.IDR, val);
1184495c0217SMahesh Rajashekhara 		src_readl(dev, MUnit.IDR);
1185495c0217SMahesh Rajashekhara 		/* unmask int. */
1186495c0217SMahesh Rajashekhara 		val = PMC_ALL_INTERRUPT_BITS;
1187495c0217SMahesh Rajashekhara 		src_writel(dev, MUnit.IOAR, val);
1188495c0217SMahesh Rajashekhara 		src_readl(dev, MUnit.IOAR);
1189495c0217SMahesh Rajashekhara 		val = src_readl(dev, MUnit.OIMR);
1190495c0217SMahesh Rajashekhara 		src_writel(dev, MUnit.OIMR,
1191495c0217SMahesh Rajashekhara 				val & (~(PMC_GLOBAL_INT_BIT2)));
1192495c0217SMahesh Rajashekhara 		break;
1193495c0217SMahesh Rajashekhara 
1194495c0217SMahesh Rajashekhara 	default:
1195495c0217SMahesh Rajashekhara 		break;
1196495c0217SMahesh Rajashekhara 	}
1197495c0217SMahesh Rajashekhara }
1198495c0217SMahesh Rajashekhara 
1199495c0217SMahesh Rajashekhara static int aac_src_get_sync_status(struct aac_dev *dev)
1200495c0217SMahesh Rajashekhara {
1201495c0217SMahesh Rajashekhara 
1202495c0217SMahesh Rajashekhara 	int val;
1203495c0217SMahesh Rajashekhara 
1204495c0217SMahesh Rajashekhara 	if (dev->msi_enabled)
1205495c0217SMahesh Rajashekhara 		val = src_readl(dev, MUnit.ODR_MSI) & 0x1000 ? 1 : 0;
1206495c0217SMahesh Rajashekhara 	else
1207495c0217SMahesh Rajashekhara 		val = src_readl(dev, MUnit.ODR_R) >> SRC_ODR_SHIFT;
1208495c0217SMahesh Rajashekhara 
1209495c0217SMahesh Rajashekhara 	return val;
1210495c0217SMahesh Rajashekhara }
1211