2009-09-24 04:46:15 +04:00
/*
2010-09-15 22:50:55 +04:00
* Copyright ( c ) 2005 - 2010 Brocade Communications Systems , Inc .
2009-09-24 04:46:15 +04:00
* All rights reserved
* www . brocade . com
*
* Linux driver for Brocade Fibre Channel Host Bus Adapter .
*
* This program is free software ; you can redistribute it and / or modify it
* under the terms of the GNU General Public License ( GPL ) Version 2 as
* published by the Free Software Foundation
*
* 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 .
*/
2010-09-15 22:50:55 +04:00
# include "bfa_defs_svc.h"
# include "bfa_port.h"
# include "bfi.h"
# include "bfa_ioc.h"
2009-09-24 04:46:15 +04:00
BFA_TRC_FILE ( CNA , PORT ) ;
# define bfa_ioc_portid(__ioc) ((__ioc)->port_id)
static void
2010-09-15 22:50:55 +04:00
bfa_port_stats_swap ( struct bfa_port_s * port , union bfa_port_stats_u * stats )
2009-09-24 04:46:15 +04:00
{
2010-09-15 22:50:55 +04:00
u32 * dip = ( u32 * ) stats ;
2010-11-30 05:26:32 +03:00
__be32 t0 , t1 ;
2010-09-15 22:50:55 +04:00
int i ;
2009-09-24 04:46:15 +04:00
2010-09-15 22:50:55 +04:00
for ( i = 0 ; i < sizeof ( union bfa_port_stats_u ) / sizeof ( u32 ) ;
i + = 2 ) {
2009-09-24 04:46:15 +04:00
t0 = dip [ i ] ;
t1 = dip [ i + 1 ] ;
# ifdef __BIGENDIAN
2010-10-19 04:10:50 +04:00
dip [ i ] = be32_to_cpu ( t0 ) ;
dip [ i + 1 ] = be32_to_cpu ( t1 ) ;
2009-09-24 04:46:15 +04:00
# else
2010-10-19 04:10:50 +04:00
dip [ i ] = be32_to_cpu ( t1 ) ;
dip [ i + 1 ] = be32_to_cpu ( t0 ) ;
2009-09-24 04:46:15 +04:00
# endif
}
}
2010-10-19 04:17:23 +04:00
/*
2009-09-24 04:46:15 +04:00
* bfa_port_enable_isr ( )
*
*
* @ param [ in ] port - Pointer to the port module
* status - Return status from the f / w
*
* @ return void
*/
static void
bfa_port_enable_isr ( struct bfa_port_s * port , bfa_status_t status )
{
2010-09-15 22:50:55 +04:00
bfa_trc ( port , status ) ;
port - > endis_pending = BFA_FALSE ;
port - > endis_cbfn ( port - > endis_cbarg , status ) ;
2009-09-24 04:46:15 +04:00
}
2010-10-19 04:17:23 +04:00
/*
2009-09-24 04:46:15 +04:00
* bfa_port_disable_isr ( )
*
*
* @ param [ in ] port - Pointer to the port module
* status - Return status from the f / w
*
* @ return void
*/
static void
bfa_port_disable_isr ( struct bfa_port_s * port , bfa_status_t status )
{
2010-09-15 22:50:55 +04:00
bfa_trc ( port , status ) ;
port - > endis_pending = BFA_FALSE ;
port - > endis_cbfn ( port - > endis_cbarg , status ) ;
2009-09-24 04:46:15 +04:00
}
2010-10-19 04:17:23 +04:00
/*
2009-09-24 04:46:15 +04:00
* bfa_port_get_stats_isr ( )
*
*
* @ param [ in ] port - Pointer to the Port module
* status - Return status from the f / w
*
* @ return void
*/
static void
bfa_port_get_stats_isr ( struct bfa_port_s * port , bfa_status_t status )
{
port - > stats_status = status ;
port - > stats_busy = BFA_FALSE ;
if ( status = = BFA_STATUS_OK ) {
2010-07-09 06:48:49 +04:00
struct bfa_timeval_s tv ;
2009-09-24 04:46:15 +04:00
memcpy ( port - > stats , port - > stats_dma . kva ,
2010-09-15 22:50:55 +04:00
sizeof ( union bfa_port_stats_u ) ) ;
2009-09-24 04:46:15 +04:00
bfa_port_stats_swap ( port , port - > stats ) ;
2010-07-09 06:48:49 +04:00
bfa_os_gettimeofday ( & tv ) ;
port - > stats - > fc . secs_reset = tv . tv_sec - port - > stats_reset_time ;
2009-09-24 04:46:15 +04:00
}
if ( port - > stats_cbfn ) {
port - > stats_cbfn ( port - > stats_cbarg , status ) ;
port - > stats_cbfn = NULL ;
}
}
2010-10-19 04:17:23 +04:00
/*
2009-09-24 04:46:15 +04:00
* bfa_port_clear_stats_isr ( )
*
*
* @ param [ in ] port - Pointer to the Port module
* status - Return status from the f / w
*
* @ return void
*/
static void
bfa_port_clear_stats_isr ( struct bfa_port_s * port , bfa_status_t status )
{
2010-07-09 06:48:49 +04:00
struct bfa_timeval_s tv ;
2009-09-24 04:46:15 +04:00
port - > stats_status = status ;
2010-09-15 22:50:55 +04:00
port - > stats_busy = BFA_FALSE ;
2009-09-24 04:46:15 +04:00
2010-10-19 04:17:23 +04:00
/*
2010-09-15 22:50:55 +04:00
* re - initialize time stamp for stats reset
*/
2010-07-09 06:48:49 +04:00
bfa_os_gettimeofday ( & tv ) ;
port - > stats_reset_time = tv . tv_sec ;
2009-09-24 04:46:15 +04:00
if ( port - > stats_cbfn ) {
port - > stats_cbfn ( port - > stats_cbarg , status ) ;
port - > stats_cbfn = NULL ;
}
}
2010-10-19 04:17:23 +04:00
/*
2009-09-24 04:46:15 +04:00
* bfa_port_isr ( )
*
*
* @ param [ in ] Pointer to the Port module data structure .
*
* @ return void
*/
static void
bfa_port_isr ( void * cbarg , struct bfi_mbmsg_s * m )
{
2010-09-15 22:50:55 +04:00
struct bfa_port_s * port = ( struct bfa_port_s * ) cbarg ;
2009-09-24 04:46:15 +04:00
union bfi_port_i2h_msg_u * i2hmsg ;
2010-09-15 22:50:55 +04:00
i2hmsg = ( union bfi_port_i2h_msg_u * ) m ;
2009-09-24 04:46:15 +04:00
bfa_trc ( port , m - > mh . msg_id ) ;
switch ( m - > mh . msg_id ) {
case BFI_PORT_I2H_ENABLE_RSP :
if ( port - > endis_pending = = BFA_FALSE )
break ;
bfa_port_enable_isr ( port , i2hmsg - > enable_rsp . status ) ;
break ;
case BFI_PORT_I2H_DISABLE_RSP :
if ( port - > endis_pending = = BFA_FALSE )
break ;
bfa_port_disable_isr ( port , i2hmsg - > disable_rsp . status ) ;
break ;
case BFI_PORT_I2H_GET_STATS_RSP :
2010-09-15 22:50:55 +04:00
/* Stats busy flag is still set? (may be cmd timed out) */
2009-09-24 04:46:15 +04:00
if ( port - > stats_busy = = BFA_FALSE )
break ;
bfa_port_get_stats_isr ( port , i2hmsg - > getstats_rsp . status ) ;
break ;
case BFI_PORT_I2H_CLEAR_STATS_RSP :
if ( port - > stats_busy = = BFA_FALSE )
break ;
bfa_port_clear_stats_isr ( port , i2hmsg - > clearstats_rsp . status ) ;
break ;
default :
bfa_assert ( 0 ) ;
}
}
2010-10-19 04:17:23 +04:00
/*
2009-09-24 04:46:15 +04:00
* bfa_port_meminfo ( )
*
*
* @ param [ in ] void
*
* @ return Size of DMA region
*/
u32
bfa_port_meminfo ( void )
{
2010-09-15 22:50:55 +04:00
return BFA_ROUNDUP ( sizeof ( union bfa_port_stats_u ) , BFA_DMA_ALIGN_SZ ) ;
2009-09-24 04:46:15 +04:00
}
2010-10-19 04:17:23 +04:00
/*
2009-09-24 04:46:15 +04:00
* bfa_port_mem_claim ( )
*
*
* @ param [ in ] port Port module pointer
2010-09-15 22:50:55 +04:00
* dma_kva Kernel Virtual Address of Port DMA Memory
* dma_pa Physical Address of Port DMA Memory
2009-09-24 04:46:15 +04:00
*
* @ return void
*/
void
bfa_port_mem_claim ( struct bfa_port_s * port , u8 * dma_kva , u64 dma_pa )
{
port - > stats_dma . kva = dma_kva ;
2010-09-15 22:50:55 +04:00
port - > stats_dma . pa = dma_pa ;
2009-09-24 04:46:15 +04:00
}
2010-10-19 04:17:23 +04:00
/*
2009-09-24 04:46:15 +04:00
* bfa_port_enable ( )
*
* Send the Port enable request to the f / w
*
* @ param [ in ] Pointer to the Port module data structure .
*
* @ return Status
*/
bfa_status_t
bfa_port_enable ( struct bfa_port_s * port , bfa_port_endis_cbfn_t cbfn ,
2010-09-15 22:50:55 +04:00
void * cbarg )
2009-09-24 04:46:15 +04:00
{
struct bfi_port_generic_req_s * m ;
2010-09-15 22:50:55 +04:00
if ( bfa_ioc_is_disabled ( port - > ioc ) ) {
bfa_trc ( port , BFA_STATUS_IOC_DISABLED ) ;
return BFA_STATUS_IOC_DISABLED ;
}
2009-09-24 04:46:15 +04:00
if ( ! bfa_ioc_is_operational ( port - > ioc ) ) {
bfa_trc ( port , BFA_STATUS_IOC_FAILURE ) ;
return BFA_STATUS_IOC_FAILURE ;
}
if ( port - > endis_pending ) {
bfa_trc ( port , BFA_STATUS_DEVBUSY ) ;
return BFA_STATUS_DEVBUSY ;
}
2010-09-15 22:50:55 +04:00
m = ( struct bfi_port_generic_req_s * ) port - > endis_mb . msg ;
2009-09-24 04:46:15 +04:00
port - > msgtag + + ;
2010-09-15 22:50:55 +04:00
port - > endis_cbfn = cbfn ;
port - > endis_cbarg = cbarg ;
2009-09-24 04:46:15 +04:00
port - > endis_pending = BFA_TRUE ;
bfi_h2i_set ( m - > mh , BFI_MC_PORT , BFI_PORT_H2I_ENABLE_REQ ,
bfa_ioc_portid ( port - > ioc ) ) ;
bfa_ioc_mbox_queue ( port - > ioc , & port - > endis_mb ) ;
return BFA_STATUS_OK ;
}
2010-10-19 04:17:23 +04:00
/*
2009-09-24 04:46:15 +04:00
* bfa_port_disable ( )
*
* Send the Port disable request to the f / w
*
* @ param [ in ] Pointer to the Port module data structure .
*
* @ return Status
*/
bfa_status_t
bfa_port_disable ( struct bfa_port_s * port , bfa_port_endis_cbfn_t cbfn ,
2010-09-15 22:50:55 +04:00
void * cbarg )
2009-09-24 04:46:15 +04:00
{
struct bfi_port_generic_req_s * m ;
2010-09-15 22:50:55 +04:00
if ( bfa_ioc_is_disabled ( port - > ioc ) ) {
bfa_trc ( port , BFA_STATUS_IOC_DISABLED ) ;
return BFA_STATUS_IOC_DISABLED ;
}
2009-09-24 04:46:15 +04:00
if ( ! bfa_ioc_is_operational ( port - > ioc ) ) {
bfa_trc ( port , BFA_STATUS_IOC_FAILURE ) ;
return BFA_STATUS_IOC_FAILURE ;
}
if ( port - > endis_pending ) {
bfa_trc ( port , BFA_STATUS_DEVBUSY ) ;
return BFA_STATUS_DEVBUSY ;
}
2010-09-15 22:50:55 +04:00
m = ( struct bfi_port_generic_req_s * ) port - > endis_mb . msg ;
2009-09-24 04:46:15 +04:00
port - > msgtag + + ;
2010-09-15 22:50:55 +04:00
port - > endis_cbfn = cbfn ;
port - > endis_cbarg = cbarg ;
2009-09-24 04:46:15 +04:00
port - > endis_pending = BFA_TRUE ;
bfi_h2i_set ( m - > mh , BFI_MC_PORT , BFI_PORT_H2I_DISABLE_REQ ,
bfa_ioc_portid ( port - > ioc ) ) ;
bfa_ioc_mbox_queue ( port - > ioc , & port - > endis_mb ) ;
return BFA_STATUS_OK ;
}
2010-10-19 04:17:23 +04:00
/*
2009-09-24 04:46:15 +04:00
* bfa_port_get_stats ( )
*
* Send the request to the f / w to fetch Port statistics .
*
* @ param [ in ] Pointer to the Port module data structure .
*
* @ return Status
*/
bfa_status_t
2010-09-15 22:50:55 +04:00
bfa_port_get_stats ( struct bfa_port_s * port , union bfa_port_stats_u * stats ,
bfa_port_stats_cbfn_t cbfn , void * cbarg )
2009-09-24 04:46:15 +04:00
{
struct bfi_port_get_stats_req_s * m ;
if ( ! bfa_ioc_is_operational ( port - > ioc ) ) {
bfa_trc ( port , BFA_STATUS_IOC_FAILURE ) ;
return BFA_STATUS_IOC_FAILURE ;
}
if ( port - > stats_busy ) {
bfa_trc ( port , BFA_STATUS_DEVBUSY ) ;
return BFA_STATUS_DEVBUSY ;
}
2010-09-15 22:50:55 +04:00
m = ( struct bfi_port_get_stats_req_s * ) port - > stats_mb . msg ;
2009-09-24 04:46:15 +04:00
2010-09-15 22:50:55 +04:00
port - > stats = stats ;
port - > stats_cbfn = cbfn ;
2009-09-24 04:46:15 +04:00
port - > stats_cbarg = cbarg ;
2010-09-15 22:50:55 +04:00
port - > stats_busy = BFA_TRUE ;
2009-09-24 04:46:15 +04:00
bfa_dma_be_addr_set ( m - > dma_addr , port - > stats_dma . pa ) ;
bfi_h2i_set ( m - > mh , BFI_MC_PORT , BFI_PORT_H2I_GET_STATS_REQ ,
bfa_ioc_portid ( port - > ioc ) ) ;
bfa_ioc_mbox_queue ( port - > ioc , & port - > stats_mb ) ;
return BFA_STATUS_OK ;
}
2010-10-19 04:17:23 +04:00
/*
2009-09-24 04:46:15 +04:00
* bfa_port_clear_stats ( )
*
*
* @ param [ in ] Pointer to the Port module data structure .
*
* @ return Status
*/
bfa_status_t
bfa_port_clear_stats ( struct bfa_port_s * port , bfa_port_stats_cbfn_t cbfn ,
2010-09-15 22:50:55 +04:00
void * cbarg )
2009-09-24 04:46:15 +04:00
{
struct bfi_port_generic_req_s * m ;
if ( ! bfa_ioc_is_operational ( port - > ioc ) ) {
bfa_trc ( port , BFA_STATUS_IOC_FAILURE ) ;
return BFA_STATUS_IOC_FAILURE ;
}
if ( port - > stats_busy ) {
bfa_trc ( port , BFA_STATUS_DEVBUSY ) ;
return BFA_STATUS_DEVBUSY ;
}
2010-09-15 22:50:55 +04:00
m = ( struct bfi_port_generic_req_s * ) port - > stats_mb . msg ;
2009-09-24 04:46:15 +04:00
2010-09-15 22:50:55 +04:00
port - > stats_cbfn = cbfn ;
2009-09-24 04:46:15 +04:00
port - > stats_cbarg = cbarg ;
2010-09-15 22:50:55 +04:00
port - > stats_busy = BFA_TRUE ;
2009-09-24 04:46:15 +04:00
bfi_h2i_set ( m - > mh , BFI_MC_PORT , BFI_PORT_H2I_CLEAR_STATS_REQ ,
bfa_ioc_portid ( port - > ioc ) ) ;
bfa_ioc_mbox_queue ( port - > ioc , & port - > stats_mb ) ;
return BFA_STATUS_OK ;
}
2010-10-19 04:17:23 +04:00
/*
2009-09-24 04:46:15 +04:00
* bfa_port_hbfail ( )
*
*
* @ param [ in ] Pointer to the Port module data structure .
*
* @ return void
*/
void
bfa_port_hbfail ( void * arg )
{
2010-09-15 22:50:55 +04:00
struct bfa_port_s * port = ( struct bfa_port_s * ) arg ;
2009-09-24 04:46:15 +04:00
2010-09-15 22:50:55 +04:00
/* Fail any pending get_stats/clear_stats requests */
2009-09-24 04:46:15 +04:00
if ( port - > stats_busy ) {
if ( port - > stats_cbfn )
2010-07-09 07:01:07 +04:00
port - > stats_cbfn ( port - > stats_cbarg , BFA_STATUS_FAILED ) ;
2009-09-24 04:46:15 +04:00
port - > stats_cbfn = NULL ;
port - > stats_busy = BFA_FALSE ;
}
2010-09-15 22:50:55 +04:00
/* Clear any enable/disable is pending */
2009-09-24 04:46:15 +04:00
if ( port - > endis_pending ) {
if ( port - > endis_cbfn )
2010-07-09 07:01:07 +04:00
port - > endis_cbfn ( port - > endis_cbarg , BFA_STATUS_FAILED ) ;
2009-09-24 04:46:15 +04:00
port - > endis_cbfn = NULL ;
port - > endis_pending = BFA_FALSE ;
}
}
2010-10-19 04:17:23 +04:00
/*
2009-09-24 04:46:15 +04:00
* bfa_port_attach ( )
*
*
* @ param [ in ] port - Pointer to the Port module data structure
* ioc - Pointer to the ioc module data structure
* dev - Pointer to the device driver module data structure
* The device driver specific mbox ISR functions have
* this pointer as one of the parameters .
* trcmod -
*
* @ return void
*/
void
2010-09-15 22:50:55 +04:00
bfa_port_attach ( struct bfa_port_s * port , struct bfa_ioc_s * ioc ,
void * dev , struct bfa_trc_mod_s * trcmod )
2009-09-24 04:46:15 +04:00
{
2010-07-09 06:48:49 +04:00
struct bfa_timeval_s tv ;
2009-09-24 04:46:15 +04:00
bfa_assert ( port ) ;
2010-09-15 22:50:55 +04:00
port - > dev = dev ;
port - > ioc = ioc ;
2009-09-24 04:46:15 +04:00
port - > trcmod = trcmod ;
2010-07-09 06:48:49 +04:00
port - > stats_busy = BFA_FALSE ;
port - > endis_pending = BFA_FALSE ;
port - > stats_cbfn = NULL ;
port - > endis_cbfn = NULL ;
2009-09-24 04:46:15 +04:00
bfa_ioc_mbox_regisr ( port - > ioc , BFI_MC_PORT , bfa_port_isr , port ) ;
bfa_ioc_hbfail_init ( & port - > hbfail , bfa_port_hbfail , port ) ;
2010-12-10 06:08:43 +03:00
list_add_tail ( & port - > hbfail . qe , & port - > ioc - > hb_notify_q ) ;
2009-09-24 04:46:15 +04:00
2010-10-19 04:17:23 +04:00
/*
2010-07-09 06:48:49 +04:00
* initialize time stamp for stats reset
*/
bfa_os_gettimeofday ( & tv ) ;
port - > stats_reset_time = tv . tv_sec ;
2009-09-24 04:46:15 +04:00
bfa_trc ( port , 0 ) ;
}