aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/aacraid/rkt.c
diff options
context:
space:
mode:
authorMark Haverkamp <markh@osdl.org>2005-10-24 13:52:22 -0400
committerJames Bottomley <jejb@mulgrave.(none)>2005-10-28 12:41:53 -0400
commit8e0c5ebde82b08f6d996e11983890fc4cc085fab (patch)
tree3ba38ff8e7b9203b47d038c215d9c7d623c250ba /drivers/scsi/aacraid/rkt.c
parent38a9a621aba953ddb8051547e98c10ec3c741312 (diff)
[SCSI] aacraid: Newer adapter communication iterface support
Received from Mark Salyzyn. This patch adds the 'new comm' interface, which modern AAC based adapters that are less than a year old support in the name of much improved performance. These modern adapters support both the legacy and the 'new comm' interfaces. Signed-off-by: Mark Haverkamp <markh@osdl.org> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/aacraid/rkt.c')
-rw-r--r--drivers/scsi/aacraid/rkt.c172
1 files changed, 110 insertions, 62 deletions
diff --git a/drivers/scsi/aacraid/rkt.c b/drivers/scsi/aacraid/rkt.c
index 557287a0b80b..fc4c73c2a6a9 100644
--- a/drivers/scsi/aacraid/rkt.c
+++ b/drivers/scsi/aacraid/rkt.c
@@ -49,40 +49,57 @@
49static irqreturn_t aac_rkt_intr(int irq, void *dev_id, struct pt_regs *regs) 49static irqreturn_t aac_rkt_intr(int irq, void *dev_id, struct pt_regs *regs)
50{ 50{
51 struct aac_dev *dev = dev_id; 51 struct aac_dev *dev = dev_id;
52 unsigned long bellbits; 52
53 u8 intstat, mask; 53 if (dev->new_comm_interface) {
54 intstat = rkt_readb(dev, MUnit.OISR); 54 u32 Index = rkt_readl(dev, MUnit.OutboundQueue);
55 /* 55 if (Index == 0xFFFFFFFFL)
56 * Read mask and invert because drawbridge is reversed. 56 Index = rkt_readl(dev, MUnit.OutboundQueue);
57 * This allows us to only service interrupts that have 57 if (Index != 0xFFFFFFFFL) {
58 * been enabled. 58 do {
59 */ 59 if (aac_intr_normal(dev, Index)) {
60 mask = ~(dev->OIMR); 60 rkt_writel(dev, MUnit.OutboundQueue, Index);
61 /* Check to see if this is our interrupt. If it isn't just return */ 61 rkt_writel(dev, MUnit.ODR, DoorBellAdapterNormRespReady);
62 if (intstat & mask) 62 }
63 { 63 Index = rkt_readl(dev, MUnit.OutboundQueue);
64 bellbits = rkt_readl(dev, OutboundDoorbellReg); 64 } while (Index != 0xFFFFFFFFL);
65 if (bellbits & DoorBellPrintfReady) { 65 return IRQ_HANDLED;
66 aac_printf(dev, rkt_readl(dev, IndexRegs.Mailbox[5]));
67 rkt_writel(dev, MUnit.ODR,DoorBellPrintfReady);
68 rkt_writel(dev, InboundDoorbellReg,DoorBellPrintfDone);
69 }
70 else if (bellbits & DoorBellAdapterNormCmdReady) {
71 rkt_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdReady);
72 aac_command_normal(&dev->queues->queue[HostNormCmdQueue]);
73 }
74 else if (bellbits & DoorBellAdapterNormRespReady) {
75 aac_response_normal(&dev->queues->queue[HostNormRespQueue]);
76 rkt_writel(dev, MUnit.ODR,DoorBellAdapterNormRespReady);
77 }
78 else if (bellbits & DoorBellAdapterNormCmdNotFull) {
79 rkt_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull);
80 } 66 }
81 else if (bellbits & DoorBellAdapterNormRespNotFull) { 67 } else {
82 rkt_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull); 68 unsigned long bellbits;
83 rkt_writel(dev, MUnit.ODR, DoorBellAdapterNormRespNotFull); 69 u8 intstat;
70 intstat = rkt_readb(dev, MUnit.OISR);
71 /*
72 * Read mask and invert because drawbridge is reversed.
73 * This allows us to only service interrupts that have
74 * been enabled.
75 * Check to see if this is our interrupt. If it isn't just return
76 */
77 if (intstat & ~(dev->OIMR))
78 {
79 bellbits = rkt_readl(dev, OutboundDoorbellReg);
80 if (bellbits & DoorBellPrintfReady) {
81 aac_printf(dev, rkt_readl (dev, IndexRegs.Mailbox[5]));
82 rkt_writel(dev, MUnit.ODR,DoorBellPrintfReady);
83 rkt_writel(dev, InboundDoorbellReg,DoorBellPrintfDone);
84 }
85 else if (bellbits & DoorBellAdapterNormCmdReady) {
86 rkt_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdReady);
87 aac_command_normal(&dev->queues->queue[HostNormCmdQueue]);
88// rkt_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdReady);
89 }
90 else if (bellbits & DoorBellAdapterNormRespReady) {
91 rkt_writel(dev, MUnit.ODR,DoorBellAdapterNormRespReady);
92 aac_response_normal(&dev->queues->queue[HostNormRespQueue]);
93 }
94 else if (bellbits & DoorBellAdapterNormCmdNotFull) {
95 rkt_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull);
96 }
97 else if (bellbits & DoorBellAdapterNormRespNotFull) {
98 rkt_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull);
99 rkt_writel(dev, MUnit.ODR, DoorBellAdapterNormRespNotFull);
100 }
101 return IRQ_HANDLED;
84 } 102 }
85 return IRQ_HANDLED;
86 } 103 }
87 return IRQ_NONE; 104 return IRQ_NONE;
88} 105}
@@ -173,7 +190,10 @@ static int rkt_sync_cmd(struct aac_dev *dev, u32 command,
173 /* 190 /*
174 * Restore interrupt mask even though we timed out 191 * Restore interrupt mask even though we timed out
175 */ 192 */
176 rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb); 193 if (dev->new_comm_interface)
194 rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xf7);
195 else
196 rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb);
177 return -ETIMEDOUT; 197 return -ETIMEDOUT;
178 } 198 }
179 /* 199 /*
@@ -196,7 +216,10 @@ static int rkt_sync_cmd(struct aac_dev *dev, u32 command,
196 /* 216 /*
197 * Restore interrupt mask 217 * Restore interrupt mask
198 */ 218 */
199 rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb); 219 if (dev->new_comm_interface)
220 rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xf7);
221 else
222 rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb);
200 return 0; 223 return 0;
201 224
202} 225}
@@ -268,15 +291,6 @@ static void aac_rkt_start_adapter(struct aac_dev *dev)
268 291
269 init = dev->init; 292 init = dev->init;
270 init->HostElapsedSeconds = cpu_to_le32(get_seconds()); 293 init->HostElapsedSeconds = cpu_to_le32(get_seconds());
271 /*
272 * First clear out all interrupts. Then enable the one's that we
273 * can handle.
274 */
275 rkt_writeb(dev, MUnit.OIMR, 0xff);
276 rkt_writel(dev, MUnit.ODR, 0xffffffff);
277// rkt_writeb(dev, MUnit.OIMR, ~(u8)OUTBOUND_DOORBELL_INTERRUPT_MASK);
278 rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb);
279
280 // We can only use a 32 bit address here 294 // We can only use a 32 bit address here
281 rkt_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (u32)(ulong)dev->init_pa, 295 rkt_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (u32)(ulong)dev->init_pa,
282 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL); 296 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL);
@@ -350,6 +364,39 @@ static int aac_rkt_check_health(struct aac_dev *dev)
350} 364}
351 365
352/** 366/**
367 * aac_rkt_send
368 * @fib: fib to issue
369 *
370 * Will send a fib, returning 0 if successful.
371 */
372static int aac_rkt_send(struct fib * fib)
373{
374 u64 addr = fib->hw_fib_pa;
375 struct aac_dev *dev = fib->dev;
376 volatile void __iomem *device = dev->regs.rkt;
377 u32 Index;
378
379 dprintk((KERN_DEBUG "%p->aac_rkt_send(%p->%llx)\n", dev, fib, addr));
380 Index = rkt_readl(dev, MUnit.InboundQueue);
381 if (Index == 0xFFFFFFFFL)
382 Index = rkt_readl(dev, MUnit.InboundQueue);
383 dprintk((KERN_DEBUG "Index = 0x%x\n", Index));
384 if (Index == 0xFFFFFFFFL)
385 return Index;
386 device += Index;
387 dprintk((KERN_DEBUG "entry = %x %x %u\n", (u32)(addr & 0xffffffff),
388 (u32)(addr >> 32), (u32)le16_to_cpu(fib->hw_fib->header.Size)));
389 writel((u32)(addr & 0xffffffff), device);
390 device += sizeof(u32);
391 writel((u32)(addr >> 32), device);
392 device += sizeof(u32);
393 writel(le16_to_cpu(fib->hw_fib->header.Size), device);
394 rkt_writel(dev, MUnit.InboundQueue, Index);
395 dprintk((KERN_DEBUG "aac_rkt_send - return 0\n"));
396 return 0;
397}
398
399/**
353 * aac_rkt_init - initialize an i960 based AAC card 400 * aac_rkt_init - initialize an i960 based AAC card
354 * @dev: device to configure 401 * @dev: device to configure
355 * 402 *
@@ -369,13 +416,8 @@ int aac_rkt_init(struct aac_dev *dev)
369 name = dev->name; 416 name = dev->name;
370 417
371 /* 418 /*
372 * Map in the registers from the adapter. 419 * Check to see if the board panic'd while booting.
373 */ 420 */
374 if((dev->regs.rkt = ioremap((unsigned long)dev->scsi_host_ptr->base, 8192))==NULL)
375 {
376 printk(KERN_WARNING "aacraid: unable to map i960.\n" );
377 goto error_iounmap;
378 }
379 /* 421 /*
380 * Check to see if the board failed any self tests. 422 * Check to see if the board failed any self tests.
381 */ 423 */
@@ -426,6 +468,7 @@ int aac_rkt_init(struct aac_dev *dev)
426 dev->a_ops.adapter_notify = aac_rkt_notify_adapter; 468 dev->a_ops.adapter_notify = aac_rkt_notify_adapter;
427 dev->a_ops.adapter_sync_cmd = rkt_sync_cmd; 469 dev->a_ops.adapter_sync_cmd = rkt_sync_cmd;
428 dev->a_ops.adapter_check_health = aac_rkt_check_health; 470 dev->a_ops.adapter_check_health = aac_rkt_check_health;
471 dev->a_ops.adapter_send = aac_rkt_send;
429 472
430 /* 473 /*
431 * First clear out all interrupts. Then enable the one's that we 474 * First clear out all interrupts. Then enable the one's that we
@@ -437,15 +480,24 @@ int aac_rkt_init(struct aac_dev *dev)
437 480
438 if (aac_init_adapter(dev) == NULL) 481 if (aac_init_adapter(dev) == NULL)
439 goto error_irq; 482 goto error_irq;
440 /* 483 if (dev->new_comm_interface) {
441 * Start any kernel threads needed 484 /*
442 */ 485 * FIB Setup has already been done, but we can minimize the
443 dev->thread_pid = kernel_thread((int (*)(void *))aac_command_thread, dev, 0); 486 * damage by at least ensuring the OS never issues more
444 if(dev->thread_pid < 0) 487 * commands than we can handle. The Rocket adapters currently
445 { 488 * can only handle 246 commands and 8 AIFs at the same time,
446 printk(KERN_ERR "aacraid: Unable to create rkt thread.\n"); 489 * and in fact do notify us accordingly if we negotiate the
447 goto error_kfree; 490 * FIB size. The problem that causes us to add this check is
448 } 491 * to ensure that we do not overdo it with the adapter when a
492 * hard coded FIB override is being utilized. This special
493 * case warrants this half baked, but convenient, check here.
494 */
495 if (dev->scsi_host_ptr->can_queue > (246 - AAC_NUM_MGT_FIB)) {
496 dev->init->MaxIoCommands = cpu_to_le32(246);
497 dev->scsi_host_ptr->can_queue = 246 - AAC_NUM_MGT_FIB;
498 }
499 rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xf7);
500 }
449 /* 501 /*
450 * Tell the adapter that all is configured, and it can start 502 * Tell the adapter that all is configured, and it can start
451 * accepting requests 503 * accepting requests
@@ -453,15 +505,11 @@ int aac_rkt_init(struct aac_dev *dev)
453 aac_rkt_start_adapter(dev); 505 aac_rkt_start_adapter(dev);
454 return 0; 506 return 0;
455 507
456error_kfree:
457 kfree(dev->queues);
458
459error_irq: 508error_irq:
460 rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff); 509 rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff);
461 free_irq(dev->scsi_host_ptr->irq, (void *)dev); 510 free_irq(dev->scsi_host_ptr->irq, (void *)dev);
462 511
463error_iounmap: 512error_iounmap:
464 iounmap(dev->regs.rkt);
465 513
466 return -1; 514 return -1;
467} 515}