[PATCH 17/21] efi_loader: efi_net: add snp_owner field to efi_net_obj struct
Adriano Cordova
adrianox at gmail.com
Wed Jan 22 18:08:54 CET 2025
Let a simple network protocol interface be shared by more than one efi
net device, but with only one owner. The owner should be the efi net device
whose underlying udevice does not use the snp protocol for its ethernet ops.
See efi_selftest_net_driver for an use.
Signed-off-by: Adriano Cordova <adriano.cordova at canonical.com>
---
lib/efi_loader/efi_net.c | 50 +++++++++++++++++++++++++---------------
1 file changed, 32 insertions(+), 18 deletions(-)
diff --git a/lib/efi_loader/efi_net.c b/lib/efi_loader/efi_net.c
index c172da4e66..2f981b043a 100644
--- a/lib/efi_loader/efi_net.c
+++ b/lib/efi_loader/efi_net.c
@@ -104,6 +104,7 @@ struct efi_net_obj {
*/
struct efi_event *network_timer_event;
int efi_seq_num;
+ bool snp_owner;
};
static int curr_efi_net_obj;
@@ -128,14 +129,17 @@ static bool efi_netobj_is_active(struct efi_net_obj *netobj)
*
*
* @snp: pointer to the simple network protocol
+ * @bool: snp owner
* Return: pointer to efi_net_obj, NULL on error
*/
-static struct efi_net_obj *efi_netobj_from_snp(struct efi_simple_network *snp)
+static struct efi_net_obj *efi_netobj_from_snp(struct efi_simple_network *snp,
+ bool snp_owner)
{
int i;
for (i = 0; i < MAX_EFI_NET_OBJS; i++) {
- if (net_objs[i] && net_objs[i]->net == snp) {
+ if (net_objs[i] && net_objs[i]->net == snp &&
+ (!snp_owner || net_objs[i]->snp_owner)) {
// Do not register duplicate devices
return net_objs[i];
}
@@ -165,7 +169,7 @@ static efi_status_t EFIAPI efi_net_start(struct efi_simple_network *this)
goto out;
}
- nt = efi_netobj_from_snp(this);
+ nt = efi_netobj_from_snp(this, true);
if (this->mode->state != EFI_NETWORK_STOPPED) {
ret = EFI_ALREADY_STARTED;
@@ -201,7 +205,7 @@ static efi_status_t EFIAPI efi_net_stop(struct efi_simple_network *this)
goto out;
}
- nt = efi_netobj_from_snp(this);
+ nt = efi_netobj_from_snp(this, true);
if (this->mode->state == EFI_NETWORK_STOPPED) {
ret = EFI_NOT_STARTED;
@@ -244,7 +248,7 @@ static efi_status_t EFIAPI efi_net_initialize(struct efi_simple_network *this,
r = EFI_INVALID_PARAMETER;
goto out;
}
- nt = efi_netobj_from_snp(this);
+ nt = efi_netobj_from_snp(this, true);
switch (this->mode->state) {
case EFI_NETWORK_INITIALIZED:
@@ -341,7 +345,7 @@ static efi_status_t EFIAPI efi_net_shutdown(struct efi_simple_network *this)
ret = EFI_INVALID_PARAMETER;
goto out;
}
- nt = efi_netobj_from_snp(this);
+ nt = efi_netobj_from_snp(this, true);
switch (this->mode->state) {
case EFI_NETWORK_INITIALIZED:
@@ -547,7 +551,7 @@ static efi_status_t EFIAPI efi_net_get_status(struct efi_simple_network *this,
goto out;
}
- nt = efi_netobj_from_snp(this);
+ nt = efi_netobj_from_snp(this, true);
switch (this->mode->state) {
case EFI_NETWORK_STOPPED:
@@ -608,7 +612,7 @@ static efi_status_t EFIAPI efi_net_transmit
goto out;
}
- nt = efi_netobj_from_snp(this);
+ nt = efi_netobj_from_snp(this, true);
/* We do not support jumbo packets */
if (buffer_size > PKTSIZE_ALIGN) {
@@ -706,7 +710,7 @@ static efi_status_t EFIAPI efi_net_receive
goto out;
}
- nt = efi_netobj_from_snp(this);
+ nt = efi_netobj_from_snp(this, true);
switch (this->mode->state) {
case EFI_NETWORK_STOPPED:
@@ -864,7 +868,7 @@ static void EFIAPI efi_network_timer_notify(struct efi_event *event,
if (!this || this->mode->state != EFI_NETWORK_INITIALIZED)
goto out;
- nt = efi_netobj_from_snp(this);
+ nt = efi_netobj_from_snp(this, true);
curr_efi_net_obj = nt->efi_seq_num;
// The following only happens if the net obj was removed but the event
@@ -1194,7 +1198,7 @@ static int efi_netobj_init(struct efi_net_obj *netobj)
dev = netobj->dev;
- if (efi_netobj_is_active(netobj))
+ if (efi_netobj_is_active(netobj) || !netobj->snp_owner)
goto set_timers;
if (!netobj->net_mode)
@@ -1408,6 +1412,7 @@ struct efi_net_obj *efi_netobj_alloc(efi_handle_t handle,
free(netobj->net->mode);
free(netobj->net);
}
+ netobj->net = NULL;
if (handle) {
netobj->handle = handle;
@@ -1419,6 +1424,8 @@ struct efi_net_obj *efi_netobj_alloc(efi_handle_t handle,
}
}
+ netobj->snp_owner = efi_netobj_from_snp(net, true) ? false : true;
+
if (net) {
netobj->net = net;
netobj->net_mode = net->mode;
@@ -1546,14 +1553,9 @@ int efi_net_unregister(void *ctx, struct event *event)
return -1;
}
+ interface = NULL;
if (drv != dev->driver) {
ret = EFI_CALL(efi_disconnect_controller(netobj->handle, NULL, NULL));
- if (ret != EFI_SUCCESS)
- return -1;
- ret = EFI_CALL(efi_close_event(netobj->wait_for_packet));
- if (ret != EFI_SUCCESS)
- return -1;
- ret = EFI_CALL(efi_close_event(netobj->network_timer_event));
if (ret != EFI_SUCCESS)
return -1;
@@ -1569,6 +1571,15 @@ int efi_net_unregister(void *ctx, struct event *event)
}
}
+ if (netobj->snp_owner) {
+ ret = EFI_CALL(efi_close_event(netobj->wait_for_packet));
+ if (ret != EFI_SUCCESS)
+ return -1;
+ ret = EFI_CALL(efi_close_event(netobj->network_timer_event));
+ if (ret != EFI_SUCCESS)
+ return -1;
+ }
+
#if IS_ENABLED(CONFIG_EFI_IP4_CONFIG2_PROTOCOL)
if (netobj->ip4_config2) {
r = efi_ipconfig_unregister(netobj->handle, netobj->ip4_config2);
@@ -1591,8 +1602,11 @@ int efi_net_unregister(void *ctx, struct event *event)
ret = efi_delete_handle(netobj->handle);
if (ret != EFI_SUCCESS)
return -1;
+ }
+
+ efi_free_pool(interface);
- efi_free_pool(interface);
+ if (netobj->snp_owner) {
if (netobj->net)
free(netobj->net);
if (netobj->net_mode)
--
2.43.0
More information about the U-Boot
mailing list