Blame view

drivers/scsi/aacraid/rx.c 16.9 KB
c82ee6d3b   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-or-later
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
3
  /*
   *	Adaptec AAC series RAID controller driver
fa195afe4   Alan Cox   [SCSI] Clean up m...
4
   *	(c) Copyright 2001 Red Hat Inc.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5
6
7
8
   *
   * based on the old aacraid driver that is..
   * Adaptec aacraid device driver for Linux.
   *
e8b12f0fb   Mahesh Rajashekhara   [SCSI] aacraid: A...
9
   * Copyright (c) 2000-2010 Adaptec, Inc.
f4babba0a   Raghava Aditya Renukunta   scsi: aacraid: Up...
10
11
   *               2010-2015 PMC-Sierra, Inc. (aacraid@pmc-sierra.com)
   *		 2016-2017 Microsemi Corp. (aacraid@microsemi.com)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
12
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
13
14
15
16
   * Module Name:
   *  rx.c
   *
   * Abstract: Hardware miniport for Drawbridge specific hardware functions.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
17
18
19
20
21
   */
  
  #include <linux/kernel.h>
  #include <linux/init.h>
  #include <linux/types.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
22
23
  #include <linux/pci.h>
  #include <linux/spinlock.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
24
25
26
27
28
  #include <linux/blkdev.h>
  #include <linux/delay.h>
  #include <linux/completion.h>
  #include <linux/time.h>
  #include <linux/interrupt.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
29
30
31
32
  
  #include <scsi/scsi_host.h>
  
  #include "aacraid.h"
28713324a   Mark Haverkamp   [SCSI] aacraid: r...
33
  static irqreturn_t aac_rx_intr_producer(int irq, void *dev_id)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34
35
  {
  	struct aac_dev *dev = dev_id;
28713324a   Mark Haverkamp   [SCSI] aacraid: r...
36
37
  	unsigned long bellbits;
  	u8 intstat = rx_readb(dev, MUnit.OISR);
8e0c5ebde   Mark Haverkamp   [SCSI] aacraid: N...
38

28713324a   Mark Haverkamp   [SCSI] aacraid: r...
39
40
41
42
43
44
  	/*
  	 *	Read mask and invert because drawbridge is reversed.
  	 *	This allows us to only service interrupts that have
  	 *	been enabled.
  	 *	Check to see if this is our interrupt.  If it isn't just return
  	 */
912d4e885   Salyzyn, Mark   [SCSI] aacraid: A...
45
  	if (likely(intstat & ~(dev->OIMR))) {
28713324a   Mark Haverkamp   [SCSI] aacraid: r...
46
  		bellbits = rx_readl(dev, OutboundDoorbellReg);
912d4e885   Salyzyn, Mark   [SCSI] aacraid: A...
47
  		if (unlikely(bellbits & DoorBellPrintfReady)) {
28713324a   Mark Haverkamp   [SCSI] aacraid: r...
48
49
50
  			aac_printf(dev, readl (&dev->IndexRegs->Mailbox[5]));
  			rx_writel(dev, MUnit.ODR,DoorBellPrintfReady);
  			rx_writel(dev, InboundDoorbellReg,DoorBellPrintfDone);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
51
  		}
912d4e885   Salyzyn, Mark   [SCSI] aacraid: A...
52
  		else if (unlikely(bellbits & DoorBellAdapterNormCmdReady)) {
28713324a   Mark Haverkamp   [SCSI] aacraid: r...
53
54
55
  			rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdReady);
  			aac_command_normal(&dev->queues->queue[HostNormCmdQueue]);
  		}
912d4e885   Salyzyn, Mark   [SCSI] aacraid: A...
56
  		else if (likely(bellbits & DoorBellAdapterNormRespReady)) {
28713324a   Mark Haverkamp   [SCSI] aacraid: r...
57
58
59
  			rx_writel(dev, MUnit.ODR,DoorBellAdapterNormRespReady);
  			aac_response_normal(&dev->queues->queue[HostNormRespQueue]);
  		}
912d4e885   Salyzyn, Mark   [SCSI] aacraid: A...
60
  		else if (unlikely(bellbits & DoorBellAdapterNormCmdNotFull)) {
28713324a   Mark Haverkamp   [SCSI] aacraid: r...
61
  			rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
62
  		}
912d4e885   Salyzyn, Mark   [SCSI] aacraid: A...
63
  		else if (unlikely(bellbits & DoorBellAdapterNormRespNotFull)) {
28713324a   Mark Haverkamp   [SCSI] aacraid: r...
64
65
66
67
68
69
70
71
72
73
  			rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull);
  			rx_writel(dev, MUnit.ODR, DoorBellAdapterNormRespNotFull);
  		}
  		return IRQ_HANDLED;
  	}
  	return IRQ_NONE;
  }
  
  static irqreturn_t aac_rx_intr_message(int irq, void *dev_id)
  {
e8b12f0fb   Mahesh Rajashekhara   [SCSI] aacraid: A...
74
  	int isAif, isFastResponse, isSpecial;
28713324a   Mark Haverkamp   [SCSI] aacraid: r...
75
76
  	struct aac_dev *dev = dev_id;
  	u32 Index = rx_readl(dev, MUnit.OutboundQueue);
912d4e885   Salyzyn, Mark   [SCSI] aacraid: A...
77
  	if (unlikely(Index == 0xFFFFFFFFL))
28713324a   Mark Haverkamp   [SCSI] aacraid: r...
78
  		Index = rx_readl(dev, MUnit.OutboundQueue);
912d4e885   Salyzyn, Mark   [SCSI] aacraid: A...
79
  	if (likely(Index != 0xFFFFFFFFL)) {
28713324a   Mark Haverkamp   [SCSI] aacraid: r...
80
  		do {
e8b12f0fb   Mahesh Rajashekhara   [SCSI] aacraid: A...
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
  			isAif = isFastResponse = isSpecial = 0;
  			if (Index & 0x00000002L) {
  				isAif = 1;
  				if (Index == 0xFFFFFFFEL)
  					isSpecial = 1;
  				Index &= ~0x00000002L;
  			} else {
  				if (Index & 0x00000001L)
  					isFastResponse = 1;
  				Index >>= 2;
  			}
  			if (!isSpecial) {
  				if (unlikely(aac_intr_normal(dev,
  						Index, isAif,
  						isFastResponse, NULL))) {
  					rx_writel(dev,
  						MUnit.OutboundQueue,
  						Index);
  					rx_writel(dev,
  						MUnit.ODR,
  						DoorBellAdapterNormRespReady);
  				}
28713324a   Mark Haverkamp   [SCSI] aacraid: r...
103
104
105
106
  			}
  			Index = rx_readl(dev, MUnit.OutboundQueue);
  		} while (Index != 0xFFFFFFFFL);
  		return IRQ_HANDLED;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
107
108
109
110
111
  	}
  	return IRQ_NONE;
  }
  
  /**
bd1aac809   Mark Haverkamp   [SCSI] aacraid: d...
112
113
114
115
116
117
118
119
120
121
   *	aac_rx_disable_interrupt	-	Disable interrupts
   *	@dev: Adapter
   */
  
  static void aac_rx_disable_interrupt(struct aac_dev *dev)
  {
  	rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff);
  }
  
  /**
28713324a   Mark Haverkamp   [SCSI] aacraid: r...
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
   *	aac_rx_enable_interrupt_producer	-	Enable interrupts
   *	@dev: Adapter
   */
  
  static void aac_rx_enable_interrupt_producer(struct aac_dev *dev)
  {
  	rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb);
  }
  
  /**
   *	aac_rx_enable_interrupt_message	-	Enable interrupts
   *	@dev: Adapter
   */
  
  static void aac_rx_enable_interrupt_message(struct aac_dev *dev)
  {
  	rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xf7);
  }
  
  /**
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
142
143
144
145
146
147
148
149
150
   *	rx_sync_cmd	-	send a command and wait
   *	@dev: Adapter
   *	@command: Command to execute
   *	@p1: first parameter
   *	@ret: adapter status
   *
   *	This routine will send a synchronous command to the adapter and wait 
   *	for its	completion.
   */
7c00ffa31   Mark Haverkamp   [SCSI] 2.6 aacrai...
151
152
153
  static int rx_sync_cmd(struct aac_dev *dev, u32 command,
  	u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6,
  	u32 *status, u32 * r1, u32 * r2, u32 * r3, u32 * r4)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
154
155
156
157
158
159
  {
  	unsigned long start;
  	int ok;
  	/*
  	 *	Write the command into Mailbox 0
  	 */
76a7f8fdc   Mark Haverkamp   [SCSI] aacraid: m...
160
  	writel(command, &dev->IndexRegs->Mailbox[0]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
161
  	/*
7c00ffa31   Mark Haverkamp   [SCSI] 2.6 aacrai...
162
  	 *	Write the parameters into Mailboxes 1 - 6
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
163
  	 */
76a7f8fdc   Mark Haverkamp   [SCSI] aacraid: m...
164
165
166
167
  	writel(p1, &dev->IndexRegs->Mailbox[1]);
  	writel(p2, &dev->IndexRegs->Mailbox[2]);
  	writel(p3, &dev->IndexRegs->Mailbox[3]);
  	writel(p4, &dev->IndexRegs->Mailbox[4]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
168
169
170
171
172
173
174
  	/*
  	 *	Clear the synch command doorbell to start on a clean slate.
  	 */
  	rx_writel(dev, OutboundDoorbellReg, OUTBOUNDDOORBELL_0);
  	/*
  	 *	Disable doorbell interrupts
  	 */
7c00ffa31   Mark Haverkamp   [SCSI] 2.6 aacrai...
175
  	rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
  	/*
  	 *	Force the completion of the mask register write before issuing
  	 *	the interrupt.
  	 */
  	rx_readb (dev, MUnit.OIMR);
  	/*
  	 *	Signal that there is a new synch command
  	 */
  	rx_writel(dev, InboundDoorbellReg, INBOUNDDOORBELL_0);
  
  	ok = 0;
  	start = jiffies;
  
  	/*
  	 *	Wait up to 30 seconds
  	 */
  	while (time_before(jiffies, start+30*HZ)) 
  	{
  		udelay(5);	/* Delay 5 microseconds to let Mon960 get info. */
  		/*
  		 *	Mon960 will set doorbell0 bit when it has completed the command.
  		 */
  		if (rx_readl(dev, OutboundDoorbellReg) & OUTBOUNDDOORBELL_0) {
  			/*
  			 *	Clear the doorbell.
  			 */
  			rx_writel(dev, OutboundDoorbellReg, OUTBOUNDDOORBELL_0);
  			ok = 1;
  			break;
  		}
  		/*
  		 *	Yield the processor in case we are slow 
  		 */
1241f3593   Mark Haverkamp   [SCSI] aacraid: G...
209
  		msleep(1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
210
  	}
912d4e885   Salyzyn, Mark   [SCSI] aacraid: A...
211
  	if (unlikely(ok != 1)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
212
213
214
  		/*
  		 *	Restore interrupt mask even though we timed out
  		 */
28713324a   Mark Haverkamp   [SCSI] aacraid: r...
215
  		aac_adapter_enable_int(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
216
217
218
219
220
221
  		return -ETIMEDOUT;
  	}
  	/*
  	 *	Pull the synch status from Mailbox 0.
  	 */
  	if (status)
76a7f8fdc   Mark Haverkamp   [SCSI] aacraid: m...
222
  		*status = readl(&dev->IndexRegs->Mailbox[0]);
7c00ffa31   Mark Haverkamp   [SCSI] 2.6 aacrai...
223
  	if (r1)
76a7f8fdc   Mark Haverkamp   [SCSI] aacraid: m...
224
  		*r1 = readl(&dev->IndexRegs->Mailbox[1]);
7c00ffa31   Mark Haverkamp   [SCSI] 2.6 aacrai...
225
  	if (r2)
76a7f8fdc   Mark Haverkamp   [SCSI] aacraid: m...
226
  		*r2 = readl(&dev->IndexRegs->Mailbox[2]);
7c00ffa31   Mark Haverkamp   [SCSI] 2.6 aacrai...
227
  	if (r3)
76a7f8fdc   Mark Haverkamp   [SCSI] aacraid: m...
228
  		*r3 = readl(&dev->IndexRegs->Mailbox[3]);
7c00ffa31   Mark Haverkamp   [SCSI] 2.6 aacrai...
229
  	if (r4)
76a7f8fdc   Mark Haverkamp   [SCSI] aacraid: m...
230
  		*r4 = readl(&dev->IndexRegs->Mailbox[4]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
231
232
233
234
235
236
237
  	/*
  	 *	Clear the synch command doorbell.
  	 */
  	rx_writel(dev, OutboundDoorbellReg, OUTBOUNDDOORBELL_0);
  	/*
  	 *	Restore interrupt mask
  	 */
28713324a   Mark Haverkamp   [SCSI] aacraid: r...
238
  	aac_adapter_enable_int(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
239
240
241
242
243
244
245
246
247
248
249
250
251
  	return 0;
  
  }
  
  /**
   *	aac_rx_interrupt_adapter	-	interrupt adapter
   *	@dev: Adapter
   *
   *	Send an interrupt to the i960 and breakpoint it.
   */
  
  static void aac_rx_interrupt_adapter(struct aac_dev *dev)
  {
7c00ffa31   Mark Haverkamp   [SCSI] 2.6 aacrai...
252
  	rx_sync_cmd(dev, BREAKPOINT_REQUEST, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
  }
  
  /**
   *	aac_rx_notify_adapter		-	send an event to the adapter
   *	@dev: Adapter
   *	@event: Event to send
   *
   *	Notify the i960 that something it probably cares about has
   *	happened.
   */
  
  static void aac_rx_notify_adapter(struct aac_dev *dev, u32 event)
  {
  	switch (event) {
  
  	case AdapNormCmdQue:
  		rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_1);
  		break;
  	case HostNormRespNotFull:
  		rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_4);
  		break;
  	case AdapNormRespQue:
  		rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_2);
  		break;
  	case HostNormCmdNotFull:
  		rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_3);
  		break;
  	case HostShutdown:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
  		break;
  	case FastIo:
  		rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_6);
  		break;
  	case AdapPrintfDone:
  		rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_5);
  		break;
  	default:
  		BUG();
  		break;
  	}
  }
  
  /**
   *	aac_rx_start_adapter		-	activate adapter
   *	@dev:	Adapter
   *
   *	Start up processing on an i960 based AAC adapter
   */
9695a25db   Adrian Bunk   [SCSI] aacraid: c...
300
  static void aac_rx_start_adapter(struct aac_dev *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
301
  {
d1ef4da84   Raghava Aditya Renukunta   scsi: aacraid: ad...
302
  	union aac_init *init;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
303
304
  
  	init = dev->init;
38150f7a6   Arnd Bergmann   scsi: aacraid: st...
305
  	init->r7.host_elapsed_seconds = cpu_to_le32(ktime_get_real_seconds());
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
306
  	// We can only use a 32 bit address here
7c00ffa31   Mark Haverkamp   [SCSI] 2.6 aacrai...
307
308
  	rx_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (u32)(ulong)dev->init_pa,
  	  0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
  }
  
  /**
   *	aac_rx_check_health
   *	@dev: device to check if healthy
   *
   *	Will attempt to determine if the specified adapter is alive and
   *	capable of handling requests, returning 0 if alive.
   */
  static int aac_rx_check_health(struct aac_dev *dev)
  {
  	u32 status = rx_readl(dev, MUnit.OMRx[0]);
  
  	/*
  	 *	Check to see if the board failed any self tests.
  	 */
912d4e885   Salyzyn, Mark   [SCSI] aacraid: A...
325
  	if (unlikely(status & SELF_TEST_FAILED))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
326
327
328
329
  		return -1;
  	/*
  	 *	Check to see if the board panic'd.
  	 */
912d4e885   Salyzyn, Mark   [SCSI] aacraid: A...
330
  	if (unlikely(status & KERNEL_PANIC)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
331
332
  		char * buffer;
  		struct POSTSTATUS {
56b587122   Mark Haverkamp   [SCSI] aacraid: r...
333
334
  			__le32 Post_Command;
  			__le32 Post_Address;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
335
336
337
  		} * post;
  		dma_addr_t paddr, baddr;
  		int ret;
912d4e885   Salyzyn, Mark   [SCSI] aacraid: A...
338
  		if (likely((status & 0xFF000000L) == 0xBC000000L))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
339
  			return (status >> 16) & 0xFF;
f481973d5   Mahesh Rajashekhara   scsi: aacraid: pc...
340
341
  		buffer = dma_alloc_coherent(&dev->pdev->dev, 512, &baddr,
  					    GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
342
  		ret = -2;
912d4e885   Salyzyn, Mark   [SCSI] aacraid: A...
343
  		if (unlikely(buffer == NULL))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
344
  			return ret;
f481973d5   Mahesh Rajashekhara   scsi: aacraid: pc...
345
346
347
  		post = dma_alloc_coherent(&dev->pdev->dev,
  					  sizeof(struct POSTSTATUS), &paddr,
  					  GFP_KERNEL);
912d4e885   Salyzyn, Mark   [SCSI] aacraid: A...
348
  		if (unlikely(post == NULL)) {
f481973d5   Mahesh Rajashekhara   scsi: aacraid: pc...
349
  			dma_free_coherent(&dev->pdev->dev, 512, buffer, baddr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
350
351
352
353
354
355
  			return ret;
  		}
  		memset(buffer, 0, 512);
  		post->Post_Command = cpu_to_le32(COMMAND_POST_RESULTS);
  		post->Post_Address = cpu_to_le32(baddr);
  		rx_writel(dev, MUnit.IMRx[0], paddr);
7c00ffa31   Mark Haverkamp   [SCSI] 2.6 aacrai...
356
357
  		rx_sync_cmd(dev, COMMAND_POST_RESULTS, baddr, 0, 0, 0, 0, 0,
  		  NULL, NULL, NULL, NULL, NULL);
f481973d5   Mahesh Rajashekhara   scsi: aacraid: pc...
358
359
  		dma_free_coherent(&dev->pdev->dev, sizeof(struct POSTSTATUS),
  				  post, paddr);
912d4e885   Salyzyn, Mark   [SCSI] aacraid: A...
360
  		if (likely((buffer[0] == '0') && ((buffer[1] == 'x') || (buffer[1] == 'X')))) {
ecc309900   Andy Shevchenko   drivers: scsi: us...
361
362
  			ret = (hex_to_bin(buffer[2]) << 4) +
  				hex_to_bin(buffer[3]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
363
  		}
f481973d5   Mahesh Rajashekhara   scsi: aacraid: pc...
364
  		dma_free_coherent(&dev->pdev->dev, 512, buffer, baddr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
365
366
367
368
369
  		return ret;
  	}
  	/*
  	 *	Wait for the adapter to be up and running.
  	 */
912d4e885   Salyzyn, Mark   [SCSI] aacraid: A...
370
  	if (unlikely(!(status & KERNEL_UP_AND_RUNNING)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
371
372
373
374
375
376
377
378
  		return -3;
  	/*
  	 *	Everything is OK
  	 */
  	return 0;
  }
  
  /**
28713324a   Mark Haverkamp   [SCSI] aacraid: r...
379
   *	aac_rx_deliver_producer
8e0c5ebde   Mark Haverkamp   [SCSI] aacraid: N...
380
381
382
383
   *	@fib: fib to issue
   *
   *	Will send a fib, returning 0 if successful.
   */
2ab01efd1   Salyzyn, Mark   [SCSI] aacraid: C...
384
  int aac_rx_deliver_producer(struct fib * fib)
8e0c5ebde   Mark Haverkamp   [SCSI] aacraid: N...
385
  {
8e0c5ebde   Mark Haverkamp   [SCSI] aacraid: N...
386
  	struct aac_dev *dev = fib->dev;
28713324a   Mark Haverkamp   [SCSI] aacraid: r...
387
  	struct aac_queue *q = &dev->queues->queue[AdapNormCmdQueue];
8e0c5ebde   Mark Haverkamp   [SCSI] aacraid: N...
388
  	u32 Index;
28713324a   Mark Haverkamp   [SCSI] aacraid: r...
389
  	unsigned long nointr = 0;
8e0c5ebde   Mark Haverkamp   [SCSI] aacraid: N...
390

a8166a529   Mark Haverkamp   [SCSI] aacraid: F...
391
  	aac_queue_get( dev, &Index, AdapNormCmdQueue, fib->hw_fib_va, 1, fib, &nointr);
28713324a   Mark Haverkamp   [SCSI] aacraid: r...
392

ef6162333   Mahesh Rajashekhara   aacraid: performa...
393
  	atomic_inc(&q->numpending);
28713324a   Mark Haverkamp   [SCSI] aacraid: r...
394
  	*(q->headers.producer) = cpu_to_le32(Index + 1);
28713324a   Mark Haverkamp   [SCSI] aacraid: r...
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
  	if (!(nointr & aac_config.irq_mod))
  		aac_adapter_notify(dev, AdapNormCmdQueue);
  
  	return 0;
  }
  
  /**
   *	aac_rx_deliver_message
   *	@fib: fib to issue
   *
   *	Will send a fib, returning 0 if successful.
   */
  static int aac_rx_deliver_message(struct fib * fib)
  {
  	struct aac_dev *dev = fib->dev;
  	struct aac_queue *q = &dev->queues->queue[AdapNormCmdQueue];
28713324a   Mark Haverkamp   [SCSI] aacraid: r...
411
412
413
414
415
  	u32 Index;
  	u64 addr;
  	volatile void __iomem *device;
  
  	unsigned long count = 10000000L; /* 50 seconds */
ef6162333   Mahesh Rajashekhara   aacraid: performa...
416
  	atomic_inc(&q->numpending);
28713324a   Mark Haverkamp   [SCSI] aacraid: r...
417
  	for(;;) {
8e0c5ebde   Mark Haverkamp   [SCSI] aacraid: N...
418
  		Index = rx_readl(dev, MUnit.InboundQueue);
912d4e885   Salyzyn, Mark   [SCSI] aacraid: A...
419
  		if (unlikely(Index == 0xFFFFFFFFL))
28713324a   Mark Haverkamp   [SCSI] aacraid: r...
420
  			Index = rx_readl(dev, MUnit.InboundQueue);
912d4e885   Salyzyn, Mark   [SCSI] aacraid: A...
421
  		if (likely(Index != 0xFFFFFFFFL))
28713324a   Mark Haverkamp   [SCSI] aacraid: r...
422
423
  			break;
  		if (--count == 0) {
ef6162333   Mahesh Rajashekhara   aacraid: performa...
424
  			atomic_dec(&q->numpending);
28713324a   Mark Haverkamp   [SCSI] aacraid: r...
425
426
427
428
  			return -ETIMEDOUT;
  		}
  		udelay(5);
  	}
76a7f8fdc   Mark Haverkamp   [SCSI] aacraid: m...
429
  	device = dev->base + Index;
28713324a   Mark Haverkamp   [SCSI] aacraid: r...
430
  	addr = fib->hw_fib_pa;
8e0c5ebde   Mark Haverkamp   [SCSI] aacraid: N...
431
432
433
434
  	writel((u32)(addr & 0xffffffff), device);
  	device += sizeof(u32);
  	writel((u32)(addr >> 32), device);
  	device += sizeof(u32);
a8166a529   Mark Haverkamp   [SCSI] aacraid: F...
435
  	writel(le16_to_cpu(fib->hw_fib_va->header.Size), device);
8e0c5ebde   Mark Haverkamp   [SCSI] aacraid: N...
436
  	rx_writel(dev, MUnit.InboundQueue, Index);
8e0c5ebde   Mark Haverkamp   [SCSI] aacraid: N...
437
438
  	return 0;
  }
76a7f8fdc   Mark Haverkamp   [SCSI] aacraid: m...
439
440
441
442
443
444
445
446
447
448
449
  /**
   *	aac_rx_ioremap
   *	@size: mapping resize request
   *
   */
  static int aac_rx_ioremap(struct aac_dev * dev, u32 size)
  {
  	if (!size) {
  		iounmap(dev->regs.rx);
  		return 0;
  	}
ff08784b4   Ben Collins   [SCSI] aacraid: U...
450
  	dev->base = dev->regs.rx = ioremap(dev->base_start, size);
76a7f8fdc   Mark Haverkamp   [SCSI] aacraid: m...
451
452
453
454
455
  	if (dev->base == NULL)
  		return -1;
  	dev->IndexRegs = &dev->regs.rx->IndexRegs;
  	return 0;
  }
313643295   Raghava Aditya Renukunta   scsi: aacraid: Ad...
456
  static int aac_rx_restart_adapter(struct aac_dev *dev, int bled, u8 reset_type)
8c23cd745   Mark Haverkamp   [SCSI] aacraid: R...
457
  {
6e40e5f02   Mahesh Rajashekhara   [SCSI] aacraid: k...
458
  	u32 var = 0;
8c23cd745   Mark Haverkamp   [SCSI] aacraid: R...
459

1c68856e6   Raghava Aditya Renukunta   scsi: aacraid: Fi...
460
  	if (!(dev->supplement_adapter_info.supported_options2 &
a3940da5e   Salyzyn, Mark   [SCSI] aacraid: f...
461
  	  AAC_OPTION_MU_RESET) || (bled >= 0) || (bled == -2)) {
29c976844   Salyzyn, Mark   [SCSI] aacraid: a...
462
463
464
465
466
467
468
  		if (bled)
  			printk(KERN_ERR "%s%d: adapter kernel panic'd %x.
  ",
  				dev->name, dev->id, bled);
  		else {
  			bled = aac_adapter_sync_cmd(dev, IOP_RESET_ALWAYS,
  			  0, 0, 0, 0, 0, 0, &var, NULL, NULL, NULL, NULL);
9859c1aa7   Salyzyn, Mark   [SCSI] aacraid: f...
469
  			if (!bled && (var != 0x00000001) && (var != 0x3803000F))
29c976844   Salyzyn, Mark   [SCSI] aacraid: a...
470
471
472
473
474
  				bled = -EINVAL;
  		}
  		if (bled && (bled != -ETIMEDOUT))
  			bled = aac_adapter_sync_cmd(dev, IOP_RESET,
  			  0, 0, 0, 0, 0, 0, &var, NULL, NULL, NULL, NULL);
8418852d1   Mark Haverkamp   [SCSI] aacraid: a...
475

29c976844   Salyzyn, Mark   [SCSI] aacraid: a...
476
477
478
  		if (bled && (bled != -ETIMEDOUT))
  			return -EINVAL;
  	}
6e40e5f02   Mahesh Rajashekhara   [SCSI] aacraid: k...
479
  	if (bled && (var == 0x3803000F)) { /* USE_OTHER_METHOD */
8418852d1   Mark Haverkamp   [SCSI] aacraid: a...
480
481
482
483
  		rx_writel(dev, MUnit.reserved2, 3);
  		msleep(5000); /* Delay 5 seconds */
  		var = 0x00000001;
  	}
6e40e5f02   Mahesh Rajashekhara   [SCSI] aacraid: k...
484
  	if (bled && (var != 0x00000001))
8418852d1   Mark Haverkamp   [SCSI] aacraid: a...
485
  		return -EINVAL;
6e40e5f02   Mahesh Rajashekhara   [SCSI] aacraid: k...
486
  	ssleep(5);
8c23cd745   Mark Haverkamp   [SCSI] aacraid: R...
487
  	if (rx_readl(dev, MUnit.OMRx[0]) & KERNEL_PANIC)
8418852d1   Mark Haverkamp   [SCSI] aacraid: a...
488
  		return -ENODEV;
1208bab5d   Salyzyn, Mark   [SCSI] aacraid: a...
489
490
  	if (startup_timeout < 300)
  		startup_timeout = 300;
8c23cd745   Mark Haverkamp   [SCSI] aacraid: R...
491
492
  	return 0;
  }
8e0c5ebde   Mark Haverkamp   [SCSI] aacraid: N...
493
  /**
28713324a   Mark Haverkamp   [SCSI] aacraid: r...
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
   *	aac_rx_select_comm	-	Select communications method
   *	@dev: Adapter
   *	@comm: communications method
   */
  
  int aac_rx_select_comm(struct aac_dev *dev, int comm)
  {
  	switch (comm) {
  	case AAC_COMM_PRODUCER:
  		dev->a_ops.adapter_enable_int = aac_rx_enable_interrupt_producer;
  		dev->a_ops.adapter_intr = aac_rx_intr_producer;
  		dev->a_ops.adapter_deliver = aac_rx_deliver_producer;
  		break;
  	case AAC_COMM_MESSAGE:
  		dev->a_ops.adapter_enable_int = aac_rx_enable_interrupt_message;
  		dev->a_ops.adapter_intr = aac_rx_intr_message;
  		dev->a_ops.adapter_deliver = aac_rx_deliver_message;
  		break;
  	default:
  		return 1;
  	}
  	return 0;
  }
  
  /**
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
519
520
521
522
523
524
525
   *	aac_rx_init	-	initialize an i960 based AAC card
   *	@dev: device to configure
   *
   *	Allocate and set up resources for the i960 based AAC variants. The 
   *	device_interface in the commregion will be allocated and linked 
   *	to the comm region.
   */
76a7f8fdc   Mark Haverkamp   [SCSI] aacraid: m...
526
  int _aac_rx_init(struct aac_dev *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
527
528
529
  {
  	unsigned long start;
  	unsigned long status;
18a6598f2   Salyzyn, Mark   [SCSI] aacraid: [...
530
  	int restart = 0;
912d4e885   Salyzyn, Mark   [SCSI] aacraid: A...
531
532
  	int instance = dev->id;
  	const char * name = dev->name;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
533

76a7f8fdc   Mark Haverkamp   [SCSI] aacraid: m...
534
535
536
537
538
  	if (aac_adapter_ioremap(dev, dev->base_size)) {
  		printk(KERN_WARNING "%s: unable to map adapter.
  ", name);
  		goto error_iounmap;
  	}
18a6598f2   Salyzyn, Mark   [SCSI] aacraid: [...
539
  	/* Failure to reset here is an option ... */
a5694ec54   Salyzyn, Mark   [SCSI] aacraid: k...
540
541
  	dev->a_ops.adapter_sync_cmd = rx_sync_cmd;
  	dev->a_ops.adapter_enable_int = aac_rx_disable_interrupt;
18a6598f2   Salyzyn, Mark   [SCSI] aacraid: [...
542
  	dev->OIMR = status = rx_readb (dev, MUnit.OIMR);
d9b6d85a3   Guilherme G. Piccoli   scsi: aacraid: Pe...
543
544
545
546
547
548
549
550
551
  
  	if (((status & 0x0c) != 0x0c) || dev->init_reset) {
  		dev->init_reset = false;
  		if (!aac_rx_restart_adapter(dev, 0, IOP_HWSOFT_RESET)) {
  			/* Make sure the Hardware FIFO is empty */
  			while ((++restart < 512) &&
  			       (rx_readl(dev, MUnit.OutboundQueue) != 0xFFFFFFFFL));
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
552
  	/*
8e0c5ebde   Mark Haverkamp   [SCSI] aacraid: N...
553
  	 *	Check to see if the board panic'd while booting.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
554
  	 */
76a7f8fdc   Mark Haverkamp   [SCSI] aacraid: m...
555
  	status = rx_readl(dev, MUnit.OMRx[0]);
8418852d1   Mark Haverkamp   [SCSI] aacraid: a...
556
  	if (status & KERNEL_PANIC) {
313643295   Raghava Aditya Renukunta   scsi: aacraid: Ad...
557
558
  		if (aac_rx_restart_adapter(dev,
  			aac_rx_check_health(dev), IOP_HWSOFT_RESET))
8418852d1   Mark Haverkamp   [SCSI] aacraid: a...
559
  			goto error_iounmap;
18a6598f2   Salyzyn, Mark   [SCSI] aacraid: [...
560
  		++restart;
8418852d1   Mark Haverkamp   [SCSI] aacraid: a...
561
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
562
563
564
  	/*
  	 *	Check to see if the board failed any self tests.
  	 */
76a7f8fdc   Mark Haverkamp   [SCSI] aacraid: m...
565
566
  	status = rx_readl(dev, MUnit.OMRx[0]);
  	if (status & SELF_TEST_FAILED) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
567
568
569
570
571
  		printk(KERN_ERR "%s%d: adapter self-test failed.
  ", dev->name, instance);
  		goto error_iounmap;
  	}
  	/*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
572
573
  	 *	Check to see if the monitor panic'd while booting.
  	 */
76a7f8fdc   Mark Haverkamp   [SCSI] aacraid: m...
574
  	if (status & MONITOR_PANIC) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
575
576
577
578
579
580
581
582
  		printk(KERN_ERR "%s%d: adapter monitor panic.
  ", dev->name, instance);
  		goto error_iounmap;
  	}
  	start = jiffies;
  	/*
  	 *	Wait for the adapter to be up and running. Wait up to 3 minutes
  	 */
76a7f8fdc   Mark Haverkamp   [SCSI] aacraid: m...
583
  	while (!((status = rx_readl(dev, MUnit.OMRx[0])) & KERNEL_UP_AND_RUNNING))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
584
  	{
18a6598f2   Salyzyn, Mark   [SCSI] aacraid: [...
585
586
587
  		if ((restart &&
  		  (status & (KERNEL_PANIC|SELF_TEST_FAILED|MONITOR_PANIC))) ||
  		  time_after(jiffies, start+HZ*startup_timeout)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
588
589
590
591
592
  			printk(KERN_ERR "%s%d: adapter kernel failed to start, init status = %lx.
  ", 
  					dev->name, instance, status);
  			goto error_iounmap;
  		}
18a6598f2   Salyzyn, Mark   [SCSI] aacraid: [...
593
594
595
596
597
598
  		if (!restart &&
  		  ((status & (KERNEL_PANIC|SELF_TEST_FAILED|MONITOR_PANIC)) ||
  		  time_after(jiffies, start + HZ *
  		  ((startup_timeout > 60)
  		    ? (startup_timeout - 60)
  		    : (startup_timeout / 2))))) {
313643295   Raghava Aditya Renukunta   scsi: aacraid: Ad...
599
600
  			if (likely(!aac_rx_restart_adapter(dev,
  				aac_rx_check_health(dev), IOP_HWSOFT_RESET)))
18a6598f2   Salyzyn, Mark   [SCSI] aacraid: [...
601
602
603
  				start = jiffies;
  			++restart;
  		}
404d9a900   Mark Haverkamp   [SCSI] aacraid: a...
604
  		msleep(1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
605
  	}
29c976844   Salyzyn, Mark   [SCSI] aacraid: a...
606
  	if (restart && aac_commit)
1208bab5d   Salyzyn, Mark   [SCSI] aacraid: a...
607
  		aac_commit = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
608
  	/*
28713324a   Mark Haverkamp   [SCSI] aacraid: r...
609
  	 *	Fill in the common function dispatch table.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
610
611
  	 */
  	dev->a_ops.adapter_interrupt = aac_rx_interrupt_adapter;
bd1aac809   Mark Haverkamp   [SCSI] aacraid: d...
612
  	dev->a_ops.adapter_disable_int = aac_rx_disable_interrupt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
613
614
615
  	dev->a_ops.adapter_notify = aac_rx_notify_adapter;
  	dev->a_ops.adapter_sync_cmd = rx_sync_cmd;
  	dev->a_ops.adapter_check_health = aac_rx_check_health;
8418852d1   Mark Haverkamp   [SCSI] aacraid: a...
616
  	dev->a_ops.adapter_restart = aac_rx_restart_adapter;
de665f28f   Mahesh Rajashekhara   aacraid: Add Powe...
617
  	dev->a_ops.adapter_start = aac_rx_start_adapter;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
618

bd1aac809   Mark Haverkamp   [SCSI] aacraid: d...
619
620
621
622
  	/*
  	 *	First clear out all interrupts.  Then enable the one's that we
  	 *	can handle.
  	 */
28713324a   Mark Haverkamp   [SCSI] aacraid: r...
623
624
  	aac_adapter_comm(dev, AAC_COMM_PRODUCER);
  	aac_adapter_disable_int(dev);
bd1aac809   Mark Haverkamp   [SCSI] aacraid: d...
625
  	rx_writel(dev, MUnit.ODR, 0xffffffff);
28713324a   Mark Haverkamp   [SCSI] aacraid: r...
626
  	aac_adapter_enable_int(dev);
bd1aac809   Mark Haverkamp   [SCSI] aacraid: d...
627

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
628
  	if (aac_init_adapter(dev) == NULL)
28713324a   Mark Haverkamp   [SCSI] aacraid: r...
629
630
  		goto error_iounmap;
  	aac_adapter_comm(dev, dev->comm_interface);
116046127   Mahesh Rajashekhara   [SCSI] aacraid: A...
631
  	dev->sync_mode = 0;	/* sync. mode not supported */
8ef222470   Salyzyn, Mark   [SCSI] aacraid: a...
632
633
  	dev->msi = aac_msi && !pci_enable_msi(dev->pdev);
  	if (request_irq(dev->pdev->irq, dev->a_ops.adapter_intr,
4909cc2b8   Michael Opdenacker   [SCSI] remove dep...
634
  			IRQF_SHARED, "aacraid", dev) < 0) {
8ef222470   Salyzyn, Mark   [SCSI] aacraid: a...
635
636
  		if (dev->msi)
  			pci_disable_msi(dev->pdev);
28713324a   Mark Haverkamp   [SCSI] aacraid: r...
637
638
639
640
641
  		printk(KERN_ERR "%s%d: Interrupt unavailable.
  ",
  			name, instance);
  		goto error_iounmap;
  	}
ff08784b4   Ben Collins   [SCSI] aacraid: U...
642
  	dev->dbg_base = dev->base_start;
e8b12f0fb   Mahesh Rajashekhara   [SCSI] aacraid: A...
643
644
  	dev->dbg_base_mapped = dev->base;
  	dev->dbg_size = dev->base_size;
28713324a   Mark Haverkamp   [SCSI] aacraid: r...
645
646
647
648
649
650
  	aac_adapter_enable_int(dev);
  	/*
  	 *	Tell the adapter that all is configured, and it can
  	 * start accepting requests
  	 */
  	aac_rx_start_adapter(dev);
8e0c5ebde   Mark Haverkamp   [SCSI] aacraid: N...
651

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
652
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
653
  error_iounmap:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
654
655
656
  
  	return -1;
  }
76a7f8fdc   Mark Haverkamp   [SCSI] aacraid: m...
657
658
659
  
  int aac_rx_init(struct aac_dev *dev)
  {
76a7f8fdc   Mark Haverkamp   [SCSI] aacraid: m...
660
661
662
663
  	/*
  	 *	Fill in the function dispatch table.
  	 */
  	dev->a_ops.adapter_ioremap = aac_rx_ioremap;
28713324a   Mark Haverkamp   [SCSI] aacraid: r...
664
  	dev->a_ops.adapter_comm = aac_rx_select_comm;
76a7f8fdc   Mark Haverkamp   [SCSI] aacraid: m...
665

28713324a   Mark Haverkamp   [SCSI] aacraid: r...
666
  	return _aac_rx_init(dev);
76a7f8fdc   Mark Haverkamp   [SCSI] aacraid: m...
667
  }