X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fscsi%2Faacraid%2Frkt.c;h=7a23e027eb782911b58d9f109d799a3143dda884;hb=43bc926fffd92024b46cafaf7350d669ba9ca884;hp=1b8ed47cfe30be3a7137141ff37da7140a48f336;hpb=cee37fe97739d85991964371c1f3a745c00dd236;p=linux-2.6.git diff --git a/drivers/scsi/aacraid/rkt.c b/drivers/scsi/aacraid/rkt.c index 1b8ed47cf..7a23e027e 100644 --- a/drivers/scsi/aacraid/rkt.c +++ b/drivers/scsi/aacraid/rkt.c @@ -49,44 +49,71 @@ static irqreturn_t aac_rkt_intr(int irq, void *dev_id, struct pt_regs *regs) { struct aac_dev *dev = dev_id; - unsigned long bellbits; - u8 intstat, mask; - intstat = rkt_readb(dev, MUnit.OISR); - /* - * Read mask and invert because drawbridge is reversed. - * This allows us to only service interrupts that have - * been enabled. - */ - mask = ~(dev->OIMR); - /* Check to see if this is our interrupt. If it isn't just return */ - if (intstat & mask) - { - bellbits = rkt_readl(dev, OutboundDoorbellReg); - if (bellbits & DoorBellPrintfReady) { - aac_printf(dev, rkt_readl(dev, IndexRegs.Mailbox[5])); - rkt_writel(dev, MUnit.ODR,DoorBellPrintfReady); - rkt_writel(dev, InboundDoorbellReg,DoorBellPrintfDone); - } - else if (bellbits & DoorBellAdapterNormCmdReady) { - rkt_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdReady); - aac_command_normal(&dev->queues->queue[HostNormCmdQueue]); - } - else if (bellbits & DoorBellAdapterNormRespReady) { - aac_response_normal(&dev->queues->queue[HostNormRespQueue]); - rkt_writel(dev, MUnit.ODR,DoorBellAdapterNormRespReady); - } - else if (bellbits & DoorBellAdapterNormCmdNotFull) { - rkt_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull); + + if (dev->new_comm_interface) { + u32 Index = rkt_readl(dev, MUnit.OutboundQueue); + if (Index == 0xFFFFFFFFL) + Index = rkt_readl(dev, MUnit.OutboundQueue); + if (Index != 0xFFFFFFFFL) { + do { + if (aac_intr_normal(dev, Index)) { + rkt_writel(dev, MUnit.OutboundQueue, Index); + rkt_writel(dev, MUnit.ODR, DoorBellAdapterNormRespReady); + } + Index = rkt_readl(dev, MUnit.OutboundQueue); + } while (Index != 0xFFFFFFFFL); + return IRQ_HANDLED; } - else if (bellbits & DoorBellAdapterNormRespNotFull) { - rkt_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull); - rkt_writel(dev, MUnit.ODR, DoorBellAdapterNormRespNotFull); + } else { + unsigned long bellbits; + u8 intstat; + intstat = rkt_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 = rkt_readl(dev, OutboundDoorbellReg); + if (bellbits & DoorBellPrintfReady) { + aac_printf(dev, rkt_readl (dev, IndexRegs.Mailbox[5])); + rkt_writel(dev, MUnit.ODR,DoorBellPrintfReady); + rkt_writel(dev, InboundDoorbellReg,DoorBellPrintfDone); + } + else if (bellbits & DoorBellAdapterNormCmdReady) { + rkt_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdReady); + aac_command_normal(&dev->queues->queue[HostNormCmdQueue]); +// rkt_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdReady); + } + else if (bellbits & DoorBellAdapterNormRespReady) { + rkt_writel(dev, MUnit.ODR,DoorBellAdapterNormRespReady); + aac_response_normal(&dev->queues->queue[HostNormRespQueue]); + } + else if (bellbits & DoorBellAdapterNormCmdNotFull) { + rkt_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull); + } + else if (bellbits & DoorBellAdapterNormRespNotFull) { + rkt_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull); + rkt_writel(dev, MUnit.ODR, DoorBellAdapterNormRespNotFull); + } + return IRQ_HANDLED; } - return IRQ_HANDLED; } return IRQ_NONE; } +/** + * aac_rkt_disable_interrupt - Disable interrupts + * @dev: Adapter + */ + +static void aac_rkt_disable_interrupt(struct aac_dev *dev) +{ + rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff); +} + /** * rkt_sync_cmd - send a command and wait * @dev: Adapter @@ -98,7 +125,9 @@ static irqreturn_t aac_rkt_intr(int irq, void *dev_id, struct pt_regs *regs) * for its completion. */ -static int rkt_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *status) +static int rkt_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) { unsigned long start; int ok; @@ -107,12 +136,12 @@ static int rkt_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *status) */ rkt_writel(dev, InboundMailbox0, command); /* - * Write the parameters into Mailboxes 1 - 4 + * Write the parameters into Mailboxes 1 - 6 */ rkt_writel(dev, InboundMailbox1, p1); - rkt_writel(dev, InboundMailbox2, 0); - rkt_writel(dev, InboundMailbox3, 0); - rkt_writel(dev, InboundMailbox4, 0); + rkt_writel(dev, InboundMailbox2, p2); + rkt_writel(dev, InboundMailbox3, p3); + rkt_writel(dev, InboundMailbox4, p4); /* * Clear the synch command doorbell to start on a clean slate. */ @@ -154,14 +183,16 @@ static int rkt_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *status) /* * Yield the processor in case we are slow */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); + msleep(1); } if (ok != 1) { /* * Restore interrupt mask even though we timed out */ - rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb); + if (dev->new_comm_interface) + rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xf7); + else + rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb); return -ETIMEDOUT; } /* @@ -169,6 +200,14 @@ static int rkt_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *status) */ if (status) *status = rkt_readl(dev, IndexRegs.Mailbox[0]); + if (r1) + *r1 = rkt_readl(dev, IndexRegs.Mailbox[1]); + if (r2) + *r2 = rkt_readl(dev, IndexRegs.Mailbox[2]); + if (r3) + *r3 = rkt_readl(dev, IndexRegs.Mailbox[3]); + if (r4) + *r4 = rkt_readl(dev, IndexRegs.Mailbox[4]); /* * Clear the synch command doorbell. */ @@ -176,7 +215,10 @@ static int rkt_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *status) /* * Restore interrupt mask */ - rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb); + if (dev->new_comm_interface) + rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xf7); + else + rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb); return 0; } @@ -190,8 +232,8 @@ static int rkt_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *status) static void aac_rkt_interrupt_adapter(struct aac_dev *dev) { - u32 ret; - rkt_sync_cmd(dev, BREAKPOINT_REQUEST, 0, &ret); + rkt_sync_cmd(dev, BREAKPOINT_REQUEST, 0, 0, 0, 0, 0, 0, + NULL, NULL, NULL, NULL, NULL); } /** @@ -220,7 +262,8 @@ static void aac_rkt_notify_adapter(struct aac_dev *dev, u32 event) rkt_writel(dev, MUnit.IDR,INBOUNDDOORBELL_3); break; case HostShutdown: -// rkt_sync_cmd(dev, HOST_CRASHING, 0, 0, 0, 0, &ret); +// rkt_sync_cmd(dev, HOST_CRASHING, 0, 0, 0, 0, 0, 0, +// NULL, NULL, NULL, NULL, NULL); break; case FastIo: rkt_writel(dev, MUnit.IDR,INBOUNDDOORBELL_6); @@ -243,27 +286,13 @@ static void aac_rkt_notify_adapter(struct aac_dev *dev, u32 event) static void aac_rkt_start_adapter(struct aac_dev *dev) { - u32 status; struct aac_init *init; init = dev->init; init->HostElapsedSeconds = cpu_to_le32(get_seconds()); - /* - * Tell the adapter we are back and up and running so it will scan - * its command queues and enable our interrupts - */ - dev->irq_mask = (DoorBellPrintfReady | OUTBOUNDDOORBELL_1 | OUTBOUNDDOORBELL_2 | OUTBOUNDDOORBELL_3 | OUTBOUNDDOORBELL_4); - /* - * First clear out all interrupts. Then enable the one's that we - * can handle. - */ - rkt_writeb(dev, MUnit.OIMR, 0xff); - rkt_writel(dev, MUnit.ODR, 0xffffffff); -// rkt_writeb(dev, MUnit.OIMR, ~(u8)OUTBOUND_DOORBELL_INTERRUPT_MASK); - rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb); - // We can only use a 32 bit address here - rkt_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (u32)(ulong)dev->init_pa, &status); + rkt_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (u32)(ulong)dev->init_pa, + 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL); } /** @@ -288,8 +317,8 @@ static int aac_rkt_check_health(struct aac_dev *dev) if (status & KERNEL_PANIC) { char * buffer; struct POSTSTATUS { - u32 Post_Command; - u32 Post_Address; + __le32 Post_Command; + __le32 Post_Address; } * post; dma_addr_t paddr, baddr; int ret; @@ -310,10 +339,11 @@ static int aac_rkt_check_health(struct aac_dev *dev) post->Post_Command = cpu_to_le32(COMMAND_POST_RESULTS); post->Post_Address = cpu_to_le32(baddr); rkt_writel(dev, MUnit.IMRx[0], paddr); - rkt_sync_cmd(dev, COMMAND_POST_RESULTS, baddr, &status); + rkt_sync_cmd(dev, COMMAND_POST_RESULTS, baddr, 0, 0, 0, 0, 0, + NULL, NULL, NULL, NULL, NULL); pci_free_consistent(dev->pdev, sizeof(struct POSTSTATUS), post, paddr); - if ((buffer[0] == '0') && (buffer[1] == 'x')) { + if ((buffer[0] == '0') && ((buffer[1] == 'x') || (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); @@ -332,6 +362,39 @@ static int aac_rkt_check_health(struct aac_dev *dev) return 0; } +/** + * aac_rkt_send + * @fib: fib to issue + * + * Will send a fib, returning 0 if successful. + */ +static int aac_rkt_send(struct fib * fib) +{ + u64 addr = fib->hw_fib_pa; + struct aac_dev *dev = fib->dev; + volatile void __iomem *device = dev->regs.rkt; + u32 Index; + + dprintk((KERN_DEBUG "%p->aac_rkt_send(%p->%llx)\n", dev, fib, addr)); + Index = rkt_readl(dev, MUnit.InboundQueue); + if (Index == 0xFFFFFFFFL) + Index = rkt_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))); + 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); + rkt_writel(dev, MUnit.InboundQueue, Index); + dprintk((KERN_DEBUG "aac_rkt_send - return 0\n")); + return 0; +} + /** * aac_rkt_init - initialize an i960 based AAC card * @dev: device to configure @@ -352,13 +415,8 @@ int aac_rkt_init(struct aac_dev *dev) name = dev->name; /* - * Map in the registers from the adapter. + * Check to see if the board panic'd while booting. */ - if((dev->regs.rkt = ioremap((unsigned long)dev->scsi_host_ptr->base, 8192))==NULL) - { - printk(KERN_WARNING "aacraid: unable to map i960.\n" ); - goto error_iounmap; - } /* * Check to see if the board failed any self tests. */ @@ -393,8 +451,7 @@ int aac_rkt_init(struct aac_dev *dev) dev->name, instance, status); goto error_iounmap; } - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_uninterruptible(1); } if (request_irq(dev->scsi_host_ptr->irq, aac_rkt_intr, SA_SHIRQ|SA_INTERRUPT, "aacraid", (void *)dev)<0) { @@ -405,21 +462,40 @@ int aac_rkt_init(struct aac_dev *dev) * Fill in the function dispatch table. */ dev->a_ops.adapter_interrupt = aac_rkt_interrupt_adapter; + dev->a_ops.adapter_disable_int = aac_rkt_disable_interrupt; dev->a_ops.adapter_notify = aac_rkt_notify_adapter; dev->a_ops.adapter_sync_cmd = rkt_sync_cmd; dev->a_ops.adapter_check_health = aac_rkt_check_health; + dev->a_ops.adapter_send = aac_rkt_send; - if (aac_init_adapter(dev) == NULL) - goto error_irq; /* - * Start any kernel threads needed + * First clear out all interrupts. Then enable the one's that we + * can handle. */ - dev->thread_pid = kernel_thread((int (*)(void *))aac_command_thread, dev, 0); - if(dev->thread_pid < 0) - { - printk(KERN_ERR "aacraid: Unable to create rkt thread.\n"); - goto error_kfree; - } + rkt_writeb(dev, MUnit.OIMR, 0xff); + rkt_writel(dev, MUnit.ODR, 0xffffffff); + rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb); + + if (aac_init_adapter(dev) == NULL) + goto error_irq; + if (dev->new_comm_interface) { + /* + * FIB Setup has already been done, but we can minimize the + * damage by at least ensuring the OS never issues more + * commands than we can handle. The Rocket adapters currently + * can only handle 246 commands and 8 AIFs at the same time, + * and in fact do notify us accordingly if we negotiate the + * FIB size. The problem that causes us to add this check is + * to ensure that we do not overdo it with the adapter when a + * hard coded FIB override is being utilized. This special + * case warrants this half baked, but convenient, check here. + */ + if (dev->scsi_host_ptr->can_queue > (246 - AAC_NUM_MGT_FIB)) { + dev->init->MaxIoCommands = cpu_to_le32(246); + dev->scsi_host_ptr->can_queue = 246 - AAC_NUM_MGT_FIB; + } + rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xf7); + } /* * Tell the adapter that all is configured, and it can start * accepting requests @@ -427,14 +503,11 @@ int aac_rkt_init(struct aac_dev *dev) aac_rkt_start_adapter(dev); return 0; -error_kfree: - kfree(dev->queues); - error_irq: + rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff); free_irq(dev->scsi_host_ptr->irq, (void *)dev); error_iounmap: - iounmap(dev->regs.rkt); return -1; }