GetStatus() must clear the interrupt status.
Transmit() should set the TX interrupt.
Receive() should clear the RX interrupt.
Initialize() and Start() should clear the interrupt status.

Signed-off-by: Heinrich Schuchardt <xypron.g...@gmx.de>
---
 include/efi_api.h        |  2 ++
 lib/efi_loader/efi_net.c | 40 +++++++++++++++++++++++++---------------
 2 files changed, 27 insertions(+), 15 deletions(-)

diff --git a/include/efi_api.h b/include/efi_api.h
index 43778197af..7f7b67fa00 100644
--- a/include/efi_api.h
+++ b/include/efi_api.h
@@ -1281,6 +1281,8 @@ struct efi_simple_network {
                        struct efi_mac_address *dest_addr, u16 *protocol);
        struct efi_event *wait_for_packet;
        struct efi_simple_network_mode *mode;
+       /* private fields */
+       u32 int_status;
 };

 #define EFI_PXE_BASE_CODE_PROTOCOL_GUID \
diff --git a/lib/efi_loader/efi_net.c b/lib/efi_loader/efi_net.c
index 825e064f9a..bf6d5ab0b3 100644
--- a/lib/efi_loader/efi_net.c
+++ b/lib/efi_loader/efi_net.c
@@ -66,10 +66,13 @@ static efi_status_t EFIAPI efi_net_start(struct 
efi_simple_network *this)
                goto out;
        }

-       if (this->mode->state != EFI_NETWORK_STOPPED)
+       if (this->mode->state != EFI_NETWORK_STOPPED) {
                ret = EFI_ALREADY_STARTED;
-       else
+       } else {
+               this->int_status = 0;
+               wait_for_packet->is_signaled = false;
                this->mode->state = EFI_NETWORK_STARTED;
+       }
 out:
        return EFI_EXIT(ret);
 }
@@ -144,6 +147,8 @@ static efi_status_t EFIAPI efi_net_initialize(struct 
efi_simple_network *this,
                r = EFI_DEVICE_ERROR;
                goto out;
        } else {
+               this->int_status = 0;
+               wait_for_packet->is_signaled = false;
                this->mode->state = EFI_NETWORK_INITIALIZED;
        }
 out:
@@ -192,6 +197,8 @@ static efi_status_t EFIAPI efi_net_shutdown(struct 
efi_simple_network *this)
        }

        eth_halt();
+       this->int_status = 0;
+       wait_for_packet->is_signaled = false;
        this->mode->state = EFI_NETWORK_STOPPED;

 out:
@@ -350,10 +357,8 @@ static efi_status_t EFIAPI efi_net_get_status(struct 
efi_simple_network *this,
        }

        if (int_status) {
-               /* We send packets synchronously, so nothing is outstanding */
-               *int_status = EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT;
-               if (new_rx_packet)
-                       *int_status |= EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;
+               *int_status = this->int_status;
+               this->int_status = 0;
        }
        if (txbuf)
                *txbuf = new_tx_packet;
@@ -429,7 +434,7 @@ static efi_status_t EFIAPI efi_net_transmit
        net_send_packet(transmit_buffer, buffer_size);

        new_tx_packet = buffer;
-
+       this->int_status |= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT;
 out:
        return EFI_EXIT(ret);
 }
@@ -487,12 +492,6 @@ static efi_status_t EFIAPI efi_net_receive
                ret = EFI_NOT_READY;
                goto out;
        }
-       /* Check that we at least received an Ethernet header */
-       if (net_rx_packet_len < sizeof(struct ethernet_hdr)) {
-               new_rx_packet = false;
-               ret = EFI_NOT_READY;
-               goto out;
-       }
        /* Fill export parameters */
        eth_hdr = (struct ethernet_hdr *)net_rx_packet;
        protlen = ntohs(eth_hdr->et_protlen);
@@ -517,7 +516,8 @@ static efi_status_t EFIAPI efi_net_receive
        /* Copy packet */
        memcpy(buffer, net_rx_packet, net_rx_packet_len);
        *buffer_size = net_rx_packet_len;
-       new_rx_packet = false;
+       new_rx_packet = 0;
+       this->int_status &= ~EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;
 out:
        return EFI_EXIT(ret);
 }
@@ -548,7 +548,6 @@ void efi_net_set_dhcp_ack(void *pkt, int len)
 static void efi_net_push(void *pkt, int len)
 {
        new_rx_packet = true;
-       wait_for_packet->is_signaled = true;
 }

 /**
@@ -577,6 +576,17 @@ static void EFIAPI efi_network_timer_notify(struct 
efi_event *event,
                push_packet = efi_net_push;
                eth_rx();
                push_packet = NULL;
+               if (new_rx_packet) {
+                       /* Check that we at least received an Ethernet header */
+                       if (net_rx_packet_len >=
+                           sizeof(struct ethernet_hdr)) {
+                               this->int_status |=
+                                       EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;
+                               wait_for_packet->is_signaled = true;
+                       } else {
+                               new_rx_packet = 0;
+                       }
+               }
        }
 out:
        EFI_EXIT(EFI_SUCCESS);
--
2.20.1

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot

Reply via email to