This is the 4.14.316 stable release

-----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEEZH8oZUiU471FcZm+ONu9yGCSaT4FAmR14EYACgkQONu9yGCS
 aT5FaBAAmUwAPNKytdgTNtrVo+mZdK8IQFL3ye+gI60A8DtleJjExE/vnVVrho4k
 PsWp8QdRuEgCWRWwe3u+59z0o/3Z+PK3L3G6rge/e/oso/FanrSZOHClbaZSfegm
 iRfj6IqlvAxLaFFPUyci0z5MlKeNj16XtCo64WmDGk+VIBgvYowj5ji0kgBk/JN8
 lKpgstPhY88jA6cmLLbN5C5h8pKMOXo2DuQiJXLh3QO1LKO5gU7r1XAGD7yVM6bm
 LKT7Gi6mXnfsrfntI77h8F6bY8BOr4rgDaSizBVsx0o1DDcaLgk07xP+uM/pzuCx
 hxiS2g0vi4maR+agO2PkvjDGt3QWDXh1XyqzBH93QJ5OZcoak+UWpbHqqqVjAdmm
 eJ7GJAaqKDwWn4nLefoJw6kLz3a1MpfNZiFPsTdb5VYml9ilZat/80X1EVBWldgq
 bXIsBW/ktju/LRbr/HP3FqEhPLV8n5wdEb49qTN7nVx5+jIzZhO0hfiYq7OT5FHb
 /Ff6qOuFJ37ax50LYQQniXwpT43DBkb5oMElaLX7rQHqd6EPqX6hFpruwyK56m47
 TvnezUveh5841XYNBB7d3vneMfB5TB9WWpZ39/1ocmN1A5iUFSNghXG4C4aXNYrY
 2KYyk7IN4+rmZwuMjTKmpQ/mACrURT0StFJ/xdwKaMavg6DOa8A=
 =qekP
 -----END PGP SIGNATURE-----

Merge 4.14.316 into android-4.14-stable

Changes in 4.14.316
	net: Fix load-tearing on sk->sk_stamp in sock_recv_cmsgs().
	netlink: annotate accesses to nlk->cb_running
	net: annotate sk->sk_err write from do_recvmmsg()
	ipvlan:Fix out-of-bounds caused by unclear skb->cb
	af_unix: Fix a data race of sk->sk_receive_queue->qlen.
	fs: hfsplus: remove WARN_ON() from hfsplus_cat_{read,write}_inode()
	regmap: cache: Return error in cache sync operations for REGCACHE_NONE
	memstick: r592: Fix UAF bug in r592_remove due to race condition
	ACPI: EC: Fix oops when removing custom query handlers
	drm/tegra: Avoid potential 32-bit integer overflow
	ACPICA: Avoid undefined behavior: applying zero offset to null pointer
	ACPICA: ACPICA: check null return of ACPI_ALLOCATE_ZEROED in acpi_db_display_objects
	wifi: brcmfmac: cfg80211: Pass the PMK in binary instead of hex
	ext2: Check block size validity during mount
	net: pasemi: Fix return type of pasemi_mac_start_tx()
	net: Catch invalid index in XPS mapping
	lib: cpu_rmap: Avoid use after free on rmap->obj array entries
	scsi: message: mptlan: Fix use after free bug in mptlan_remove() due to race condition
	gfs2: Fix inode height consistency check
	ext4: set goal start correctly in ext4_mb_normalize_request
	ext4: Fix best extent lstart adjustment logic in ext4_mb_new_inode_pa()
	wifi: iwlwifi: dvm: Fix memcpy: detected field-spanning write backtrace
	Bluetooth: L2CAP: fix "bad unlock balance" in l2cap_disconnect_rsp
	staging: rtl8192e: Replace macro RTL_PCI_DEVICE with PCI_DEVICE
	HID: logitech-hidpp: Don't use the USB serial for USB devices
	HID: logitech-hidpp: Reconcile USB and Unifying serials
	spi: spi-imx: fix MX51_ECSPI_* macros when cs > 3
	HID: wacom: generic: Set battery quirk only when we see battery data
	serial: 8250: Reinit port->pm on port specific driver unbind
	mcb-pci: Reallocate memory region to avoid memory overlapping
	sched: Fix KCSAN noinstr violation
	recordmcount: Fix memory leaks in the uwrite function
	clk: tegra20: fix gcc-7 constant overflow warning
	Input: xpad - add constants for GIP interface numbers
	phy: st: miphy28lp: use _poll_timeout functions for waits
	mfd: dln2: Fix memory leak in dln2_probe()
	cpupower: Make TSC read per CPU for Mperf monitor
	af_key: Reject optional tunnel/BEET mode templates in outbound policies
	net: fec: Better handle pm_runtime_get() failing in .remove()
	vsock: avoid to close connected socket after the timeout
	media: netup_unidvb: fix use-after-free at del_timer()
	net: nsh: Use correct mac_offset to unwind gso skb in nsh_gso_segment()
	cassini: Fix a memory leak in the error handling path of cas_init_one()
	igb: fix bit_shift to be in [1..8] range
	vlan: fix a potential uninit-value in vlan_dev_hard_start_xmit()
	usb-storage: fix deadlock when a scsi command timeouts more than once
	ALSA: hda: Fix Oops by 9.1 surround channel names
	ALSA: hda: Add NVIDIA codec IDs a3 through a7 to patch table
	statfs: enforce statfs[64] structure initialization
	serial: Add support for Advantech PCI-1611U card
	ceph: force updating the msg pointer in non-split case
	nilfs2: fix use-after-free bug of nilfs_root in nilfs_evict_inode()
	netfilter: nf_tables: bogus EBUSY in helper removal from transaction
	spi: spi-fsl-spi: automatically adapt bits-per-word in cpu mode
	spi: fsl-spi: Re-organise transfer bits_per_word adaptation
	spi: fsl-cpm: Use 16 bit mode for large transfers with even size
	m68k: Move signal frame following exception on 68020/030
	parisc: Allow to reboot machine after system halt
	netfilter: nftables: add nft_parse_register_load() and use it
	netfilter: nftables: add nft_parse_register_store() and use it
	netfilter: nftables: statify nft_parse_register()
	netfilter: nf_tables: validate registers coming from userspace.
	netfilter: nf_tables: add nft_setelem_parse_key()
	netfilter: nf_tables: allow up to 64 bytes in the set element data area
	netfilter: nf_tables: stricter validation of element data
	netfilter: nft_dynset: do not reject set updates with NFT_SET_EVAL
	netfilter: nf_tables: do not allow RULE_ID to refer to another chain
	netfilter: nf_tables: do not allow SET_ID to refer to another table
	netfilter: nf_tables: fix register ordering
	x86/mm: Avoid incomplete Global INVLPG flushes
	selftests/memfd: Fix unknown type name build failure
	USB: core: Add routines for endpoint checks in old drivers
	USB: sisusbvga: Add endpoint checks
	media: radio-shark: Add endpoint checks
	net: fix skb leak in __skb_tstamp_tx()
	ipv6: Fix out-of-bounds access in ipv6_find_tlv()
	power: supply: leds: Fix blink to LED on transition
	power: supply: bq27xxx: Fix bq27xxx_battery_update() race condition
	power: supply: bq27xxx: Fix I2C IRQ race on remove
	power: supply: bq27xxx: Fix poll_interval handling and races on remove
	power: supply: sbs-charger: Fix INHIBITED bit for Status reg
	xen/pvcalls-back: fix double frees with pvcalls_new_active_socket()
	x86/show_trace_log_lvl: Ensure stack pointer is aligned, again
	forcedeth: Fix an error handling path in nv_probe()
	3c589_cs: Fix an error handling path in tc589_probe()
	Linux 4.14.316

Change-Id: I3057e11d999112040cd36a7715309365928e3c02
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
Greg Kroah-Hartman 2023-05-30 17:53:01 +00:00
commit a1789769b3
109 changed files with 998 additions and 513 deletions

View File

@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
VERSION = 4
PATCHLEVEL = 14
SUBLEVEL = 315
SUBLEVEL = 316
EXTRAVERSION =
NAME = Petit Gorille

View File

@ -819,11 +819,17 @@ static inline int rt_setup_ucontext(struct ucontext __user *uc, struct pt_regs *
}
static inline void __user *
get_sigframe(struct ksignal *ksig, size_t frame_size)
get_sigframe(struct ksignal *ksig, struct pt_regs *tregs, size_t frame_size)
{
unsigned long usp = sigsp(rdusp(), ksig);
unsigned long gap = 0;
return (void __user *)((usp - frame_size) & -8UL);
if (CPU_IS_020_OR_030 && tregs->format == 0xb) {
/* USP is unreliable so use worst-case value */
gap = 256;
}
return (void __user *)((usp - gap - frame_size) & -8UL);
}
static int setup_frame(struct ksignal *ksig, sigset_t *set,
@ -841,7 +847,7 @@ static int setup_frame(struct ksignal *ksig, sigset_t *set,
return -EFAULT;
}
frame = get_sigframe(ksig, sizeof(*frame) + fsize);
frame = get_sigframe(ksig, tregs, sizeof(*frame) + fsize);
if (fsize)
err |= copy_to_user (frame + 1, regs + 1, fsize);
@ -912,7 +918,7 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
return -EFAULT;
}
frame = get_sigframe(ksig, sizeof(*frame));
frame = get_sigframe(ksig, tregs, sizeof(*frame));
if (fsize)
err |= copy_to_user (&frame->uc.uc_extra, regs + 1, fsize);

View File

@ -142,13 +142,18 @@ void machine_power_off(void)
/* It seems we have no way to power the system off via
* software. The user has to press the button himself. */
printk(KERN_EMERG "System shut down completed.\n"
"Please power this system off now.");
printk("Power off or press RETURN to reboot.\n");
/* prevent soft lockup/stalled CPU messages for endless loop. */
rcu_sysrq_start();
lockup_detector_soft_poweroff();
for (;;);
while (1) {
/* reboot if user presses RETURN key */
if (pdc_iodc_getc() == 13) {
printk("Rebooting...\n");
machine_restart(NULL);
}
}
}
void (*pm_power_off)(void) = machine_power_off;

View File

@ -73,6 +73,11 @@
#define INTEL_FAM6_LAKEFIELD 0x8A
#define INTEL_FAM6_ALDERLAKE 0x97
#define INTEL_FAM6_ALDERLAKE_L 0x9A
#define INTEL_FAM6_ALDERLAKE_N 0xBE
#define INTEL_FAM6_RAPTORLAKE 0xB7
#define INTEL_FAM6_RAPTORLAKE_P 0xBA
#define INTEL_FAM6_RAPTORLAKE_S 0xBF
#define INTEL_FAM6_TIGERLAKE_L 0x8C
#define INTEL_FAM6_TIGERLAKE 0x8D

View File

@ -115,7 +115,6 @@ void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
printk("%sCall Trace:\n", log_lvl);
unwind_start(&state, task, regs, stack);
stack = stack ? : get_stack_pointer(task, regs);
regs = unwind_get_entry_regs(&state, &partial);
/*
@ -134,9 +133,13 @@ void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
* - hardirq stack
* - entry stack
*/
for ( ; stack; stack = PTR_ALIGN(stack_info.next_sp, sizeof(long))) {
for (stack = stack ?: get_stack_pointer(task, regs);
stack;
stack = stack_info.next_sp) {
const char *stack_name;
stack = PTR_ALIGN(stack, sizeof(long));
if (get_stack_info(stack, task, &stack_info, &visit_mask)) {
/*
* We weren't on a valid stack. It's possible that

View File

@ -8,6 +8,7 @@
#include <linux/swapops.h>
#include <asm/set_memory.h>
#include <asm/cpu_device_id.h>
#include <asm/e820/api.h>
#include <asm/init.h>
#include <asm/page.h>
@ -199,6 +200,24 @@ static void __init probe_page_size_mask(void)
}
}
#define INTEL_MATCH(_model) { .vendor = X86_VENDOR_INTEL, \
.family = 6, \
.model = _model, \
}
/*
* INVLPG may not properly flush Global entries
* on these CPUs when PCIDs are enabled.
*/
static const struct x86_cpu_id invlpg_miss_ids[] = {
INTEL_MATCH(INTEL_FAM6_ALDERLAKE ),
INTEL_MATCH(INTEL_FAM6_ALDERLAKE_L ),
INTEL_MATCH(INTEL_FAM6_ALDERLAKE_N ),
INTEL_MATCH(INTEL_FAM6_RAPTORLAKE ),
INTEL_MATCH(INTEL_FAM6_RAPTORLAKE_P),
INTEL_MATCH(INTEL_FAM6_RAPTORLAKE_S),
{}
};
static void setup_pcid(void)
{
if (!IS_ENABLED(CONFIG_X86_64))
@ -207,6 +226,12 @@ static void setup_pcid(void)
if (!boot_cpu_has(X86_FEATURE_PCID))
return;
if (x86_match_cpu(invlpg_miss_ids)) {
pr_info("Incomplete global flushes, disabling PCID");
setup_clear_cpu_cap(X86_FEATURE_PCID);
return;
}
if (boot_cpu_has(X86_FEATURE_PGE)) {
/*
* This can't be cr4_set_bits_and_update_boot() -- the

View File

@ -600,6 +600,9 @@ acpi_status acpi_db_display_objects(char *obj_type_arg, char *display_count_arg)
object_info =
ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_object_info));
if (!object_info)
return (AE_NO_MEMORY);
/* Walk the namespace from the root */
(void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,

View File

@ -610,9 +610,14 @@ acpi_ds_init_aml_walk(struct acpi_walk_state *walk_state,
ACPI_FUNCTION_TRACE(ds_init_aml_walk);
walk_state->parser_state.aml =
walk_state->parser_state.aml_start = aml_start;
walk_state->parser_state.aml_end =
walk_state->parser_state.pkg_end = aml_start + aml_length;
walk_state->parser_state.aml_start =
walk_state->parser_state.aml_end =
walk_state->parser_state.pkg_end = aml_start;
/* Avoid undefined behavior: applying zero offset to null pointer */
if (aml_length != 0) {
walk_state->parser_state.aml_end += aml_length;
walk_state->parser_state.pkg_end += aml_length;
}
/* The next_op of the next_walk will be the beginning of the method */

View File

@ -1135,6 +1135,7 @@ static void acpi_ec_remove_query_handlers(struct acpi_ec *ec,
void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit)
{
acpi_ec_remove_query_handlers(ec, false, query_bit);
flush_workqueue(ec_query_wq);
}
EXPORT_SYMBOL_GPL(acpi_ec_remove_query_handler);

View File

@ -347,6 +347,9 @@ int regcache_sync(struct regmap *map)
const char *name;
bool bypass;
if (WARN_ON(map->cache_type == REGCACHE_NONE))
return -EINVAL;
BUG_ON(!map->cache_ops);
map->lock(map->lock_arg);
@ -416,6 +419,9 @@ int regcache_sync_region(struct regmap *map, unsigned int min,
const char *name;
bool bypass;
if (WARN_ON(map->cache_type == REGCACHE_NONE))
return -EINVAL;
BUG_ON(!map->cache_ops);
map->lock(map->lock_arg);

View File

@ -27,24 +27,24 @@
#include "clk-id.h"
#define OSC_CTRL 0x50
#define OSC_CTRL_OSC_FREQ_MASK (3<<30)
#define OSC_CTRL_OSC_FREQ_13MHZ (0<<30)
#define OSC_CTRL_OSC_FREQ_19_2MHZ (1<<30)
#define OSC_CTRL_OSC_FREQ_12MHZ (2<<30)
#define OSC_CTRL_OSC_FREQ_26MHZ (3<<30)
#define OSC_CTRL_MASK (0x3f2 | OSC_CTRL_OSC_FREQ_MASK)
#define OSC_CTRL_OSC_FREQ_MASK (3u<<30)
#define OSC_CTRL_OSC_FREQ_13MHZ (0u<<30)
#define OSC_CTRL_OSC_FREQ_19_2MHZ (1u<<30)
#define OSC_CTRL_OSC_FREQ_12MHZ (2u<<30)
#define OSC_CTRL_OSC_FREQ_26MHZ (3u<<30)
#define OSC_CTRL_MASK (0x3f2u | OSC_CTRL_OSC_FREQ_MASK)
#define OSC_CTRL_PLL_REF_DIV_MASK (3<<28)
#define OSC_CTRL_PLL_REF_DIV_1 (0<<28)
#define OSC_CTRL_PLL_REF_DIV_2 (1<<28)
#define OSC_CTRL_PLL_REF_DIV_4 (2<<28)
#define OSC_CTRL_PLL_REF_DIV_MASK (3u<<28)
#define OSC_CTRL_PLL_REF_DIV_1 (0u<<28)
#define OSC_CTRL_PLL_REF_DIV_2 (1u<<28)
#define OSC_CTRL_PLL_REF_DIV_4 (2u<<28)
#define OSC_FREQ_DET 0x58
#define OSC_FREQ_DET_TRIG (1<<31)
#define OSC_FREQ_DET_TRIG (1u<<31)
#define OSC_FREQ_DET_STATUS 0x5c
#define OSC_FREQ_DET_BUSY (1<<31)
#define OSC_FREQ_DET_CNT_MASK 0xFFFF
#define OSC_FREQ_DET_BUSYu (1<<31)
#define OSC_FREQ_DET_CNT_MASK 0xFFFFu
#define TEGRA20_CLK_PERIPH_BANKS 3

View File

@ -709,7 +709,7 @@ static int tegra_sor_compute_config(struct tegra_sor *sor,
struct drm_dp_link *link)
{
const u64 f = 100000, link_rate = link->rate * 1000;
const u64 pclk = mode->clock * 1000;
const u64 pclk = (u64)mode->clock * 1000;
u64 input, output, watermark, num;
struct tegra_sor_params params;
u32 num_syms_per_line;

View File

@ -675,8 +675,7 @@ static int hidpp_unifying_init(struct hidpp_device *hidpp)
if (ret)
return ret;
snprintf(hdev->uniq, sizeof(hdev->uniq), "%04x-%4phD",
hdev->product, &serial);
snprintf(hdev->uniq, sizeof(hdev->uniq), "%4phD", &serial);
dbg_hid("HID++ Unifying: Got serial: %s\n", hdev->uniq);
name = hidpp_unifying_get_name(hidpp);
@ -777,6 +776,54 @@ static bool hidpp_is_connected(struct hidpp_device *hidpp)
return ret == 0;
}
/* -------------------------------------------------------------------------- */
/* 0x0003: Device Information */
/* -------------------------------------------------------------------------- */
#define HIDPP_PAGE_DEVICE_INFORMATION 0x0003
#define CMD_GET_DEVICE_INFO 0x00
static int hidpp_get_serial(struct hidpp_device *hidpp, u32 *serial)
{
struct hidpp_report response;
u8 feature_type;
u8 feature_index;
int ret;
ret = hidpp_root_get_feature(hidpp, HIDPP_PAGE_DEVICE_INFORMATION,
&feature_index,
&feature_type);
if (ret)
return ret;
ret = hidpp_send_fap_command_sync(hidpp, feature_index,
CMD_GET_DEVICE_INFO,
NULL, 0, &response);
if (ret)
return ret;
/* See hidpp_unifying_get_serial() */
*serial = *((u32 *)&response.rap.params[1]);
return 0;
}
static int hidpp_serial_init(struct hidpp_device *hidpp)
{
struct hid_device *hdev = hidpp->hid_dev;
u32 serial;
int ret;
ret = hidpp_get_serial(hidpp, &serial);
if (ret)
return ret;
snprintf(hdev->uniq, sizeof(hdev->uniq), "%4phD", &serial);
dbg_hid("HID++ DeviceInformation: Got serial: %s\n", hdev->uniq);
return 0;
}
/* -------------------------------------------------------------------------- */
/* 0x0005: GetDeviceNameType */
/* -------------------------------------------------------------------------- */
@ -3039,6 +3086,8 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
if (hidpp->quirks & HIDPP_QUIRK_UNIFYING)
hidpp_unifying_init(hidpp);
else if (hid_is_usb(hidpp->hid_dev))
hidpp_serial_init(hidpp);
connected = hidpp_is_connected(hidpp);
atomic_set(&hidpp->connected, connected);

View File

@ -1782,18 +1782,7 @@ static void wacom_map_usage(struct input_dev *input, struct hid_usage *usage,
static void wacom_wac_battery_usage_mapping(struct hid_device *hdev,
struct hid_field *field, struct hid_usage *usage)
{
struct wacom *wacom = hid_get_drvdata(hdev);
struct wacom_wac *wacom_wac = &wacom->wacom_wac;
struct wacom_features *features = &wacom_wac->features;
unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);
switch (equivalent_usage) {
case HID_DG_BATTERYSTRENGTH:
case WACOM_HID_WD_BATTERY_LEVEL:
case WACOM_HID_WD_BATTERY_CHARGING:
features->quirks |= WACOM_QUIRK_BATTERY;
break;
}
return;
}
static void wacom_wac_battery_event(struct hid_device *hdev, struct hid_field *field,
@ -1814,18 +1803,21 @@ static void wacom_wac_battery_event(struct hid_device *hdev, struct hid_field *f
wacom_wac->hid_data.bat_connected = 1;
wacom_wac->hid_data.bat_status = WACOM_POWER_SUPPLY_STATUS_AUTO;
}
wacom_wac->features.quirks |= WACOM_QUIRK_BATTERY;
break;
case WACOM_HID_WD_BATTERY_LEVEL:
value = value * 100 / (field->logical_maximum - field->logical_minimum);
wacom_wac->hid_data.battery_capacity = value;
wacom_wac->hid_data.bat_connected = 1;
wacom_wac->hid_data.bat_status = WACOM_POWER_SUPPLY_STATUS_AUTO;
wacom_wac->features.quirks |= WACOM_QUIRK_BATTERY;
break;
case WACOM_HID_WD_BATTERY_CHARGING:
wacom_wac->hid_data.bat_charging = value;
wacom_wac->hid_data.ps_connected = value;
wacom_wac->hid_data.bat_connected = 1;
wacom_wac->hid_data.bat_status = WACOM_POWER_SUPPLY_STATUS_AUTO;
wacom_wac->features.quirks |= WACOM_QUIRK_BATTERY;
break;
}
}
@ -1841,18 +1833,15 @@ static void wacom_wac_battery_report(struct hid_device *hdev,
{
struct wacom *wacom = hid_get_drvdata(hdev);
struct wacom_wac *wacom_wac = &wacom->wacom_wac;
struct wacom_features *features = &wacom_wac->features;
if (features->quirks & WACOM_QUIRK_BATTERY) {
int status = wacom_wac->hid_data.bat_status;
int capacity = wacom_wac->hid_data.battery_capacity;
bool charging = wacom_wac->hid_data.bat_charging;
bool connected = wacom_wac->hid_data.bat_connected;
bool powered = wacom_wac->hid_data.ps_connected;
int status = wacom_wac->hid_data.bat_status;
int capacity = wacom_wac->hid_data.battery_capacity;
bool charging = wacom_wac->hid_data.bat_charging;
bool connected = wacom_wac->hid_data.bat_connected;
bool powered = wacom_wac->hid_data.ps_connected;
wacom_notify_battery(wacom_wac, status, capacity, charging,
connected, powered);
}
wacom_notify_battery(wacom_wac, status, capacity, charging,
connected, powered);
}
static void wacom_wac_pad_usage_mapping(struct hid_device *hdev,

View File

@ -506,6 +506,9 @@ struct xboxone_init_packet {
}
#define GIP_WIRED_INTF_DATA 0
#define GIP_WIRED_INTF_AUDIO 1
/*
* This packet is required for all Xbox One pads with 2015
* or later firmware installed (or present from the factory).
@ -1830,7 +1833,7 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
}
if (xpad->xtype == XTYPE_XBOXONE &&
intf->cur_altsetting->desc.bInterfaceNumber != 0) {
intf->cur_altsetting->desc.bInterfaceNumber != GIP_WIRED_INTF_DATA) {
/*
* The Xbox One controller lists three interfaces all with the
* same interface class, subclass and protocol. Differentiate by

View File

@ -34,7 +34,7 @@ static int mcb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct resource *res;
struct priv *priv;
int ret;
int ret, table_size;
unsigned long flags;
priv = devm_kzalloc(&pdev->dev, sizeof(struct priv), GFP_KERNEL);
@ -93,7 +93,30 @@ static int mcb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (ret < 0)
goto out_mcb_bus;
dev_dbg(&pdev->dev, "Found %d cells\n", ret);
table_size = ret;
if (table_size < CHAM_HEADER_SIZE) {
/* Release the previous resources */
devm_iounmap(&pdev->dev, priv->base);
devm_release_mem_region(&pdev->dev, priv->mapbase, CHAM_HEADER_SIZE);
/* Then, allocate it again with the actual chameleon table size */
res = devm_request_mem_region(&pdev->dev, priv->mapbase,
table_size,
KBUILD_MODNAME);
if (!res) {
dev_err(&pdev->dev, "Failed to request PCI memory\n");
ret = -EBUSY;
goto out_mcb_bus;
}
priv->base = devm_ioremap(&pdev->dev, priv->mapbase, table_size);
if (!priv->base) {
dev_err(&pdev->dev, "Cannot ioremap\n");
ret = -ENOMEM;
goto out_mcb_bus;
}
}
mcb_bus_add_devices(priv->bus);

View File

@ -707,7 +707,7 @@ static void netup_unidvb_dma_fini(struct netup_unidvb_dev *ndev, int num)
netup_unidvb_dma_enable(dma, 0);
msleep(50);
cancel_work_sync(&dma->work);
del_timer(&dma->timeout);
del_timer_sync(&dma->timeout);
}
static int netup_unidvb_dma_setup(struct netup_unidvb_dev *ndev)

View File

@ -316,6 +316,16 @@ static int usb_shark_probe(struct usb_interface *intf,
{
struct shark_device *shark;
int retval = -ENOMEM;
static const u8 ep_addresses[] = {
SHARK_IN_EP | USB_DIR_IN,
SHARK_OUT_EP | USB_DIR_OUT,
0};
/* Are the expected endpoints present? */
if (!usb_check_int_endpoints(intf, ep_addresses)) {
dev_err(&intf->dev, "Invalid radioSHARK device\n");
return -EINVAL;
}
shark = kzalloc(sizeof(struct shark_device), GFP_KERNEL);
if (!shark)

View File

@ -282,6 +282,16 @@ static int usb_shark_probe(struct usb_interface *intf,
{
struct shark_device *shark;
int retval = -ENOMEM;
static const u8 ep_addresses[] = {
SHARK_IN_EP | USB_DIR_IN,
SHARK_OUT_EP | USB_DIR_OUT,
0};
/* Are the expected endpoints present? */
if (!usb_check_int_endpoints(intf, ep_addresses)) {
dev_err(&intf->dev, "Invalid radioSHARK2 device\n");
return -EINVAL;
}
shark = kzalloc(sizeof(struct shark_device), GFP_KERNEL);
if (!shark)

View File

@ -832,7 +832,7 @@ static void r592_remove(struct pci_dev *pdev)
/* Stop the processing thread.
That ensures that we won't take any more requests */
kthread_stop(dev->io_thread);
del_timer_sync(&dev->detect_timer);
r592_enable_device(dev, false);
while (!error && dev->req) {

View File

@ -1429,7 +1429,9 @@ mptlan_remove(struct pci_dev *pdev)
{
MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
struct net_device *dev = ioc->netdev;
struct mpt_lan_priv *priv = netdev_priv(dev);
cancel_delayed_work_sync(&priv->post_buckets_task);
if(dev != NULL) {
unregister_netdev(dev);
free_netdev(dev);

View File

@ -804,6 +804,7 @@ out_stop_rx:
dln2_stop_rx_urbs(dln2);
out_free:
usb_put_dev(dln2->usb_dev);
dln2_free(dln2);
return ret;

View File

@ -196,6 +196,7 @@ static int tc589_probe(struct pcmcia_device *link)
{
struct el3_private *lp;
struct net_device *dev;
int ret;
dev_dbg(&link->dev, "3c589_attach()\n");
@ -219,7 +220,15 @@ static int tc589_probe(struct pcmcia_device *link)
dev->ethtool_ops = &netdev_ethtool_ops;
return tc589_config(link);
ret = tc589_config(link);
if (ret)
goto err_free_netdev;
return 0;
err_free_netdev:
free_netdev(dev);
return ret;
}
static void tc589_detach(struct pcmcia_device *link)

View File

@ -3569,7 +3569,9 @@ fec_drv_remove(struct platform_device *pdev)
ret = pm_runtime_get_sync(&pdev->dev);
if (ret < 0)
return ret;
dev_err(&pdev->dev,
"Failed to resume device in remove callback (%pe)\n",
ERR_PTR(ret));
cancel_work_sync(&fep->tx_timeout_work);
fec_ptp_stop(pdev);
@ -3582,8 +3584,13 @@ fec_drv_remove(struct platform_device *pdev)
of_phy_deregister_fixed_link(np);
of_node_put(fep->phy_node);
clk_disable_unprepare(fep->clk_ahb);
clk_disable_unprepare(fep->clk_ipg);
/* After pm_runtime_get_sync() failed, the clks are still off, so skip
* disabling them again.
*/
if (ret >= 0) {
clk_disable_unprepare(fep->clk_ahb);
clk_disable_unprepare(fep->clk_ipg);
}
pm_runtime_put_noidle(&pdev->dev);
pm_runtime_disable(&pdev->dev);

View File

@ -445,7 +445,7 @@ void igb_mta_set(struct e1000_hw *hw, u32 hash_value)
static u32 igb_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr)
{
u32 hash_value, hash_mask;
u8 bit_shift = 0;
u8 bit_shift = 1;
/* Register count multiplied by bits per register */
hash_mask = (hw->mac.mta_reg_count * 32) - 1;
@ -453,7 +453,7 @@ static u32 igb_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr)
/* For a mc_filter_type of 0, bit_shift is the number of left-shifts
* where 0xFF would still fall within the hash mask.
*/
while (hash_mask >> bit_shift != 0xFF)
while (hash_mask >> bit_shift != 0xFF && bit_shift < 4)
bit_shift++;
/* The portion of the address that is used for the hash table

View File

@ -6020,6 +6020,7 @@ static int nv_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
return 0;
out_error:
nv_mgmt_release_sema(dev);
if (phystate_orig)
writel(phystate|NVREG_ADAPTCTL_RUNNING, base + NvRegAdapterControl);
out_freering:

View File

@ -1436,7 +1436,7 @@ static void pasemi_mac_queue_csdesc(const struct sk_buff *skb,
write_dma_reg(PAS_DMA_TXCHAN_INCR(txring->chan.chno), 2);
}
static int pasemi_mac_start_tx(struct sk_buff *skb, struct net_device *dev)
static netdev_tx_t pasemi_mac_start_tx(struct sk_buff *skb, struct net_device *dev)
{
struct pasemi_mac * const mac = netdev_priv(dev);
struct pasemi_mac_txring * const txring = tx_ring(mac);

View File

@ -5152,6 +5152,8 @@ err_out_iounmap:
cas_shutdown(cp);
mutex_unlock(&cp->pm_mutex);
vfree(cp->fw_data);
pci_iounmap(pdev, cp->regs);

View File

@ -394,6 +394,9 @@ static int ipvlan_process_v4_outbound(struct sk_buff *skb)
goto err;
}
skb_dst_set(skb, &rt->dst);
memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
err = ip_local_out(net, skb->sk, skb);
if (unlikely(net_xmit_eval(err)))
dev->stats.tx_errors++;
@ -431,6 +434,9 @@ static int ipvlan_process_v6_outbound(struct sk_buff *skb)
goto err;
}
skb_dst_set(skb, dst);
memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));
err = ip6_local_out(net, skb->sk, skb);
if (unlikely(net_xmit_eval(err)))
dev->stats.tx_errors++;

View File

@ -1349,13 +1349,14 @@ static u16 brcmf_map_fw_linkdown_reason(const struct brcmf_event_msg *e)
static int brcmf_set_pmk(struct brcmf_if *ifp, const u8 *pmk_data, u16 pmk_len)
{
struct brcmf_wsec_pmk_le pmk;
int i, err;
int err;
/* convert to firmware key format */
pmk.key_len = cpu_to_le16(pmk_len << 1);
pmk.flags = cpu_to_le16(BRCMF_WSEC_PASSPHRASE);
for (i = 0; i < pmk_len; i++)
snprintf(&pmk.key[2 * i], 3, "%02x", pmk_data[i]);
memset(&pmk, 0, sizeof(pmk));
/* pass pmk directly */
pmk.key_len = cpu_to_le16(pmk_len);
pmk.flags = cpu_to_le16(0);
memcpy(pmk.key, pmk_data, pmk_len);
/* store psk in firmware */
err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_WSEC_PMK,

View File

@ -1101,6 +1101,7 @@ static int iwlagn_send_sta_key(struct iwl_priv *priv,
{
__le16 key_flags;
struct iwl_addsta_cmd sta_cmd;
size_t to_copy;
int i;
spin_lock_bh(&priv->sta_lock);
@ -1120,7 +1121,9 @@ static int iwlagn_send_sta_key(struct iwl_priv *priv,
sta_cmd.key.tkip_rx_tsc_byte2 = tkip_iv32;
for (i = 0; i < 5; i++)
sta_cmd.key.tkip_rx_ttak[i] = cpu_to_le16(tkip_p1k[i]);
memcpy(sta_cmd.key.key, keyconf->key, keyconf->keylen);
/* keyconf may contain MIC rx/tx keys which iwl does not use */
to_copy = min_t(size_t, sizeof(sta_cmd.key.key), keyconf->keylen);
memcpy(sta_cmd.key.key, keyconf->key, to_copy);
break;
case WLAN_CIPHER_SUITE_WEP104:
key_flags |= STA_KEY_FLG_KEY_SIZE_MSK;

View File

@ -13,6 +13,7 @@
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
@ -488,19 +489,11 @@ static inline void miphy28lp_pcie_config_gen(struct miphy28lp_phy *miphy_phy)
static inline int miphy28lp_wait_compensation(struct miphy28lp_phy *miphy_phy)
{
unsigned long finish = jiffies + 5 * HZ;
u8 val;
/* Waiting for Compensation to complete */
do {
val = readb_relaxed(miphy_phy->base + MIPHY_COMP_FSM_6);
if (time_after_eq(jiffies, finish))
return -EBUSY;
cpu_relax();
} while (!(val & COMP_DONE));
return 0;
return readb_relaxed_poll_timeout(miphy_phy->base + MIPHY_COMP_FSM_6,
val, val & COMP_DONE, 1, 5 * USEC_PER_SEC);
}
@ -809,7 +802,6 @@ static inline void miphy28lp_configure_usb3(struct miphy28lp_phy *miphy_phy)
static inline int miphy_is_ready(struct miphy28lp_phy *miphy_phy)
{
unsigned long finish = jiffies + 5 * HZ;
u8 mask = HFC_PLL | HFC_RDY;
u8 val;
@ -820,21 +812,14 @@ static inline int miphy_is_ready(struct miphy28lp_phy *miphy_phy)
if (miphy_phy->type == PHY_TYPE_SATA)
mask |= PHY_RDY;
do {
val = readb_relaxed(miphy_phy->base + MIPHY_STATUS_1);
if ((val & mask) != mask)
cpu_relax();
else
return 0;
} while (!time_after_eq(jiffies, finish));
return -EBUSY;
return readb_relaxed_poll_timeout(miphy_phy->base + MIPHY_STATUS_1,
val, (val & mask) == mask, 1,
5 * USEC_PER_SEC);
}
static int miphy_osc_is_ready(struct miphy28lp_phy *miphy_phy)
{
struct miphy28lp_dev *miphy_dev = miphy_phy->phydev;
unsigned long finish = jiffies + 5 * HZ;
u32 val;
if (!miphy_phy->osc_rdy)
@ -843,17 +828,10 @@ static int miphy_osc_is_ready(struct miphy28lp_phy *miphy_phy)
if (!miphy_phy->syscfg_reg[SYSCFG_STATUS])
return -EINVAL;
do {
regmap_read(miphy_dev->regmap,
miphy_phy->syscfg_reg[SYSCFG_STATUS], &val);
if ((val & MIPHY_OSC_RDY) != MIPHY_OSC_RDY)
cpu_relax();
else
return 0;
} while (!time_after_eq(jiffies, finish));
return -EBUSY;
return regmap_read_poll_timeout(miphy_dev->regmap,
miphy_phy->syscfg_reg[SYSCFG_STATUS],
val, val & MIPHY_OSC_RDY, 1,
5 * USEC_PER_SEC);
}
static int miphy28lp_get_resource_byname(struct device_node *child,

View File

@ -1506,7 +1506,7 @@ static int bq27xxx_battery_read_health(struct bq27xxx_device_info *di)
return POWER_SUPPLY_HEALTH_GOOD;
}
void bq27xxx_battery_update(struct bq27xxx_device_info *di)
static void bq27xxx_battery_update_unlocked(struct bq27xxx_device_info *di)
{
struct bq27xxx_reg_cache cache = {0, };
bool has_ci_flag = di->opts & BQ27XXX_O_ZERO;
@ -1554,6 +1554,16 @@ void bq27xxx_battery_update(struct bq27xxx_device_info *di)
di->cache = cache;
di->last_update = jiffies;
if (!di->removed && poll_interval > 0)
mod_delayed_work(system_wq, &di->work, poll_interval * HZ);
}
void bq27xxx_battery_update(struct bq27xxx_device_info *di)
{
mutex_lock(&di->lock);
bq27xxx_battery_update_unlocked(di);
mutex_unlock(&di->lock);
}
EXPORT_SYMBOL_GPL(bq27xxx_battery_update);
@ -1564,9 +1574,6 @@ static void bq27xxx_battery_poll(struct work_struct *work)
work.work);
bq27xxx_battery_update(di);
if (poll_interval > 0)
schedule_delayed_work(&di->work, poll_interval * HZ);
}
/*
@ -1725,10 +1732,8 @@ static int bq27xxx_battery_get_property(struct power_supply *psy,
struct bq27xxx_device_info *di = power_supply_get_drvdata(psy);
mutex_lock(&di->lock);
if (time_is_before_jiffies(di->last_update + 5 * HZ)) {
cancel_delayed_work_sync(&di->work);
bq27xxx_battery_poll(&di->work.work);
}
if (time_is_before_jiffies(di->last_update + 5 * HZ))
bq27xxx_battery_update_unlocked(di);
mutex_unlock(&di->lock);
if (psp != POWER_SUPPLY_PROP_PRESENT && di->cache.flags < 0)
@ -1865,22 +1870,18 @@ EXPORT_SYMBOL_GPL(bq27xxx_battery_setup);
void bq27xxx_battery_teardown(struct bq27xxx_device_info *di)
{
/*
* power_supply_unregister call bq27xxx_battery_get_property which
* call bq27xxx_battery_poll.
* Make sure that bq27xxx_battery_poll will not call
* schedule_delayed_work again after unregister (which cause OOPS).
*/
poll_interval = 0;
cancel_delayed_work_sync(&di->work);
power_supply_unregister(di->bat);
mutex_lock(&bq27xxx_list_lock);
list_del(&di->list);
mutex_unlock(&bq27xxx_list_lock);
/* Set removed to avoid bq27xxx_battery_update() re-queuing the work */
mutex_lock(&di->lock);
di->removed = true;
mutex_unlock(&di->lock);
cancel_delayed_work_sync(&di->work);
power_supply_unregister(di->bat);
mutex_destroy(&di->lock);
}
EXPORT_SYMBOL_GPL(bq27xxx_battery_teardown);

View File

@ -187,7 +187,7 @@ static int bq27xxx_battery_i2c_probe(struct i2c_client *client,
i2c_set_clientdata(client, di);
if (client->irq) {
ret = devm_request_threaded_irq(&client->dev, client->irq,
ret = request_threaded_irq(client->irq,
NULL, bq27xxx_battery_irq_handler_thread,
IRQF_ONESHOT,
di->name, di);
@ -217,6 +217,7 @@ static int bq27xxx_battery_i2c_remove(struct i2c_client *client)
{
struct bq27xxx_device_info *di = i2c_get_clientdata(client);
free_irq(client->irq, di);
bq27xxx_battery_teardown(di);
mutex_lock(&battery_mutex);

View File

@ -35,8 +35,9 @@ static void power_supply_update_bat_leds(struct power_supply *psy)
led_trigger_event(psy->charging_full_trig, LED_FULL);
led_trigger_event(psy->charging_trig, LED_OFF);
led_trigger_event(psy->full_trig, LED_FULL);
led_trigger_event(psy->charging_blink_full_solid_trig,
LED_FULL);
/* Going from blink to LED on requires a LED_OFF event to stop blink */
led_trigger_event(psy->charging_blink_full_solid_trig, LED_OFF);
led_trigger_event(psy->charging_blink_full_solid_trig, LED_FULL);
break;
case POWER_SUPPLY_STATUS_CHARGING:
led_trigger_event(psy->charging_full_trig, LED_FULL);

View File

@ -29,7 +29,7 @@
#define SBS_CHARGER_REG_STATUS 0x13
#define SBS_CHARGER_REG_ALARM_WARNING 0x16
#define SBS_CHARGER_STATUS_CHARGE_INHIBITED BIT(1)
#define SBS_CHARGER_STATUS_CHARGE_INHIBITED BIT(0)
#define SBS_CHARGER_STATUS_RES_COLD BIT(9)
#define SBS_CHARGER_STATUS_RES_HOT BIT(10)
#define SBS_CHARGER_STATUS_BATTERY_PRESENT BIT(14)

View File

@ -25,6 +25,7 @@
#include <linux/spi/spi.h>
#include <linux/types.h>
#include <linux/platform_device.h>
#include <linux/byteorder/generic.h>
#include "spi-fsl-cpm.h"
#include "spi-fsl-lib.h"
@ -124,6 +125,21 @@ int fsl_spi_cpm_bufs(struct mpc8xxx_spi *mspi,
mspi->rx_dma = mspi->dma_dummy_rx;
mspi->map_rx_dma = 0;
}
if (t->bits_per_word == 16 && t->tx_buf) {
const u16 *src = t->tx_buf;
u16 *dst;
int i;
dst = kmalloc(t->len, GFP_KERNEL);
if (!dst)
return -ENOMEM;
for (i = 0; i < t->len >> 1; i++)
dst[i] = cpu_to_le16p(src + i);
mspi->tx = dst;
mspi->map_tx_dma = 1;
}
if (mspi->map_tx_dma) {
void *nonconst_tx = (void *)mspi->tx; /* shut up gcc */
@ -177,6 +193,13 @@ void fsl_spi_cpm_bufs_complete(struct mpc8xxx_spi *mspi)
if (mspi->map_rx_dma)
dma_unmap_single(dev, mspi->rx_dma, t->len, DMA_FROM_DEVICE);
mspi->xfer_in_progress = NULL;
if (t->bits_per_word == 16 && t->rx_buf) {
int i;
for (i = 0; i < t->len; i += 2)
le16_to_cpus(t->rx_buf + i);
}
}
EXPORT_SYMBOL_GPL(fsl_spi_cpm_bufs_complete);

View File

@ -201,26 +201,6 @@ static int mspi_apply_cpu_mode_quirks(struct spi_mpc8xxx_cs *cs,
return bits_per_word;
}
static int mspi_apply_qe_mode_quirks(struct spi_mpc8xxx_cs *cs,
struct spi_device *spi,
int bits_per_word)
{
/* CPM/QE uses Little Endian for words > 8
* so transform 16 and 32 bits words into 8 bits
* Unfortnatly that doesn't work for LSB so
* reject these for now */
/* Note: 32 bits word, LSB works iff
* tfcr/rfcr is set to CPMFCR_GBL */
if (spi->mode & SPI_LSB_FIRST &&
bits_per_word > 8)
return -EINVAL;
if (bits_per_word <= 8)
return bits_per_word;
if (bits_per_word == 16 || bits_per_word == 32)
return 8; /* pretend its 8 bits */
return -EINVAL;
}
static int fsl_spi_setup_transfer(struct spi_device *spi,
struct spi_transfer *t)
{
@ -248,9 +228,6 @@ static int fsl_spi_setup_transfer(struct spi_device *spi,
bits_per_word = mspi_apply_cpu_mode_quirks(cs, spi,
mpc8xxx_spi,
bits_per_word);
else
bits_per_word = mspi_apply_qe_mode_quirks(cs, spi,
bits_per_word);
if (bits_per_word < 0)
return bits_per_word;
@ -357,12 +334,44 @@ static int fsl_spi_bufs(struct spi_device *spi, struct spi_transfer *t,
static int fsl_spi_do_one_msg(struct spi_master *master,
struct spi_message *m)
{
struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master);
struct spi_device *spi = m->spi;
struct spi_transfer *t, *first;
unsigned int cs_change;
const int nsecs = 50;
int status;
/*
* In CPU mode, optimize large byte transfers to use larger
* bits_per_word values to reduce number of interrupts taken.
*/
list_for_each_entry(t, &m->transfers, transfer_list) {
if (!(mpc8xxx_spi->flags & SPI_CPM_MODE)) {
if (t->len < 256 || t->bits_per_word != 8)
continue;
if ((t->len & 3) == 0)
t->bits_per_word = 32;
else if ((t->len & 1) == 0)
t->bits_per_word = 16;
} else {
/*
* CPM/QE uses Little Endian for words > 8
* so transform 16 and 32 bits words into 8 bits
* Unfortnatly that doesn't work for LSB so
* reject these for now
* Note: 32 bits word, LSB works iff
* tfcr/rfcr is set to CPMFCR_GBL
*/
if (m->spi->mode & SPI_LSB_FIRST && t->bits_per_word > 8)
return -EINVAL;
if (t->bits_per_word == 16 || t->bits_per_word == 32)
t->bits_per_word = 8; /* pretend its 8 bits */
if (t->bits_per_word == 8 && t->len >= 256 &&
(mpc8xxx_spi->flags & SPI_CPM1))
t->bits_per_word = 16;
}
}
/* Don't allow changes if CS is active */
first = list_first_entry(&m->transfers, struct spi_transfer,
transfer_list);
@ -642,8 +651,14 @@ static struct spi_master * fsl_spi_probe(struct device *dev,
if (mpc8xxx_spi->type == TYPE_GRLIB)
fsl_spi_grlib_probe(dev);
master->bits_per_word_mask =
(SPI_BPW_RANGE_MASK(4, 16) | SPI_BPW_MASK(32)) &
if (mpc8xxx_spi->flags & SPI_CPM_MODE)
master->bits_per_word_mask =
(SPI_BPW_RANGE_MASK(4, 8) | SPI_BPW_MASK(16) | SPI_BPW_MASK(32));
else
master->bits_per_word_mask =
(SPI_BPW_RANGE_MASK(4, 16) | SPI_BPW_MASK(32));
master->bits_per_word_mask &=
SPI_BPW_RANGE_MASK(1, mpc8xxx_spi->max_bits_per_word);
if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE)

View File

@ -241,6 +241,18 @@ static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi,
return true;
}
/*
* Note the number of natively supported chip selects for MX51 is 4. Some
* devices may have less actual SS pins but the register map supports 4. When
* using gpio chip selects the cs values passed into the macros below can go
* outside the range 0 - 3. We therefore need to limit the cs value to avoid
* corrupting bits outside the allocated locations.
*
* The simplest way to do this is to just mask the cs bits to 2 bits. This
* still allows all 4 native chip selects to work as well as gpio chip selects
* (which can use any of the 4 chip select configurations).
*/
#define MX51_ECSPI_CTRL 0x08
#define MX51_ECSPI_CTRL_ENABLE (1 << 0)
#define MX51_ECSPI_CTRL_XCH (1 << 2)
@ -249,16 +261,16 @@ static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi,
#define MX51_ECSPI_CTRL_DRCTL(drctl) ((drctl) << 16)
#define MX51_ECSPI_CTRL_POSTDIV_OFFSET 8
#define MX51_ECSPI_CTRL_PREDIV_OFFSET 12
#define MX51_ECSPI_CTRL_CS(cs) ((cs) << 18)
#define MX51_ECSPI_CTRL_CS(cs) ((cs & 3) << 18)
#define MX51_ECSPI_CTRL_BL_OFFSET 20
#define MX51_ECSPI_CTRL_BL_MASK (0xfff << 20)
#define MX51_ECSPI_CONFIG 0x0c
#define MX51_ECSPI_CONFIG_SCLKPHA(cs) (1 << ((cs) + 0))
#define MX51_ECSPI_CONFIG_SCLKPOL(cs) (1 << ((cs) + 4))
#define MX51_ECSPI_CONFIG_SBBCTRL(cs) (1 << ((cs) + 8))
#define MX51_ECSPI_CONFIG_SSBPOL(cs) (1 << ((cs) + 12))
#define MX51_ECSPI_CONFIG_SCLKCTL(cs) (1 << ((cs) + 20))
#define MX51_ECSPI_CONFIG_SCLKPHA(cs) (1 << ((cs & 3) + 0))
#define MX51_ECSPI_CONFIG_SCLKPOL(cs) (1 << ((cs & 3) + 4))
#define MX51_ECSPI_CONFIG_SBBCTRL(cs) (1 << ((cs & 3) + 8))
#define MX51_ECSPI_CONFIG_SSBPOL(cs) (1 << ((cs & 3) + 12))
#define MX51_ECSPI_CONFIG_SCLKCTL(cs) (1 << ((cs & 3) + 20))
#define MX51_ECSPI_INT 0x10
#define MX51_ECSPI_INT_TEEN (1 << 0)

View File

@ -61,9 +61,9 @@ static const struct rtl819x_ops rtl819xp_ops = {
};
static struct pci_device_id rtl8192_pci_id_tbl[] = {
{RTL_PCI_DEVICE(0x10ec, 0x8192, rtl819xp_ops)},
{RTL_PCI_DEVICE(0x07aa, 0x0044, rtl819xp_ops)},
{RTL_PCI_DEVICE(0x07aa, 0x0047, rtl819xp_ops)},
{PCI_DEVICE(0x10ec, 0x8192)},
{PCI_DEVICE(0x07aa, 0x0044)},
{PCI_DEVICE(0x07aa, 0x0047)},
{}
};

View File

@ -67,11 +67,6 @@
#define IS_HARDWARE_TYPE_8192SE(_priv) \
(((struct r8192_priv *)rtllib_priv(dev))->card_8192 == NIC_8192SE)
#define RTL_PCI_DEVICE(vend, dev, cfg) \
.vendor = (vend), .device = (dev), \
.subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, \
.driver_data = (kernel_ulong_t)&(cfg)
#define TOTAL_CAM_ENTRY 32
#define CAM_CONTENT_COUNT 8

View File

@ -1128,6 +1128,7 @@ void serial8250_unregister_port(int line)
uart->port.type = PORT_UNKNOWN;
uart->port.dev = &serial8250_isa_devs->dev;
uart->capabilities = 0;
serial8250_init_port(uart);
serial8250_apply_quirks(uart);
uart_add_one_port(&serial8250_reg, &uart->port);
} else {

View File

@ -1651,6 +1651,8 @@ pci_wch_ch38x_setup(struct serial_private *priv,
#define PCI_SUBDEVICE_ID_SIIG_DUAL_30 0x2530
#define PCI_VENDOR_ID_ADVANTECH 0x13fe
#define PCI_DEVICE_ID_INTEL_CE4100_UART 0x2e66
#define PCI_DEVICE_ID_ADVANTECH_PCI1600 0x1600
#define PCI_DEVICE_ID_ADVANTECH_PCI1600_1611 0x1611
#define PCI_DEVICE_ID_ADVANTECH_PCI3620 0x3620
#define PCI_DEVICE_ID_ADVANTECH_PCI3618 0x3618
#define PCI_DEVICE_ID_ADVANTECH_PCIf618 0xf618
@ -3851,6 +3853,9 @@ static SIMPLE_DEV_PM_OPS(pciserial_pm_ops, pciserial_suspend_one,
pciserial_resume_one);
static const struct pci_device_id serial_pci_tbl[] = {
{ PCI_VENDOR_ID_ADVANTECH, PCI_DEVICE_ID_ADVANTECH_PCI1600,
PCI_DEVICE_ID_ADVANTECH_PCI1600_1611, PCI_ANY_ID, 0, 0,
pbn_b0_4_921600 },
/* Advantech use PCI_DEVICE_ID_ADVANTECH_PCI3620 (0x3620) as 'PCI_SUBVENDOR_ID' */
{ PCI_VENDOR_ID_ADVANTECH, PCI_DEVICE_ID_ADVANTECH_PCI3620,
PCI_DEVICE_ID_ADVANTECH_PCI3620, 0x0001, 0, 0,

View File

@ -209,6 +209,82 @@ int usb_find_common_endpoints_reverse(struct usb_host_interface *alt,
}
EXPORT_SYMBOL_GPL(usb_find_common_endpoints_reverse);
/**
* usb_find_endpoint() - Given an endpoint address, search for the endpoint's
* usb_host_endpoint structure in an interface's current altsetting.
* @intf: the interface whose current altsetting should be searched
* @ep_addr: the endpoint address (number and direction) to find
*
* Search the altsetting's list of endpoints for one with the specified address.
*
* Return: Pointer to the usb_host_endpoint if found, %NULL otherwise.
*/
static const struct usb_host_endpoint *usb_find_endpoint(
const struct usb_interface *intf, unsigned int ep_addr)
{
int n;
const struct usb_host_endpoint *ep;
n = intf->cur_altsetting->desc.bNumEndpoints;
ep = intf->cur_altsetting->endpoint;
for (; n > 0; (--n, ++ep)) {
if (ep->desc.bEndpointAddress == ep_addr)
return ep;
}
return NULL;
}
/**
* usb_check_bulk_endpoints - Check whether an interface's current altsetting
* contains a set of bulk endpoints with the given addresses.
* @intf: the interface whose current altsetting should be searched
* @ep_addrs: 0-terminated array of the endpoint addresses (number and
* direction) to look for
*
* Search for endpoints with the specified addresses and check their types.
*
* Return: %true if all the endpoints are found and are bulk, %false otherwise.
*/
bool usb_check_bulk_endpoints(
const struct usb_interface *intf, const u8 *ep_addrs)
{
const struct usb_host_endpoint *ep;
for (; *ep_addrs; ++ep_addrs) {
ep = usb_find_endpoint(intf, *ep_addrs);
if (!ep || !usb_endpoint_xfer_bulk(&ep->desc))
return false;
}
return true;
}
EXPORT_SYMBOL_GPL(usb_check_bulk_endpoints);
/**
* usb_check_int_endpoints - Check whether an interface's current altsetting
* contains a set of interrupt endpoints with the given addresses.
* @intf: the interface whose current altsetting should be searched
* @ep_addrs: 0-terminated array of the endpoint addresses (number and
* direction) to look for
*
* Search for endpoints with the specified addresses and check their types.
*
* Return: %true if all the endpoints are found and are interrupt,
* %false otherwise.
*/
bool usb_check_int_endpoints(
const struct usb_interface *intf, const u8 *ep_addrs)
{
const struct usb_host_endpoint *ep;
for (; *ep_addrs; ++ep_addrs) {
ep = usb_find_endpoint(intf, *ep_addrs);
if (!ep || !usb_endpoint_xfer_int(&ep->desc))
return false;
}
return true;
}
EXPORT_SYMBOL_GPL(usb_check_int_endpoints);
/**
* usb_find_alt_setting() - Given a configuration, find the alternate setting
* for the given interface.

View File

@ -3015,6 +3015,20 @@ static int sisusb_probe(struct usb_interface *intf,
struct usb_device *dev = interface_to_usbdev(intf);
struct sisusb_usb_data *sisusb;
int retval = 0, i;
static const u8 ep_addresses[] = {
SISUSB_EP_GFX_IN | USB_DIR_IN,
SISUSB_EP_GFX_OUT | USB_DIR_OUT,
SISUSB_EP_GFX_BULK_OUT | USB_DIR_OUT,
SISUSB_EP_GFX_LBULK_OUT | USB_DIR_OUT,
SISUSB_EP_BRIDGE_IN | USB_DIR_IN,
SISUSB_EP_BRIDGE_OUT | USB_DIR_OUT,
0};
/* Are the expected endpoints present? */
if (!usb_check_bulk_endpoints(intf, ep_addresses)) {
dev_err(&intf->dev, "Invalid USB2VGA device\n");
return -EINVAL;
}
dev_info(&dev->dev, "USB2VGA dongle found at address %d\n",
dev->devnum);

View File

@ -408,22 +408,25 @@ static DEF_SCSI_QCMD(queuecommand)
***********************************************************************/
/* Command timeout and abort */
static int command_abort(struct scsi_cmnd *srb)
static int command_abort_matching(struct us_data *us, struct scsi_cmnd *srb_match)
{
struct us_data *us = host_to_us(srb->device->host);
usb_stor_dbg(us, "%s called\n", __func__);
/*
* us->srb together with the TIMED_OUT, RESETTING, and ABORTING
* bits are protected by the host lock.
*/
scsi_lock(us_to_host(us));
/* Is this command still active? */
if (us->srb != srb) {
/* is there any active pending command to abort ? */
if (!us->srb) {
scsi_unlock(us_to_host(us));
usb_stor_dbg(us, "-- nothing to abort\n");
return SUCCESS;
}
/* Does the command match the passed srb if any ? */
if (srb_match && us->srb != srb_match) {
scsi_unlock(us_to_host(us));
usb_stor_dbg(us, "-- pending command mismatch\n");
return FAILED;
}
@ -446,6 +449,14 @@ static int command_abort(struct scsi_cmnd *srb)
return SUCCESS;
}
static int command_abort(struct scsi_cmnd *srb)
{
struct us_data *us = host_to_us(srb->device->host);
usb_stor_dbg(us, "%s called\n", __func__);
return command_abort_matching(us, srb);
}
/*
* This invokes the transport reset mechanism to reset the state of the
* device
@ -457,6 +468,9 @@ static int device_reset(struct scsi_cmnd *srb)
usb_stor_dbg(us, "%s called\n", __func__);
/* abort any pending command before reset */
command_abort_matching(us, NULL);
/* lock the device pointers and do the reset */
mutex_lock(&(us->dev_mutex));
result = us->transport_reset(us);

View File

@ -338,8 +338,10 @@ static struct sock_mapping *pvcalls_new_active_socket(
void *page;
map = kzalloc(sizeof(*map), GFP_KERNEL);
if (map == NULL)
if (map == NULL) {
sock_release(sock);
return NULL;
}
map->fedata = fedata;
map->sock = sock;
@ -431,10 +433,8 @@ static int pvcalls_back_connect(struct xenbus_device *dev,
req->u.connect.ref,
req->u.connect.evtchn,
sock);
if (!map) {
if (!map)
ret = -EFAULT;
sock_release(sock);
}
out:
rsp = RING_GET_RESPONSE(&fedata->ring, fedata->ring.rsp_prod_pvt++);
@ -575,7 +575,6 @@ static void __pvcalls_back_accept(struct work_struct *work)
sock);
if (!map) {
ret = -EFAULT;
sock_release(sock);
goto out_error;
}

View File

@ -959,6 +959,19 @@ skip_inode:
continue;
adjust_snap_realm_parent(mdsc, child, realm->ino);
}
} else {
/*
* In the non-split case both 'num_split_inos' and
* 'num_split_realms' should be 0, making this a no-op.
* However the MDS happens to populate 'split_realms' list
* in one of the UPDATE op cases by mistake.
*
* Skip both lists just in case to ensure that 'p' is
* positioned at the start of realm info, as expected by
* ceph_update_snap_trace().
*/
p += sizeof(u64) * num_split_inos;
p += sizeof(u64) * num_split_realms;
}
/*

View File

@ -177,6 +177,7 @@ static inline struct ext2_sb_info *EXT2_SB(struct super_block *sb)
#define EXT2_MIN_BLOCK_SIZE 1024
#define EXT2_MAX_BLOCK_SIZE 4096
#define EXT2_MIN_BLOCK_LOG_SIZE 10
#define EXT2_MAX_BLOCK_LOG_SIZE 16
#define EXT2_BLOCK_SIZE(s) ((s)->s_blocksize)
#define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (__u32))
#define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits)

View File

@ -965,6 +965,13 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
goto failed_mount;
}
if (le32_to_cpu(es->s_log_block_size) >
(EXT2_MAX_BLOCK_LOG_SIZE - BLOCK_SIZE_BITS)) {
ext2_msg(sb, KERN_ERR,
"Invalid log block size: %u",
le32_to_cpu(es->s_log_block_size));
goto failed_mount;
}
blocksize = BLOCK_SIZE << le32_to_cpu(sbi->s_es->s_log_block_size);
if (sbi->s_mount_opt & EXT2_MOUNT_DAX) {

View File

@ -3116,6 +3116,7 @@ ext4_mb_normalize_request(struct ext4_allocation_context *ac,
struct ext4_allocation_request *ar)
{
struct ext4_sb_info *sbi = EXT4_SB(ac->ac_sb);
struct ext4_super_block *es = sbi->s_es;
int bsbits, max;
ext4_lblk_t end;
loff_t size, start_off;
@ -3296,18 +3297,21 @@ ext4_mb_normalize_request(struct ext4_allocation_context *ac,
ac->ac_g_ex.fe_len = EXT4_NUM_B2C(sbi, size);
/* define goal start in order to merge */
if (ar->pright && (ar->lright == (start + size))) {
if (ar->pright && (ar->lright == (start + size)) &&
ar->pright >= size &&
ar->pright - size >= le32_to_cpu(es->s_first_data_block)) {
/* merge to the right */
ext4_get_group_no_and_offset(ac->ac_sb, ar->pright - size,
&ac->ac_f_ex.fe_group,
&ac->ac_f_ex.fe_start);
&ac->ac_g_ex.fe_group,
&ac->ac_g_ex.fe_start);
ac->ac_flags |= EXT4_MB_HINT_TRY_GOAL;
}
if (ar->pleft && (ar->lleft + 1 == start)) {
if (ar->pleft && (ar->lleft + 1 == start) &&
ar->pleft + 1 < ext4_blocks_count(es)) {
/* merge to the left */
ext4_get_group_no_and_offset(ac->ac_sb, ar->pleft + 1,
&ac->ac_f_ex.fe_group,
&ac->ac_f_ex.fe_start);
&ac->ac_g_ex.fe_group,
&ac->ac_g_ex.fe_start);
ac->ac_flags |= EXT4_MB_HINT_TRY_GOAL;
}
@ -3399,6 +3403,7 @@ static void ext4_mb_use_inode_pa(struct ext4_allocation_context *ac,
BUG_ON(start < pa->pa_pstart);
BUG_ON(end > pa->pa_pstart + EXT4_C2B(sbi, pa->pa_len));
BUG_ON(pa->pa_free < len);
BUG_ON(ac->ac_b_ex.fe_len <= 0);
pa->pa_free -= len;
mb_debug(1, "use %llu/%u from inode pa %p\n", start, len, pa);
@ -3703,10 +3708,8 @@ ext4_mb_new_inode_pa(struct ext4_allocation_context *ac)
return -ENOMEM;
if (ac->ac_b_ex.fe_len < ac->ac_g_ex.fe_len) {
int winl;
int wins;
int win;
int offs;
int new_bex_start;
int new_bex_end;
/* we can't allocate as much as normalizer wants.
* so, found space must get proper lstart
@ -3714,26 +3717,40 @@ ext4_mb_new_inode_pa(struct ext4_allocation_context *ac)
BUG_ON(ac->ac_g_ex.fe_logical > ac->ac_o_ex.fe_logical);
BUG_ON(ac->ac_g_ex.fe_len < ac->ac_o_ex.fe_len);
/* we're limited by original request in that
* logical block must be covered any way
* winl is window we can move our chunk within */
winl = ac->ac_o_ex.fe_logical - ac->ac_g_ex.fe_logical;
/*
* Use the below logic for adjusting best extent as it keeps
* fragmentation in check while ensuring logical range of best
* extent doesn't overflow out of goal extent:
*
* 1. Check if best ex can be kept at end of goal and still
* cover original start
* 2. Else, check if best ex can be kept at start of goal and
* still cover original start
* 3. Else, keep the best ex at start of original request.
*/
new_bex_end = ac->ac_g_ex.fe_logical +
EXT4_C2B(sbi, ac->ac_g_ex.fe_len);
new_bex_start = new_bex_end - EXT4_C2B(sbi, ac->ac_b_ex.fe_len);
if (ac->ac_o_ex.fe_logical >= new_bex_start)
goto adjust_bex;
/* also, we should cover whole original request */
wins = EXT4_C2B(sbi, ac->ac_b_ex.fe_len - ac->ac_o_ex.fe_len);
new_bex_start = ac->ac_g_ex.fe_logical;
new_bex_end =
new_bex_start + EXT4_C2B(sbi, ac->ac_b_ex.fe_len);
if (ac->ac_o_ex.fe_logical < new_bex_end)
goto adjust_bex;
/* the smallest one defines real window */
win = min(winl, wins);
new_bex_start = ac->ac_o_ex.fe_logical;
new_bex_end =
new_bex_start + EXT4_C2B(sbi, ac->ac_b_ex.fe_len);
offs = ac->ac_o_ex.fe_logical %
EXT4_C2B(sbi, ac->ac_b_ex.fe_len);
if (offs && offs < win)
win = offs;
adjust_bex:
ac->ac_b_ex.fe_logical = new_bex_start;
ac->ac_b_ex.fe_logical = ac->ac_o_ex.fe_logical -
EXT4_NUM_B2C(sbi, win);
BUG_ON(ac->ac_o_ex.fe_logical < ac->ac_b_ex.fe_logical);
BUG_ON(ac->ac_o_ex.fe_len > ac->ac_b_ex.fe_len);
BUG_ON(new_bex_end > (ac->ac_g_ex.fe_logical +
EXT4_C2B(sbi, ac->ac_g_ex.fe_len)));
}
/* preallocation can change ac_b_ex, thus we store actually

View File

@ -333,6 +333,7 @@ static int inode_go_demote_ok(const struct gfs2_glock *gl)
static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
{
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
const struct gfs2_dinode *str = buf;
struct timespec atime;
u16 height, depth;
@ -372,7 +373,7 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
/* i_diskflags and i_eattr must be set before gfs2_set_inode_flags() */
gfs2_set_inode_flags(&ip->i_inode);
height = be16_to_cpu(str->di_height);
if (unlikely(height > GFS2_MAX_META_HEIGHT))
if (unlikely(height > sdp->sd_max_height))
goto corrupt;
ip->i_height = (u8)height;

View File

@ -488,7 +488,11 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
if (type == HFSPLUS_FOLDER) {
struct hfsplus_cat_folder *folder = &entry.folder;
WARN_ON(fd->entrylength < sizeof(struct hfsplus_cat_folder));
if (fd->entrylength < sizeof(struct hfsplus_cat_folder)) {
pr_err("bad catalog folder entry\n");
res = -EIO;
goto out;
}
hfs_bnode_read(fd->bnode, &entry, fd->entryoffset,
sizeof(struct hfsplus_cat_folder));
hfsplus_get_perms(inode, &folder->permissions, 1);
@ -508,7 +512,11 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
} else if (type == HFSPLUS_FILE) {
struct hfsplus_cat_file *file = &entry.file;
WARN_ON(fd->entrylength < sizeof(struct hfsplus_cat_file));
if (fd->entrylength < sizeof(struct hfsplus_cat_file)) {
pr_err("bad catalog file entry\n");
res = -EIO;
goto out;
}
hfs_bnode_read(fd->bnode, &entry, fd->entryoffset,
sizeof(struct hfsplus_cat_file));
@ -539,6 +547,7 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
pr_err("bad catalog entry used to create inode\n");
res = -EIO;
}
out:
return res;
}
@ -547,6 +556,7 @@ int hfsplus_cat_write_inode(struct inode *inode)
struct inode *main_inode = inode;
struct hfs_find_data fd;
hfsplus_cat_entry entry;
int res = 0;
if (HFSPLUS_IS_RSRC(inode))
main_inode = HFSPLUS_I(inode)->rsrc_inode;
@ -565,7 +575,11 @@ int hfsplus_cat_write_inode(struct inode *inode)
if (S_ISDIR(main_inode->i_mode)) {
struct hfsplus_cat_folder *folder = &entry.folder;
WARN_ON(fd.entrylength < sizeof(struct hfsplus_cat_folder));
if (fd.entrylength < sizeof(struct hfsplus_cat_folder)) {
pr_err("bad catalog folder entry\n");
res = -EIO;
goto out;
}
hfs_bnode_read(fd.bnode, &entry, fd.entryoffset,
sizeof(struct hfsplus_cat_folder));
/* simple node checks? */
@ -590,7 +604,11 @@ int hfsplus_cat_write_inode(struct inode *inode)
} else {
struct hfsplus_cat_file *file = &entry.file;
WARN_ON(fd.entrylength < sizeof(struct hfsplus_cat_file));
if (fd.entrylength < sizeof(struct hfsplus_cat_file)) {
pr_err("bad catalog file entry\n");
res = -EIO;
goto out;
}
hfs_bnode_read(fd.bnode, &entry, fd.entryoffset,
sizeof(struct hfsplus_cat_file));
hfsplus_inode_write_fork(inode, &file->data_fork);
@ -611,5 +629,5 @@ int hfsplus_cat_write_inode(struct inode *inode)
set_bit(HFSPLUS_I_CAT_DIRTY, &HFSPLUS_I(inode)->flags);
out:
hfs_find_exit(&fd);
return 0;
return res;
}

View File

@ -939,6 +939,7 @@ void nilfs_evict_inode(struct inode *inode)
struct nilfs_transaction_info ti;
struct super_block *sb = inode->i_sb;
struct nilfs_inode_info *ii = NILFS_I(inode);
struct the_nilfs *nilfs;
int ret;
if (inode->i_nlink || !ii->i_root || unlikely(is_bad_inode(inode))) {
@ -951,6 +952,23 @@ void nilfs_evict_inode(struct inode *inode)
truncate_inode_pages_final(&inode->i_data);
nilfs = sb->s_fs_info;
if (unlikely(sb_rdonly(sb) || !nilfs->ns_writer)) {
/*
* If this inode is about to be disposed after the file system
* has been degraded to read-only due to file system corruption
* or after the writer has been detached, do not make any
* changes that cause writes, just clear it.
* Do this check after read-locking ns_segctor_sem by
* nilfs_transaction_begin() in order to avoid a race with
* the writer detach operation.
*/
clear_inode(inode);
nilfs_clear_inode(inode);
nilfs_transaction_abort(sb);
return;
}
/* TODO: some of the following operations may fail. */
nilfs_truncate_bmap(ii, 0);
nilfs_mark_inode_dirty(inode);

View File

@ -114,6 +114,7 @@ static int do_statfs_native(struct kstatfs *st, struct statfs __user *p)
if (sizeof(buf) == sizeof(*st))
memcpy(&buf, st, sizeof(*st));
else {
memset(&buf, 0, sizeof(buf));
if (sizeof buf.f_blocks == 4) {
if ((st->f_blocks | st->f_bfree | st->f_bavail |
st->f_bsize | st->f_frsize) &
@ -142,7 +143,6 @@ static int do_statfs_native(struct kstatfs *st, struct statfs __user *p)
buf.f_namelen = st->f_namelen;
buf.f_frsize = st->f_frsize;
buf.f_flags = st->f_flags;
memset(buf.f_spare, 0, sizeof(buf.f_spare));
}
if (copy_to_user(p, &buf, sizeof(buf)))
return -EFAULT;
@ -155,6 +155,7 @@ static int do_statfs64(struct kstatfs *st, struct statfs64 __user *p)
if (sizeof(buf) == sizeof(*st))
memcpy(&buf, st, sizeof(*st));
else {
memset(&buf, 0, sizeof(buf));
buf.f_type = st->f_type;
buf.f_bsize = st->f_bsize;
buf.f_blocks = st->f_blocks;
@ -166,7 +167,6 @@ static int do_statfs64(struct kstatfs *st, struct statfs64 __user *p)
buf.f_namelen = st->f_namelen;
buf.f_frsize = st->f_frsize;
buf.f_flags = st->f_flags;
memset(buf.f_spare, 0, sizeof(buf.f_spare));
}
if (copy_to_user(p, &buf, sizeof(buf)))
return -EFAULT;

View File

@ -61,6 +61,7 @@ struct bq27xxx_device_info {
struct bq27xxx_access_methods bus;
struct bq27xxx_reg_cache cache;
int charge_design_full;
bool removed;
unsigned long last_update;
struct delayed_work work;
struct power_supply *bat;

View File

@ -23,7 +23,7 @@ static inline void *task_stack_page(const struct task_struct *task)
#define setup_thread_stack(new,old) do { } while(0)
static inline unsigned long *end_of_stack(const struct task_struct *task)
static __always_inline unsigned long *end_of_stack(const struct task_struct *task)
{
#ifdef CONFIG_STACK_GROWSUP
return (unsigned long *)((unsigned long)task->stack + THREAD_SIZE) - 1;

View File

@ -279,6 +279,11 @@ void usb_put_intf(struct usb_interface *intf);
#define USB_MAXINTERFACES 32
#define USB_MAXIADS (USB_MAXINTERFACES/2)
bool usb_check_bulk_endpoints(
const struct usb_interface *intf, const u8 *ep_addrs);
bool usb_check_int_endpoints(
const struct usb_interface *intf, const u8 *ep_addrs);
/*
* USB Resume Timer: Every Host controller driver should drive the resume
* signalling on the bus for the amount of time defined by this macro.

View File

@ -195,14 +195,13 @@ static inline enum nft_registers nft_type_to_reg(enum nft_data_types type)
}
int nft_parse_u32_check(const struct nlattr *attr, int max, u32 *dest);
unsigned int nft_parse_register(const struct nlattr *attr);
int nft_dump_register(struct sk_buff *skb, unsigned int attr, unsigned int reg);
int nft_validate_register_load(enum nft_registers reg, unsigned int len);
int nft_validate_register_store(const struct nft_ctx *ctx,
enum nft_registers reg,
const struct nft_data *data,
enum nft_data_types type, unsigned int len);
int nft_parse_register_load(const struct nlattr *attr, u8 *sreg, u32 len);
int nft_parse_register_store(const struct nft_ctx *ctx,
const struct nlattr *attr, u8 *dreg,
const struct nft_data *data,
enum nft_data_types type, unsigned int len);
/**
* struct nft_userdata - user defined data associated with an object
@ -230,6 +229,10 @@ struct nft_set_elem {
u32 buf[NFT_DATA_VALUE_MAXLEN / sizeof(u32)];
struct nft_data val;
} key;
union {
u32 buf[NFT_DATA_VALUE_MAXLEN / sizeof(u32)];
struct nft_data val;
} data;
void *priv;
};
@ -378,6 +381,7 @@ void nft_unregister_set(struct nft_set_type *type);
*
* @list: table set list node
* @bindings: list of set bindings
* @table: table this set belongs to
* @name: name of the set
* @ktype: key type (numeric type defined by userspace, not used in the kernel)
* @dtype: data type (verdict or numeric type defined by userspace)
@ -401,6 +405,7 @@ void nft_unregister_set(struct nft_set_type *type);
struct nft_set {
struct list_head list;
struct list_head bindings;
struct nft_table *table;
char *name;
u32 ktype;
u32 dtype;

View File

@ -14,9 +14,17 @@ extern struct nft_expr_type nft_range_type;
int nf_tables_core_module_init(void);
void nf_tables_core_module_exit(void);
struct nft_bitwise_fast_expr {
u32 mask;
u32 xor;
u8 sreg;
u8 dreg;
};
struct nft_cmp_fast_expr {
u32 data;
enum nft_registers sreg:8;
u32 mask;
u8 sreg;
u8 len;
};
@ -36,14 +44,14 @@ struct nft_payload {
enum nft_payload_bases base:8;
u8 offset;
u8 len;
enum nft_registers dreg:8;
u8 dreg;
};
struct nft_payload_set {
enum nft_payload_bases base:8;
u8 offset;
u8 len;
enum nft_registers sreg:8;
u8 sreg;
u8 csum_type;
u8 csum_offset;
u8 csum_flags;

View File

@ -3,7 +3,7 @@
#define _NFT_FIB_H_
struct nft_fib {
enum nft_registers dreg:8;
u8 dreg;
u8 result;
u32 flags;
};

View File

@ -4,8 +4,8 @@
struct nft_masq {
u32 flags;
enum nft_registers sreg_proto_min:8;
enum nft_registers sreg_proto_max:8;
u8 sreg_proto_min;
u8 sreg_proto_max;
};
extern const struct nla_policy nft_masq_policy[];

View File

@ -5,8 +5,8 @@
struct nft_meta {
enum nft_meta_keys key:8;
union {
enum nft_registers dreg:8;
enum nft_registers sreg:8;
u8 dreg;
u8 sreg;
};
};

View File

@ -3,8 +3,8 @@
#define _NFT_REDIR_H_
struct nft_redir {
enum nft_registers sreg_proto_min:8;
enum nft_registers sreg_proto_max:8;
u8 sreg_proto_min;
u8 sreg_proto_max;
u16 flags;
};

View File

@ -2317,7 +2317,7 @@ static inline void sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk,
__sock_recv_ts_and_drops(msg, sk, skb);
else if (unlikely(sock_flag(sk, SOCK_TIMESTAMP)))
sock_write_timestamp(sk, skb->tstamp);
else if (unlikely(sk->sk_stamp == SK_DEFAULT_STAMP))
else if (unlikely(sock_read_timestamp(sk) == SK_DEFAULT_STAMP))
sock_write_timestamp(sk, 0);
}

View File

@ -258,7 +258,7 @@ enum nft_rule_compat_attributes {
* @NFT_SET_INTERVAL: set contains intervals
* @NFT_SET_MAP: set is used as a dictionary
* @NFT_SET_TIMEOUT: set uses timeouts
* @NFT_SET_EVAL: set contains expressions for evaluation
* @NFT_SET_EVAL: set can be updated from the evaluation path
* @NFT_SET_OBJECT: set contains stateful objects
*/
enum nft_set_flags {

View File

@ -235,7 +235,8 @@ void free_irq_cpu_rmap(struct cpu_rmap *rmap)
for (index = 0; index < rmap->used; index++) {
glue = rmap->obj[index];
irq_set_affinity_notifier(glue->notify.irq, NULL);
if (glue)
irq_set_affinity_notifier(glue->notify.irq, NULL);
}
cpu_rmap_put(rmap);
@ -271,6 +272,7 @@ static void irq_cpu_rmap_release(struct kref *ref)
container_of(ref, struct irq_glue, notify.kref);
cpu_rmap_put(glue->rmap);
glue->rmap->obj[glue->index] = NULL;
kfree(glue);
}
@ -300,6 +302,7 @@ int irq_cpu_rmap_add(struct cpu_rmap *rmap, int irq)
rc = irq_set_affinity_notifier(irq, &glue->notify);
if (rc) {
cpu_rmap_put(glue->rmap);
rmap->obj[glue->index] = NULL;
kfree(glue);
}
return rc;

View File

@ -115,8 +115,8 @@ static netdev_tx_t vlan_dev_hard_start_xmit(struct sk_buff *skb,
* NOTE: THIS ASSUMES DIX ETHERNET, SPECIFICALLY NOT SUPPORTING
* OTHER THINGS LIKE FDDI/TokenRing/802.3 SNAPs...
*/
if (veth->h_vlan_proto != vlan->vlan_proto ||
vlan->flags & VLAN_FLAG_REORDER_HDR) {
if (vlan->flags & VLAN_FLAG_REORDER_HDR ||
veth->h_vlan_proto != vlan->vlan_proto) {
u16 vlan_tci;
vlan_tci = vlan->vlan_id;
vlan_tci |= vlan_dev_get_egress_qos_mask(dev, skb->priority);

View File

@ -4392,7 +4392,6 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn,
chan = l2cap_get_chan_by_scid(conn, scid);
if (!chan) {
mutex_unlock(&conn->chan_lock);
return 0;
}

View File

@ -65,9 +65,8 @@ static int nft_meta_bridge_get_init(const struct nft_ctx *ctx,
return nft_meta_get_init(ctx, expr, tb);
}
priv->dreg = nft_parse_register(tb[NFTA_META_DREG]);
return nft_validate_register_store(ctx, priv->dreg, NULL,
NFT_DATA_VALUE, len);
return nft_parse_register_store(ctx, tb[NFTA_META_DREG], &priv->dreg,
NULL, NFT_DATA_VALUE, len);
}
static struct nft_expr_type nft_meta_bridge_type;

View File

@ -2165,6 +2165,8 @@ int netif_set_xps_queue(struct net_device *dev, const struct cpumask *mask,
struct xps_map *map, *new_map;
bool active = false;
WARN_ON_ONCE(index >= dev->num_tx_queues);
if (dev->num_tc) {
num_tc = dev->num_tc;
tc = netdev_txq_to_tc(dev, index);

View File

@ -4421,8 +4421,10 @@ void __skb_tstamp_tx(struct sk_buff *orig_skb,
} else {
skb = skb_clone(orig_skb, GFP_ATOMIC);
if (skb_orphan_frags_rx(skb, GFP_ATOMIC))
if (skb_orphan_frags_rx(skb, GFP_ATOMIC)) {
kfree_skb(skb);
return;
}
}
if (!skb)
return;

View File

@ -16,8 +16,8 @@
#include <net/netfilter/ipv4/nf_dup_ipv4.h>
struct nft_dup_ipv4 {
enum nft_registers sreg_addr:8;
enum nft_registers sreg_dev:8;
u8 sreg_addr;
u8 sreg_dev;
};
static void nft_dup_ipv4_eval(const struct nft_expr *expr,
@ -43,16 +43,16 @@ static int nft_dup_ipv4_init(const struct nft_ctx *ctx,
if (tb[NFTA_DUP_SREG_ADDR] == NULL)
return -EINVAL;
priv->sreg_addr = nft_parse_register(tb[NFTA_DUP_SREG_ADDR]);
err = nft_validate_register_load(priv->sreg_addr, sizeof(struct in_addr));
err = nft_parse_register_load(tb[NFTA_DUP_SREG_ADDR], &priv->sreg_addr,
sizeof(struct in_addr));
if (err < 0)
return err;
if (tb[NFTA_DUP_SREG_DEV] != NULL) {
priv->sreg_dev = nft_parse_register(tb[NFTA_DUP_SREG_DEV]);
return nft_validate_register_load(priv->sreg_dev, sizeof(int));
}
return 0;
if (tb[NFTA_DUP_SREG_DEV])
err = nft_parse_register_load(tb[NFTA_DUP_SREG_DEV],
&priv->sreg_dev, sizeof(int));
return err;
}
static int nft_dup_ipv4_dump(struct sk_buff *skb, const struct nft_expr *expr)

View File

@ -142,6 +142,8 @@ int ipv6_find_tlv(const struct sk_buff *skb, int offset, int type)
optlen = 1;
break;
default:
if (len < 2)
goto bad;
optlen = nh[offset + 1] + 2;
if (optlen > len)
goto bad;

View File

@ -16,8 +16,8 @@
#include <net/netfilter/ipv6/nf_dup_ipv6.h>
struct nft_dup_ipv6 {
enum nft_registers sreg_addr:8;
enum nft_registers sreg_dev:8;
u8 sreg_addr;
u8 sreg_dev;
};
static void nft_dup_ipv6_eval(const struct nft_expr *expr,
@ -41,16 +41,16 @@ static int nft_dup_ipv6_init(const struct nft_ctx *ctx,
if (tb[NFTA_DUP_SREG_ADDR] == NULL)
return -EINVAL;
priv->sreg_addr = nft_parse_register(tb[NFTA_DUP_SREG_ADDR]);
err = nft_validate_register_load(priv->sreg_addr, sizeof(struct in6_addr));
err = nft_parse_register_load(tb[NFTA_DUP_SREG_ADDR], &priv->sreg_addr,
sizeof(struct in6_addr));
if (err < 0)
return err;
if (tb[NFTA_DUP_SREG_DEV] != NULL) {
priv->sreg_dev = nft_parse_register(tb[NFTA_DUP_SREG_DEV]);
return nft_validate_register_load(priv->sreg_dev, sizeof(int));
}
return 0;
if (tb[NFTA_DUP_SREG_DEV])
err = nft_parse_register_load(tb[NFTA_DUP_SREG_DEV],
&priv->sreg_dev, sizeof(int));
return err;
}
static int nft_dup_ipv6_dump(struct sk_buff *skb, const struct nft_expr *expr)

View File

@ -1950,7 +1950,8 @@ static u32 gen_reqid(struct net *net)
}
static int
parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_ipsecrequest *rq)
parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_policy *pol,
struct sadb_x_ipsecrequest *rq)
{
struct net *net = xp_net(xp);
struct xfrm_tmpl *t = xp->xfrm_vec + xp->xfrm_nr;
@ -1968,9 +1969,12 @@ parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_ipsecrequest *rq)
if ((mode = pfkey_mode_to_xfrm(rq->sadb_x_ipsecrequest_mode)) < 0)
return -EINVAL;
t->mode = mode;
if (rq->sadb_x_ipsecrequest_level == IPSEC_LEVEL_USE)
if (rq->sadb_x_ipsecrequest_level == IPSEC_LEVEL_USE) {
if ((mode == XFRM_MODE_TUNNEL || mode == XFRM_MODE_BEET) &&
pol->sadb_x_policy_dir == IPSEC_DIR_OUTBOUND)
return -EINVAL;
t->optional = 1;
else if (rq->sadb_x_ipsecrequest_level == IPSEC_LEVEL_UNIQUE) {
} else if (rq->sadb_x_ipsecrequest_level == IPSEC_LEVEL_UNIQUE) {
t->reqid = rq->sadb_x_ipsecrequest_reqid;
if (t->reqid > IPSEC_MANUAL_REQID_MAX)
t->reqid = 0;
@ -2012,7 +2016,7 @@ parse_ipsecrequests(struct xfrm_policy *xp, struct sadb_x_policy *pol)
rq->sadb_x_ipsecrequest_len < sizeof(*rq))
return -EINVAL;
if ((err = parse_ipsecrequest(xp, rq)) < 0)
if ((err = parse_ipsecrequest(xp, pol, rq)) < 0)
return err;
len -= rq->sadb_x_ipsecrequest_len;
rq = (void*)((u8*)rq + rq->sadb_x_ipsecrequest_len);

View File

@ -2475,6 +2475,7 @@ err1:
}
static struct nft_rule *nft_rule_lookup_byid(const struct net *net,
const struct nft_chain *chain,
const struct nlattr *nla)
{
u32 id = ntohl(nla_get_be32(nla));
@ -2484,6 +2485,7 @@ static struct nft_rule *nft_rule_lookup_byid(const struct net *net,
struct nft_rule *rule = nft_trans_rule(trans);
if (trans->msg_type == NFT_MSG_NEWRULE &&
trans->ctx.chain == chain &&
id == nft_trans_rule_id(trans))
return rule;
}
@ -2530,7 +2532,7 @@ static int nf_tables_delrule(struct net *net, struct sock *nlsk,
err = nft_delrule(&ctx, rule);
} else if (nla[NFTA_RULE_ID]) {
rule = nft_rule_lookup_byid(net, nla[NFTA_RULE_ID]);
rule = nft_rule_lookup_byid(net, chain, nla[NFTA_RULE_ID]);
if (IS_ERR(rule))
return PTR_ERR(rule);
@ -2744,6 +2746,7 @@ static struct nft_set *nf_tables_set_lookup(const struct nft_table *table,
}
static struct nft_set *nf_tables_set_lookup_byid(const struct net *net,
const struct nft_table *table,
const struct nlattr *nla,
u8 genmask)
{
@ -2755,6 +2758,7 @@ static struct nft_set *nf_tables_set_lookup_byid(const struct net *net,
struct nft_set *set = nft_trans_set(trans);
if (id == nft_trans_set_id(trans) &&
set->table == table &&
nft_active_genmask(set, genmask))
return set;
}
@ -2775,7 +2779,7 @@ struct nft_set *nft_set_lookup(const struct net *net,
if (!nla_set_id)
return set;
set = nf_tables_set_lookup_byid(net, nla_set_id, genmask);
set = nf_tables_set_lookup_byid(net, table, nla_set_id, genmask);
}
return set;
}
@ -3270,6 +3274,7 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
}
INIT_LIST_HEAD(&set->bindings);
set->table = table;
set->ops = ops;
set->ktype = ktype;
set->klen = desc.klen;
@ -3349,6 +3354,12 @@ static int nf_tables_delset(struct net *net, struct sock *nlsk,
return nft_delset(&ctx, set);
}
static int nft_validate_register_store(const struct nft_ctx *ctx,
enum nft_registers reg,
const struct nft_data *data,
enum nft_data_types type,
unsigned int len);
static int nf_tables_bind_check_setelem(const struct nft_ctx *ctx,
struct nft_set *set,
const struct nft_set_iter *iter,
@ -3730,6 +3741,24 @@ static int nf_tables_dump_set_done(struct netlink_callback *cb)
return 0;
}
static int nft_setelem_parse_key(struct nft_ctx *ctx, struct nft_set *set,
struct nft_data *key, struct nlattr *attr)
{
struct nft_data_desc desc;
int err;
err = nft_data_init(ctx, key, NFT_DATA_VALUE_MAXLEN, &desc, attr);
if (err < 0)
return err;
if (desc.type != NFT_DATA_VALUE || desc.len != set->klen) {
nft_data_release(key, desc.type);
return -EINVAL;
}
return 0;
}
static int nf_tables_getsetelem(struct net *net, struct sock *nlsk,
struct sk_buff *skb, const struct nlmsghdr *nlh,
const struct nlattr * const nla[],
@ -3930,19 +3959,44 @@ static int nft_setelem_parse_flags(const struct nft_set *set,
return 0;
}
static int nft_setelem_parse_data(struct nft_ctx *ctx, struct nft_set *set,
struct nft_data_desc *desc,
struct nft_data *data,
struct nlattr *attr)
{
u32 dtype;
int err;
err = nft_data_init(ctx, data, NFT_DATA_VALUE_MAXLEN, desc, attr);
if (err < 0)
return err;
if (set->dtype == NFT_DATA_VERDICT)
dtype = NFT_DATA_VERDICT;
else
dtype = NFT_DATA_VALUE;
if (dtype != desc->type ||
set->dlen != desc->len) {
nft_data_release(data, desc->type);
return -EINVAL;
}
return 0;
}
static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
const struct nlattr *attr, u32 nlmsg_flags)
{
struct nlattr *nla[NFTA_SET_ELEM_MAX + 1];
u8 genmask = nft_genmask_next(ctx->net);
struct nft_data_desc d1, d2;
struct nft_set_ext_tmpl tmpl;
struct nft_set_ext *ext, *ext2;
struct nft_set_elem elem;
struct nft_set_binding *binding;
struct nft_object *obj = NULL;
struct nft_userdata *udata;
struct nft_data data;
struct nft_data_desc desc;
enum nft_registers dreg;
struct nft_trans *trans;
u32 flags = 0;
@ -3994,15 +4048,12 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
timeout = set->timeout;
}
err = nft_data_init(ctx, &elem.key.val, sizeof(elem.key), &d1,
nla[NFTA_SET_ELEM_KEY]);
err = nft_setelem_parse_key(ctx, set, &elem.key.val,
nla[NFTA_SET_ELEM_KEY]);
if (err < 0)
goto err1;
err = -EINVAL;
if (d1.type != NFT_DATA_VALUE || d1.len != set->klen)
goto err2;
nft_set_ext_add_length(&tmpl, NFT_SET_EXT_KEY, d1.len);
nft_set_ext_add_length(&tmpl, NFT_SET_EXT_KEY, set->klen);
if (timeout > 0) {
nft_set_ext_add(&tmpl, NFT_SET_EXT_EXPIRATION);
if (timeout != set->timeout)
@ -4024,15 +4075,11 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
}
if (nla[NFTA_SET_ELEM_DATA] != NULL) {
err = nft_data_init(ctx, &data, sizeof(data), &d2,
nla[NFTA_SET_ELEM_DATA]);
err = nft_setelem_parse_data(ctx, set, &desc, &elem.data.val,
nla[NFTA_SET_ELEM_DATA]);
if (err < 0)
goto err2;
err = -EINVAL;
if (set->dtype != NFT_DATA_VERDICT && d2.len != set->dlen)
goto err3;
dreg = nft_type_to_reg(set->dtype);
list_for_each_entry(binding, &set->bindings, list) {
struct nft_ctx bind_ctx = {
@ -4046,13 +4093,13 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
continue;
err = nft_validate_register_store(&bind_ctx, dreg,
&data,
d2.type, d2.len);
&elem.data.val,
desc.type, desc.len);
if (err < 0)
goto err3;
}
nft_set_ext_add_length(&tmpl, NFT_SET_EXT_DATA, d2.len);
nft_set_ext_add_length(&tmpl, NFT_SET_EXT_DATA, desc.len);
}
/* The full maximum length of userdata can exceed the maximum
@ -4068,7 +4115,8 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
}
err = -ENOMEM;
elem.priv = nft_set_elem_init(set, &tmpl, elem.key.val.data, data.data,
elem.priv = nft_set_elem_init(set, &tmpl, elem.key.val.data,
elem.data.val.data,
timeout, GFP_KERNEL);
if (elem.priv == NULL)
goto err3;
@ -4135,9 +4183,9 @@ err4:
kfree(elem.priv);
err3:
if (nla[NFTA_SET_ELEM_DATA] != NULL)
nft_data_release(&data, d2.type);
nft_data_release(&elem.data.val, desc.type);
err2:
nft_data_release(&elem.key.val, d1.type);
nft_data_release(&elem.key.val, NFT_DATA_VALUE);
err1:
return err;
}
@ -4164,7 +4212,7 @@ static int nf_tables_newsetelem(struct net *net, struct sock *nlsk,
genmask);
if (IS_ERR(set)) {
if (nla[NFTA_SET_ELEM_LIST_SET_ID]) {
set = nf_tables_set_lookup_byid(net,
set = nf_tables_set_lookup_byid(net, ctx.table,
nla[NFTA_SET_ELEM_LIST_SET_ID],
genmask);
}
@ -4235,7 +4283,6 @@ static int nft_del_setelem(struct nft_ctx *ctx, struct nft_set *set,
{
struct nlattr *nla[NFTA_SET_ELEM_MAX + 1];
struct nft_set_ext_tmpl tmpl;
struct nft_data_desc desc;
struct nft_set_elem elem;
struct nft_set_ext *ext;
struct nft_trans *trans;
@ -4246,11 +4293,10 @@ static int nft_del_setelem(struct nft_ctx *ctx, struct nft_set *set,
err = nla_parse_nested(nla, NFTA_SET_ELEM_MAX, attr,
nft_set_elem_policy, NULL);
if (err < 0)
goto err1;
return err;
err = -EINVAL;
if (nla[NFTA_SET_ELEM_KEY] == NULL)
goto err1;
return -EINVAL;
nft_set_ext_prepare(&tmpl);
@ -4260,37 +4306,31 @@ static int nft_del_setelem(struct nft_ctx *ctx, struct nft_set *set,
if (flags != 0)
nft_set_ext_add(&tmpl, NFT_SET_EXT_FLAGS);
err = nft_data_init(ctx, &elem.key.val, sizeof(elem.key), &desc,
nla[NFTA_SET_ELEM_KEY]);
err = nft_setelem_parse_key(ctx, set, &elem.key.val,
nla[NFTA_SET_ELEM_KEY]);
if (err < 0)
goto err1;
return err;
err = -EINVAL;
if (desc.type != NFT_DATA_VALUE || desc.len != set->klen)
goto err2;
nft_set_ext_add_length(&tmpl, NFT_SET_EXT_KEY, desc.len);
nft_set_ext_add_length(&tmpl, NFT_SET_EXT_KEY, set->klen);
err = -ENOMEM;
elem.priv = nft_set_elem_init(set, &tmpl, elem.key.val.data, NULL, 0,
GFP_KERNEL);
if (elem.priv == NULL)
goto err2;
goto fail_elem;
ext = nft_set_elem_ext(set, elem.priv);
if (flags)
*nft_set_ext_flags(ext) = flags;
trans = nft_trans_elem_alloc(ctx, NFT_MSG_DELSETELEM, set);
if (trans == NULL) {
err = -ENOMEM;
goto err3;
}
if (trans == NULL)
goto fail_trans;
priv = set->ops->deactivate(ctx->net, set, &elem);
if (priv == NULL) {
err = -ENOENT;
goto err4;
goto fail_ops;
}
kfree(elem.priv);
elem.priv = priv;
@ -4301,13 +4341,12 @@ static int nft_del_setelem(struct nft_ctx *ctx, struct nft_set *set,
list_add_tail(&trans->list, &ctx->net->nft.commit_list);
return 0;
err4:
fail_ops:
kfree(trans);
err3:
fail_trans:
kfree(elem.priv);
err2:
nft_data_release(&elem.key.val, desc.type);
err1:
fail_elem:
nft_data_release(&elem.key.val, NFT_DATA_VALUE);
return err;
}
@ -5609,28 +5648,24 @@ int nft_parse_u32_check(const struct nlattr *attr, int max, u32 *dest)
}
EXPORT_SYMBOL_GPL(nft_parse_u32_check);
/**
* nft_parse_register - parse a register value from a netlink attribute
*
* @attr: netlink attribute
*
* Parse and translate a register value from a netlink attribute.
* Registers used to be 128 bit wide, these register numbers will be
* mapped to the corresponding 32 bit register numbers.
*/
unsigned int nft_parse_register(const struct nlattr *attr)
static int nft_parse_register(const struct nlattr *attr, u32 *preg)
{
unsigned int reg;
reg = ntohl(nla_get_be32(attr));
switch (reg) {
case NFT_REG_VERDICT...NFT_REG_4:
return reg * NFT_REG_SIZE / NFT_REG32_SIZE;
*preg = reg * NFT_REG_SIZE / NFT_REG32_SIZE;
break;
case NFT_REG32_00...NFT_REG32_15:
*preg = reg + NFT_REG_SIZE / NFT_REG32_SIZE - NFT_REG32_00;
break;
default:
return reg + NFT_REG_SIZE / NFT_REG32_SIZE - NFT_REG32_00;
return -ERANGE;
}
return 0;
}
EXPORT_SYMBOL_GPL(nft_parse_register);
/**
* nft_dump_register - dump a register value to a netlink attribute
@ -5663,7 +5698,7 @@ EXPORT_SYMBOL_GPL(nft_dump_register);
* Validate that the input register is one of the general purpose
* registers and that the length of the load is within the bounds.
*/
int nft_validate_register_load(enum nft_registers reg, unsigned int len)
static int nft_validate_register_load(enum nft_registers reg, unsigned int len)
{
if (reg < NFT_REG_1 * NFT_REG_SIZE / NFT_REG32_SIZE)
return -EINVAL;
@ -5674,7 +5709,24 @@ int nft_validate_register_load(enum nft_registers reg, unsigned int len)
return 0;
}
EXPORT_SYMBOL_GPL(nft_validate_register_load);
int nft_parse_register_load(const struct nlattr *attr, u8 *sreg, u32 len)
{
u32 reg;
int err;
err = nft_parse_register(attr, &reg);
if (err < 0)
return err;
err = nft_validate_register_load(reg, len);
if (err < 0)
return err;
*sreg = reg;
return 0;
}
EXPORT_SYMBOL_GPL(nft_parse_register_load);
/**
* nft_validate_register_store - validate an expressions' register store
@ -5690,10 +5742,11 @@ EXPORT_SYMBOL_GPL(nft_validate_register_load);
* A value of NULL for the data means that its runtime gathered
* data.
*/
int nft_validate_register_store(const struct nft_ctx *ctx,
enum nft_registers reg,
const struct nft_data *data,
enum nft_data_types type, unsigned int len)
static int nft_validate_register_store(const struct nft_ctx *ctx,
enum nft_registers reg,
const struct nft_data *data,
enum nft_data_types type,
unsigned int len)
{
int err;
@ -5732,7 +5785,27 @@ int nft_validate_register_store(const struct nft_ctx *ctx,
return 0;
}
}
EXPORT_SYMBOL_GPL(nft_validate_register_store);
int nft_parse_register_store(const struct nft_ctx *ctx,
const struct nlattr *attr, u8 *dreg,
const struct nft_data *data,
enum nft_data_types type, unsigned int len)
{
int err;
u32 reg;
err = nft_parse_register(attr, &reg);
if (err < 0)
return err;
err = nft_validate_register_store(ctx, reg, data, type, len);
if (err < 0)
return err;
*dreg = reg;
return 0;
}
EXPORT_SYMBOL_GPL(nft_parse_register_store);
static const struct nla_policy nft_verdict_policy[NFTA_VERDICT_MAX + 1] = {
[NFTA_VERDICT_CODE] = { .type = NLA_U32 },
@ -6032,18 +6105,25 @@ static int __init nf_tables_module_init(void)
goto err1;
}
err = nf_tables_core_module_init();
err = register_pernet_subsys(&nf_tables_net_ops);
if (err < 0)
goto err2;
err = nfnetlink_subsys_register(&nf_tables_subsys);
err = nf_tables_core_module_init();
if (err < 0)
goto err3;
/* must be last */
err = nfnetlink_subsys_register(&nf_tables_subsys);
if (err < 0)
goto err4;
pr_info("nf_tables: (c) 2007-2009 Patrick McHardy <kaber@trash.net>\n");
return register_pernet_subsys(&nf_tables_net_ops);
err3:
return err;
err4:
nf_tables_core_module_exit();
err3:
unregister_pernet_subsys(&nf_tables_net_ops);
err2:
kfree(info);
err1:

View File

@ -18,8 +18,8 @@
#include <net/netfilter/nf_tables.h>
struct nft_bitwise {
enum nft_registers sreg:8;
enum nft_registers dreg:8;
u8 sreg;
u8 dreg;
u8 len;
struct nft_data mask;
struct nft_data xor;
@ -68,14 +68,14 @@ static int nft_bitwise_init(const struct nft_ctx *ctx,
priv->len = len;
priv->sreg = nft_parse_register(tb[NFTA_BITWISE_SREG]);
err = nft_validate_register_load(priv->sreg, priv->len);
err = nft_parse_register_load(tb[NFTA_BITWISE_SREG], &priv->sreg,
priv->len);
if (err < 0)
return err;
priv->dreg = nft_parse_register(tb[NFTA_BITWISE_DREG]);
err = nft_validate_register_store(ctx, priv->dreg, NULL,
NFT_DATA_VALUE, priv->len);
err = nft_parse_register_store(ctx, tb[NFTA_BITWISE_DREG],
&priv->dreg, NULL, NFT_DATA_VALUE,
priv->len);
if (err < 0)
return err;

View File

@ -19,8 +19,8 @@
#include <net/netfilter/nf_tables.h>
struct nft_byteorder {
enum nft_registers sreg:8;
enum nft_registers dreg:8;
u8 sreg;
u8 dreg;
enum nft_byteorder_ops op:8;
u8 len;
u8 size;
@ -133,20 +133,20 @@ static int nft_byteorder_init(const struct nft_ctx *ctx,
return -EINVAL;
}
priv->sreg = nft_parse_register(tb[NFTA_BYTEORDER_SREG]);
err = nft_parse_u32_check(tb[NFTA_BYTEORDER_LEN], U8_MAX, &len);
if (err < 0)
return err;
priv->len = len;
err = nft_validate_register_load(priv->sreg, priv->len);
err = nft_parse_register_load(tb[NFTA_BYTEORDER_SREG], &priv->sreg,
priv->len);
if (err < 0)
return err;
priv->dreg = nft_parse_register(tb[NFTA_BYTEORDER_DREG]);
return nft_validate_register_store(ctx, priv->dreg, NULL,
NFT_DATA_VALUE, priv->len);
return nft_parse_register_store(ctx, tb[NFTA_BYTEORDER_DREG],
&priv->dreg, NULL, NFT_DATA_VALUE,
priv->len);
}
static int nft_byteorder_dump(struct sk_buff *skb, const struct nft_expr *expr)

View File

@ -19,7 +19,7 @@
struct nft_cmp_expr {
struct nft_data data;
enum nft_registers sreg:8;
u8 sreg;
u8 len;
enum nft_cmp_ops op:8;
};
@ -79,8 +79,7 @@ static int nft_cmp_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
tb[NFTA_CMP_DATA]);
BUG_ON(err < 0);
priv->sreg = nft_parse_register(tb[NFTA_CMP_SREG]);
err = nft_validate_register_load(priv->sreg, desc.len);
err = nft_parse_register_load(tb[NFTA_CMP_SREG], &priv->sreg, desc.len);
if (err < 0)
return err;
@ -129,8 +128,7 @@ static int nft_cmp_fast_init(const struct nft_ctx *ctx,
tb[NFTA_CMP_DATA]);
BUG_ON(err < 0);
priv->sreg = nft_parse_register(tb[NFTA_CMP_SREG]);
err = nft_validate_register_load(priv->sreg, desc.len);
err = nft_parse_register_load(tb[NFTA_CMP_SREG], &priv->sreg, desc.len);
if (err < 0)
return err;

View File

@ -27,8 +27,8 @@ struct nft_ct {
enum nft_ct_keys key:8;
enum ip_conntrack_dir dir:8;
union {
enum nft_registers dreg:8;
enum nft_registers sreg:8;
u8 dreg;
u8 sreg;
};
};
@ -483,9 +483,8 @@ static int nft_ct_get_init(const struct nft_ctx *ctx,
}
}
priv->dreg = nft_parse_register(tb[NFTA_CT_DREG]);
err = nft_validate_register_store(ctx, priv->dreg, NULL,
NFT_DATA_VALUE, len);
err = nft_parse_register_store(ctx, tb[NFTA_CT_DREG], &priv->dreg, NULL,
NFT_DATA_VALUE, len);
if (err < 0)
return err;
@ -578,8 +577,7 @@ static int nft_ct_set_init(const struct nft_ctx *ctx,
}
}
priv->sreg = nft_parse_register(tb[NFTA_CT_SREG]);
err = nft_validate_register_load(priv->sreg, len);
err = nft_parse_register_load(tb[NFTA_CT_SREG], &priv->sreg, len);
if (err < 0)
goto err1;

View File

@ -16,7 +16,7 @@
#include <net/netfilter/nf_dup_netdev.h>
struct nft_dup_netdev {
enum nft_registers sreg_dev:8;
u8 sreg_dev;
};
static void nft_dup_netdev_eval(const struct nft_expr *expr,
@ -42,8 +42,8 @@ static int nft_dup_netdev_init(const struct nft_ctx *ctx,
if (tb[NFTA_DUP_SREG_DEV] == NULL)
return -EINVAL;
priv->sreg_dev = nft_parse_register(tb[NFTA_DUP_SREG_DEV]);
return nft_validate_register_load(priv->sreg_dev, sizeof(int));
return nft_parse_register_load(tb[NFTA_DUP_SREG_DEV], &priv->sreg_dev,
sizeof(int));
}
static const struct nft_expr_ops nft_dup_netdev_ingress_ops;

View File

@ -20,8 +20,8 @@ struct nft_dynset {
struct nft_set *set;
struct nft_set_ext_tmpl tmpl;
enum nft_dynset_ops op:8;
enum nft_registers sreg_key:8;
enum nft_registers sreg_data:8;
u8 sreg_key;
u8 sreg_data;
bool invert;
u64 timeout;
struct nft_expr *expr;
@ -163,8 +163,8 @@ static int nft_dynset_init(const struct nft_ctx *ctx,
tb[NFTA_DYNSET_TIMEOUT])));
}
priv->sreg_key = nft_parse_register(tb[NFTA_DYNSET_SREG_KEY]);
err = nft_validate_register_load(priv->sreg_key, set->klen);;
err = nft_parse_register_load(tb[NFTA_DYNSET_SREG_KEY], &priv->sreg_key,
set->klen);
if (err < 0)
return err;
@ -174,8 +174,8 @@ static int nft_dynset_init(const struct nft_ctx *ctx,
if (set->dtype == NFT_DATA_VERDICT)
return -EOPNOTSUPP;
priv->sreg_data = nft_parse_register(tb[NFTA_DYNSET_SREG_DATA]);
err = nft_validate_register_load(priv->sreg_data, set->dlen);
err = nft_parse_register_load(tb[NFTA_DYNSET_SREG_DATA],
&priv->sreg_data, set->dlen);
if (err < 0)
return err;
} else if (set->flags & NFT_SET_MAP)
@ -190,9 +190,7 @@ static int nft_dynset_init(const struct nft_ctx *ctx,
priv->expr = nft_expr_init(ctx, tb[NFTA_DYNSET_EXPR]);
if (IS_ERR(priv->expr))
return PTR_ERR(priv->expr);
} else if (set->flags & NFT_SET_EVAL)
return -EINVAL;
}
nft_set_ext_prepare(&priv->tmpl);
nft_set_ext_add_length(&priv->tmpl, NFT_SET_EXT_KEY, set->klen);

View File

@ -23,8 +23,8 @@ struct nft_exthdr {
u8 offset;
u8 len;
u8 op;
enum nft_registers dreg:8;
enum nft_registers sreg:8;
u8 dreg;
u8 sreg;
u8 flags;
};
@ -257,12 +257,12 @@ static int nft_exthdr_init(const struct nft_ctx *ctx,
priv->type = nla_get_u8(tb[NFTA_EXTHDR_TYPE]);
priv->offset = offset;
priv->len = len;
priv->dreg = nft_parse_register(tb[NFTA_EXTHDR_DREG]);
priv->flags = flags;
priv->op = op;
return nft_validate_register_store(ctx, priv->dreg, NULL,
NFT_DATA_VALUE, priv->len);
return nft_parse_register_store(ctx, tb[NFTA_EXTHDR_DREG],
&priv->dreg, NULL, NFT_DATA_VALUE,
priv->len);
}
static int nft_exthdr_tcp_set_init(const struct nft_ctx *ctx,
@ -307,11 +307,11 @@ static int nft_exthdr_tcp_set_init(const struct nft_ctx *ctx,
priv->type = nla_get_u8(tb[NFTA_EXTHDR_TYPE]);
priv->offset = offset;
priv->len = len;
priv->sreg = nft_parse_register(tb[NFTA_EXTHDR_SREG]);
priv->flags = flags;
priv->op = op;
return nft_validate_register_load(priv->sreg, priv->len);
return nft_parse_register_load(tb[NFTA_EXTHDR_SREG], &priv->sreg,
priv->len);
}
static int nft_exthdr_dump_common(struct sk_buff *skb, const struct nft_exthdr *priv)

View File

@ -88,7 +88,6 @@ int nft_fib_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
return -EINVAL;
priv->result = ntohl(nla_get_be32(tb[NFTA_FIB_RESULT]));
priv->dreg = nft_parse_register(tb[NFTA_FIB_DREG]);
switch (priv->result) {
case NFT_FIB_RESULT_OIF:
@ -108,8 +107,8 @@ int nft_fib_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
return -EINVAL;
}
err = nft_validate_register_store(ctx, priv->dreg, NULL,
NFT_DATA_VALUE, len);
err = nft_parse_register_store(ctx, tb[NFTA_FIB_DREG], &priv->dreg,
NULL, NFT_DATA_VALUE, len);
if (err < 0)
return err;

View File

@ -16,7 +16,7 @@
#include <net/netfilter/nf_dup_netdev.h>
struct nft_fwd_netdev {
enum nft_registers sreg_dev:8;
u8 sreg_dev;
};
static void nft_fwd_netdev_eval(const struct nft_expr *expr,
@ -43,8 +43,8 @@ static int nft_fwd_netdev_init(const struct nft_ctx *ctx,
if (tb[NFTA_FWD_SREG_DEV] == NULL)
return -EINVAL;
priv->sreg_dev = nft_parse_register(tb[NFTA_FWD_SREG_DEV]);
return nft_validate_register_load(priv->sreg_dev, sizeof(int));
return nft_parse_register_load(tb[NFTA_FWD_SREG_DEV], &priv->sreg_dev,
sizeof(int));
}
static const struct nft_expr_ops nft_fwd_netdev_ingress_ops;

View File

@ -18,8 +18,8 @@
#include <linux/jhash.h>
struct nft_jhash {
enum nft_registers sreg:8;
enum nft_registers dreg:8;
u8 sreg;
u8 dreg;
u8 len;
bool autogen_seed:1;
u32 modulus;
@ -40,7 +40,7 @@ static void nft_jhash_eval(const struct nft_expr *expr,
}
struct nft_symhash {
enum nft_registers dreg:8;
u8 dreg;
u32 modulus;
u32 offset;
};
@ -85,9 +85,6 @@ static int nft_jhash_init(const struct nft_ctx *ctx,
if (tb[NFTA_HASH_OFFSET])
priv->offset = ntohl(nla_get_be32(tb[NFTA_HASH_OFFSET]));
priv->sreg = nft_parse_register(tb[NFTA_HASH_SREG]);
priv->dreg = nft_parse_register(tb[NFTA_HASH_DREG]);
err = nft_parse_u32_check(tb[NFTA_HASH_LEN], U8_MAX, &len);
if (err < 0)
return err;
@ -96,6 +93,10 @@ static int nft_jhash_init(const struct nft_ctx *ctx,
priv->len = len;
err = nft_parse_register_load(tb[NFTA_HASH_SREG], &priv->sreg, len);
if (err < 0)
return err;
priv->modulus = ntohl(nla_get_be32(tb[NFTA_HASH_MODULUS]));
if (priv->modulus <= 1)
return -ERANGE;
@ -110,9 +111,8 @@ static int nft_jhash_init(const struct nft_ctx *ctx,
get_random_bytes(&priv->seed, sizeof(priv->seed));
}
return nft_validate_register_load(priv->sreg, len) &&
nft_validate_register_store(ctx, priv->dreg, NULL,
NFT_DATA_VALUE, sizeof(u32));
return nft_parse_register_store(ctx, tb[NFTA_HASH_DREG], &priv->dreg,
NULL, NFT_DATA_VALUE, sizeof(u32));
}
static int nft_symhash_init(const struct nft_ctx *ctx,
@ -128,8 +128,6 @@ static int nft_symhash_init(const struct nft_ctx *ctx,
if (tb[NFTA_HASH_OFFSET])
priv->offset = ntohl(nla_get_be32(tb[NFTA_HASH_OFFSET]));
priv->dreg = nft_parse_register(tb[NFTA_HASH_DREG]);
priv->modulus = ntohl(nla_get_be32(tb[NFTA_HASH_MODULUS]));
if (priv->modulus < 1)
return -ERANGE;
@ -137,8 +135,9 @@ static int nft_symhash_init(const struct nft_ctx *ctx,
if (priv->offset + priv->modulus - 1 < priv->offset)
return -EOVERFLOW;
return nft_validate_register_store(ctx, priv->dreg, NULL,
NFT_DATA_VALUE, sizeof(u32));
return nft_parse_register_store(ctx, tb[NFTA_HASH_DREG],
&priv->dreg, NULL, NFT_DATA_VALUE,
sizeof(u32));
}
static int nft_jhash_dump(struct sk_buff *skb,

View File

@ -19,7 +19,7 @@
struct nft_immediate_expr {
struct nft_data data;
enum nft_registers dreg:8;
u8 dreg;
u8 dlen;
};
@ -56,9 +56,9 @@ static int nft_immediate_init(const struct nft_ctx *ctx,
priv->dlen = desc.len;
priv->dreg = nft_parse_register(tb[NFTA_IMMEDIATE_DREG]);
err = nft_validate_register_store(ctx, priv->dreg, &priv->data,
desc.type, desc.len);
err = nft_parse_register_store(ctx, tb[NFTA_IMMEDIATE_DREG],
&priv->dreg, &priv->data, desc.type,
desc.len);
if (err < 0)
goto err1;

View File

@ -20,8 +20,8 @@
struct nft_lookup {
struct nft_set *set;
enum nft_registers sreg:8;
enum nft_registers dreg:8;
u8 sreg;
u8 dreg;
bool invert;
struct nft_set_binding binding;
};
@ -76,8 +76,8 @@ static int nft_lookup_init(const struct nft_ctx *ctx,
if (IS_ERR(set))
return PTR_ERR(set);
priv->sreg = nft_parse_register(tb[NFTA_LOOKUP_SREG]);
err = nft_validate_register_load(priv->sreg, set->klen);
err = nft_parse_register_load(tb[NFTA_LOOKUP_SREG], &priv->sreg,
set->klen);
if (err < 0)
return err;
@ -100,9 +100,9 @@ static int nft_lookup_init(const struct nft_ctx *ctx,
if (!(set->flags & NFT_SET_MAP))
return -EINVAL;
priv->dreg = nft_parse_register(tb[NFTA_LOOKUP_DREG]);
err = nft_validate_register_store(ctx, priv->dreg, NULL,
set->dtype, set->dlen);
err = nft_parse_register_store(ctx, tb[NFTA_LOOKUP_DREG],
&priv->dreg, NULL, set->dtype,
set->dlen);
if (err < 0)
return err;
} else if (set->flags & NFT_SET_MAP)

View File

@ -53,19 +53,15 @@ int nft_masq_init(const struct nft_ctx *ctx,
}
if (tb[NFTA_MASQ_REG_PROTO_MIN]) {
priv->sreg_proto_min =
nft_parse_register(tb[NFTA_MASQ_REG_PROTO_MIN]);
err = nft_validate_register_load(priv->sreg_proto_min, plen);
err = nft_parse_register_load(tb[NFTA_MASQ_REG_PROTO_MIN],
&priv->sreg_proto_min, plen);
if (err < 0)
return err;
if (tb[NFTA_MASQ_REG_PROTO_MAX]) {
priv->sreg_proto_max =
nft_parse_register(tb[NFTA_MASQ_REG_PROTO_MAX]);
err = nft_validate_register_load(priv->sreg_proto_max,
plen);
err = nft_parse_register_load(tb[NFTA_MASQ_REG_PROTO_MAX],
&priv->sreg_proto_max,
plen);
if (err < 0)
return err;
} else {

View File

@ -314,9 +314,8 @@ int nft_meta_get_init(const struct nft_ctx *ctx,
return -EOPNOTSUPP;
}
priv->dreg = nft_parse_register(tb[NFTA_META_DREG]);
return nft_validate_register_store(ctx, priv->dreg, NULL,
NFT_DATA_VALUE, len);
return nft_parse_register_store(ctx, tb[NFTA_META_DREG], &priv->dreg,
NULL, NFT_DATA_VALUE, len);
}
EXPORT_SYMBOL_GPL(nft_meta_get_init);
@ -374,8 +373,7 @@ int nft_meta_set_init(const struct nft_ctx *ctx,
return -EOPNOTSUPP;
}
priv->sreg = nft_parse_register(tb[NFTA_META_SREG]);
err = nft_validate_register_load(priv->sreg, len);
err = nft_parse_register_load(tb[NFTA_META_SREG], &priv->sreg, len);
if (err < 0)
return err;

View File

@ -27,10 +27,10 @@
#include <net/ip.h>
struct nft_nat {
enum nft_registers sreg_addr_min:8;
enum nft_registers sreg_addr_max:8;
enum nft_registers sreg_proto_min:8;
enum nft_registers sreg_proto_max:8;
u8 sreg_addr_min;
u8 sreg_addr_max;
u8 sreg_proto_min;
u8 sreg_proto_max;
enum nf_nat_manip_type type:8;
u8 family;
u16 flags;
@ -160,18 +160,15 @@ static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
priv->family = family;
if (tb[NFTA_NAT_REG_ADDR_MIN]) {
priv->sreg_addr_min =
nft_parse_register(tb[NFTA_NAT_REG_ADDR_MIN]);
err = nft_validate_register_load(priv->sreg_addr_min, alen);
err = nft_parse_register_load(tb[NFTA_NAT_REG_ADDR_MIN],
&priv->sreg_addr_min, alen);
if (err < 0)
return err;
if (tb[NFTA_NAT_REG_ADDR_MAX]) {
priv->sreg_addr_max =
nft_parse_register(tb[NFTA_NAT_REG_ADDR_MAX]);
err = nft_validate_register_load(priv->sreg_addr_max,
alen);
err = nft_parse_register_load(tb[NFTA_NAT_REG_ADDR_MAX],
&priv->sreg_addr_max,
alen);
if (err < 0)
return err;
} else {
@ -181,19 +178,15 @@ static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
plen = FIELD_SIZEOF(struct nf_nat_range, min_addr.all);
if (tb[NFTA_NAT_REG_PROTO_MIN]) {
priv->sreg_proto_min =
nft_parse_register(tb[NFTA_NAT_REG_PROTO_MIN]);
err = nft_validate_register_load(priv->sreg_proto_min, plen);
err = nft_parse_register_load(tb[NFTA_NAT_REG_PROTO_MIN],
&priv->sreg_proto_min, plen);
if (err < 0)
return err;
if (tb[NFTA_NAT_REG_PROTO_MAX]) {
priv->sreg_proto_max =
nft_parse_register(tb[NFTA_NAT_REG_PROTO_MAX]);
err = nft_validate_register_load(priv->sreg_proto_max,
plen);
err = nft_parse_register_load(tb[NFTA_NAT_REG_PROTO_MAX],
&priv->sreg_proto_max,
plen);
if (err < 0)
return err;
} else {

View File

@ -20,7 +20,7 @@
static DEFINE_PER_CPU(struct rnd_state, nft_numgen_prandom_state);
struct nft_ng_inc {
enum nft_registers dreg:8;
u8 dreg;
u32 modulus;
atomic_t counter;
u32 offset;
@ -64,11 +64,10 @@ static int nft_ng_inc_init(const struct nft_ctx *ctx,
if (priv->offset + priv->modulus - 1 < priv->offset)
return -EOVERFLOW;
priv->dreg = nft_parse_register(tb[NFTA_NG_DREG]);
atomic_set(&priv->counter, priv->modulus - 1);
return nft_validate_register_store(ctx, priv->dreg, NULL,
NFT_DATA_VALUE, sizeof(u32));
return nft_parse_register_store(ctx, tb[NFTA_NG_DREG], &priv->dreg,
NULL, NFT_DATA_VALUE, sizeof(u32));
}
static int nft_ng_dump(struct sk_buff *skb, enum nft_registers dreg,
@ -98,7 +97,7 @@ static int nft_ng_inc_dump(struct sk_buff *skb, const struct nft_expr *expr)
}
struct nft_ng_random {
enum nft_registers dreg:8;
u8 dreg;
u32 modulus;
u32 offset;
};
@ -133,10 +132,8 @@ static int nft_ng_random_init(const struct nft_ctx *ctx,
prandom_init_once(&nft_numgen_prandom_state);
priv->dreg = nft_parse_register(tb[NFTA_NG_DREG]);
return nft_validate_register_store(ctx, priv->dreg, NULL,
NFT_DATA_VALUE, sizeof(u32));
return nft_parse_register_store(ctx, tb[NFTA_NG_DREG], &priv->dreg,
NULL, NFT_DATA_VALUE, sizeof(u32));
}
static int nft_ng_random_dump(struct sk_buff *skb, const struct nft_expr *expr)

View File

@ -64,27 +64,40 @@ nla_put_failure:
return -1;
}
static void nft_objref_destroy(const struct nft_ctx *ctx,
const struct nft_expr *expr)
static void nft_objref_deactivate(const struct nft_ctx *ctx,
const struct nft_expr *expr,
enum nft_trans_phase phase)
{
struct nft_object *obj = nft_objref_priv(expr);
if (phase == NFT_TRANS_COMMIT)
return;
obj->use--;
}
static void nft_objref_activate(const struct nft_ctx *ctx,
const struct nft_expr *expr)
{
struct nft_object *obj = nft_objref_priv(expr);
obj->use++;
}
static struct nft_expr_type nft_objref_type;
static const struct nft_expr_ops nft_objref_ops = {
.type = &nft_objref_type,
.size = NFT_EXPR_SIZE(sizeof(struct nft_object *)),
.eval = nft_objref_eval,
.init = nft_objref_init,
.destroy = nft_objref_destroy,
.activate = nft_objref_activate,
.deactivate = nft_objref_deactivate,
.dump = nft_objref_dump,
};
struct nft_objref_map {
struct nft_set *set;
enum nft_registers sreg:8;
u8 sreg;
struct nft_set_binding binding;
};
@ -125,8 +138,8 @@ static int nft_objref_map_init(const struct nft_ctx *ctx,
if (!(set->flags & NFT_SET_OBJECT))
return -EINVAL;
priv->sreg = nft_parse_register(tb[NFTA_OBJREF_SET_SREG]);
err = nft_validate_register_load(priv->sreg, set->klen);
err = nft_parse_register_load(tb[NFTA_OBJREF_SET_SREG], &priv->sreg,
set->klen);
if (err < 0)
return err;

View File

@ -135,10 +135,10 @@ static int nft_payload_init(const struct nft_ctx *ctx,
priv->base = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_BASE]));
priv->offset = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_OFFSET]));
priv->len = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_LEN]));
priv->dreg = nft_parse_register(tb[NFTA_PAYLOAD_DREG]);
return nft_validate_register_store(ctx, priv->dreg, NULL,
NFT_DATA_VALUE, priv->len);
return nft_parse_register_store(ctx, tb[NFTA_PAYLOAD_DREG],
&priv->dreg, NULL, NFT_DATA_VALUE,
priv->len);
}
static int nft_payload_dump(struct sk_buff *skb, const struct nft_expr *expr)
@ -338,7 +338,6 @@ static int nft_payload_set_init(const struct nft_ctx *ctx,
priv->base = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_BASE]));
priv->offset = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_OFFSET]));
priv->len = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_LEN]));
priv->sreg = nft_parse_register(tb[NFTA_PAYLOAD_SREG]);
if (tb[NFTA_PAYLOAD_CSUM_TYPE])
csum_type = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_CSUM_TYPE]));
@ -369,7 +368,8 @@ static int nft_payload_set_init(const struct nft_ctx *ctx,
}
priv->csum_type = csum_type;
return nft_validate_register_load(priv->sreg, priv->len);
return nft_parse_register_load(tb[NFTA_PAYLOAD_SREG], &priv->sreg,
priv->len);
}
static int nft_payload_set_dump(struct sk_buff *skb, const struct nft_expr *expr)

View File

@ -22,10 +22,10 @@
static u32 jhash_initval __read_mostly;
struct nft_queue {
enum nft_registers sreg_qnum:8;
u16 queuenum;
u16 queues_total;
u16 flags;
u8 sreg_qnum;
u16 queuenum;
u16 queues_total;
u16 flags;
};
static void nft_queue_eval(const struct nft_expr *expr,
@ -114,8 +114,8 @@ static int nft_queue_sreg_init(const struct nft_ctx *ctx,
struct nft_queue *priv = nft_expr_priv(expr);
int err;
priv->sreg_qnum = nft_parse_register(tb[NFTA_QUEUE_SREG_QNUM]);
err = nft_validate_register_load(priv->sreg_qnum, sizeof(u32));
err = nft_parse_register_load(tb[NFTA_QUEUE_SREG_QNUM],
&priv->sreg_qnum, sizeof(u32));
if (err < 0)
return err;

View File

@ -18,7 +18,7 @@
struct nft_range_expr {
struct nft_data data_from;
struct nft_data data_to;
enum nft_registers sreg:8;
u8 sreg;
u8 len;
enum nft_range_ops op:8;
};
@ -80,8 +80,8 @@ static int nft_range_init(const struct nft_ctx *ctx, const struct nft_expr *expr
goto err2;
}
priv->sreg = nft_parse_register(tb[NFTA_RANGE_SREG]);
err = nft_validate_register_load(priv->sreg, desc_from.len);
err = nft_parse_register_load(tb[NFTA_RANGE_SREG], &priv->sreg,
desc_from.len);
if (err < 0)
goto err2;

View File

@ -49,19 +49,15 @@ int nft_redir_init(const struct nft_ctx *ctx,
plen = FIELD_SIZEOF(struct nf_nat_range, min_addr.all);
if (tb[NFTA_REDIR_REG_PROTO_MIN]) {
priv->sreg_proto_min =
nft_parse_register(tb[NFTA_REDIR_REG_PROTO_MIN]);
err = nft_validate_register_load(priv->sreg_proto_min, plen);
err = nft_parse_register_load(tb[NFTA_REDIR_REG_PROTO_MIN],
&priv->sreg_proto_min, plen);
if (err < 0)
return err;
if (tb[NFTA_REDIR_REG_PROTO_MAX]) {
priv->sreg_proto_max =
nft_parse_register(tb[NFTA_REDIR_REG_PROTO_MAX]);
err = nft_validate_register_load(priv->sreg_proto_max,
plen);
err = nft_parse_register_load(tb[NFTA_REDIR_REG_PROTO_MAX],
&priv->sreg_proto_max,
plen);
if (err < 0)
return err;
} else {

View File

@ -20,7 +20,7 @@
struct nft_rt {
enum nft_rt_keys key:8;
enum nft_registers dreg:8;
u8 dreg;
};
static u16 get_tcpmss(const struct nft_pktinfo *pkt, const struct dst_entry *skbdst)
@ -141,9 +141,8 @@ static int nft_rt_get_init(const struct nft_ctx *ctx,
return -EOPNOTSUPP;
}
priv->dreg = nft_parse_register(tb[NFTA_RT_DREG]);
return nft_validate_register_store(ctx, priv->dreg, NULL,
NFT_DATA_VALUE, len);
return nft_parse_register_store(ctx, tb[NFTA_RT_DREG], &priv->dreg,
NULL, NFT_DATA_VALUE, len);
}
static int nft_rt_get_dump(struct sk_buff *skb,

View File

@ -1977,7 +1977,7 @@ static int netlink_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
skb_free_datagram(sk, skb);
if (nlk->cb_running &&
if (READ_ONCE(nlk->cb_running) &&
atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf / 2) {
ret = netlink_dump(sk);
if (ret) {
@ -2259,7 +2259,7 @@ static int netlink_dump(struct sock *sk)
if (cb->done)
cb->done(cb);
nlk->cb_running = false;
WRITE_ONCE(nlk->cb_running, false);
module = cb->module;
skb = cb->skb;
mutex_unlock(nlk->cb_mutex);
@ -2320,7 +2320,7 @@ int __netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
goto error_put;
}
nlk->cb_running = true;
WRITE_ONCE(nlk->cb_running, true);
nlk->dump_done_errno = INT_MAX;
mutex_unlock(nlk->cb_mutex);
@ -2633,7 +2633,7 @@ static int netlink_seq_show(struct seq_file *seq, void *v)
nlk->groups ? (u32)nlk->groups[0] : 0,
sk_rmem_alloc_get(s),
sk_wmem_alloc_get(s),
nlk->cb_running,
READ_ONCE(nlk->cb_running),
refcount_read(&s->sk_refcnt),
atomic_read(&s->sk_drops),
sock_i_ino(s)

Some files were not shown because too many files have changed in this diff Show More