]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge branch 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa...
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 17 May 2017 21:13:44 +0000 (14:13 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 17 May 2017 21:13:44 +0000 (14:13 -0700)
Pull i2c fixes from Wolfram Sang:
 "Here are some bugfixes from I2C, especially removing a wrongly
  displayed error message for all i2c muxes"

* 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux:
  i2c: xgene: Set ACPI_COMPANION_I2C
  i2c: mv64xxx: don't override deferred probing when getting irq
  i2c: mux: only print failure message on error
  i2c: mux: reg: rename label to indicate what it does
  i2c: mux: reg: put away the parent i2c adapter on probe failure

98 files changed:
arch/arm64/net/bpf_jit_comp.c
arch/s390/include/asm/debug.h
arch/s390/include/asm/dis.h
arch/s390/include/asm/kprobes.h
arch/s390/include/asm/sysinfo.h
arch/s390/kernel/debug.c
arch/s390/kernel/entry.S
arch/s390/kernel/ftrace.c
arch/s390/kernel/vmlinux.lds.S
arch/s390/lib/probes.c
arch/s390/lib/uaccess.c
drivers/edac/amd64_edac.c
drivers/firmware/efi/efi-pstore.c
drivers/net/dsa/mv88e6xxx/chip.c
drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c
drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c
drivers/net/ethernet/mellanox/mlx4/main.c
drivers/net/ethernet/mellanox/mlx5/core/en.h
drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
drivers/net/ethernet/mellanox/mlx5/core/en_fs.c
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c
drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h
drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
drivers/net/ethernet/mellanox/mlx5/core/fs_core.h
drivers/net/ethernet/mellanox/mlx5/core/ipoib.c
drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c
drivers/net/ethernet/qlogic/qed/qed_init_fw_funcs.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
drivers/net/ethernet/qualcomm/qca_spi.c
drivers/net/ethernet/sfc/nic.h
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/sun/ldmvsw.c
drivers/net/ethernet/ti/netcp_core.c
drivers/net/ethernet/ti/netcp_ethss.c
drivers/net/irda/irda-usb.c
drivers/net/macvlan.c
drivers/net/phy/mdio-mux.c
drivers/net/phy/mdio_bus.c
drivers/net/usb/ch9200.c
drivers/net/vmxnet3/vmxnet3_drv.c
drivers/net/vrf.c
drivers/net/xen-netfront.c
drivers/s390/cio/ccwgroup.c
drivers/s390/cio/qdio_debug.h
drivers/s390/net/qeth_core.h
drivers/s390/net/qeth_core_main.c
drivers/s390/net/qeth_core_sys.c
drivers/s390/net/qeth_l2.h
drivers/s390/net/qeth_l2_main.c
drivers/s390/net/qeth_l2_sys.c
drivers/s390/net/qeth_l3_main.c
drivers/s390/virtio/virtio_ccw.c
drivers/soc/ti/knav_dma.c
fs/cifs/cifsacl.c
fs/cifs/cifsglob.h
fs/cifs/cifsproto.h
fs/cifs/cifssmb.c
fs/cifs/file.c
fs/cifs/inode.c
fs/cifs/smb2pdu.c
fs/cifs/transport.c
fs/cifs/xattr.c
include/linux/bpf_verifier.h
include/linux/mlx5/fs.h
include/linux/netdevice.h
include/uapi/linux/bpf.h
include/uapi/linux/if_link.h
kernel/bpf/syscall.c
kernel/bpf/verifier.c
net/core/dev.c
net/core/rtnetlink.c
net/core/sock.c
net/dccp/ipv6.c
net/ipv4/tcp_input.c
net/ipv6/addrconf.c
net/ipv6/tcp_ipv6.c
net/packet/af_packet.c
net/sched/sch_api.c
net/sctp/ipv6.c
net/tipc/socket.c
samples/bpf/cookie_uid_helper_example.c
samples/bpf/offwaketime_user.c
samples/bpf/sampleip_user.c
samples/bpf/trace_event_user.c
samples/bpf/tracex2_user.c
samples/bpf/xdp1_user.c
samples/bpf/xdp_tx_iptunnel_user.c
tools/build/feature/test-bpf.c
tools/include/uapi/linux/bpf.h
tools/lib/bpf/bpf.c
tools/lib/bpf/bpf.h
tools/testing/selftests/bpf/Makefile
tools/testing/selftests/bpf/include/uapi/linux/types.h [new file with mode: 0644]
tools/testing/selftests/bpf/test_align.c [new file with mode: 0644]

index c6e53580aefe9148f6d865a9a89e611a6d1c542e..71f930501ade7cec2d1f230aa638ad3fc9112ee8 100644 (file)
@@ -253,8 +253,9 @@ static int emit_bpf_tail_call(struct jit_ctx *ctx)
         */
        off = offsetof(struct bpf_array, ptrs);
        emit_a64_mov_i64(tmp, off, ctx);
-       emit(A64_LDR64(tmp, r2, tmp), ctx);
-       emit(A64_LDR64(prg, tmp, r3), ctx);
+       emit(A64_ADD(1, tmp, r2, tmp), ctx);
+       emit(A64_LSL(1, prg, r3, 3), ctx);
+       emit(A64_LDR64(prg, tmp, prg), ctx);
        emit(A64_CBZ(1, prg, jmp_offset), ctx);
 
        /* goto *(prog->bpf_func + prologue_size); */
index 0206c805232878c95a6588dbb9909ecb4268d5d0..df7b54ea956daeb6c9a1091518e73417e688e504 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/spinlock.h>
 #include <linux/kernel.h>
 #include <linux/time.h>
+#include <linux/refcount.h>
 #include <uapi/asm/debug.h>
 
 #define DEBUG_MAX_LEVEL            6  /* debug levels range from 0 to 6 */
@@ -31,7 +32,7 @@ struct debug_view;
 typedef struct debug_info {    
        struct debug_info* next;
        struct debug_info* prev;
-       atomic_t ref_count;
+       refcount_t ref_count;
        spinlock_t lock;                        
        int level;
        int nr_areas;
index 60323c21938bb5d97407e9f0cb35c6fcdd335597..37f617dfbeded0de8edb9f9f4e1a263c46bd0635 100644 (file)
@@ -40,6 +40,8 @@ static inline int insn_length(unsigned char code)
        return ((((int) code + 64) >> 7) + 1) << 1;
 }
 
+struct pt_regs;
+
 void show_code(struct pt_regs *regs);
 void print_fn_code(unsigned char *code, unsigned long len);
 int insn_to_mnemonic(unsigned char *instruction, char *buf, unsigned int len);
index 1293c4066cfc806f96f06bec93743f7d051f2973..28792ef82c837a2f2c11a5765098434018d02598 100644 (file)
  * 2005-Dec    Used as a template for s390 by Mike Grundy
  *             <grundym@us.ibm.com>
  */
+#include <linux/types.h>
 #include <asm-generic/kprobes.h>
 
 #define BREAKPOINT_INSTRUCTION 0x0002
 
+#define FIXUP_PSW_NORMAL       0x08
+#define FIXUP_BRANCH_NOT_TAKEN 0x04
+#define FIXUP_RETURN_REGISTER  0x02
+#define FIXUP_NOT_REQUIRED     0x01
+
+int probe_is_prohibited_opcode(u16 *insn);
+int probe_get_fixup_type(u16 *insn);
+int probe_is_insn_relative_long(u16 *insn);
+
 #ifdef CONFIG_KPROBES
-#include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
 #include <linux/sched/task_stack.h>
@@ -56,11 +65,6 @@ typedef u16 kprobe_opcode_t;
 
 #define KPROBE_SWAP_INST       0x10
 
-#define FIXUP_PSW_NORMAL       0x08
-#define FIXUP_BRANCH_NOT_TAKEN 0x04
-#define FIXUP_RETURN_REGISTER  0x02
-#define FIXUP_NOT_REQUIRED     0x01
-
 /* Architecture specific copy of original instruction */
 struct arch_specific_insn {
        /* copy of original instruction */
@@ -90,10 +94,6 @@ int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
 int kprobe_exceptions_notify(struct notifier_block *self,
        unsigned long val, void *data);
 
-int probe_is_prohibited_opcode(u16 *insn);
-int probe_get_fixup_type(u16 *insn);
-int probe_is_insn_relative_long(u16 *insn);
-
 #define flush_insn_slot(p)     do { } while (0)
 
 #endif /* CONFIG_KPROBES */
index 73bff45ced55268c7f06e52a98be46f7eaa2ea54..e784bed6ed7ffb24cabb02eb92a1d90494e3b7e1 100644 (file)
@@ -146,7 +146,7 @@ extern int topology_max_mnest;
  * Returns the maximum nesting level supported by the cpu topology code.
  * The current maximum level is 4 which is the drawer level.
  */
-static inline int topology_mnest_limit(void)
+static inline unsigned char topology_mnest_limit(void)
 {
        return min(topology_max_mnest, 4);
 }
index 530226b6cb19a2ed5bb011ab61215f69e243d4c5..86b3e74f569eb7823ba6c4b0c4ec7baeb456e2f1 100644 (file)
@@ -277,7 +277,7 @@ debug_info_alloc(const char *name, int pages_per_area, int nr_areas,
        memset(rc->views, 0, DEBUG_MAX_VIEWS * sizeof(struct debug_view *));
        memset(rc->debugfs_entries, 0 ,DEBUG_MAX_VIEWS *
                sizeof(struct dentry*));
-       atomic_set(&(rc->ref_count), 0);
+       refcount_set(&(rc->ref_count), 0);
 
        return rc;
 
@@ -361,7 +361,7 @@ debug_info_create(const char *name, int pages_per_area, int nr_areas,
         debug_area_last = rc;
         rc->next = NULL;
 
-       debug_info_get(rc);
+       refcount_set(&rc->ref_count, 1);
 out:
        return rc;
 }
@@ -416,7 +416,7 @@ static void
 debug_info_get(debug_info_t * db_info)
 {
        if (db_info)
-               atomic_inc(&db_info->ref_count);
+               refcount_inc(&db_info->ref_count);
 }
 
 /*
@@ -431,7 +431,7 @@ debug_info_put(debug_info_t *db_info)
 
        if (!db_info)
                return;
-       if (atomic_dec_and_test(&db_info->ref_count)) {
+       if (refcount_dec_and_test(&db_info->ref_count)) {
                for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
                        if (!db_info->views[i])
                                continue;
index a5f5d3bb3dbc516d23c98082d0f3abe186fc95c1..e408d9cc5b96adf40b873d8aabb3235793cd1b16 100644 (file)
@@ -312,6 +312,7 @@ ENTRY(system_call)
        lg      %r14,__LC_VDSO_PER_CPU
        lmg     %r0,%r10,__PT_R0(%r11)
        mvc     __LC_RETURN_PSW(16),__PT_PSW(%r11)
+.Lsysc_exit_timer:
        stpt    __LC_EXIT_TIMER
        mvc     __VDSO_ECTG_BASE(16,%r14),__LC_EXIT_TIMER
        lmg     %r11,%r15,__PT_R11(%r11)
@@ -623,6 +624,7 @@ ENTRY(io_int_handler)
        lg      %r14,__LC_VDSO_PER_CPU
        lmg     %r0,%r10,__PT_R0(%r11)
        mvc     __LC_RETURN_PSW(16),__PT_PSW(%r11)
+.Lio_exit_timer:
        stpt    __LC_EXIT_TIMER
        mvc     __VDSO_ECTG_BASE(16,%r14),__LC_EXIT_TIMER
        lmg     %r11,%r15,__PT_R11(%r11)
@@ -1174,15 +1176,23 @@ cleanup_critical:
        br      %r14
 
 .Lcleanup_sysc_restore:
+       # check if stpt has been executed
        clg     %r9,BASED(.Lcleanup_sysc_restore_insn)
+       jh      0f
+       mvc     __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER
+       cghi    %r11,__LC_SAVE_AREA_ASYNC
        je      0f
+       mvc     __LC_EXIT_TIMER(8),__LC_MCCK_ENTER_TIMER
+0:     clg     %r9,BASED(.Lcleanup_sysc_restore_insn+8)
+       je      1f
        lg      %r9,24(%r11)            # get saved pointer to pt_regs
        mvc     __LC_RETURN_PSW(16),__PT_PSW(%r9)
        mvc     0(64,%r11),__PT_R8(%r9)
        lmg     %r0,%r7,__PT_R0(%r9)
-0:     lmg     %r8,%r9,__LC_RETURN_PSW
+1:     lmg     %r8,%r9,__LC_RETURN_PSW
        br      %r14
 .Lcleanup_sysc_restore_insn:
+       .quad   .Lsysc_exit_timer
        .quad   .Lsysc_done - 4
 
 .Lcleanup_io_tif:
@@ -1190,15 +1200,20 @@ cleanup_critical:
        br      %r14
 
 .Lcleanup_io_restore:
+       # check if stpt has been executed
        clg     %r9,BASED(.Lcleanup_io_restore_insn)
-       je      0f
+       jh      0f
+       mvc     __LC_EXIT_TIMER(8),__LC_MCCK_ENTER_TIMER
+0:     clg     %r9,BASED(.Lcleanup_io_restore_insn+8)
+       je      1f
        lg      %r9,24(%r11)            # get saved r11 pointer to pt_regs
        mvc     __LC_RETURN_PSW(16),__PT_PSW(%r9)
        mvc     0(64,%r11),__PT_R8(%r9)
        lmg     %r0,%r7,__PT_R0(%r9)
-0:     lmg     %r8,%r9,__LC_RETURN_PSW
+1:     lmg     %r8,%r9,__LC_RETURN_PSW
        br      %r14
 .Lcleanup_io_restore_insn:
+       .quad   .Lio_exit_timer
        .quad   .Lio_done - 4
 
 .Lcleanup_idle:
index 27477f34cc0a9844a7391eef1e40ab28e3b1dcf1..d03a6d12c4bdc4118c3c10e0c80e90822cac6a03 100644 (file)
@@ -173,6 +173,8 @@ int __init ftrace_dyn_arch_init(void)
        return 0;
 }
 
+#ifdef CONFIG_MODULES
+
 static int __init ftrace_plt_init(void)
 {
        unsigned int *ip;
@@ -191,6 +193,8 @@ static int __init ftrace_plt_init(void)
 }
 device_initcall(ftrace_plt_init);
 
+#endif /* CONFIG_MODULES */
+
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 /*
  * Hook the return address and push it in the stack of return addresses
index 72307f108c40387fd718e9ca1e07ee5cb6ef9cb8..6e2c42bd1c3badbc4837176aeb1e266d86890bcf 100644 (file)
@@ -31,8 +31,14 @@ SECTIONS
 {
        . = 0x00000000;
        .text : {
-       _text = .;              /* Text and read-only data */
+               /* Text and read-only data */
                HEAD_TEXT
+               /*
+                * E.g. perf doesn't like symbols starting at address zero,
+                * therefore skip the initial PSW and channel program located
+                * at address zero and let _text start at 0x200.
+                */
+       _text = 0x200;
                TEXT_TEXT
                SCHED_TEXT
                CPUIDLE_TEXT
index ae90e1ae3607052c6ac4403f815d33061fcaf604..1963ddbf4ab385898160ce1d75881201b9c848c8 100644 (file)
@@ -4,6 +4,7 @@
  *    Copyright IBM Corp. 2014
  */
 
+#include <linux/errno.h>
 #include <asm/kprobes.h>
 #include <asm/dis.h>
 
index 1e5bb2b86c423fefee7987ec45483077748e8ca8..b3bd3f23b8e851c7f67e46cb527e20603512e7f5 100644 (file)
@@ -337,8 +337,8 @@ long __strncpy_from_user(char *dst, const char __user *src, long size)
                return 0;
        done = 0;
        do {
-               offset = (size_t)src & ~PAGE_MASK;
-               len = min(size - done, PAGE_SIZE - offset);
+               offset = (size_t)src & (L1_CACHE_BYTES - 1);
+               len = min(size - done, L1_CACHE_BYTES - offset);
                if (copy_from_user(dst, src, len))
                        return -EFAULT;
                len_str = strnlen(dst, len);
index 82dab1692264d04baeb409622d54bbd895e013ff..3aea5569816557b9b55503fb7fd654e9b088b6df 100644 (file)
@@ -782,24 +782,26 @@ static void debug_dump_dramcfg_low(struct amd64_pvt *pvt, u32 dclr, int chan)
 
 static void debug_display_dimm_sizes_df(struct amd64_pvt *pvt, u8 ctrl)
 {
-       u32 *dcsb = ctrl ? pvt->csels[1].csbases : pvt->csels[0].csbases;
-       int dimm, size0, size1;
+       int dimm, size0, size1, cs0, cs1;
 
        edac_printk(KERN_DEBUG, EDAC_MC, "UMC%d chip selects:\n", ctrl);
 
        for (dimm = 0; dimm < 4; dimm++) {
                size0 = 0;
+               cs0 = dimm * 2;
 
-               if (dcsb[dimm*2] & DCSB_CS_ENABLE)
-                       size0 = pvt->ops->dbam_to_cs(pvt, ctrl, 0, dimm);
+               if (csrow_enabled(cs0, ctrl, pvt))
+                       size0 = pvt->ops->dbam_to_cs(pvt, ctrl, 0, cs0);
 
                size1 = 0;
-               if (dcsb[dimm*2 + 1] & DCSB_CS_ENABLE)
-                       size1 = pvt->ops->dbam_to_cs(pvt, ctrl, 0, dimm);
+               cs1 = dimm * 2 + 1;
+
+               if (csrow_enabled(cs1, ctrl, pvt))
+                       size1 = pvt->ops->dbam_to_cs(pvt, ctrl, 0, cs1);
 
                amd64_info(EDAC_MC ": %d: %5dMB %d: %5dMB\n",
-                               dimm * 2,     size0,
-                               dimm * 2 + 1, size1);
+                               cs0,    size0,
+                               cs1,    size1);
        }
 }
 
@@ -2756,26 +2758,22 @@ skip:
  *     encompasses
  *
  */
-static u32 get_csrow_nr_pages(struct amd64_pvt *pvt, u8 dct, int csrow_nr)
+static u32 get_csrow_nr_pages(struct amd64_pvt *pvt, u8 dct, int csrow_nr_orig)
 {
-       u32 cs_mode, nr_pages;
        u32 dbam = dct ? pvt->dbam1 : pvt->dbam0;
+       int csrow_nr = csrow_nr_orig;
+       u32 cs_mode, nr_pages;
 
+       if (!pvt->umc)
+               csrow_nr >>= 1;
 
-       /*
-        * The math on this doesn't look right on the surface because x/2*4 can
-        * be simplified to x*2 but this expression makes use of the fact that
-        * it is integral math where 1/2=0. This intermediate value becomes the
-        * number of bits to shift the DBAM register to extract the proper CSROW
-        * field.
-        */
-       cs_mode = DBAM_DIMM(csrow_nr / 2, dbam);
+       cs_mode = DBAM_DIMM(csrow_nr, dbam);
 
-       nr_pages = pvt->ops->dbam_to_cs(pvt, dct, cs_mode, (csrow_nr / 2))
-                                                          << (20 - PAGE_SHIFT);
+       nr_pages   = pvt->ops->dbam_to_cs(pvt, dct, cs_mode, csrow_nr);
+       nr_pages <<= 20 - PAGE_SHIFT;
 
        edac_dbg(0, "csrow: %d, channel: %d, DBAM idx: %d\n",
-                   csrow_nr, dct,  cs_mode);
+                   csrow_nr_orig, dct,  cs_mode);
        edac_dbg(0, "nr_pages/channel: %u\n", nr_pages);
 
        return nr_pages;
index ed3137c1ceb0c0ed0fcbb1c94bffdf1a4811bf41..ab3a951a17e6c182dfa1c68b579ee003b3c1c44a 100644 (file)
@@ -155,19 +155,14 @@ static int efi_pstore_scan_sysfs_exit(struct efivar_entry *pos,
  * efi_pstore_sysfs_entry_iter
  *
  * @record: pstore record to pass to callback
- * @pos: entry to begin iterating from
  *
  * You MUST call efivar_enter_iter_begin() before this function, and
  * efivar_entry_iter_end() afterwards.
  *
- * It is possible to begin iteration from an arbitrary entry within
- * the list by passing @pos. @pos is updated on return to point to
- * the next entry of the last one passed to efi_pstore_read_func().
- * To begin iterating from the beginning of the list @pos must be %NULL.
  */
-static int efi_pstore_sysfs_entry_iter(struct pstore_record *record,
-                                      struct efivar_entry **pos)
+static int efi_pstore_sysfs_entry_iter(struct pstore_record *record)
 {
+       struct efivar_entry **pos = (struct efivar_entry **)&record->psi->data;
        struct efivar_entry *entry, *n;
        struct list_head *head = &efivar_sysfs_list;
        int size = 0;
@@ -218,7 +213,6 @@ static int efi_pstore_sysfs_entry_iter(struct pstore_record *record,
  */
 static ssize_t efi_pstore_read(struct pstore_record *record)
 {
-       struct efivar_entry *entry = (struct efivar_entry *)record->psi->data;
        ssize_t size;
 
        record->buf = kzalloc(EFIVARS_DATA_SIZE_MAX, GFP_KERNEL);
@@ -229,7 +223,7 @@ static ssize_t efi_pstore_read(struct pstore_record *record)
                size = -EINTR;
                goto out;
        }
-       size = efi_pstore_sysfs_entry_iter(record, &entry);
+       size = efi_pstore_sysfs_entry_iter(record);
        efivar_entry_iter_end();
 
 out:
index 19581d783d8ec7dc9ed9e5fd5a2891e8f2d22135..d034d8cd7d22dcde187f0becb24afd45480271f3 100644 (file)
@@ -849,6 +849,9 @@ static uint64_t _mv88e6xxx_get_ethtool_stat(struct mv88e6xxx_chip *chip,
                mv88e6xxx_g1_stats_read(chip, reg, &low);
                if (s->sizeof_stat == 8)
                        mv88e6xxx_g1_stats_read(chip, reg + 1, &high);
+               break;
+       default:
+               return UINT64_MAX;
        }
        value = (((u64)high) << 16) | low;
        return value;
index 4ee15ff06a448b72dbd6763427d9d02dfadad268..faeb4935ef3e3af5c998ef701e1e7cd2f5d739c8 100644 (file)
@@ -200,29 +200,18 @@ err_exit:
 static int hw_atl_a0_hw_offload_set(struct aq_hw_s *self,
                                    struct aq_nic_cfg_s *aq_nic_cfg)
 {
-       int err = 0;
-
        /* TX checksums offloads*/
        tpo_ipv4header_crc_offload_en_set(self, 1);
        tpo_tcp_udp_crc_offload_en_set(self, 1);
-       if (err < 0)
-               goto err_exit;
 
        /* RX checksums offloads*/
        rpo_ipv4header_crc_offload_en_set(self, 1);
        rpo_tcp_udp_crc_offload_en_set(self, 1);
-       if (err < 0)
-               goto err_exit;
 
        /* LSO offloads*/
        tdm_large_send_offload_en_set(self, 0xFFFFFFFFU);
-       if (err < 0)
-               goto err_exit;
-
-       err = aq_hw_err_from_flags(self);
 
-err_exit:
-       return err;
+       return aq_hw_err_from_flags(self);
 }
 
 static int hw_atl_a0_hw_init_tx_path(struct aq_hw_s *self)
index 42150708191dbf67d91b33218a2a275e9b5fd45d..1bceb7358e5ca3a4455badf55bc091d3705dc89d 100644 (file)
@@ -200,25 +200,18 @@ err_exit:
 static int hw_atl_b0_hw_offload_set(struct aq_hw_s *self,
                                    struct aq_nic_cfg_s *aq_nic_cfg)
 {
-       int err = 0;
        unsigned int i;
 
        /* TX checksums offloads*/
        tpo_ipv4header_crc_offload_en_set(self, 1);
        tpo_tcp_udp_crc_offload_en_set(self, 1);
-       if (err < 0)
-               goto err_exit;
 
        /* RX checksums offloads*/
        rpo_ipv4header_crc_offload_en_set(self, 1);
        rpo_tcp_udp_crc_offload_en_set(self, 1);
-       if (err < 0)
-               goto err_exit;
 
        /* LSO offloads*/
        tdm_large_send_offload_en_set(self, 0xFFFFFFFFU);
-       if (err < 0)
-               goto err_exit;
 
 /* LRO offloads */
        {
@@ -245,10 +238,7 @@ static int hw_atl_b0_hw_offload_set(struct aq_hw_s *self,
 
                rpo_lro_en_set(self, aq_nic_cfg->is_lro ? 0xFFFFFFFFU : 0U);
        }
-       err = aq_hw_err_from_flags(self);
-
-err_exit:
-       return err;
+       return aq_hw_err_from_flags(self);
 }
 
 static int hw_atl_b0_hw_init_tx_path(struct aq_hw_s *self)
index 703205475524d689cd2762f2d2ce3abfd2b6ebcb..83aab1e4c8c8c76f73a598c5bdde51e185d9121a 100644 (file)
@@ -2862,12 +2862,10 @@ static void mlx4_enable_msi_x(struct mlx4_dev *dev)
        int port = 0;
 
        if (msi_x) {
-               int nreq = dev->caps.num_ports * num_online_cpus() + 1;
-
-               nreq = min_t(int, dev->caps.num_eqs - dev->caps.reserved_eqs,
-                            nreq);
-               if (nreq > MAX_MSIX)
-                       nreq = MAX_MSIX;
+               int nreq = min3(dev->caps.num_ports *
+                               (int)num_online_cpus() + 1,
+                               dev->caps.num_eqs - dev->caps.reserved_eqs,
+                               MAX_MSIX);
 
                entries = kcalloc(nreq, sizeof *entries, GFP_KERNEL);
                if (!entries)
index 0099a3e397bcf8758388b44e0e44888b35468920..2fd044b238750fedc61384fda55bf25206d25b51 100644 (file)
@@ -1003,7 +1003,7 @@ int mlx5e_create_direct_tirs(struct mlx5e_priv *priv);
 void mlx5e_destroy_direct_tirs(struct mlx5e_priv *priv);
 void mlx5e_destroy_rqt(struct mlx5e_priv *priv, struct mlx5e_rqt *rqt);
 
-int mlx5e_create_ttc_table(struct mlx5e_priv *priv, u32 underlay_qpn);
+int mlx5e_create_ttc_table(struct mlx5e_priv *priv);
 void mlx5e_destroy_ttc_table(struct mlx5e_priv *priv);
 
 int mlx5e_create_tis(struct mlx5_core_dev *mdev, int tc,
index ce7b09d72ff68b1850f6df3845f2fd9ae7f57bbd..8209affa75c3e5e0419634740d6985970f61fa67 100644 (file)
@@ -794,7 +794,6 @@ static void get_supported(u32 eth_proto_cap,
        ptys2ethtool_supported_port(link_ksettings, eth_proto_cap);
        ptys2ethtool_supported_link(supported, eth_proto_cap);
        ethtool_link_ksettings_add_link_mode(link_ksettings, supported, Pause);
-       ethtool_link_ksettings_add_link_mode(link_ksettings, supported, Asym_Pause);
 }
 
 static void get_advertising(u32 eth_proto_cap, u8 tx_pause,
@@ -804,7 +803,7 @@ static void get_advertising(u32 eth_proto_cap, u8 tx_pause,
        unsigned long *advertising = link_ksettings->link_modes.advertising;
 
        ptys2ethtool_adver_link(advertising, eth_proto_cap);
-       if (tx_pause)
+       if (rx_pause)
                ethtool_link_ksettings_add_link_mode(link_ksettings, advertising, Pause);
        if (tx_pause ^ rx_pause)
                ethtool_link_ksettings_add_link_mode(link_ksettings, advertising, Asym_Pause);
@@ -849,6 +848,8 @@ static int mlx5e_get_link_ksettings(struct net_device *netdev,
        struct mlx5e_priv *priv    = netdev_priv(netdev);
        struct mlx5_core_dev *mdev = priv->mdev;
        u32 out[MLX5_ST_SZ_DW(ptys_reg)] = {0};
+       u32 rx_pause = 0;
+       u32 tx_pause = 0;
        u32 eth_proto_cap;
        u32 eth_proto_admin;
        u32 eth_proto_lp;
@@ -871,11 +872,13 @@ static int mlx5e_get_link_ksettings(struct net_device *netdev,
        an_disable_admin = MLX5_GET(ptys_reg, out, an_disable_admin);
        an_status        = MLX5_GET(ptys_reg, out, an_status);
 
+       mlx5_query_port_pause(mdev, &rx_pause, &tx_pause);
+
        ethtool_link_ksettings_zero_link_mode(link_ksettings, supported);
        ethtool_link_ksettings_zero_link_mode(link_ksettings, advertising);
 
        get_supported(eth_proto_cap, link_ksettings);
-       get_advertising(eth_proto_admin, 0, 0, link_ksettings);
+       get_advertising(eth_proto_admin, tx_pause, rx_pause, link_ksettings);
        get_speed_duplex(netdev, eth_proto_oper, link_ksettings);
 
        eth_proto_oper = eth_proto_oper ? eth_proto_oper : eth_proto_cap;
index 576d6787b484b6387c55a172a65fa838b50e198a..53ed58320a24aef89e40230c67728ea01bd086ac 100644 (file)
@@ -800,7 +800,7 @@ void mlx5e_destroy_ttc_table(struct mlx5e_priv *priv)
        mlx5e_destroy_flow_table(&ttc->ft);
 }
 
-int mlx5e_create_ttc_table(struct mlx5e_priv *priv, u32 underlay_qpn)
+int mlx5e_create_ttc_table(struct mlx5e_priv *priv)
 {
        struct mlx5e_ttc_table *ttc = &priv->fs.ttc;
        struct mlx5_flow_table_attr ft_attr = {};
@@ -810,7 +810,6 @@ int mlx5e_create_ttc_table(struct mlx5e_priv *priv, u32 underlay_qpn)
        ft_attr.max_fte = MLX5E_TTC_TABLE_SIZE;
        ft_attr.level = MLX5E_TTC_FT_LEVEL;
        ft_attr.prio = MLX5E_NIC_PRIO;
-       ft_attr.underlay_qpn = underlay_qpn;
 
        ft->t = mlx5_create_flow_table(priv->fs.ns, &ft_attr);
        if (IS_ERR(ft->t)) {
@@ -1147,7 +1146,7 @@ int mlx5e_create_flow_steering(struct mlx5e_priv *priv)
                priv->netdev->hw_features &= ~NETIF_F_NTUPLE;
        }
 
-       err = mlx5e_create_ttc_table(priv, 0);
+       err = mlx5e_create_ttc_table(priv);
        if (err) {
                netdev_err(priv->netdev, "Failed to create ttc table, err=%d\n",
                           err);
index a61b71b6fff30358e43602b1f84e16c697e3140f..41cd22a223dccbd9dae460331525a1fc2414be9e 100644 (file)
@@ -2976,7 +2976,7 @@ static int mlx5e_setup_tc(struct net_device *netdev, u8 tc)
        new_channels.params = priv->channels.params;
        new_channels.params.num_tc = tc ? tc : 1;
 
-       if (test_bit(MLX5E_STATE_OPENED, &priv->state)) {
+       if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) {
                priv->channels.params = new_channels.params;
                goto out;
        }
index 19e3d2fc2099e09a987d0d475629580c72cd37c0..fcec7bedd3cd348f78ec25703d4e77a6e005f596 100644 (file)
 #include "eswitch.h"
 
 int mlx5_cmd_update_root_ft(struct mlx5_core_dev *dev,
-                           struct mlx5_flow_table *ft)
+                           struct mlx5_flow_table *ft, u32 underlay_qpn)
 {
        u32 in[MLX5_ST_SZ_DW(set_flow_table_root_in)]   = {0};
        u32 out[MLX5_ST_SZ_DW(set_flow_table_root_out)] = {0};
 
        if ((MLX5_CAP_GEN(dev, port_type) == MLX5_CAP_PORT_TYPE_IB) &&
-           ft->underlay_qpn == 0)
+           underlay_qpn == 0)
                return 0;
 
        MLX5_SET(set_flow_table_root_in, in, opcode,
                 MLX5_CMD_OP_SET_FLOW_TABLE_ROOT);
        MLX5_SET(set_flow_table_root_in, in, table_type, ft->type);
        MLX5_SET(set_flow_table_root_in, in, table_id, ft->id);
+       MLX5_SET(set_flow_table_root_in, in, underlay_qpn, underlay_qpn);
        if (ft->vport) {
                MLX5_SET(set_flow_table_root_in, in, vport_number, ft->vport);
                MLX5_SET(set_flow_table_root_in, in, other_vport, 1);
        }
 
-       if ((MLX5_CAP_GEN(dev, port_type) == MLX5_CAP_PORT_TYPE_IB) &&
-           ft->underlay_qpn != 0)
-               MLX5_SET(set_flow_table_root_in, in, underlay_qpn, ft->underlay_qpn);
-
        return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
 }
 
index 8fad806885362dce727791213422b7a9c0d5b897..0f98a7cf4877d8103ef03989e15d05eda570fdb2 100644 (file)
@@ -71,7 +71,8 @@ int mlx5_cmd_delete_fte(struct mlx5_core_dev *dev,
                        unsigned int index);
 
 int mlx5_cmd_update_root_ft(struct mlx5_core_dev *dev,
-                           struct mlx5_flow_table *ft);
+                           struct mlx5_flow_table *ft,
+                           u32 underlay_qpn);
 
 int mlx5_cmd_fc_alloc(struct mlx5_core_dev *dev, u16 *id);
 int mlx5_cmd_fc_free(struct mlx5_core_dev *dev, u16 id);
index b8a176503d384f863de75cacf7bd81d1f40ad9d8..0e487e8ca634bce0108979823e755918fe27c3fb 100644 (file)
@@ -650,7 +650,7 @@ static int update_root_ft_create(struct mlx5_flow_table *ft, struct fs_prio
        if (ft->level >= min_level)
                return 0;
 
-       err = mlx5_cmd_update_root_ft(root->dev, ft);
+       err = mlx5_cmd_update_root_ft(root->dev, ft, root->underlay_qpn);
        if (err)
                mlx5_core_warn(root->dev, "Update root flow table of id=%u failed\n",
                               ft->id);
@@ -818,8 +818,6 @@ static struct mlx5_flow_table *__mlx5_create_flow_table(struct mlx5_flow_namespa
                goto unlock_root;
        }
 
-       ft->underlay_qpn = ft_attr->underlay_qpn;
-
        tree_init_node(&ft->node, 1, del_flow_table);
        log_table_sz = ft->max_fte ? ilog2(ft->max_fte) : 0;
        next_ft = find_next_chained_ft(fs_prio);
@@ -1489,7 +1487,8 @@ static int update_root_ft_destroy(struct mlx5_flow_table *ft)
 
        new_root_ft = find_next_ft(ft);
        if (new_root_ft) {
-               int err = mlx5_cmd_update_root_ft(root->dev, new_root_ft);
+               int err = mlx5_cmd_update_root_ft(root->dev, new_root_ft,
+                                                 root->underlay_qpn);
 
                if (err) {
                        mlx5_core_warn(root->dev, "Update root flow table of id=%u failed\n",
@@ -2062,3 +2061,21 @@ err:
        mlx5_cleanup_fs(dev);
        return err;
 }
+
+int mlx5_fs_add_rx_underlay_qpn(struct mlx5_core_dev *dev, u32 underlay_qpn)
+{
+       struct mlx5_flow_root_namespace *root = dev->priv.steering->root_ns;
+
+       root->underlay_qpn = underlay_qpn;
+       return 0;
+}
+EXPORT_SYMBOL(mlx5_fs_add_rx_underlay_qpn);
+
+int mlx5_fs_remove_rx_underlay_qpn(struct mlx5_core_dev *dev, u32 underlay_qpn)
+{
+       struct mlx5_flow_root_namespace *root = dev->priv.steering->root_ns;
+
+       root->underlay_qpn = 0;
+       return 0;
+}
+EXPORT_SYMBOL(mlx5_fs_remove_rx_underlay_qpn);
index 81eafc7b9dd93fc4c8411aa8ad473299ca6c623e..990acee6fb091f102e7412c499df8df44eb806db 100644 (file)
@@ -118,7 +118,6 @@ struct mlx5_flow_table {
        /* FWD rules that point on this flow table */
        struct list_head                fwd_rules;
        u32                             flags;
-       u32                             underlay_qpn;
 };
 
 struct mlx5_fc_cache {
@@ -195,6 +194,7 @@ struct mlx5_flow_root_namespace {
        struct mlx5_flow_table          *root_ft;
        /* Should be held when chaining flow tables */
        struct mutex                    chain_lock;
+       u32                             underlay_qpn;
 };
 
 int mlx5_init_fc_stats(struct mlx5_core_dev *dev);
index 019c230da498f4d540cfb253a5c5f06edffeee05..cc1858752e70818650ca86a00795b3bb48668fb6 100644 (file)
@@ -66,6 +66,10 @@ static void mlx5i_init(struct mlx5_core_dev *mdev,
 
        mlx5e_build_nic_params(mdev, &priv->channels.params, profile->max_nch(mdev));
 
+       /* Override RQ params as IPoIB supports only LINKED LIST RQ for now */
+       mlx5e_set_rq_type_params(mdev, &priv->channels.params, MLX5_WQ_TYPE_LINKED_LIST);
+       priv->channels.params.lro_en = false;
+
        mutex_init(&priv->state_lock);
 
        netdev->hw_features    |= NETIF_F_SG;
@@ -156,6 +160,8 @@ out:
 
 static void mlx5i_destroy_underlay_qp(struct mlx5_core_dev *mdev, struct mlx5_core_qp *qp)
 {
+       mlx5_fs_remove_rx_underlay_qpn(mdev, qp->qpn);
+
        mlx5_core_destroy_qp(mdev, qp);
 }
 
@@ -170,6 +176,8 @@ static int mlx5i_init_tx(struct mlx5e_priv *priv)
                return err;
        }
 
+       mlx5_fs_add_rx_underlay_qpn(priv->mdev, ipriv->qp.qpn);
+
        err = mlx5e_create_tis(priv->mdev, 0 /* tc */, ipriv->qp.qpn, &priv->tisn[0]);
        if (err) {
                mlx5_core_warn(priv->mdev, "create tis failed, %d\n", err);
@@ -189,7 +197,6 @@ static void mlx5i_cleanup_tx(struct mlx5e_priv *priv)
 
 static int mlx5i_create_flow_steering(struct mlx5e_priv *priv)
 {
-       struct mlx5i_priv *ipriv = priv->ppriv;
        int err;
 
        priv->fs.ns = mlx5_get_flow_namespace(priv->mdev,
@@ -205,7 +212,7 @@ static int mlx5i_create_flow_steering(struct mlx5e_priv *priv)
                priv->netdev->hw_features &= ~NETIF_F_NTUPLE;
        }
 
-       err = mlx5e_create_ttc_table(priv, ipriv->qp.qpn);
+       err = mlx5e_create_ttc_table(priv);
        if (err) {
                netdev_err(priv->netdev, "Failed to create ttc table, err=%d\n",
                           err);
index b8d5270359cd8a7109226c0be1731cbafa6d1423..e306765155290a31e390f5ddcf88b4f0aa8f973c 100644 (file)
@@ -247,7 +247,7 @@ nx_fw_cmd_set_mtu(struct netxen_adapter *adapter, int mtu)
        cmd.req.arg3 = 0;
 
        if (recv_ctx->state == NX_HOST_CTX_STATE_ACTIVE)
-               netxen_issue_cmd(adapter, &cmd);
+               rcode = netxen_issue_cmd(adapter, &cmd);
 
        if (rcode != NX_RCODE_SUCCESS)
                return -EIO;
index 67200c5498ab01d3911735f25e6ccea05aed200e..0a8fde6299919b3c1e0d7382ac90be30631644e3 100644 (file)
@@ -983,7 +983,7 @@ void qed_set_rfs_mode_disable(struct qed_hwfn *p_hwfn,
        memset(&camline, 0, sizeof(union gft_cam_line_union));
        qed_wr(p_hwfn, p_ptt, PRS_REG_GFT_CAM + CAM_LINE_SIZE * pf_id,
               camline.cam_line_mapped.camline);
-       memset(&ramline, 0, sizeof(union gft_cam_line_union));
+       memset(&ramline, 0, sizeof(ramline));
 
        for (i = 0; i < RAM_LINE_SIZE / REG_SIZE; i++) {
                u32 hw_addr = PRS_REG_GFT_PROFILE_MASK_RAM;
index 49bad00a0f8f994837b0554f3250d5ca0811bff7..7245b1072518fff31566c471b6eb32b512e41846 100644 (file)
@@ -37,8 +37,8 @@
 
 #define _QLCNIC_LINUX_MAJOR 5
 #define _QLCNIC_LINUX_MINOR 3
-#define _QLCNIC_LINUX_SUBVERSION 65
-#define QLCNIC_LINUX_VERSIONID  "5.3.65"
+#define _QLCNIC_LINUX_SUBVERSION 66
+#define QLCNIC_LINUX_VERSIONID  "5.3.66"
 #define QLCNIC_DRV_IDC_VER  0x01
 #define QLCNIC_DRIVER_VERSION  ((_QLCNIC_LINUX_MAJOR << 16) |\
                 (_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION))
index 718bf58a7da66284e121f3aab8e79de7a6221c67..4fb68797630e9531e7ffc4e7bc7c015313a44063 100644 (file)
@@ -3168,6 +3168,40 @@ int qlcnic_83xx_flash_read32(struct qlcnic_adapter *adapter, u32 flash_addr,
        return 0;
 }
 
+void qlcnic_83xx_get_port_type(struct qlcnic_adapter *adapter)
+{
+       struct qlcnic_hardware_context *ahw = adapter->ahw;
+       struct qlcnic_cmd_args cmd;
+       u32 config;
+       int err;
+
+       err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_LINK_STATUS);
+       if (err)
+               return;
+
+       err = qlcnic_issue_cmd(adapter, &cmd);
+       if (err) {
+               dev_info(&adapter->pdev->dev,
+                        "Get Link Status Command failed: 0x%x\n", err);
+               goto out;
+       } else {
+               config = cmd.rsp.arg[3];
+
+               switch (QLC_83XX_SFP_MODULE_TYPE(config)) {
+               case QLC_83XX_MODULE_FIBRE_1000BASE_SX:
+               case QLC_83XX_MODULE_FIBRE_1000BASE_LX:
+               case QLC_83XX_MODULE_FIBRE_1000BASE_CX:
+               case QLC_83XX_MODULE_TP_1000BASE_T:
+                       ahw->port_type = QLCNIC_GBE;
+                       break;
+               default:
+                       ahw->port_type = QLCNIC_XGBE;
+               }
+       }
+out:
+       qlcnic_free_mbx_args(&cmd);
+}
+
 int qlcnic_83xx_test_link(struct qlcnic_adapter *adapter)
 {
        u8 pci_func;
index 3dfe8e27b51c68de0af32af949b096d247e3ccb0..b75a812468569de7728fd9c654b6f1c7e353729f 100644 (file)
@@ -637,6 +637,7 @@ void qlcnic_83xx_get_pauseparam(struct qlcnic_adapter *,
 int qlcnic_83xx_set_pauseparam(struct qlcnic_adapter *,
                               struct ethtool_pauseparam *);
 int qlcnic_83xx_test_link(struct qlcnic_adapter *);
+void qlcnic_83xx_get_port_type(struct qlcnic_adapter *adapter);
 int qlcnic_83xx_reg_test(struct qlcnic_adapter *);
 int qlcnic_83xx_get_regs_len(struct qlcnic_adapter *);
 int qlcnic_83xx_get_registers(struct qlcnic_adapter *, u32 *);
index 9a869c15d8bfbfc64b48a831a2b4eb7b38160714..7f7deeaf1cf07913454a13b4f7801c7b3b07545f 100644 (file)
@@ -486,6 +486,9 @@ static int qlcnic_set_link_ksettings(struct net_device *dev,
        u32 ret = 0;
        struct qlcnic_adapter *adapter = netdev_priv(dev);
 
+       if (qlcnic_83xx_check(adapter))
+               qlcnic_83xx_get_port_type(adapter);
+
        if (adapter->ahw->port_type != QLCNIC_GBE)
                return -EOPNOTSUPP;
 
index 513e6c74e1990b6fb2c8b00ee9f5a4b70076115d..24ca7df15d07d48a4214bd5df38edcceb6d284aa 100644 (file)
@@ -296,8 +296,9 @@ qcaspi_receive(struct qcaspi *qca)
 
        /* Allocate rx SKB if we don't have one available. */
        if (!qca->rx_skb) {
-               qca->rx_skb = netdev_alloc_skb(net_dev,
-                                              net_dev->mtu + VLAN_ETH_HLEN);
+               qca->rx_skb = netdev_alloc_skb_ip_align(net_dev,
+                                                       net_dev->mtu +
+                                                       VLAN_ETH_HLEN);
                if (!qca->rx_skb) {
                        netdev_dbg(net_dev, "out of RX resources\n");
                        qca->stats.out_of_mem++;
@@ -377,7 +378,7 @@ qcaspi_receive(struct qcaspi *qca)
                                        qca->rx_skb, qca->rx_skb->dev);
                                qca->rx_skb->ip_summed = CHECKSUM_UNNECESSARY;
                                netif_rx_ni(qca->rx_skb);
-                               qca->rx_skb = netdev_alloc_skb(net_dev,
+                               qca->rx_skb = netdev_alloc_skb_ip_align(net_dev,
                                        net_dev->mtu + VLAN_ETH_HLEN);
                                if (!qca->rx_skb) {
                                        netdev_dbg(net_dev, "out of RX resources\n");
@@ -759,7 +760,8 @@ qcaspi_netdev_init(struct net_device *dev)
        if (!qca->rx_buffer)
                return -ENOBUFS;
 
-       qca->rx_skb = netdev_alloc_skb(dev, qca->net_dev->mtu + VLAN_ETH_HLEN);
+       qca->rx_skb = netdev_alloc_skb_ip_align(dev, qca->net_dev->mtu +
+                                               VLAN_ETH_HLEN);
        if (!qca->rx_skb) {
                kfree(qca->rx_buffer);
                netdev_info(qca->net_dev, "Failed to allocate RX sk_buff.\n");
index 7b916aa21bdef18896debc4bdd7384696e50f3a3..4d7fb8af880d0f36189f8475a9859b229a7bd078 100644 (file)
 #include "mcdi.h"
 
 enum {
-       EFX_REV_SIENA_A0 = 0,
-       EFX_REV_HUNT_A0 = 1,
+       /* Revisions 0-2 were Falcon A0, A1 and B0 respectively.
+        * They are not supported by this driver but these revision numbers
+        * form part of the ethtool API for register dumping.
+        */
+       EFX_REV_SIENA_A0 = 3,
+       EFX_REV_HUNT_A0 = 4,
 };
 
 static inline int efx_nic_rev(struct efx_nic *efx)
index cd8c601323905a7ded2504fa69faa54a1c728066..a74c481401c46ee659b1244b0124966cabeafdbd 100644 (file)
@@ -3725,7 +3725,7 @@ static void sysfs_display_ring(void *head, int size, int extend_desc,
                        ep++;
                } else {
                        seq_printf(seq, "%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n",
-                                  i, (unsigned int)virt_to_phys(ep),
+                                  i, (unsigned int)virt_to_phys(p),
                                   le32_to_cpu(p->des0), le32_to_cpu(p->des1),
                                   le32_to_cpu(p->des2), le32_to_cpu(p->des3));
                        p++;
index 5a90fed0626065613ba59fa7c5f8ca3c2dff6ef3..5b56c24b6ed2e0c45b5a40d32941527bb1539390 100644 (file)
@@ -411,13 +411,14 @@ static int vsw_port_remove(struct vio_dev *vdev)
 
        if (port) {
                del_timer_sync(&port->vio.timer);
+               del_timer_sync(&port->clean_timer);
 
                napi_disable(&port->napi);
+               unregister_netdev(port->dev);
 
                list_del_rcu(&port->list);
 
                synchronize_rcu();
-               del_timer_sync(&port->clean_timer);
                spin_lock_irqsave(&port->vp->lock, flags);
                sunvnet_port_rm_txq_common(port);
                spin_unlock_irqrestore(&port->vp->lock, flags);
@@ -427,7 +428,6 @@ static int vsw_port_remove(struct vio_dev *vdev)
 
                dev_set_drvdata(&vdev->dev, NULL);
 
-               unregister_netdev(port->dev);
                free_netdev(port->dev);
        }
 
index 729a7da90b5bed279d58d72cfc53cfa6fc2e9c80..e6222e535019a076ea0d4cd4c902f12332f079b2 100644 (file)
@@ -1353,9 +1353,10 @@ int netcp_txpipe_open(struct netcp_tx_pipe *tx_pipe)
 
        tx_pipe->dma_channel = knav_dma_open_channel(dev,
                                tx_pipe->dma_chan_name, &config);
-       if (IS_ERR_OR_NULL(tx_pipe->dma_channel)) {
+       if (IS_ERR(tx_pipe->dma_channel)) {
                dev_err(dev, "failed opening tx chan(%s)\n",
                        tx_pipe->dma_chan_name);
+               ret = PTR_ERR(tx_pipe->dma_channel);
                goto err;
        }
 
@@ -1673,9 +1674,10 @@ static int netcp_setup_navigator_resources(struct net_device *ndev)
 
        netcp->rx_channel = knav_dma_open_channel(netcp->netcp_device->device,
                                        netcp->dma_chan_name, &config);
-       if (IS_ERR_OR_NULL(netcp->rx_channel)) {
+       if (IS_ERR(netcp->rx_channel)) {
                dev_err(netcp->ndev_dev, "failed opening rx chan(%s\n",
                        netcp->dma_chan_name);
+               ret = PTR_ERR(netcp->rx_channel);
                goto fail;
        }
 
index 897176fc5043bf0da12fe5dcb7a659c269fdf615..dd92950a4615c3aab559c6dc383a4e90ee539160 100644 (file)
@@ -2651,7 +2651,6 @@ static int gbe_hwtstamp_set(struct gbe_intf *gbe_intf, struct ifreq *ifr)
        case HWTSTAMP_FILTER_NONE:
                cpts_rx_enable(cpts, 0);
                break;
-       case HWTSTAMP_FILTER_ALL:
        case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
        case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
        case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
index 8716b8c07febf5669b5fe21d78f1b68b4d10ea3f..6f3c805f72118b1b04b48cc501b8579caeddf37a 100644 (file)
@@ -1077,7 +1077,7 @@ static int stir421x_patch_device(struct irda_usb_cb *self)
          * are "42101001.sb" or "42101002.sb"
          */
         sprintf(stir421x_fw_name, "4210%4X.sb",
-                self->usbdev->descriptor.bcdDevice);
+               le16_to_cpu(self->usbdev->descriptor.bcdDevice));
         ret = request_firmware(&fw, stir421x_fw_name, &self->usbdev->dev);
         if (ret < 0)
                 return ret;
index b34eaaae03fd3f289aab4a90b11c05c587858ad2..346ad2ff39989d3da4cacc6ec1965ca882c475cd 100644 (file)
@@ -789,10 +789,12 @@ static int macvlan_change_mtu(struct net_device *dev, int new_mtu)
  */
 static struct lock_class_key macvlan_netdev_addr_lock_key;
 
-#define ALWAYS_ON_FEATURES \
-       (NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_GSO_SOFTWARE | NETIF_F_LLTX | \
+#define ALWAYS_ON_OFFLOADS \
+       (NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_GSO_SOFTWARE | \
         NETIF_F_GSO_ROBUST)
 
+#define ALWAYS_ON_FEATURES (ALWAYS_ON_OFFLOADS | NETIF_F_LLTX)
+
 #define MACVLAN_FEATURES \
        (NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST | \
         NETIF_F_GSO | NETIF_F_TSO | NETIF_F_UFO | NETIF_F_LRO | \
@@ -827,6 +829,7 @@ static int macvlan_init(struct net_device *dev)
        dev->features           |= ALWAYS_ON_FEATURES;
        dev->hw_features        |= NETIF_F_LRO;
        dev->vlan_features      = lowerdev->vlan_features & MACVLAN_FEATURES;
+       dev->vlan_features      |= ALWAYS_ON_OFFLOADS;
        dev->gso_max_size       = lowerdev->gso_max_size;
        dev->gso_max_segs       = lowerdev->gso_max_segs;
        dev->hard_header_len    = lowerdev->hard_header_len;
index 963838d4fac12428e0c01f88537a72b4a2fd8703..599ce24c514f1b0eb1e8a6df1e3a0362f53bee26 100644 (file)
@@ -122,10 +122,9 @@ int mdio_mux_init(struct device *dev,
        pb = devm_kzalloc(dev, sizeof(*pb), GFP_KERNEL);
        if (pb == NULL) {
                ret_val = -ENOMEM;
-               goto err_parent_bus;
+               goto err_pb_kz;
        }
 
-
        pb->switch_data = data;
        pb->switch_fn = switch_fn;
        pb->current_child = -1;
@@ -154,6 +153,7 @@ int mdio_mux_init(struct device *dev,
                cb->mii_bus = mdiobus_alloc();
                if (!cb->mii_bus) {
                        ret_val = -ENOMEM;
+                       devm_kfree(dev, cb);
                        of_node_put(child_bus_node);
                        break;
                }
@@ -170,7 +170,6 @@ int mdio_mux_init(struct device *dev,
                        mdiobus_free(cb->mii_bus);
                        devm_kfree(dev, cb);
                } else {
-                       of_node_get(child_bus_node);
                        cb->next = pb->children;
                        pb->children = cb;
                }
@@ -181,9 +180,11 @@ int mdio_mux_init(struct device *dev,
                return 0;
        }
 
+       devm_kfree(dev, pb);
+err_pb_kz:
        /* balance the reference of_mdio_find_bus() took */
-       put_device(&pb->mii_bus->dev);
-
+       if (!mux_bus)
+               put_device(&parent_bus->dev);
 err_parent_bus:
        of_node_put(parent_bus_node);
        return ret_val;
index a898e5c4ef1b465768c3216fc1985382c23eba89..8e73f5f36e7120a5aa28b6e0dfb992eca3330e3e 100644 (file)
@@ -364,9 +364,6 @@ int __mdiobus_register(struct mii_bus *bus, struct module *owner)
 
        mutex_init(&bus->mdio_lock);
 
-       if (bus->reset)
-               bus->reset(bus);
-
        /* de-assert bus level PHY GPIO resets */
        if (bus->num_reset_gpios > 0) {
                bus->reset_gpiod = devm_kcalloc(&bus->dev,
@@ -396,6 +393,9 @@ int __mdiobus_register(struct mii_bus *bus, struct module *owner)
                }
        }
 
+       if (bus->reset)
+               bus->reset(bus);
+
        for (i = 0; i < PHY_MAX_ADDR; i++) {
                if ((bus->phy_mask & (1 << i)) == 0) {
                        struct phy_device *phydev;
index c4f1c363e24b89404c6834312074f8a4451ded50..9df3c1ffff355c491ab7f0a38bdddd0276cfff92 100644 (file)
@@ -310,8 +310,8 @@ static int get_mac_address(struct usbnet *dev, unsigned char *data)
        int rd_mac_len = 0;
 
        netdev_dbg(dev->net, "get_mac_address:\n\tusbnet VID:%0x PID:%0x\n",
-                  dev->udev->descriptor.idVendor,
-                  dev->udev->descriptor.idProduct);
+                  le16_to_cpu(dev->udev->descriptor.idVendor),
+                  le16_to_cpu(dev->udev->descriptor.idProduct));
 
        memset(mac_addr, 0, sizeof(mac_addr));
        rd_mac_len = control_read(dev, REQUEST_READ, 0,
index 25bc764ae7dc4c4dc9a5e6cb4f17f89f62464f4c..d1c7029ded7cefef468eb035f971b969da612bf5 100644 (file)
@@ -2962,6 +2962,11 @@ vmxnet3_force_close(struct vmxnet3_adapter *adapter)
        /* we need to enable NAPI, otherwise dev_close will deadlock */
        for (i = 0; i < adapter->num_rx_queues; i++)
                napi_enable(&adapter->rx_queue[i].napi);
+       /*
+        * Need to clear the quiesce bit to ensure that vmxnet3_close
+        * can quiesce the device properly
+        */
+       clear_bit(VMXNET3_STATE_BIT_QUIESCED, &adapter->state);
        dev_close(adapter->netdev);
 }
 
index ceda5861da780bc64b6070acec7f37de9a8fa3e5..db882493875cd97d30ac5a2b26a764a5b65d9e2e 100644 (file)
@@ -989,6 +989,7 @@ static u32 vrf_fib_table(const struct net_device *dev)
 
 static int vrf_rcv_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
 {
+       kfree_skb(skb);
        return 0;
 }
 
@@ -998,7 +999,7 @@ static struct sk_buff *vrf_rcv_nfhook(u8 pf, unsigned int hook,
 {
        struct net *net = dev_net(dev);
 
-       if (NF_HOOK(pf, hook, net, NULL, skb, dev, NULL, vrf_rcv_finish) < 0)
+       if (nf_hook(pf, hook, net, NULL, skb, dev, NULL, vrf_rcv_finish) != 1)
                skb = NULL;    /* kfree_skb(skb) handled by nf code */
 
        return skb;
index 6ffc482550c1d24f9b795f1ab3951101fd901f1c..7b61adb6270c99f8c70f1efa7575b1bb62d96f45 100644 (file)
@@ -1934,8 +1934,7 @@ abort_transaction_no_dev_fatal:
        xennet_disconnect_backend(info);
        xennet_destroy_queues(info);
  out:
-       unregister_netdev(info->netdev);
-       xennet_free_netdev(info->netdev);
+       device_unregister(&dev->dev);
        return err;
 }
 
index e443b0d0b23612efec3800a5468e36e58ef7f8d3..34b9ad6b31438fb8864a9068d7f72294722da169 100644 (file)
@@ -35,7 +35,7 @@ static struct bus_type ccwgroup_bus_type;
 static void __ccwgroup_remove_symlinks(struct ccwgroup_device *gdev)
 {
        int i;
-       char str[8];
+       char str[16];
 
        for (i = 0; i < gdev->count; i++) {
                sprintf(str, "cdev%d", i);
@@ -238,7 +238,7 @@ static void ccwgroup_release(struct device *dev)
 
 static int __ccwgroup_create_symlinks(struct ccwgroup_device *gdev)
 {
-       char str[8];
+       char str[16];
        int i, rc;
 
        for (i = 0; i < gdev->count; i++) {
index f33ce85776190ab938548dccbc84fb311d3703fd..1d595d17bf11f6b529eca2caafc494721130b32c 100644 (file)
@@ -11,7 +11,7 @@
 #include "qdio.h"
 
 /* that gives us 15 characters in the text event views */
-#define QDIO_DBF_LEN   16
+#define QDIO_DBF_LEN   32
 
 extern debug_info_t *qdio_dbf_setup;
 extern debug_info_t *qdio_dbf_error;
index f6aa21176d89780e9e745f9045255ff37f1cf788..30bc6105aac3731f2bfad5ffd0d4f14f07f9d291 100644 (file)
@@ -701,6 +701,7 @@ enum qeth_discipline_id {
 };
 
 struct qeth_discipline {
+       const struct device_type *devtype;
        void (*start_poll)(struct ccw_device *, int, unsigned long);
        qdio_handler_t *input_handler;
        qdio_handler_t *output_handler;
@@ -875,6 +876,9 @@ extern struct qeth_discipline qeth_l2_discipline;
 extern struct qeth_discipline qeth_l3_discipline;
 extern const struct attribute_group *qeth_generic_attr_groups[];
 extern const struct attribute_group *qeth_osn_attr_groups[];
+extern const struct attribute_group qeth_device_attr_group;
+extern const struct attribute_group qeth_device_blkt_group;
+extern const struct device_type qeth_generic_devtype;
 extern struct workqueue_struct *qeth_wq;
 
 int qeth_card_hw_is_reachable(struct qeth_card *);
index 38114a8d56e00f471360ab400767dcb8ba8a1a7b..fc6d85f2b38d60d4c1b62bd169776d5cfcabcc52 100644 (file)
@@ -5530,10 +5530,12 @@ void qeth_core_free_discipline(struct qeth_card *card)
        card->discipline = NULL;
 }
 
-static const struct device_type qeth_generic_devtype = {
+const struct device_type qeth_generic_devtype = {
        .name = "qeth_generic",
        .groups = qeth_generic_attr_groups,
 };
+EXPORT_SYMBOL_GPL(qeth_generic_devtype);
+
 static const struct device_type qeth_osn_devtype = {
        .name = "qeth_osn",
        .groups = qeth_osn_attr_groups,
@@ -5659,23 +5661,22 @@ static int qeth_core_probe_device(struct ccwgroup_device *gdev)
                goto err_card;
        }
 
-       if (card->info.type == QETH_CARD_TYPE_OSN)
-               gdev->dev.type = &qeth_osn_devtype;
-       else
-               gdev->dev.type = &qeth_generic_devtype;
-
        switch (card->info.type) {
        case QETH_CARD_TYPE_OSN:
        case QETH_CARD_TYPE_OSM:
                rc = qeth_core_load_discipline(card, QETH_DISCIPLINE_LAYER2);
                if (rc)
                        goto err_card;
+
+               gdev->dev.type = (card->info.type != QETH_CARD_TYPE_OSN)
+                                       ? card->discipline->devtype
+                                       : &qeth_osn_devtype;
                rc = card->discipline->setup(card->gdev);
                if (rc)
                        goto err_disc;
-       case QETH_CARD_TYPE_OSD:
-       case QETH_CARD_TYPE_OSX:
+               break;
        default:
+               gdev->dev.type = &qeth_generic_devtype;
                break;
        }
 
@@ -5731,8 +5732,10 @@ static int qeth_core_set_online(struct ccwgroup_device *gdev)
                if (rc)
                        goto err;
                rc = card->discipline->setup(card->gdev);
-               if (rc)
+               if (rc) {
+                       qeth_core_free_discipline(card);
                        goto err;
+               }
        }
        rc = card->discipline->set_online(gdev);
 err:
index 75b29fd2fcf4eab64e82b23b1183fe88211d97ba..db6a285d41e033674706543c2353c0312046e331 100644 (file)
@@ -413,12 +413,16 @@ static ssize_t qeth_dev_layer2_store(struct device *dev,
 
        if (card->options.layer2 == newdis)
                goto out;
-       else {
-               card->info.mac_bits  = 0;
-               if (card->discipline) {
-                       card->discipline->remove(card->gdev);
-                       qeth_core_free_discipline(card);
-               }
+       if (card->info.type == QETH_CARD_TYPE_OSM) {
+               /* fixed layer, can't switch */
+               rc = -EOPNOTSUPP;
+               goto out;
+       }
+
+       card->info.mac_bits = 0;
+       if (card->discipline) {
+               card->discipline->remove(card->gdev);
+               qeth_core_free_discipline(card);
        }
 
        rc = qeth_core_load_discipline(card, newdis);
@@ -426,6 +430,8 @@ static ssize_t qeth_dev_layer2_store(struct device *dev,
                goto out;
 
        rc = card->discipline->setup(card->gdev);
+       if (rc)
+               qeth_core_free_discipline(card);
 out:
        mutex_unlock(&card->discipline_mutex);
        return rc ? rc : count;
@@ -703,10 +709,11 @@ static struct attribute *qeth_blkt_device_attrs[] = {
        &dev_attr_inter_jumbo.attr,
        NULL,
 };
-static struct attribute_group qeth_device_blkt_group = {
+const struct attribute_group qeth_device_blkt_group = {
        .name = "blkt",
        .attrs = qeth_blkt_device_attrs,
 };
+EXPORT_SYMBOL_GPL(qeth_device_blkt_group);
 
 static struct attribute *qeth_device_attrs[] = {
        &dev_attr_state.attr,
@@ -726,9 +733,10 @@ static struct attribute *qeth_device_attrs[] = {
        &dev_attr_switch_attrs.attr,
        NULL,
 };
-static struct attribute_group qeth_device_attr_group = {
+const struct attribute_group qeth_device_attr_group = {
        .attrs = qeth_device_attrs,
 };
+EXPORT_SYMBOL_GPL(qeth_device_attr_group);
 
 const struct attribute_group *qeth_generic_attr_groups[] = {
        &qeth_device_attr_group,
index 29d9fb3890ad570826db6d54b1396c149f83fcb5..0d59f9a45ea9e3c52ba4eee9cbc7b37b433dd449 100644 (file)
@@ -8,6 +8,8 @@
 
 #include "qeth_core.h"
 
+extern const struct attribute_group *qeth_l2_attr_groups[];
+
 int qeth_l2_create_device_attributes(struct device *);
 void qeth_l2_remove_device_attributes(struct device *);
 void qeth_l2_setup_bridgeport_attrs(struct qeth_card *card);
index 1b07f382d74c955974d138271bdce2bbbf594f63..bd2df62a5cdf50a85243a878ed98d4d1784b9106 100644 (file)
@@ -880,11 +880,21 @@ static int qeth_l2_stop(struct net_device *dev)
        return 0;
 }
 
+static const struct device_type qeth_l2_devtype = {
+       .name = "qeth_layer2",
+       .groups = qeth_l2_attr_groups,
+};
+
 static int qeth_l2_probe_device(struct ccwgroup_device *gdev)
 {
        struct qeth_card *card = dev_get_drvdata(&gdev->dev);
+       int rc;
 
-       qeth_l2_create_device_attributes(&gdev->dev);
+       if (gdev->dev.type == &qeth_generic_devtype) {
+               rc = qeth_l2_create_device_attributes(&gdev->dev);
+               if (rc)
+                       return rc;
+       }
        INIT_LIST_HEAD(&card->vid_list);
        hash_init(card->mac_htable);
        card->options.layer2 = 1;
@@ -896,7 +906,8 @@ static void qeth_l2_remove_device(struct ccwgroup_device *cgdev)
 {
        struct qeth_card *card = dev_get_drvdata(&cgdev->dev);
 
-       qeth_l2_remove_device_attributes(&cgdev->dev);
+       if (cgdev->dev.type == &qeth_generic_devtype)
+               qeth_l2_remove_device_attributes(&cgdev->dev);
        qeth_set_allowed_threads(card, 0, 1);
        wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0);
 
@@ -954,7 +965,6 @@ static int qeth_l2_setup_netdev(struct qeth_card *card)
        case QETH_CARD_TYPE_OSN:
                card->dev = alloc_netdev(0, "osn%d", NET_NAME_UNKNOWN,
                                         ether_setup);
-               card->dev->flags |= IFF_NOARP;
                break;
        default:
                card->dev = alloc_etherdev(0);
@@ -969,9 +979,12 @@ static int qeth_l2_setup_netdev(struct qeth_card *card)
        card->dev->min_mtu = 64;
        card->dev->max_mtu = ETH_MAX_MTU;
        card->dev->netdev_ops = &qeth_l2_netdev_ops;
-       card->dev->ethtool_ops =
-               (card->info.type != QETH_CARD_TYPE_OSN) ?
-               &qeth_l2_ethtool_ops : &qeth_l2_osn_ops;
+       if (card->info.type == QETH_CARD_TYPE_OSN) {
+               card->dev->ethtool_ops = &qeth_l2_osn_ops;
+               card->dev->flags |= IFF_NOARP;
+       } else {
+               card->dev->ethtool_ops = &qeth_l2_ethtool_ops;
+       }
        card->dev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
        if (card->info.type == QETH_CARD_TYPE_OSD && !card->info.guestlan) {
                card->dev->hw_features = NETIF_F_SG;
@@ -1269,6 +1282,7 @@ static int qeth_l2_control_event(struct qeth_card *card,
 }
 
 struct qeth_discipline qeth_l2_discipline = {
+       .devtype = &qeth_l2_devtype,
        .start_poll = qeth_qdio_start_poll,
        .input_handler = (qdio_handler_t *) qeth_qdio_input_handler,
        .output_handler = (qdio_handler_t *) qeth_qdio_output_handler,
index 687972356d6b00f8776cb332e31b1ae0063183a5..9696baa49e2d4409062be4338ea383472a7d4ab0 100644 (file)
@@ -269,3 +269,11 @@ void qeth_l2_setup_bridgeport_attrs(struct qeth_card *card)
        } else
                qeth_bridgeport_an_set(card, 0);
 }
+
+const struct attribute_group *qeth_l2_attr_groups[] = {
+       &qeth_device_attr_group,
+       &qeth_device_blkt_group,
+       /* l2 specific, see l2_{create,remove}_device_attributes(): */
+       &qeth_l2_bridgeport_attr_group,
+       NULL,
+};
index 6e0354ef4b8629827e4c8ef40b9d569bc11e354b..d8df1e6351636250ea534cf17527c8fb198435f2 100644 (file)
@@ -3039,8 +3039,13 @@ static int qeth_l3_setup_netdev(struct qeth_card *card)
 static int qeth_l3_probe_device(struct ccwgroup_device *gdev)
 {
        struct qeth_card *card = dev_get_drvdata(&gdev->dev);
+       int rc;
 
-       qeth_l3_create_device_attributes(&gdev->dev);
+       rc = qeth_l3_create_device_attributes(&gdev->dev);
+       if (rc)
+               return rc;
+       hash_init(card->ip_htable);
+       hash_init(card->ip_mc_htable);
        card->options.layer2 = 0;
        card->info.hwtrap = 0;
        return 0;
@@ -3306,6 +3311,7 @@ static int qeth_l3_control_event(struct qeth_card *card,
 }
 
 struct qeth_discipline qeth_l3_discipline = {
+       .devtype = &qeth_generic_devtype,
        .start_poll = qeth_qdio_start_poll,
        .input_handler = (qdio_handler_t *) qeth_qdio_input_handler,
        .output_handler = (qdio_handler_t *) qeth_qdio_output_handler,
index 2a76ea78a0bf1ae9f62508e701cca07a9f690d1f..b18fe2014cf2195a193186c08c956dc8e5cfe7e3 100644 (file)
@@ -87,7 +87,7 @@ struct vq_info_block {
 } __packed;
 
 struct virtio_feature_desc {
-       __u32 features;
+       __le32 features;
        __u8 index;
 } __packed;
 
index ecebe2eecc3aac5058de888817b719f42934d526..026182d3b27c1405a9b875d529795a2e8295a0aa 100644 (file)
@@ -413,7 +413,7 @@ static int of_channel_match_helper(struct device_node *np, const char *name,
  * @name:      slave channel name
  * @config:    dma configuration parameters
  *
- * Returns pointer to appropriate DMA channel on success or NULL.
+ * Returns pointer to appropriate DMA channel on success or error.
  */
 void *knav_dma_open_channel(struct device *dev, const char *name,
                                        struct knav_dma_cfg *config)
index 15bac390dff945d7fa5d785f666b2b0291fb9f65..b98436f5c7c74f9e773db0485bb9e80fcb43be99 100644 (file)
@@ -1135,20 +1135,19 @@ cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
        u32 acllen = 0;
        int rc = 0;
        struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
-       struct cifs_tcon *tcon;
+       struct smb_version_operations *ops;
 
        cifs_dbg(NOISY, "converting ACL to mode for %s\n", path);
 
        if (IS_ERR(tlink))
                return PTR_ERR(tlink);
-       tcon = tlink_tcon(tlink);
 
-       if (pfid && (tcon->ses->server->ops->get_acl_by_fid))
-               pntsd = tcon->ses->server->ops->get_acl_by_fid(cifs_sb, pfid,
-                                                         &acllen);
-       else if (tcon->ses->server->ops->get_acl)
-               pntsd = tcon->ses->server->ops->get_acl(cifs_sb, inode, path,
-                                                       &acllen);
+       ops = tlink_tcon(tlink)->ses->server->ops;
+
+       if (pfid && (ops->get_acl_by_fid))
+               pntsd = ops->get_acl_by_fid(cifs_sb, pfid, &acllen);
+       else if (ops->get_acl)
+               pntsd = ops->get_acl(cifs_sb, inode, path, &acllen);
        else {
                cifs_put_tlink(tlink);
                return -EOPNOTSUPP;
@@ -1181,23 +1180,23 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode,
        struct cifs_ntsd *pnntsd = NULL; /* modified acl to be sent to server */
        struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
        struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
-       struct cifs_tcon *tcon;
+       struct smb_version_operations *ops;
 
        if (IS_ERR(tlink))
                return PTR_ERR(tlink);
-       tcon = tlink_tcon(tlink);
+
+       ops = tlink_tcon(tlink)->ses->server->ops;
 
        cifs_dbg(NOISY, "set ACL from mode for %s\n", path);
 
        /* Get the security descriptor */
 
-       if (tcon->ses->server->ops->get_acl == NULL) {
+       if (ops->get_acl == NULL) {
                cifs_put_tlink(tlink);
                return -EOPNOTSUPP;
        }
 
-       pntsd = tcon->ses->server->ops->get_acl(cifs_sb, inode, path,
-                                               &secdesclen);
+       pntsd = ops->get_acl(cifs_sb, inode, path, &secdesclen);
        if (IS_ERR(pntsd)) {
                rc = PTR_ERR(pntsd);
                cifs_dbg(VFS, "%s: error %d getting sec desc\n", __func__, rc);
@@ -1224,13 +1223,12 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode,
 
        cifs_dbg(NOISY, "build_sec_desc rc: %d\n", rc);
 
-       if (tcon->ses->server->ops->set_acl == NULL)
+       if (ops->set_acl == NULL)
                rc = -EOPNOTSUPP;
 
        if (!rc) {
                /* Set the security descriptor */
-               rc = tcon->ses->server->ops->set_acl(pnntsd, secdesclen, inode,
-                                                    path, aclflag);
+               rc = ops->set_acl(pnntsd, secdesclen, inode, path, aclflag);
                cifs_dbg(NOISY, "set_cifs_acl rc: %d\n", rc);
        }
        cifs_put_tlink(tlink);
index 8be55be70faf6c278de7b7c623501385bf21acaf..bcc7d9acad64b3a59b9c966956accb2c51d9ac13 100644 (file)
@@ -418,7 +418,7 @@ struct smb_version_operations {
        int (*validate_negotiate)(const unsigned int, struct cifs_tcon *);
        ssize_t (*query_all_EAs)(const unsigned int, struct cifs_tcon *,
                        const unsigned char *, const unsigned char *, char *,
-                       size_t, const struct nls_table *, int);
+                       size_t, struct cifs_sb_info *);
        int (*set_EA)(const unsigned int, struct cifs_tcon *, const char *,
                        const char *, const void *, const __u16,
                        const struct nls_table *, int);
index e49958c3f8bbded4265b71e47a87d736a34676da..6eb3147132e30c2225b610b01281111bb896c617 100644 (file)
@@ -480,8 +480,7 @@ extern int CIFSSMBCopy(unsigned int xid,
 extern ssize_t CIFSSMBQAllEAs(const unsigned int xid, struct cifs_tcon *tcon,
                        const unsigned char *searchName,
                        const unsigned char *ea_name, char *EAData,
-                       size_t bufsize, const struct nls_table *nls_codepage,
-                       int remap_special_chars);
+                       size_t bufsize, struct cifs_sb_info *cifs_sb);
 extern int CIFSSMBSetEA(const unsigned int xid, struct cifs_tcon *tcon,
                const char *fileName, const char *ea_name,
                const void *ea_value, const __u16 ea_value_len,
index 4c01b3f9abf02efb70648e030998220bab13bd55..fbb0d4cbda413e5349ab97c8fdfe65435efdc6ed 100644 (file)
@@ -697,9 +697,7 @@ cifs_echo_callback(struct mid_q_entry *mid)
 {
        struct TCP_Server_Info *server = mid->callback_data;
 
-       mutex_lock(&server->srv_mutex);
        DeleteMidQEntry(mid);
-       mutex_unlock(&server->srv_mutex);
        add_credits(server, 1, CIFS_ECHO_OP);
 }
 
@@ -1599,9 +1597,7 @@ cifs_readv_callback(struct mid_q_entry *mid)
        }
 
        queue_work(cifsiod_wq, &rdata->work);
-       mutex_lock(&server->srv_mutex);
        DeleteMidQEntry(mid);
-       mutex_unlock(&server->srv_mutex);
        add_credits(server, 1, 0);
 }
 
@@ -2058,7 +2054,6 @@ cifs_writev_callback(struct mid_q_entry *mid)
 {
        struct cifs_writedata *wdata = mid->callback_data;
        struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
-       struct TCP_Server_Info *server = tcon->ses->server;
        unsigned int written;
        WRITE_RSP *smb = (WRITE_RSP *)mid->resp_buf;
 
@@ -2095,9 +2090,7 @@ cifs_writev_callback(struct mid_q_entry *mid)
        }
 
        queue_work(cifsiod_wq, &wdata->work);
-       mutex_lock(&server->srv_mutex);
        DeleteMidQEntry(mid);
-       mutex_unlock(&server->srv_mutex);
        add_credits(tcon->ses->server, 1, 0);
 }
 
@@ -6076,11 +6069,13 @@ ssize_t
 CIFSSMBQAllEAs(const unsigned int xid, struct cifs_tcon *tcon,
                const unsigned char *searchName, const unsigned char *ea_name,
                char *EAData, size_t buf_size,
-               const struct nls_table *nls_codepage, int remap)
+               struct cifs_sb_info *cifs_sb)
 {
                /* BB assumes one setup word */
        TRANSACTION2_QPI_REQ *pSMB = NULL;
        TRANSACTION2_QPI_RSP *pSMBr = NULL;
+       int remap = cifs_remap(cifs_sb);
+       struct nls_table *nls_codepage = cifs_sb->local_nls;
        int rc = 0;
        int bytes_returned;
        int list_len;
index 6ef78ad838e6e3e8b4cf24e72de24fcba8e4313c..0fd081bd2a2f5d3fb4ed18fdcb7a1371cf9f5627 100644 (file)
@@ -582,7 +582,7 @@ cifs_relock_file(struct cifsFileInfo *cfile)
        struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
        int rc = 0;
 
-       down_read(&cinode->lock_sem);
+       down_read_nested(&cinode->lock_sem, SINGLE_DEPTH_NESTING);
        if (cinode->can_cache_brlcks) {
                /* can cache locks - no need to relock */
                up_read(&cinode->lock_sem);
index c3b2fa0b2ec8a6ceed83a74b65bd60cc1e1a7cee..4d1fcd76d022f6848c16294411d5a937e053e27a 100644 (file)
@@ -563,8 +563,7 @@ static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path,
 
        rc = tcon->ses->server->ops->query_all_EAs(xid, tcon, path,
                        "SETFILEBITS", ea_value, 4 /* size of buf */,
-                       cifs_sb->local_nls,
-                       cifs_remap(cifs_sb));
+                       cifs_sb);
        cifs_put_tlink(tlink);
        if (rc < 0)
                return (int)rc;
index 48ff7703b91912c79b8412539919c3ce6fe76ac6..e4afdaae743f28cf2d1396faed88e7465f875d48 100644 (file)
@@ -1240,15 +1240,19 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
                goto tcon_exit;
        }
 
-       if (rsp->ShareType & SMB2_SHARE_TYPE_DISK)
+       switch (rsp->ShareType) {
+       case SMB2_SHARE_TYPE_DISK:
                cifs_dbg(FYI, "connection to disk share\n");
-       else if (rsp->ShareType & SMB2_SHARE_TYPE_PIPE) {
+               break;
+       case SMB2_SHARE_TYPE_PIPE:
                tcon->ipc = true;
                cifs_dbg(FYI, "connection to pipe share\n");
-       } else if (rsp->ShareType & SMB2_SHARE_TYPE_PRINT) {
-               tcon->print = true;
+               break;
+       case SMB2_SHARE_TYPE_PRINT:
+               tcon->ipc = true;
                cifs_dbg(FYI, "connection to printer\n");
-       } else {
+               break;
+       default:
                cifs_dbg(VFS, "unknown share type %d\n", rsp->ShareType);
                rc = -EOPNOTSUPP;
                goto tcon_error_exit;
@@ -2173,9 +2177,7 @@ smb2_echo_callback(struct mid_q_entry *mid)
        if (mid->mid_state == MID_RESPONSE_RECEIVED)
                credits_received = le16_to_cpu(rsp->hdr.sync_hdr.CreditRequest);
 
-       mutex_lock(&server->srv_mutex);
        DeleteMidQEntry(mid);
-       mutex_unlock(&server->srv_mutex);
        add_credits(server, credits_received, CIFS_ECHO_OP);
 }
 
@@ -2433,9 +2435,7 @@ smb2_readv_callback(struct mid_q_entry *mid)
                cifs_stats_fail_inc(tcon, SMB2_READ_HE);
 
        queue_work(cifsiod_wq, &rdata->work);
-       mutex_lock(&server->srv_mutex);
        DeleteMidQEntry(mid);
-       mutex_unlock(&server->srv_mutex);
        add_credits(server, credits_received, 0);
 }
 
@@ -2594,7 +2594,6 @@ smb2_writev_callback(struct mid_q_entry *mid)
 {
        struct cifs_writedata *wdata = mid->callback_data;
        struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
-       struct TCP_Server_Info *server = tcon->ses->server;
        unsigned int written;
        struct smb2_write_rsp *rsp = (struct smb2_write_rsp *)mid->resp_buf;
        unsigned int credits_received = 1;
@@ -2634,9 +2633,7 @@ smb2_writev_callback(struct mid_q_entry *mid)
                cifs_stats_fail_inc(tcon, SMB2_WRITE_HE);
 
        queue_work(cifsiod_wq, &wdata->work);
-       mutex_lock(&server->srv_mutex);
        DeleteMidQEntry(mid);
-       mutex_unlock(&server->srv_mutex);
        add_credits(tcon->ses->server, credits_received, 0);
 }
 
index 4d64b5b8fc9c6fae67f7f3e0ec74284548ff7c32..47a125ece11ea0d3e2daa0814c8cab28b4643bb1 100644 (file)
@@ -94,7 +94,7 @@ DeleteMidQEntry(struct mid_q_entry *midEntry)
        now = jiffies;
        /* commands taking longer than one second are indications that
           something is wrong, unless it is quite a slow link or server */
-       if ((now - midEntry->when_alloc) > HZ) {
+       if (time_after(now, midEntry->when_alloc + HZ)) {
                if ((cifsFYI & CIFS_TIMER) && (midEntry->command != command)) {
                        pr_debug(" CIFS slow rsp: cmd %d mid %llu",
                               midEntry->command, midEntry->mid);
@@ -613,9 +613,7 @@ cifs_sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server)
        }
        spin_unlock(&GlobalMid_Lock);
 
-       mutex_lock(&server->srv_mutex);
        DeleteMidQEntry(mid);
-       mutex_unlock(&server->srv_mutex);
        return rc;
 }
 
index 20af5187ba63cc14150185952a3f7cdf9526556d..3cb5c9e2d4e78f641549818fbbad7681b193854d 100644 (file)
@@ -235,8 +235,7 @@ static int cifs_xattr_get(const struct xattr_handler *handler,
 
                if (pTcon->ses->server->ops->query_all_EAs)
                        rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon,
-                               full_path, name, value, size,
-                               cifs_sb->local_nls, cifs_remap(cifs_sb));
+                               full_path, name, value, size, cifs_sb);
                break;
 
        case XATTR_CIFS_ACL: {
@@ -336,8 +335,7 @@ ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size)
 
        if (pTcon->ses->server->ops->query_all_EAs)
                rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon,
-                               full_path, NULL, data, buf_size,
-                               cifs_sb->local_nls, cifs_remap(cifs_sb));
+                               full_path, NULL, data, buf_size, cifs_sb);
 list_ea_exit:
        kfree(full_path);
        free_xid(xid);
index 5efb4db44e1ef3223d984296ccf1ca0737224d10..d5093b52b4855f5ec0fbd6d29df265da80945a68 100644 (file)
@@ -40,6 +40,9 @@ struct bpf_reg_state {
         */
        s64 min_value;
        u64 max_value;
+       u32 min_align;
+       u32 aux_off;
+       u32 aux_off_align;
 };
 
 enum bpf_stack_slot_type {
@@ -87,6 +90,7 @@ struct bpf_verifier_env {
        struct bpf_prog *prog;          /* eBPF program being verified */
        struct bpf_verifier_stack_elem *head; /* stack of verifier states to be processed */
        int stack_size;                 /* number of states to be processed */
+       bool strict_alignment;          /* perform strict pointer alignment checks */
        struct bpf_verifier_state cur_state; /* current verifier state */
        struct bpf_verifier_state_list **explored_states; /* search pruning optimization */
        const struct bpf_ext_analyzer_ops *analyzer_ops; /* external analyzer ops */
index 1b166d2e19c57829279faa20a88796fabb5d3f5e..b25e7baa273e8d9db99fb1e2f33e3086ea875e89 100644 (file)
@@ -109,7 +109,6 @@ struct mlx5_flow_table_attr {
        int max_fte;
        u32 level;
        u32 flags;
-       u32 underlay_qpn;
 };
 
 struct mlx5_flow_table *
@@ -167,4 +166,7 @@ struct mlx5_fc *mlx5_fc_create(struct mlx5_core_dev *dev, bool aging);
 void mlx5_fc_destroy(struct mlx5_core_dev *dev, struct mlx5_fc *counter);
 void mlx5_fc_query_cached(struct mlx5_fc *counter,
                          u64 *bytes, u64 *packets, u64 *lastuse);
+int mlx5_fs_add_rx_underlay_qpn(struct mlx5_core_dev *dev, u32 underlay_qpn);
+int mlx5_fs_remove_rx_underlay_qpn(struct mlx5_core_dev *dev, u32 underlay_qpn);
+
 #endif
index 9c23bd2efb56393e7c616d42d427101c3f5f51d2..3f39d27decf4d72e734734edec4403b00ca95657 100644 (file)
@@ -3296,11 +3296,15 @@ int dev_get_phys_port_id(struct net_device *dev,
 int dev_get_phys_port_name(struct net_device *dev,
                           char *name, size_t len);
 int dev_change_proto_down(struct net_device *dev, bool proto_down);
-int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack,
-                     int fd, u32 flags);
 struct sk_buff *validate_xmit_skb_list(struct sk_buff *skb, struct net_device *dev);
 struct sk_buff *dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
                                    struct netdev_queue *txq, int *ret);
+
+typedef int (*xdp_op_t)(struct net_device *dev, struct netdev_xdp *xdp);
+int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack,
+                     int fd, u32 flags);
+bool __dev_xdp_attached(struct net_device *dev, xdp_op_t xdp_op);
+
 int __dev_forward_skb(struct net_device *dev, struct sk_buff *skb);
 int dev_forward_skb(struct net_device *dev, struct sk_buff *skb);
 bool is_skb_forwardable(const struct net_device *dev,
index 945a1f5f63c546c5521da5254a80664344ebd0ad..94dfa9def355f7f52805bba5ade3a32c304f989a 100644 (file)
@@ -132,6 +132,13 @@ enum bpf_attach_type {
  */
 #define BPF_F_ALLOW_OVERRIDE   (1U << 0)
 
+/* If BPF_F_STRICT_ALIGNMENT is used in BPF_PROG_LOAD command, the
+ * verifier will perform strict alignment checking as if the kernel
+ * has been built with CONFIG_EFFICIENT_UNALIGNED_ACCESS not set,
+ * and NET_IP_ALIGN defined to 2.
+ */
+#define BPF_F_STRICT_ALIGNMENT (1U << 0)
+
 #define BPF_PSEUDO_MAP_FD      1
 
 /* flags for BPF_MAP_UPDATE_ELEM command */
@@ -177,6 +184,7 @@ union bpf_attr {
                __u32           log_size;       /* size of user buffer */
                __aligned_u64   log_buf;        /* user supplied buffer */
                __u32           kern_version;   /* checked when prog_type=kprobe */
+               __u32           prog_flags;
        };
 
        struct { /* anonymous struct used by BPF_OBJ_* commands */
index 8e56ac70e0d1a3536a43aff83370e5b3bd5bb0b4..15ac20382ababeecafe2a336aa59a45e50d879e6 100644 (file)
@@ -888,9 +888,18 @@ enum {
 /* XDP section */
 
 #define XDP_FLAGS_UPDATE_IF_NOEXIST    (1U << 0)
-#define XDP_FLAGS_SKB_MODE             (2U << 0)
+#define XDP_FLAGS_SKB_MODE             (1U << 1)
+#define XDP_FLAGS_DRV_MODE             (1U << 2)
 #define XDP_FLAGS_MASK                 (XDP_FLAGS_UPDATE_IF_NOEXIST | \
-                                        XDP_FLAGS_SKB_MODE)
+                                        XDP_FLAGS_SKB_MODE | \
+                                        XDP_FLAGS_DRV_MODE)
+
+/* These are stored into IFLA_XDP_ATTACHED on dump. */
+enum {
+       XDP_ATTACHED_NONE = 0,
+       XDP_ATTACHED_DRV,
+       XDP_ATTACHED_SKB,
+};
 
 enum {
        IFLA_XDP_UNSPEC,
index fd2411fd69148cff375120316fba0a0e033541f6..265a0d854e3358c5c714af9cc3ab2bae8a4754b4 100644 (file)
@@ -783,7 +783,7 @@ struct bpf_prog *bpf_prog_get_type(u32 ufd, enum bpf_prog_type type)
 EXPORT_SYMBOL_GPL(bpf_prog_get_type);
 
 /* last field in 'union bpf_attr' used by this command */
-#define        BPF_PROG_LOAD_LAST_FIELD kern_version
+#define        BPF_PROG_LOAD_LAST_FIELD prog_flags
 
 static int bpf_prog_load(union bpf_attr *attr)
 {
@@ -796,6 +796,9 @@ static int bpf_prog_load(union bpf_attr *attr)
        if (CHECK_ATTR(BPF_PROG_LOAD))
                return -EINVAL;
 
+       if (attr->prog_flags & ~BPF_F_STRICT_ALIGNMENT)
+               return -EINVAL;
+
        /* copy eBPF program license from user space */
        if (strncpy_from_user(license, u64_to_user_ptr(attr->license),
                              sizeof(license) - 1) < 0)
index c5b56c92f8e255d1b13634ad07c460969484f2f4..39f2dcbc4cbc0021de60d8dcea178b2de93e74d1 100644 (file)
@@ -241,6 +241,12 @@ static void print_verifier_state(struct bpf_verifier_state *state)
                if (reg->max_value != BPF_REGISTER_MAX_RANGE)
                        verbose(",max_value=%llu",
                                (unsigned long long)reg->max_value);
+               if (reg->min_align)
+                       verbose(",min_align=%u", reg->min_align);
+               if (reg->aux_off)
+                       verbose(",aux_off=%u", reg->aux_off);
+               if (reg->aux_off_align)
+                       verbose(",aux_off_align=%u", reg->aux_off_align);
        }
        for (i = 0; i < MAX_BPF_STACK; i += BPF_REG_SIZE) {
                if (state->stack_slot_type[i] == STACK_SPILL)
@@ -466,6 +472,9 @@ static void init_reg_state(struct bpf_reg_state *regs)
                regs[i].imm = 0;
                regs[i].min_value = BPF_REGISTER_MIN_RANGE;
                regs[i].max_value = BPF_REGISTER_MAX_RANGE;
+               regs[i].min_align = 0;
+               regs[i].aux_off = 0;
+               regs[i].aux_off_align = 0;
        }
 
        /* frame pointer */
@@ -492,6 +501,7 @@ static void reset_reg_range_values(struct bpf_reg_state *regs, u32 regno)
 {
        regs[regno].min_value = BPF_REGISTER_MIN_RANGE;
        regs[regno].max_value = BPF_REGISTER_MAX_RANGE;
+       regs[regno].min_align = 0;
 }
 
 static void mark_reg_unknown_value_and_range(struct bpf_reg_state *regs,
@@ -779,17 +789,33 @@ static bool is_pointer_value(struct bpf_verifier_env *env, int regno)
 }
 
 static int check_pkt_ptr_alignment(const struct bpf_reg_state *reg,
-                                  int off, int size)
+                                  int off, int size, bool strict)
 {
-       if (reg->id && size != 1) {
-               verbose("Unknown alignment. Only byte-sized access allowed in packet access.\n");
-               return -EACCES;
+       int ip_align;
+       int reg_off;
+
+       /* Byte size accesses are always allowed. */
+       if (!strict || size == 1)
+               return 0;
+
+       reg_off = reg->off;
+       if (reg->id) {
+               if (reg->aux_off_align % size) {
+                       verbose("Packet access is only %u byte aligned, %d byte access not allowed\n",
+                               reg->aux_off_align, size);
+                       return -EACCES;
+               }
+               reg_off += reg->aux_off;
        }
 
-       /* skb->data is NET_IP_ALIGN-ed */
-       if ((NET_IP_ALIGN + reg->off + off) % size != 0) {
+       /* skb->data is NET_IP_ALIGN-ed, but for strict alignment checking
+        * we force this to 2 which is universally what architectures use
+        * when they don't set CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS.
+        */
+       ip_align = strict ? 2 : NET_IP_ALIGN;
+       if ((ip_align + reg_off + off) % size != 0) {
                verbose("misaligned packet access off %d+%d+%d size %d\n",
-                       NET_IP_ALIGN, reg->off, off, size);
+                       ip_align, reg_off, off, size);
                return -EACCES;
        }
 
@@ -797,9 +823,9 @@ static int check_pkt_ptr_alignment(const struct bpf_reg_state *reg,
 }
 
 static int check_val_ptr_alignment(const struct bpf_reg_state *reg,
-                                  int size)
+                                  int size, bool strict)
 {
-       if (size != 1) {
+       if (strict && size != 1) {
                verbose("Unknown alignment. Only byte-sized access allowed in value access.\n");
                return -EACCES;
        }
@@ -807,16 +833,20 @@ static int check_val_ptr_alignment(const struct bpf_reg_state *reg,
        return 0;
 }
 
-static int check_ptr_alignment(const struct bpf_reg_state *reg,
+static int check_ptr_alignment(struct bpf_verifier_env *env,
+                              const struct bpf_reg_state *reg,
                               int off, int size)
 {
+       bool strict = env->strict_alignment;
+
+       if (!IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS))
+               strict = true;
+
        switch (reg->type) {
        case PTR_TO_PACKET:
-               return IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) ? 0 :
-                      check_pkt_ptr_alignment(reg, off, size);
+               return check_pkt_ptr_alignment(reg, off, size, strict);
        case PTR_TO_MAP_VALUE_ADJ:
-               return IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) ? 0 :
-                      check_val_ptr_alignment(reg, size);
+               return check_val_ptr_alignment(reg, size, strict);
        default:
                if (off % size != 0) {
                        verbose("misaligned access off %d size %d\n",
@@ -849,7 +879,7 @@ static int check_mem_access(struct bpf_verifier_env *env, u32 regno, int off,
        if (size < 0)
                return size;
 
-       err = check_ptr_alignment(reg, off, size);
+       err = check_ptr_alignment(env, reg, off, size);
        if (err)
                return err;
 
@@ -883,6 +913,8 @@ static int check_mem_access(struct bpf_verifier_env *env, u32 regno, int off,
                                                         value_regno);
                        /* note that reg.[id|off|range] == 0 */
                        state->regs[value_regno].type = reg_type;
+                       state->regs[value_regno].aux_off = 0;
+                       state->regs[value_regno].aux_off_align = 0;
                }
 
        } else if (reg->type == FRAME_PTR || reg->type == PTR_TO_STACK) {
@@ -1455,6 +1487,8 @@ add_imm:
                 */
                dst_reg->off += imm;
        } else {
+               bool had_id;
+
                if (src_reg->type == PTR_TO_PACKET) {
                        /* R6=pkt(id=0,off=0,r=62) R7=imm22; r7 += r6 */
                        tmp_reg = *dst_reg;  /* save r7 state */
@@ -1488,14 +1522,23 @@ add_imm:
                                src_reg->imm);
                        return -EACCES;
                }
+
+               had_id = (dst_reg->id != 0);
+
                /* dst_reg stays as pkt_ptr type and since some positive
                 * integer value was added to the pointer, increment its 'id'
                 */
                dst_reg->id = ++env->id_gen;
 
-               /* something was added to pkt_ptr, set range and off to zero */
+               /* something was added to pkt_ptr, set range to zero */
+               dst_reg->aux_off += dst_reg->off;
                dst_reg->off = 0;
                dst_reg->range = 0;
+               if (had_id)
+                       dst_reg->aux_off_align = min(dst_reg->aux_off_align,
+                                                    src_reg->min_align);
+               else
+                       dst_reg->aux_off_align = src_reg->min_align;
        }
        return 0;
 }
@@ -1669,6 +1712,13 @@ static void check_reg_overflow(struct bpf_reg_state *reg)
                reg->min_value = BPF_REGISTER_MIN_RANGE;
 }
 
+static u32 calc_align(u32 imm)
+{
+       if (!imm)
+               return 1U << 31;
+       return imm - ((imm - 1) & imm);
+}
+
 static void adjust_reg_min_max_vals(struct bpf_verifier_env *env,
                                    struct bpf_insn *insn)
 {
@@ -1676,8 +1726,10 @@ static void adjust_reg_min_max_vals(struct bpf_verifier_env *env,
        s64 min_val = BPF_REGISTER_MIN_RANGE;
        u64 max_val = BPF_REGISTER_MAX_RANGE;
        u8 opcode = BPF_OP(insn->code);
+       u32 dst_align, src_align;
 
        dst_reg = &regs[insn->dst_reg];
+       src_align = 0;
        if (BPF_SRC(insn->code) == BPF_X) {
                check_reg_overflow(&regs[insn->src_reg]);
                min_val = regs[insn->src_reg].min_value;
@@ -1693,12 +1745,18 @@ static void adjust_reg_min_max_vals(struct bpf_verifier_env *env,
                    regs[insn->src_reg].type != UNKNOWN_VALUE) {
                        min_val = BPF_REGISTER_MIN_RANGE;
                        max_val = BPF_REGISTER_MAX_RANGE;
+                       src_align = 0;
+               } else {
+                       src_align = regs[insn->src_reg].min_align;
                }
        } else if (insn->imm < BPF_REGISTER_MAX_RANGE &&
                   (s64)insn->imm > BPF_REGISTER_MIN_RANGE) {
                min_val = max_val = insn->imm;
+               src_align = calc_align(insn->imm);
        }
 
+       dst_align = dst_reg->min_align;
+
        /* We don't know anything about what was done to this register, mark it
         * as unknown.
         */
@@ -1723,18 +1781,21 @@ static void adjust_reg_min_max_vals(struct bpf_verifier_env *env,
                        dst_reg->min_value += min_val;
                if (dst_reg->max_value != BPF_REGISTER_MAX_RANGE)
                        dst_reg->max_value += max_val;
+               dst_reg->min_align = min(src_align, dst_align);
                break;
        case BPF_SUB:
                if (dst_reg->min_value != BPF_REGISTER_MIN_RANGE)
                        dst_reg->min_value -= min_val;
                if (dst_reg->max_value != BPF_REGISTER_MAX_RANGE)
                        dst_reg->max_value -= max_val;
+               dst_reg->min_align = min(src_align, dst_align);
                break;
        case BPF_MUL:
                if (dst_reg->min_value != BPF_REGISTER_MIN_RANGE)
                        dst_reg->min_value *= min_val;
                if (dst_reg->max_value != BPF_REGISTER_MAX_RANGE)
                        dst_reg->max_value *= max_val;
+               dst_reg->min_align = max(src_align, dst_align);
                break;
        case BPF_AND:
                /* Disallow AND'ing of negative numbers, ain't nobody got time
@@ -1746,17 +1807,23 @@ static void adjust_reg_min_max_vals(struct bpf_verifier_env *env,
                else
                        dst_reg->min_value = 0;
                dst_reg->max_value = max_val;
+               dst_reg->min_align = max(src_align, dst_align);
                break;
        case BPF_LSH:
                /* Gotta have special overflow logic here, if we're shifting
                 * more than MAX_RANGE then just assume we have an invalid
                 * range.
                 */
-               if (min_val > ilog2(BPF_REGISTER_MAX_RANGE))
+               if (min_val > ilog2(BPF_REGISTER_MAX_RANGE)) {
                        dst_reg->min_value = BPF_REGISTER_MIN_RANGE;
-               else if (dst_reg->min_value != BPF_REGISTER_MIN_RANGE)
-                       dst_reg->min_value <<= min_val;
-
+                       dst_reg->min_align = 1;
+               } else {
+                       if (dst_reg->min_value != BPF_REGISTER_MIN_RANGE)
+                               dst_reg->min_value <<= min_val;
+                       if (!dst_reg->min_align)
+                               dst_reg->min_align = 1;
+                       dst_reg->min_align <<= min_val;
+               }
                if (max_val > ilog2(BPF_REGISTER_MAX_RANGE))
                        dst_reg->max_value = BPF_REGISTER_MAX_RANGE;
                else if (dst_reg->max_value != BPF_REGISTER_MAX_RANGE)
@@ -1766,11 +1833,19 @@ static void adjust_reg_min_max_vals(struct bpf_verifier_env *env,
                /* RSH by a negative number is undefined, and the BPF_RSH is an
                 * unsigned shift, so make the appropriate casts.
                 */
-               if (min_val < 0 || dst_reg->min_value < 0)
+               if (min_val < 0 || dst_reg->min_value < 0) {
                        dst_reg->min_value = BPF_REGISTER_MIN_RANGE;
-               else
+               } else {
                        dst_reg->min_value =
                                (u64)(dst_reg->min_value) >> min_val;
+               }
+               if (min_val < 0) {
+                       dst_reg->min_align = 1;
+               } else {
+                       dst_reg->min_align >>= (u64) min_val;
+                       if (!dst_reg->min_align)
+                               dst_reg->min_align = 1;
+               }
                if (dst_reg->max_value != BPF_REGISTER_MAX_RANGE)
                        dst_reg->max_value >>= max_val;
                break;
@@ -1872,6 +1947,7 @@ static int check_alu_op(struct bpf_verifier_env *env, struct bpf_insn *insn)
                        regs[insn->dst_reg].imm = insn->imm;
                        regs[insn->dst_reg].max_value = insn->imm;
                        regs[insn->dst_reg].min_value = insn->imm;
+                       regs[insn->dst_reg].min_align = calc_align(insn->imm);
                }
 
        } else if (opcode > BPF_END) {
@@ -2856,8 +2932,12 @@ static int do_check(struct bpf_verifier_env *env)
                        goto process_bpf_exit;
                }
 
-               if (log_level && do_print_state) {
-                       verbose("\nfrom %d to %d:", prev_insn_idx, insn_idx);
+               if (log_level > 1 || (log_level && do_print_state)) {
+                       if (log_level > 1)
+                               verbose("%d:", insn_idx);
+                       else
+                               verbose("\nfrom %d to %d:",
+                                       prev_insn_idx, insn_idx);
                        print_verifier_state(&env->cur_state);
                        do_print_state = false;
                }
@@ -3494,6 +3574,10 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr)
        } else {
                log_level = 0;
        }
+       if (attr->prog_flags & BPF_F_STRICT_ALIGNMENT)
+               env->strict_alignment = true;
+       else
+               env->strict_alignment = false;
 
        ret = replace_map_fd_with_map_ptr(env);
        if (ret < 0)
@@ -3599,6 +3683,7 @@ int bpf_analyzer(struct bpf_prog *prog, const struct bpf_ext_analyzer_ops *ops,
        mutex_lock(&bpf_verifier_lock);
 
        log_level = 0;
+       env->strict_alignment = false;
 
        env->explored_states = kcalloc(env->prog->len,
                                       sizeof(struct bpf_verifier_state_list *),
index 96cf83da0d66b2db07d5504c4c3aec7da735ea46..fca407b4a6ea178d9224949bc57f89a26c97c5c1 100644 (file)
@@ -6852,6 +6852,32 @@ int dev_change_proto_down(struct net_device *dev, bool proto_down)
 }
 EXPORT_SYMBOL(dev_change_proto_down);
 
+bool __dev_xdp_attached(struct net_device *dev, xdp_op_t xdp_op)
+{
+       struct netdev_xdp xdp;
+
+       memset(&xdp, 0, sizeof(xdp));
+       xdp.command = XDP_QUERY_PROG;
+
+       /* Query must always succeed. */
+       WARN_ON(xdp_op(dev, &xdp) < 0);
+       return xdp.prog_attached;
+}
+
+static int dev_xdp_install(struct net_device *dev, xdp_op_t xdp_op,
+                          struct netlink_ext_ack *extack,
+                          struct bpf_prog *prog)
+{
+       struct netdev_xdp xdp;
+
+       memset(&xdp, 0, sizeof(xdp));
+       xdp.command = XDP_SETUP_PROG;
+       xdp.extack = extack;
+       xdp.prog = prog;
+
+       return xdp_op(dev, &xdp);
+}
+
 /**
  *     dev_change_xdp_fd - set or clear a bpf program for a device rx path
  *     @dev: device
@@ -6864,41 +6890,34 @@ EXPORT_SYMBOL(dev_change_proto_down);
 int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack,
                      int fd, u32 flags)
 {
-       int (*xdp_op)(struct net_device *dev, struct netdev_xdp *xdp);
        const struct net_device_ops *ops = dev->netdev_ops;
        struct bpf_prog *prog = NULL;
-       struct netdev_xdp xdp;
+       xdp_op_t xdp_op, xdp_chk;
        int err;
 
        ASSERT_RTNL();
 
-       xdp_op = ops->ndo_xdp;
+       xdp_op = xdp_chk = ops->ndo_xdp;
+       if (!xdp_op && (flags & XDP_FLAGS_DRV_MODE))
+               return -EOPNOTSUPP;
        if (!xdp_op || (flags & XDP_FLAGS_SKB_MODE))
                xdp_op = generic_xdp_install;
+       if (xdp_op == xdp_chk)
+               xdp_chk = generic_xdp_install;
 
        if (fd >= 0) {
-               if (flags & XDP_FLAGS_UPDATE_IF_NOEXIST) {
-                       memset(&xdp, 0, sizeof(xdp));
-                       xdp.command = XDP_QUERY_PROG;
-
-                       err = xdp_op(dev, &xdp);
-                       if (err < 0)
-                               return err;
-                       if (xdp.prog_attached)
-                               return -EBUSY;
-               }
+               if (xdp_chk && __dev_xdp_attached(dev, xdp_chk))
+                       return -EEXIST;
+               if ((flags & XDP_FLAGS_UPDATE_IF_NOEXIST) &&
+                   __dev_xdp_attached(dev, xdp_op))
+                       return -EBUSY;
 
                prog = bpf_prog_get_type(fd, BPF_PROG_TYPE_XDP);
                if (IS_ERR(prog))
                        return PTR_ERR(prog);
        }
 
-       memset(&xdp, 0, sizeof(xdp));
-       xdp.command = XDP_SETUP_PROG;
-       xdp.extack = extack;
-       xdp.prog = prog;
-
-       err = xdp_op(dev, &xdp);
+       err = dev_xdp_install(dev, xdp_op, extack, prog);
        if (err < 0 && prog)
                bpf_prog_put(prog);
 
index bcb0f610ee422a12ad6b8ae41763296ba0fa3c6a..d7f82c3450b124948db66b6191a67bfc9b817305 100644 (file)
@@ -899,8 +899,7 @@ static size_t rtnl_port_size(const struct net_device *dev,
 static size_t rtnl_xdp_size(void)
 {
        size_t xdp_size = nla_total_size(0) +   /* nest IFLA_XDP */
-                         nla_total_size(1) +   /* XDP_ATTACHED */
-                         nla_total_size(4);    /* XDP_FLAGS */
+                         nla_total_size(1);    /* XDP_ATTACHED */
 
        return xdp_size;
 }
@@ -1247,37 +1246,34 @@ static int rtnl_fill_link_ifmap(struct sk_buff *skb, struct net_device *dev)
        return 0;
 }
 
+static u8 rtnl_xdp_attached_mode(struct net_device *dev)
+{
+       const struct net_device_ops *ops = dev->netdev_ops;
+
+       ASSERT_RTNL();
+
+       if (rcu_access_pointer(dev->xdp_prog))
+               return XDP_ATTACHED_SKB;
+       if (ops->ndo_xdp && __dev_xdp_attached(dev, ops->ndo_xdp))
+               return XDP_ATTACHED_DRV;
+
+       return XDP_ATTACHED_NONE;
+}
+
 static int rtnl_xdp_fill(struct sk_buff *skb, struct net_device *dev)
 {
        struct nlattr *xdp;
-       u32 xdp_flags = 0;
-       u8 val = 0;
        int err;
 
        xdp = nla_nest_start(skb, IFLA_XDP);
        if (!xdp)
                return -EMSGSIZE;
-       if (rcu_access_pointer(dev->xdp_prog)) {
-               xdp_flags = XDP_FLAGS_SKB_MODE;
-               val = 1;
-       } else if (dev->netdev_ops->ndo_xdp) {
-               struct netdev_xdp xdp_op = {};
-
-               xdp_op.command = XDP_QUERY_PROG;
-               err = dev->netdev_ops->ndo_xdp(dev, &xdp_op);
-               if (err)
-                       goto err_cancel;
-               val = xdp_op.prog_attached;
-       }
-       err = nla_put_u8(skb, IFLA_XDP_ATTACHED, val);
+
+       err = nla_put_u8(skb, IFLA_XDP_ATTACHED,
+                        rtnl_xdp_attached_mode(dev));
        if (err)
                goto err_cancel;
 
-       if (xdp_flags) {
-               err = nla_put_u32(skb, IFLA_XDP_FLAGS, xdp_flags);
-               if (err)
-                       goto err_cancel;
-       }
        nla_nest_end(skb, xdp);
        return 0;
 
@@ -2199,6 +2195,11 @@ static int do_setlink(const struct sk_buff *skb,
                                err = -EINVAL;
                                goto errout;
                        }
+                       if ((xdp_flags & XDP_FLAGS_SKB_MODE) &&
+                           (xdp_flags & XDP_FLAGS_DRV_MODE)) {
+                               err = -EINVAL;
+                               goto errout;
+                       }
                }
 
                if (xdp[IFLA_XDP_FD]) {
index 79c6aee6af9b817bd7086f04ae8f46342a3bf4b6..e43e71d7856b385111cd4c4b1bd835a78c670c60 100644 (file)
@@ -1803,28 +1803,24 @@ EXPORT_SYMBOL(skb_set_owner_w);
  * delay queue. We want to allow the owner socket to send more
  * packets, as if they were already TX completed by a typical driver.
  * But we also want to keep skb->sk set because some packet schedulers
- * rely on it (sch_fq for example). So we set skb->truesize to a small
- * amount (1) and decrease sk_wmem_alloc accordingly.
+ * rely on it (sch_fq for example).
  */
 void skb_orphan_partial(struct sk_buff *skb)
 {
-       /* If this skb is a TCP pure ACK or already went here,
-        * we have nothing to do. 2 is already a very small truesize.
-        */
-       if (skb->truesize <= 2)
+       if (skb_is_tcp_pure_ack(skb))
                return;
 
-       /* TCP stack sets skb->ooo_okay based on sk_wmem_alloc,
-        * so we do not completely orphan skb, but transfert all
-        * accounted bytes but one, to avoid unexpected reorders.
-        */
        if (skb->destructor == sock_wfree
 #ifdef CONFIG_INET
            || skb->destructor == tcp_wfree
 #endif
                ) {
-               atomic_sub(skb->truesize - 1, &skb->sk->sk_wmem_alloc);
-               skb->truesize = 1;
+               struct sock *sk = skb->sk;
+
+               if (atomic_inc_not_zero(&sk->sk_refcnt)) {
+                       atomic_sub(skb->truesize, &sk->sk_wmem_alloc);
+                       skb->destructor = sock_efree;
+               }
        } else {
                skb_orphan(skb);
        }
index 840f14aaa01635e0f6fb62232b67814736c84b5d..992621172220d136a1114a58f1c0e75219c57ea4 100644 (file)
@@ -426,6 +426,9 @@ static struct sock *dccp_v6_request_recv_sock(const struct sock *sk,
                newsk->sk_backlog_rcv = dccp_v4_do_rcv;
                newnp->pktoptions  = NULL;
                newnp->opt         = NULL;
+               newnp->ipv6_mc_list = NULL;
+               newnp->ipv6_ac_list = NULL;
+               newnp->ipv6_fl_list = NULL;
                newnp->mcast_oif   = inet6_iif(skb);
                newnp->mcast_hops  = ipv6_hdr(skb)->hop_limit;
 
@@ -490,6 +493,9 @@ static struct sock *dccp_v6_request_recv_sock(const struct sock *sk,
        /* Clone RX bits */
        newnp->rxopt.all = np->rxopt.all;
 
+       newnp->ipv6_mc_list = NULL;
+       newnp->ipv6_ac_list = NULL;
+       newnp->ipv6_fl_list = NULL;
        newnp->pktoptions = NULL;
        newnp->opt        = NULL;
        newnp->mcast_oif  = inet6_iif(skb);
index 5a3ad09e2786fb41ad12681d09938c645b69866d..06e2dbc2b4a212a054fd88e57bb902c55a171b11 100644 (file)
@@ -1179,13 +1179,14 @@ static int tcp_match_skb_to_sack(struct sock *sk, struct sk_buff *skb,
                 */
                if (pkt_len > mss) {
                        unsigned int new_len = (pkt_len / mss) * mss;
-                       if (!in_sack && new_len < pkt_len) {
+                       if (!in_sack && new_len < pkt_len)
                                new_len += mss;
-                               if (new_len >= skb->len)
-                                       return 0;
-                       }
                        pkt_len = new_len;
                }
+
+               if (pkt_len >= skb->len && !in_sack)
+                       return 0;
+
                err = tcp_fragment(sk, skb, pkt_len, mss, GFP_ATOMIC);
                if (err < 0)
                        return err;
index 8d297a79b5680761b290aaa1bc947d05bcb60f3b..6a4fb1e629fb7609048156974ae2eb322cebddae 100644 (file)
@@ -1022,7 +1022,10 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
        INIT_HLIST_NODE(&ifa->addr_lst);
        ifa->scope = scope;
        ifa->prefix_len = pfxlen;
-       ifa->flags = flags | IFA_F_TENTATIVE;
+       ifa->flags = flags;
+       /* No need to add the TENTATIVE flag for addresses with NODAD */
+       if (!(flags & IFA_F_NODAD))
+               ifa->flags |= IFA_F_TENTATIVE;
        ifa->valid_lft = valid_lft;
        ifa->prefered_lft = prefered_lft;
        ifa->cstamp = ifa->tstamp = jiffies;
index 7a8237acd210bf58cdc98f085fcf7fed433c3f24..4f4310a36a0481e2bd068e39285011ff28377ea5 100644 (file)
@@ -1062,6 +1062,7 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff *
                newtp->af_specific = &tcp_sock_ipv6_mapped_specific;
 #endif
 
+               newnp->ipv6_mc_list = NULL;
                newnp->ipv6_ac_list = NULL;
                newnp->ipv6_fl_list = NULL;
                newnp->pktoptions  = NULL;
@@ -1131,6 +1132,7 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff *
           First: no IPv4 options.
         */
        newinet->inet_opt = NULL;
+       newnp->ipv6_mc_list = NULL;
        newnp->ipv6_ac_list = NULL;
        newnp->ipv6_fl_list = NULL;
 
index f4001763134da35ed5f0f04bc2836015bb15a4af..e3eeed19cc7a130e80e24a3d67776a5b5a3c2698 100644 (file)
@@ -2658,13 +2658,6 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
                dev = dev_get_by_index(sock_net(&po->sk), saddr->sll_ifindex);
        }
 
-       sockc.tsflags = po->sk.sk_tsflags;
-       if (msg->msg_controllen) {
-               err = sock_cmsg_send(&po->sk, msg, &sockc);
-               if (unlikely(err))
-                       goto out;
-       }
-
        err = -ENXIO;
        if (unlikely(dev == NULL))
                goto out;
@@ -2672,6 +2665,13 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
        if (unlikely(!(dev->flags & IFF_UP)))
                goto out_put;
 
+       sockc.tsflags = po->sk.sk_tsflags;
+       if (msg->msg_controllen) {
+               err = sock_cmsg_send(&po->sk, msg, &sockc);
+               if (unlikely(err))
+                       goto out_put;
+       }
+
        if (po->sk.sk_socket->type == SOCK_RAW)
                reserve = dev->hard_header_len;
        size_max = po->tx_ring.frame_size
index bbe57d57b67fd498692bd41db49147511f1bb091..e88342fde1bc409aed6a3c86e7a628030eaac66f 100644 (file)
@@ -1831,6 +1831,12 @@ static int tc_dump_tclass_root(struct Qdisc *root, struct sk_buff *skb,
        if (!qdisc_dev(root))
                return 0;
 
+       if (tcm->tcm_parent) {
+               q = qdisc_match_from_root(root, TC_H_MAJ(tcm->tcm_parent));
+               if (q && tc_dump_tclass_qdisc(q, skb, tcm, cb, t_p, s_t) < 0)
+                       return -1;
+               return 0;
+       }
        hash_for_each(qdisc_dev(root)->qdisc_hash, b, q, hash) {
                if (tc_dump_tclass_qdisc(q, skb, tcm, cb, t_p, s_t) < 0)
                        return -1;
index 961ee59f696a0b0a8b6c2bade0031a073dff53ad..142b70e959af9142ce35b88749ad2160327c8267 100644 (file)
@@ -240,12 +240,10 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr,
        struct sctp_bind_addr *bp;
        struct ipv6_pinfo *np = inet6_sk(sk);
        struct sctp_sockaddr_entry *laddr;
-       union sctp_addr *baddr = NULL;
        union sctp_addr *daddr = &t->ipaddr;
        union sctp_addr dst_saddr;
        struct in6_addr *final_p, final;
        __u8 matchlen = 0;
-       __u8 bmatchlen;
        sctp_scope_t scope;
 
        memset(fl6, 0, sizeof(struct flowi6));
@@ -312,23 +310,37 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr,
         */
        rcu_read_lock();
        list_for_each_entry_rcu(laddr, &bp->address_list, list) {
-               if (!laddr->valid)
+               struct dst_entry *bdst;
+               __u8 bmatchlen;
+
+               if (!laddr->valid ||
+                   laddr->state != SCTP_ADDR_SRC ||
+                   laddr->a.sa.sa_family != AF_INET6 ||
+                   scope > sctp_scope(&laddr->a))
                        continue;
-               if ((laddr->state == SCTP_ADDR_SRC) &&
-                   (laddr->a.sa.sa_family == AF_INET6) &&
-                   (scope <= sctp_scope(&laddr->a))) {
-                       bmatchlen = sctp_v6_addr_match_len(daddr, &laddr->a);
-                       if (!baddr || (matchlen < bmatchlen)) {
-                               baddr = &laddr->a;
-                               matchlen = bmatchlen;
-                       }
-               }
-       }
-       if (baddr) {
-               fl6->saddr = baddr->v6.sin6_addr;
-               fl6->fl6_sport = baddr->v6.sin6_port;
+
+               fl6->saddr = laddr->a.v6.sin6_addr;
+               fl6->fl6_sport = laddr->a.v6.sin6_port;
                final_p = fl6_update_dst(fl6, rcu_dereference(np->opt), &final);
-               dst = ip6_dst_lookup_flow(sk, fl6, final_p);
+               bdst = ip6_dst_lookup_flow(sk, fl6, final_p);
+
+               if (!IS_ERR(bdst) &&
+                   ipv6_chk_addr(dev_net(bdst->dev),
+                                 &laddr->a.v6.sin6_addr, bdst->dev, 1)) {
+                       if (!IS_ERR_OR_NULL(dst))
+                               dst_release(dst);
+                       dst = bdst;
+                       break;
+               }
+
+               bmatchlen = sctp_v6_addr_match_len(daddr, &laddr->a);
+               if (matchlen > bmatchlen)
+                       continue;
+
+               if (!IS_ERR_OR_NULL(dst))
+                       dst_release(dst);
+               dst = bdst;
+               matchlen = bmatchlen;
        }
        rcu_read_unlock();
 
index 0d4f2f455a7c91a1d7ea2b0fd9c8d121e6da98af..1b92b72e812f942fc9826d8542f29bf1bd7c26c5 100644 (file)
@@ -362,25 +362,25 @@ static int tipc_sk_sock_err(struct socket *sock, long *timeout)
        return 0;
 }
 
-#define tipc_wait_for_cond(sock_, timeout_, condition_)                        \
-({                                                                     \
-       int rc_ = 0;                                                    \
-       int done_ = 0;                                                  \
-                                                                       \
-       while (!(condition_) && !done_) {                               \
-               struct sock *sk_ = sock->sk;                            \
-               DEFINE_WAIT_FUNC(wait_, woken_wake_function);           \
-                                                                       \
-               rc_ = tipc_sk_sock_err(sock_, timeout_);                \
-               if (rc_)                                                \
-                       break;                                          \
-               prepare_to_wait(sk_sleep(sk_), &wait_,                  \
-                               TASK_INTERRUPTIBLE);                    \
-               done_ = sk_wait_event(sk_, timeout_,                    \
-                                     (condition_), &wait_);            \
-               remove_wait_queue(sk_sleep(sk_), &wait_);               \
-       }                                                               \
-       rc_;                                                            \
+#define tipc_wait_for_cond(sock_, timeo_, condition_)                         \
+({                                                                             \
+       struct sock *sk_;                                                      \
+       int rc_;                                                               \
+                                                                              \
+       while ((rc_ = !(condition_))) {                                        \
+               DEFINE_WAIT_FUNC(wait_, woken_wake_function);                  \
+               sk_ = (sock_)->sk;                                             \
+               rc_ = tipc_sk_sock_err((sock_), timeo_);                       \
+               if (rc_)                                                       \
+                       break;                                                 \
+               prepare_to_wait(sk_sleep(sk_), &wait_, TASK_INTERRUPTIBLE);    \
+               release_sock(sk_);                                             \
+               *(timeo_) = wait_woken(&wait_, TASK_INTERRUPTIBLE, *(timeo_)); \
+               sched_annotate_sleep();                                        \
+               lock_sock(sk_);                                                \
+               remove_wait_queue(sk_sleep(sk_), &wait_);                      \
+       }                                                                      \
+       rc_;                                                                   \
 })
 
 /**
index b08ab4e889293c30f64b717065e6860603063f7c..9d751e209f313ca8f20a07e6d578cfb98c23defd 100644 (file)
@@ -306,7 +306,9 @@ int main(int argc, char *argv[])
        prog_attach_iptables(argv[2]);
        if (cfg_test_traffic) {
                if (signal(SIGINT, finish) == SIG_ERR)
-                       error(1, errno, "register handler failed");
+                       error(1, errno, "register SIGINT handler failed");
+               if (signal(SIGTERM, finish) == SIG_ERR)
+                       error(1, errno, "register SIGTERM handler failed");
                while (!test_finish) {
                        print_table();
                        printf("\n");
index 9cce2a66bd664c40668b3c8ca0dd12bd148bb21b..512f87a5fd20e08d0b97893b17e20e971425830e 100644 (file)
@@ -100,6 +100,7 @@ int main(int argc, char **argv)
        setrlimit(RLIMIT_MEMLOCK, &r);
 
        signal(SIGINT, int_exit);
+       signal(SIGTERM, int_exit);
 
        if (load_kallsyms()) {
                printf("failed to process /proc/kallsyms\n");
index be59d7dcbdde3664c573a78d6d27adee03234a16..4ed690b907ff844961499d492350746065e423fb 100644 (file)
@@ -180,6 +180,7 @@ int main(int argc, char **argv)
                return 1;
        }
        signal(SIGINT, int_exit);
+       signal(SIGTERM, int_exit);
 
        /* do sampling */
        printf("Sampling at %d Hertz for %d seconds. Ctrl-C also ends.\n",
index 0c5561d193a487f2257ccece359530b97b06a170..fa4336423da569f31fc432b9adc61f0835bb3f69 100644 (file)
@@ -192,6 +192,7 @@ int main(int argc, char **argv)
        setrlimit(RLIMIT_MEMLOCK, &r);
 
        signal(SIGINT, int_exit);
+       signal(SIGTERM, int_exit);
 
        if (load_kallsyms()) {
                printf("failed to process /proc/kallsyms\n");
index 7fee0f1ba9a313baf2d233b3bf705994c183755e..7321a3f253c991f88e96f2a53e6ffa3e7c5f1719 100644 (file)
@@ -127,6 +127,7 @@ int main(int ac, char **argv)
        }
 
        signal(SIGINT, int_exit);
+       signal(SIGTERM, int_exit);
 
        /* start 'ping' in the background to have some kfree_skb events */
        f = popen("ping -c5 localhost", "r");
index 378850c70eb81afdbc5283611573f89ea4d8923e..2431c0321b712ce54d15414836b148d483a8a632 100644 (file)
@@ -62,13 +62,14 @@ static void usage(const char *prog)
        fprintf(stderr,
                "usage: %s [OPTS] IFINDEX\n\n"
                "OPTS:\n"
-               "    -S    use skb-mode\n",
+               "    -S    use skb-mode\n"
+               "    -N    enforce native mode\n",
                prog);
 }
 
 int main(int argc, char **argv)
 {
-       const char *optstr = "S";
+       const char *optstr = "SN";
        char filename[256];
        int opt;
 
@@ -77,6 +78,9 @@ int main(int argc, char **argv)
                case 'S':
                        xdp_flags |= XDP_FLAGS_SKB_MODE;
                        break;
+               case 'N':
+                       xdp_flags |= XDP_FLAGS_DRV_MODE;
+                       break;
                default:
                        usage(basename(argv[0]));
                        return 1;
@@ -102,6 +106,7 @@ int main(int argc, char **argv)
        }
 
        signal(SIGINT, int_exit);
+       signal(SIGTERM, int_exit);
 
        if (set_link_xdp_fd(ifindex, prog_fd[0], xdp_flags) < 0) {
                printf("link set xdp fd failed\n");
index 92b8bde9337c8cec6128e73d23d307b628ba5a38..715cd12eaca5c0729d11e0918e564db9e2fa980f 100644 (file)
@@ -79,6 +79,8 @@ static void usage(const char *cmd)
        printf("    -m <dest-MAC> Used in sending the IP Tunneled pkt\n");
        printf("    -T <stop-after-X-seconds> Default: 0 (forever)\n");
        printf("    -P <IP-Protocol> Default is TCP\n");
+       printf("    -S use skb-mode\n");
+       printf("    -N enforce native mode\n");
        printf("    -h Display this help\n");
 }
 
@@ -138,7 +140,7 @@ int main(int argc, char **argv)
 {
        unsigned char opt_flags[256] = {};
        unsigned int kill_after_s = 0;
-       const char *optstr = "i:a:p:s:d:m:T:P:Sh";
+       const char *optstr = "i:a:p:s:d:m:T:P:SNh";
        int min_port = 0, max_port = 0;
        struct iptnl_info tnl = {};
        struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
@@ -206,6 +208,9 @@ int main(int argc, char **argv)
                case 'S':
                        xdp_flags |= XDP_FLAGS_SKB_MODE;
                        break;
+               case 'N':
+                       xdp_flags |= XDP_FLAGS_DRV_MODE;
+                       break;
                default:
                        usage(argv[0]);
                        return 1;
@@ -239,6 +244,7 @@ int main(int argc, char **argv)
        }
 
        signal(SIGINT, int_exit);
+       signal(SIGTERM, int_exit);
 
        while (min_port <= max_port) {
                vip.dport = htons(min_port++);
index ebc6dceddb58c00e4253e4fc3b37eda7a17b62be..7598361ef1f10898ea73d944ae0b0c02c4725d99 100644 (file)
@@ -29,6 +29,7 @@ int main(void)
        attr.log_size = 0;
        attr.log_level = 0;
        attr.kern_version = 0;
+       attr.prog_flags = 0;
 
        /*
         * Test existence of __NR_bpf and BPF_PROG_LOAD.
index e553529929f683c4c39ae336d10c6f670e589b54..94dfa9def355f7f52805bba5ade3a32c304f989a 100644 (file)
@@ -132,6 +132,13 @@ enum bpf_attach_type {
  */
 #define BPF_F_ALLOW_OVERRIDE   (1U << 0)
 
+/* If BPF_F_STRICT_ALIGNMENT is used in BPF_PROG_LOAD command, the
+ * verifier will perform strict alignment checking as if the kernel
+ * has been built with CONFIG_EFFICIENT_UNALIGNED_ACCESS not set,
+ * and NET_IP_ALIGN defined to 2.
+ */
+#define BPF_F_STRICT_ALIGNMENT (1U << 0)
+
 #define BPF_PSEUDO_MAP_FD      1
 
 /* flags for BPF_MAP_UPDATE_ELEM command */
@@ -177,6 +184,7 @@ union bpf_attr {
                __u32           log_size;       /* size of user buffer */
                __aligned_u64   log_buf;        /* user supplied buffer */
                __u32           kern_version;   /* checked when prog_type=kprobe */
+               __u32           prog_flags;
        };
 
        struct { /* anonymous struct used by BPF_OBJ_* commands */
@@ -481,8 +489,7 @@ union bpf_attr {
  * u32 bpf_get_socket_uid(skb)
  *     Get the owner uid of the socket stored inside sk_buff.
  *     @skb: pointer to skb
- *     Return: uid of the socket owner on success or 0 if the socket pointer
- *     inside sk_buff is NULL
+ *     Return: uid of the socket owner on success or overflowuid if failed.
  */
 #define __BPF_FUNC_MAPPER(FN)          \
        FN(unspec),                     \
index 4fe444b8092e2d6dc8aea6b7ce8349a64e439c44..6e178987af8e3f45d63da349e38c39b4e4cd6d84 100644 (file)
@@ -117,6 +117,28 @@ int bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns,
        return sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
 }
 
+int bpf_verify_program(enum bpf_prog_type type, const struct bpf_insn *insns,
+                      size_t insns_cnt, int strict_alignment,
+                      const char *license, __u32 kern_version,
+                      char *log_buf, size_t log_buf_sz)
+{
+       union bpf_attr attr;
+
+       bzero(&attr, sizeof(attr));
+       attr.prog_type = type;
+       attr.insn_cnt = (__u32)insns_cnt;
+       attr.insns = ptr_to_u64(insns);
+       attr.license = ptr_to_u64(license);
+       attr.log_buf = ptr_to_u64(log_buf);
+       attr.log_size = log_buf_sz;
+       attr.log_level = 2;
+       log_buf[0] = 0;
+       attr.kern_version = kern_version;
+       attr.prog_flags = strict_alignment ? BPF_F_STRICT_ALIGNMENT : 0;
+
+       return sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
+}
+
 int bpf_map_update_elem(int fd, const void *key, const void *value,
                        __u64 flags)
 {
index edb4daeff7a52c44f6bc366c265a7f5a3aadfc10..972bd8333eb72e982420abeac9f8ceff5a4ed1a3 100644 (file)
@@ -35,6 +35,10 @@ int bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns,
                     size_t insns_cnt, const char *license,
                     __u32 kern_version, char *log_buf,
                     size_t log_buf_sz);
+int bpf_verify_program(enum bpf_prog_type type, const struct bpf_insn *insns,
+                      size_t insns_cnt, int strict_alignment,
+                      const char *license, __u32 kern_version,
+                      char *log_buf, size_t log_buf_sz);
 
 int bpf_map_update_elem(int fd, const void *key, const void *value,
                        __u64 flags);
index 91edd056623789fb5585bd774b6d98eb5dba1cc2..f389b02d43a004e90aed9acd68148875af3beba2 100644 (file)
@@ -11,7 +11,8 @@ endif
 CFLAGS += -Wall -O2 -I$(APIDIR) -I$(LIBDIR) -I$(GENDIR) $(GENFLAGS) -I../../../include
 LDLIBS += -lcap -lelf
 
-TEST_GEN_PROGS = test_verifier test_tag test_maps test_lru_map test_lpm_map test_progs
+TEST_GEN_PROGS = test_verifier test_tag test_maps test_lru_map test_lpm_map test_progs \
+       test_align
 
 TEST_GEN_FILES = test_pkt_access.o test_xdp.o test_l4lb.o test_tcp_estats.o
 
@@ -34,6 +35,7 @@ $(BPFOBJ): force
 CLANG ?= clang
 
 %.o: %.c
-       $(CLANG) -I. -I../../../include/uapi -I../../../../samples/bpf/ \
+       $(CLANG) -I. -I./include/uapi -I../../../include/uapi \
+               -I../../../../samples/bpf/ \
                -Wno-compare-distinct-pointer-types \
                -O2 -target bpf -c $< -o $@
diff --git a/tools/testing/selftests/bpf/include/uapi/linux/types.h b/tools/testing/selftests/bpf/include/uapi/linux/types.h
new file mode 100644 (file)
index 0000000..fbd16a7
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _UAPI_LINUX_TYPES_H
+#define _UAPI_LINUX_TYPES_H
+
+#include <asm-generic/int-ll64.h>
+
+#endif /* _UAPI_LINUX_TYPES_H */
diff --git a/tools/testing/selftests/bpf/test_align.c b/tools/testing/selftests/bpf/test_align.c
new file mode 100644 (file)
index 0000000..9644d4e
--- /dev/null
@@ -0,0 +1,453 @@
+#include <asm/types.h>
+#include <linux/types.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <stddef.h>
+#include <stdbool.h>
+
+#include <linux/unistd.h>
+#include <linux/filter.h>
+#include <linux/bpf_perf_event.h>
+#include <linux/bpf.h>
+
+#include <bpf/bpf.h>
+
+#include "../../../include/linux/filter.h"
+
+#ifndef ARRAY_SIZE
+# define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+#endif
+
+#define MAX_INSNS      512
+#define MAX_MATCHES    16
+
+struct bpf_align_test {
+       const char *descr;
+       struct bpf_insn insns[MAX_INSNS];
+       enum {
+               UNDEF,
+               ACCEPT,
+               REJECT
+       } result;
+       enum bpf_prog_type prog_type;
+       const char *matches[MAX_MATCHES];
+};
+
+static struct bpf_align_test tests[] = {
+       {
+               .descr = "mov",
+               .insns = {
+                       BPF_MOV64_IMM(BPF_REG_3, 2),
+                       BPF_MOV64_IMM(BPF_REG_3, 4),
+                       BPF_MOV64_IMM(BPF_REG_3, 8),
+                       BPF_MOV64_IMM(BPF_REG_3, 16),
+                       BPF_MOV64_IMM(BPF_REG_3, 32),
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               .prog_type = BPF_PROG_TYPE_SCHED_CLS,
+               .matches = {
+                       "1: R1=ctx R3=imm2,min_value=2,max_value=2,min_align=2 R10=fp",
+                       "2: R1=ctx R3=imm4,min_value=4,max_value=4,min_align=4 R10=fp",
+                       "3: R1=ctx R3=imm8,min_value=8,max_value=8,min_align=8 R10=fp",
+                       "4: R1=ctx R3=imm16,min_value=16,max_value=16,min_align=16 R10=fp",
+                       "5: R1=ctx R3=imm32,min_value=32,max_value=32,min_align=32 R10=fp",
+               },
+       },
+       {
+               .descr = "shift",
+               .insns = {
+                       BPF_MOV64_IMM(BPF_REG_3, 1),
+                       BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1),
+                       BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1),
+                       BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1),
+                       BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1),
+                       BPF_ALU64_IMM(BPF_RSH, BPF_REG_3, 4),
+                       BPF_MOV64_IMM(BPF_REG_4, 32),
+                       BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1),
+                       BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1),
+                       BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1),
+                       BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1),
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               .prog_type = BPF_PROG_TYPE_SCHED_CLS,
+               .matches = {
+                       "1: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R10=fp",
+                       "2: R1=ctx R3=imm2,min_value=2,max_value=2,min_align=2 R10=fp",
+                       "3: R1=ctx R3=imm4,min_value=4,max_value=4,min_align=4 R10=fp",
+                       "4: R1=ctx R3=imm8,min_value=8,max_value=8,min_align=8 R10=fp",
+                       "5: R1=ctx R3=imm16,min_value=16,max_value=16,min_align=16 R10=fp",
+                       "6: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R10=fp",
+                       "7: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R4=imm32,min_value=32,max_value=32,min_align=32 R10=fp",
+                       "8: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R4=imm16,min_value=16,max_value=16,min_align=16 R10=fp",
+                       "9: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R4=imm8,min_value=8,max_value=8,min_align=8 R10=fp",
+                       "10: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R4=imm4,min_value=4,max_value=4,min_align=4 R10=fp",
+                       "11: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R4=imm2,min_value=2,max_value=2,min_align=2 R10=fp",
+               },
+       },
+       {
+               .descr = "addsub",
+               .insns = {
+                       BPF_MOV64_IMM(BPF_REG_3, 4),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, 4),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, 2),
+                       BPF_MOV64_IMM(BPF_REG_4, 8),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 2),
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               .prog_type = BPF_PROG_TYPE_SCHED_CLS,
+               .matches = {
+                       "1: R1=ctx R3=imm4,min_value=4,max_value=4,min_align=4 R10=fp",
+                       "2: R1=ctx R3=imm8,min_value=8,max_value=8,min_align=4 R10=fp",
+                       "3: R1=ctx R3=imm10,min_value=10,max_value=10,min_align=2 R10=fp",
+                       "4: R1=ctx R3=imm10,min_value=10,max_value=10,min_align=2 R4=imm8,min_value=8,max_value=8,min_align=8 R10=fp",
+                       "5: R1=ctx R3=imm10,min_value=10,max_value=10,min_align=2 R4=imm12,min_value=12,max_value=12,min_align=4 R10=fp",
+                       "6: R1=ctx R3=imm10,min_value=10,max_value=10,min_align=2 R4=imm14,min_value=14,max_value=14,min_align=2 R10=fp",
+               },
+       },
+       {
+               .descr = "mul",
+               .insns = {
+                       BPF_MOV64_IMM(BPF_REG_3, 7),
+                       BPF_ALU64_IMM(BPF_MUL, BPF_REG_3, 1),
+                       BPF_ALU64_IMM(BPF_MUL, BPF_REG_3, 2),
+                       BPF_ALU64_IMM(BPF_MUL, BPF_REG_3, 4),
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               .prog_type = BPF_PROG_TYPE_SCHED_CLS,
+               .matches = {
+                       "1: R1=ctx R3=imm7,min_value=7,max_value=7,min_align=1 R10=fp",
+                       "2: R1=ctx R3=imm7,min_value=7,max_value=7,min_align=1 R10=fp",
+                       "3: R1=ctx R3=imm14,min_value=14,max_value=14,min_align=2 R10=fp",
+                       "4: R1=ctx R3=imm56,min_value=56,max_value=56,min_align=4 R10=fp",
+               },
+       },
+
+#define PREP_PKT_POINTERS \
+       BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, \
+                   offsetof(struct __sk_buff, data)), \
+       BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, \
+                   offsetof(struct __sk_buff, data_end))
+
+#define LOAD_UNKNOWN(DST_REG) \
+       PREP_PKT_POINTERS, \
+       BPF_MOV64_REG(BPF_REG_0, BPF_REG_2), \
+       BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8), \
+       BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_0, 1), \
+       BPF_EXIT_INSN(), \
+       BPF_LDX_MEM(BPF_B, DST_REG, BPF_REG_2, 0)
+
+       {
+               .descr = "unknown shift",
+               .insns = {
+                       LOAD_UNKNOWN(BPF_REG_3),
+                       BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1),
+                       BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1),
+                       BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1),
+                       BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1),
+                       LOAD_UNKNOWN(BPF_REG_4),
+                       BPF_ALU64_IMM(BPF_LSH, BPF_REG_4, 5),
+                       BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1),
+                       BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1),
+                       BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1),
+                       BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1),
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               .prog_type = BPF_PROG_TYPE_SCHED_CLS,
+               .matches = {
+                       "7: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R10=fp",
+                       "8: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv55,min_align=2 R10=fp",
+                       "9: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv54,min_align=4 R10=fp",
+                       "10: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv53,min_align=8 R10=fp",
+                       "11: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv52,min_align=16 R10=fp",
+                       "18: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv56 R10=fp",
+                       "19: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv51,min_align=32 R10=fp",
+                       "20: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv52,min_align=16 R10=fp",
+                       "21: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv53,min_align=8 R10=fp",
+                       "22: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv54,min_align=4 R10=fp",
+                       "23: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv55,min_align=2 R10=fp",
+               },
+       },
+       {
+               .descr = "unknown mul",
+               .insns = {
+                       LOAD_UNKNOWN(BPF_REG_3),
+                       BPF_MOV64_REG(BPF_REG_4, BPF_REG_3),
+                       BPF_ALU64_IMM(BPF_MUL, BPF_REG_4, 1),
+                       BPF_MOV64_REG(BPF_REG_4, BPF_REG_3),
+                       BPF_ALU64_IMM(BPF_MUL, BPF_REG_4, 2),
+                       BPF_MOV64_REG(BPF_REG_4, BPF_REG_3),
+                       BPF_ALU64_IMM(BPF_MUL, BPF_REG_4, 4),
+                       BPF_MOV64_REG(BPF_REG_4, BPF_REG_3),
+                       BPF_ALU64_IMM(BPF_MUL, BPF_REG_4, 8),
+                       BPF_ALU64_IMM(BPF_MUL, BPF_REG_4, 2),
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               .prog_type = BPF_PROG_TYPE_SCHED_CLS,
+               .matches = {
+                       "7: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R10=fp",
+                       "8: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv56 R10=fp",
+                       "9: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv55,min_align=1 R10=fp",
+                       "10: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv56 R10=fp",
+                       "11: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv54,min_align=2 R10=fp",
+                       "12: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv56 R10=fp",
+                       "13: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv53,min_align=4 R10=fp",
+                       "14: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv56 R10=fp",
+                       "15: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv52,min_align=8 R10=fp",
+                       "16: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv50,min_align=8 R10=fp"
+               },
+       },
+       {
+               .descr = "packet const offset",
+               .insns = {
+                       PREP_PKT_POINTERS,
+                       BPF_MOV64_REG(BPF_REG_5, BPF_REG_2),
+
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+
+                       /* Skip over ethernet header.  */
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, 14),
+                       BPF_MOV64_REG(BPF_REG_4, BPF_REG_5),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4),
+                       BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_4, 1),
+                       BPF_EXIT_INSN(),
+
+                       BPF_LDX_MEM(BPF_B, BPF_REG_4, BPF_REG_5, 0),
+                       BPF_LDX_MEM(BPF_B, BPF_REG_4, BPF_REG_5, 1),
+                       BPF_LDX_MEM(BPF_B, BPF_REG_4, BPF_REG_5, 2),
+                       BPF_LDX_MEM(BPF_B, BPF_REG_4, BPF_REG_5, 3),
+                       BPF_LDX_MEM(BPF_H, BPF_REG_4, BPF_REG_5, 0),
+                       BPF_LDX_MEM(BPF_H, BPF_REG_4, BPF_REG_5, 2),
+                       BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_5, 0),
+
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               .prog_type = BPF_PROG_TYPE_SCHED_CLS,
+               .matches = {
+                       "4: R0=imm0,min_value=0,max_value=0,min_align=2147483648 R1=ctx R2=pkt(id=0,off=0,r=0) R3=pkt_end R5=pkt(id=0,off=0,r=0) R10=fp",
+                       "5: R0=imm0,min_value=0,max_value=0,min_align=2147483648 R1=ctx R2=pkt(id=0,off=0,r=0) R3=pkt_end R5=pkt(id=0,off=14,r=0) R10=fp",
+                       "6: R0=imm0,min_value=0,max_value=0,min_align=2147483648 R1=ctx R2=pkt(id=0,off=0,r=0) R3=pkt_end R4=pkt(id=0,off=14,r=0) R5=pkt(id=0,off=14,r=0) R10=fp",
+                       "10: R0=imm0,min_value=0,max_value=0,min_align=2147483648 R1=ctx R2=pkt(id=0,off=0,r=18) R3=pkt_end R4=inv56 R5=pkt(id=0,off=14,r=18) R10=fp",
+                       "14: R0=imm0,min_value=0,max_value=0,min_align=2147483648 R1=ctx R2=pkt(id=0,off=0,r=18) R3=pkt_end R4=inv48 R5=pkt(id=0,off=14,r=18) R10=fp",
+                       "15: R0=imm0,min_value=0,max_value=0,min_align=2147483648 R1=ctx R2=pkt(id=0,off=0,r=18) R3=pkt_end R4=inv48 R5=pkt(id=0,off=14,r=18) R10=fp",
+               },
+       },
+       {
+               .descr = "packet variable offset",
+               .insns = {
+                       LOAD_UNKNOWN(BPF_REG_6),
+                       BPF_ALU64_IMM(BPF_LSH, BPF_REG_6, 2),
+
+                       /* First, add a constant to the R5 packet pointer,
+                        * then a variable with a known alignment.
+                        */
+                       BPF_MOV64_REG(BPF_REG_5, BPF_REG_2),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, 14),
+                       BPF_ALU64_REG(BPF_ADD, BPF_REG_5, BPF_REG_6),
+                       BPF_MOV64_REG(BPF_REG_4, BPF_REG_5),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4),
+                       BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_4, 1),
+                       BPF_EXIT_INSN(),
+                       BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_5, 0),
+
+                       /* Now, test in the other direction.  Adding first
+                        * the variable offset to R5, then the constant.
+                        */
+                       BPF_MOV64_REG(BPF_REG_5, BPF_REG_2),
+                       BPF_ALU64_REG(BPF_ADD, BPF_REG_5, BPF_REG_6),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, 14),
+                       BPF_MOV64_REG(BPF_REG_4, BPF_REG_5),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4),
+                       BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_4, 1),
+                       BPF_EXIT_INSN(),
+                       BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_5, 0),
+
+                       /* Test multiple accumulations of unknown values
+                        * into a packet pointer.
+                        */
+                       BPF_MOV64_REG(BPF_REG_5, BPF_REG_2),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, 14),
+                       BPF_ALU64_REG(BPF_ADD, BPF_REG_5, BPF_REG_6),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, 4),
+                       BPF_ALU64_REG(BPF_ADD, BPF_REG_5, BPF_REG_6),
+                       BPF_MOV64_REG(BPF_REG_4, BPF_REG_5),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4),
+                       BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_4, 1),
+                       BPF_EXIT_INSN(),
+                       BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_5, 0),
+
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               .prog_type = BPF_PROG_TYPE_SCHED_CLS,
+               .matches = {
+                       /* Calculated offset in R6 has unknown value, but known
+                        * alignment of 4.
+                        */
+                       "8: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R6=inv54,min_align=4 R10=fp",
+
+                       /* Offset is added to packet pointer R5, resulting in known
+                        * auxiliary alignment and offset.
+                        */
+                       "11: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R5=pkt(id=1,off=0,r=0),aux_off=14,aux_off_align=4 R6=inv54,min_align=4 R10=fp",
+
+                       /* At the time the word size load is performed from R5,
+                        * it's total offset is NET_IP_ALIGN + reg->off (0) +
+                        * reg->aux_off (14) which is 16.  Then the variable
+                        * offset is considered using reg->aux_off_align which
+                        * is 4 and meets the load's requirements.
+                        */
+                       "15: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=pkt(id=1,off=4,r=4),aux_off=14,aux_off_align=4 R5=pkt(id=1,off=0,r=4),aux_off=14,aux_off_align=4 R6=inv54,min_align=4 R10=fp",
+
+
+                       /* Variable offset is added to R5 packet pointer,
+                        * resulting in auxiliary alignment of 4.
+                        */
+                       "18: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv,aux_off=14,aux_off_align=4 R5=pkt(id=2,off=0,r=0),aux_off_align=4 R6=inv54,min_align=4 R10=fp",
+
+                       /* Constant offset is added to R5, resulting in
+                        * reg->off of 14.
+                        */
+                       "19: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv,aux_off=14,aux_off_align=4 R5=pkt(id=2,off=14,r=0),aux_off_align=4 R6=inv54,min_align=4 R10=fp",
+
+                       /* At the time the word size load is performed from R5,
+                        * it's total offset is NET_IP_ALIGN + reg->off (14) which
+                        * is 16.  Then the variable offset is considered using
+                        * reg->aux_off_align which is 4 and meets the load's
+                        * requirements.
+                        */
+                       "23: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=pkt(id=2,off=18,r=18),aux_off_align=4 R5=pkt(id=2,off=14,r=18),aux_off_align=4 R6=inv54,min_align=4 R10=fp",
+
+                       /* Constant offset is added to R5 packet pointer,
+                        * resulting in reg->off value of 14.
+                        */
+                       "26: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv,aux_off_align=4 R5=pkt(id=0,off=14,r=8) R6=inv54,min_align=4 R10=fp",
+                       /* Variable offset is added to R5, resulting in an
+                        * auxiliary offset of 14, and an auxiliary alignment of 4.
+                        */
+                       "27: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv,aux_off_align=4 R5=pkt(id=3,off=0,r=0),aux_off=14,aux_off_align=4 R6=inv54,min_align=4 R10=fp",
+                       /* Constant is added to R5 again, setting reg->off to 4. */
+                       "28: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv,aux_off_align=4 R5=pkt(id=3,off=4,r=0),aux_off=14,aux_off_align=4 R6=inv54,min_align=4 R10=fp",
+                       /* And once more we add a variable, which causes an accumulation
+                        * of reg->off into reg->aux_off_align, with resulting value of
+                        * 18.  The auxiliary alignment stays at 4.
+                        */
+                       "29: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv,aux_off_align=4 R5=pkt(id=4,off=0,r=0),aux_off=18,aux_off_align=4 R6=inv54,min_align=4 R10=fp",
+                       /* At the time the word size load is performed from R5,
+                        * it's total offset is NET_IP_ALIGN + reg->off (0) +
+                        * reg->aux_off (18) which is 20.  Then the variable offset
+                        * is considered using reg->aux_off_align which is 4 and meets
+                        * the load's requirements.
+                        */
+                       "33: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=pkt(id=4,off=4,r=4),aux_off=18,aux_off_align=4 R5=pkt(id=4,off=0,r=4),aux_off=18,aux_off_align=4 R6=inv54,min_align=4 R10=fp",
+               },
+       },
+};
+
+static int probe_filter_length(const struct bpf_insn *fp)
+{
+       int len;
+
+       for (len = MAX_INSNS - 1; len > 0; --len)
+               if (fp[len].code != 0 || fp[len].imm != 0)
+                       break;
+       return len + 1;
+}
+
+static char bpf_vlog[32768];
+
+static int do_test_single(struct bpf_align_test *test)
+{
+       struct bpf_insn *prog = test->insns;
+       int prog_type = test->prog_type;
+       int prog_len, i;
+       int fd_prog;
+       int ret;
+
+       prog_len = probe_filter_length(prog);
+       fd_prog = bpf_verify_program(prog_type ? : BPF_PROG_TYPE_SOCKET_FILTER,
+                                    prog, prog_len, 1, "GPL", 0,
+                                    bpf_vlog, sizeof(bpf_vlog));
+       if (fd_prog < 0) {
+               printf("Failed to load program.\n");
+               printf("%s", bpf_vlog);
+               ret = 1;
+       } else {
+               ret = 0;
+               for (i = 0; i < MAX_MATCHES; i++) {
+                       const char *t, *m = test->matches[i];
+
+                       if (!m)
+                               break;
+                       t = strstr(bpf_vlog, m);
+                       if (!t) {
+                               printf("Failed to find match: %s\n", m);
+                               ret = 1;
+                               printf("%s", bpf_vlog);
+                               break;
+                       }
+               }
+               close(fd_prog);
+       }
+       return ret;
+}
+
+static int do_test(unsigned int from, unsigned int to)
+{
+       int all_pass = 0;
+       int all_fail = 0;
+       unsigned int i;
+
+       for (i = from; i < to; i++) {
+               struct bpf_align_test *test = &tests[i];
+               int fail;
+
+               printf("Test %3d: %s ... ",
+                      i, test->descr);
+               fail = do_test_single(test);
+               if (fail) {
+                       all_fail++;
+                       printf("FAIL\n");
+               } else {
+                       all_pass++;
+                       printf("PASS\n");
+               }
+       }
+       printf("Results: %d pass %d fail\n",
+              all_pass, all_fail);
+       return 0;
+}
+
+int main(int argc, char **argv)
+{
+       unsigned int from = 0, to = ARRAY_SIZE(tests);
+
+       if (argc == 3) {
+               unsigned int l = atoi(argv[argc - 2]);
+               unsigned int u = atoi(argv[argc - 1]);
+
+               if (l < to && u < to) {
+                       from = l;
+                       to   = u + 1;
+               }
+       } else if (argc == 2) {
+               unsigned int t = atoi(argv[argc - 1]);
+
+               if (t < to) {
+                       from = t;
+                       to   = t + 1;
+               }
+       }
+       return do_test(from, to);
+}