Merge android11-5.4.57 (3f413d0) into msm-5.4

* refs/heads/tmp-3f413d0:
  Linux 5.4.57
  bpf: sockmap: Require attach_bpf_fd when detaching a program
  selftests: bpf: Fix detach from sockmap tests
  ext4: fix direct I/O read error
  arm64: Workaround circular dependency in pointer_auth.h
  random32: move the pseudo-random 32-bit definitions to prandom.h
  random32: remove net_rand_state from the latent entropy gcc plugin
  random: fix circular include dependency on arm64 after addition of percpu.h
  ARM: percpu.h: fix build error
  random32: update the net random state on interrupt and activity
  ANDROID: Update ABI xml
  UPSTREAM: of: property: Add device link support for pinctrl-0 through pinctrl-8
  UPSTREAM: of: property: Add device link support for multiple DT bindings
  UPSTREAM: of: property: Add device link support for extcon
  UPSTREAM: driver core: Change delimiter in devlink device's name to "--"
  UPSTREAM: driver core: Fix sleeping in invalid context during device link deletion
  BACKPORT: driver core: Add waiting_for_supplier sysfs file for devices
  UPSTREAM: driver core: Add state_synced sysfs file for devices that support it
  UPSTREAM: driver core: Expose device link details in sysfs
  UPSTREAM: driver core: Avoid deferred probe due to fw_devlink_pause/resume()
  UPSTREAM: driver core: Rename dev_links_info.defer_sync to defer_hook
  UPSTREAM: driver core: Don't do deferred probe in parallel with kernel_init thread
  UPSTREAM: arm64/module: Optimize module load time by optimizing PLT counting
  FROMGIT: scsi: block: pm: Simplify resume handling

Change-Id: Ide67c767b3a0f455ab5cec4b571ab599eae813d5
Signed-off-by: Blagovest Kolenichev <bkolenichev@codeaurora.org>
This commit is contained in:
Blagovest Kolenichev 2020-08-10 02:29:46 -07:00
commit 33a0fb78c7
29 changed files with 7223 additions and 6261 deletions

View File

@ -0,0 +1,126 @@
What: /sys/class/devlink/.../
Date: May 2020
Contact: Saravana Kannan <saravanak@google.com>
Description:
Provide a place in sysfs for the device link objects in the
kernel at any given time. The name of a device link directory,
denoted as ... above, is of the form <supplier>--<consumer>
where <supplier> is the supplier device name and <consumer> is
the consumer device name.
What: /sys/class/devlink/.../auto_remove_on
Date: May 2020
Contact: Saravana Kannan <saravanak@google.com>
Description:
This file indicates if the device link will ever be
automatically removed by the driver core when the consumer and
supplier devices themselves are still present.
This will be one of the following strings:
'consumer unbind'
'supplier unbind'
'never'
'consumer unbind' means the device link will be removed when
the consumer's driver is unbound from the consumer device.
'supplier unbind' means the device link will be removed when
the supplier's driver is unbound from the supplier device.
'never' means the device link will not be automatically removed
when as long as the supplier and consumer devices themselves
are still present.
What: /sys/class/devlink/.../consumer
Date: May 2020
Contact: Saravana Kannan <saravanak@google.com>
Description:
This file is a symlink to the consumer device's sysfs directory.
What: /sys/class/devlink/.../runtime_pm
Date: May 2020
Contact: Saravana Kannan <saravanak@google.com>
Description:
This file indicates if the device link has any impact on the
runtime power management behavior of the consumer and supplier
devices. For example: Making sure the supplier doesn't enter
runtime suspend while the consumer is active.
This will be one of the following strings:
'0' - Does not affect runtime power management
'1' - Affects runtime power management
What: /sys/class/devlink/.../status
Date: May 2020
Contact: Saravana Kannan <saravanak@google.com>
Description:
This file indicates the status of the device link. The status
of a device link is affected by whether the supplier and
consumer devices have been bound to their corresponding
drivers. The status of a device link also affects the binding
and unbinding of the supplier and consumer devices with their
drivers and also affects whether the software state of the
supplier device is synced with the hardware state of the
supplier device after boot up.
See also: sysfs-devices-state_synced.
This will be one of the following strings:
'not tracked'
'dormant'
'available'
'consumer probing'
'active'
'supplier unbinding'
'unknown'
'not tracked' means this device link does not track the status
and has no impact on the binding, unbinding and syncing the
hardware and software device state.
'dormant' means the supplier and the consumer devices have not
bound to their driver.
'available' means the supplier has bound to its driver and is
available to supply resources to the consumer device.
'consumer probing' means the consumer device is currently
trying to bind to its driver.
'active' means the supplier and consumer devices have both
bound successfully to their drivers.
'supplier unbinding' means the supplier devices is currently in
the process of unbinding from its driver.
'unknown' means the state of the device link is not any of the
above. If this is ever the value, there's a bug in the kernel.
What: /sys/class/devlink/.../supplier
Date: May 2020
Contact: Saravana Kannan <saravanak@google.com>
Description:
This file is a symlink to the supplier device's sysfs directory.
What: /sys/class/devlink/.../sync_state_only
Date: May 2020
Contact: Saravana Kannan <saravanak@google.com>
Description:
This file indicates if the device link is limited to only
affecting the syncing of the hardware and software state of the
supplier device.
This will be one of the following strings:
'0'
'1' - Affects runtime power management
'0' means the device link can affect other device behaviors
like binding/unbinding, suspend/resume, runtime power
management, etc.
'1' means the device link will only affect the syncing of
hardware and software state of the supplier device after boot
up and doesn't not affect other behaviors of the devices.

View File

@ -0,0 +1,8 @@
What: /sys/devices/.../consumer:<consumer>
Date: May 2020
Contact: Saravana Kannan <saravanak@google.com>
Description:
The /sys/devices/.../consumer:<consumer> are symlinks to device
links where this device is the supplier. <consumer> denotes the
name of the consumer in that device link. There can be zero or
more of these symlinks for a given device.

View File

@ -0,0 +1,24 @@
What: /sys/devices/.../state_synced
Date: May 2020
Contact: Saravana Kannan <saravanak@google.com>
Description:
The /sys/devices/.../state_synced attribute is only present for
devices whose bus types or driver provides the .sync_state()
callback. The number read from it (0 or 1) reflects the value
of the device's 'state_synced' field. A value of 0 means the
.sync_state() callback hasn't been called yet. A value of 1
means the .sync_state() callback has been called.
Generally, if a device has sync_state() support and has some of
the resources it provides enabled at the time the kernel starts
(Eg: enabled by hardware reset or bootloader or anything that
run before the kernel starts), then it'll keep those resources
enabled and in a state that's compatible with the state they
were in at the start of the kernel. The device will stop doing
this only when the sync_state() callback has been called --
which happens only when all its consumer devices are registered
and have probed successfully. Resources that were left disabled
at the time the kernel starts are not affected or limited in
any way by sync_state() callbacks.

View File

@ -0,0 +1,8 @@
What: /sys/devices/.../supplier:<supplier>
Date: May 2020
Contact: Saravana Kannan <saravanak@google.com>
Description:
The /sys/devices/.../supplier:<supplier> are symlinks to device
links where this device is the consumer. <supplier> denotes the
name of the supplier in that device link. There can be zero or
more of these symlinks for a given device.

View File

@ -0,0 +1,17 @@
What: /sys/devices/.../waiting_for_supplier
Date: May 2020
Contact: Saravana Kannan <saravanak@google.com>
Description:
The /sys/devices/.../waiting_for_supplier attribute is only
present when fw_devlink kernel command line option is enabled
and is set to something stricter than "permissive". It is
removed once a device probes successfully (because the
information is no longer relevant). The number read from it (0
or 1) reflects whether the device is waiting for one or more
suppliers to be added and then linked to using device links
before the device can probe.
A value of 0 means the device is not waiting for any suppliers
to be added before it can probe. A value of 1 means the device
is waiting for one or more suppliers to be added before it can
probe.

View File

@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
VERSION = 5
PATCHLEVEL = 4
SUBLEVEL = 56
SUBLEVEL = 57
EXTRAVERSION =
NAME = Kleptomaniac Octopus

File diff suppressed because it is too large Load Diff

View File

@ -5,6 +5,8 @@
#ifndef _ASM_ARM_PERCPU_H_
#define _ASM_ARM_PERCPU_H_
#include <asm/thread_info.h>
/*
* Same as asm-generic/percpu.h, except that we store the per cpu offset
* in the TPIDRPRW. TPIDRPRW only exists on V6K and V7

View File

@ -3,7 +3,6 @@
#define __ASM_POINTER_AUTH_H
#include <linux/bitops.h>
#include <linux/random.h>
#include <asm/cpufeature.h>
#include <asm/memory.h>
@ -30,6 +29,13 @@ struct ptrauth_keys {
struct ptrauth_key apga;
};
/*
* Only include random.h once ptrauth_keys_* structures are defined
* to avoid yet another circular include hell (random.h * ends up
* including asm/smp.h, which requires ptrauth_keys_kernel).
*/
#include <linux/random.h>
static inline void ptrauth_keys_init(struct ptrauth_keys *keys)
{
if (system_supports_address_auth()) {

View File

@ -252,6 +252,40 @@ static unsigned int count_plts(Elf64_Sym *syms, Elf64_Rela *rela, int num,
return ret;
}
static bool branch_rela_needs_plt(Elf64_Sym *syms, Elf64_Rela *rela,
Elf64_Word dstidx)
{
Elf64_Sym *s = syms + ELF64_R_SYM(rela->r_info);
if (s->st_shndx == dstidx)
return false;
return ELF64_R_TYPE(rela->r_info) == R_AARCH64_JUMP26 ||
ELF64_R_TYPE(rela->r_info) == R_AARCH64_CALL26;
}
/* Group branch PLT relas at the front end of the array. */
static int partition_branch_plt_relas(Elf64_Sym *syms, Elf64_Rela *rela,
int numrels, Elf64_Word dstidx)
{
int i = 0, j = numrels - 1;
if (!IS_ENABLED(CONFIG_RANDOMIZE_BASE))
return 0;
while (i < j) {
if (branch_rela_needs_plt(syms, &rela[i], dstidx))
i++;
else if (branch_rela_needs_plt(syms, &rela[j], dstidx))
swap(rela[i], rela[j]);
else
j--;
}
return i;
}
int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs,
char *secstrings, struct module *mod)
{
@ -289,7 +323,7 @@ int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs,
for (i = 0; i < ehdr->e_shnum; i++) {
Elf64_Rela *rels = (void *)ehdr + sechdrs[i].sh_offset;
int numrels = sechdrs[i].sh_size / sizeof(Elf64_Rela);
int nents, numrels = sechdrs[i].sh_size / sizeof(Elf64_Rela);
Elf64_Shdr *dstsec = sechdrs + sechdrs[i].sh_info;
if (sechdrs[i].sh_type != SHT_RELA)
@ -299,8 +333,14 @@ int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs,
if (!(dstsec->sh_flags & SHF_EXECINSTR))
continue;
/* sort by type, symbol index and addend */
sort(rels, numrels, sizeof(Elf64_Rela), cmp_rela, NULL);
/*
* sort branch relocations requiring a PLT by type, symbol index
* and addend
*/
nents = partition_branch_plt_relas(syms, rels, numrels,
sechdrs[i].sh_info);
if (nents)
sort(rels, nents, sizeof(Elf64_Rela), cmp_rela, NULL);
if (!str_has_prefix(secstrings + dstsec->sh_name, ".init"))
core_plts += count_plts(syms, rels, numrels,

View File

@ -164,9 +164,8 @@ EXPORT_SYMBOL(blk_pre_runtime_resume);
*
* Description:
* Update the queue's runtime status according to the return value of the
* device's runtime_resume function. If it is successfully resumed, process
* the requests that are queued into the device's queue when it is resuming
* and then mark last busy and initiate autosuspend for it.
* device's runtime_resume function. If the resume was successful, call
* blk_set_runtime_active() to do the real work of restarting the queue.
*
* This function should be called near the end of the device's
* runtime_resume callback.
@ -175,19 +174,13 @@ void blk_post_runtime_resume(struct request_queue *q, int err)
{
if (!q->dev)
return;
spin_lock_irq(&q->queue_lock);
if (!err) {
q->rpm_status = RPM_ACTIVE;
pm_runtime_mark_last_busy(q->dev);
pm_request_autosuspend(q->dev);
blk_set_runtime_active(q);
} else {
spin_lock_irq(&q->queue_lock);
q->rpm_status = RPM_SUSPENDED;
spin_unlock_irq(&q->queue_lock);
}
spin_unlock_irq(&q->queue_lock);
if (!err)
blk_clear_pm_only(q);
}
EXPORT_SYMBOL(blk_post_runtime_resume);
@ -204,15 +197,25 @@ EXPORT_SYMBOL(blk_post_runtime_resume);
* This function can be used in driver's resume hook to correct queue
* runtime PM status and re-enable peeking requests from the queue. It
* should be called before first request is added to the queue.
*
* This function is also called by blk_post_runtime_resume() for successful
* runtime resumes. It does everything necessary to restart the queue.
*/
void blk_set_runtime_active(struct request_queue *q)
{
if (q->dev) {
spin_lock_irq(&q->queue_lock);
q->rpm_status = RPM_ACTIVE;
pm_runtime_mark_last_busy(q->dev);
pm_request_autosuspend(q->dev);
spin_unlock_irq(&q->queue_lock);
}
int old_status;
if (!q->dev)
return;
spin_lock_irq(&q->queue_lock);
old_status = q->rpm_status;
q->rpm_status = RPM_ACTIVE;
pm_runtime_mark_last_busy(q->dev);
pm_request_autosuspend(q->dev);
spin_unlock_irq(&q->queue_lock);
if (old_status != RPM_ACTIVE)
blk_clear_pm_only(q);
}
EXPORT_SYMBOL(blk_set_runtime_active);

View File

@ -142,7 +142,6 @@ extern char *make_class_name(const char *name, struct kobject *kobj);
extern int devres_release_all(struct device *dev);
extern void device_block_probing(void);
extern void device_unblock_probing(void);
extern void driver_deferred_probe_force_trigger(void);
/* /sys/devices directory */
extern struct kset *devices_kset;

View File

@ -50,6 +50,7 @@ static DEFINE_MUTEX(wfs_lock);
static LIST_HEAD(deferred_sync);
static unsigned int defer_sync_state_count = 1;
static unsigned int defer_fw_devlink_count;
static LIST_HEAD(deferred_fw_devlink);
static DEFINE_MUTEX(defer_fw_devlink_lock);
#ifdef CONFIG_SRCU
@ -234,6 +235,210 @@ void device_pm_move_to_tail(struct device *dev)
device_links_read_unlock(idx);
}
#define to_devlink(dev) container_of((dev), struct device_link, link_dev)
static ssize_t status_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
char *status;
switch (to_devlink(dev)->status) {
case DL_STATE_NONE:
status = "not tracked"; break;
case DL_STATE_DORMANT:
status = "dormant"; break;
case DL_STATE_AVAILABLE:
status = "available"; break;
case DL_STATE_CONSUMER_PROBE:
status = "consumer probing"; break;
case DL_STATE_ACTIVE:
status = "active"; break;
case DL_STATE_SUPPLIER_UNBIND:
status = "supplier unbinding"; break;
default:
status = "unknown"; break;
}
return sprintf(buf, "%s\n", status);
}
static DEVICE_ATTR_RO(status);
static ssize_t auto_remove_on_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct device_link *link = to_devlink(dev);
char *str;
if (link->flags & DL_FLAG_AUTOREMOVE_SUPPLIER)
str = "supplier unbind";
else if (link->flags & DL_FLAG_AUTOREMOVE_CONSUMER)
str = "consumer unbind";
else
str = "never";
return sprintf(buf, "%s\n", str);
}
static DEVICE_ATTR_RO(auto_remove_on);
static ssize_t runtime_pm_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct device_link *link = to_devlink(dev);
return sprintf(buf, "%d\n", !!(link->flags & DL_FLAG_PM_RUNTIME));
}
static DEVICE_ATTR_RO(runtime_pm);
static ssize_t sync_state_only_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct device_link *link = to_devlink(dev);
return sprintf(buf, "%d\n", !!(link->flags & DL_FLAG_SYNC_STATE_ONLY));
}
static DEVICE_ATTR_RO(sync_state_only);
static struct attribute *devlink_attrs[] = {
&dev_attr_status.attr,
&dev_attr_auto_remove_on.attr,
&dev_attr_runtime_pm.attr,
&dev_attr_sync_state_only.attr,
NULL,
};
ATTRIBUTE_GROUPS(devlink);
static void device_link_free(struct device_link *link)
{
while (refcount_dec_not_one(&link->rpm_active))
pm_runtime_put(link->supplier);
put_device(link->consumer);
put_device(link->supplier);
kfree(link);
}
#ifdef CONFIG_SRCU
static void __device_link_free_srcu(struct rcu_head *rhead)
{
device_link_free(container_of(rhead, struct device_link, rcu_head));
}
static void devlink_dev_release(struct device *dev)
{
struct device_link *link = to_devlink(dev);
call_srcu(&device_links_srcu, &link->rcu_head, __device_link_free_srcu);
}
#else
static void devlink_dev_release(struct device *dev)
{
device_link_free(to_devlink(dev));
}
#endif
static struct class devlink_class = {
.name = "devlink",
.owner = THIS_MODULE,
.dev_groups = devlink_groups,
.dev_release = devlink_dev_release,
};
static int devlink_add_symlinks(struct device *dev,
struct class_interface *class_intf)
{
int ret;
size_t len;
struct device_link *link = to_devlink(dev);
struct device *sup = link->supplier;
struct device *con = link->consumer;
char *buf;
len = max(strlen(dev_name(sup)), strlen(dev_name(con)));
len += strlen("supplier:") + 1;
buf = kzalloc(len, GFP_KERNEL);
if (!buf)
return -ENOMEM;
ret = sysfs_create_link(&link->link_dev.kobj, &sup->kobj, "supplier");
if (ret)
goto out;
ret = sysfs_create_link(&link->link_dev.kobj, &con->kobj, "consumer");
if (ret)
goto err_con;
snprintf(buf, len, "consumer:%s", dev_name(con));
ret = sysfs_create_link(&sup->kobj, &link->link_dev.kobj, buf);
if (ret)
goto err_con_dev;
snprintf(buf, len, "supplier:%s", dev_name(sup));
ret = sysfs_create_link(&con->kobj, &link->link_dev.kobj, buf);
if (ret)
goto err_sup_dev;
goto out;
err_sup_dev:
snprintf(buf, len, "consumer:%s", dev_name(con));
sysfs_remove_link(&sup->kobj, buf);
err_con_dev:
sysfs_remove_link(&link->link_dev.kobj, "consumer");
err_con:
sysfs_remove_link(&link->link_dev.kobj, "supplier");
out:
kfree(buf);
return ret;
}
static void devlink_remove_symlinks(struct device *dev,
struct class_interface *class_intf)
{
struct device_link *link = to_devlink(dev);
size_t len;
struct device *sup = link->supplier;
struct device *con = link->consumer;
char *buf;
sysfs_remove_link(&link->link_dev.kobj, "consumer");
sysfs_remove_link(&link->link_dev.kobj, "supplier");
len = max(strlen(dev_name(sup)), strlen(dev_name(con)));
len += strlen("supplier:") + 1;
buf = kzalloc(len, GFP_KERNEL);
if (!buf) {
WARN(1, "Unable to properly free device link symlinks!\n");
return;
}
snprintf(buf, len, "supplier:%s", dev_name(sup));
sysfs_remove_link(&con->kobj, buf);
snprintf(buf, len, "consumer:%s", dev_name(con));
sysfs_remove_link(&sup->kobj, buf);
kfree(buf);
}
static struct class_interface devlink_class_intf = {
.class = &devlink_class,
.add_dev = devlink_add_symlinks,
.remove_dev = devlink_remove_symlinks,
};
static int __init devlink_class_init(void)
{
int ret;
ret = class_register(&devlink_class);
if (ret)
return ret;
ret = class_interface_register(&devlink_class_intf);
if (ret)
class_unregister(&devlink_class);
return ret;
}
postcore_initcall(devlink_class_init);
#define DL_MANAGED_LINK_FLAGS (DL_FLAG_AUTOREMOVE_CONSUMER | \
DL_FLAG_AUTOREMOVE_SUPPLIER | \
DL_FLAG_AUTOPROBE_CONSUMER | \
@ -406,13 +611,6 @@ struct device_link *device_link_add(struct device *consumer,
refcount_set(&link->rpm_active, 1);
if (flags & DL_FLAG_PM_RUNTIME) {
if (flags & DL_FLAG_RPM_ACTIVE)
refcount_inc(&link->rpm_active);
pm_runtime_new_link(consumer);
}
get_device(supplier);
link->supplier = supplier;
INIT_LIST_HEAD(&link->s_node);
@ -422,6 +620,25 @@ struct device_link *device_link_add(struct device *consumer,
link->flags = flags;
kref_init(&link->kref);
link->link_dev.class = &devlink_class;
device_set_pm_not_required(&link->link_dev);
dev_set_name(&link->link_dev, "%s--%s",
dev_name(supplier), dev_name(consumer));
if (device_register(&link->link_dev)) {
put_device(consumer);
put_device(supplier);
kfree(link);
link = NULL;
goto out;
}
if (flags & DL_FLAG_PM_RUNTIME) {
if (flags & DL_FLAG_RPM_ACTIVE)
refcount_inc(&link->rpm_active);
pm_runtime_new_link(consumer);
}
/* Determine the initial link state. */
if (flags & DL_FLAG_STATELESS)
link->status = DL_STATE_NONE;
@ -537,22 +754,7 @@ static void device_link_add_missing_supplier_links(void)
mutex_unlock(&wfs_lock);
}
static void device_link_free(struct device_link *link)
{
while (refcount_dec_not_one(&link->rpm_active))
pm_runtime_put(link->supplier);
put_device(link->consumer);
put_device(link->supplier);
kfree(link);
}
#ifdef CONFIG_SRCU
static void __device_link_free_srcu(struct rcu_head *rhead)
{
device_link_free(container_of(rhead, struct device_link, rcu_head));
}
static void __device_link_del(struct kref *kref)
{
struct device_link *link = container_of(kref, struct device_link, kref);
@ -565,7 +767,7 @@ static void __device_link_del(struct kref *kref)
list_del_rcu(&link->s_node);
list_del_rcu(&link->c_node);
call_srcu(&device_links_srcu, &link->rcu_head, __device_link_free_srcu);
device_unregister(&link->link_dev);
}
#else /* !CONFIG_SRCU */
static void __device_link_del(struct kref *kref)
@ -580,7 +782,7 @@ static void __device_link_del(struct kref *kref)
list_del(&link->s_node);
list_del(&link->c_node);
device_link_free(link);
device_unregister(&link->link_dev);
}
#endif /* !CONFIG_SRCU */
@ -753,11 +955,11 @@ static void __device_links_queue_sync_state(struct device *dev,
*/
dev->state_synced = true;
if (WARN_ON(!list_empty(&dev->links.defer_sync)))
if (WARN_ON(!list_empty(&dev->links.defer_hook)))
return;
get_device(dev);
list_add_tail(&dev->links.defer_sync, list);
list_add_tail(&dev->links.defer_hook, list);
}
/**
@ -775,8 +977,8 @@ static void device_links_flush_sync_list(struct list_head *list,
{
struct device *dev, *tmp;
list_for_each_entry_safe(dev, tmp, list, links.defer_sync) {
list_del_init(&dev->links.defer_sync);
list_for_each_entry_safe(dev, tmp, list, links.defer_hook) {
list_del_init(&dev->links.defer_hook);
if (dev != dont_lock_dev)
device_lock(dev);
@ -814,12 +1016,12 @@ void device_links_supplier_sync_state_resume(void)
if (defer_sync_state_count)
goto out;
list_for_each_entry_safe(dev, tmp, &deferred_sync, links.defer_sync) {
list_for_each_entry_safe(dev, tmp, &deferred_sync, links.defer_hook) {
/*
* Delete from deferred_sync list before queuing it to
* sync_list because defer_sync is used for both lists.
* sync_list because defer_hook is used for both lists.
*/
list_del_init(&dev->links.defer_sync);
list_del_init(&dev->links.defer_hook);
__device_links_queue_sync_state(dev, &sync_list);
}
out:
@ -837,8 +1039,8 @@ late_initcall(sync_state_resume_initcall);
static void __device_links_supplier_defer_sync(struct device *sup)
{
if (list_empty(&sup->links.defer_sync) && dev_has_sync_state(sup))
list_add_tail(&sup->links.defer_sync, &deferred_sync);
if (list_empty(&sup->links.defer_hook) && dev_has_sync_state(sup))
list_add_tail(&sup->links.defer_hook, &deferred_sync);
}
static void device_link_drop_managed(struct device_link *link)
@ -848,6 +1050,22 @@ static void device_link_drop_managed(struct device_link *link)
kref_put(&link->kref, __device_link_del);
}
static ssize_t waiting_for_supplier_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
bool val;
device_lock(dev);
mutex_lock(&wfs_lock);
val = !list_empty(&dev->links.needs_suppliers)
&& dev->links.need_for_probe;
mutex_unlock(&wfs_lock);
device_unlock(dev);
return sprintf(buf, "%u\n", val);
}
static DEVICE_ATTR_RO(waiting_for_supplier);
/**
* device_links_driver_bound - Update device links after probing its driver.
* @dev: Device to update the links for.
@ -872,6 +1090,7 @@ void device_links_driver_bound(struct device *dev)
mutex_lock(&wfs_lock);
list_del_init(&dev->links.needs_suppliers);
mutex_unlock(&wfs_lock);
device_remove_file(dev, &dev_attr_waiting_for_supplier);
device_links_write_lock();
@ -1051,7 +1270,7 @@ void device_links_driver_cleanup(struct device *dev)
WRITE_ONCE(link->status, DL_STATE_DORMANT);
}
list_del_init(&dev->links.defer_sync);
list_del_init(&dev->links.defer_hook);
__device_links_no_driver(dev);
device_links_write_unlock();
@ -1158,6 +1377,9 @@ static void device_links_purge(struct device *dev)
{
struct device_link *link, *ln;
if (dev->class == &devlink_class)
return;
mutex_lock(&wfs_lock);
list_del(&dev->links.needs_suppliers);
mutex_unlock(&wfs_lock);
@ -1208,6 +1430,12 @@ static void fw_devlink_link_device(struct device *dev)
fw_ret = fwnode_call_int_op(dev->fwnode, add_links, dev);
} else {
fw_ret = -ENODEV;
/*
* defer_hook is not used to add device to deferred_sync list
* until device is bound. Since deferred fw devlink also blocks
* probing, same list hook can be used for deferred_fw_devlink.
*/
list_add_tail(&dev->links.defer_hook, &deferred_fw_devlink);
}
if (fw_ret == -ENODEV)
@ -1276,6 +1504,9 @@ void fw_devlink_pause(void)
*/
void fw_devlink_resume(void)
{
struct device *dev, *tmp;
LIST_HEAD(probe_list);
mutex_lock(&defer_fw_devlink_lock);
if (!defer_fw_devlink_count) {
WARN(true, "Unmatched fw_devlink pause/resume!");
@ -1287,9 +1518,19 @@ void fw_devlink_resume(void)
goto out;
device_link_add_missing_supplier_links();
driver_deferred_probe_force_trigger();
list_splice_tail_init(&deferred_fw_devlink, &probe_list);
out:
mutex_unlock(&defer_fw_devlink_lock);
/*
* bus_probe_device() can cause new devices to get added and they'll
* try to grab defer_fw_devlink_lock. So, this needs to be done outside
* the defer_fw_devlink_lock.
*/
list_for_each_entry_safe(dev, tmp, &probe_list, links.defer_hook) {
list_del_init(&dev->links.defer_hook);
bus_probe_device(dev);
}
}
/* Device links support end. */
@ -1925,8 +2166,14 @@ static int device_add_attrs(struct device *dev)
goto err_remove_dev_groups;
}
error = device_create_file(dev, &dev_attr_waiting_for_supplier);
if (error)
goto err_remove_dev_online;
return 0;
err_remove_dev_online:
device_remove_file(dev, &dev_attr_online);
err_remove_dev_groups:
device_remove_groups(dev, dev->groups);
err_remove_type_groups:
@ -1944,6 +2191,7 @@ static void device_remove_attrs(struct device *dev)
struct class *class = dev->class;
const struct device_type *type = dev->type;
device_remove_file(dev, &dev_attr_waiting_for_supplier);
device_remove_file(dev, &dev_attr_online);
device_remove_groups(dev, dev->groups);
@ -2148,7 +2396,7 @@ void device_initialize(struct device *dev)
INIT_LIST_HEAD(&dev->links.consumers);
INIT_LIST_HEAD(&dev->links.suppliers);
INIT_LIST_HEAD(&dev->links.needs_suppliers);
INIT_LIST_HEAD(&dev->links.defer_sync);
INIT_LIST_HEAD(&dev->links.defer_hook);
dev->links.status = DL_DEV_NO_DRIVER;
}
EXPORT_SYMBOL_GPL(device_initialize);

View File

@ -164,11 +164,6 @@ static void driver_deferred_probe_trigger(void)
if (!driver_deferred_probe_enable)
return;
driver_deferred_probe_force_trigger();
}
void driver_deferred_probe_force_trigger(void)
{
/*
* A successful probe means that all the devices in the pending list
* should be triggered to be reprobed. Move all the deferred devices
@ -494,6 +489,18 @@ static void driver_deferred_probe_add_trigger(struct device *dev,
driver_deferred_probe_trigger();
}
static ssize_t state_synced_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
bool val;
device_lock(dev);
val = dev->state_synced;
device_unlock(dev);
return sprintf(buf, "%u\n", val);
}
static DEVICE_ATTR_RO(state_synced);
static int really_probe(struct device *dev, struct device_driver *drv)
{
int ret = -EPROBE_DEFER;
@ -567,9 +574,16 @@ static int really_probe(struct device *dev, struct device_driver *drv)
goto dev_groups_failed;
}
if (dev_has_sync_state(dev) &&
device_create_file(dev, &dev_attr_state_synced)) {
dev_err(dev, "state_synced sysfs add failed\n");
goto dev_sysfs_state_synced_failed;
}
if (test_remove) {
test_remove = false;
device_remove_file(dev, &dev_attr_state_synced);
device_remove_groups(dev, drv->dev_groups);
if (dev->bus->remove)
@ -599,6 +613,8 @@ static int really_probe(struct device *dev, struct device_driver *drv)
drv->bus->name, __func__, dev_name(dev), drv->name);
goto done;
dev_sysfs_state_synced_failed:
device_remove_groups(dev, drv->dev_groups);
dev_groups_failed:
if (dev->bus->remove)
dev->bus->remove(dev);
@ -1134,6 +1150,7 @@ static void __device_release_driver(struct device *dev, struct device *parent)
pm_runtime_put_sync(dev);
device_remove_file(dev, &dev_attr_state_synced);
device_remove_groups(dev, drv->dev_groups);
if (dev->bus && dev->bus->remove)

View File

@ -1249,6 +1249,7 @@ void add_interrupt_randomness(int irq, int irq_flags)
fast_mix(fast_pool);
add_interrupt_bench(cycles);
this_cpu_add(net_rand_state.s1, fast_pool->pool[cycles & 3]);
if (unlikely(crng_init == 0)) {
if ((fast_pool->count >= 64) &&

View File

@ -1192,6 +1192,21 @@ DEFINE_SIMPLE_PROP(interrupt_parent, "interrupt-parent", NULL)
DEFINE_SIMPLE_PROP(dmas, "dmas", "#dma-cells")
DEFINE_SIMPLE_PROP(power_domains, "power-domains", "#power-domain-cells")
DEFINE_SIMPLE_PROP(hwlocks, "hwlocks", "#hwlock-cells")
DEFINE_SIMPLE_PROP(extcon, "extcon", NULL)
DEFINE_SIMPLE_PROP(interrupts_extended, "interrupts-extended",
"#interrupt-cells")
DEFINE_SIMPLE_PROP(nvmem_cells, "nvmem-cells", NULL)
DEFINE_SIMPLE_PROP(phys, "phys", "#phy-cells")
DEFINE_SIMPLE_PROP(wakeup_parent, "wakeup-parent", NULL)
DEFINE_SIMPLE_PROP(pinctrl0, "pinctrl-0", NULL)
DEFINE_SIMPLE_PROP(pinctrl1, "pinctrl-1", NULL)
DEFINE_SIMPLE_PROP(pinctrl2, "pinctrl-2", NULL)
DEFINE_SIMPLE_PROP(pinctrl3, "pinctrl-3", NULL)
DEFINE_SIMPLE_PROP(pinctrl4, "pinctrl-4", NULL)
DEFINE_SIMPLE_PROP(pinctrl5, "pinctrl-5", NULL)
DEFINE_SIMPLE_PROP(pinctrl6, "pinctrl-6", NULL)
DEFINE_SIMPLE_PROP(pinctrl7, "pinctrl-7", NULL)
DEFINE_SIMPLE_PROP(pinctrl8, "pinctrl-8", NULL)
DEFINE_SUFFIX_PROP(regulators, "-supply", NULL)
DEFINE_SUFFIX_PROP(gpio, "-gpio", "#gpio-cells")
DEFINE_SUFFIX_PROP(gpios, "-gpios", "#gpio-cells")
@ -1216,6 +1231,20 @@ static const struct supplier_bindings of_supplier_bindings[] = {
{ .parse_prop = parse_dmas, },
{ .parse_prop = parse_power_domains, },
{ .parse_prop = parse_hwlocks, },
{ .parse_prop = parse_extcon, },
{ .parse_prop = parse_interrupts_extended, },
{ .parse_prop = parse_nvmem_cells, },
{ .parse_prop = parse_phys, },
{ .parse_prop = parse_wakeup_parent, },
{ .parse_prop = parse_pinctrl0, },
{ .parse_prop = parse_pinctrl1, },
{ .parse_prop = parse_pinctrl2, },
{ .parse_prop = parse_pinctrl3, },
{ .parse_prop = parse_pinctrl4, },
{ .parse_prop = parse_pinctrl5, },
{ .parse_prop = parse_pinctrl6, },
{ .parse_prop = parse_pinctrl7, },
{ .parse_prop = parse_pinctrl8, },
{ .parse_prop = parse_regulators, },
{ .parse_prop = parse_gpio, },
{ .parse_prop = parse_gpios, },

View File

@ -80,10 +80,6 @@ static int scsi_dev_type_resume(struct device *dev,
dev_dbg(dev, "scsi resume: %d\n", err);
if (err == 0) {
bool was_runtime_suspended;
was_runtime_suspended = pm_runtime_suspended(dev);
pm_runtime_disable(dev);
err = pm_runtime_set_active(dev);
pm_runtime_enable(dev);
@ -97,10 +93,8 @@ static int scsi_dev_type_resume(struct device *dev,
*/
if (!err && scsi_is_sdev_device(dev)) {
struct scsi_device *sdev = to_scsi_device(dev);
if (was_runtime_suspended)
blk_post_runtime_resume(sdev->request_queue, 0);
else
blk_set_runtime_active(sdev->request_queue);
blk_set_runtime_active(sdev->request_queue);
}
}

View File

@ -3860,6 +3860,11 @@ static ssize_t ext4_direct_IO_read(struct kiocb *iocb, struct iov_iter *iter)
struct inode *inode = mapping->host;
size_t count = iov_iter_count(iter);
ssize_t ret;
loff_t offset = iocb->ki_pos;
loff_t size = i_size_read(inode);
if (offset >= size)
return 0;
/*
* Shared inode_lock is enough for us - it protects against concurrent

View File

@ -956,11 +956,14 @@ static inline void bpf_map_offload_map_free(struct bpf_map *map)
#endif /* CONFIG_NET && CONFIG_BPF_SYSCALL */
#if defined(CONFIG_BPF_STREAM_PARSER)
int sock_map_prog_update(struct bpf_map *map, struct bpf_prog *prog, u32 which);
int sock_map_prog_update(struct bpf_map *map, struct bpf_prog *prog,
struct bpf_prog *old, u32 which);
int sock_map_get_from_fd(const union bpf_attr *attr, struct bpf_prog *prog);
int sock_map_prog_detach(const union bpf_attr *attr, enum bpf_prog_type ptype);
#else
static inline int sock_map_prog_update(struct bpf_map *map,
struct bpf_prog *prog, u32 which)
struct bpf_prog *prog,
struct bpf_prog *old, u32 which)
{
return -EOPNOTSUPP;
}
@ -970,6 +973,12 @@ static inline int sock_map_get_from_fd(const union bpf_attr *attr,
{
return -EINVAL;
}
static inline int sock_map_prog_detach(const union bpf_attr *attr,
enum bpf_prog_type ptype)
{
return -EOPNOTSUPP;
}
#endif
#if defined(CONFIG_XDP_SOCKETS)

View File

@ -1123,34 +1123,6 @@ enum device_link_state {
#define DL_FLAG_MANAGED BIT(6)
#define DL_FLAG_SYNC_STATE_ONLY BIT(7)
/**
* struct device_link - Device link representation.
* @supplier: The device on the supplier end of the link.
* @s_node: Hook to the supplier device's list of links to consumers.
* @consumer: The device on the consumer end of the link.
* @c_node: Hook to the consumer device's list of links to suppliers.
* @status: The state of the link (with respect to the presence of drivers).
* @flags: Link flags.
* @rpm_active: Whether or not the consumer device is runtime-PM-active.
* @kref: Count repeated addition of the same link.
* @rcu_head: An RCU head to use for deferred execution of SRCU callbacks.
* @supplier_preactivated: Supplier has been made active before consumer probe.
*/
struct device_link {
struct device *supplier;
struct list_head s_node;
struct device *consumer;
struct list_head c_node;
enum device_link_state status;
u32 flags;
refcount_t rpm_active;
struct kref kref;
#ifdef CONFIG_SRCU
struct rcu_head rcu_head;
#endif
bool supplier_preactivated; /* Owned by consumer probe. */
};
/**
* enum dl_dev_state - Device driver presence tracking information.
* @DL_DEV_NO_DRIVER: There is no driver attached to the device.
@ -1170,7 +1142,8 @@ enum dl_dev_state {
* @suppliers: List of links to supplier devices.
* @consumers: List of links to consumer devices.
* @needs_suppliers: Hook to global list of devices waiting for suppliers.
* @defer_sync: Hook to global list of devices that have deferred sync_state.
* @defer_hook: Hook to global list of devices that have deferred sync_state or
* deferred fw_devlink.
* @need_for_probe: If needs_suppliers is on a list, this indicates if the
* suppliers are needed for probe or not.
* @status: Driver status information.
@ -1179,7 +1152,7 @@ struct dev_links_info {
struct list_head suppliers;
struct list_head consumers;
struct list_head needs_suppliers;
struct list_head defer_sync;
struct list_head defer_hook;
bool need_for_probe;
enum dl_dev_state status;
};
@ -1377,6 +1350,36 @@ struct device {
ANDROID_KABI_RESERVE(8);
};
/**
* struct device_link - Device link representation.
* @supplier: The device on the supplier end of the link.
* @s_node: Hook to the supplier device's list of links to consumers.
* @consumer: The device on the consumer end of the link.
* @c_node: Hook to the consumer device's list of links to suppliers.
* @link_dev: device used to expose link details in sysfs
* @status: The state of the link (with respect to the presence of drivers).
* @flags: Link flags.
* @rpm_active: Whether or not the consumer device is runtime-PM-active.
* @kref: Count repeated addition of the same link.
* @rcu_head: An RCU head to use for deferred execution of SRCU callbacks.
* @supplier_preactivated: Supplier has been made active before consumer probe.
*/
struct device_link {
struct device *supplier;
struct list_head s_node;
struct device *consumer;
struct list_head c_node;
struct device link_dev;
enum device_link_state status;
u32 flags;
refcount_t rpm_active;
struct kref kref;
#ifdef CONFIG_SRCU
struct rcu_head rcu_head;
#endif
bool supplier_preactivated; /* Owned by consumer probe. */
};
static inline struct device *kobj_to_dev(struct kobject *kobj)
{
return container_of(kobj, struct device, kobj);

78
include/linux/prandom.h Normal file
View File

@ -0,0 +1,78 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* include/linux/prandom.h
*
* Include file for the fast pseudo-random 32-bit
* generation.
*/
#ifndef _LINUX_PRANDOM_H
#define _LINUX_PRANDOM_H
#include <linux/types.h>
#include <linux/percpu.h>
u32 prandom_u32(void);
void prandom_bytes(void *buf, size_t nbytes);
void prandom_seed(u32 seed);
void prandom_reseed_late(void);
struct rnd_state {
__u32 s1, s2, s3, s4;
};
DECLARE_PER_CPU(struct rnd_state, net_rand_state);
u32 prandom_u32_state(struct rnd_state *state);
void prandom_bytes_state(struct rnd_state *state, void *buf, size_t nbytes);
void prandom_seed_full_state(struct rnd_state __percpu *pcpu_state);
#define prandom_init_once(pcpu_state) \
DO_ONCE(prandom_seed_full_state, (pcpu_state))
/**
* prandom_u32_max - returns a pseudo-random number in interval [0, ep_ro)
* @ep_ro: right open interval endpoint
*
* Returns a pseudo-random number that is in interval [0, ep_ro). Note
* that the result depends on PRNG being well distributed in [0, ~0U]
* u32 space. Here we use maximally equidistributed combined Tausworthe
* generator, that is, prandom_u32(). This is useful when requesting a
* random index of an array containing ep_ro elements, for example.
*
* Returns: pseudo-random number in interval [0, ep_ro)
*/
static inline u32 prandom_u32_max(u32 ep_ro)
{
return (u32)(((u64) prandom_u32() * ep_ro) >> 32);
}
/*
* Handle minimum values for seeds
*/
static inline u32 __seed(u32 x, u32 m)
{
return (x < m) ? x + m : x;
}
/**
* prandom_seed_state - set seed for prandom_u32_state().
* @state: pointer to state structure to receive the seed.
* @seed: arbitrary 64-bit value to use as a seed.
*/
static inline void prandom_seed_state(struct rnd_state *state, u64 seed)
{
u32 i = (seed >> 32) ^ (seed << 10) ^ seed;
state->s1 = __seed(i, 2U);
state->s2 = __seed(i, 8U);
state->s3 = __seed(i, 16U);
state->s4 = __seed(i, 128U);
}
/* Pseudo random number generator from numerical recipes. */
static inline u32 next_pseudo_random32(u32 seed)
{
return seed * 1664525 + 1013904223;
}
#endif

View File

@ -108,61 +108,12 @@ declare_get_random_var_wait(long)
unsigned long randomize_page(unsigned long start, unsigned long range);
u32 prandom_u32(void);
void prandom_bytes(void *buf, size_t nbytes);
void prandom_seed(u32 seed);
void prandom_reseed_late(void);
struct rnd_state {
__u32 s1, s2, s3, s4;
};
u32 prandom_u32_state(struct rnd_state *state);
void prandom_bytes_state(struct rnd_state *state, void *buf, size_t nbytes);
void prandom_seed_full_state(struct rnd_state __percpu *pcpu_state);
#define prandom_init_once(pcpu_state) \
DO_ONCE(prandom_seed_full_state, (pcpu_state))
/**
* prandom_u32_max - returns a pseudo-random number in interval [0, ep_ro)
* @ep_ro: right open interval endpoint
*
* Returns a pseudo-random number that is in interval [0, ep_ro). Note
* that the result depends on PRNG being well distributed in [0, ~0U]
* u32 space. Here we use maximally equidistributed combined Tausworthe
* generator, that is, prandom_u32(). This is useful when requesting a
* random index of an array containing ep_ro elements, for example.
*
* Returns: pseudo-random number in interval [0, ep_ro)
*/
static inline u32 prandom_u32_max(u32 ep_ro)
{
return (u32)(((u64) prandom_u32() * ep_ro) >> 32);
}
/*
* Handle minimum values for seeds
* This is designed to be standalone for just prandom
* users, but for now we include it from <linux/random.h>
* for legacy reasons.
*/
static inline u32 __seed(u32 x, u32 m)
{
return (x < m) ? x + m : x;
}
/**
* prandom_seed_state - set seed for prandom_u32_state().
* @state: pointer to state structure to receive the seed.
* @seed: arbitrary 64-bit value to use as a seed.
*/
static inline void prandom_seed_state(struct rnd_state *state, u64 seed)
{
u32 i = (seed >> 32) ^ (seed << 10) ^ seed;
state->s1 = __seed(i, 2U);
state->s2 = __seed(i, 8U);
state->s3 = __seed(i, 16U);
state->s4 = __seed(i, 128U);
}
#include <linux/prandom.h>
#ifdef CONFIG_ARCH_RANDOM
# include <asm/archrandom.h>
@ -185,10 +136,4 @@ static inline bool __must_check arch_get_random_seed_int(unsigned int *v)
}
#endif
/* Pseudo random number generator from numerical recipes. */
static inline u32 next_pseudo_random32(u32 seed)
{
return seed * 1664525 + 1013904223;
}
#endif /* _LINUX_RANDOM_H */

View File

@ -450,6 +450,19 @@ static inline void psock_set_prog(struct bpf_prog **pprog,
bpf_prog_put(prog);
}
static inline int psock_replace_prog(struct bpf_prog **pprog,
struct bpf_prog *prog,
struct bpf_prog *old)
{
if (cmpxchg(pprog, old, prog) != old)
return -ENOENT;
if (old)
bpf_prog_put(old);
return 0;
}
static inline void psock_progs_drop(struct sk_psock_progs *progs)
{
psock_set_prog(&progs->msg_parser, NULL);

View File

@ -2029,10 +2029,10 @@ static int bpf_prog_detach(const union bpf_attr *attr)
ptype = BPF_PROG_TYPE_CGROUP_DEVICE;
break;
case BPF_SK_MSG_VERDICT:
return sock_map_get_from_fd(attr, NULL);
return sock_map_prog_detach(attr, BPF_PROG_TYPE_SK_MSG);
case BPF_SK_SKB_STREAM_PARSER:
case BPF_SK_SKB_STREAM_VERDICT:
return sock_map_get_from_fd(attr, NULL);
return sock_map_prog_detach(attr, BPF_PROG_TYPE_SK_SKB);
case BPF_LIRC_MODE2:
return lirc_prog_detach(attr);
case BPF_FLOW_DISSECTOR:

View File

@ -43,6 +43,7 @@
#include <linux/sched/debug.h>
#include <linux/slab.h>
#include <linux/compat.h>
#include <linux/random.h>
#include <linux/uaccess.h>
#include <asm/unistd.h>
@ -1775,6 +1776,13 @@ void update_process_times(int user_tick)
scheduler_tick();
if (IS_ENABLED(CONFIG_POSIX_TIMERS))
run_posix_cpu_timers();
/* The current CPU might make use of net randoms without receiving IRQs
* to renew them often enough. Let's update the net_rand_state from a
* non-constant value that's not affine to the number of calls to make
* sure it's updated when there's some activity (we don't care in idle).
*/
this_cpu_add(net_rand_state.s1, rol32(jiffies, 24) + user_tick);
}
/**

View File

@ -48,7 +48,7 @@ static inline void prandom_state_selftest(void)
}
#endif
static DEFINE_PER_CPU(struct rnd_state, net_rand_state) __latent_entropy;
DEFINE_PER_CPU(struct rnd_state, net_rand_state);
/**
* prandom_u32_state - seeded pseudo-random number generator.

View File

@ -71,7 +71,42 @@ int sock_map_get_from_fd(const union bpf_attr *attr, struct bpf_prog *prog)
map = __bpf_map_get(f);
if (IS_ERR(map))
return PTR_ERR(map);
ret = sock_map_prog_update(map, prog, attr->attach_type);
ret = sock_map_prog_update(map, prog, NULL, attr->attach_type);
fdput(f);
return ret;
}
int sock_map_prog_detach(const union bpf_attr *attr, enum bpf_prog_type ptype)
{
u32 ufd = attr->target_fd;
struct bpf_prog *prog;
struct bpf_map *map;
struct fd f;
int ret;
if (attr->attach_flags)
return -EINVAL;
f = fdget(ufd);
map = __bpf_map_get(f);
if (IS_ERR(map))
return PTR_ERR(map);
prog = bpf_prog_get(attr->attach_bpf_fd);
if (IS_ERR(prog)) {
ret = PTR_ERR(prog);
goto put_map;
}
if (prog->type != ptype) {
ret = -EINVAL;
goto put_prog;
}
ret = sock_map_prog_update(map, NULL, prog, attr->attach_type);
put_prog:
bpf_prog_put(prog);
put_map:
fdput(f);
return ret;
}
@ -1015,27 +1050,32 @@ static struct sk_psock_progs *sock_map_progs(struct bpf_map *map)
}
int sock_map_prog_update(struct bpf_map *map, struct bpf_prog *prog,
u32 which)
struct bpf_prog *old, u32 which)
{
struct sk_psock_progs *progs = sock_map_progs(map);
struct bpf_prog **pprog;
if (!progs)
return -EOPNOTSUPP;
switch (which) {
case BPF_SK_MSG_VERDICT:
psock_set_prog(&progs->msg_parser, prog);
pprog = &progs->msg_parser;
break;
case BPF_SK_SKB_STREAM_PARSER:
psock_set_prog(&progs->skb_parser, prog);
pprog = &progs->skb_parser;
break;
case BPF_SK_SKB_STREAM_VERDICT:
psock_set_prog(&progs->skb_verdict, prog);
pprog = &progs->skb_verdict;
break;
default:
return -EOPNOTSUPP;
}
if (old)
return psock_replace_prog(pprog, prog, old);
psock_set_prog(pprog, prog);
return 0;
}

View File

@ -793,19 +793,19 @@ static void test_sockmap(unsigned int tasks, void *data)
}
err = bpf_prog_detach(fd, BPF_SK_SKB_STREAM_PARSER);
if (err) {
if (!err) {
printf("Failed empty parser prog detach\n");
goto out_sockmap;
}
err = bpf_prog_detach(fd, BPF_SK_SKB_STREAM_VERDICT);
if (err) {
if (!err) {
printf("Failed empty verdict prog detach\n");
goto out_sockmap;
}
err = bpf_prog_detach(fd, BPF_SK_MSG_VERDICT);
if (err) {
if (!err) {
printf("Failed empty msg verdict prog detach\n");
goto out_sockmap;
}
@ -1094,19 +1094,19 @@ static void test_sockmap(unsigned int tasks, void *data)
assert(status == 0);
}
err = bpf_prog_detach(map_fd_rx, __MAX_BPF_ATTACH_TYPE);
err = bpf_prog_detach2(parse_prog, map_fd_rx, __MAX_BPF_ATTACH_TYPE);
if (!err) {
printf("Detached an invalid prog type.\n");
goto out_sockmap;
}
err = bpf_prog_detach(map_fd_rx, BPF_SK_SKB_STREAM_PARSER);
err = bpf_prog_detach2(parse_prog, map_fd_rx, BPF_SK_SKB_STREAM_PARSER);
if (err) {
printf("Failed parser prog detach\n");
goto out_sockmap;
}
err = bpf_prog_detach(map_fd_rx, BPF_SK_SKB_STREAM_VERDICT);
err = bpf_prog_detach2(verdict_prog, map_fd_rx, BPF_SK_SKB_STREAM_VERDICT);
if (err) {
printf("Failed parser prog detach\n");
goto out_sockmap;