aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/aacraid/rx.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/rx.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/rx.c')
-rw-r--r--drivers/scsi/aacraid/rx.c157
1 files changed, 95 insertions, 62 deletions
diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c
index a8459faf87ca..da99046e5393 100644
--- a/drivers/scsi/aacraid/rx.c
+++ b/drivers/scsi/aacraid/rx.c
@@ -49,40 +49,57 @@
49static irqreturn_t aac_rx_intr(int irq, void *dev_id, struct pt_regs *regs) 49static irqreturn_t aac_rx_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 dprintk((KERN_DEBUG "aac_rx_intr(%d,%p,%p)\n", irq, dev_id, regs));
54 intstat = rx_readb(dev, MUnit.OISR); 54 if (dev->new_comm_interface) {
55 /* 55 u32 Index = rx_readl(dev, MUnit.OutboundQueue);
56 * Read mask and invert because drawbridge is reversed. 56 if (Index == 0xFFFFFFFFL)
57 * This allows us to only service interrupts that have 57 Index = rx_readl(dev, MUnit.OutboundQueue);
58 * been enabled. 58 if (Index != 0xFFFFFFFFL) {
59 */ 59 do {
60 mask = ~(dev->OIMR); 60 if (aac_intr_normal(dev, Index)) {
61 /* Check to see if this is our interrupt. If it isn't just return */ 61 rx_writel(dev, MUnit.OutboundQueue, Index);
62 if (intstat & mask) 62 rx_writel(dev, MUnit.ODR, DoorBellAdapterNormRespReady);
63 { 63 }
64 bellbits = rx_readl(dev, OutboundDoorbellReg); 64 Index = rx_readl(dev, MUnit.OutboundQueue);
65 if (bellbits & DoorBellPrintfReady) { 65 } while (Index != 0xFFFFFFFFL);
66 aac_printf(dev, rx_readl(dev, IndexRegs.Mailbox[5])); 66 return IRQ_HANDLED;
67 rx_writel(dev, MUnit.ODR,DoorBellPrintfReady);
68 rx_writel(dev, InboundDoorbellReg,DoorBellPrintfDone);
69 }
70 else if (bellbits & DoorBellAdapterNormCmdReady) {
71 rx_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 rx_writel(dev, MUnit.ODR,DoorBellAdapterNormRespReady);
77 }
78 else if (bellbits & DoorBellAdapterNormCmdNotFull) {
79 rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull);
80 } 67 }
81 else if (bellbits & DoorBellAdapterNormRespNotFull) { 68 } else {
82 rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull); 69 unsigned long bellbits;
83 rx_writel(dev, MUnit.ODR, DoorBellAdapterNormRespNotFull); 70 u8 intstat;
71 intstat = rx_readb(dev, MUnit.OISR);
72 /*
73 * Read mask and invert because drawbridge is reversed.
74 * This allows us to only service interrupts that have
75 * been enabled.
76 * Check to see if this is our interrupt. If it isn't just return
77 */
78 if (intstat & ~(dev->OIMR))
79 {
80 bellbits = rx_readl(dev, OutboundDoorbellReg);
81 if (bellbits & DoorBellPrintfReady) {
82 aac_printf(dev, rx_readl (dev, IndexRegs.Mailbox[5]));
83 rx_writel(dev, MUnit.ODR,DoorBellPrintfReady);
84 rx_writel(dev, InboundDoorbellReg,DoorBellPrintfDone);
85 }
86 else if (bellbits & DoorBellAdapterNormCmdReady) {
87 rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdReady);
88 aac_command_normal(&dev->queues->queue[HostNormCmdQueue]);
89 }
90 else if (bellbits & DoorBellAdapterNormRespReady) {
91 rx_writel(dev, MUnit.ODR,DoorBellAdapterNormRespReady);
92 aac_response_normal(&dev->queues->queue[HostNormRespQueue]);
93 }
94 else if (bellbits & DoorBellAdapterNormCmdNotFull) {
95 rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull);
96 }
97 else if (bellbits & DoorBellAdapterNormRespNotFull) {
98 rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull);
99 rx_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 rx_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 rx_writeb(dev, MUnit.OIMR, dev->OIMR &= 0xfb); 193 if (dev->new_comm_interface)
194 rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xf7);
195 else
196 rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb);
177 return -ETIMEDOUT; 197 return -ETIMEDOUT;
178 } 198 }
179 /* 199 /*
@@ -196,7 +216,10 @@ static int rx_sync_cmd(struct aac_dev *dev, u32 command,
196 /* 216 /*
197 * Restore interrupt mask 217 * Restore interrupt mask
198 */ 218 */
199 rx_writeb(dev, MUnit.OIMR, dev->OIMR &= 0xfb); 219 if (dev->new_comm_interface)
220 rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xf7);
221 else
222 rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb);
200 return 0; 223 return 0;
201 224
202} 225}
@@ -267,15 +290,6 @@ static void aac_rx_start_adapter(struct aac_dev *dev)
267 290
268 init = dev->init; 291 init = dev->init;
269 init->HostElapsedSeconds = cpu_to_le32(get_seconds()); 292 init->HostElapsedSeconds = cpu_to_le32(get_seconds());
270 /*
271 * First clear out all interrupts. Then enable the one's that we
272 * can handle.
273 */
274 rx_writeb(dev, MUnit.OIMR, 0xff);
275 rx_writel(dev, MUnit.ODR, 0xffffffff);
276// rx_writeb(dev, MUnit.OIMR, ~(u8)OUTBOUND_DOORBELL_INTERRUPT_MASK);
277 rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb);
278
279 // We can only use a 32 bit address here 293 // We can only use a 32 bit address here
280 rx_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (u32)(ulong)dev->init_pa, 294 rx_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (u32)(ulong)dev->init_pa,
281 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL); 295 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL);
@@ -349,6 +363,39 @@ static int aac_rx_check_health(struct aac_dev *dev)
349} 363}
350 364
351/** 365/**
366 * aac_rx_send
367 * @fib: fib to issue
368 *
369 * Will send a fib, returning 0 if successful.
370 */
371static int aac_rx_send(struct fib * fib)
372{
373 u64 addr = fib->hw_fib_pa;
374 struct aac_dev *dev = fib->dev;
375 volatile void __iomem *device = dev->regs.rx;
376 u32 Index;
377
378 dprintk((KERN_DEBUG "%p->aac_rx_send(%p->%llx)\n", dev, fib, addr));
379 Index = rx_readl(dev, MUnit.InboundQueue);
380 if (Index == 0xFFFFFFFFL)
381 Index = rx_readl(dev, MUnit.InboundQueue);
382 dprintk((KERN_DEBUG "Index = 0x%x\n", Index));
383 if (Index == 0xFFFFFFFFL)
384 return Index;
385 device += Index;
386 dprintk((KERN_DEBUG "entry = %x %x %u\n", (u32)(addr & 0xffffffff),
387 (u32)(addr >> 32), (u32)le16_to_cpu(fib->hw_fib->header.Size)));
388 writel((u32)(addr & 0xffffffff), device);
389 device += sizeof(u32);
390 writel((u32)(addr >> 32), device);
391 device += sizeof(u32);
392 writel(le16_to_cpu(fib->hw_fib->header.Size), device);
393 rx_writel(dev, MUnit.InboundQueue, Index);
394 dprintk((KERN_DEBUG "aac_rx_send - return 0\n"));
395 return 0;
396}
397
398/**
352 * aac_rx_init - initialize an i960 based AAC card 399 * aac_rx_init - initialize an i960 based AAC card
353 * @dev: device to configure 400 * @dev: device to configure
354 * 401 *
@@ -368,13 +415,8 @@ int aac_rx_init(struct aac_dev *dev)
368 name = dev->name; 415 name = dev->name;
369 416
370 /* 417 /*
371 * Map in the registers from the adapter. 418 * Check to see if the board panic'd while booting.
372 */ 419 */
373 if((dev->regs.rx = ioremap((unsigned long)dev->scsi_host_ptr->base, 8192))==NULL)
374 {
375 printk(KERN_WARNING "aacraid: unable to map i960.\n" );
376 return -1;
377 }
378 /* 420 /*
379 * Check to see if the board failed any self tests. 421 * Check to see if the board failed any self tests.
380 */ 422 */
@@ -426,6 +468,7 @@ int aac_rx_init(struct aac_dev *dev)
426 dev->a_ops.adapter_notify = aac_rx_notify_adapter; 468 dev->a_ops.adapter_notify = aac_rx_notify_adapter;
427 dev->a_ops.adapter_sync_cmd = rx_sync_cmd; 469 dev->a_ops.adapter_sync_cmd = rx_sync_cmd;
428 dev->a_ops.adapter_check_health = aac_rx_check_health; 470 dev->a_ops.adapter_check_health = aac_rx_check_health;
471 dev->a_ops.adapter_send = aac_rx_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,9 @@ int aac_rx_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 rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xf7);
442 */ 485
443 dev->thread_pid = kernel_thread((int (*)(void *))aac_command_thread, dev, 0);
444 if(dev->thread_pid < 0)
445 {
446 printk(KERN_ERR "aacraid: Unable to create rx thread.\n");
447 goto error_kfree;
448 }
449 /* 486 /*
450 * Tell the adapter that all is configured, and it can start 487 * Tell the adapter that all is configured, and it can start
451 * accepting requests 488 * accepting requests
@@ -453,15 +490,11 @@ int aac_rx_init(struct aac_dev *dev)
453 aac_rx_start_adapter(dev); 490 aac_rx_start_adapter(dev);
454 return 0; 491 return 0;
455 492
456error_kfree:
457 kfree(dev->queues);
458
459error_irq: 493error_irq:
460 rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff); 494 rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff);
461 free_irq(dev->scsi_host_ptr->irq, (void *)dev); 495 free_irq(dev->scsi_host_ptr->irq, (void *)dev);
462 496
463error_iounmap: 497error_iounmap:
464 iounmap(dev->regs.rx);
465 498
466 return -1; 499 return -1;
467} 500}