mirror of
https://github.com/ipxe/ipxe
synced 2026-02-14 02:31:26 +03:00
[fc] Maintain a list of Fibre Channel upper-layer protocol users
Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
@@ -357,7 +357,15 @@ struct fc_peer {
|
|||||||
|
|
||||||
/** List of upper-layer protocols */
|
/** List of upper-layer protocols */
|
||||||
struct list_head ulps;
|
struct list_head ulps;
|
||||||
/** Active usage count */
|
/** Active usage count
|
||||||
|
*
|
||||||
|
* A peer (and attached ULPs) may be created in response to
|
||||||
|
* unsolicited login requests received via the fabric. We
|
||||||
|
* track our own active usage count independently of the
|
||||||
|
* existence of the peer, so that if the peer becomes logged
|
||||||
|
* out (e.g. due to a link failure) then we know whether or
|
||||||
|
* not we should attempt to relogin.
|
||||||
|
*/
|
||||||
unsigned int usage;
|
unsigned int usage;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -424,8 +432,15 @@ struct fc_ulp {
|
|||||||
/** Service parameter length */
|
/** Service parameter length */
|
||||||
size_t param_len;
|
size_t param_len;
|
||||||
|
|
||||||
/** Active usage count */
|
/** Active users of this upper-layer protocol
|
||||||
unsigned int usage;
|
*
|
||||||
|
* As with peers, an upper-layer protocol may be created in
|
||||||
|
* response to an unsolicited login request received via the
|
||||||
|
* fabric. This list records the number of active users of
|
||||||
|
* the ULP; the number of entries in the list is equivalent to
|
||||||
|
* the peer usage count.
|
||||||
|
*/
|
||||||
|
struct list_head users;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Fibre Channel upper-layer protocol flags */
|
/** Fibre Channel upper-layer protocol flags */
|
||||||
@@ -434,6 +449,14 @@ enum fc_ulp_flags {
|
|||||||
FC_ULP_ORIGINATED_LOGIN_OK = 0x0001,
|
FC_ULP_ORIGINATED_LOGIN_OK = 0x0001,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** A Fibre Channel upper-layer protocol user */
|
||||||
|
struct fc_ulp_user {
|
||||||
|
/** Fibre Channel upper layer protocol */
|
||||||
|
struct fc_ulp *ulp;
|
||||||
|
/** List of users */
|
||||||
|
struct list_head list;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get reference to Fibre Channel upper-layer protocol
|
* Get reference to Fibre Channel upper-layer protocol
|
||||||
*
|
*
|
||||||
@@ -462,8 +485,8 @@ extern struct fc_ulp *
|
|||||||
fc_ulp_get_port_id_type ( struct fc_port *port,
|
fc_ulp_get_port_id_type ( struct fc_port *port,
|
||||||
const struct fc_port_id *peer_port_id,
|
const struct fc_port_id *peer_port_id,
|
||||||
unsigned int type );
|
unsigned int type );
|
||||||
extern void fc_ulp_increment ( struct fc_ulp *ulp );
|
extern void fc_ulp_attach ( struct fc_ulp *ulp, struct fc_ulp_user *user );
|
||||||
extern void fc_ulp_decrement ( struct fc_ulp *ulp );
|
extern void fc_ulp_detach ( struct fc_ulp_user *user );
|
||||||
extern int fc_ulp_login ( struct fc_ulp *ulp, const void *param,
|
extern int fc_ulp_login ( struct fc_ulp *ulp, const void *param,
|
||||||
size_t param_len, int originated );
|
size_t param_len, int originated );
|
||||||
extern void fc_ulp_logout ( struct fc_ulp *ulp, int rc );
|
extern void fc_ulp_logout ( struct fc_ulp *ulp, int rc );
|
||||||
|
|||||||
44
src/net/fc.c
44
src/net/fc.c
@@ -1580,7 +1580,7 @@ static void fc_ulp_close ( struct fc_ulp *ulp, int rc ) {
|
|||||||
fc_ntoa ( &ulp->peer->port_wwn ), ulp->type, strerror ( rc ) );
|
fc_ntoa ( &ulp->peer->port_wwn ), ulp->type, strerror ( rc ) );
|
||||||
|
|
||||||
/* Sanity check */
|
/* Sanity check */
|
||||||
assert ( ulp->usage == 0 );
|
assert ( list_empty ( &ulp->users ) );
|
||||||
|
|
||||||
/* Stop link monitor */
|
/* Stop link monitor */
|
||||||
fc_link_stop ( &ulp->link );
|
fc_link_stop ( &ulp->link );
|
||||||
@@ -1594,35 +1594,50 @@ static void fc_ulp_close ( struct fc_ulp *ulp, int rc ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Increment Fibre Channel upper-layer protocol active usage count
|
* Attach Fibre Channel upper-layer protocol user
|
||||||
*
|
*
|
||||||
* @v ulp Fibre Channel ulp
|
* @v ulp Fibre Channel upper-layer protocol
|
||||||
|
* @v user Fibre Channel upper-layer protocol user
|
||||||
*/
|
*/
|
||||||
void fc_ulp_increment ( struct fc_ulp *ulp ) {
|
void fc_ulp_attach ( struct fc_ulp *ulp, struct fc_ulp_user *user ) {
|
||||||
|
|
||||||
|
/* Sanity check */
|
||||||
|
assert ( user->ulp == NULL );
|
||||||
|
|
||||||
/* Increment peer's usage count */
|
/* Increment peer's usage count */
|
||||||
fc_peer_increment ( ulp->peer );
|
fc_peer_increment ( ulp->peer );
|
||||||
|
|
||||||
/* Increment our usage count */
|
/* Attach user */
|
||||||
ulp->usage++;
|
user->ulp = fc_ulp_get ( ulp );
|
||||||
|
list_add ( &user->list, &ulp->users );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decrement Fibre Channel upper-layer protocol active usage count
|
* Detach Fibre Channel upper-layer protocol user
|
||||||
*
|
*
|
||||||
* @v ulp Fibre Channel ulp
|
* @v user Fibre Channel upper-layer protocol user
|
||||||
*/
|
*/
|
||||||
void fc_ulp_decrement ( struct fc_ulp *ulp ) {
|
void fc_ulp_detach ( struct fc_ulp_user *user ) {
|
||||||
|
struct fc_ulp *ulp = user->ulp;
|
||||||
|
|
||||||
/* Sanity check */
|
/* Do nothing if not attached */
|
||||||
assert ( ulp->usage > 0 );
|
if ( ! ulp )
|
||||||
|
return;
|
||||||
|
|
||||||
/* Decrement our usage count and log out if we reach zero */
|
/* Sanity checks */
|
||||||
if ( --(ulp->usage) == 0 )
|
list_check_contains ( user, &ulp->users, list );
|
||||||
|
|
||||||
|
/* Detach user and log out if no users remain */
|
||||||
|
list_del ( &user->list );
|
||||||
|
if ( list_empty ( &ulp->users ) )
|
||||||
fc_ulp_logout ( ulp, 0 );
|
fc_ulp_logout ( ulp, 0 );
|
||||||
|
|
||||||
/* Decrement our peer's usage count */
|
/* Decrement our peer's usage count */
|
||||||
fc_peer_decrement ( ulp->peer );
|
fc_peer_decrement ( ulp->peer );
|
||||||
|
|
||||||
|
/* Drop reference */
|
||||||
|
user->ulp = NULL;
|
||||||
|
fc_ulp_put ( ulp );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1712,7 +1727,7 @@ void fc_ulp_logout ( struct fc_ulp *ulp, int rc ) {
|
|||||||
fc_link_err ( &ulp->link, rc );
|
fc_link_err ( &ulp->link, rc );
|
||||||
|
|
||||||
/* Close ULP if there are no clients attached */
|
/* Close ULP if there are no clients attached */
|
||||||
if ( ulp->usage == 0 )
|
if ( list_empty ( &ulp->users ) )
|
||||||
fc_ulp_close ( ulp, rc );
|
fc_ulp_close ( ulp, rc );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1795,6 +1810,7 @@ static struct fc_ulp * fc_ulp_create ( struct fc_peer *peer,
|
|||||||
ulp->peer = fc_peer_get ( peer );
|
ulp->peer = fc_peer_get ( peer );
|
||||||
list_add_tail ( &ulp->list, &peer->ulps );
|
list_add_tail ( &ulp->list, &peer->ulps );
|
||||||
ulp->type = type;
|
ulp->type = type;
|
||||||
|
INIT_LIST_HEAD ( &ulp->users );
|
||||||
|
|
||||||
/* Start link state monitor */
|
/* Start link state monitor */
|
||||||
fc_link_start ( &ulp->link );
|
fc_link_start ( &ulp->link );
|
||||||
|
|||||||
@@ -146,8 +146,8 @@ struct fc_els_prli_descriptor fcp_prli_descriptor __fc_els_prli_descriptor = {
|
|||||||
struct fcp_device {
|
struct fcp_device {
|
||||||
/** Reference count */
|
/** Reference count */
|
||||||
struct refcnt refcnt;
|
struct refcnt refcnt;
|
||||||
/** Fibre Channel upper-layer protocol */
|
/** Fibre Channel upper-layer protocol user */
|
||||||
struct fc_ulp *ulp;
|
struct fc_ulp_user user;
|
||||||
/** SCSI command issuing interface */
|
/** SCSI command issuing interface */
|
||||||
struct interface scsi;
|
struct interface scsi;
|
||||||
/** List of active commands */
|
/** List of active commands */
|
||||||
@@ -734,13 +734,13 @@ static struct interface_descriptor fcpcmd_xchg_desc =
|
|||||||
static int fcpdev_scsi_command ( struct fcp_device *fcpdev,
|
static int fcpdev_scsi_command ( struct fcp_device *fcpdev,
|
||||||
struct interface *parent,
|
struct interface *parent,
|
||||||
struct scsi_cmd *command ) {
|
struct scsi_cmd *command ) {
|
||||||
struct fcp_prli_service_parameters *param = fcpdev->ulp->param;
|
struct fcp_prli_service_parameters *param = fcpdev->user.ulp->param;
|
||||||
struct fcp_command *fcpcmd;
|
struct fcp_command *fcpcmd;
|
||||||
int xchg_id;
|
int xchg_id;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
/* Check link */
|
/* Check link */
|
||||||
if ( ( rc = fcpdev->ulp->link.rc ) != 0 ) {
|
if ( ( rc = fcpdev->user.ulp->link.rc ) != 0 ) {
|
||||||
DBGC ( fcpdev, "FCP %p could not issue command while link is "
|
DBGC ( fcpdev, "FCP %p could not issue command while link is "
|
||||||
"down: %s\n", fcpdev, strerror ( rc ) );
|
"down: %s\n", fcpdev, strerror ( rc ) );
|
||||||
goto err_link;
|
goto err_link;
|
||||||
@@ -748,7 +748,7 @@ static int fcpdev_scsi_command ( struct fcp_device *fcpdev,
|
|||||||
|
|
||||||
/* Check target capability */
|
/* Check target capability */
|
||||||
assert ( param != NULL );
|
assert ( param != NULL );
|
||||||
assert ( fcpdev->ulp->param_len >= sizeof ( *param ) );
|
assert ( fcpdev->user.ulp->param_len >= sizeof ( *param ) );
|
||||||
if ( ! ( param->flags & htonl ( FCP_PRLI_TARGET ) ) ) {
|
if ( ! ( param->flags & htonl ( FCP_PRLI_TARGET ) ) ) {
|
||||||
DBGC ( fcpdev, "FCP %p could not issue command: not a target\n",
|
DBGC ( fcpdev, "FCP %p could not issue command: not a target\n",
|
||||||
fcpdev );
|
fcpdev );
|
||||||
@@ -772,8 +772,8 @@ static int fcpdev_scsi_command ( struct fcp_device *fcpdev,
|
|||||||
|
|
||||||
/* Create new exchange */
|
/* Create new exchange */
|
||||||
if ( ( xchg_id = fc_xchg_originate ( &fcpcmd->xchg,
|
if ( ( xchg_id = fc_xchg_originate ( &fcpcmd->xchg,
|
||||||
fcpdev->ulp->peer->port,
|
fcpdev->user.ulp->peer->port,
|
||||||
&fcpdev->ulp->peer->port_id,
|
&fcpdev->user.ulp->peer->port_id,
|
||||||
FC_TYPE_FCP ) ) < 0 ) {
|
FC_TYPE_FCP ) ) < 0 ) {
|
||||||
rc = xchg_id;
|
rc = xchg_id;
|
||||||
DBGC ( fcpdev, "FCP %p could not create exchange: %s\n",
|
DBGC ( fcpdev, "FCP %p could not create exchange: %s\n",
|
||||||
@@ -822,11 +822,7 @@ static void fcpdev_close ( struct fcp_device *fcpdev, int rc ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Drop reference to ULP */
|
/* Drop reference to ULP */
|
||||||
if ( fcpdev->ulp ) {
|
fc_ulp_detach ( &fcpdev->user );
|
||||||
fc_ulp_decrement ( fcpdev->ulp );
|
|
||||||
fc_ulp_put ( fcpdev->ulp );
|
|
||||||
fcpdev->ulp = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -836,7 +832,8 @@ static void fcpdev_close ( struct fcp_device *fcpdev, int rc ) {
|
|||||||
* @ret len Length of window
|
* @ret len Length of window
|
||||||
*/
|
*/
|
||||||
static size_t fcpdev_window ( struct fcp_device *fcpdev ) {
|
static size_t fcpdev_window ( struct fcp_device *fcpdev ) {
|
||||||
return ( fc_link_ok ( &fcpdev->ulp->link ) ? ~( ( size_t ) 0 ) : 0 );
|
return ( fc_link_ok ( &fcpdev->user.ulp->link ) ?
|
||||||
|
~( ( size_t ) 0 ) : 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -897,15 +894,15 @@ static struct device * fcpdev_identify_device ( struct fcp_device *fcpdev ) {
|
|||||||
/* We know the underlying device only if the link is up;
|
/* We know the underlying device only if the link is up;
|
||||||
* otherwise we don't have a port to examine.
|
* otherwise we don't have a port to examine.
|
||||||
*/
|
*/
|
||||||
if ( ! fc_link_ok ( &fcpdev->ulp->link ) ) {
|
if ( ! fc_link_ok ( &fcpdev->user.ulp->link ) ) {
|
||||||
DBGC ( fcpdev, "FCP %p doesn't know underlying device "
|
DBGC ( fcpdev, "FCP %p doesn't know underlying device "
|
||||||
"until link is up\n", fcpdev );
|
"until link is up\n", fcpdev );
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Hand off to port's transport interface */
|
/* Hand off to port's transport interface */
|
||||||
assert ( fcpdev->ulp->peer->port != NULL );
|
assert ( fcpdev->user.ulp->peer->port != NULL );
|
||||||
return identify_device ( &fcpdev->ulp->peer->port->transport );
|
return identify_device ( &fcpdev->user.ulp->peer->port->transport );
|
||||||
}
|
}
|
||||||
|
|
||||||
/** FCP device SCSI interface operations */
|
/** FCP device SCSI interface operations */
|
||||||
@@ -953,8 +950,7 @@ static int fcpdev_open ( struct interface *parent, struct fc_name *wwn,
|
|||||||
ref_init ( &fcpdev->refcnt, NULL );
|
ref_init ( &fcpdev->refcnt, NULL );
|
||||||
intf_init ( &fcpdev->scsi, &fcpdev_scsi_desc, &fcpdev->refcnt );
|
intf_init ( &fcpdev->scsi, &fcpdev_scsi_desc, &fcpdev->refcnt );
|
||||||
INIT_LIST_HEAD ( &fcpdev->fcpcmds );
|
INIT_LIST_HEAD ( &fcpdev->fcpcmds );
|
||||||
fcpdev->ulp = fc_ulp_get ( ulp );
|
fc_ulp_attach ( ulp, &fcpdev->user );
|
||||||
fc_ulp_increment ( fcpdev->ulp );
|
|
||||||
|
|
||||||
DBGC ( fcpdev, "FCP %p opened for %s\n", fcpdev, fc_ntoa ( wwn ) );
|
DBGC ( fcpdev, "FCP %p opened for %s\n", fcpdev, fc_ntoa ( wwn ) );
|
||||||
|
|
||||||
|
|||||||
@@ -74,8 +74,7 @@ void fcpeerstat ( struct fc_peer *peer ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
list_for_each_entry ( ulp, &peer->ulps, list ) {
|
list_for_each_entry ( ulp, &peer->ulps, list ) {
|
||||||
printf ( " [Type %02x usage %d link:",
|
printf ( " [Type %02x link:", ulp->type );
|
||||||
ulp->type, ulp->usage );
|
|
||||||
if ( fc_link_ok ( &ulp->link ) ) {
|
if ( fc_link_ok ( &ulp->link ) ) {
|
||||||
printf ( " up, params" );
|
printf ( " up, params" );
|
||||||
param = ulp->param;
|
param = ulp->param;
|
||||||
|
|||||||
Reference in New Issue
Block a user