An AoE session holds a persistent reference to a net device.
authorMichael Brown <mcb30@etherboot.org>
Thu, 4 Jan 2007 03:21:45 +0000 (03:21 +0000)
committerMichael Brown <mcb30@etherboot.org>
Thu, 4 Jan 2007 03:21:45 +0000 (03:21 +0000)
src/include/gpxe/aoe.h
src/net/aoe.c

index 60c7a82..c070673 100644 (file)
@@ -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 */
index 199cabf..2dc5ed4 100644 (file)
@@ -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 );
 }