1e8b12f0fSMahesh Rajashekhara /* 2e8b12f0fSMahesh Rajashekhara * Adaptec AAC series RAID controller driver 3e8b12f0fSMahesh Rajashekhara * (c) Copyright 2001 Red Hat Inc. 4e8b12f0fSMahesh Rajashekhara * 5e8b12f0fSMahesh Rajashekhara * based on the old aacraid driver that is.. 6e8b12f0fSMahesh Rajashekhara * Adaptec aacraid device driver for Linux. 7e8b12f0fSMahesh Rajashekhara * 8e8b12f0fSMahesh Rajashekhara * Copyright (c) 2000-2010 Adaptec, Inc. 9e8b12f0fSMahesh Rajashekhara * 2010 PMC-Sierra, Inc. (aacraid@pmc-sierra.com) 10e8b12f0fSMahesh Rajashekhara * 11e8b12f0fSMahesh Rajashekhara * This program is free software; you can redistribute it and/or modify 12e8b12f0fSMahesh Rajashekhara * it under the terms of the GNU General Public License as published by 13e8b12f0fSMahesh Rajashekhara * the Free Software Foundation; either version 2, or (at your option) 14e8b12f0fSMahesh Rajashekhara * any later version. 15e8b12f0fSMahesh Rajashekhara * 16e8b12f0fSMahesh Rajashekhara * This program is distributed in the hope that it will be useful, 17e8b12f0fSMahesh Rajashekhara * but WITHOUT ANY WARRANTY; without even the implied warranty of 18e8b12f0fSMahesh Rajashekhara * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19e8b12f0fSMahesh Rajashekhara * GNU General Public License for more details. 20e8b12f0fSMahesh Rajashekhara * 21e8b12f0fSMahesh Rajashekhara * You should have received a copy of the GNU General Public License 22e8b12f0fSMahesh Rajashekhara * along with this program; see the file COPYING. If not, write to 23e8b12f0fSMahesh Rajashekhara * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 24e8b12f0fSMahesh Rajashekhara * 25e8b12f0fSMahesh Rajashekhara * Module Name: 26e8b12f0fSMahesh Rajashekhara * src.c 27e8b12f0fSMahesh Rajashekhara * 28e8b12f0fSMahesh Rajashekhara * Abstract: Hardware Device Interface for PMC SRC based controllers 29e8b12f0fSMahesh Rajashekhara * 30e8b12f0fSMahesh Rajashekhara */ 31e8b12f0fSMahesh Rajashekhara 32e8b12f0fSMahesh Rajashekhara #include <linux/kernel.h> 33e8b12f0fSMahesh Rajashekhara #include <linux/init.h> 34e8b12f0fSMahesh Rajashekhara #include <linux/types.h> 35e8b12f0fSMahesh Rajashekhara #include <linux/pci.h> 36e8b12f0fSMahesh Rajashekhara #include <linux/spinlock.h> 37e8b12f0fSMahesh Rajashekhara #include <linux/slab.h> 38e8b12f0fSMahesh Rajashekhara #include <linux/blkdev.h> 39e8b12f0fSMahesh Rajashekhara #include <linux/delay.h> 40e8b12f0fSMahesh Rajashekhara #include <linux/completion.h> 41e8b12f0fSMahesh Rajashekhara #include <linux/time.h> 42e8b12f0fSMahesh Rajashekhara #include <linux/interrupt.h> 43e8b12f0fSMahesh Rajashekhara #include <scsi/scsi_host.h> 44e8b12f0fSMahesh Rajashekhara 45e8b12f0fSMahesh Rajashekhara #include "aacraid.h" 46e8b12f0fSMahesh Rajashekhara 47e8b12f0fSMahesh Rajashekhara static irqreturn_t aac_src_intr_message(int irq, void *dev_id) 48e8b12f0fSMahesh Rajashekhara { 49e8b12f0fSMahesh Rajashekhara struct aac_dev *dev = dev_id; 50e8b12f0fSMahesh Rajashekhara unsigned long bellbits, bellbits_shifted; 51e8b12f0fSMahesh Rajashekhara int our_interrupt = 0; 52e8b12f0fSMahesh Rajashekhara int isFastResponse; 53e8b12f0fSMahesh Rajashekhara u32 index, handle; 54e8b12f0fSMahesh Rajashekhara 55e8b12f0fSMahesh Rajashekhara bellbits = src_readl(dev, MUnit.ODR_R); 56e8b12f0fSMahesh Rajashekhara if (bellbits & PmDoorBellResponseSent) { 57e8b12f0fSMahesh Rajashekhara bellbits = PmDoorBellResponseSent; 58e8b12f0fSMahesh Rajashekhara /* handle async. status */ 59e8b12f0fSMahesh Rajashekhara our_interrupt = 1; 60e8b12f0fSMahesh Rajashekhara index = dev->host_rrq_idx; 61e8b12f0fSMahesh Rajashekhara if (dev->host_rrq[index] == 0) { 62e8b12f0fSMahesh Rajashekhara u32 old_index = index; 63e8b12f0fSMahesh Rajashekhara /* adjust index */ 64e8b12f0fSMahesh Rajashekhara do { 65e8b12f0fSMahesh Rajashekhara index++; 66e8b12f0fSMahesh Rajashekhara if (index == dev->scsi_host_ptr->can_queue + 67e8b12f0fSMahesh Rajashekhara AAC_NUM_MGT_FIB) 68e8b12f0fSMahesh Rajashekhara index = 0; 69e8b12f0fSMahesh Rajashekhara if (dev->host_rrq[index] != 0) 70e8b12f0fSMahesh Rajashekhara break; 71e8b12f0fSMahesh Rajashekhara } while (index != old_index); 72e8b12f0fSMahesh Rajashekhara dev->host_rrq_idx = index; 73e8b12f0fSMahesh Rajashekhara } 74e8b12f0fSMahesh Rajashekhara for (;;) { 75e8b12f0fSMahesh Rajashekhara isFastResponse = 0; 76e8b12f0fSMahesh Rajashekhara /* remove toggle bit (31) */ 77e8b12f0fSMahesh Rajashekhara handle = (dev->host_rrq[index] & 0x7fffffff); 78e8b12f0fSMahesh Rajashekhara /* check fast response bit (30) */ 79e8b12f0fSMahesh Rajashekhara if (handle & 0x40000000) 80e8b12f0fSMahesh Rajashekhara isFastResponse = 1; 81e8b12f0fSMahesh Rajashekhara handle &= 0x0000ffff; 82e8b12f0fSMahesh Rajashekhara if (handle == 0) 83e8b12f0fSMahesh Rajashekhara break; 84e8b12f0fSMahesh Rajashekhara 85e8b12f0fSMahesh Rajashekhara aac_intr_normal(dev, handle-1, 0, isFastResponse, NULL); 86e8b12f0fSMahesh Rajashekhara 87e8b12f0fSMahesh Rajashekhara dev->host_rrq[index++] = 0; 88e8b12f0fSMahesh Rajashekhara if (index == dev->scsi_host_ptr->can_queue + 89e8b12f0fSMahesh Rajashekhara AAC_NUM_MGT_FIB) 90e8b12f0fSMahesh Rajashekhara index = 0; 91e8b12f0fSMahesh Rajashekhara dev->host_rrq_idx = index; 92e8b12f0fSMahesh Rajashekhara } 93e8b12f0fSMahesh Rajashekhara } else { 94e8b12f0fSMahesh Rajashekhara bellbits_shifted = (bellbits >> SRC_ODR_SHIFT); 95e8b12f0fSMahesh Rajashekhara if (bellbits_shifted & DoorBellAifPending) { 96e8b12f0fSMahesh Rajashekhara our_interrupt = 1; 97e8b12f0fSMahesh Rajashekhara /* handle AIF */ 98e8b12f0fSMahesh Rajashekhara aac_intr_normal(dev, 0, 2, 0, NULL); 9911604612SMahesh Rajashekhara } else if (bellbits_shifted & OUTBOUNDDOORBELL_0) { 10011604612SMahesh Rajashekhara unsigned long sflags; 10111604612SMahesh Rajashekhara struct list_head *entry; 10211604612SMahesh Rajashekhara int send_it = 0; 10311604612SMahesh Rajashekhara 10411604612SMahesh Rajashekhara if (dev->sync_fib) { 10511604612SMahesh Rajashekhara our_interrupt = 1; 10611604612SMahesh Rajashekhara if (dev->sync_fib->callback) 10711604612SMahesh Rajashekhara dev->sync_fib->callback(dev->sync_fib->callback_data, 10811604612SMahesh Rajashekhara dev->sync_fib); 10911604612SMahesh Rajashekhara spin_lock_irqsave(&dev->sync_fib->event_lock, sflags); 11011604612SMahesh Rajashekhara if (dev->sync_fib->flags & FIB_CONTEXT_FLAG_WAIT) { 11111604612SMahesh Rajashekhara dev->management_fib_count--; 11211604612SMahesh Rajashekhara up(&dev->sync_fib->event_wait); 11311604612SMahesh Rajashekhara } 11411604612SMahesh Rajashekhara spin_unlock_irqrestore(&dev->sync_fib->event_lock, sflags); 11511604612SMahesh Rajashekhara spin_lock_irqsave(&dev->sync_lock, sflags); 11611604612SMahesh Rajashekhara if (!list_empty(&dev->sync_fib_list)) { 11711604612SMahesh Rajashekhara entry = dev->sync_fib_list.next; 11811604612SMahesh Rajashekhara dev->sync_fib = list_entry(entry, struct fib, fiblink); 11911604612SMahesh Rajashekhara list_del(entry); 12011604612SMahesh Rajashekhara send_it = 1; 12111604612SMahesh Rajashekhara } else { 12211604612SMahesh Rajashekhara dev->sync_fib = NULL; 12311604612SMahesh Rajashekhara } 12411604612SMahesh Rajashekhara spin_unlock_irqrestore(&dev->sync_lock, sflags); 12511604612SMahesh Rajashekhara if (send_it) { 12611604612SMahesh Rajashekhara aac_adapter_sync_cmd(dev, SEND_SYNCHRONOUS_FIB, 12711604612SMahesh Rajashekhara (u32)dev->sync_fib->hw_fib_pa, 0, 0, 0, 0, 0, 12811604612SMahesh Rajashekhara NULL, NULL, NULL, NULL, NULL); 12911604612SMahesh Rajashekhara } 13011604612SMahesh Rajashekhara } 131e8b12f0fSMahesh Rajashekhara } 132e8b12f0fSMahesh Rajashekhara } 133e8b12f0fSMahesh Rajashekhara 134e8b12f0fSMahesh Rajashekhara if (our_interrupt) { 135e8b12f0fSMahesh Rajashekhara src_writel(dev, MUnit.ODR_C, bellbits); 136e8b12f0fSMahesh Rajashekhara return IRQ_HANDLED; 137e8b12f0fSMahesh Rajashekhara } 138e8b12f0fSMahesh Rajashekhara return IRQ_NONE; 139e8b12f0fSMahesh Rajashekhara } 140e8b12f0fSMahesh Rajashekhara 141e8b12f0fSMahesh Rajashekhara /** 142e8b12f0fSMahesh Rajashekhara * aac_src_disable_interrupt - Disable interrupts 143e8b12f0fSMahesh Rajashekhara * @dev: Adapter 144e8b12f0fSMahesh Rajashekhara */ 145e8b12f0fSMahesh Rajashekhara 146e8b12f0fSMahesh Rajashekhara static void aac_src_disable_interrupt(struct aac_dev *dev) 147e8b12f0fSMahesh Rajashekhara { 148e8b12f0fSMahesh Rajashekhara src_writel(dev, MUnit.OIMR, dev->OIMR = 0xffffffff); 149e8b12f0fSMahesh Rajashekhara } 150e8b12f0fSMahesh Rajashekhara 151e8b12f0fSMahesh Rajashekhara /** 152e8b12f0fSMahesh Rajashekhara * aac_src_enable_interrupt_message - Enable interrupts 153e8b12f0fSMahesh Rajashekhara * @dev: Adapter 154e8b12f0fSMahesh Rajashekhara */ 155e8b12f0fSMahesh Rajashekhara 156e8b12f0fSMahesh Rajashekhara static void aac_src_enable_interrupt_message(struct aac_dev *dev) 157e8b12f0fSMahesh Rajashekhara { 158e8b12f0fSMahesh Rajashekhara src_writel(dev, MUnit.OIMR, dev->OIMR = 0xfffffff8); 159e8b12f0fSMahesh Rajashekhara } 160e8b12f0fSMahesh Rajashekhara 161e8b12f0fSMahesh Rajashekhara /** 162e8b12f0fSMahesh Rajashekhara * src_sync_cmd - send a command and wait 163e8b12f0fSMahesh Rajashekhara * @dev: Adapter 164e8b12f0fSMahesh Rajashekhara * @command: Command to execute 165e8b12f0fSMahesh Rajashekhara * @p1: first parameter 166e8b12f0fSMahesh Rajashekhara * @ret: adapter status 167e8b12f0fSMahesh Rajashekhara * 168e8b12f0fSMahesh Rajashekhara * This routine will send a synchronous command to the adapter and wait 169e8b12f0fSMahesh Rajashekhara * for its completion. 170e8b12f0fSMahesh Rajashekhara */ 171e8b12f0fSMahesh Rajashekhara 172e8b12f0fSMahesh Rajashekhara static int src_sync_cmd(struct aac_dev *dev, u32 command, 173e8b12f0fSMahesh Rajashekhara u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6, 174e8b12f0fSMahesh Rajashekhara u32 *status, u32 * r1, u32 * r2, u32 * r3, u32 * r4) 175e8b12f0fSMahesh Rajashekhara { 176e8b12f0fSMahesh Rajashekhara unsigned long start; 177e8b12f0fSMahesh Rajashekhara int ok; 178e8b12f0fSMahesh Rajashekhara 179e8b12f0fSMahesh Rajashekhara /* 180e8b12f0fSMahesh Rajashekhara * Write the command into Mailbox 0 181e8b12f0fSMahesh Rajashekhara */ 182e8b12f0fSMahesh Rajashekhara writel(command, &dev->IndexRegs->Mailbox[0]); 183e8b12f0fSMahesh Rajashekhara /* 184e8b12f0fSMahesh Rajashekhara * Write the parameters into Mailboxes 1 - 6 185e8b12f0fSMahesh Rajashekhara */ 186e8b12f0fSMahesh Rajashekhara writel(p1, &dev->IndexRegs->Mailbox[1]); 187e8b12f0fSMahesh Rajashekhara writel(p2, &dev->IndexRegs->Mailbox[2]); 188e8b12f0fSMahesh Rajashekhara writel(p3, &dev->IndexRegs->Mailbox[3]); 189e8b12f0fSMahesh Rajashekhara writel(p4, &dev->IndexRegs->Mailbox[4]); 190e8b12f0fSMahesh Rajashekhara 191e8b12f0fSMahesh Rajashekhara /* 192e8b12f0fSMahesh Rajashekhara * Clear the synch command doorbell to start on a clean slate. 193e8b12f0fSMahesh Rajashekhara */ 194e8b12f0fSMahesh Rajashekhara src_writel(dev, MUnit.ODR_C, OUTBOUNDDOORBELL_0 << SRC_ODR_SHIFT); 195e8b12f0fSMahesh Rajashekhara 196e8b12f0fSMahesh Rajashekhara /* 197e8b12f0fSMahesh Rajashekhara * Disable doorbell interrupts 198e8b12f0fSMahesh Rajashekhara */ 199e8b12f0fSMahesh Rajashekhara src_writel(dev, MUnit.OIMR, dev->OIMR = 0xffffffff); 200e8b12f0fSMahesh Rajashekhara 201e8b12f0fSMahesh Rajashekhara /* 202e8b12f0fSMahesh Rajashekhara * Force the completion of the mask register write before issuing 203e8b12f0fSMahesh Rajashekhara * the interrupt. 204e8b12f0fSMahesh Rajashekhara */ 205e8b12f0fSMahesh Rajashekhara src_readl(dev, MUnit.OIMR); 206e8b12f0fSMahesh Rajashekhara 207e8b12f0fSMahesh Rajashekhara /* 208e8b12f0fSMahesh Rajashekhara * Signal that there is a new synch command 209e8b12f0fSMahesh Rajashekhara */ 210e8b12f0fSMahesh Rajashekhara src_writel(dev, MUnit.IDR, INBOUNDDOORBELL_0 << SRC_IDR_SHIFT); 211e8b12f0fSMahesh Rajashekhara 21211604612SMahesh Rajashekhara if (!dev->sync_mode || command != SEND_SYNCHRONOUS_FIB) { 213e8b12f0fSMahesh Rajashekhara ok = 0; 214e8b12f0fSMahesh Rajashekhara start = jiffies; 215e8b12f0fSMahesh Rajashekhara 216e8b12f0fSMahesh Rajashekhara /* 21711604612SMahesh Rajashekhara * Wait up to 5 minutes 218e8b12f0fSMahesh Rajashekhara */ 21911604612SMahesh Rajashekhara while (time_before(jiffies, start+300*HZ)) { 22011604612SMahesh Rajashekhara udelay(5); /* Delay 5 microseconds to let Mon960 get info. */ 22111604612SMahesh Rajashekhara /* 22211604612SMahesh Rajashekhara * Mon960 will set doorbell0 bit when it has completed the command. 223e8b12f0fSMahesh Rajashekhara */ 224e8b12f0fSMahesh Rajashekhara if ((src_readl(dev, MUnit.ODR_R) >> SRC_ODR_SHIFT) & OUTBOUNDDOORBELL_0) { 22511604612SMahesh Rajashekhara /* 22611604612SMahesh Rajashekhara * Clear the doorbell. 22711604612SMahesh Rajashekhara */ 22811604612SMahesh Rajashekhara src_writel(dev, MUnit.ODR_C, OUTBOUNDDOORBELL_0 << SRC_ODR_SHIFT); 229e8b12f0fSMahesh Rajashekhara ok = 1; 230e8b12f0fSMahesh Rajashekhara break; 231e8b12f0fSMahesh Rajashekhara } 23211604612SMahesh Rajashekhara /* 23311604612SMahesh Rajashekhara * Yield the processor in case we are slow 23411604612SMahesh Rajashekhara */ 235e8b12f0fSMahesh Rajashekhara msleep(1); 236e8b12f0fSMahesh Rajashekhara } 237e8b12f0fSMahesh Rajashekhara if (unlikely(ok != 1)) { 23811604612SMahesh Rajashekhara /* 23911604612SMahesh Rajashekhara * Restore interrupt mask even though we timed out 24011604612SMahesh Rajashekhara */ 241e8b12f0fSMahesh Rajashekhara aac_adapter_enable_int(dev); 242e8b12f0fSMahesh Rajashekhara return -ETIMEDOUT; 243e8b12f0fSMahesh Rajashekhara } 24411604612SMahesh Rajashekhara /* 24511604612SMahesh Rajashekhara * Pull the synch status from Mailbox 0. 24611604612SMahesh Rajashekhara */ 247e8b12f0fSMahesh Rajashekhara if (status) 248e8b12f0fSMahesh Rajashekhara *status = readl(&dev->IndexRegs->Mailbox[0]); 249e8b12f0fSMahesh Rajashekhara if (r1) 250e8b12f0fSMahesh Rajashekhara *r1 = readl(&dev->IndexRegs->Mailbox[1]); 251e8b12f0fSMahesh Rajashekhara if (r2) 252e8b12f0fSMahesh Rajashekhara *r2 = readl(&dev->IndexRegs->Mailbox[2]); 253e8b12f0fSMahesh Rajashekhara if (r3) 254e8b12f0fSMahesh Rajashekhara *r3 = readl(&dev->IndexRegs->Mailbox[3]); 255e8b12f0fSMahesh Rajashekhara if (r4) 256e8b12f0fSMahesh Rajashekhara *r4 = readl(&dev->IndexRegs->Mailbox[4]); 257e8b12f0fSMahesh Rajashekhara 25811604612SMahesh Rajashekhara /* 25911604612SMahesh Rajashekhara * Clear the synch command doorbell. 26011604612SMahesh Rajashekhara */ 261e8b12f0fSMahesh Rajashekhara src_writel(dev, MUnit.ODR_C, OUTBOUNDDOORBELL_0 << SRC_ODR_SHIFT); 26211604612SMahesh Rajashekhara } 263e8b12f0fSMahesh Rajashekhara 26411604612SMahesh Rajashekhara /* 26511604612SMahesh Rajashekhara * Restore interrupt mask 26611604612SMahesh Rajashekhara */ 267e8b12f0fSMahesh Rajashekhara aac_adapter_enable_int(dev); 268e8b12f0fSMahesh Rajashekhara return 0; 269e8b12f0fSMahesh Rajashekhara } 270e8b12f0fSMahesh Rajashekhara 271e8b12f0fSMahesh Rajashekhara /** 272e8b12f0fSMahesh Rajashekhara * aac_src_interrupt_adapter - interrupt adapter 273e8b12f0fSMahesh Rajashekhara * @dev: Adapter 274e8b12f0fSMahesh Rajashekhara * 275e8b12f0fSMahesh Rajashekhara * Send an interrupt to the i960 and breakpoint it. 276e8b12f0fSMahesh Rajashekhara */ 277e8b12f0fSMahesh Rajashekhara 278e8b12f0fSMahesh Rajashekhara static void aac_src_interrupt_adapter(struct aac_dev *dev) 279e8b12f0fSMahesh Rajashekhara { 280e8b12f0fSMahesh Rajashekhara src_sync_cmd(dev, BREAKPOINT_REQUEST, 281e8b12f0fSMahesh Rajashekhara 0, 0, 0, 0, 0, 0, 282e8b12f0fSMahesh Rajashekhara NULL, NULL, NULL, NULL, NULL); 283e8b12f0fSMahesh Rajashekhara } 284e8b12f0fSMahesh Rajashekhara 285e8b12f0fSMahesh Rajashekhara /** 286e8b12f0fSMahesh Rajashekhara * aac_src_notify_adapter - send an event to the adapter 287e8b12f0fSMahesh Rajashekhara * @dev: Adapter 288e8b12f0fSMahesh Rajashekhara * @event: Event to send 289e8b12f0fSMahesh Rajashekhara * 290e8b12f0fSMahesh Rajashekhara * Notify the i960 that something it probably cares about has 291e8b12f0fSMahesh Rajashekhara * happened. 292e8b12f0fSMahesh Rajashekhara */ 293e8b12f0fSMahesh Rajashekhara 294e8b12f0fSMahesh Rajashekhara static void aac_src_notify_adapter(struct aac_dev *dev, u32 event) 295e8b12f0fSMahesh Rajashekhara { 296e8b12f0fSMahesh Rajashekhara switch (event) { 297e8b12f0fSMahesh Rajashekhara 298e8b12f0fSMahesh Rajashekhara case AdapNormCmdQue: 299e8b12f0fSMahesh Rajashekhara src_writel(dev, MUnit.ODR_C, 300e8b12f0fSMahesh Rajashekhara INBOUNDDOORBELL_1 << SRC_ODR_SHIFT); 301e8b12f0fSMahesh Rajashekhara break; 302e8b12f0fSMahesh Rajashekhara case HostNormRespNotFull: 303e8b12f0fSMahesh Rajashekhara src_writel(dev, MUnit.ODR_C, 304e8b12f0fSMahesh Rajashekhara INBOUNDDOORBELL_4 << SRC_ODR_SHIFT); 305e8b12f0fSMahesh Rajashekhara break; 306e8b12f0fSMahesh Rajashekhara case AdapNormRespQue: 307e8b12f0fSMahesh Rajashekhara src_writel(dev, MUnit.ODR_C, 308e8b12f0fSMahesh Rajashekhara INBOUNDDOORBELL_2 << SRC_ODR_SHIFT); 309e8b12f0fSMahesh Rajashekhara break; 310e8b12f0fSMahesh Rajashekhara case HostNormCmdNotFull: 311e8b12f0fSMahesh Rajashekhara src_writel(dev, MUnit.ODR_C, 312e8b12f0fSMahesh Rajashekhara INBOUNDDOORBELL_3 << SRC_ODR_SHIFT); 313e8b12f0fSMahesh Rajashekhara break; 314e8b12f0fSMahesh Rajashekhara case FastIo: 315e8b12f0fSMahesh Rajashekhara src_writel(dev, MUnit.ODR_C, 316e8b12f0fSMahesh Rajashekhara INBOUNDDOORBELL_6 << SRC_ODR_SHIFT); 317e8b12f0fSMahesh Rajashekhara break; 318e8b12f0fSMahesh Rajashekhara case AdapPrintfDone: 319e8b12f0fSMahesh Rajashekhara src_writel(dev, MUnit.ODR_C, 320e8b12f0fSMahesh Rajashekhara INBOUNDDOORBELL_5 << SRC_ODR_SHIFT); 321e8b12f0fSMahesh Rajashekhara break; 322e8b12f0fSMahesh Rajashekhara default: 323e8b12f0fSMahesh Rajashekhara BUG(); 324e8b12f0fSMahesh Rajashekhara break; 325e8b12f0fSMahesh Rajashekhara } 326e8b12f0fSMahesh Rajashekhara } 327e8b12f0fSMahesh Rajashekhara 328e8b12f0fSMahesh Rajashekhara /** 329e8b12f0fSMahesh Rajashekhara * aac_src_start_adapter - activate adapter 330e8b12f0fSMahesh Rajashekhara * @dev: Adapter 331e8b12f0fSMahesh Rajashekhara * 332e8b12f0fSMahesh Rajashekhara * Start up processing on an i960 based AAC adapter 333e8b12f0fSMahesh Rajashekhara */ 334e8b12f0fSMahesh Rajashekhara 335e8b12f0fSMahesh Rajashekhara static void aac_src_start_adapter(struct aac_dev *dev) 336e8b12f0fSMahesh Rajashekhara { 337e8b12f0fSMahesh Rajashekhara struct aac_init *init; 338e8b12f0fSMahesh Rajashekhara 339e8b12f0fSMahesh Rajashekhara init = dev->init; 340e8b12f0fSMahesh Rajashekhara init->HostElapsedSeconds = cpu_to_le32(get_seconds()); 341e8b12f0fSMahesh Rajashekhara 342e8b12f0fSMahesh Rajashekhara /* We can only use a 32 bit address here */ 343e8b12f0fSMahesh Rajashekhara src_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (u32)(ulong)dev->init_pa, 344e8b12f0fSMahesh Rajashekhara 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL); 345e8b12f0fSMahesh Rajashekhara } 346e8b12f0fSMahesh Rajashekhara 347e8b12f0fSMahesh Rajashekhara /** 348e8b12f0fSMahesh Rajashekhara * aac_src_check_health 349e8b12f0fSMahesh Rajashekhara * @dev: device to check if healthy 350e8b12f0fSMahesh Rajashekhara * 351e8b12f0fSMahesh Rajashekhara * Will attempt to determine if the specified adapter is alive and 352e8b12f0fSMahesh Rajashekhara * capable of handling requests, returning 0 if alive. 353e8b12f0fSMahesh Rajashekhara */ 354e8b12f0fSMahesh Rajashekhara static int aac_src_check_health(struct aac_dev *dev) 355e8b12f0fSMahesh Rajashekhara { 356e8b12f0fSMahesh Rajashekhara u32 status = src_readl(dev, MUnit.OMR); 357e8b12f0fSMahesh Rajashekhara 358e8b12f0fSMahesh Rajashekhara /* 359e8b12f0fSMahesh Rajashekhara * Check to see if the board failed any self tests. 360e8b12f0fSMahesh Rajashekhara */ 361e8b12f0fSMahesh Rajashekhara if (unlikely(status & SELF_TEST_FAILED)) 362e8b12f0fSMahesh Rajashekhara return -1; 363e8b12f0fSMahesh Rajashekhara 364e8b12f0fSMahesh Rajashekhara /* 365e8b12f0fSMahesh Rajashekhara * Check to see if the board panic'd. 366e8b12f0fSMahesh Rajashekhara */ 367e8b12f0fSMahesh Rajashekhara if (unlikely(status & KERNEL_PANIC)) 368e8b12f0fSMahesh Rajashekhara return (status >> 16) & 0xFF; 369e8b12f0fSMahesh Rajashekhara /* 370e8b12f0fSMahesh Rajashekhara * Wait for the adapter to be up and running. 371e8b12f0fSMahesh Rajashekhara */ 372e8b12f0fSMahesh Rajashekhara if (unlikely(!(status & KERNEL_UP_AND_RUNNING))) 373e8b12f0fSMahesh Rajashekhara return -3; 374e8b12f0fSMahesh Rajashekhara /* 375e8b12f0fSMahesh Rajashekhara * Everything is OK 376e8b12f0fSMahesh Rajashekhara */ 377e8b12f0fSMahesh Rajashekhara return 0; 378e8b12f0fSMahesh Rajashekhara } 379e8b12f0fSMahesh Rajashekhara 380e8b12f0fSMahesh Rajashekhara /** 381e8b12f0fSMahesh Rajashekhara * aac_src_deliver_message 382e8b12f0fSMahesh Rajashekhara * @fib: fib to issue 383e8b12f0fSMahesh Rajashekhara * 384e8b12f0fSMahesh Rajashekhara * Will send a fib, returning 0 if successful. 385e8b12f0fSMahesh Rajashekhara */ 386e8b12f0fSMahesh Rajashekhara static int aac_src_deliver_message(struct fib *fib) 387e8b12f0fSMahesh Rajashekhara { 388e8b12f0fSMahesh Rajashekhara struct aac_dev *dev = fib->dev; 389e8b12f0fSMahesh Rajashekhara struct aac_queue *q = &dev->queues->queue[AdapNormCmdQueue]; 390e8b12f0fSMahesh Rajashekhara unsigned long qflags; 391e8b12f0fSMahesh Rajashekhara u32 fibsize; 392e8b12f0fSMahesh Rajashekhara u64 address; 393e8b12f0fSMahesh Rajashekhara struct aac_fib_xporthdr *pFibX; 394e8b12f0fSMahesh Rajashekhara 395e8b12f0fSMahesh Rajashekhara spin_lock_irqsave(q->lock, qflags); 396e8b12f0fSMahesh Rajashekhara q->numpending++; 397e8b12f0fSMahesh Rajashekhara spin_unlock_irqrestore(q->lock, qflags); 398e8b12f0fSMahesh Rajashekhara 399e8b12f0fSMahesh Rajashekhara /* Calculate the amount to the fibsize bits */ 400e8b12f0fSMahesh Rajashekhara fibsize = (sizeof(struct aac_fib_xporthdr) + 401e8b12f0fSMahesh Rajashekhara fib->hw_fib_va->header.Size + 127) / 128 - 1; 402e8b12f0fSMahesh Rajashekhara if (fibsize > (ALIGN32 - 1)) 403e8b12f0fSMahesh Rajashekhara fibsize = ALIGN32 - 1; 404e8b12f0fSMahesh Rajashekhara 405e8b12f0fSMahesh Rajashekhara /* Fill XPORT header */ 406e8b12f0fSMahesh Rajashekhara pFibX = (struct aac_fib_xporthdr *) 407e8b12f0fSMahesh Rajashekhara ((unsigned char *)fib->hw_fib_va - 408e8b12f0fSMahesh Rajashekhara sizeof(struct aac_fib_xporthdr)); 409e8b12f0fSMahesh Rajashekhara pFibX->Handle = fib->hw_fib_va->header.SenderData + 1; 410e8b12f0fSMahesh Rajashekhara pFibX->HostAddress = fib->hw_fib_pa; 411e8b12f0fSMahesh Rajashekhara pFibX->Size = fib->hw_fib_va->header.Size; 412e8b12f0fSMahesh Rajashekhara address = fib->hw_fib_pa - (u64)sizeof(struct aac_fib_xporthdr); 413e8b12f0fSMahesh Rajashekhara 414e8b12f0fSMahesh Rajashekhara src_writel(dev, MUnit.IQ_H, (u32)(address >> 32)); 415e8b12f0fSMahesh Rajashekhara src_writel(dev, MUnit.IQ_L, (u32)(address & 0xffffffff) + fibsize); 416e8b12f0fSMahesh Rajashekhara return 0; 417e8b12f0fSMahesh Rajashekhara } 418e8b12f0fSMahesh Rajashekhara 419e8b12f0fSMahesh Rajashekhara /** 420e8b12f0fSMahesh Rajashekhara * aac_src_ioremap 421e8b12f0fSMahesh Rajashekhara * @size: mapping resize request 422e8b12f0fSMahesh Rajashekhara * 423e8b12f0fSMahesh Rajashekhara */ 424e8b12f0fSMahesh Rajashekhara static int aac_src_ioremap(struct aac_dev *dev, u32 size) 425e8b12f0fSMahesh Rajashekhara { 426e8b12f0fSMahesh Rajashekhara if (!size) { 42771552505STomas Henzl iounmap(dev->regs.src.bar1); 42871552505STomas Henzl dev->regs.src.bar1 = NULL; 429e8b12f0fSMahesh Rajashekhara iounmap(dev->regs.src.bar0); 43011604612SMahesh Rajashekhara dev->base = dev->regs.src.bar0 = NULL; 431e8b12f0fSMahesh Rajashekhara return 0; 432e8b12f0fSMahesh Rajashekhara } 433e8b12f0fSMahesh Rajashekhara dev->regs.src.bar1 = ioremap(pci_resource_start(dev->pdev, 2), 434e8b12f0fSMahesh Rajashekhara AAC_MIN_SRC_BAR1_SIZE); 435e8b12f0fSMahesh Rajashekhara dev->base = NULL; 436e8b12f0fSMahesh Rajashekhara if (dev->regs.src.bar1 == NULL) 437e8b12f0fSMahesh Rajashekhara return -1; 438e8b12f0fSMahesh Rajashekhara dev->base = dev->regs.src.bar0 = ioremap(dev->scsi_host_ptr->base, 439e8b12f0fSMahesh Rajashekhara size); 440e8b12f0fSMahesh Rajashekhara if (dev->base == NULL) { 441e8b12f0fSMahesh Rajashekhara iounmap(dev->regs.src.bar1); 442e8b12f0fSMahesh Rajashekhara dev->regs.src.bar1 = NULL; 443e8b12f0fSMahesh Rajashekhara return -1; 444e8b12f0fSMahesh Rajashekhara } 445e8b12f0fSMahesh Rajashekhara dev->IndexRegs = &((struct src_registers __iomem *) 44611604612SMahesh Rajashekhara dev->base)->u.tupelo.IndexRegs; 44711604612SMahesh Rajashekhara return 0; 44811604612SMahesh Rajashekhara } 44911604612SMahesh Rajashekhara 45011604612SMahesh Rajashekhara /** 45111604612SMahesh Rajashekhara * aac_srcv_ioremap 45211604612SMahesh Rajashekhara * @size: mapping resize request 45311604612SMahesh Rajashekhara * 45411604612SMahesh Rajashekhara */ 45511604612SMahesh Rajashekhara static int aac_srcv_ioremap(struct aac_dev *dev, u32 size) 45611604612SMahesh Rajashekhara { 45711604612SMahesh Rajashekhara if (!size) { 45811604612SMahesh Rajashekhara iounmap(dev->regs.src.bar0); 45911604612SMahesh Rajashekhara dev->base = dev->regs.src.bar0 = NULL; 46011604612SMahesh Rajashekhara return 0; 46111604612SMahesh Rajashekhara } 46211604612SMahesh Rajashekhara dev->base = dev->regs.src.bar0 = ioremap(dev->scsi_host_ptr->base, size); 46311604612SMahesh Rajashekhara if (dev->base == NULL) 46411604612SMahesh Rajashekhara return -1; 46511604612SMahesh Rajashekhara dev->IndexRegs = &((struct src_registers __iomem *) 46611604612SMahesh Rajashekhara dev->base)->u.denali.IndexRegs; 467e8b12f0fSMahesh Rajashekhara return 0; 468e8b12f0fSMahesh Rajashekhara } 469e8b12f0fSMahesh Rajashekhara 470e8b12f0fSMahesh Rajashekhara static int aac_src_restart_adapter(struct aac_dev *dev, int bled) 471e8b12f0fSMahesh Rajashekhara { 472e8b12f0fSMahesh Rajashekhara u32 var, reset_mask; 473e8b12f0fSMahesh Rajashekhara 474e8b12f0fSMahesh Rajashekhara if (bled >= 0) { 475e8b12f0fSMahesh Rajashekhara if (bled) 476e8b12f0fSMahesh Rajashekhara printk(KERN_ERR "%s%d: adapter kernel panic'd %x.\n", 477e8b12f0fSMahesh Rajashekhara dev->name, dev->id, bled); 478e8b12f0fSMahesh Rajashekhara bled = aac_adapter_sync_cmd(dev, IOP_RESET_ALWAYS, 479e8b12f0fSMahesh Rajashekhara 0, 0, 0, 0, 0, 0, &var, &reset_mask, NULL, NULL, NULL); 480e8b12f0fSMahesh Rajashekhara if (bled || (var != 0x00000001)) 48111604612SMahesh Rajashekhara return -EINVAL; 482e8b12f0fSMahesh Rajashekhara if (dev->supplement_adapter_info.SupportedOptions2 & 483e8b12f0fSMahesh Rajashekhara AAC_OPTION_DOORBELL_RESET) { 484e8b12f0fSMahesh Rajashekhara src_writel(dev, MUnit.IDR, reset_mask); 485e8b12f0fSMahesh Rajashekhara msleep(5000); /* Delay 5 seconds */ 486e8b12f0fSMahesh Rajashekhara } 487e8b12f0fSMahesh Rajashekhara } 488e8b12f0fSMahesh Rajashekhara 489e8b12f0fSMahesh Rajashekhara if (src_readl(dev, MUnit.OMR) & KERNEL_PANIC) 490e8b12f0fSMahesh Rajashekhara return -ENODEV; 491e8b12f0fSMahesh Rajashekhara 492e8b12f0fSMahesh Rajashekhara if (startup_timeout < 300) 493e8b12f0fSMahesh Rajashekhara startup_timeout = 300; 494e8b12f0fSMahesh Rajashekhara 495e8b12f0fSMahesh Rajashekhara return 0; 496e8b12f0fSMahesh Rajashekhara } 497e8b12f0fSMahesh Rajashekhara 498e8b12f0fSMahesh Rajashekhara /** 499e8b12f0fSMahesh Rajashekhara * aac_src_select_comm - Select communications method 500e8b12f0fSMahesh Rajashekhara * @dev: Adapter 501e8b12f0fSMahesh Rajashekhara * @comm: communications method 502e8b12f0fSMahesh Rajashekhara */ 503e8b12f0fSMahesh Rajashekhara int aac_src_select_comm(struct aac_dev *dev, int comm) 504e8b12f0fSMahesh Rajashekhara { 505e8b12f0fSMahesh Rajashekhara switch (comm) { 506e8b12f0fSMahesh Rajashekhara case AAC_COMM_MESSAGE: 507e8b12f0fSMahesh Rajashekhara dev->a_ops.adapter_enable_int = aac_src_enable_interrupt_message; 508e8b12f0fSMahesh Rajashekhara dev->a_ops.adapter_intr = aac_src_intr_message; 509e8b12f0fSMahesh Rajashekhara dev->a_ops.adapter_deliver = aac_src_deliver_message; 510e8b12f0fSMahesh Rajashekhara break; 511e8b12f0fSMahesh Rajashekhara default: 512e8b12f0fSMahesh Rajashekhara return 1; 513e8b12f0fSMahesh Rajashekhara } 514e8b12f0fSMahesh Rajashekhara return 0; 515e8b12f0fSMahesh Rajashekhara } 516e8b12f0fSMahesh Rajashekhara 517e8b12f0fSMahesh Rajashekhara /** 518e8b12f0fSMahesh Rajashekhara * aac_src_init - initialize an Cardinal Frey Bar card 519e8b12f0fSMahesh Rajashekhara * @dev: device to configure 520e8b12f0fSMahesh Rajashekhara * 521e8b12f0fSMahesh Rajashekhara */ 522e8b12f0fSMahesh Rajashekhara 523e8b12f0fSMahesh Rajashekhara int aac_src_init(struct aac_dev *dev) 524e8b12f0fSMahesh Rajashekhara { 525e8b12f0fSMahesh Rajashekhara unsigned long start; 526e8b12f0fSMahesh Rajashekhara unsigned long status; 527e8b12f0fSMahesh Rajashekhara int restart = 0; 528e8b12f0fSMahesh Rajashekhara int instance = dev->id; 529e8b12f0fSMahesh Rajashekhara const char *name = dev->name; 530e8b12f0fSMahesh Rajashekhara 531e8b12f0fSMahesh Rajashekhara dev->a_ops.adapter_ioremap = aac_src_ioremap; 532e8b12f0fSMahesh Rajashekhara dev->a_ops.adapter_comm = aac_src_select_comm; 533e8b12f0fSMahesh Rajashekhara 534e8b12f0fSMahesh Rajashekhara dev->base_size = AAC_MIN_SRC_BAR0_SIZE; 535e8b12f0fSMahesh Rajashekhara if (aac_adapter_ioremap(dev, dev->base_size)) { 536e8b12f0fSMahesh Rajashekhara printk(KERN_WARNING "%s: unable to map adapter.\n", name); 537e8b12f0fSMahesh Rajashekhara goto error_iounmap; 538e8b12f0fSMahesh Rajashekhara } 539e8b12f0fSMahesh Rajashekhara 540e8b12f0fSMahesh Rajashekhara /* Failure to reset here is an option ... */ 541e8b12f0fSMahesh Rajashekhara dev->a_ops.adapter_sync_cmd = src_sync_cmd; 542e8b12f0fSMahesh Rajashekhara dev->a_ops.adapter_enable_int = aac_src_disable_interrupt; 543e8b12f0fSMahesh Rajashekhara if ((aac_reset_devices || reset_devices) && 544e8b12f0fSMahesh Rajashekhara !aac_src_restart_adapter(dev, 0)) 545e8b12f0fSMahesh Rajashekhara ++restart; 546e8b12f0fSMahesh Rajashekhara /* 547e8b12f0fSMahesh Rajashekhara * Check to see if the board panic'd while booting. 548e8b12f0fSMahesh Rajashekhara */ 549e8b12f0fSMahesh Rajashekhara status = src_readl(dev, MUnit.OMR); 550e8b12f0fSMahesh Rajashekhara if (status & KERNEL_PANIC) { 551e8b12f0fSMahesh Rajashekhara if (aac_src_restart_adapter(dev, aac_src_check_health(dev))) 552e8b12f0fSMahesh Rajashekhara goto error_iounmap; 553e8b12f0fSMahesh Rajashekhara ++restart; 554e8b12f0fSMahesh Rajashekhara } 555e8b12f0fSMahesh Rajashekhara /* 556e8b12f0fSMahesh Rajashekhara * Check to see if the board failed any self tests. 557e8b12f0fSMahesh Rajashekhara */ 558e8b12f0fSMahesh Rajashekhara status = src_readl(dev, MUnit.OMR); 559e8b12f0fSMahesh Rajashekhara if (status & SELF_TEST_FAILED) { 560e8b12f0fSMahesh Rajashekhara printk(KERN_ERR "%s%d: adapter self-test failed.\n", 561e8b12f0fSMahesh Rajashekhara dev->name, instance); 562e8b12f0fSMahesh Rajashekhara goto error_iounmap; 563e8b12f0fSMahesh Rajashekhara } 564e8b12f0fSMahesh Rajashekhara /* 565e8b12f0fSMahesh Rajashekhara * Check to see if the monitor panic'd while booting. 566e8b12f0fSMahesh Rajashekhara */ 567e8b12f0fSMahesh Rajashekhara if (status & MONITOR_PANIC) { 568e8b12f0fSMahesh Rajashekhara printk(KERN_ERR "%s%d: adapter monitor panic.\n", 569e8b12f0fSMahesh Rajashekhara dev->name, instance); 570e8b12f0fSMahesh Rajashekhara goto error_iounmap; 571e8b12f0fSMahesh Rajashekhara } 572e8b12f0fSMahesh Rajashekhara start = jiffies; 573e8b12f0fSMahesh Rajashekhara /* 574e8b12f0fSMahesh Rajashekhara * Wait for the adapter to be up and running. Wait up to 3 minutes 575e8b12f0fSMahesh Rajashekhara */ 576e8b12f0fSMahesh Rajashekhara while (!((status = src_readl(dev, MUnit.OMR)) & 577e8b12f0fSMahesh Rajashekhara KERNEL_UP_AND_RUNNING)) { 578e8b12f0fSMahesh Rajashekhara if ((restart && 579e8b12f0fSMahesh Rajashekhara (status & (KERNEL_PANIC|SELF_TEST_FAILED|MONITOR_PANIC))) || 580e8b12f0fSMahesh Rajashekhara time_after(jiffies, start+HZ*startup_timeout)) { 581e8b12f0fSMahesh Rajashekhara printk(KERN_ERR "%s%d: adapter kernel failed to start, init status = %lx.\n", 582e8b12f0fSMahesh Rajashekhara dev->name, instance, status); 583e8b12f0fSMahesh Rajashekhara goto error_iounmap; 584e8b12f0fSMahesh Rajashekhara } 585e8b12f0fSMahesh Rajashekhara if (!restart && 586e8b12f0fSMahesh Rajashekhara ((status & (KERNEL_PANIC|SELF_TEST_FAILED|MONITOR_PANIC)) || 587e8b12f0fSMahesh Rajashekhara time_after(jiffies, start + HZ * 588e8b12f0fSMahesh Rajashekhara ((startup_timeout > 60) 589e8b12f0fSMahesh Rajashekhara ? (startup_timeout - 60) 590e8b12f0fSMahesh Rajashekhara : (startup_timeout / 2))))) { 591e8b12f0fSMahesh Rajashekhara if (likely(!aac_src_restart_adapter(dev, 592e8b12f0fSMahesh Rajashekhara aac_src_check_health(dev)))) 593e8b12f0fSMahesh Rajashekhara start = jiffies; 594e8b12f0fSMahesh Rajashekhara ++restart; 595e8b12f0fSMahesh Rajashekhara } 596e8b12f0fSMahesh Rajashekhara msleep(1); 597e8b12f0fSMahesh Rajashekhara } 598e8b12f0fSMahesh Rajashekhara if (restart && aac_commit) 599e8b12f0fSMahesh Rajashekhara aac_commit = 1; 600e8b12f0fSMahesh Rajashekhara /* 601e8b12f0fSMahesh Rajashekhara * Fill in the common function dispatch table. 602e8b12f0fSMahesh Rajashekhara */ 603e8b12f0fSMahesh Rajashekhara dev->a_ops.adapter_interrupt = aac_src_interrupt_adapter; 604e8b12f0fSMahesh Rajashekhara dev->a_ops.adapter_disable_int = aac_src_disable_interrupt; 605e8b12f0fSMahesh Rajashekhara dev->a_ops.adapter_notify = aac_src_notify_adapter; 606e8b12f0fSMahesh Rajashekhara dev->a_ops.adapter_sync_cmd = src_sync_cmd; 607e8b12f0fSMahesh Rajashekhara dev->a_ops.adapter_check_health = aac_src_check_health; 608e8b12f0fSMahesh Rajashekhara dev->a_ops.adapter_restart = aac_src_restart_adapter; 609e8b12f0fSMahesh Rajashekhara 610e8b12f0fSMahesh Rajashekhara /* 611e8b12f0fSMahesh Rajashekhara * First clear out all interrupts. Then enable the one's that we 612e8b12f0fSMahesh Rajashekhara * can handle. 613e8b12f0fSMahesh Rajashekhara */ 614e8b12f0fSMahesh Rajashekhara aac_adapter_comm(dev, AAC_COMM_MESSAGE); 615e8b12f0fSMahesh Rajashekhara aac_adapter_disable_int(dev); 616e8b12f0fSMahesh Rajashekhara src_writel(dev, MUnit.ODR_C, 0xffffffff); 617e8b12f0fSMahesh Rajashekhara aac_adapter_enable_int(dev); 618e8b12f0fSMahesh Rajashekhara 619e8b12f0fSMahesh Rajashekhara if (aac_init_adapter(dev) == NULL) 620e8b12f0fSMahesh Rajashekhara goto error_iounmap; 621e8b12f0fSMahesh Rajashekhara if (dev->comm_interface != AAC_COMM_MESSAGE_TYPE1) 622e8b12f0fSMahesh Rajashekhara goto error_iounmap; 623e8b12f0fSMahesh Rajashekhara 624e8b12f0fSMahesh Rajashekhara dev->msi = aac_msi && !pci_enable_msi(dev->pdev); 625e8b12f0fSMahesh Rajashekhara 626e8b12f0fSMahesh Rajashekhara if (request_irq(dev->pdev->irq, dev->a_ops.adapter_intr, 627e8b12f0fSMahesh Rajashekhara IRQF_SHARED|IRQF_DISABLED, "aacraid", dev) < 0) { 628e8b12f0fSMahesh Rajashekhara 629e8b12f0fSMahesh Rajashekhara if (dev->msi) 630e8b12f0fSMahesh Rajashekhara pci_disable_msi(dev->pdev); 631e8b12f0fSMahesh Rajashekhara 632e8b12f0fSMahesh Rajashekhara printk(KERN_ERR "%s%d: Interrupt unavailable.\n", 633e8b12f0fSMahesh Rajashekhara name, instance); 634e8b12f0fSMahesh Rajashekhara goto error_iounmap; 635e8b12f0fSMahesh Rajashekhara } 636e8b12f0fSMahesh Rajashekhara dev->dbg_base = pci_resource_start(dev->pdev, 2); 637e8b12f0fSMahesh Rajashekhara dev->dbg_base_mapped = dev->regs.src.bar1; 638e8b12f0fSMahesh Rajashekhara dev->dbg_size = AAC_MIN_SRC_BAR1_SIZE; 639e8b12f0fSMahesh Rajashekhara 640e8b12f0fSMahesh Rajashekhara aac_adapter_enable_int(dev); 64111604612SMahesh Rajashekhara 64211604612SMahesh Rajashekhara if (!dev->sync_mode) { 643e8b12f0fSMahesh Rajashekhara /* 644e8b12f0fSMahesh Rajashekhara * Tell the adapter that all is configured, and it can 645e8b12f0fSMahesh Rajashekhara * start accepting requests 646e8b12f0fSMahesh Rajashekhara */ 647e8b12f0fSMahesh Rajashekhara aac_src_start_adapter(dev); 64811604612SMahesh Rajashekhara } 649e8b12f0fSMahesh Rajashekhara return 0; 650e8b12f0fSMahesh Rajashekhara 651e8b12f0fSMahesh Rajashekhara error_iounmap: 652e8b12f0fSMahesh Rajashekhara 653e8b12f0fSMahesh Rajashekhara return -1; 654e8b12f0fSMahesh Rajashekhara } 65511604612SMahesh Rajashekhara 65611604612SMahesh Rajashekhara /** 65711604612SMahesh Rajashekhara * aac_srcv_init - initialize an SRCv card 65811604612SMahesh Rajashekhara * @dev: device to configure 65911604612SMahesh Rajashekhara * 66011604612SMahesh Rajashekhara */ 66111604612SMahesh Rajashekhara 66211604612SMahesh Rajashekhara int aac_srcv_init(struct aac_dev *dev) 66311604612SMahesh Rajashekhara { 66411604612SMahesh Rajashekhara unsigned long start; 66511604612SMahesh Rajashekhara unsigned long status; 66611604612SMahesh Rajashekhara int restart = 0; 66711604612SMahesh Rajashekhara int instance = dev->id; 66811604612SMahesh Rajashekhara const char *name = dev->name; 66911604612SMahesh Rajashekhara 67011604612SMahesh Rajashekhara dev->a_ops.adapter_ioremap = aac_srcv_ioremap; 67111604612SMahesh Rajashekhara dev->a_ops.adapter_comm = aac_src_select_comm; 67211604612SMahesh Rajashekhara 67311604612SMahesh Rajashekhara dev->base_size = AAC_MIN_SRCV_BAR0_SIZE; 67411604612SMahesh Rajashekhara if (aac_adapter_ioremap(dev, dev->base_size)) { 67511604612SMahesh Rajashekhara printk(KERN_WARNING "%s: unable to map adapter.\n", name); 67611604612SMahesh Rajashekhara goto error_iounmap; 67711604612SMahesh Rajashekhara } 67811604612SMahesh Rajashekhara 67911604612SMahesh Rajashekhara /* Failure to reset here is an option ... */ 68011604612SMahesh Rajashekhara dev->a_ops.adapter_sync_cmd = src_sync_cmd; 68111604612SMahesh Rajashekhara dev->a_ops.adapter_enable_int = aac_src_disable_interrupt; 68211604612SMahesh Rajashekhara if ((aac_reset_devices || reset_devices) && 68311604612SMahesh Rajashekhara !aac_src_restart_adapter(dev, 0)) 68411604612SMahesh Rajashekhara ++restart; 68511604612SMahesh Rajashekhara /* 68611604612SMahesh Rajashekhara * Check to see if the board panic'd while booting. 68711604612SMahesh Rajashekhara */ 68811604612SMahesh Rajashekhara status = src_readl(dev, MUnit.OMR); 68911604612SMahesh Rajashekhara if (status & KERNEL_PANIC) { 69011604612SMahesh Rajashekhara if (aac_src_restart_adapter(dev, aac_src_check_health(dev))) 69111604612SMahesh Rajashekhara goto error_iounmap; 69211604612SMahesh Rajashekhara ++restart; 69311604612SMahesh Rajashekhara } 69411604612SMahesh Rajashekhara /* 69511604612SMahesh Rajashekhara * Check to see if the board failed any self tests. 69611604612SMahesh Rajashekhara */ 69711604612SMahesh Rajashekhara status = src_readl(dev, MUnit.OMR); 69811604612SMahesh Rajashekhara if (status & SELF_TEST_FAILED) { 69911604612SMahesh Rajashekhara printk(KERN_ERR "%s%d: adapter self-test failed.\n", dev->name, instance); 70011604612SMahesh Rajashekhara goto error_iounmap; 70111604612SMahesh Rajashekhara } 70211604612SMahesh Rajashekhara /* 70311604612SMahesh Rajashekhara * Check to see if the monitor panic'd while booting. 70411604612SMahesh Rajashekhara */ 70511604612SMahesh Rajashekhara if (status & MONITOR_PANIC) { 70611604612SMahesh Rajashekhara printk(KERN_ERR "%s%d: adapter monitor panic.\n", dev->name, instance); 70711604612SMahesh Rajashekhara goto error_iounmap; 70811604612SMahesh Rajashekhara } 70911604612SMahesh Rajashekhara start = jiffies; 71011604612SMahesh Rajashekhara /* 71111604612SMahesh Rajashekhara * Wait for the adapter to be up and running. Wait up to 3 minutes 71211604612SMahesh Rajashekhara */ 71311604612SMahesh Rajashekhara while (!((status = src_readl(dev, MUnit.OMR)) & KERNEL_UP_AND_RUNNING)) { 71411604612SMahesh Rajashekhara if ((restart && 71511604612SMahesh Rajashekhara (status & (KERNEL_PANIC|SELF_TEST_FAILED|MONITOR_PANIC))) || 71611604612SMahesh Rajashekhara time_after(jiffies, start+HZ*startup_timeout)) { 71711604612SMahesh Rajashekhara printk(KERN_ERR "%s%d: adapter kernel failed to start, init status = %lx.\n", 71811604612SMahesh Rajashekhara dev->name, instance, status); 71911604612SMahesh Rajashekhara goto error_iounmap; 72011604612SMahesh Rajashekhara } 72111604612SMahesh Rajashekhara if (!restart && 72211604612SMahesh Rajashekhara ((status & (KERNEL_PANIC|SELF_TEST_FAILED|MONITOR_PANIC)) || 72311604612SMahesh Rajashekhara time_after(jiffies, start + HZ * 72411604612SMahesh Rajashekhara ((startup_timeout > 60) 72511604612SMahesh Rajashekhara ? (startup_timeout - 60) 72611604612SMahesh Rajashekhara : (startup_timeout / 2))))) { 72711604612SMahesh Rajashekhara if (likely(!aac_src_restart_adapter(dev, aac_src_check_health(dev)))) 72811604612SMahesh Rajashekhara start = jiffies; 72911604612SMahesh Rajashekhara ++restart; 73011604612SMahesh Rajashekhara } 73111604612SMahesh Rajashekhara msleep(1); 73211604612SMahesh Rajashekhara } 73311604612SMahesh Rajashekhara if (restart && aac_commit) 73411604612SMahesh Rajashekhara aac_commit = 1; 73511604612SMahesh Rajashekhara /* 73611604612SMahesh Rajashekhara * Fill in the common function dispatch table. 73711604612SMahesh Rajashekhara */ 73811604612SMahesh Rajashekhara dev->a_ops.adapter_interrupt = aac_src_interrupt_adapter; 73911604612SMahesh Rajashekhara dev->a_ops.adapter_disable_int = aac_src_disable_interrupt; 74011604612SMahesh Rajashekhara dev->a_ops.adapter_notify = aac_src_notify_adapter; 74111604612SMahesh Rajashekhara dev->a_ops.adapter_sync_cmd = src_sync_cmd; 74211604612SMahesh Rajashekhara dev->a_ops.adapter_check_health = aac_src_check_health; 74311604612SMahesh Rajashekhara dev->a_ops.adapter_restart = aac_src_restart_adapter; 74411604612SMahesh Rajashekhara 74511604612SMahesh Rajashekhara /* 74611604612SMahesh Rajashekhara * First clear out all interrupts. Then enable the one's that we 74711604612SMahesh Rajashekhara * can handle. 74811604612SMahesh Rajashekhara */ 74911604612SMahesh Rajashekhara aac_adapter_comm(dev, AAC_COMM_MESSAGE); 75011604612SMahesh Rajashekhara aac_adapter_disable_int(dev); 75111604612SMahesh Rajashekhara src_writel(dev, MUnit.ODR_C, 0xffffffff); 75211604612SMahesh Rajashekhara aac_adapter_enable_int(dev); 75311604612SMahesh Rajashekhara 75411604612SMahesh Rajashekhara if (aac_init_adapter(dev) == NULL) 75511604612SMahesh Rajashekhara goto error_iounmap; 75611604612SMahesh Rajashekhara if (dev->comm_interface != AAC_COMM_MESSAGE_TYPE1) 75711604612SMahesh Rajashekhara goto error_iounmap; 75811604612SMahesh Rajashekhara dev->msi = aac_msi && !pci_enable_msi(dev->pdev); 75911604612SMahesh Rajashekhara if (request_irq(dev->pdev->irq, dev->a_ops.adapter_intr, 76011604612SMahesh Rajashekhara IRQF_SHARED|IRQF_DISABLED, "aacraid", dev) < 0) { 76111604612SMahesh Rajashekhara if (dev->msi) 76211604612SMahesh Rajashekhara pci_disable_msi(dev->pdev); 76311604612SMahesh Rajashekhara printk(KERN_ERR "%s%d: Interrupt unavailable.\n", 76411604612SMahesh Rajashekhara name, instance); 76511604612SMahesh Rajashekhara goto error_iounmap; 76611604612SMahesh Rajashekhara } 76711604612SMahesh Rajashekhara dev->dbg_base = dev->scsi_host_ptr->base; 76811604612SMahesh Rajashekhara dev->dbg_base_mapped = dev->base; 76911604612SMahesh Rajashekhara dev->dbg_size = dev->base_size; 77011604612SMahesh Rajashekhara 77111604612SMahesh Rajashekhara aac_adapter_enable_int(dev); 77211604612SMahesh Rajashekhara 77311604612SMahesh Rajashekhara if (!dev->sync_mode) { 77411604612SMahesh Rajashekhara /* 77511604612SMahesh Rajashekhara * Tell the adapter that all is configured, and it can 77611604612SMahesh Rajashekhara * start accepting requests 77711604612SMahesh Rajashekhara */ 77811604612SMahesh Rajashekhara aac_src_start_adapter(dev); 77911604612SMahesh Rajashekhara } 78011604612SMahesh Rajashekhara return 0; 78111604612SMahesh Rajashekhara 78211604612SMahesh Rajashekhara error_iounmap: 78311604612SMahesh Rajashekhara 78411604612SMahesh Rajashekhara return -1; 78511604612SMahesh Rajashekhara } 78611604612SMahesh Rajashekhara 787