diff --git a/src/include/gpxe/aoe.h b/src/include/gpxe/aoe.h index 60c7a823..c0706736 100644 --- a/src/include/gpxe/aoe.h +++ b/src/include/gpxe/aoe.h @@ -86,6 +86,9 @@ struct aoe_session { /** Network device */ struct net_device *netdev; + /** Reference to network device */ + struct reference netdev_ref; + /** Major number */ uint16_t major; /** Minor number */ diff --git a/src/net/aoe.c b/src/net/aoe.c index 199cabf7..2dc5ed40 100644 --- a/src/net/aoe.c +++ b/src/net/aoe.c @@ -76,6 +76,12 @@ static int aoe_send_command ( struct aoe_session *aoe ) { unsigned int count; unsigned int data_out_len; + /* Fail immediately if we have no netdev to send on */ + if ( ! aoe->netdev ) { + aoe_done ( aoe, -ENETUNREACH ); + return -ENETUNREACH; + } + /* Calculate count and data_out_len for this subcommand */ count = command->cb.count.native; if ( count > AOE_MAX_COUNT ) @@ -259,6 +265,19 @@ struct net_protocol aoe_protocol __net_protocol = { .rx = aoe_rx, }; +/** + * Forget reference to net_device + * + * @v ref Persistent reference + */ +static void aoe_forget_netdev ( struct reference *ref ) { + struct aoe_session *aoe + = container_of ( ref, struct aoe_session, netdev_ref ); + + aoe->netdev = NULL; + ref_del ( &aoe->netdev_ref ); +} + /** * Open AoE session * @@ -269,6 +288,8 @@ void aoe_open ( struct aoe_session *aoe ) { sizeof ( aoe->target ) ); aoe->tag = AOE_TAG_MAGIC; aoe->timer.expired = aoe_timer_expired; + aoe->netdev_ref.forget = aoe_forget_netdev; + ref_add ( &aoe->netdev_ref, &aoe->netdev->references ); list_add ( &aoe->list, &aoe_sessions ); } @@ -278,6 +299,8 @@ void aoe_open ( struct aoe_session *aoe ) { * @v aoe AoE session */ void aoe_close ( struct aoe_session *aoe ) { + if ( aoe->netdev ) + ref_del ( &aoe->netdev_ref ); list_del ( &aoe->list ); }