2019-05-19 15:51:48 +02:00
// SPDX-License-Identifier: GPL-2.0-or-later
2005-04-16 15:20:36 -07:00
/*
* Adaptec AAC series RAID controller driver
2008-10-27 15:16:36 +00:00
* ( c ) Copyright 2001 Red Hat Inc .
2005-04-16 15:20:36 -07:00
*
* based on the old aacraid driver that is . .
* Adaptec aacraid device driver for Linux .
*
2011-03-17 02:10:32 -07:00
* Copyright ( c ) 2000 - 2010 Adaptec , Inc .
2017-02-02 15:53:36 -08:00
* 2010 - 2015 PMC - Sierra , Inc . ( aacraid @ pmc - sierra . com )
* 2016 - 2017 Microsemi Corp . ( aacraid @ microsemi . com )
2005-04-16 15:20:36 -07:00
*
* Module Name :
* comminit . c
*
* Abstract : This supports the initialization of the host adapter commuication interface .
* This is a platform dependent module for the pci cyclone board .
*/
# 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>
2016-04-25 23:32:37 -07:00
# include <linux/delay.h>
2005-04-16 15:20:36 -07:00
# include <linux/completion.h>
# include <linux/mm.h>
2005-05-16 18:28:42 -07:00
# include <scsi/scsi_host.h>
2017-12-26 20:34:29 -08:00
# include <scsi/scsi_device.h>
# include <scsi/scsi_cmnd.h>
2005-04-16 15:20:36 -07:00
# include "aacraid.h"
2005-08-03 15:38:51 -07:00
struct aac_common aac_config = {
. irq_mod = 1
} ;
2005-04-16 15:20:36 -07:00
2016-04-25 23:32:37 -07:00
static inline int aac_is_msix_mode ( struct aac_dev * dev )
{
2017-02-09 11:04:47 -07:00
u32 status = 0 ;
2016-04-25 23:32:37 -07:00
2017-05-10 09:39:52 -07:00
if ( aac_is_src ( dev ) )
2017-02-09 11:04:47 -07:00
status = src_readl ( dev , MUnit . OMR ) ;
2016-04-25 23:32:37 -07:00
return ( status & AAC_INT_MODE_MSIX ) ;
}
static inline void aac_change_to_intx ( struct aac_dev * dev )
{
aac_src_access_devreg ( dev , AAC_DISABLE_MSIX ) ;
aac_src_access_devreg ( dev , AAC_ENABLE_INTX ) ;
}
2005-04-16 15:20:36 -07:00
static int aac_alloc_comm ( struct aac_dev * dev , void * * commaddr , unsigned long commsize , unsigned long commalign )
{
unsigned char * base ;
unsigned long size , align ;
2015-03-26 10:41:30 -04:00
const unsigned long fibsize = dev - > max_fib_size ;
2005-05-16 18:28:42 -07:00
const unsigned long printfbufsiz = 256 ;
2017-02-02 15:53:17 -08:00
unsigned long host_rrq_size , aac_init_size ;
union aac_init * init ;
2005-04-16 15:20:36 -07:00
dma_addr_t phys ;
2009-04-01 07:16:08 -07:00
unsigned long aac_max_hostphysmempages ;
2005-04-16 15:20:36 -07:00
2017-02-02 15:53:17 -08:00
if ( ( dev - > comm_interface = = AAC_COMM_MESSAGE_TYPE1 ) | |
( dev - > comm_interface = = AAC_COMM_MESSAGE_TYPE2 ) | |
2017-02-02 15:53:18 -08:00
( dev - > comm_interface = = AAC_COMM_MESSAGE_TYPE3 & &
! dev - > sa_firmware ) ) {
2017-02-02 15:53:17 -08:00
host_rrq_size =
( dev - > scsi_host_ptr - > can_queue + AAC_NUM_MGT_FIB )
* sizeof ( u32 ) ;
2017-02-02 15:53:18 -08:00
aac_init_size = sizeof ( union aac_init ) ;
} else if ( dev - > comm_interface = = AAC_COMM_MESSAGE_TYPE3 & &
dev - > sa_firmware ) {
2011-03-17 02:10:32 -07:00
host_rrq_size = ( dev - > scsi_host_ptr - > can_queue
2017-02-02 15:53:18 -08:00
+ AAC_NUM_MGT_FIB ) * sizeof ( u32 ) * AAC_MAX_MSIX ;
aac_init_size = sizeof ( union aac_init ) +
( AAC_MAX_HRRQ - 1 ) * sizeof ( struct _rrq ) ;
} else {
2017-02-02 15:53:17 -08:00
host_rrq_size = 0 ;
2017-02-02 15:53:18 -08:00
aac_init_size = sizeof ( union aac_init ) ;
}
2017-02-02 15:53:17 -08:00
size = fibsize + aac_init_size + commsize + commalign +
printfbufsiz + host_rrq_size ;
2017-04-05 16:14:16 +05:30
base = dma_alloc_coherent ( & dev - > pdev - > dev , size , & phys , GFP_KERNEL ) ;
2017-02-02 15:53:17 -08:00
if ( base = = NULL ) {
2005-04-16 15:20:36 -07:00
printk ( KERN_ERR " aacraid: unable to create mapping. \n " ) ;
return 0 ;
}
2017-02-02 15:53:17 -08:00
2005-04-16 15:20:36 -07:00
dev - > comm_addr = ( void * ) base ;
dev - > comm_phys = phys ;
dev - > comm_size = size ;
2017-02-02 15:53:17 -08:00
if ( ( dev - > comm_interface = = AAC_COMM_MESSAGE_TYPE1 ) | |
( dev - > comm_interface = = AAC_COMM_MESSAGE_TYPE2 ) | |
( dev - > comm_interface = = AAC_COMM_MESSAGE_TYPE3 ) ) {
2011-03-17 02:10:32 -07:00
dev - > host_rrq = ( u32 * ) ( base + fibsize ) ;
dev - > host_rrq_pa = phys + fibsize ;
memset ( dev - > host_rrq , 0 , host_rrq_size ) ;
}
2017-02-02 15:53:17 -08:00
dev - > init = ( union aac_init * ) ( base + fibsize + host_rrq_size ) ;
2011-03-17 02:10:32 -07:00
dev - > init_pa = phys + fibsize + host_rrq_size ;
2005-04-16 15:20:36 -07:00
init = dev - > init ;
2017-02-02 15:53:17 -08:00
if ( dev - > comm_interface = = AAC_COMM_MESSAGE_TYPE3 ) {
int i ;
u64 addr ;
init - > r8 . init_struct_revision =
cpu_to_le32 ( ADAPTER_INIT_STRUCT_REVISION_8 ) ;
init - > r8 . init_flags = cpu_to_le32 ( INITFLAGS_NEW_COMM_SUPPORTED |
INITFLAGS_DRIVER_USES_UTC_TIME |
INITFLAGS_DRIVER_SUPPORTS_PM ) ;
init - > r8 . init_flags | =
cpu_to_le32 ( INITFLAGS_DRIVER_SUPPORTS_HBA_MODE ) ;
init - > r8 . rr_queue_count = cpu_to_le32 ( dev - > max_msix ) ;
init - > r8 . max_io_size =
cpu_to_le32 ( dev - > scsi_host_ptr - > max_sectors < < 9 ) ;
init - > r8 . max_num_aif = init - > r8 . reserved1 =
init - > r8 . reserved2 = 0 ;
for ( i = 0 ; i < dev - > max_msix ; i + + ) {
addr = ( u64 ) dev - > host_rrq_pa + dev - > vector_cap * i *
sizeof ( u32 ) ;
init - > r8 . rrq [ i ] . host_addr_high = cpu_to_le32 (
upper_32_bits ( addr ) ) ;
init - > r8 . rrq [ i ] . host_addr_low = cpu_to_le32 (
lower_32_bits ( addr ) ) ;
init - > r8 . rrq [ i ] . msix_id = i ;
init - > r8 . rrq [ i ] . element_count = cpu_to_le16 (
( u16 ) dev - > vector_cap ) ;
init - > r8 . rrq [ i ] . comp_thresh =
init - > r8 . rrq [ i ] . unused = 0 ;
}
2005-04-16 15:20:36 -07:00
2017-02-02 15:53:17 -08:00
pr_warn ( " aacraid: Comm Interface type3 enabled \n " ) ;
} else {
init - > r7 . init_struct_revision =
cpu_to_le32 ( ADAPTER_INIT_STRUCT_REVISION ) ;
if ( dev - > max_fib_size ! = sizeof ( struct hw_fib ) )
init - > r7 . init_struct_revision =
cpu_to_le32 ( ADAPTER_INIT_STRUCT_REVISION_4 ) ;
init - > r7 . no_of_msix_vectors = cpu_to_le32 ( SA_MINIPORT_REVISION ) ;
init - > r7 . fsrev = cpu_to_le32 ( dev - > fsrev ) ;
/*
* Adapter Fibs are the first thing allocated so that they
* start page aligned
*/
dev - > aif_base_va = ( struct hw_fib * ) base ;
init - > r7 . adapter_fibs_virtual_address = 0 ;
init - > r7 . adapter_fibs_physical_address = cpu_to_le32 ( ( u32 ) phys ) ;
init - > r7 . adapter_fibs_size = cpu_to_le32 ( fibsize ) ;
init - > r7 . adapter_fib_align = cpu_to_le32 ( sizeof ( struct hw_fib ) ) ;
/*
* number of 4 k pages of host physical memory . The aacraid fw
* needs this number to be less than 4 gb worth of pages . New
* firmware doesn ' t have any issues with the mapping system , but
* older Firmware did , and had * troubles * dealing with the math
* overloading past 32 bits , thus we must limit this field .
*/
aac_max_hostphysmempages =
dma_get_required_mask ( & dev - > pdev - > dev ) > > 12 ;
if ( aac_max_hostphysmempages < AAC_MAX_HOSTPHYSMEMPAGES )
init - > r7 . host_phys_mem_pages =
cpu_to_le32 ( aac_max_hostphysmempages ) ;
else
init - > r7 . host_phys_mem_pages =
cpu_to_le32 ( AAC_MAX_HOSTPHYSMEMPAGES ) ;
init - > r7 . init_flags =
cpu_to_le32 ( INITFLAGS_DRIVER_USES_UTC_TIME |
INITFLAGS_DRIVER_SUPPORTS_PM ) ;
init - > r7 . max_io_commands =
cpu_to_le32 ( dev - > scsi_host_ptr - > can_queue +
AAC_NUM_MGT_FIB ) ;
init - > r7 . max_io_size =
cpu_to_le32 ( dev - > scsi_host_ptr - > max_sectors < < 9 ) ;
init - > r7 . max_fib_size = cpu_to_le32 ( dev - > max_fib_size ) ;
init - > r7 . max_num_aif = cpu_to_le32 ( dev - > max_num_aif ) ;
if ( dev - > comm_interface = = AAC_COMM_MESSAGE ) {
init - > r7 . init_flags | =
cpu_to_le32 ( INITFLAGS_NEW_COMM_SUPPORTED ) ;
pr_warn ( " aacraid: Comm Interface enabled \n " ) ;
} else if ( dev - > comm_interface = = AAC_COMM_MESSAGE_TYPE1 ) {
init - > r7 . init_struct_revision =
cpu_to_le32 ( ADAPTER_INIT_STRUCT_REVISION_6 ) ;
init - > r7 . init_flags | =
cpu_to_le32 ( INITFLAGS_NEW_COMM_SUPPORTED |
INITFLAGS_NEW_COMM_TYPE1_SUPPORTED |
INITFLAGS_FAST_JBOD_SUPPORTED ) ;
init - > r7 . host_rrq_addr_high =
cpu_to_le32 ( upper_32_bits ( dev - > host_rrq_pa ) ) ;
init - > r7 . host_rrq_addr_low =
cpu_to_le32 ( lower_32_bits ( dev - > host_rrq_pa ) ) ;
pr_warn ( " aacraid: Comm Interface type1 enabled \n " ) ;
} else if ( dev - > comm_interface = = AAC_COMM_MESSAGE_TYPE2 ) {
init - > r7 . init_struct_revision =
cpu_to_le32 ( ADAPTER_INIT_STRUCT_REVISION_7 ) ;
init - > r7 . init_flags | =
cpu_to_le32 ( INITFLAGS_NEW_COMM_SUPPORTED |
INITFLAGS_NEW_COMM_TYPE2_SUPPORTED |
INITFLAGS_FAST_JBOD_SUPPORTED ) ;
init - > r7 . host_rrq_addr_high =
cpu_to_le32 ( upper_32_bits ( dev - > host_rrq_pa ) ) ;
init - > r7 . host_rrq_addr_low =
cpu_to_le32 ( lower_32_bits ( dev - > host_rrq_pa ) ) ;
init - > r7 . no_of_msix_vectors =
cpu_to_le32 ( dev - > max_msix ) ;
/* must be the COMM_PREFERRED_SETTINGS values */
pr_warn ( " aacraid: Comm Interface type2 enabled \n " ) ;
}
2005-10-24 10:52:22 -07:00
}
2011-03-17 02:10:32 -07:00
2005-04-16 15:20:36 -07:00
/*
* Increment the base address by the amount already used
*/
2017-02-02 15:53:17 -08:00
base = base + fibsize + host_rrq_size + aac_init_size ;
2011-03-17 02:10:32 -07:00
phys = ( dma_addr_t ) ( ( ulong ) phys + fibsize + host_rrq_size +
2017-02-02 15:53:17 -08:00
aac_init_size ) ;
2011-03-17 02:10:32 -07:00
2005-04-16 15:20:36 -07:00
/*
* Align the beginning of Headers to commalign
*/
2007-10-29 05:11:28 +00:00
align = ( commalign - ( ( uintptr_t ) ( base ) & ( commalign - 1 ) ) ) ;
2005-04-16 15:20:36 -07:00
base = base + align ;
phys = phys + align ;
/*
* Fill in addresses of the Comm Area Headers and Queues
*/
* commaddr = base ;
2017-02-02 15:53:17 -08:00
if ( dev - > comm_interface ! = AAC_COMM_MESSAGE_TYPE3 )
init - > r7 . comm_header_address = cpu_to_le32 ( ( u32 ) phys ) ;
2005-04-16 15:20:36 -07:00
/*
* Increment the base address by the size of the CommArea
*/
base = base + commsize ;
phys = phys + commsize ;
/*
* Place the Printf buffer area after the Fast I / O comm area .
*/
dev - > printfbuf = ( void * ) base ;
2017-02-02 15:53:17 -08:00
if ( dev - > comm_interface ! = AAC_COMM_MESSAGE_TYPE3 ) {
init - > r7 . printfbuf = cpu_to_le32 ( phys ) ;
init - > r7 . printfbufsiz = cpu_to_le32 ( printfbufsiz ) ;
}
2005-04-16 15:20:36 -07:00
memset ( base , 0 , printfbufsiz ) ;
return 1 ;
}
2017-02-02 15:53:17 -08:00
2005-04-16 15:20:36 -07:00
static void aac_queue_init ( struct aac_dev * dev , struct aac_queue * q , u32 * mem , int qsize )
{
2015-03-26 10:41:30 -04:00
atomic_set ( & q - > numpending , 0 ) ;
2005-04-16 15:20:36 -07:00
q - > dev = dev ;
init_waitqueue_head ( & q - > cmdready ) ;
INIT_LIST_HEAD ( & q - > cmdq ) ;
init_waitqueue_head ( & q - > qfull ) ;
spin_lock_init ( & q - > lockdata ) ;
q - > lock = & q - > lockdata ;
2005-04-27 06:05:51 -07:00
q - > headers . producer = ( __le32 * ) mem ;
q - > headers . consumer = ( __le32 * ) ( mem + 1 ) ;
2005-04-16 15:20:36 -07:00
* ( q - > headers . producer ) = cpu_to_le32 ( qsize ) ;
* ( q - > headers . consumer ) = cpu_to_le32 ( qsize ) ;
q - > entries = qsize ;
}
2017-12-26 20:34:29 -08:00
static void aac_wait_for_io_completion ( struct aac_dev * aac )
{
unsigned long flagv = 0 ;
int i = 0 ;
for ( i = 60 ; i ; - - i ) {
struct scsi_device * dev ;
struct scsi_cmnd * command ;
int active = 0 ;
__shost_for_each_device ( dev , aac - > scsi_host_ptr ) {
spin_lock_irqsave ( & dev - > list_lock , flagv ) ;
list_for_each_entry ( command , & dev - > cmd_list , list ) {
if ( command - > SCp . phase = = AAC_OWNER_FIRMWARE ) {
active + + ;
break ;
}
}
spin_unlock_irqrestore ( & dev - > list_lock , flagv ) ;
if ( active )
break ;
}
/*
* We can exit If all the commands are complete
*/
if ( active = = 0 )
break ;
ssleep ( 1 ) ;
}
}
2005-04-16 15:20:36 -07:00
/**
* aac_send_shutdown - shutdown an adapter
* @ dev : Adapter to shutdown
*
* This routine will send a VM_CloseAll ( shutdown ) request to the adapter .
*/
int aac_send_shutdown ( struct aac_dev * dev )
{
struct fib * fibctx ;
struct aac_close * cmd ;
2017-12-26 20:34:27 -08:00
int status = 0 ;
2005-04-16 15:20:36 -07:00
2017-12-26 20:34:27 -08:00
if ( aac_adapter_check_health ( dev ) )
return status ;
2005-04-16 15:20:36 -07:00
2017-10-16 17:22:31 -07:00
if ( ! dev - > adapter_shutdown ) {
mutex_lock ( & dev - > ioctl_mutex ) ;
dev - > adapter_shutdown = 1 ;
mutex_unlock ( & dev - > ioctl_mutex ) ;
}
2005-04-16 15:20:36 -07:00
2017-12-26 20:34:29 -08:00
aac_wait_for_io_completion ( dev ) ;
2017-12-26 20:34:27 -08:00
fibctx = aac_fib_alloc ( dev ) ;
if ( ! fibctx )
return - ENOMEM ;
aac_fib_init ( fibctx ) ;
2016-02-03 15:06:06 -08:00
cmd = ( struct aac_close * ) fib_data ( fibctx ) ;
2005-04-16 15:20:36 -07:00
cmd - > command = cpu_to_le32 ( VM_CloseAll ) ;
2013-03-19 12:37:26 +05:30
cmd - > cid = cpu_to_le32 ( 0xfffffffe ) ;
2005-04-16 15:20:36 -07:00
2006-02-01 09:30:55 -08:00
status = aac_fib_send ( ContainerCommand ,
2005-04-16 15:20:36 -07:00
fibctx ,
sizeof ( struct aac_close ) ,
FsaNormal ,
2005-09-20 12:56:50 -07:00
- 2 /* Timeout silently */ , 1 ,
2005-04-16 15:20:36 -07:00
NULL , NULL ) ;
2006-08-03 08:03:07 -07:00
if ( status > = 0 )
2006-02-01 09:30:55 -08:00
aac_fib_complete ( fibctx ) ;
2009-12-21 18:39:27 +05:30
/* FIB should be freed only after getting the response from the F/W */
if ( status ! = - ERESTARTSYS )
aac_fib_free ( fibctx ) ;
2017-05-10 09:39:52 -07:00
if ( aac_is_src ( dev ) & &
2015-03-26 10:41:25 -04:00
dev - > msi_enabled )
2017-02-16 12:51:16 -08:00
aac_set_intx_mode ( dev ) ;
2005-04-16 15:20:36 -07:00
return status ;
}
/**
* aac_comm_init - Initialise FSA data structures
* @ dev : Adapter to initialise
*
* Initializes the data structures that are required for the FSA commuication
* interface to operate .
* Returns
* 1 - if we were able to init the commuication interface .
* 0 - If there were errors initing . This is a fatal error .
*/
2005-04-25 19:45:58 -07:00
static int aac_comm_init ( struct aac_dev * dev )
2005-04-16 15:20:36 -07:00
{
unsigned long hdrsize = ( sizeof ( u32 ) * NUMBER_OF_COMM_QUEUES ) * 2 ;
unsigned long queuesize = sizeof ( struct aac_entry ) * TOTAL_QUEUE_ENTRIES ;
u32 * headers ;
struct aac_entry * queues ;
unsigned long size ;
struct aac_queue_block * comm = dev - > queues ;
/*
* Now allocate and initialize the zone structures used as our
* pool of FIB context records . The size of the zone is based
* on the system memory size . We also initialize the mutex used
* to protect the zone .
*/
spin_lock_init ( & dev - > fib_lock ) ;
/*
tree-wide: fix assorted typos all over the place
That is "success", "unknown", "through", "performance", "[re|un]mapping"
, "access", "default", "reasonable", "[con]currently", "temperature"
, "channel", "[un]used", "application", "example","hierarchy", "therefore"
, "[over|under]flow", "contiguous", "threshold", "enough" and others.
Signed-off-by: André Goddard Rosa <andre.goddard@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
2009-11-14 13:09:05 -02:00
* Allocate the physically contiguous space for the commuication
2005-04-16 15:20:36 -07:00
* queue headers .
*/
size = hdrsize + queuesize ;
if ( ! aac_alloc_comm ( dev , ( void * * ) & headers , size , QUEUE_ALIGNMENT ) )
return - ENOMEM ;
queues = ( struct aac_entry * ) ( ( ( ulong ) headers ) + hdrsize ) ;
/* Adapter to Host normal priority Command queue */
comm - > queue [ HostNormCmdQueue ] . base = queues ;
aac_queue_init ( dev , & comm - > queue [ HostNormCmdQueue ] , headers , HOST_NORM_CMD_ENTRIES ) ;
queues + = HOST_NORM_CMD_ENTRIES ;
headers + = 2 ;
/* Adapter to Host high priority command queue */
comm - > queue [ HostHighCmdQueue ] . base = queues ;
aac_queue_init ( dev , & comm - > queue [ HostHighCmdQueue ] , headers , HOST_HIGH_CMD_ENTRIES ) ;
queues + = HOST_HIGH_CMD_ENTRIES ;
headers + = 2 ;
/* Host to adapter normal priority command queue */
comm - > queue [ AdapNormCmdQueue ] . base = queues ;
aac_queue_init ( dev , & comm - > queue [ AdapNormCmdQueue ] , headers , ADAP_NORM_CMD_ENTRIES ) ;
queues + = ADAP_NORM_CMD_ENTRIES ;
headers + = 2 ;
/* host to adapter high priority command queue */
comm - > queue [ AdapHighCmdQueue ] . base = queues ;
aac_queue_init ( dev , & comm - > queue [ AdapHighCmdQueue ] , headers , ADAP_HIGH_CMD_ENTRIES ) ;
queues + = ADAP_HIGH_CMD_ENTRIES ;
headers + = 2 ;
/* adapter to host normal priority response queue */
comm - > queue [ HostNormRespQueue ] . base = queues ;
aac_queue_init ( dev , & comm - > queue [ HostNormRespQueue ] , headers , HOST_NORM_RESP_ENTRIES ) ;
queues + = HOST_NORM_RESP_ENTRIES ;
headers + = 2 ;
/* adapter to host high priority response queue */
comm - > queue [ HostHighRespQueue ] . base = queues ;
aac_queue_init ( dev , & comm - > queue [ HostHighRespQueue ] , headers , HOST_HIGH_RESP_ENTRIES ) ;
queues + = HOST_HIGH_RESP_ENTRIES ;
headers + = 2 ;
/* host to adapter normal priority response queue */
comm - > queue [ AdapNormRespQueue ] . base = queues ;
aac_queue_init ( dev , & comm - > queue [ AdapNormRespQueue ] , headers , ADAP_NORM_RESP_ENTRIES ) ;
queues + = ADAP_NORM_RESP_ENTRIES ;
headers + = 2 ;
/* host to adapter high priority response queue */
comm - > queue [ AdapHighRespQueue ] . base = queues ;
aac_queue_init ( dev , & comm - > queue [ AdapHighRespQueue ] , headers , ADAP_HIGH_RESP_ENTRIES ) ;
comm - > queue [ AdapNormCmdQueue ] . lock = comm - > queue [ HostNormRespQueue ] . lock ;
comm - > queue [ AdapHighCmdQueue ] . lock = comm - > queue [ HostHighRespQueue ] . lock ;
comm - > queue [ AdapNormRespQueue ] . lock = comm - > queue [ HostNormCmdQueue ] . lock ;
comm - > queue [ AdapHighRespQueue ] . lock = comm - > queue [ HostHighCmdQueue ] . lock ;
return 0 ;
}
2015-08-28 06:38:34 -04:00
void aac_define_int_mode ( struct aac_dev * dev )
{
2015-08-28 06:38:40 -04:00
int i , msi_count , min_msix ;
2015-08-28 06:38:34 -04:00
msi_count = i = 0 ;
/* max. vectors from GET_COMM_PREFERRED_SETTINGS */
if ( dev - > max_msix = = 0 | |
dev - > pdev - > device = = PMC_DEVICE_S6 | |
dev - > sync_mode ) {
dev - > max_msix = 1 ;
dev - > vector_cap =
dev - > scsi_host_ptr - > can_queue +
AAC_NUM_MGT_FIB ;
return ;
}
/* Don't bother allocating more MSI-X vectors than cpus */
msi_count = min ( dev - > max_msix ,
( unsigned int ) num_online_cpus ( ) ) ;
dev - > max_msix = msi_count ;
if ( msi_count > AAC_MAX_MSIX )
msi_count = AAC_MAX_MSIX ;
if ( msi_count > 1 & &
pci_find_capability ( dev - > pdev , PCI_CAP_ID_MSIX ) ) {
2015-08-28 06:38:40 -04:00
min_msix = 2 ;
2016-11-08 08:11:30 +01:00
i = pci_alloc_irq_vectors ( dev - > pdev ,
min_msix , msi_count ,
PCI_IRQ_MSIX | PCI_IRQ_AFFINITY ) ;
2015-08-28 06:38:40 -04:00
if ( i > 0 ) {
2015-08-28 06:38:34 -04:00
dev - > msi_enabled = 1 ;
2015-08-28 06:38:40 -04:00
msi_count = i ;
2015-08-28 06:38:34 -04:00
} else {
dev - > msi_enabled = 0 ;
2016-04-25 23:31:43 -07:00
dev_err ( & dev - > pdev - > dev ,
" MSIX not supported!! Will try INTX 0x%x. \n " , i ) ;
2015-08-28 06:38:34 -04:00
}
}
if ( ! dev - > msi_enabled )
dev - > max_msix = msi_count = 1 ;
else {
if ( dev - > max_msix > msi_count )
dev - > max_msix = msi_count ;
}
2017-02-02 15:53:18 -08:00
if ( dev - > comm_interface = = AAC_COMM_MESSAGE_TYPE3 & & dev - > sa_firmware )
dev - > vector_cap = dev - > scsi_host_ptr - > can_queue +
AAC_NUM_MGT_FIB ;
else
dev - > vector_cap = ( dev - > scsi_host_ptr - > can_queue +
AAC_NUM_MGT_FIB ) / msi_count ;
2015-08-28 06:38:34 -04:00
}
2005-04-16 15:20:36 -07:00
struct aac_dev * aac_init_adapter ( struct aac_dev * dev )
{
2005-05-16 18:28:42 -07:00
u32 status [ 5 ] ;
struct Scsi_Host * host = dev - > scsi_host_ptr ;
2012-02-08 22:51:04 -08:00
extern int aac_sync_mode ;
2005-05-16 18:28:42 -07:00
/*
* Check the preferred comm settings , defaults from template .
*/
2009-12-21 18:39:27 +05:30
dev - > management_fib_count = 0 ;
spin_lock_init ( & dev - > manage_lock ) ;
2012-02-08 22:51:04 -08:00
spin_lock_init ( & dev - > sync_lock ) ;
2015-08-28 06:38:36 -04:00
spin_lock_init ( & dev - > iq_lock ) ;
2005-05-16 18:28:42 -07:00
dev - > max_fib_size = sizeof ( struct hw_fib ) ;
dev - > sg_tablesize = host - > sg_tablesize = ( dev - > max_fib_size
- sizeof ( struct aac_fibhdr )
2005-09-20 12:57:04 -07:00
- sizeof ( struct aac_write ) + sizeof ( struct sgentry ) )
/ sizeof ( struct sgentry ) ;
2007-01-23 14:59:20 -08:00
dev - > comm_interface = AAC_COMM_PRODUCER ;
2011-03-17 02:10:32 -07:00
dev - > raw_io_interface = dev - > raw_io_64 = 0 ;
2016-04-25 23:32:37 -07:00
/*
* Enable INTX mode , if not done already Enabled
*/
if ( aac_is_msix_mode ( dev ) ) {
aac_change_to_intx ( dev ) ;
dev_info ( & dev - > pdev - > dev , " Changed firmware to INTX mode " ) ;
}
2005-09-22 09:15:24 -07:00
if ( ( ! aac_adapter_sync_cmd ( dev , GET_ADAPTER_PROPERTIES ,
2015-03-26 10:41:28 -04:00
0 , 0 , 0 , 0 , 0 , 0 ,
2017-02-02 15:53:17 -08:00
status + 0 , status + 1 , status + 2 , status + 3 , status + 4 ) ) & &
( status [ 0 ] = = 0x00000001 ) ) {
2015-03-26 10:41:28 -04:00
dev - > doorbell_mask = status [ 3 ] ;
2017-02-02 15:53:17 -08:00
if ( status [ 1 ] & AAC_OPT_NEW_COMM_64 )
2005-09-22 09:15:24 -07:00
dev - > raw_io_64 = 1 ;
2012-02-08 22:51:04 -08:00
dev - > sync_mode = aac_sync_mode ;
if ( dev - > a_ops . adapter_comm & &
2017-08-29 13:59:02 +02:00
( status [ 1 ] & AAC_OPT_NEW_COMM ) ) {
dev - > comm_interface = AAC_COMM_MESSAGE ;
dev - > raw_io_interface = 1 ;
2017-02-02 15:53:17 -08:00
if ( ( status [ 1 ] & AAC_OPT_NEW_COMM_TYPE1 ) ) {
2012-02-08 22:51:04 -08:00
/* driver supports TYPE1 (Tupelo) */
dev - > comm_interface = AAC_COMM_MESSAGE_TYPE1 ;
2017-02-02 15:53:17 -08:00
} else if ( status [ 1 ] & AAC_OPT_NEW_COMM_TYPE2 ) {
/* driver supports TYPE2 (Denali, Yosemite) */
2012-07-14 18:18:51 +05:30
dev - > comm_interface = AAC_COMM_MESSAGE_TYPE2 ;
2017-02-02 15:53:17 -08:00
} else if ( status [ 1 ] & AAC_OPT_NEW_COMM_TYPE3 ) {
/* driver supports TYPE3 (Yosemite, Thor) */
dev - > comm_interface = AAC_COMM_MESSAGE_TYPE3 ;
} else if ( status [ 1 ] & AAC_OPT_NEW_COMM_TYPE4 ) {
/* not supported TYPE - switch to sync. mode */
2012-07-14 18:18:51 +05:30
dev - > comm_interface = AAC_COMM_MESSAGE_TYPE2 ;
dev - > sync_mode = 1 ;
2011-03-17 02:10:32 -07:00
}
}
2017-02-02 15:53:18 -08:00
if ( ( status [ 1 ] & le32_to_cpu ( AAC_OPT_EXTENDED ) ) & &
( status [ 4 ] & le32_to_cpu ( AAC_EXTOPT_SA_FIRMWARE ) ) )
dev - > sa_firmware = 1 ;
else
dev - > sa_firmware = 0 ;
2007-01-23 14:59:20 -08:00
if ( ( dev - > comm_interface = = AAC_COMM_MESSAGE ) & &
( status [ 2 ] > dev - > base_size ) ) {
2006-09-19 09:00:02 -07:00
aac_adapter_ioremap ( dev , 0 ) ;
2005-10-24 10:52:22 -07:00
dev - > base_size = status [ 2 ] ;
2006-09-19 09:00:02 -07:00
if ( aac_adapter_ioremap ( dev , status [ 2 ] ) ) {
2005-10-24 10:52:22 -07:00
/* remap failed, go back ... */
2007-01-23 14:59:20 -08:00
dev - > comm_interface = AAC_COMM_PRODUCER ;
2006-09-19 09:00:02 -07:00
if ( aac_adapter_ioremap ( dev , AAC_MIN_FOOTPRINT_SIZE ) ) {
2005-10-24 10:52:22 -07:00
printk ( KERN_WARNING
" aacraid: unable to map adapter. \n " ) ;
return NULL ;
}
}
}
2005-09-22 09:15:24 -07:00
}
2015-03-26 10:41:25 -04:00
dev - > max_msix = 0 ;
dev - > msi_enabled = 0 ;
2015-03-26 10:41:29 -04:00
dev - > adapter_shutdown = 0 ;
2005-05-16 18:28:42 -07:00
if ( ( ! aac_adapter_sync_cmd ( dev , GET_COMM_PREFERRED_SETTINGS ,
0 , 0 , 0 , 0 , 0 , 0 ,
status + 0 , status + 1 , status + 2 , status + 3 , status + 4 ) )
& & ( status [ 0 ] = = 0x00000001 ) ) {
/*
* status [ 1 ] > > 16 maximum command size in KB
* status [ 1 ] & 0xFFFF maximum FIB size
* status [ 2 ] > > 16 maximum SG elements to driver
* status [ 2 ] & 0xFFFF maximum SG elements from driver
* status [ 3 ] & 0xFFFF maximum number FIBs outstanding
*/
host - > max_sectors = ( status [ 1 ] > > 16 ) < < 1 ;
2011-03-17 02:10:32 -07:00
/* Multiple of 32 for PMC */
dev - > max_fib_size = status [ 1 ] & 0xFFE0 ;
2005-05-16 18:28:42 -07:00
host - > sg_tablesize = status [ 2 ] > > 16 ;
dev - > sg_tablesize = status [ 2 ] & 0xFFFF ;
2017-05-10 09:39:52 -07:00
if ( aac_is_src ( dev ) ) {
2017-02-02 15:53:18 -08:00
if ( host - > can_queue > ( status [ 3 ] > > 16 ) -
AAC_NUM_MGT_FIB )
host - > can_queue = ( status [ 3 ] > > 16 ) -
AAC_NUM_MGT_FIB ;
} else if ( host - > can_queue > ( status [ 3 ] & 0xFFFF ) -
AAC_NUM_MGT_FIB )
host - > can_queue = ( status [ 3 ] & 0xFFFF ) -
AAC_NUM_MGT_FIB ;
2011-03-17 02:10:32 -07:00
dev - > max_num_aif = status [ 4 ] & 0xFFFF ;
2005-05-16 18:28:42 -07:00
}
2017-02-02 15:53:18 -08:00
if ( numacb > 0 ) {
if ( numacb < host - > can_queue )
host - > can_queue = numacb ;
else
pr_warn ( " numacb=%d ignored \n " , numacb ) ;
2005-05-16 18:28:42 -07:00
}
2017-05-10 09:39:52 -07:00
if ( aac_is_src ( dev ) )
2015-03-26 10:41:25 -04:00
aac_define_int_mode ( dev ) ;
2005-04-16 15:20:36 -07:00
/*
* Ok now init the communication subsystem
*/
2007-04-16 11:21:50 -04:00
dev - > queues = kzalloc ( sizeof ( struct aac_queue_block ) , GFP_KERNEL ) ;
2005-04-16 15:20:36 -07:00
if ( dev - > queues = = NULL ) {
printk ( KERN_ERR " Error could not allocate comm region. \n " ) ;
return NULL ;
}
if ( aac_comm_init ( dev ) < 0 ) {
kfree ( dev - > queues ) ;
return NULL ;
}
/*
* Initialize the list of fibs
*/
2006-02-01 09:30:55 -08:00
if ( aac_fib_setup ( dev ) < 0 ) {
2005-04-16 15:20:36 -07:00
kfree ( dev - > queues ) ;
return NULL ;
}
INIT_LIST_HEAD ( & dev - > fib_list ) ;
2012-02-08 22:51:04 -08:00
INIT_LIST_HEAD ( & dev - > sync_fib_list ) ;
2005-04-16 15:20:36 -07:00
return dev ;
}