2011-03-17 02:10:32 -07:00
/*
* Adaptec AAC series RAID controller driver
* ( c ) Copyright 2001 Red Hat Inc .
*
* based on the old aacraid driver that is . .
* Adaptec aacraid device driver for Linux .
*
* 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
* the Free Software Foundation ; either version 2 , or ( at your option )
* any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; see the file COPYING . If not , write to
* the Free Software Foundation , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*
* Module Name :
* src . c
*
* Abstract : Hardware Device Interface for PMC SRC based controllers
*
*/
# include <linux/kernel.h>
# include <linux/init.h>
# include <linux/types.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 <scsi/scsi_host.h>
# include "aacraid.h"
static irqreturn_t aac_src_intr_message ( int irq , void * dev_id )
{
struct aac_dev * dev = dev_id ;
unsigned long bellbits , bellbits_shifted ;
int our_interrupt = 0 ;
int isFastResponse ;
u32 index , handle ;
bellbits = src_readl ( dev , MUnit . ODR_R ) ;
if ( bellbits & PmDoorBellResponseSent ) {
bellbits = PmDoorBellResponseSent ;
/* handle async. status */
2012-07-14 18:18:51 +05:30
src_writel ( dev , MUnit . ODR_C , bellbits ) ;
src_readl ( dev , MUnit . ODR_C ) ;
2011-03-17 02:10:32 -07:00
our_interrupt = 1 ;
index = dev - > host_rrq_idx ;
for ( ; ; ) {
isFastResponse = 0 ;
/* remove toggle bit (31) */
2012-06-11 16:14:36 -04:00
handle = le32_to_cpu ( dev - > host_rrq [ index ] ) & 0x7fffffff ;
2011-03-17 02:10:32 -07:00
/* check fast response bit (30) */
if ( handle & 0x40000000 )
isFastResponse = 1 ;
handle & = 0x0000ffff ;
if ( handle = = 0 )
break ;
aac_intr_normal ( dev , handle - 1 , 0 , isFastResponse , NULL ) ;
dev - > host_rrq [ index + + ] = 0 ;
if ( index = = dev - > scsi_host_ptr - > can_queue +
AAC_NUM_MGT_FIB )
index = 0 ;
dev - > host_rrq_idx = index ;
}
} else {
bellbits_shifted = ( bellbits > > SRC_ODR_SHIFT ) ;
if ( bellbits_shifted & DoorBellAifPending ) {
2012-07-14 18:18:51 +05:30
src_writel ( dev , MUnit . ODR_C , bellbits ) ;
src_readl ( dev , MUnit . ODR_C ) ;
2011-03-17 02:10:32 -07:00
our_interrupt = 1 ;
/* handle AIF */
aac_intr_normal ( dev , 0 , 2 , 0 , NULL ) ;
2012-02-08 22:51:04 -08:00
} else if ( bellbits_shifted & OUTBOUNDDOORBELL_0 ) {
unsigned long sflags ;
struct list_head * entry ;
int send_it = 0 ;
2012-07-14 18:18:51 +05:30
extern int aac_sync_mode ;
2013-06-18 17:02:07 +05:30
src_writel ( dev , MUnit . ODR_C , bellbits ) ;
src_readl ( dev , MUnit . ODR_C ) ;
2012-07-14 18:18:51 +05:30
if ( ! aac_sync_mode ) {
src_writel ( dev , MUnit . ODR_C , bellbits ) ;
src_readl ( dev , MUnit . ODR_C ) ;
our_interrupt = 1 ;
}
2012-02-08 22:51:04 -08:00
if ( dev - > sync_fib ) {
our_interrupt = 1 ;
if ( dev - > sync_fib - > callback )
dev - > sync_fib - > callback ( dev - > sync_fib - > callback_data ,
dev - > sync_fib ) ;
spin_lock_irqsave ( & dev - > sync_fib - > event_lock , sflags ) ;
if ( dev - > sync_fib - > flags & FIB_CONTEXT_FLAG_WAIT ) {
dev - > management_fib_count - - ;
up ( & dev - > sync_fib - > event_wait ) ;
}
spin_unlock_irqrestore ( & dev - > sync_fib - > event_lock , sflags ) ;
spin_lock_irqsave ( & dev - > sync_lock , sflags ) ;
if ( ! list_empty ( & dev - > sync_fib_list ) ) {
entry = dev - > sync_fib_list . next ;
dev - > sync_fib = list_entry ( entry , struct fib , fiblink ) ;
list_del ( entry ) ;
send_it = 1 ;
} else {
dev - > sync_fib = NULL ;
}
spin_unlock_irqrestore ( & dev - > sync_lock , sflags ) ;
if ( send_it ) {
aac_adapter_sync_cmd ( dev , SEND_SYNCHRONOUS_FIB ,
( u32 ) dev - > sync_fib - > hw_fib_pa , 0 , 0 , 0 , 0 , 0 ,
NULL , NULL , NULL , NULL , NULL ) ;
}
}
2011-03-17 02:10:32 -07:00
}
}
if ( our_interrupt ) {
return IRQ_HANDLED ;
}
return IRQ_NONE ;
}
/**
* aac_src_disable_interrupt - Disable interrupts
* @ dev : Adapter
*/
static void aac_src_disable_interrupt ( struct aac_dev * dev )
{
src_writel ( dev , MUnit . OIMR , dev - > OIMR = 0xffffffff ) ;
}
/**
* aac_src_enable_interrupt_message - Enable interrupts
* @ dev : Adapter
*/
static void aac_src_enable_interrupt_message ( struct aac_dev * dev )
{
src_writel ( dev , MUnit . OIMR , dev - > OIMR = 0xfffffff8 ) ;
}
/**
* src_sync_cmd - send a command and wait
* @ dev : Adapter
* @ command : Command to execute
* @ p1 : first parameter
* @ ret : adapter status
*
* This routine will send a synchronous command to the adapter and wait
* for its completion .
*/
static int src_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 ;
/*
* Write the command into Mailbox 0
*/
writel ( command , & dev - > IndexRegs - > Mailbox [ 0 ] ) ;
/*
* Write the parameters into Mailboxes 1 - 6
*/
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 .
*/
src_writel ( dev , MUnit . ODR_C , OUTBOUNDDOORBELL_0 < < SRC_ODR_SHIFT ) ;
/*
* Disable doorbell interrupts
*/
src_writel ( dev , MUnit . OIMR , dev - > OIMR = 0xffffffff ) ;
/*
* Force the completion of the mask register write before issuing
* the interrupt .
*/
src_readl ( dev , MUnit . OIMR ) ;
/*
* Signal that there is a new synch command
*/
src_writel ( dev , MUnit . IDR , INBOUNDDOORBELL_0 < < SRC_IDR_SHIFT ) ;
2012-02-08 22:51:04 -08:00
if ( ! dev - > sync_mode | | command ! = SEND_SYNCHRONOUS_FIB ) {
ok = 0 ;
start = jiffies ;
2011-03-17 02:10:32 -07:00
2012-02-08 22:51:04 -08:00
/*
* Wait up to 5 minutes
2011-03-17 02:10:32 -07:00
*/
2012-02-08 22:51:04 -08:00
while ( time_before ( jiffies , start + 300 * HZ ) ) {
udelay ( 5 ) ; /* Delay 5 microseconds to let Mon960 get info. */
/*
* Mon960 will set doorbell0 bit when it has completed the command .
*/
if ( ( src_readl ( dev , MUnit . ODR_R ) > > SRC_ODR_SHIFT ) & OUTBOUNDDOORBELL_0 ) {
/*
* Clear the doorbell .
*/
src_writel ( dev , MUnit . ODR_C , OUTBOUNDDOORBELL_0 < < SRC_ODR_SHIFT ) ;
ok = 1 ;
break ;
}
/*
* Yield the processor in case we are slow
*/
msleep ( 1 ) ;
2011-03-17 02:10:32 -07:00
}
2012-02-08 22:51:04 -08:00
if ( unlikely ( ok ! = 1 ) ) {
/*
* Restore interrupt mask even though we timed out
*/
aac_adapter_enable_int ( dev ) ;
return - ETIMEDOUT ;
}
/*
* Pull the synch status from Mailbox 0.
*/
if ( status )
* status = readl ( & dev - > IndexRegs - > Mailbox [ 0 ] ) ;
if ( r1 )
* r1 = readl ( & dev - > IndexRegs - > Mailbox [ 1 ] ) ;
if ( r2 )
* r2 = readl ( & dev - > IndexRegs - > Mailbox [ 2 ] ) ;
if ( r3 )
* r3 = readl ( & dev - > IndexRegs - > Mailbox [ 3 ] ) ;
if ( r4 )
* r4 = readl ( & dev - > IndexRegs - > Mailbox [ 4 ] ) ;
/*
* Clear the synch command doorbell .
*/
src_writel ( dev , MUnit . ODR_C , OUTBOUNDDOORBELL_0 < < SRC_ODR_SHIFT ) ;
2011-03-17 02:10:32 -07:00
}
2012-02-08 22:51:04 -08:00
/*
* Restore interrupt mask
*/
2011-03-17 02:10:32 -07:00
aac_adapter_enable_int ( dev ) ;
return 0 ;
}
/**
* aac_src_interrupt_adapter - interrupt adapter
* @ dev : Adapter
*
* Send an interrupt to the i960 and breakpoint it .
*/
static void aac_src_interrupt_adapter ( struct aac_dev * dev )
{
src_sync_cmd ( dev , BREAKPOINT_REQUEST ,
0 , 0 , 0 , 0 , 0 , 0 ,
NULL , NULL , NULL , NULL , NULL ) ;
}
/**
* aac_src_notify_adapter - send an event to the adapter
* @ dev : Adapter
* @ event : Event to send
*
* Notify the i960 that something it probably cares about has
* happened .
*/
static void aac_src_notify_adapter ( struct aac_dev * dev , u32 event )
{
switch ( event ) {
case AdapNormCmdQue :
src_writel ( dev , MUnit . ODR_C ,
INBOUNDDOORBELL_1 < < SRC_ODR_SHIFT ) ;
break ;
case HostNormRespNotFull :
src_writel ( dev , MUnit . ODR_C ,
INBOUNDDOORBELL_4 < < SRC_ODR_SHIFT ) ;
break ;
case AdapNormRespQue :
src_writel ( dev , MUnit . ODR_C ,
INBOUNDDOORBELL_2 < < SRC_ODR_SHIFT ) ;
break ;
case HostNormCmdNotFull :
src_writel ( dev , MUnit . ODR_C ,
INBOUNDDOORBELL_3 < < SRC_ODR_SHIFT ) ;
break ;
case FastIo :
src_writel ( dev , MUnit . ODR_C ,
INBOUNDDOORBELL_6 < < SRC_ODR_SHIFT ) ;
break ;
case AdapPrintfDone :
src_writel ( dev , MUnit . ODR_C ,
INBOUNDDOORBELL_5 < < SRC_ODR_SHIFT ) ;
break ;
default :
BUG ( ) ;
break ;
}
}
/**
* aac_src_start_adapter - activate adapter
* @ dev : Adapter
*
* Start up processing on an i960 based AAC adapter
*/
static void aac_src_start_adapter ( struct aac_dev * dev )
{
struct aac_init * init ;
2012-07-14 18:18:51 +05:30
/* reset host_rrq_idx first */
dev - > host_rrq_idx = 0 ;
2011-03-17 02:10:32 -07:00
init = dev - > init ;
init - > HostElapsedSeconds = cpu_to_le32 ( get_seconds ( ) ) ;
/* We can only use a 32 bit address here */
src_sync_cmd ( dev , INIT_STRUCT_BASE_ADDRESS , ( u32 ) ( ulong ) dev - > init_pa ,
0 , 0 , 0 , 0 , 0 , NULL , NULL , NULL , NULL , NULL ) ;
}
/**
* aac_src_check_health
* @ dev : device to check if healthy
*
* Will attempt to determine if the specified adapter is alive and
* capable of handling requests , returning 0 if alive .
*/
static int aac_src_check_health ( struct aac_dev * dev )
{
u32 status = src_readl ( dev , MUnit . OMR ) ;
/*
* Check to see if the board failed any self tests .
*/
if ( unlikely ( status & SELF_TEST_FAILED ) )
return - 1 ;
/*
* Check to see if the board panic ' d .
*/
if ( unlikely ( status & KERNEL_PANIC ) )
return ( status > > 16 ) & 0xFF ;
/*
* Wait for the adapter to be up and running .
*/
if ( unlikely ( ! ( status & KERNEL_UP_AND_RUNNING ) ) )
return - 3 ;
/*
* Everything is OK
*/
return 0 ;
}
/**
* aac_src_deliver_message
* @ fib : fib to issue
*
* Will send a fib , returning 0 if successful .
*/
static int aac_src_deliver_message ( struct fib * fib )
{
struct aac_dev * dev = fib - > dev ;
struct aac_queue * q = & dev - > queues - > queue [ AdapNormCmdQueue ] ;
unsigned long qflags ;
u32 fibsize ;
2012-06-11 16:14:36 -04:00
dma_addr_t address ;
2011-03-17 02:10:32 -07:00
struct aac_fib_xporthdr * pFibX ;
2012-06-11 16:14:36 -04:00
u16 hdr_size = le16_to_cpu ( fib - > hw_fib_va - > header . Size ) ;
2011-03-17 02:10:32 -07:00
spin_lock_irqsave ( q - > lock , qflags ) ;
q - > numpending + + ;
spin_unlock_irqrestore ( q - > lock , qflags ) ;
2012-07-14 18:18:51 +05:30
if ( dev - > comm_interface = = AAC_COMM_MESSAGE_TYPE2 ) {
/* Calculate the amount to the fibsize bits */
fibsize = ( hdr_size + 127 ) / 128 - 1 ;
if ( fibsize > ( ALIGN32 - 1 ) )
return - EMSGSIZE ;
/* New FIB header, 32-bit */
address = fib - > hw_fib_pa ;
fib - > hw_fib_va - > header . StructType = FIB_MAGIC2 ;
fib - > hw_fib_va - > header . SenderFibAddress = ( u32 ) address ;
fib - > hw_fib_va - > header . u . TimeStamp = 0 ;
2013-02-21 12:39:44 +01:00
BUG_ON ( upper_32_bits ( address ) ! = 0L ) ;
2012-07-14 18:18:51 +05:30
address | = fibsize ;
} else {
/* Calculate the amount to the fibsize bits */
fibsize = ( sizeof ( struct aac_fib_xporthdr ) + hdr_size + 127 ) / 128 - 1 ;
if ( fibsize > ( ALIGN32 - 1 ) )
return - EMSGSIZE ;
/* Fill XPORT header */
pFibX = ( void * ) fib - > hw_fib_va - sizeof ( struct aac_fib_xporthdr ) ;
pFibX - > Handle = cpu_to_le32 ( fib - > hw_fib_va - > header . Handle ) ;
pFibX - > HostAddress = cpu_to_le64 ( fib - > hw_fib_pa ) ;
pFibX - > Size = cpu_to_le32 ( hdr_size ) ;
2012-06-11 16:14:36 -04:00
2012-07-14 18:18:51 +05:30
/*
* The xport header has been 32 - byte aligned for us so that fibsize
* can be masked out of this address by hardware . - - BenC
*/
address = fib - > hw_fib_pa - sizeof ( struct aac_fib_xporthdr ) ;
if ( address & ( ALIGN32 - 1 ) )
return - EINVAL ;
address | = fibsize ;
}
2012-06-11 16:14:36 -04:00
2013-02-21 12:39:44 +01:00
src_writel ( dev , MUnit . IQ_H , upper_32_bits ( address ) & 0xffffffff ) ;
2012-06-11 16:14:36 -04:00
src_writel ( dev , MUnit . IQ_L , address & 0xffffffff ) ;
2011-03-17 02:10:32 -07:00
return 0 ;
}
/**
* aac_src_ioremap
* @ size : mapping resize request
*
*/
static int aac_src_ioremap ( struct aac_dev * dev , u32 size )
{
if ( ! size ) {
2012-03-29 17:23:46 +02:00
iounmap ( dev - > regs . src . bar1 ) ;
dev - > regs . src . bar1 = NULL ;
2011-03-17 02:10:32 -07:00
iounmap ( dev - > regs . src . bar0 ) ;
2012-02-08 22:51:04 -08:00
dev - > base = dev - > regs . src . bar0 = NULL ;
2011-03-17 02:10:32 -07:00
return 0 ;
}
dev - > regs . src . bar1 = ioremap ( pci_resource_start ( dev - > pdev , 2 ) ,
AAC_MIN_SRC_BAR1_SIZE ) ;
dev - > base = NULL ;
if ( dev - > regs . src . bar1 = = NULL )
return - 1 ;
2012-06-11 14:05:02 -04:00
dev - > base = dev - > regs . src . bar0 = ioremap ( dev - > base_start , size ) ;
2011-03-17 02:10:32 -07:00
if ( dev - > base = = NULL ) {
iounmap ( dev - > regs . src . bar1 ) ;
dev - > regs . src . bar1 = NULL ;
return - 1 ;
}
dev - > IndexRegs = & ( ( struct src_registers __iomem * )
2012-02-08 22:51:04 -08:00
dev - > base ) - > u . tupelo . IndexRegs ;
return 0 ;
}
/**
* aac_srcv_ioremap
* @ size : mapping resize request
*
*/
static int aac_srcv_ioremap ( struct aac_dev * dev , u32 size )
{
if ( ! size ) {
iounmap ( dev - > regs . src . bar0 ) ;
dev - > base = dev - > regs . src . bar0 = NULL ;
return 0 ;
}
2012-06-11 14:05:02 -04:00
dev - > base = dev - > regs . src . bar0 = ioremap ( dev - > base_start , size ) ;
2012-02-08 22:51:04 -08:00
if ( dev - > base = = NULL )
return - 1 ;
dev - > IndexRegs = & ( ( struct src_registers __iomem * )
dev - > base ) - > u . denali . IndexRegs ;
2011-03-17 02:10:32 -07:00
return 0 ;
}
static int aac_src_restart_adapter ( struct aac_dev * dev , int bled )
{
u32 var , reset_mask ;
if ( bled > = 0 ) {
if ( bled )
printk ( KERN_ERR " %s%d: adapter kernel panic'd %x. \n " ,
dev - > name , dev - > id , bled ) ;
bled = aac_adapter_sync_cmd ( dev , IOP_RESET_ALWAYS ,
0 , 0 , 0 , 0 , 0 , 0 , & var , & reset_mask , NULL , NULL , NULL ) ;
if ( bled | | ( var ! = 0x00000001 ) )
2012-02-08 22:51:04 -08:00
return - EINVAL ;
2011-03-17 02:10:32 -07:00
if ( dev - > supplement_adapter_info . SupportedOptions2 &
AAC_OPTION_DOORBELL_RESET ) {
src_writel ( dev , MUnit . IDR , reset_mask ) ;
msleep ( 5000 ) ; /* Delay 5 seconds */
}
}
if ( src_readl ( dev , MUnit . OMR ) & KERNEL_PANIC )
return - ENODEV ;
if ( startup_timeout < 300 )
startup_timeout = 300 ;
return 0 ;
}
/**
* aac_src_select_comm - Select communications method
* @ dev : Adapter
* @ comm : communications method
*/
int aac_src_select_comm ( struct aac_dev * dev , int comm )
{
switch ( comm ) {
case AAC_COMM_MESSAGE :
dev - > a_ops . adapter_enable_int = aac_src_enable_interrupt_message ;
dev - > a_ops . adapter_intr = aac_src_intr_message ;
dev - > a_ops . adapter_deliver = aac_src_deliver_message ;
break ;
default :
return 1 ;
}
return 0 ;
}
/**
* aac_src_init - initialize an Cardinal Frey Bar card
* @ dev : device to configure
*
*/
int aac_src_init ( struct aac_dev * dev )
{
unsigned long start ;
unsigned long status ;
int restart = 0 ;
int instance = dev - > id ;
const char * name = dev - > name ;
dev - > a_ops . adapter_ioremap = aac_src_ioremap ;
dev - > a_ops . adapter_comm = aac_src_select_comm ;
dev - > base_size = AAC_MIN_SRC_BAR0_SIZE ;
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 = src_sync_cmd ;
dev - > a_ops . adapter_enable_int = aac_src_disable_interrupt ;
if ( ( aac_reset_devices | | reset_devices ) & &
! aac_src_restart_adapter ( dev , 0 ) )
+ + restart ;
/*
* Check to see if the board panic ' d while booting .
*/
status = src_readl ( dev , MUnit . OMR ) ;
if ( status & KERNEL_PANIC ) {
if ( aac_src_restart_adapter ( dev , aac_src_check_health ( dev ) ) )
goto error_iounmap ;
+ + restart ;
}
/*
* Check to see if the board failed any self tests .
*/
status = src_readl ( dev , MUnit . OMR ) ;
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 monitor panic ' d while booting .
*/
if ( status & MONITOR_PANIC ) {
printk ( KERN_ERR " %s%d: adapter monitor panic. \n " ,
dev - > name , instance ) ;
goto error_iounmap ;
}
start = jiffies ;
/*
* Wait for the adapter to be up and running . Wait up to 3 minutes
*/
while ( ! ( ( status = src_readl ( dev , MUnit . OMR ) ) &
KERNEL_UP_AND_RUNNING ) ) {
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 ;
}
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_src_restart_adapter ( dev ,
aac_src_check_health ( dev ) ) ) )
start = jiffies ;
+ + restart ;
}
msleep ( 1 ) ;
}
if ( restart & & aac_commit )
aac_commit = 1 ;
/*
* Fill in the common function dispatch table .
*/
dev - > a_ops . adapter_interrupt = aac_src_interrupt_adapter ;
dev - > a_ops . adapter_disable_int = aac_src_disable_interrupt ;
dev - > a_ops . adapter_notify = aac_src_notify_adapter ;
dev - > a_ops . adapter_sync_cmd = src_sync_cmd ;
dev - > a_ops . adapter_check_health = aac_src_check_health ;
dev - > a_ops . adapter_restart = aac_src_restart_adapter ;
/*
* First clear out all interrupts . Then enable the one ' s that we
* can handle .
*/
aac_adapter_comm ( dev , AAC_COMM_MESSAGE ) ;
aac_adapter_disable_int ( dev ) ;
src_writel ( dev , MUnit . ODR_C , 0xffffffff ) ;
aac_adapter_enable_int ( dev ) ;
if ( aac_init_adapter ( dev ) = = NULL )
goto error_iounmap ;
if ( dev - > comm_interface ! = AAC_COMM_MESSAGE_TYPE1 )
goto error_iounmap ;
dev - > msi = aac_msi & & ! pci_enable_msi ( dev - > pdev ) ;
if ( request_irq ( dev - > pdev - > irq , dev - > a_ops . adapter_intr ,
2014-03-05 06:09:41 +01:00
IRQF_SHARED , " aacraid " , dev ) < 0 ) {
2011-03-17 02:10:32 -07:00
if ( dev - > msi )
pci_disable_msi ( dev - > pdev ) ;
printk ( KERN_ERR " %s%d: Interrupt unavailable. \n " ,
name , instance ) ;
goto error_iounmap ;
}
dev - > dbg_base = pci_resource_start ( dev - > pdev , 2 ) ;
dev - > dbg_base_mapped = dev - > regs . src . bar1 ;
dev - > dbg_size = AAC_MIN_SRC_BAR1_SIZE ;
aac_adapter_enable_int ( dev ) ;
2012-02-08 22:51:04 -08:00
if ( ! dev - > sync_mode ) {
/*
* Tell the adapter that all is configured , and it can
* start accepting requests
*/
aac_src_start_adapter ( dev ) ;
}
return 0 ;
error_iounmap :
return - 1 ;
}
/**
* aac_srcv_init - initialize an SRCv card
* @ dev : device to configure
*
*/
int aac_srcv_init ( struct aac_dev * dev )
{
unsigned long start ;
unsigned long status ;
int restart = 0 ;
int instance = dev - > id ;
const char * name = dev - > name ;
dev - > a_ops . adapter_ioremap = aac_srcv_ioremap ;
dev - > a_ops . adapter_comm = aac_src_select_comm ;
dev - > base_size = AAC_MIN_SRCV_BAR0_SIZE ;
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 = src_sync_cmd ;
dev - > a_ops . adapter_enable_int = aac_src_disable_interrupt ;
if ( ( aac_reset_devices | | reset_devices ) & &
! aac_src_restart_adapter ( dev , 0 ) )
+ + restart ;
2013-03-19 12:37:26 +05:30
/*
* Check to see if flash update is running .
* Wait for the adapter to be up and running . Wait up to 5 minutes
*/
status = src_readl ( dev , MUnit . OMR ) ;
if ( status & FLASH_UPD_PENDING ) {
start = jiffies ;
do {
status = src_readl ( dev , MUnit . OMR ) ;
if ( time_after ( jiffies , start + HZ * FWUPD_TIMEOUT ) ) {
printk ( KERN_ERR " %s%d: adapter flash update failed. \n " ,
dev - > name , instance ) ;
goto error_iounmap ;
}
} while ( ! ( status & FLASH_UPD_SUCCESS ) & &
! ( status & FLASH_UPD_FAILED ) ) ;
/* Delay 10 seconds.
* Because right now FW is doing a soft reset ,
* do not read scratch pad register at this time
*/
ssleep ( 10 ) ;
}
2011-03-17 02:10:32 -07:00
/*
2012-02-08 22:51:04 -08:00
* Check to see if the board panic ' d while booting .
2011-03-17 02:10:32 -07:00
*/
2012-02-08 22:51:04 -08:00
status = src_readl ( dev , MUnit . OMR ) ;
if ( status & KERNEL_PANIC ) {
if ( aac_src_restart_adapter ( dev , aac_src_check_health ( dev ) ) )
goto error_iounmap ;
+ + restart ;
}
/*
* Check to see if the board failed any self tests .
*/
status = src_readl ( dev , MUnit . OMR ) ;
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 monitor panic ' d while booting .
*/
if ( status & MONITOR_PANIC ) {
printk ( KERN_ERR " %s%d: adapter monitor panic. \n " , dev - > name , instance ) ;
goto error_iounmap ;
}
start = jiffies ;
/*
* Wait for the adapter to be up and running . Wait up to 3 minutes
*/
2013-03-19 12:37:26 +05:30
while ( ! ( ( status = src_readl ( dev , MUnit . OMR ) ) &
KERNEL_UP_AND_RUNNING ) | |
status = = 0xffffffff ) {
2012-02-08 22:51:04 -08:00
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 ;
}
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_src_restart_adapter ( dev , aac_src_check_health ( dev ) ) ) )
start = jiffies ;
+ + restart ;
}
msleep ( 1 ) ;
}
if ( restart & & aac_commit )
aac_commit = 1 ;
/*
* Fill in the common function dispatch table .
*/
dev - > a_ops . adapter_interrupt = aac_src_interrupt_adapter ;
dev - > a_ops . adapter_disable_int = aac_src_disable_interrupt ;
dev - > a_ops . adapter_notify = aac_src_notify_adapter ;
dev - > a_ops . adapter_sync_cmd = src_sync_cmd ;
dev - > a_ops . adapter_check_health = aac_src_check_health ;
dev - > a_ops . adapter_restart = aac_src_restart_adapter ;
/*
* First clear out all interrupts . Then enable the one ' s that we
* can handle .
*/
aac_adapter_comm ( dev , AAC_COMM_MESSAGE ) ;
aac_adapter_disable_int ( dev ) ;
src_writel ( dev , MUnit . ODR_C , 0xffffffff ) ;
aac_adapter_enable_int ( dev ) ;
2011-03-17 02:10:32 -07:00
2012-02-08 22:51:04 -08:00
if ( aac_init_adapter ( dev ) = = NULL )
goto error_iounmap ;
2012-07-14 18:18:51 +05:30
if ( dev - > comm_interface ! = AAC_COMM_MESSAGE_TYPE2 )
2012-02-08 22:51:04 -08:00
goto error_iounmap ;
dev - > msi = aac_msi & & ! pci_enable_msi ( dev - > pdev ) ;
if ( request_irq ( dev - > pdev - > irq , dev - > a_ops . adapter_intr ,
2014-03-05 06:09:41 +01:00
IRQF_SHARED , " aacraid " , dev ) < 0 ) {
2012-02-08 22:51:04 -08:00
if ( dev - > msi )
pci_disable_msi ( dev - > pdev ) ;
printk ( KERN_ERR " %s%d: Interrupt unavailable. \n " ,
name , instance ) ;
goto error_iounmap ;
}
2012-06-11 14:05:02 -04:00
dev - > dbg_base = dev - > base_start ;
2012-02-08 22:51:04 -08:00
dev - > dbg_base_mapped = dev - > base ;
dev - > dbg_size = dev - > base_size ;
aac_adapter_enable_int ( dev ) ;
if ( ! dev - > sync_mode ) {
/*
* Tell the adapter that all is configured , and it can
* start accepting requests
*/
aac_src_start_adapter ( dev ) ;
}
2011-03-17 02:10:32 -07:00
return 0 ;
error_iounmap :
return - 1 ;
}
2012-02-08 22:51:04 -08:00