src.c revision 101ae14edc14efb0fe6ed8a77ed370cca670ffc8
1/*
2 *	Adaptec AAC series RAID controller driver
3 *	(c) Copyright 2001 Red Hat Inc.
4 *
5 * based on the old aacraid driver that is..
6 * Adaptec aacraid device driver for Linux.
7 *
8 * Copyright (c) 2000-2010 Adaptec, Inc.
9 *               2010 PMC-Sierra, Inc. (aacraid@pmc-sierra.com)
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2, or (at your option)
14 * any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; see the file COPYING.  If not, write to
23 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 * Module Name:
26 *  src.c
27 *
28 * Abstract: Hardware Device Interface for PMC SRC based controllers
29 *
30 */
31
32#include <linux/kernel.h>
33#include <linux/init.h>
34#include <linux/types.h>
35#include <linux/pci.h>
36#include <linux/spinlock.h>
37#include <linux/slab.h>
38#include <linux/blkdev.h>
39#include <linux/delay.h>
40#include <linux/completion.h>
41#include <linux/time.h>
42#include <linux/interrupt.h>
43#include <scsi/scsi_host.h>
44
45#include "aacraid.h"
46
47static irqreturn_t aac_src_intr_message(int irq, void *dev_id)
48{
49	struct aac_dev *dev = dev_id;
50	unsigned long bellbits, bellbits_shifted;
51	int our_interrupt = 0;
52	int isFastResponse;
53	u32 index, handle;
54
55	bellbits = src_readl(dev, MUnit.ODR_R);
56	if (bellbits & PmDoorBellResponseSent) {
57		bellbits = PmDoorBellResponseSent;
58		/* handle async. status */
59		our_interrupt = 1;
60		index = dev->host_rrq_idx;
61		if (dev->host_rrq[index] == 0) {
62			u32 old_index = index;
63			/* adjust index */
64			do {
65				index++;
66				if (index == dev->scsi_host_ptr->can_queue +
67							AAC_NUM_MGT_FIB)
68					index = 0;
69				if (dev->host_rrq[index] != 0)
70					break;
71			} while (index != old_index);
72			dev->host_rrq_idx = index;
73		}
74		for (;;) {
75			isFastResponse = 0;
76			/* remove toggle bit (31) */
77			handle = (dev->host_rrq[index] & 0x7fffffff);
78			/* check fast response bit (30) */
79			if (handle & 0x40000000)
80				isFastResponse = 1;
81			handle &= 0x0000ffff;
82			if (handle == 0)
83				break;
84
85			aac_intr_normal(dev, handle-1, 0, isFastResponse, NULL);
86
87			dev->host_rrq[index++] = 0;
88			if (index == dev->scsi_host_ptr->can_queue +
89						AAC_NUM_MGT_FIB)
90				index = 0;
91			dev->host_rrq_idx = index;
92		}
93	} else {
94		bellbits_shifted = (bellbits >> SRC_ODR_SHIFT);
95		if (bellbits_shifted & DoorBellAifPending) {
96			our_interrupt = 1;
97			/* handle AIF */
98			aac_intr_normal(dev, 0, 2, 0, NULL);
99		}
100	}
101
102	if (our_interrupt) {
103		src_writel(dev, MUnit.ODR_C, bellbits);
104		return IRQ_HANDLED;
105	}
106	return IRQ_NONE;
107}
108
109/**
110 *	aac_src_disable_interrupt	-	Disable interrupts
111 *	@dev: Adapter
112 */
113
114static void aac_src_disable_interrupt(struct aac_dev *dev)
115{
116	src_writel(dev, MUnit.OIMR, dev->OIMR = 0xffffffff);
117}
118
119/**
120 *	aac_src_enable_interrupt_message	-	Enable interrupts
121 *	@dev: Adapter
122 */
123
124static void aac_src_enable_interrupt_message(struct aac_dev *dev)
125{
126	src_writel(dev, MUnit.OIMR, dev->OIMR = 0xfffffff8);
127}
128
129/**
130 *	src_sync_cmd	-	send a command and wait
131 *	@dev: Adapter
132 *	@command: Command to execute
133 *	@p1: first parameter
134 *	@ret: adapter status
135 *
136 *	This routine will send a synchronous command to the adapter and wait
137 *	for its	completion.
138 */
139
140static int src_sync_cmd(struct aac_dev *dev, u32 command,
141	u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6,
142	u32 *status, u32 * r1, u32 * r2, u32 * r3, u32 * r4)
143{
144	unsigned long start;
145	int ok;
146
147	/*
148	 *	Write the command into Mailbox 0
149	 */
150	writel(command, &dev->IndexRegs->Mailbox[0]);
151	/*
152	 *	Write the parameters into Mailboxes 1 - 6
153	 */
154	writel(p1, &dev->IndexRegs->Mailbox[1]);
155	writel(p2, &dev->IndexRegs->Mailbox[2]);
156	writel(p3, &dev->IndexRegs->Mailbox[3]);
157	writel(p4, &dev->IndexRegs->Mailbox[4]);
158
159	/*
160	 *	Clear the synch command doorbell to start on a clean slate.
161	 */
162	src_writel(dev, MUnit.ODR_C, OUTBOUNDDOORBELL_0 << SRC_ODR_SHIFT);
163
164	/*
165	 *	Disable doorbell interrupts
166	 */
167	src_writel(dev, MUnit.OIMR, dev->OIMR = 0xffffffff);
168
169	/*
170	 *	Force the completion of the mask register write before issuing
171	 *	the interrupt.
172	 */
173	src_readl(dev, MUnit.OIMR);
174
175	/*
176	 *	Signal that there is a new synch command
177	 */
178	src_writel(dev, MUnit.IDR, INBOUNDDOORBELL_0 << SRC_IDR_SHIFT);
179
180	ok = 0;
181	start = jiffies;
182
183	/*
184	 *	Wait up to 30 seconds
185	 */
186	while (time_before(jiffies, start+30*HZ)) {
187		/* Delay 5 microseconds to let Mon960 get info. */
188		udelay(5);
189
190		/* Mon960 will set doorbell0 bit
191		 * when it has completed the command
192		 */
193		if ((src_readl(dev, MUnit.ODR_R) >> SRC_ODR_SHIFT) & OUTBOUNDDOORBELL_0) {
194			/* Clear the doorbell */
195			src_writel(dev,
196				MUnit.ODR_C,
197				OUTBOUNDDOORBELL_0 << SRC_ODR_SHIFT);
198			ok = 1;
199			break;
200		}
201
202		 /* Yield the processor in case we are slow */
203		msleep(1);
204	}
205	if (unlikely(ok != 1)) {
206		 /* Restore interrupt mask even though we timed out */
207		aac_adapter_enable_int(dev);
208		return -ETIMEDOUT;
209	}
210
211	 /* Pull the synch status from Mailbox 0 */
212	if (status)
213		*status = readl(&dev->IndexRegs->Mailbox[0]);
214	if (r1)
215		*r1 = readl(&dev->IndexRegs->Mailbox[1]);
216	if (r2)
217		*r2 = readl(&dev->IndexRegs->Mailbox[2]);
218	if (r3)
219		*r3 = readl(&dev->IndexRegs->Mailbox[3]);
220	if (r4)
221		*r4 = readl(&dev->IndexRegs->Mailbox[4]);
222
223	 /* Clear the synch command doorbell */
224	src_writel(dev, MUnit.ODR_C, OUTBOUNDDOORBELL_0 << SRC_ODR_SHIFT);
225
226	 /* Restore interrupt mask */
227	aac_adapter_enable_int(dev);
228	return 0;
229
230}
231
232/**
233 *	aac_src_interrupt_adapter	-	interrupt adapter
234 *	@dev: Adapter
235 *
236 *	Send an interrupt to the i960 and breakpoint it.
237 */
238
239static void aac_src_interrupt_adapter(struct aac_dev *dev)
240{
241	src_sync_cmd(dev, BREAKPOINT_REQUEST,
242		0, 0, 0, 0, 0, 0,
243		NULL, NULL, NULL, NULL, NULL);
244}
245
246/**
247 *	aac_src_notify_adapter		-	send an event to the adapter
248 *	@dev: Adapter
249 *	@event: Event to send
250 *
251 *	Notify the i960 that something it probably cares about has
252 *	happened.
253 */
254
255static void aac_src_notify_adapter(struct aac_dev *dev, u32 event)
256{
257	switch (event) {
258
259	case AdapNormCmdQue:
260		src_writel(dev, MUnit.ODR_C,
261			INBOUNDDOORBELL_1 << SRC_ODR_SHIFT);
262		break;
263	case HostNormRespNotFull:
264		src_writel(dev, MUnit.ODR_C,
265			INBOUNDDOORBELL_4 << SRC_ODR_SHIFT);
266		break;
267	case AdapNormRespQue:
268		src_writel(dev, MUnit.ODR_C,
269			INBOUNDDOORBELL_2 << SRC_ODR_SHIFT);
270		break;
271	case HostNormCmdNotFull:
272		src_writel(dev, MUnit.ODR_C,
273			INBOUNDDOORBELL_3 << SRC_ODR_SHIFT);
274		break;
275	case FastIo:
276		src_writel(dev, MUnit.ODR_C,
277			INBOUNDDOORBELL_6 << SRC_ODR_SHIFT);
278		break;
279	case AdapPrintfDone:
280		src_writel(dev, MUnit.ODR_C,
281			INBOUNDDOORBELL_5 << SRC_ODR_SHIFT);
282		break;
283	default:
284		BUG();
285		break;
286	}
287}
288
289/**
290 *	aac_src_start_adapter		-	activate adapter
291 *	@dev:	Adapter
292 *
293 *	Start up processing on an i960 based AAC adapter
294 */
295
296static void aac_src_start_adapter(struct aac_dev *dev)
297{
298	struct aac_init *init;
299
300	init = dev->init;
301	init->HostElapsedSeconds = cpu_to_le32(get_seconds());
302
303	/* We can only use a 32 bit address here */
304	src_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (u32)(ulong)dev->init_pa,
305	  0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL);
306}
307
308/**
309 *	aac_src_check_health
310 *	@dev: device to check if healthy
311 *
312 *	Will attempt to determine if the specified adapter is alive and
313 *	capable of handling requests, returning 0 if alive.
314 */
315static int aac_src_check_health(struct aac_dev *dev)
316{
317	u32 status = src_readl(dev, MUnit.OMR);
318
319	/*
320	 *	Check to see if the board failed any self tests.
321	 */
322	if (unlikely(status & SELF_TEST_FAILED))
323		return -1;
324
325	/*
326	 *	Check to see if the board panic'd.
327	 */
328	if (unlikely(status & KERNEL_PANIC))
329		return (status >> 16) & 0xFF;
330	/*
331	 *	Wait for the adapter to be up and running.
332	 */
333	if (unlikely(!(status & KERNEL_UP_AND_RUNNING)))
334		return -3;
335	/*
336	 *	Everything is OK
337	 */
338	return 0;
339}
340
341/**
342 *	aac_src_deliver_message
343 *	@fib: fib to issue
344 *
345 *	Will send a fib, returning 0 if successful.
346 */
347static int aac_src_deliver_message(struct fib *fib)
348{
349	struct aac_dev *dev = fib->dev;
350	struct aac_queue *q = &dev->queues->queue[AdapNormCmdQueue];
351	unsigned long qflags;
352	u32 fibsize;
353	u64 address;
354	struct aac_fib_xporthdr *pFibX;
355
356	spin_lock_irqsave(q->lock, qflags);
357	q->numpending++;
358	spin_unlock_irqrestore(q->lock, qflags);
359
360	/* Calculate the amount to the fibsize bits */
361	fibsize = (sizeof(struct aac_fib_xporthdr) +
362		fib->hw_fib_va->header.Size + 127) / 128 - 1;
363	if (fibsize > (ALIGN32 - 1))
364		fibsize = ALIGN32 - 1;
365
366    /* Fill XPORT header */
367	pFibX = (struct aac_fib_xporthdr *)
368		((unsigned char *)fib->hw_fib_va -
369		sizeof(struct aac_fib_xporthdr));
370	pFibX->Handle = fib->hw_fib_va->header.SenderData + 1;
371	pFibX->HostAddress = fib->hw_fib_pa;
372	pFibX->Size = fib->hw_fib_va->header.Size;
373	address = fib->hw_fib_pa - (u64)sizeof(struct aac_fib_xporthdr);
374
375	src_writel(dev, MUnit.IQ_H, (u32)(address >> 32));
376	src_writel(dev, MUnit.IQ_L, (u32)(address & 0xffffffff) + fibsize);
377	return 0;
378}
379
380/**
381 *	aac_src_ioremap
382 *	@size: mapping resize request
383 *
384 */
385static int aac_src_ioremap(struct aac_dev *dev, u32 size)
386{
387	if (!size) {
388		iounmap(dev->regs.src.bar0);
389		dev->regs.src.bar0 = NULL;
390		iounmap(dev->base);
391		dev->base = NULL;
392		return 0;
393	}
394	dev->regs.src.bar1 = ioremap(pci_resource_start(dev->pdev, 2),
395		AAC_MIN_SRC_BAR1_SIZE);
396	dev->base = NULL;
397	if (dev->regs.src.bar1 == NULL)
398		return -1;
399	dev->base = dev->regs.src.bar0 = ioremap(dev->scsi_host_ptr->base,
400				size);
401	if (dev->base == NULL) {
402		iounmap(dev->regs.src.bar1);
403		dev->regs.src.bar1 = NULL;
404		return -1;
405	}
406	dev->IndexRegs = &((struct src_registers __iomem *)
407		dev->base)->IndexRegs;
408	return 0;
409}
410
411static int aac_src_restart_adapter(struct aac_dev *dev, int bled)
412{
413	u32 var, reset_mask;
414
415	if (bled >= 0) {
416		if (bled)
417			printk(KERN_ERR "%s%d: adapter kernel panic'd %x.\n",
418				dev->name, dev->id, bled);
419		bled = aac_adapter_sync_cmd(dev, IOP_RESET_ALWAYS,
420			0, 0, 0, 0, 0, 0, &var, &reset_mask, NULL, NULL, NULL);
421			if (bled || (var != 0x00000001))
422				bled = -EINVAL;
423		if (dev->supplement_adapter_info.SupportedOptions2 &
424			AAC_OPTION_DOORBELL_RESET) {
425			src_writel(dev, MUnit.IDR, reset_mask);
426			msleep(5000); /* Delay 5 seconds */
427		}
428	}
429
430	if (src_readl(dev, MUnit.OMR) & KERNEL_PANIC)
431		return -ENODEV;
432
433	if (startup_timeout < 300)
434		startup_timeout = 300;
435
436	return 0;
437}
438
439/**
440 *	aac_src_select_comm	-	Select communications method
441 *	@dev: Adapter
442 *	@comm: communications method
443 */
444int aac_src_select_comm(struct aac_dev *dev, int comm)
445{
446	switch (comm) {
447	case AAC_COMM_MESSAGE:
448		dev->a_ops.adapter_enable_int = aac_src_enable_interrupt_message;
449		dev->a_ops.adapter_intr = aac_src_intr_message;
450		dev->a_ops.adapter_deliver = aac_src_deliver_message;
451		break;
452	default:
453		return 1;
454	}
455	return 0;
456}
457
458/**
459 *  aac_src_init	-	initialize an Cardinal Frey Bar card
460 *  @dev: device to configure
461 *
462 */
463
464int aac_src_init(struct aac_dev *dev)
465{
466	unsigned long start;
467	unsigned long status;
468	int restart = 0;
469	int instance = dev->id;
470	const char *name = dev->name;
471
472	dev->a_ops.adapter_ioremap = aac_src_ioremap;
473	dev->a_ops.adapter_comm = aac_src_select_comm;
474
475	dev->base_size = AAC_MIN_SRC_BAR0_SIZE;
476	if (aac_adapter_ioremap(dev, dev->base_size)) {
477		printk(KERN_WARNING "%s: unable to map adapter.\n", name);
478		goto error_iounmap;
479	}
480
481	/* Failure to reset here is an option ... */
482	dev->a_ops.adapter_sync_cmd = src_sync_cmd;
483	dev->a_ops.adapter_enable_int = aac_src_disable_interrupt;
484	if ((aac_reset_devices || reset_devices) &&
485		!aac_src_restart_adapter(dev, 0))
486		++restart;
487	/*
488	 *	Check to see if the board panic'd while booting.
489	 */
490	status = src_readl(dev, MUnit.OMR);
491	if (status & KERNEL_PANIC) {
492		if (aac_src_restart_adapter(dev, aac_src_check_health(dev)))
493			goto error_iounmap;
494		++restart;
495	}
496	/*
497	 *	Check to see if the board failed any self tests.
498	 */
499	status = src_readl(dev, MUnit.OMR);
500	if (status & SELF_TEST_FAILED) {
501		printk(KERN_ERR "%s%d: adapter self-test failed.\n",
502			dev->name, instance);
503		goto error_iounmap;
504	}
505	/*
506	 *	Check to see if the monitor panic'd while booting.
507	 */
508	if (status & MONITOR_PANIC) {
509		printk(KERN_ERR "%s%d: adapter monitor panic.\n",
510			dev->name, instance);
511		goto error_iounmap;
512	}
513	start = jiffies;
514	/*
515	 *	Wait for the adapter to be up and running. Wait up to 3 minutes
516	 */
517	while (!((status = src_readl(dev, MUnit.OMR)) &
518		KERNEL_UP_AND_RUNNING)) {
519		if ((restart &&
520		  (status & (KERNEL_PANIC|SELF_TEST_FAILED|MONITOR_PANIC))) ||
521		  time_after(jiffies, start+HZ*startup_timeout)) {
522			printk(KERN_ERR "%s%d: adapter kernel failed to start, init status = %lx.\n",
523					dev->name, instance, status);
524			goto error_iounmap;
525		}
526		if (!restart &&
527		  ((status & (KERNEL_PANIC|SELF_TEST_FAILED|MONITOR_PANIC)) ||
528		  time_after(jiffies, start + HZ *
529		  ((startup_timeout > 60)
530		    ? (startup_timeout - 60)
531		    : (startup_timeout / 2))))) {
532			if (likely(!aac_src_restart_adapter(dev,
533			    aac_src_check_health(dev))))
534				start = jiffies;
535			++restart;
536		}
537		msleep(1);
538	}
539	if (restart && aac_commit)
540		aac_commit = 1;
541	/*
542	 *	Fill in the common function dispatch table.
543	 */
544	dev->a_ops.adapter_interrupt = aac_src_interrupt_adapter;
545	dev->a_ops.adapter_disable_int = aac_src_disable_interrupt;
546	dev->a_ops.adapter_notify = aac_src_notify_adapter;
547	dev->a_ops.adapter_sync_cmd = src_sync_cmd;
548	dev->a_ops.adapter_check_health = aac_src_check_health;
549	dev->a_ops.adapter_restart = aac_src_restart_adapter;
550
551	/*
552	 *	First clear out all interrupts.  Then enable the one's that we
553	 *	can handle.
554	 */
555	aac_adapter_comm(dev, AAC_COMM_MESSAGE);
556	aac_adapter_disable_int(dev);
557	src_writel(dev, MUnit.ODR_C, 0xffffffff);
558	aac_adapter_enable_int(dev);
559
560	if (aac_init_adapter(dev) == NULL)
561		goto error_iounmap;
562	if (dev->comm_interface != AAC_COMM_MESSAGE_TYPE1)
563		goto error_iounmap;
564
565	dev->msi = aac_msi && !pci_enable_msi(dev->pdev);
566
567	if (request_irq(dev->pdev->irq, dev->a_ops.adapter_intr,
568			IRQF_SHARED|IRQF_DISABLED, "aacraid", dev) < 0) {
569
570		if (dev->msi)
571			pci_disable_msi(dev->pdev);
572
573		printk(KERN_ERR "%s%d: Interrupt unavailable.\n",
574			name, instance);
575		goto error_iounmap;
576	}
577	dev->dbg_base = pci_resource_start(dev->pdev, 2);
578	dev->dbg_base_mapped = dev->regs.src.bar1;
579	dev->dbg_size = AAC_MIN_SRC_BAR1_SIZE;
580
581	aac_adapter_enable_int(dev);
582	/*
583	 *	Tell the adapter that all is configured, and it can
584	 * start accepting requests
585	 */
586	aac_src_start_adapter(dev);
587
588	return 0;
589
590error_iounmap:
591
592	return -1;
593}
594