Skip to content

Commit

Permalink
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Browse files Browse the repository at this point in the history
Pull networking fixes from David Miller:

 1) Fix list tests in netfilter ingress support, from Florian Westphal.

 2) Fix reversal of input and output interfaces in ingress hook
    invocation, from Pablo Neira Ayuso.

 3) We have a use after free in r8169, caught by Dave Jones, fixed by
    Francois Romieu.

 4) Splice use-after-free fix in AF_UNIX frmo Hannes Frederic Sowa.

 5) Three ipv6 route handling bug fixes from Martin KaFai Lau:
    a) Don't create clone routes not managed by the fib6 tree
    b) Don't forget to check expiration of DST_NOCACHE routes.
    c) Handle rt->dst.from == NULL properly.

 6) Several AF_PACKET fixes wrt transport header setting and SKB
    protocol setting, from Daniel Borkmann.

 7) Fix thunder driver crash on shutdown, from Pavel Fedin.

 8) Several Mellanox driver fixes (max MTU calculations, use of correct
    DMA unmap in TX path, etc.) from Saeed Mahameed, Tariq Toukan, Doron
    Tsur, Achiad Shochat, Eran Ben Elisha, and Noa Osherovich.

 9) Several mv88e6060 DSA driver fixes (wrong bit definitions for
    certain registers, etc.) from Neil Armstrong.

10) Make sure to disable preemption while updating per-cpu stats of ip
    tunnels, from Jason A.  Donenfeld.

11) Various ARM64 bpf JIT fixes, from Yang Shi.

12) Flush icache properly in ARM JITs, from Daniel Borkmann.

13) Fix masking of RX and TX interrupts in ravb driver, from Masaru
    Nagai.

14) Fix netdev feature propagation for devices not implementing
    ->ndo_set_features().  From Nikolay Aleksandrov.

15) Big endian fix in vmxnet3 driver, from Shrikrishna Khare.

16) RAW socket code increments incorrect SNMP counters, fix from Ben
    Cartwright-Cox.

17) IPv6 multicast SNMP counters are bumped twice, fix from Neil Horman.

18) Fix handling of VLAN headers on stacked devices when REORDER is
    disabled.  From Vlad Yasevich.

19) Fix SKB leaks and use-after-free in ipvlan and macvlan drivers, from
    Sabrina Dubroca.

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: (83 commits)
  MAINTAINERS: Update Mellanox's Eth NIC driver entries
  net/core: revert "net: fix __netdev_update_features return.." and add comment
  af_unix: take receive queue lock while appending new skb
  rtnetlink: fix frame size warning in rtnl_fill_ifinfo
  net: use skb_clone to avoid alloc_pages failure.
  packet: Use PAGE_ALIGNED macro
  packet: Don't check frames_per_block against negative values
  net: phy: Use interrupts when available in NOLINK state
  phy: marvell: Add support for 88E1540 PHY
  arm64: bpf: make BPF prologue and epilogue align with ARM64 AAPCS
  macvlan: fix leak in macvlan_handle_frame
  ipvlan: fix use after free of skb
  ipvlan: fix leak in ipvlan_rcv_frame
  vlan: Do not put vlan headers back on bridge and macvlan ports
  vlan: Fix untag operations of stacked vlans with REORDER_HEADER off
  via-velocity: unconditionally drop frames with bad l2 length
  ipg: Remove ipg driver
  dl2k: Add support for IP1000A-based cards
  snmp: Remove duplicate OUTMCAST stat increment
  net: thunder: Check for driver data in nicvf_remove()
  ...
  • Loading branch information
torvalds committed Nov 17, 2015
2 parents a18ab2f + e7523a4 commit 7f151f1
Show file tree
Hide file tree
Showing 84 changed files with 1,036 additions and 3,650 deletions.
17 changes: 9 additions & 8 deletions MAINTAINERS
Expand Up @@ -5711,13 +5711,6 @@ M: Juanjo Ciarlante <jjciarla@raiz.uncu.edu.ar>
S: Maintained
F: net/ipv4/netfilter/ipt_MASQUERADE.c

IP1000A 10/100/1000 GIGABIT ETHERNET DRIVER
M: Francois Romieu <romieu@fr.zoreil.com>
M: Sorbica Shieh <sorbica@icplus.com.tw>
L: netdev@vger.kernel.org
S: Maintained
F: drivers/net/ethernet/icplus/ipg.*

IPATH DRIVER
M: Mike Marciniszyn <infinipath@intel.com>
L: linux-rdma@vger.kernel.org
Expand Down Expand Up @@ -6923,13 +6916,21 @@ F: drivers/scsi/megaraid.*
F: drivers/scsi/megaraid/

MELLANOX ETHERNET DRIVER (mlx4_en)
M: Amir Vadai <amirv@mellanox.com>
M: Eugenia Emantayev <eugenia@mellanox.com>
L: netdev@vger.kernel.org
S: Supported
W: http://www.mellanox.com
Q: http://patchwork.ozlabs.org/project/netdev/list/
F: drivers/net/ethernet/mellanox/mlx4/en_*

MELLANOX ETHERNET DRIVER (mlx5e)
M: Saeed Mahameed <saeedm@mellanox.com>
L: netdev@vger.kernel.org
S: Supported
W: http://www.mellanox.com
Q: http://patchwork.ozlabs.org/project/netdev/list/
F: drivers/net/ethernet/mellanox/mlx5/core/en_*

MELLANOX ETHERNET SWITCH DRIVERS
M: Jiri Pirko <jiri@mellanox.com>
M: Ido Schimmel <idosch@mellanox.com>
Expand Down
2 changes: 1 addition & 1 deletion arch/arm/net/bpf_jit_32.c
Expand Up @@ -1061,7 +1061,7 @@ void bpf_jit_compile(struct bpf_prog *fp)
}
build_epilogue(&ctx);

flush_icache_range((u32)ctx.target, (u32)(ctx.target + ctx.idx));
flush_icache_range((u32)header, (u32)(ctx.target + ctx.idx));

#if __LINUX_ARM_ARCH__ < 7
if (ctx.imm_count)
Expand Down
48 changes: 41 additions & 7 deletions arch/arm64/net/bpf_jit_comp.c
Expand Up @@ -50,7 +50,7 @@ static const int bpf2a64[] = {
[BPF_REG_8] = A64_R(21),
[BPF_REG_9] = A64_R(22),
/* read-only frame pointer to access stack */
[BPF_REG_FP] = A64_FP,
[BPF_REG_FP] = A64_R(25),
/* temporary register for internal BPF JIT */
[TMP_REG_1] = A64_R(23),
[TMP_REG_2] = A64_R(24),
Expand Down Expand Up @@ -155,18 +155,49 @@ static void build_prologue(struct jit_ctx *ctx)
stack_size += 4; /* extra for skb_copy_bits buffer */
stack_size = STACK_ALIGN(stack_size);

/*
* BPF prog stack layout
*
* high
* original A64_SP => 0:+-----+ BPF prologue
* |FP/LR|
* current A64_FP => -16:+-----+
* | ... | callee saved registers
* +-----+
* | | x25/x26
* BPF fp register => -80:+-----+
* | |
* | ... | BPF prog stack
* | |
* | |
* current A64_SP => +-----+
* | |
* | ... | Function call stack
* | |
* +-----+
* low
*
*/

/* Save FP and LR registers to stay align with ARM64 AAPCS */
emit(A64_PUSH(A64_FP, A64_LR, A64_SP), ctx);
emit(A64_MOV(1, A64_FP, A64_SP), ctx);

/* Save callee-saved register */
emit(A64_PUSH(r6, r7, A64_SP), ctx);
emit(A64_PUSH(r8, r9, A64_SP), ctx);
if (ctx->tmp_used)
emit(A64_PUSH(tmp1, tmp2, A64_SP), ctx);

/* Set up BPF stack */
emit(A64_SUB_I(1, A64_SP, A64_SP, stack_size), ctx);
/* Save fp (x25) and x26. SP requires 16 bytes alignment */
emit(A64_PUSH(fp, A64_R(26), A64_SP), ctx);

/* Set up frame pointer */
/* Set up BPF prog stack base register (x25) */
emit(A64_MOV(1, fp, A64_SP), ctx);

/* Set up function call stack */
emit(A64_SUB_I(1, A64_SP, A64_SP, stack_size), ctx);

/* Clear registers A and X */
emit_a64_mov_i64(ra, 0, ctx);
emit_a64_mov_i64(rx, 0, ctx);
Expand All @@ -190,14 +221,17 @@ static void build_epilogue(struct jit_ctx *ctx)
/* We're done with BPF stack */
emit(A64_ADD_I(1, A64_SP, A64_SP, stack_size), ctx);

/* Restore fs (x25) and x26 */
emit(A64_POP(fp, A64_R(26), A64_SP), ctx);

/* Restore callee-saved register */
if (ctx->tmp_used)
emit(A64_POP(tmp1, tmp2, A64_SP), ctx);
emit(A64_POP(r8, r9, A64_SP), ctx);
emit(A64_POP(r6, r7, A64_SP), ctx);

/* Restore frame pointer */
emit(A64_MOV(1, fp, A64_SP), ctx);
/* Restore FP/LR registers */
emit(A64_POP(A64_FP, A64_LR, A64_SP), ctx);

/* Set return value */
emit(A64_MOV(1, A64_R(0), r0), ctx);
Expand Down Expand Up @@ -758,7 +792,7 @@ void bpf_int_jit_compile(struct bpf_prog *prog)
if (bpf_jit_enable > 1)
bpf_jit_dump(prog->len, image_size, 2, ctx.image);

bpf_flush_icache(ctx.image, ctx.image + ctx.idx);
bpf_flush_icache(header, ctx.image + ctx.idx);

set_memory_ro((unsigned long)header, header->pages);
prog->bpf_func = (void *)ctx.image;
Expand Down
114 changes: 38 additions & 76 deletions drivers/net/dsa/mv88e6060.c
Expand Up @@ -15,9 +15,7 @@
#include <linux/netdevice.h>
#include <linux/phy.h>
#include <net/dsa.h>

#define REG_PORT(p) (8 + (p))
#define REG_GLOBAL 0x0f
#include "mv88e6060.h"

static int reg_read(struct dsa_switch *ds, int addr, int reg)
{
Expand Down Expand Up @@ -67,13 +65,14 @@ static char *mv88e6060_probe(struct device *host_dev, int sw_addr)
if (bus == NULL)
return NULL;

ret = mdiobus_read(bus, sw_addr + REG_PORT(0), 0x03);
ret = mdiobus_read(bus, sw_addr + REG_PORT(0), PORT_SWITCH_ID);
if (ret >= 0) {
if (ret == 0x0600)
if (ret == PORT_SWITCH_ID_6060)
return "Marvell 88E6060 (A0)";
if (ret == 0x0601 || ret == 0x0602)
if (ret == PORT_SWITCH_ID_6060_R1 ||
ret == PORT_SWITCH_ID_6060_R2)
return "Marvell 88E6060 (B0)";
if ((ret & 0xfff0) == 0x0600)
if ((ret & PORT_SWITCH_ID_6060_MASK) == PORT_SWITCH_ID_6060)
return "Marvell 88E6060";
}

Expand All @@ -87,22 +86,26 @@ static int mv88e6060_switch_reset(struct dsa_switch *ds)
unsigned long timeout;

/* Set all ports to the disabled state. */
for (i = 0; i < 6; i++) {
ret = REG_READ(REG_PORT(i), 0x04);
REG_WRITE(REG_PORT(i), 0x04, ret & 0xfffc);
for (i = 0; i < MV88E6060_PORTS; i++) {
ret = REG_READ(REG_PORT(i), PORT_CONTROL);
REG_WRITE(REG_PORT(i), PORT_CONTROL,
ret & ~PORT_CONTROL_STATE_MASK);
}

/* Wait for transmit queues to drain. */
usleep_range(2000, 4000);

/* Reset the switch. */
REG_WRITE(REG_GLOBAL, 0x0a, 0xa130);
REG_WRITE(REG_GLOBAL, GLOBAL_ATU_CONTROL,
GLOBAL_ATU_CONTROL_SWRESET |
GLOBAL_ATU_CONTROL_ATUSIZE_1024 |
GLOBAL_ATU_CONTROL_ATE_AGE_5MIN);

/* Wait up to one second for reset to complete. */
timeout = jiffies + 1 * HZ;
while (time_before(jiffies, timeout)) {
ret = REG_READ(REG_GLOBAL, 0x00);
if ((ret & 0x8000) == 0x0000)
ret = REG_READ(REG_GLOBAL, GLOBAL_STATUS);
if (ret & GLOBAL_STATUS_INIT_READY)
break;

usleep_range(1000, 2000);
Expand All @@ -119,13 +122,15 @@ static int mv88e6060_setup_global(struct dsa_switch *ds)
* set the maximum frame size to 1536 bytes, and mask all
* interrupt sources.
*/
REG_WRITE(REG_GLOBAL, 0x04, 0x0800);
REG_WRITE(REG_GLOBAL, GLOBAL_CONTROL, GLOBAL_CONTROL_MAX_FRAME_1536);

/* Enable automatic address learning, set the address
* database size to 1024 entries, and set the default aging
* time to 5 minutes.
*/
REG_WRITE(REG_GLOBAL, 0x0a, 0x2130);
REG_WRITE(REG_GLOBAL, GLOBAL_ATU_CONTROL,
GLOBAL_ATU_CONTROL_ATUSIZE_1024 |
GLOBAL_ATU_CONTROL_ATE_AGE_5MIN);

return 0;
}
Expand All @@ -139,25 +144,30 @@ static int mv88e6060_setup_port(struct dsa_switch *ds, int p)
* state to Forwarding. Additionally, if this is the CPU
* port, enable Ingress and Egress Trailer tagging mode.
*/
REG_WRITE(addr, 0x04, dsa_is_cpu_port(ds, p) ? 0x4103 : 0x0003);
REG_WRITE(addr, PORT_CONTROL,
dsa_is_cpu_port(ds, p) ?
PORT_CONTROL_TRAILER |
PORT_CONTROL_INGRESS_MODE |
PORT_CONTROL_STATE_FORWARDING :
PORT_CONTROL_STATE_FORWARDING);

/* Port based VLAN map: give each port its own address
* database, allow the CPU port to talk to each of the 'real'
* ports, and allow each of the 'real' ports to only talk to
* the CPU port.
*/
REG_WRITE(addr, 0x06,
((p & 0xf) << 12) |
(dsa_is_cpu_port(ds, p) ?
ds->phys_port_mask :
(1 << ds->dst->cpu_port)));
REG_WRITE(addr, PORT_VLAN_MAP,
((p & 0xf) << PORT_VLAN_MAP_DBNUM_SHIFT) |
(dsa_is_cpu_port(ds, p) ?
ds->phys_port_mask :
BIT(ds->dst->cpu_port)));

/* Port Association Vector: when learning source addresses
* of packets, add the address to the address database using
* a port bitmap that has only the bit for this port set and
* the other bits clear.
*/
REG_WRITE(addr, 0x0b, 1 << p);
REG_WRITE(addr, PORT_ASSOC_VECTOR, BIT(p));

return 0;
}
Expand All @@ -177,7 +187,7 @@ static int mv88e6060_setup(struct dsa_switch *ds)
if (ret < 0)
return ret;

for (i = 0; i < 6; i++) {
for (i = 0; i < MV88E6060_PORTS; i++) {
ret = mv88e6060_setup_port(ds, i);
if (ret < 0)
return ret;
Expand All @@ -188,16 +198,17 @@ static int mv88e6060_setup(struct dsa_switch *ds)

static int mv88e6060_set_addr(struct dsa_switch *ds, u8 *addr)
{
REG_WRITE(REG_GLOBAL, 0x01, (addr[0] << 8) | addr[1]);
REG_WRITE(REG_GLOBAL, 0x02, (addr[2] << 8) | addr[3]);
REG_WRITE(REG_GLOBAL, 0x03, (addr[4] << 8) | addr[5]);
/* Use the same MAC Address as FD Pause frames for all ports */
REG_WRITE(REG_GLOBAL, GLOBAL_MAC_01, (addr[0] << 9) | addr[1]);
REG_WRITE(REG_GLOBAL, GLOBAL_MAC_23, (addr[2] << 8) | addr[3]);
REG_WRITE(REG_GLOBAL, GLOBAL_MAC_45, (addr[4] << 8) | addr[5]);

return 0;
}

static int mv88e6060_port_to_phy_addr(int port)
{
if (port >= 0 && port <= 5)
if (port >= 0 && port < MV88E6060_PORTS)
return port;
return -1;
}
Expand Down Expand Up @@ -225,62 +236,13 @@ mv88e6060_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val)
return reg_write(ds, addr, regnum, val);
}

static void mv88e6060_poll_link(struct dsa_switch *ds)
{
int i;

for (i = 0; i < DSA_MAX_PORTS; i++) {
struct net_device *dev;
int uninitialized_var(port_status);
int link;
int speed;
int duplex;
int fc;

dev = ds->ports[i];
if (dev == NULL)
continue;

link = 0;
if (dev->flags & IFF_UP) {
port_status = reg_read(ds, REG_PORT(i), 0x00);
if (port_status < 0)
continue;

link = !!(port_status & 0x1000);
}

if (!link) {
if (netif_carrier_ok(dev)) {
netdev_info(dev, "link down\n");
netif_carrier_off(dev);
}
continue;
}

speed = (port_status & 0x0100) ? 100 : 10;
duplex = (port_status & 0x0200) ? 1 : 0;
fc = ((port_status & 0xc000) == 0xc000) ? 1 : 0;

if (!netif_carrier_ok(dev)) {
netdev_info(dev,
"link up, %d Mb/s, %s duplex, flow control %sabled\n",
speed,
duplex ? "full" : "half",
fc ? "en" : "dis");
netif_carrier_on(dev);
}
}
}

static struct dsa_switch_driver mv88e6060_switch_driver = {
.tag_protocol = DSA_TAG_PROTO_TRAILER,
.probe = mv88e6060_probe,
.setup = mv88e6060_setup,
.set_addr = mv88e6060_set_addr,
.phy_read = mv88e6060_phy_read,
.phy_write = mv88e6060_phy_write,
.poll_link = mv88e6060_poll_link,
};

static int __init mv88e6060_init(void)
Expand Down

0 comments on commit 7f151f1

Please sign in to comment.