Subject: linux-next: manual merge of the bpf-next tree with Linus' tree

From: Stephen Rothwell <[email-masked]>
Date: Tue, 24 Jan 2023 09:44:03 +1100

Hi all,

Today's linux-next merge of the bpf-next tree got a conflict in:

  kernel/bpf/offload.c

between commit:

  ef01f4e25c17 ("bpf: restore the ebpf program ID for BPF_AUDIT_UNLOAD and PERF_BPF_EVENT_PROG_UNLOAD")

from Linus' tree and commit:

  89bbc53a4dbb ("bpf: Reshuffle some parts of bpf/offload.c")

from the bpf-next tree.

I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging.  You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.

-- 
Cheers,
Stephen Rothwell

diff --cc kernel/bpf/offload.c
index 190d9f9dc987,e87cab2ed710..000000000000
--- a/kernel/bpf/offload.c
+++ b/kernel/bpf/offload.c
@@@ -75,20 -74,124 +74,121 @@@ bpf_offload_find_netdev(struct net_devi
  	return rhashtable_lookup_fast(&offdevs, &netdev, offdevs_params);
  }
  
- int bpf_prog_offload_init(struct bpf_prog *prog, union bpf_attr *attr)
+ static int __bpf_offload_dev_netdev_register(struct bpf_offload_dev *offdev,
+ 					     struct net_device *netdev)
  {
  	struct bpf_offload_netdev *ondev;
- 	struct bpf_prog_offload *offload;
  	int err;
  
- 	if (attr->prog_type != BPF_PROG_TYPE_SCHED_CLS &&
- 	    attr->prog_type != BPF_PROG_TYPE_XDP)
- 		return -EINVAL;
+ 	ondev = kzalloc(sizeof(*ondev), GFP_KERNEL);
+ 	if (!ondev)
+ 		return -ENOMEM;
  
- 	if (attr->prog_flags)
- 		return -EINVAL;
+ 	ondev->netdev = netdev;
+ 	ondev->offdev = offdev;
+ 	INIT_LIST_HEAD(&ondev->progs);
+ 	INIT_LIST_HEAD(&ondev->maps);
+ 
+ 	err = rhashtable_insert_fast(&offdevs, &ondev->l, offdevs_params);
+ 	if (err) {
+ 		netdev_warn(netdev, "failed to register for BPF offload\n");
+ 		goto err_free;
+ 	}
+ 
+ 	if (offdev)
+ 		list_add(&ondev->offdev_netdevs, &offdev->netdevs);
+ 	return 0;
+ 
+ err_free:
+ 	kfree(ondev);
+ 	return err;
+ }
+ 
+ static void __bpf_prog_offload_destroy(struct bpf_prog *prog)
+ {
+ 	struct bpf_prog_offload *offload = prog->aux->offload;
+ 
+ 	if (offload->dev_state)
+ 		offload->offdev->ops->destroy(prog);
+ 
 -	/* Make sure BPF_PROG_GET_NEXT_ID can't find this dead program */
 -	bpf_prog_free_id(prog, true);
 -
+ 	list_del_init(&offload->offloads);
+ 	kfree(offload);
+ 	prog->aux->offload = NULL;
+ }
+ 
+ static int bpf_map_offload_ndo(struct bpf_offloaded_map *offmap,
+ 			       enum bpf_netdev_command cmd)
+ {
+ 	struct netdev_bpf data = {};
+ 	struct net_device *netdev;
+ 
+ 	ASSERT_RTNL();
+ 
+ 	data.command = cmd;
+ 	data.offmap = offmap;
+ 	/* Caller must make sure netdev is valid */
+ 	netdev = offmap->netdev;
+ 
+ 	return netdev->netdev_ops->ndo_bpf(netdev, &data);
+ }
+ 
+ static void __bpf_map_offload_destroy(struct bpf_offloaded_map *offmap)
+ {
+ 	WARN_ON(bpf_map_offload_ndo(offmap, BPF_OFFLOAD_MAP_FREE));
+ 	/* Make sure BPF_MAP_GET_NEXT_ID can't find this dead map */
+ 	bpf_map_free_id(&offmap->map, true);
+ 	list_del_init(&offmap->offloads);
+ 	offmap->netdev = NULL;
+ }
+ 
+ static void __bpf_offload_dev_netdev_unregister(struct bpf_offload_dev *offdev,
+ 						struct net_device *netdev)
+ {
+ 	struct bpf_offload_netdev *ondev, *altdev = NULL;
+ 	struct bpf_offloaded_map *offmap, *mtmp;
+ 	struct bpf_prog_offload *offload, *ptmp;
+ 
+ 	ASSERT_RTNL();
+ 
+ 	ondev = rhashtable_lookup_fast(&offdevs, &netdev, offdevs_params);
+ 	if (WARN_ON(!ondev))
+ 		return;
+ 
+ 	WARN_ON(rhashtable_remove_fast(&offdevs, &ondev->l, offdevs_params));
+ 
+ 	/* Try to move the objects to another netdev of the device */
+ 	if (offdev) {
+ 		list_del(&ondev->offdev_netdevs);
+ 		altdev = list_first_entry_or_null(&offdev->netdevs,
+ 						  struct bpf_offload_netdev,
+ 						  offdev_netdevs);
+ 	}
+ 
+ 	if (altdev) {
+ 		list_for_each_entry(offload, &ondev->progs, offloads)
+ 			offload->netdev = altdev->netdev;
+ 		list_splice_init(&ondev->progs, &altdev->progs);
+ 
+ 		list_for_each_entry(offmap, &ondev->maps, offloads)
+ 			offmap->netdev = altdev->netdev;
+ 		list_splice_init(&ondev->maps, &altdev->maps);
+ 	} else {
+ 		list_for_each_entry_safe(offload, ptmp, &ondev->progs, offloads)
+ 			__bpf_prog_offload_destroy(offload->prog);
+ 		list_for_each_entry_safe(offmap, mtmp, &ondev->maps, offloads)
+ 			__bpf_map_offload_destroy(offmap);
+ 	}
+ 
+ 	WARN_ON(!list_empty(&ondev->progs));
+ 	WARN_ON(!list_empty(&ondev->maps));
+ 	kfree(ondev);
+ }
+ 
+ static int __bpf_prog_dev_bound_init(struct bpf_prog *prog, struct net_device *netdev)
+ {
+ 	struct bpf_offload_netdev *ondev;
+ 	struct bpf_prog_offload *offload;
+ 	int err;
  
  	offload = kzalloc(sizeof(*offload), GFP_USER);
  	if (!offload)