diff options
Diffstat (limited to 'drivers/scsi/aacraid/rx.c')
| -rw-r--r-- | drivers/scsi/aacraid/rx.c | 462 |
1 files changed, 324 insertions, 138 deletions
diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c index 6998bc877dd..5c6a8703f53 100644 --- a/drivers/scsi/aacraid/rx.c +++ b/drivers/scsi/aacraid/rx.c @@ -1,11 +1,12 @@ /* * Adaptec AAC series RAID controller driver - * (c) Copyright 2001 Red Hat Inc. <alan@redhat.com> + * (c) Copyright 2001 Red Hat Inc. * * based on the old aacraid driver that is.. * Adaptec aacraid device driver for Linux. * - * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com) + * Copyright (c) 2000-2010 Adaptec, Inc. + * 2010 PMC-Sierra, Inc. (aacraid@pmc-sierra.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -31,75 +32,92 @@ #include <linux/kernel.h> #include <linux/init.h> #include <linux/types.h> -#include <linux/sched.h> #include <linux/pci.h> #include <linux/spinlock.h> -#include <linux/slab.h> #include <linux/blkdev.h> #include <linux/delay.h> #include <linux/completion.h> #include <linux/time.h> #include <linux/interrupt.h> -#include <asm/semaphore.h> #include <scsi/scsi_host.h> #include "aacraid.h" -static irqreturn_t aac_rx_intr(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t aac_rx_intr_producer(int irq, void *dev_id) { struct aac_dev *dev = dev_id; + unsigned long bellbits; + u8 intstat = rx_readb(dev, MUnit.OISR); - dprintk((KERN_DEBUG "aac_rx_intr(%d,%p,%p)\n", irq, dev_id, regs)); - if (dev->new_comm_interface) { - u32 Index = rx_readl(dev, MUnit.OutboundQueue); - if (Index == 0xFFFFFFFFL) - Index = rx_readl(dev, MUnit.OutboundQueue); - if (Index != 0xFFFFFFFFL) { - do { - if (aac_intr_normal(dev, Index)) { - rx_writel(dev, MUnit.OutboundQueue, Index); - rx_writel(dev, MUnit.ODR, DoorBellAdapterNormRespReady); - } - Index = rx_readl(dev, MUnit.OutboundQueue); - } while (Index != 0xFFFFFFFFL); - return IRQ_HANDLED; + /* + * 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 + */ + if (likely(intstat & ~(dev->OIMR))) { + bellbits = rx_readl(dev, OutboundDoorbellReg); + if (unlikely(bellbits & DoorBellPrintfReady)) { + aac_printf(dev, readl (&dev->IndexRegs->Mailbox[5])); + rx_writel(dev, MUnit.ODR,DoorBellPrintfReady); + rx_writel(dev, InboundDoorbellReg,DoorBellPrintfDone); } - } else { - unsigned long bellbits; - u8 intstat; - intstat = rx_readb(dev, MUnit.OISR); - /* - * 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 - */ - if (intstat & ~(dev->OIMR)) - { - bellbits = rx_readl(dev, OutboundDoorbellReg); - if (bellbits & DoorBellPrintfReady) { - aac_printf(dev, rx_readl (dev, IndexRegs.Mailbox[5])); - rx_writel(dev, MUnit.ODR,DoorBellPrintfReady); - rx_writel(dev, InboundDoorbellReg,DoorBellPrintfDone); - } - else if (bellbits & DoorBellAdapterNormCmdReady) { - rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdReady); - aac_command_normal(&dev->queues->queue[HostNormCmdQueue]); - } - else if (bellbits & DoorBellAdapterNormRespReady) { - rx_writel(dev, MUnit.ODR,DoorBellAdapterNormRespReady); - aac_response_normal(&dev->queues->queue[HostNormRespQueue]); - } - else if (bellbits & DoorBellAdapterNormCmdNotFull) { - rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull); + else if (unlikely(bellbits & DoorBellAdapterNormCmdReady)) { + rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdReady); + aac_command_normal(&dev->queues->queue[HostNormCmdQueue]); + } + else if (likely(bellbits & DoorBellAdapterNormRespReady)) { + rx_writel(dev, MUnit.ODR,DoorBellAdapterNormRespReady); + aac_response_normal(&dev->queues->queue[HostNormRespQueue]); + } + else if (unlikely(bellbits & DoorBellAdapterNormCmdNotFull)) { + rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull); + } + else if (unlikely(bellbits & DoorBellAdapterNormRespNotFull)) { + 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) +{ + int isAif, isFastResponse, isSpecial; + struct aac_dev *dev = dev_id; + u32 Index = rx_readl(dev, MUnit.OutboundQueue); + if (unlikely(Index == 0xFFFFFFFFL)) + Index = rx_readl(dev, MUnit.OutboundQueue); + if (likely(Index != 0xFFFFFFFFL)) { + do { + isAif = isFastResponse = isSpecial = 0; + if (Index & 0x00000002L) { + isAif = 1; + if (Index == 0xFFFFFFFEL) + isSpecial = 1; + Index &= ~0x00000002L; + } else { + if (Index & 0x00000001L) + isFastResponse = 1; + Index >>= 2; } - else if (bellbits & DoorBellAdapterNormRespNotFull) { - rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull); - rx_writel(dev, MUnit.ODR, DoorBellAdapterNormRespNotFull); + if (!isSpecial) { + if (unlikely(aac_intr_normal(dev, + Index, isAif, + isFastResponse, NULL))) { + rx_writel(dev, + MUnit.OutboundQueue, + Index); + rx_writel(dev, + MUnit.ODR, + DoorBellAdapterNormRespReady); + } } - return IRQ_HANDLED; - } + Index = rx_readl(dev, MUnit.OutboundQueue); + } while (Index != 0xFFFFFFFFL); + return IRQ_HANDLED; } return IRQ_NONE; } @@ -115,6 +133,26 @@ static void aac_rx_disable_interrupt(struct aac_dev *dev) } /** + * 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); +} + +/** * rx_sync_cmd - send a command and wait * @dev: Adapter * @command: Command to execute @@ -134,14 +172,14 @@ static int rx_sync_cmd(struct aac_dev *dev, u32 command, /* * Write the command into Mailbox 0 */ - rx_writel(dev, InboundMailbox0, command); + writel(command, &dev->IndexRegs->Mailbox[0]); /* * Write the parameters into Mailboxes 1 - 6 */ - rx_writel(dev, InboundMailbox1, p1); - rx_writel(dev, InboundMailbox2, p2); - rx_writel(dev, InboundMailbox3, p3); - rx_writel(dev, InboundMailbox4, p4); + writel(p1, &dev->IndexRegs->Mailbox[1]); + writel(p2, &dev->IndexRegs->Mailbox[2]); + writel(p3, &dev->IndexRegs->Mailbox[3]); + writel(p4, &dev->IndexRegs->Mailbox[4]); /* * Clear the synch command doorbell to start on a clean slate. */ @@ -183,31 +221,28 @@ static int rx_sync_cmd(struct aac_dev *dev, u32 command, /* * Yield the processor in case we are slow */ - schedule_timeout_uninterruptible(1); + msleep(1); } - if (ok != 1) { + if (unlikely(ok != 1)) { /* * Restore interrupt mask even though we timed out */ - if (dev->new_comm_interface) - rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xf7); - else - rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb); + aac_adapter_enable_int(dev); return -ETIMEDOUT; } /* * Pull the synch status from Mailbox 0. */ if (status) - *status = rx_readl(dev, IndexRegs.Mailbox[0]); + *status = readl(&dev->IndexRegs->Mailbox[0]); if (r1) - *r1 = rx_readl(dev, IndexRegs.Mailbox[1]); + *r1 = readl(&dev->IndexRegs->Mailbox[1]); if (r2) - *r2 = rx_readl(dev, IndexRegs.Mailbox[2]); + *r2 = readl(&dev->IndexRegs->Mailbox[2]); if (r3) - *r3 = rx_readl(dev, IndexRegs.Mailbox[3]); + *r3 = readl(&dev->IndexRegs->Mailbox[3]); if (r4) - *r4 = rx_readl(dev, IndexRegs.Mailbox[4]); + *r4 = readl(&dev->IndexRegs->Mailbox[4]); /* * Clear the synch command doorbell. */ @@ -215,10 +250,7 @@ static int rx_sync_cmd(struct aac_dev *dev, u32 command, /* * Restore interrupt mask */ - if (dev->new_comm_interface) - rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xf7); - else - rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb); + aac_adapter_enable_int(dev); return 0; } @@ -261,8 +293,6 @@ static void aac_rx_notify_adapter(struct aac_dev *dev, u32 event) rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_3); break; case HostShutdown: -// rx_sync_cmd(dev, HOST_CRASHING, 0, 0, 0, 0, 0, 0, -// NULL, NULL, NULL, NULL, NULL); break; case FastIo: rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_6); @@ -308,12 +338,12 @@ static int aac_rx_check_health(struct aac_dev *dev) /* * Check to see if the board failed any self tests. */ - if (status & SELF_TEST_FAILED) + if (unlikely(status & SELF_TEST_FAILED)) return -1; /* * Check to see if the board panic'd. */ - if (status & KERNEL_PANIC) { + if (unlikely(status & KERNEL_PANIC)) { char * buffer; struct POSTSTATUS { __le32 Post_Command; @@ -322,15 +352,15 @@ static int aac_rx_check_health(struct aac_dev *dev) dma_addr_t paddr, baddr; int ret; - if ((status & 0xFF000000L) == 0xBC000000L) + if (likely((status & 0xFF000000L) == 0xBC000000L)) return (status >> 16) & 0xFF; buffer = pci_alloc_consistent(dev->pdev, 512, &baddr); ret = -2; - if (buffer == NULL) + if (unlikely(buffer == NULL)) return ret; post = pci_alloc_consistent(dev->pdev, sizeof(struct POSTSTATUS), &paddr); - if (post == NULL) { + if (unlikely(post == NULL)) { pci_free_consistent(dev->pdev, 512, buffer, baddr); return ret; } @@ -342,10 +372,9 @@ static int aac_rx_check_health(struct aac_dev *dev) NULL, NULL, NULL, NULL, NULL); pci_free_consistent(dev->pdev, sizeof(struct POSTSTATUS), post, paddr); - if ((buffer[0] == '0') && (buffer[1] == 'x')) { - ret = (buffer[2] <= '9') ? (buffer[2] - '0') : (buffer[2] - 'A' + 10); - ret <<= 4; - ret += (buffer[3] <= '9') ? (buffer[3] - '0') : (buffer[3] - 'A' + 10); + if (likely((buffer[0] == '0') && ((buffer[1] == 'x') || (buffer[1] == 'X')))) { + ret = (hex_to_bin(buffer[2]) << 4) + + hex_to_bin(buffer[3]); } pci_free_consistent(dev->pdev, 512, buffer, baddr); return ret; @@ -353,7 +382,7 @@ static int aac_rx_check_health(struct aac_dev *dev) /* * Wait for the adapter to be up and running. */ - if (!(status & KERNEL_UP_AND_RUNNING)) + if (unlikely(!(status & KERNEL_UP_AND_RUNNING))) return -3; /* * Everything is OK @@ -362,35 +391,152 @@ static int aac_rx_check_health(struct aac_dev *dev) } /** - * aac_rx_send + * aac_rx_deliver_producer * @fib: fib to issue * * Will send a fib, returning 0 if successful. */ -static int aac_rx_send(struct fib * fib) +int aac_rx_deliver_producer(struct fib * fib) { - u64 addr = fib->hw_fib_pa; struct aac_dev *dev = fib->dev; - volatile void __iomem *device = dev->regs.rx; + struct aac_queue *q = &dev->queues->queue[AdapNormCmdQueue]; + unsigned long qflags; u32 Index; + unsigned long nointr = 0; + + spin_lock_irqsave(q->lock, qflags); + aac_queue_get( dev, &Index, AdapNormCmdQueue, fib->hw_fib_va, 1, fib, &nointr); - dprintk((KERN_DEBUG "%p->aac_rx_send(%p->%llx)\n", dev, fib, addr)); - Index = rx_readl(dev, MUnit.InboundQueue); - if (Index == 0xFFFFFFFFL) + q->numpending++; + *(q->headers.producer) = cpu_to_le32(Index + 1); + spin_unlock_irqrestore(q->lock, qflags); + 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]; + unsigned long qflags; + u32 Index; + u64 addr; + volatile void __iomem *device; + + unsigned long count = 10000000L; /* 50 seconds */ + spin_lock_irqsave(q->lock, qflags); + q->numpending++; + spin_unlock_irqrestore(q->lock, qflags); + for(;;) { Index = rx_readl(dev, MUnit.InboundQueue); - dprintk((KERN_DEBUG "Index = 0x%x\n", Index)); - if (Index == 0xFFFFFFFFL) - return Index; - device += Index; - dprintk((KERN_DEBUG "entry = %x %x %u\n", (u32)(addr & 0xffffffff), - (u32)(addr >> 32), (u32)le16_to_cpu(fib->hw_fib->header.Size))); + if (unlikely(Index == 0xFFFFFFFFL)) + Index = rx_readl(dev, MUnit.InboundQueue); + if (likely(Index != 0xFFFFFFFFL)) + break; + if (--count == 0) { + spin_lock_irqsave(q->lock, qflags); + q->numpending--; + spin_unlock_irqrestore(q->lock, qflags); + return -ETIMEDOUT; + } + udelay(5); + } + device = dev->base + Index; + addr = fib->hw_fib_pa; writel((u32)(addr & 0xffffffff), device); device += sizeof(u32); writel((u32)(addr >> 32), device); device += sizeof(u32); - writel(le16_to_cpu(fib->hw_fib->header.Size), device); + writel(le16_to_cpu(fib->hw_fib_va->header.Size), device); rx_writel(dev, MUnit.InboundQueue, Index); - dprintk((KERN_DEBUG "aac_rx_send - return 0\n")); + return 0; +} + +/** + * 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; + } + dev->base = dev->regs.rx = ioremap(dev->base_start, size); + if (dev->base == NULL) + return -1; + dev->IndexRegs = &dev->regs.rx->IndexRegs; + return 0; +} + +static int aac_rx_restart_adapter(struct aac_dev *dev, int bled) +{ + u32 var = 0; + + if (!(dev->supplement_adapter_info.SupportedOptions2 & + AAC_OPTION_MU_RESET) || (bled >= 0) || (bled == -2)) { + if (bled) + printk(KERN_ERR "%s%d: adapter kernel panic'd %x.\n", + 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); + if (!bled && (var != 0x00000001) && (var != 0x3803000F)) + 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); + + if (bled && (bled != -ETIMEDOUT)) + return -EINVAL; + } + if (bled && (var == 0x3803000F)) { /* USE_OTHER_METHOD */ + rx_writel(dev, MUnit.reserved2, 3); + msleep(5000); /* Delay 5 seconds */ + var = 0x00000001; + } + if (bled && (var != 0x00000001)) + return -EINVAL; + ssleep(5); + if (rx_readl(dev, MUnit.OMRx[0]) & KERNEL_PANIC) + return -ENODEV; + if (startup_timeout < 300) + startup_timeout = 300; + return 0; +} + +/** + * 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; } @@ -403,37 +549,49 @@ static int aac_rx_send(struct fib * fib) * to the comm region. */ -int aac_rx_init(struct aac_dev *dev) +int _aac_rx_init(struct aac_dev *dev) { unsigned long start; unsigned long status; - int instance; - const char * name; + int restart = 0; + int instance = dev->id; + const char * name = dev->name; - instance = dev->id; - name = dev->name; + if (aac_adapter_ioremap(dev, dev->base_size)) { + printk(KERN_WARNING "%s: unable to map adapter.\n", name); + goto error_iounmap; + } + /* Failure to reset here is an option ... */ + dev->a_ops.adapter_sync_cmd = rx_sync_cmd; + dev->a_ops.adapter_enable_int = aac_rx_disable_interrupt; + dev->OIMR = status = rx_readb (dev, MUnit.OIMR); + if ((((status & 0x0c) != 0x0c) || aac_reset_devices || reset_devices) && + !aac_rx_restart_adapter(dev, 0)) + /* Make sure the Hardware FIFO is empty */ + while ((++restart < 512) && + (rx_readl(dev, MUnit.OutboundQueue) != 0xFFFFFFFFL)); /* * Check to see if the board panic'd while booting. */ + status = rx_readl(dev, MUnit.OMRx[0]); + if (status & KERNEL_PANIC) { + if (aac_rx_restart_adapter(dev, aac_rx_check_health(dev))) + goto error_iounmap; + ++restart; + } /* * Check to see if the board failed any self tests. */ - if (rx_readl(dev, MUnit.OMRx[0]) & SELF_TEST_FAILED) { + status = rx_readl(dev, MUnit.OMRx[0]); + if (status & SELF_TEST_FAILED) { printk(KERN_ERR "%s%d: adapter self-test failed.\n", dev->name, instance); goto error_iounmap; } /* - * Check to see if the board panic'd while booting. - */ - if (rx_readl(dev, MUnit.OMRx[0]) & KERNEL_PANIC) { - printk(KERN_ERR "%s%d: adapter kernel panic.\n", dev->name, instance); - goto error_iounmap; - } - /* * Check to see if the monitor panic'd while booting. */ - if (rx_readl(dev, MUnit.OMRx[0]) & MONITOR_PANIC) { + if (status & MONITOR_PANIC) { printk(KERN_ERR "%s%d: adapter monitor panic.\n", dev->name, instance); goto error_iounmap; } @@ -441,58 +599,86 @@ int aac_rx_init(struct aac_dev *dev) /* * Wait for the adapter to be up and running. Wait up to 3 minutes */ - while ((!(rx_readl(dev, IndexRegs.Mailbox[7]) & KERNEL_UP_AND_RUNNING)) - || (!(rx_readl(dev, MUnit.OMRx[0]) & KERNEL_UP_AND_RUNNING))) + while (!((status = rx_readl(dev, MUnit.OMRx[0])) & KERNEL_UP_AND_RUNNING)) { - if(time_after(jiffies, start+180*HZ)) - { - status = rx_readl(dev, IndexRegs.Mailbox[7]); + if ((restart && + (status & (KERNEL_PANIC|SELF_TEST_FAILED|MONITOR_PANIC))) || + time_after(jiffies, start+HZ*startup_timeout)) { printk(KERN_ERR "%s%d: adapter kernel failed to start, init status = %lx.\n", dev->name, instance, status); goto error_iounmap; } - schedule_timeout_uninterruptible(1); - } - if (request_irq(dev->scsi_host_ptr->irq, aac_rx_intr, SA_SHIRQ|SA_INTERRUPT, "aacraid", (void *)dev)<0) - { - printk(KERN_ERR "%s%d: Interrupt unavailable.\n", name, instance); - goto error_iounmap; + if (!restart && + ((status & (KERNEL_PANIC|SELF_TEST_FAILED|MONITOR_PANIC)) || + time_after(jiffies, start + HZ * + ((startup_timeout > 60) + ? (startup_timeout - 60) + : (startup_timeout / 2))))) { + if (likely(!aac_rx_restart_adapter(dev, aac_rx_check_health(dev)))) + start = jiffies; + ++restart; + } + msleep(1); } + if (restart && aac_commit) + aac_commit = 1; /* - * Fill in the function dispatch table. + * Fill in the common function dispatch table. */ dev->a_ops.adapter_interrupt = aac_rx_interrupt_adapter; dev->a_ops.adapter_disable_int = aac_rx_disable_interrupt; 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; - dev->a_ops.adapter_send = aac_rx_send; + dev->a_ops.adapter_restart = aac_rx_restart_adapter; /* * First clear out all interrupts. Then enable the one's that we * can handle. */ - rx_writeb(dev, MUnit.OIMR, 0xff); + aac_adapter_comm(dev, AAC_COMM_PRODUCER); + aac_adapter_disable_int(dev); rx_writel(dev, MUnit.ODR, 0xffffffff); - rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb); + aac_adapter_enable_int(dev); if (aac_init_adapter(dev) == NULL) - goto error_irq; - if (dev->new_comm_interface) - rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xf7); + goto error_iounmap; + aac_adapter_comm(dev, dev->comm_interface); + dev->sync_mode = 0; /* sync. mode not supported */ + dev->msi = aac_msi && !pci_enable_msi(dev->pdev); + if (request_irq(dev->pdev->irq, dev->a_ops.adapter_intr, + IRQF_SHARED, "aacraid", dev) < 0) { + if (dev->msi) + pci_disable_msi(dev->pdev); + printk(KERN_ERR "%s%d: Interrupt unavailable.\n", + name, instance); + goto error_iounmap; + } + dev->dbg_base = dev->base_start; + dev->dbg_base_mapped = dev->base; + dev->dbg_size = dev->base_size; + aac_adapter_enable_int(dev); /* - * Tell the adapter that all is configured, and it can start - * accepting requests + * Tell the adapter that all is configured, and it can + * start accepting requests */ aac_rx_start_adapter(dev); - return 0; -error_irq: - rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff); - free_irq(dev->scsi_host_ptr->irq, (void *)dev); + return 0; error_iounmap: return -1; } + +int aac_rx_init(struct aac_dev *dev) +{ + /* + * Fill in the function dispatch table. + */ + dev->a_ops.adapter_ioremap = aac_rx_ioremap; + dev->a_ops.adapter_comm = aac_rx_select_comm; + + return _aac_rx_init(dev); +} |
