Commit a0549ef6073e346eb0cbbae1395d4db446b7b05e

Authored by Heinrich Schuchardt
Committed by Alexander Graf
1 parent 61da678c39

efi_loader: use events for efi_net_receive

A timer event is defined. The timer handler cares for receiving new
packets.

efi_timer_check is called both in efi_net_transmit and efi_net_receive
to enable events during network communication.

Calling efi_timer_check in efi_net_get_status is implemented in a
separate patch.

[agraf] This patch is needed to make efi_net_get_status() actually
        report incoming packets.

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
[agraf: fix spelling in comment]
Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Alexander Graf <agraf@suse.de>

Showing 1 changed file with 50 additions and 3 deletions Side-by-side Diff

lib/efi_loader/efi_net.c
... ... @@ -19,6 +19,11 @@
19 19 static struct efi_pxe_packet *dhcp_ack;
20 20 static bool new_rx_packet;
21 21 static void *new_tx_packet;
  22 +/*
  23 + * The notification function of this event is called in every timer cycle
  24 + * to check if a new network packet has been received.
  25 + */
  26 +static struct efi_event *network_timer_event;
22 27  
23 28 struct efi_net_obj {
24 29 /* Generic EFI object parent class data */
... ... @@ -143,6 +148,8 @@
143 148 EFI_ENTRY("%p, %lx, %lx, %p, %p, %p, %p", this, header_size,
144 149 buffer_size, buffer, src_addr, dest_addr, protocol);
145 150  
  151 + efi_timer_check();
  152 +
146 153 if (header_size) {
147 154 /* We would need to create the header if header_size != 0 */
148 155 return EFI_EXIT(EFI_INVALID_PARAMETER);
... ... @@ -174,9 +181,7 @@
174 181 EFI_ENTRY("%p, %p, %p, %p, %p, %p, %p", this, header_size,
175 182 buffer_size, buffer, src_addr, dest_addr, protocol);
176 183  
177   - push_packet = efi_net_push;
178   - eth_rx();
179   - push_packet = NULL;
  184 + efi_timer_check();
180 185  
181 186 if (!new_rx_packet)
182 187 return EFI_EXIT(EFI_NOT_READY);
183 188  
... ... @@ -204,10 +209,32 @@
204 209 memcpy(dhcp_ack, pkt, min(len, maxsize));
205 210 }
206 211  
  212 +/*
  213 + * Check if a new network packet has been received.
  214 + *
  215 + * This notification function is called in every timer cycle.
  216 + *
  217 + * @event the event for which this notification function is registered
  218 + * @context event context - not used in this function
  219 + */
  220 +static void EFIAPI efi_network_timer_notify(struct efi_event *event,
  221 + void *context)
  222 +{
  223 + EFI_ENTRY("%p, %p", event, context);
  224 +
  225 + if (!new_rx_packet) {
  226 + push_packet = efi_net_push;
  227 + eth_rx();
  228 + push_packet = NULL;
  229 + }
  230 + EFI_EXIT(EFI_SUCCESS);
  231 +}
  232 +
207 233 /* This gets called from do_bootefi_exec(). */
208 234 int efi_net_register(void)
209 235 {
210 236 struct efi_net_obj *netobj;
  237 + efi_status_t r;
211 238  
212 239 if (!eth_get_dev()) {
213 240 /* No eth device active, don't expose any */
... ... @@ -252,6 +279,26 @@
252 279  
253 280 /* Hook net up to the device list */
254 281 list_add_tail(&netobj->parent.link, &efi_obj_list);
  282 +
  283 + /*
  284 + * Create a timer event.
  285 + *
  286 + * The notification function is used to check if a new network packet
  287 + * has been received.
  288 + */
  289 + r = efi_create_event(EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_CALLBACK,
  290 + efi_network_timer_notify, NULL,
  291 + &network_timer_event);
  292 + if (r != EFI_SUCCESS) {
  293 + printf("ERROR: Failed to register network event\n");
  294 + return r;
  295 + }
  296 + /* Network is time critical, create event in every timer cyle */
  297 + r = efi_set_timer(network_timer_event, EFI_TIMER_PERIODIC, 0);
  298 + if (r != EFI_SUCCESS) {
  299 + printf("ERROR: Failed to set network timer\n");
  300 + return r;
  301 + }
255 302  
256 303 return 0;
257 304 }