2009-09-23 17:46:15 -07:00
/*
* Copyright ( c ) 2005 - 2009 Brocade Communications Systems , Inc .
* 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 .
*/
/**
* port_loop . c vport private loop implementation .
*/
# include <bfa.h>
# include <bfa_svc.h>
# include "fcs_lport.h"
# include "fcs_rport.h"
# include "fcs_trcmod.h"
# include "lport_priv.h"
BFA_TRC_FILE ( FCS , LOOP ) ;
/**
* ALPA to LIXA bitmap mapping
*
* ALPA 0x00 ( Word 0 , Bit 30 ) is invalid for N_Ports . Also Word 0 Bit 31
* is for L_bit ( login required ) and is filled as ALPA 0x00 here .
*/
static const u8 port_loop_alpa_map [ ] = {
0xEF , 0xE8 , 0xE4 , 0xE2 , 0xE1 , 0xE0 , 0xDC , 0xDA , /* Word 3 Bits 0..7 */
0xD9 , 0xD6 , 0xD5 , 0xD4 , 0xD3 , 0xD2 , 0xD1 , 0xCE , /* Word 3 Bits 8..15 */
0xCD , 0xCC , 0xCB , 0xCA , 0xC9 , 0xC7 , 0xC6 , 0xC5 , /* Word 3 Bits 16..23 */
0xC3 , 0xBC , 0xBA , 0xB9 , 0xB6 , 0xB5 , 0xB4 , 0xB3 , /* Word 3 Bits 24..31 */
0xB2 , 0xB1 , 0xAE , 0xAD , 0xAC , 0xAB , 0xAA , 0xA9 , /* Word 2 Bits 0..7 */
0xA7 , 0xA6 , 0xA5 , 0xA3 , 0x9F , 0x9E , 0x9D , 0x9B , /* Word 2 Bits 8..15 */
0x98 , 0x97 , 0x90 , 0x8F , 0x88 , 0x84 , 0x82 , 0x81 , /* Word 2 Bits 16..23 */
0x80 , 0x7C , 0x7A , 0x79 , 0x76 , 0x75 , 0x74 , 0x73 , /* Word 2 Bits 24..31 */
0x72 , 0x71 , 0x6E , 0x6D , 0x6C , 0x6B , 0x6A , 0x69 , /* Word 1 Bits 0..7 */
0x67 , 0x66 , 0x65 , 0x63 , 0x5C , 0x5A , 0x59 , 0x56 , /* Word 1 Bits 8..15 */
0x55 , 0x54 , 0x53 , 0x52 , 0x51 , 0x4E , 0x4D , 0x4C , /* Word 1 Bits 16..23 */
0x4B , 0x4A , 0x49 , 0x47 , 0x46 , 0x45 , 0x43 , 0x3C , /* Word 1 Bits 24..31 */
0x3A , 0x39 , 0x36 , 0x35 , 0x34 , 0x33 , 0x32 , 0x31 , /* Word 0 Bits 0..7 */
0x2E , 0x2D , 0x2C , 0x2B , 0x2A , 0x29 , 0x27 , 0x26 , /* Word 0 Bits 8..15 */
0x25 , 0x23 , 0x1F , 0x1E , 0x1D , 0x1B , 0x18 , 0x17 , /* Word 0 Bits 16..23 */
0x10 , 0x0F , 0x08 , 0x04 , 0x02 , 0x01 , 0x00 , 0x00 , /* Word 0 Bits 24..31 */
} ;
/*
* Local Functions
*/
2009-09-25 12:29:54 -07:00
static bfa_status_t bfa_fcs_port_loop_send_plogi ( struct bfa_fcs_port_s * port ,
u8 alpa ) ;
static void bfa_fcs_port_loop_plogi_response ( void * fcsarg ,
struct bfa_fcxp_s * fcxp ,
void * cbarg ,
bfa_status_t req_status ,
u32 rsp_len ,
u32 resid_len ,
struct fchs_s * rsp_fchs ) ;
2009-09-23 17:46:15 -07:00
/**
* Called by port to initializar in provate LOOP topology .
*/
void
bfa_fcs_port_loop_init ( struct bfa_fcs_port_s * port )
{
}
/**
* Called by port to notify transition to online state .
*/
void
bfa_fcs_port_loop_online ( struct bfa_fcs_port_s * port )
{
u8 num_alpa = port - > port_topo . ploop . num_alpa ;
u8 * alpa_pos_map = port - > port_topo . ploop . alpa_pos_map ;
struct bfa_fcs_rport_s * r_port ;
int ii = 0 ;
/*
* If the port role is Initiator Mode , create Rports .
*/
if ( port - > port_cfg . roles = = BFA_PORT_ROLE_FCP_IM ) {
/*
* Check if the ALPA positional bitmap is available .
* if not , we send PLOGI to all possible ALPAs .
*/
if ( num_alpa > 0 ) {
for ( ii = 0 ; ii < num_alpa ; ii + + ) {
/*
* ignore ALPA of bfa port
*/
if ( alpa_pos_map [ ii ] ! = port - > pid ) {
r_port = bfa_fcs_rport_create ( port ,
alpa_pos_map [ ii ] ) ;
}
}
} else {
for ( ii = 0 ; ii < MAX_ALPA_COUNT ; ii + + ) {
/*
* ignore ALPA of bfa port
*/
if ( ( port_loop_alpa_map [ ii ] > 0 )
& & ( port_loop_alpa_map [ ii ] ! = port - > pid ) )
bfa_fcs_port_loop_send_plogi ( port ,
port_loop_alpa_map [ ii ] ) ;
/**TBD */
}
}
} else {
/*
* TBD Target Mode ? ?
*/
}
}
/**
* Called by port to notify transition to offline state .
*/
void
bfa_fcs_port_loop_offline ( struct bfa_fcs_port_s * port )
{
}
/**
* Called by port to notify a LIP on the loop .
*/
void
bfa_fcs_port_loop_lip ( struct bfa_fcs_port_s * port )
{
}
/**
* Local Functions .
*/
2009-09-25 12:29:54 -07:00
static bfa_status_t
2009-09-23 17:46:15 -07:00
bfa_fcs_port_loop_send_plogi ( struct bfa_fcs_port_s * port , u8 alpa )
{
struct fchs_s fchs ;
struct bfa_fcxp_s * fcxp = NULL ;
int len ;
bfa_trc ( port - > fcs , alpa ) ;
fcxp = bfa_fcxp_alloc ( NULL , port - > fcs - > bfa , 0 , 0 , NULL , NULL , NULL ,
NULL ) ;
bfa_assert ( fcxp ) ;
len = fc_plogi_build ( & fchs , bfa_fcxp_get_reqbuf ( fcxp ) , alpa ,
bfa_fcs_port_get_fcid ( port ) , 0 ,
port - > port_cfg . pwwn , port - > port_cfg . nwwn ,
bfa_pport_get_maxfrsize ( port - > fcs - > bfa ) ) ;
bfa_fcxp_send ( fcxp , NULL , port - > fabric - > vf_id , port - > lp_tag , BFA_FALSE ,
FC_CLASS_3 , len , & fchs ,
bfa_fcs_port_loop_plogi_response , ( void * ) port ,
FC_MAX_PDUSZ , FC_RA_TOV ) ;
return BFA_STATUS_OK ;
}
/**
* Called by fcxp to notify the Plogi response
*/
2009-09-25 12:29:54 -07:00
static void
2009-09-23 17:46:15 -07:00
bfa_fcs_port_loop_plogi_response ( void * fcsarg , struct bfa_fcxp_s * fcxp ,
void * cbarg , bfa_status_t req_status ,
u32 rsp_len , u32 resid_len ,
struct fchs_s * rsp_fchs )
{
struct bfa_fcs_port_s * port = ( struct bfa_fcs_port_s * ) cbarg ;
struct fc_logi_s * plogi_resp ;
struct fc_els_cmd_s * els_cmd ;
bfa_trc ( port - > fcs , req_status ) ;
/*
* Sanity Checks
*/
if ( req_status ! = BFA_STATUS_OK ) {
bfa_trc ( port - > fcs , req_status ) ;
/*
* @ todo
* This could mean that the device with this APLA does not
* exist on the loop .
*/
return ;
}
els_cmd = ( struct fc_els_cmd_s * ) BFA_FCXP_RSP_PLD ( fcxp ) ;
plogi_resp = ( struct fc_logi_s * ) els_cmd ;
if ( els_cmd - > els_code = = FC_ELS_ACC ) {
bfa_fcs_rport_start ( port , rsp_fchs , plogi_resp ) ;
} else {
bfa_trc ( port - > fcs , plogi_resp - > els_cmd . els_code ) ;
bfa_assert ( 0 ) ;
}
}