Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7f151f1d authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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()
  ...
parents a18ab2f6 e7523a49
Loading
Loading
Loading
Loading
+9 −8
Original line number Original line Diff line number Diff line
@@ -5711,13 +5711,6 @@ M: Juanjo Ciarlante <jjciarla@raiz.uncu.edu.ar>
S:	Maintained
S:	Maintained
F:	net/ipv4/netfilter/ipt_MASQUERADE.c
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
IPATH DRIVER
M:	Mike Marciniszyn <infinipath@intel.com>
M:	Mike Marciniszyn <infinipath@intel.com>
L:	linux-rdma@vger.kernel.org
L:	linux-rdma@vger.kernel.org
@@ -6923,13 +6916,21 @@ F: drivers/scsi/megaraid.*
F:	drivers/scsi/megaraid/
F:	drivers/scsi/megaraid/


MELLANOX ETHERNET DRIVER (mlx4_en)
MELLANOX ETHERNET DRIVER (mlx4_en)
M:	Amir Vadai <amirv@mellanox.com>
M: 	Eugenia Emantayev <eugenia@mellanox.com>
L:	netdev@vger.kernel.org
L:	netdev@vger.kernel.org
S:	Supported
S:	Supported
W:	http://www.mellanox.com
W:	http://www.mellanox.com
Q:	http://patchwork.ozlabs.org/project/netdev/list/
Q:	http://patchwork.ozlabs.org/project/netdev/list/
F:	drivers/net/ethernet/mellanox/mlx4/en_*
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
MELLANOX ETHERNET SWITCH DRIVERS
M:	Jiri Pirko <jiri@mellanox.com>
M:	Jiri Pirko <jiri@mellanox.com>
M:	Ido Schimmel <idosch@mellanox.com>
M:	Ido Schimmel <idosch@mellanox.com>
+1 −1
Original line number Original line Diff line number Diff line
@@ -1061,7 +1061,7 @@ void bpf_jit_compile(struct bpf_prog *fp)
	}
	}
	build_epilogue(&ctx);
	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 __LINUX_ARM_ARCH__ < 7
	if (ctx.imm_count)
	if (ctx.imm_count)
+41 −7
Original line number Original line Diff line number Diff line
@@ -50,7 +50,7 @@ static const int bpf2a64[] = {
	[BPF_REG_8] = A64_R(21),
	[BPF_REG_8] = A64_R(21),
	[BPF_REG_9] = A64_R(22),
	[BPF_REG_9] = A64_R(22),
	/* read-only frame pointer to access stack */
	/* read-only frame pointer to access stack */
	[BPF_REG_FP] = A64_FP,
	[BPF_REG_FP] = A64_R(25),
	/* temporary register for internal BPF JIT */
	/* temporary register for internal BPF JIT */
	[TMP_REG_1] = A64_R(23),
	[TMP_REG_1] = A64_R(23),
	[TMP_REG_2] = A64_R(24),
	[TMP_REG_2] = A64_R(24),
@@ -155,18 +155,49 @@ static void build_prologue(struct jit_ctx *ctx)
	stack_size += 4; /* extra for skb_copy_bits buffer */
	stack_size += 4; /* extra for skb_copy_bits buffer */
	stack_size = STACK_ALIGN(stack_size);
	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 */
	/* Save callee-saved register */
	emit(A64_PUSH(r6, r7, A64_SP), ctx);
	emit(A64_PUSH(r6, r7, A64_SP), ctx);
	emit(A64_PUSH(r8, r9, A64_SP), ctx);
	emit(A64_PUSH(r8, r9, A64_SP), ctx);
	if (ctx->tmp_used)
	if (ctx->tmp_used)
		emit(A64_PUSH(tmp1, tmp2, A64_SP), ctx);
		emit(A64_PUSH(tmp1, tmp2, A64_SP), ctx);


	/* Set up BPF stack */
	/* Save fp (x25) and x26. SP requires 16 bytes alignment */
	emit(A64_SUB_I(1, A64_SP, A64_SP, stack_size), ctx);
	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);
	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 */
	/* Clear registers A and X */
	emit_a64_mov_i64(ra, 0, ctx);
	emit_a64_mov_i64(ra, 0, ctx);
	emit_a64_mov_i64(rx, 0, ctx);
	emit_a64_mov_i64(rx, 0, ctx);
@@ -190,14 +221,17 @@ static void build_epilogue(struct jit_ctx *ctx)
	/* We're done with BPF stack */
	/* We're done with BPF stack */
	emit(A64_ADD_I(1, A64_SP, A64_SP, stack_size), ctx);
	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 */
	/* Restore callee-saved register */
	if (ctx->tmp_used)
	if (ctx->tmp_used)
		emit(A64_POP(tmp1, tmp2, A64_SP), ctx);
		emit(A64_POP(tmp1, tmp2, A64_SP), ctx);
	emit(A64_POP(r8, r9, A64_SP), ctx);
	emit(A64_POP(r8, r9, A64_SP), ctx);
	emit(A64_POP(r6, r7, A64_SP), ctx);
	emit(A64_POP(r6, r7, A64_SP), ctx);


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


	/* Set return value */
	/* Set return value */
	emit(A64_MOV(1, A64_R(0), r0), ctx);
	emit(A64_MOV(1, A64_R(0), r0), ctx);
@@ -758,7 +792,7 @@ void bpf_int_jit_compile(struct bpf_prog *prog)
	if (bpf_jit_enable > 1)
	if (bpf_jit_enable > 1)
		bpf_jit_dump(prog->len, image_size, 2, ctx.image);
		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);
	set_memory_ro((unsigned long)header, header->pages);
	prog->bpf_func = (void *)ctx.image;
	prog->bpf_func = (void *)ctx.image;
+38 −76
Original line number Original line Diff line number Diff line
@@ -15,9 +15,7 @@
#include <linux/netdevice.h>
#include <linux/netdevice.h>
#include <linux/phy.h>
#include <linux/phy.h>
#include <net/dsa.h>
#include <net/dsa.h>

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


static int reg_read(struct dsa_switch *ds, int addr, int reg)
static int reg_read(struct dsa_switch *ds, int addr, int reg)
{
{
@@ -67,13 +65,14 @@ static char *mv88e6060_probe(struct device *host_dev, int sw_addr)
	if (bus == NULL)
	if (bus == NULL)
		return 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 >= 0) {
		if (ret == 0x0600)
		if (ret == PORT_SWITCH_ID_6060)
			return "Marvell 88E6060 (A0)";
			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)";
			return "Marvell 88E6060 (B0)";
		if ((ret & 0xfff0) == 0x0600)
		if ((ret & PORT_SWITCH_ID_6060_MASK) == PORT_SWITCH_ID_6060)
			return "Marvell 88E6060";
			return "Marvell 88E6060";
	}
	}


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


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


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


	/* Reset the switch. */
	/* 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. */
	/* Wait up to one second for reset to complete. */
	timeout = jiffies + 1 * HZ;
	timeout = jiffies + 1 * HZ;
	while (time_before(jiffies, timeout)) {
	while (time_before(jiffies, timeout)) {
		ret = REG_READ(REG_GLOBAL, 0x00);
		ret = REG_READ(REG_GLOBAL, GLOBAL_STATUS);
		if ((ret & 0x8000) == 0x0000)
		if (ret & GLOBAL_STATUS_INIT_READY)
			break;
			break;


		usleep_range(1000, 2000);
		usleep_range(1000, 2000);
@@ -119,13 +122,15 @@ static int mv88e6060_setup_global(struct dsa_switch *ds)
	 * set the maximum frame size to 1536 bytes, and mask all
	 * set the maximum frame size to 1536 bytes, and mask all
	 * interrupt sources.
	 * 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
	/* Enable automatic address learning, set the address
	 * database size to 1024 entries, and set the default aging
	 * database size to 1024 entries, and set the default aging
	 * time to 5 minutes.
	 * 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;
	return 0;
}
}
@@ -139,25 +144,30 @@ static int mv88e6060_setup_port(struct dsa_switch *ds, int p)
	 * state to Forwarding.  Additionally, if this is the CPU
	 * state to Forwarding.  Additionally, if this is the CPU
	 * port, enable Ingress and Egress Trailer tagging mode.
	 * 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
	/* Port based VLAN map: give each port its own address
	 * database, allow the CPU port to talk to each of the 'real'
	 * database, allow the CPU port to talk to each of the 'real'
	 * ports, and allow each of the 'real' ports to only talk to
	 * ports, and allow each of the 'real' ports to only talk to
	 * the CPU port.
	 * the CPU port.
	 */
	 */
	REG_WRITE(addr, 0x06,
	REG_WRITE(addr, PORT_VLAN_MAP,
			((p & 0xf) << 12) |
		  ((p & 0xf) << PORT_VLAN_MAP_DBNUM_SHIFT) |
		   (dsa_is_cpu_port(ds, p) ?
		   (dsa_is_cpu_port(ds, p) ?
			ds->phys_port_mask :
			ds->phys_port_mask :
				(1 << ds->dst->cpu_port)));
			BIT(ds->dst->cpu_port)));


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


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


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


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


static int mv88e6060_port_to_phy_addr(int port)
static int mv88e6060_port_to_phy_addr(int port)
{
{
	if (port >= 0 && port <= 5)
	if (port >= 0 && port < MV88E6060_PORTS)
		return port;
		return port;
	return -1;
	return -1;
}
}
@@ -225,54 +236,6 @@ mv88e6060_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val)
	return reg_write(ds, addr, regnum, 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 = {
static struct dsa_switch_driver mv88e6060_switch_driver = {
	.tag_protocol	= DSA_TAG_PROTO_TRAILER,
	.tag_protocol	= DSA_TAG_PROTO_TRAILER,
	.probe		= mv88e6060_probe,
	.probe		= mv88e6060_probe,
@@ -280,7 +243,6 @@ static struct dsa_switch_driver mv88e6060_switch_driver = {
	.set_addr	= mv88e6060_set_addr,
	.set_addr	= mv88e6060_set_addr,
	.phy_read	= mv88e6060_phy_read,
	.phy_read	= mv88e6060_phy_read,
	.phy_write	= mv88e6060_phy_write,
	.phy_write	= mv88e6060_phy_write,
	.poll_link	= mv88e6060_poll_link,
};
};


static int __init mv88e6060_init(void)
static int __init mv88e6060_init(void)
+111 −0
Original line number Original line Diff line number Diff line
/*
 * drivers/net/dsa/mv88e6060.h - Marvell 88e6060 switch chip support
 * Copyright (c) 2015 Neil Armstrong
 *
 * Based on mv88e6xxx.h
 * Copyright (c) 2008 Marvell Semiconductor
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 */

#ifndef __MV88E6060_H
#define __MV88E6060_H

#define MV88E6060_PORTS	6

#define REG_PORT(p)		(0x8 + (p))
#define PORT_STATUS		0x00
#define PORT_STATUS_PAUSE_EN	BIT(15)
#define PORT_STATUS_MY_PAUSE	BIT(14)
#define PORT_STATUS_FC		(PORT_STATUS_MY_PAUSE | PORT_STATUS_PAUSE_EN)
#define PORT_STATUS_RESOLVED	BIT(13)
#define PORT_STATUS_LINK	BIT(12)
#define PORT_STATUS_PORTMODE	BIT(11)
#define PORT_STATUS_PHYMODE	BIT(10)
#define PORT_STATUS_DUPLEX	BIT(9)
#define PORT_STATUS_SPEED	BIT(8)
#define PORT_SWITCH_ID		0x03
#define PORT_SWITCH_ID_6060	0x0600
#define PORT_SWITCH_ID_6060_MASK	0xfff0
#define PORT_SWITCH_ID_6060_R1	0x0601
#define PORT_SWITCH_ID_6060_R2	0x0602
#define PORT_CONTROL		0x04
#define PORT_CONTROL_FORCE_FLOW_CTRL	BIT(15)
#define PORT_CONTROL_TRAILER	BIT(14)
#define PORT_CONTROL_HEADER	BIT(11)
#define PORT_CONTROL_INGRESS_MODE	BIT(8)
#define PORT_CONTROL_VLAN_TUNNEL	BIT(7)
#define PORT_CONTROL_STATE_MASK	0x03
#define PORT_CONTROL_STATE_DISABLED	0x00
#define PORT_CONTROL_STATE_BLOCKING	0x01
#define PORT_CONTROL_STATE_LEARNING	0x02
#define PORT_CONTROL_STATE_FORWARDING	0x03
#define PORT_VLAN_MAP		0x06
#define PORT_VLAN_MAP_DBNUM_SHIFT	12
#define PORT_VLAN_MAP_TABLE_MASK	0x1f
#define PORT_ASSOC_VECTOR	0x0b
#define PORT_ASSOC_VECTOR_MONITOR	BIT(15)
#define PORT_ASSOC_VECTOR_PAV_MASK	0x1f
#define PORT_RX_CNTR		0x10
#define PORT_TX_CNTR		0x11

#define REG_GLOBAL		0x0f
#define GLOBAL_STATUS		0x00
#define GLOBAL_STATUS_SW_MODE_MASK	(0x3 << 12)
#define GLOBAL_STATUS_SW_MODE_0	(0x0 << 12)
#define GLOBAL_STATUS_SW_MODE_1	(0x1 << 12)
#define GLOBAL_STATUS_SW_MODE_2	(0x2 << 12)
#define GLOBAL_STATUS_SW_MODE_3	(0x3 << 12)
#define GLOBAL_STATUS_INIT_READY	BIT(11)
#define GLOBAL_STATUS_ATU_FULL		BIT(3)
#define GLOBAL_STATUS_ATU_DONE		BIT(2)
#define GLOBAL_STATUS_PHY_INT	BIT(1)
#define GLOBAL_STATUS_EEINT	BIT(0)
#define GLOBAL_MAC_01		0x01
#define GLOBAL_MAC_01_DIFF_ADDR	BIT(8)
#define GLOBAL_MAC_23		0x02
#define GLOBAL_MAC_45		0x03
#define GLOBAL_CONTROL		0x04
#define GLOBAL_CONTROL_DISCARD_EXCESS	BIT(13)
#define GLOBAL_CONTROL_MAX_FRAME_1536	BIT(10)
#define GLOBAL_CONTROL_RELOAD_EEPROM	BIT(9)
#define GLOBAL_CONTROL_CTRMODE		BIT(8)
#define GLOBAL_CONTROL_ATU_FULL_EN	BIT(3)
#define GLOBAL_CONTROL_ATU_DONE_EN	BIT(2)
#define GLOBAL_CONTROL_PHYINT_EN	BIT(1)
#define GLOBAL_CONTROL_EEPROM_DONE_EN	BIT(0)
#define GLOBAL_ATU_CONTROL	0x0a
#define GLOBAL_ATU_CONTROL_SWRESET	BIT(15)
#define GLOBAL_ATU_CONTROL_LEARNDIS	BIT(14)
#define GLOBAL_ATU_CONTROL_ATUSIZE_256	(0x0 << 12)
#define GLOBAL_ATU_CONTROL_ATUSIZE_512	(0x1 << 12)
#define GLOBAL_ATU_CONTROL_ATUSIZE_1024	(0x2 << 12)
#define GLOBAL_ATU_CONTROL_ATE_AGE_SHIFT	4
#define GLOBAL_ATU_CONTROL_ATE_AGE_MASK	(0xff << 4)
#define GLOBAL_ATU_CONTROL_ATE_AGE_5MIN	(0x13 << 4)
#define GLOBAL_ATU_OP		0x0b
#define GLOBAL_ATU_OP_BUSY	BIT(15)
#define GLOBAL_ATU_OP_NOP		(0 << 12)
#define GLOBAL_ATU_OP_FLUSH_ALL	((1 << 12) | GLOBAL_ATU_OP_BUSY)
#define GLOBAL_ATU_OP_FLUSH_UNLOCKED	((2 << 12) | GLOBAL_ATU_OP_BUSY)
#define GLOBAL_ATU_OP_LOAD_DB		((3 << 12) | GLOBAL_ATU_OP_BUSY)
#define GLOBAL_ATU_OP_GET_NEXT_DB	((4 << 12) | GLOBAL_ATU_OP_BUSY)
#define GLOBAL_ATU_OP_FLUSH_DB		((5 << 12) | GLOBAL_ATU_OP_BUSY)
#define GLOBAL_ATU_OP_FLUSH_UNLOCKED_DB ((6 << 12) | GLOBAL_ATU_OP_BUSY)
#define GLOBAL_ATU_DATA		0x0c
#define GLOBAL_ATU_DATA_PORT_VECTOR_MASK	0x3f0
#define GLOBAL_ATU_DATA_PORT_VECTOR_SHIFT	4
#define GLOBAL_ATU_DATA_STATE_MASK		0x0f
#define GLOBAL_ATU_DATA_STATE_UNUSED		0x00
#define GLOBAL_ATU_DATA_STATE_UC_STATIC		0x0e
#define GLOBAL_ATU_DATA_STATE_UC_LOCKED		0x0f
#define GLOBAL_ATU_DATA_STATE_MC_STATIC		0x07
#define GLOBAL_ATU_DATA_STATE_MC_LOCKED		0x0e
#define GLOBAL_ATU_MAC_01	0x0d
#define GLOBAL_ATU_MAC_23	0x0e
#define GLOBAL_ATU_MAC_45	0x0f

#endif
Loading