* [PATCH net-next 3/5] net: dsa: b53: Add helper to set link parameters
From: Florian Fainelli @ 2018-09-04 22:11 UTC (permalink / raw)
To: netdev; +Cc: Florian Fainelli, andrew, vivien.didelot, davem
In-Reply-To: <20180904221120.13018-1-f.fainelli@gmail.com>
Extract the logic from b53_adjust_link() responsible for overriding a
given port's link, speed, duplex and pause settings and make two helper
functions to set the port's configuration and the port's link settings.
We will make use of both, as separate functions while adding PHYLINK
support next.
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
drivers/net/dsa/b53/b53_common.c | 89 +++++++++++++++++++++-----------
1 file changed, 60 insertions(+), 29 deletions(-)
diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c
index 85ed264bc163..78aeaccf19a1 100644
--- a/drivers/net/dsa/b53/b53_common.c
+++ b/drivers/net/dsa/b53/b53_common.c
@@ -26,6 +26,7 @@
#include <linux/module.h>
#include <linux/platform_data/b53.h>
#include <linux/phy.h>
+#include <linux/phylink.h>
#include <linux/etherdevice.h>
#include <linux/if_bridge.h>
#include <net/dsa.h>
@@ -947,33 +948,50 @@ static int b53_setup(struct dsa_switch *ds)
return ret;
}
-static void b53_adjust_link(struct dsa_switch *ds, int port,
- struct phy_device *phydev)
+static void b53_force_link(struct b53_device *dev, int port, int link)
{
- struct b53_device *dev = ds->priv;
- struct ethtool_eee *p = &dev->ports[port].eee;
- u8 rgmii_ctrl = 0, reg = 0, off;
-
- if (!phy_is_pseudo_fixed_link(phydev))
- return;
+ u8 reg, val, off;
/* Override the port settings */
if (port == dev->cpu_port) {
off = B53_PORT_OVERRIDE_CTRL;
- reg = PORT_OVERRIDE_EN;
+ val = PORT_OVERRIDE_EN;
} else {
off = B53_GMII_PORT_OVERRIDE_CTRL(port);
- reg = GMII_PO_EN;
+ val = GMII_PO_EN;
}
- /* Set the link UP */
- if (phydev->link)
+ b53_read8(dev, B53_CTRL_PAGE, off, ®);
+ reg |= val;
+ if (link)
reg |= PORT_OVERRIDE_LINK;
+ else
+ reg &= ~PORT_OVERRIDE_LINK;
+ b53_write8(dev, B53_CTRL_PAGE, off, reg);
+}
+
+static void b53_force_port_config(struct b53_device *dev, int port,
+ int speed, int duplex, int pause)
+{
+ u8 reg, val, off;
+
+ /* Override the port settings */
+ if (port == dev->cpu_port) {
+ off = B53_PORT_OVERRIDE_CTRL;
+ val = PORT_OVERRIDE_EN;
+ } else {
+ off = B53_GMII_PORT_OVERRIDE_CTRL(port);
+ val = GMII_PO_EN;
+ }
- if (phydev->duplex == DUPLEX_FULL)
+ b53_read8(dev, B53_CTRL_PAGE, off, ®);
+ reg |= val;
+ if (duplex == DUPLEX_FULL)
reg |= PORT_OVERRIDE_FULL_DUPLEX;
+ else
+ reg &= ~PORT_OVERRIDE_FULL_DUPLEX;
- switch (phydev->speed) {
+ switch (speed) {
case 2000:
reg |= PORT_OVERRIDE_SPEED_2000M;
/* fallthrough */
@@ -987,21 +1005,41 @@ static void b53_adjust_link(struct dsa_switch *ds, int port,
reg |= PORT_OVERRIDE_SPEED_10M;
break;
default:
- dev_err(ds->dev, "unknown speed: %d\n", phydev->speed);
+ dev_err(dev->dev, "unknown speed: %d\n", speed);
return;
}
+ if (pause & MLO_PAUSE_RX)
+ reg |= PORT_OVERRIDE_RX_FLOW;
+ if (pause & MLO_PAUSE_TX)
+ reg |= PORT_OVERRIDE_TX_FLOW;
+
+ b53_write8(dev, B53_CTRL_PAGE, off, reg);
+}
+
+static void b53_adjust_link(struct dsa_switch *ds, int port,
+ struct phy_device *phydev)
+{
+ struct b53_device *dev = ds->priv;
+ struct ethtool_eee *p = &dev->ports[port].eee;
+ u8 rgmii_ctrl = 0, reg = 0, off;
+ int pause;
+
+ if (!phy_is_pseudo_fixed_link(phydev))
+ return;
+
/* Enable flow control on BCM5301x's CPU port */
if (is5301x(dev) && port == dev->cpu_port)
- reg |= PORT_OVERRIDE_RX_FLOW | PORT_OVERRIDE_TX_FLOW;
+ pause = MLO_PAUSE_TXRX_MASK;
if (phydev->pause) {
if (phydev->asym_pause)
- reg |= PORT_OVERRIDE_TX_FLOW;
- reg |= PORT_OVERRIDE_RX_FLOW;
+ pause |= MLO_PAUSE_TX;
+ pause |= MLO_PAUSE_RX;
}
- b53_write8(dev, B53_CTRL_PAGE, off, reg);
+ b53_force_port_config(dev, port, phydev->speed, phydev->duplex, pause);
+ b53_force_link(dev, port, phydev->link);
if (is531x5(dev) && phy_interface_is_rgmii(phydev)) {
if (port == 8)
@@ -1061,16 +1099,9 @@ static void b53_adjust_link(struct dsa_switch *ds, int port,
}
} else if (is5301x(dev)) {
if (port != dev->cpu_port) {
- u8 po_reg = B53_GMII_PORT_OVERRIDE_CTRL(dev->cpu_port);
- u8 gmii_po;
-
- b53_read8(dev, B53_CTRL_PAGE, po_reg, &gmii_po);
- gmii_po |= GMII_PO_LINK |
- GMII_PO_RX_FLOW |
- GMII_PO_TX_FLOW |
- GMII_PO_EN |
- GMII_PO_SPEED_2000M;
- b53_write8(dev, B53_CTRL_PAGE, po_reg, gmii_po);
+ b53_force_port_config(dev, dev->cpu_port, 2000,
+ DUPLEX_FULL, MLO_PAUSE_TXRX_MASK);
+ b53_force_link(dev, dev->cpu_port, 1);
}
}
--
2.17.1
^ permalink raw reply related
* [PATCH net-next 4/5] net: dsa: b53: Add PHYLINK support
From: Florian Fainelli @ 2018-09-04 22:11 UTC (permalink / raw)
To: netdev; +Cc: Florian Fainelli, andrew, vivien.didelot, davem
In-Reply-To: <20180904221120.13018-1-f.fainelli@gmail.com>
Add support for PHYLINK, things are reasonably straight forward since we
do not yet support SerDes interfaces, that leaves us with just
MLO_AN_PHY and MLO_AN_FIXED to deal with.
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
drivers/net/dsa/b53/b53_common.c | 120 +++++++++++++++++++++++++++++++
drivers/net/dsa/b53/b53_priv.h | 17 +++++
2 files changed, 137 insertions(+)
diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c
index 78aeaccf19a1..108d272ca4c7 100644
--- a/drivers/net/dsa/b53/b53_common.c
+++ b/drivers/net/dsa/b53/b53_common.c
@@ -1109,6 +1109,120 @@ static void b53_adjust_link(struct dsa_switch *ds, int port,
p->eee_enabled = b53_eee_init(ds, port, phydev);
}
+void b53_port_event(struct dsa_switch *ds, int port)
+{
+ struct b53_device *dev = ds->priv;
+ bool link;
+ u16 sts;
+
+ b53_read16(dev, B53_STAT_PAGE, B53_LINK_STAT, &sts);
+ link = !!(sts & BIT(port));
+ dsa_port_phylink_mac_change(ds, port, link);
+}
+EXPORT_SYMBOL(b53_port_event);
+
+void b53_phylink_validate(struct dsa_switch *ds, int port,
+ unsigned long *supported,
+ struct phylink_link_state *state)
+{
+ struct b53_device *dev = ds->priv;
+ __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
+
+ /* Allow all the expected bits */
+ phylink_set(mask, Autoneg);
+ phylink_set_port_modes(mask);
+ phylink_set(mask, Pause);
+ phylink_set(mask, Asym_Pause);
+
+ /* With the exclusion of 5325/5365, MII, Reverse MII and 802.3z, we
+ * support Gigabit, including Half duplex.
+ */
+ if (state->interface != PHY_INTERFACE_MODE_MII &&
+ state->interface != PHY_INTERFACE_MODE_REVMII &&
+ !phy_interface_mode_is_8023z(state->interface) &&
+ !(is5325(dev) || is5365(dev))) {
+ phylink_set(mask, 1000baseT_Full);
+ phylink_set(mask, 1000baseT_Half);
+ }
+
+ if (!phy_interface_mode_is_8023z(state->interface)) {
+ phylink_set(mask, 10baseT_Half);
+ phylink_set(mask, 10baseT_Full);
+ phylink_set(mask, 100baseT_Half);
+ phylink_set(mask, 100baseT_Full);
+ }
+
+ bitmap_and(supported, supported, mask,
+ __ETHTOOL_LINK_MODE_MASK_NBITS);
+ bitmap_and(state->advertising, state->advertising, mask,
+ __ETHTOOL_LINK_MODE_MASK_NBITS);
+
+ phylink_helper_basex_speed(state);
+}
+EXPORT_SYMBOL(b53_phylink_validate);
+
+int b53_phylink_mac_link_state(struct dsa_switch *ds, int port,
+ struct phylink_link_state *state)
+{
+ int ret = -EOPNOTSUPP;
+
+ return ret;
+}
+EXPORT_SYMBOL(b53_phylink_mac_link_state);
+
+void b53_phylink_mac_config(struct dsa_switch *ds, int port,
+ unsigned int mode,
+ const struct phylink_link_state *state)
+{
+ struct b53_device *dev = ds->priv;
+
+ if (mode == MLO_AN_PHY)
+ return;
+
+ if (mode == MLO_AN_FIXED)
+ b53_force_port_config(dev, port, state->speed,
+ state->duplex, state->pause);
+}
+EXPORT_SYMBOL(b53_phylink_mac_config);
+
+void b53_phylink_mac_an_restart(struct dsa_switch *ds, int port)
+{
+}
+EXPORT_SYMBOL(b53_phylink_mac_an_restart);
+
+void b53_phylink_mac_link_down(struct dsa_switch *ds, int port,
+ unsigned int mode,
+ phy_interface_t interface)
+{
+ struct b53_device *dev = ds->priv;
+
+ if (mode == MLO_AN_PHY)
+ return;
+
+ if (mode == MLO_AN_FIXED) {
+ b53_force_link(dev, port, false);
+ return;
+ }
+}
+EXPORT_SYMBOL(b53_phylink_mac_link_down);
+
+void b53_phylink_mac_link_up(struct dsa_switch *ds, int port,
+ unsigned int mode,
+ phy_interface_t interface,
+ struct phy_device *phydev)
+{
+ struct b53_device *dev = ds->priv;
+
+ if (mode == MLO_AN_PHY)
+ return;
+
+ if (mode == MLO_AN_FIXED) {
+ b53_force_link(dev, port, true);
+ return;
+ }
+}
+EXPORT_SYMBOL(b53_phylink_mac_link_up);
+
int b53_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering)
{
return 0;
@@ -1750,6 +1864,12 @@ static const struct dsa_switch_ops b53_switch_ops = {
.phy_read = b53_phy_read16,
.phy_write = b53_phy_write16,
.adjust_link = b53_adjust_link,
+ .phylink_validate = b53_phylink_validate,
+ .phylink_mac_link_state = b53_phylink_mac_link_state,
+ .phylink_mac_config = b53_phylink_mac_config,
+ .phylink_mac_an_restart = b53_phylink_mac_an_restart,
+ .phylink_mac_link_down = b53_phylink_mac_link_down,
+ .phylink_mac_link_up = b53_phylink_mac_link_up,
.port_enable = b53_enable_port,
.port_disable = b53_disable_port,
.get_mac_eee = b53_get_mac_eee,
diff --git a/drivers/net/dsa/b53/b53_priv.h b/drivers/net/dsa/b53/b53_priv.h
index 2980a5838f58..3f79dc07c00f 100644
--- a/drivers/net/dsa/b53/b53_priv.h
+++ b/drivers/net/dsa/b53/b53_priv.h
@@ -300,6 +300,23 @@ int b53_br_join(struct dsa_switch *ds, int port, struct net_device *bridge);
void b53_br_leave(struct dsa_switch *ds, int port, struct net_device *bridge);
void b53_br_set_stp_state(struct dsa_switch *ds, int port, u8 state);
void b53_br_fast_age(struct dsa_switch *ds, int port);
+void b53_port_event(struct dsa_switch *ds, int port);
+void b53_phylink_validate(struct dsa_switch *ds, int port,
+ unsigned long *supported,
+ struct phylink_link_state *state);
+int b53_phylink_mac_link_state(struct dsa_switch *ds, int port,
+ struct phylink_link_state *state);
+void b53_phylink_mac_config(struct dsa_switch *ds, int port,
+ unsigned int mode,
+ const struct phylink_link_state *state);
+void b53_phylink_mac_an_restart(struct dsa_switch *ds, int port);
+void b53_phylink_mac_link_down(struct dsa_switch *ds, int port,
+ unsigned int mode,
+ phy_interface_t interface);
+void b53_phylink_mac_link_up(struct dsa_switch *ds, int port,
+ unsigned int mode,
+ phy_interface_t interface,
+ struct phy_device *phydev);
int b53_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering);
int b53_vlan_prepare(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_vlan *vlan);
--
2.17.1
^ permalink raw reply related
* [PATCH net-next 5/5] net: dsa: b53: Add SerDes support
From: Florian Fainelli @ 2018-09-04 22:11 UTC (permalink / raw)
To: netdev; +Cc: Florian Fainelli, andrew, vivien.didelot, davem
In-Reply-To: <20180904221120.13018-1-f.fainelli@gmail.com>
Add support for the Northstar Plus SerDes which is accessed through a
special page of the switch. Since this is something that most people
probably will not want to use, make it a configurable option.
The SerDes supports both SGMII and 1000baseX modes, and is internally
looking like a seemingly standard MII PHY, except for the few bits that
got repurposed.
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
drivers/net/dsa/b53/Kconfig | 7 +
drivers/net/dsa/b53/Makefile | 1 +
drivers/net/dsa/b53/b53_common.c | 25 ++++
drivers/net/dsa/b53/b53_priv.h | 17 +++
drivers/net/dsa/b53/b53_serdes.c | 217 +++++++++++++++++++++++++++++++
drivers/net/dsa/b53/b53_serdes.h | 121 +++++++++++++++++
drivers/net/dsa/b53/b53_srab.c | 109 ++++++++++++++++
7 files changed, 497 insertions(+)
create mode 100644 drivers/net/dsa/b53/b53_serdes.c
create mode 100644 drivers/net/dsa/b53/b53_serdes.h
diff --git a/drivers/net/dsa/b53/Kconfig b/drivers/net/dsa/b53/Kconfig
index 37745f4bf4f6..ceb5cee10218 100644
--- a/drivers/net/dsa/b53/Kconfig
+++ b/drivers/net/dsa/b53/Kconfig
@@ -35,3 +35,10 @@ config B53_SRAB_DRIVER
help
Select to enable support for memory-mapped Switch Register Access
Bridge Registers (SRAB) like it is found on the BCM53010
+
+config B53_SERDES
+ tristate "B53 SerDes support"
+ depends on B53
+ default ARCH_BCM_IPROC
+ help
+ Select to enable support for SerDes on e.g: Northstar Plus SoCs.
diff --git a/drivers/net/dsa/b53/Makefile b/drivers/net/dsa/b53/Makefile
index 4256fb42a4dd..b1be13023ae4 100644
--- a/drivers/net/dsa/b53/Makefile
+++ b/drivers/net/dsa/b53/Makefile
@@ -5,3 +5,4 @@ obj-$(CONFIG_B53_SPI_DRIVER) += b53_spi.o
obj-$(CONFIG_B53_MDIO_DRIVER) += b53_mdio.o
obj-$(CONFIG_B53_MMAP_DRIVER) += b53_mmap.o
obj-$(CONFIG_B53_SRAB_DRIVER) += b53_srab.o
+obj-$(CONFIG_B53_SERDES) += b53_serdes.o
diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c
index 108d272ca4c7..64d72c713f1e 100644
--- a/drivers/net/dsa/b53/b53_common.c
+++ b/drivers/net/dsa/b53/b53_common.c
@@ -765,6 +765,8 @@ static int b53_reset_switch(struct b53_device *priv)
memset(priv->vlans, 0, sizeof(*priv->vlans) * priv->num_vlans);
memset(priv->ports, 0, sizeof(*priv->ports) * priv->num_ports);
+ priv->serdes_lane = B53_INVALID_LANE;
+
return b53_switch_reset(priv);
}
@@ -1128,6 +1130,9 @@ void b53_phylink_validate(struct dsa_switch *ds, int port,
struct b53_device *dev = ds->priv;
__ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
+ if (dev->ops->serdes_phylink_validate)
+ dev->ops->serdes_phylink_validate(dev, port, mask, state);
+
/* Allow all the expected bits */
phylink_set(mask, Autoneg);
phylink_set_port_modes(mask);
@@ -1164,8 +1169,12 @@ EXPORT_SYMBOL(b53_phylink_validate);
int b53_phylink_mac_link_state(struct dsa_switch *ds, int port,
struct phylink_link_state *state)
{
+ struct b53_device *dev = ds->priv;
int ret = -EOPNOTSUPP;
+ if (dev->ops->serdes_link_state)
+ ret = dev->ops->serdes_link_state(dev, port, state);
+
return ret;
}
EXPORT_SYMBOL(b53_phylink_mac_link_state);
@@ -1182,11 +1191,19 @@ void b53_phylink_mac_config(struct dsa_switch *ds, int port,
if (mode == MLO_AN_FIXED)
b53_force_port_config(dev, port, state->speed,
state->duplex, state->pause);
+
+ if (phy_interface_mode_is_8023z(state->interface) &&
+ dev->ops->serdes_config)
+ dev->ops->serdes_config(dev, port, mode, state);
}
EXPORT_SYMBOL(b53_phylink_mac_config);
void b53_phylink_mac_an_restart(struct dsa_switch *ds, int port)
{
+ struct b53_device *dev = ds->priv;
+
+ if (dev->ops->serdes_an_restart)
+ dev->ops->serdes_an_restart(dev, port);
}
EXPORT_SYMBOL(b53_phylink_mac_an_restart);
@@ -1203,6 +1220,10 @@ void b53_phylink_mac_link_down(struct dsa_switch *ds, int port,
b53_force_link(dev, port, false);
return;
}
+
+ if (phy_interface_mode_is_8023z(interface) &&
+ dev->ops->serdes_link_set)
+ dev->ops->serdes_link_set(dev, port, mode, interface, false);
}
EXPORT_SYMBOL(b53_phylink_mac_link_down);
@@ -1220,6 +1241,10 @@ void b53_phylink_mac_link_up(struct dsa_switch *ds, int port,
b53_force_link(dev, port, true);
return;
}
+
+ if (phy_interface_mode_is_8023z(interface) &&
+ dev->ops->serdes_link_set)
+ dev->ops->serdes_link_set(dev, port, mode, interface, true);
}
EXPORT_SYMBOL(b53_phylink_mac_link_up);
diff --git a/drivers/net/dsa/b53/b53_priv.h b/drivers/net/dsa/b53/b53_priv.h
index 3f79dc07c00f..ec796482792d 100644
--- a/drivers/net/dsa/b53/b53_priv.h
+++ b/drivers/net/dsa/b53/b53_priv.h
@@ -29,6 +29,7 @@
struct b53_device;
struct net_device;
+struct phylink_link_state;
struct b53_io_ops {
int (*read8)(struct b53_device *dev, u8 page, u8 reg, u8 *value);
@@ -45,8 +46,23 @@ struct b53_io_ops {
int (*phy_write16)(struct b53_device *dev, int addr, int reg, u16 value);
int (*irq_enable)(struct b53_device *dev, int port);
void (*irq_disable)(struct b53_device *dev, int port);
+ u8 (*serdes_map_lane)(struct b53_device *dev, int port);
+ int (*serdes_link_state)(struct b53_device *dev, int port,
+ struct phylink_link_state *state);
+ void (*serdes_config)(struct b53_device *dev, int port,
+ unsigned int mode,
+ const struct phylink_link_state *state);
+ void (*serdes_an_restart)(struct b53_device *dev, int port);
+ void (*serdes_link_set)(struct b53_device *dev, int port,
+ unsigned int mode, phy_interface_t interface,
+ bool link_up);
+ void (*serdes_phylink_validate)(struct b53_device *dev, int port,
+ unsigned long *supported,
+ struct phylink_link_state *state);
};
+#define B53_INVALID_LANE 0xff
+
enum {
BCM5325_DEVICE_ID = 0x25,
BCM5365_DEVICE_ID = 0x65,
@@ -109,6 +125,7 @@ struct b53_device {
/* connect specific data */
u8 current_page;
struct device *dev;
+ u8 serdes_lane;
/* Master MDIO bus we got probed from */
struct mii_bus *bus;
diff --git a/drivers/net/dsa/b53/b53_serdes.c b/drivers/net/dsa/b53/b53_serdes.c
new file mode 100644
index 000000000000..b45c55e0b8b4
--- /dev/null
+++ b/drivers/net/dsa/b53/b53_serdes.c
@@ -0,0 +1,217 @@
+// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause
+/*
+ * Northstar Plus switch SerDes/SGMII PHY main logic
+ *
+ * Copyright (C) 2018 Florian Fainelli <f.fainelli@gmail.com>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/phy.h>
+#include <linux/phylink.h>
+#include <net/dsa.h>
+
+#include "b53_priv.h"
+#include "b53_serdes.h"
+#include "b53_regs.h"
+
+static void b53_serdes_write_blk(struct b53_device *dev, u8 offset, u16 block,
+ u16 value)
+{
+ b53_write16(dev, B53_SERDES_PAGE, B53_SERDES_BLKADDR, block);
+ b53_write16(dev, B53_SERDES_PAGE, offset, value);
+}
+
+static u16 b53_serdes_read_blk(struct b53_device *dev, u8 offset, u16 block)
+{
+ u16 value;
+
+ b53_write16(dev, B53_SERDES_PAGE, B53_SERDES_BLKADDR, block);
+ b53_read16(dev, B53_SERDES_PAGE, offset, &value);
+
+ return value;
+}
+
+static void b53_serdes_set_lane(struct b53_device *dev, u8 lane)
+{
+ if (dev->serdes_lane == lane)
+ return;
+
+ WARN_ON(lane > 1);
+
+ b53_serdes_write_blk(dev, B53_SERDES_LANE,
+ SERDES_XGXSBLK0_BLOCKADDRESS, lane);
+ dev->serdes_lane = lane;
+}
+
+static void b53_serdes_write(struct b53_device *dev, u8 lane,
+ u8 offset, u16 block, u16 value)
+{
+ b53_serdes_set_lane(dev, lane);
+ b53_serdes_write_blk(dev, offset, block, value);
+}
+
+static u16 b53_serdes_read(struct b53_device *dev, u8 lane,
+ u8 offset, u16 block)
+{
+ b53_serdes_set_lane(dev, lane);
+ return b53_serdes_read_blk(dev, offset, block);
+}
+
+void b53_serdes_config(struct b53_device *dev, int port, unsigned int mode,
+ const struct phylink_link_state *state)
+{
+ u8 lane = b53_serdes_map_lane(dev, port);
+ u16 reg;
+
+ if (lane == B53_INVALID_LANE)
+ return;
+
+ reg = b53_serdes_read(dev, lane, B53_SERDES_DIGITAL_CONTROL(1),
+ SERDES_DIGITAL_BLK);
+ if (state->interface == PHY_INTERFACE_MODE_1000BASEX)
+ reg |= FIBER_MODE_1000X;
+ else
+ reg &= ~FIBER_MODE_1000X;
+ b53_serdes_write(dev, lane, B53_SERDES_DIGITAL_CONTROL(1),
+ SERDES_DIGITAL_BLK, reg);
+}
+EXPORT_SYMBOL(b53_serdes_config);
+
+void b53_serdes_an_restart(struct b53_device *dev, int port)
+{
+ u8 lane = b53_serdes_map_lane(dev, port);
+ u16 reg;
+
+ if (lane == B53_INVALID_LANE)
+ return;
+
+ reg = b53_serdes_read(dev, lane, B53_SERDES_MII_REG(MII_BMCR),
+ SERDES_MII_BLK);
+ reg |= BMCR_ANRESTART;
+ b53_serdes_write(dev, lane, B53_SERDES_MII_REG(MII_BMCR),
+ SERDES_MII_BLK, reg);
+}
+EXPORT_SYMBOL(b53_serdes_an_restart);
+
+int b53_serdes_link_state(struct b53_device *dev, int port,
+ struct phylink_link_state *state)
+{
+ u8 lane = b53_serdes_map_lane(dev, port);
+ u16 dig, bmcr, bmsr;
+
+ if (lane == B53_INVALID_LANE)
+ return 1;
+
+ dig = b53_serdes_read(dev, lane, B53_SERDES_DIGITAL_STATUS,
+ SERDES_DIGITAL_BLK);
+ bmcr = b53_serdes_read(dev, lane, B53_SERDES_MII_REG(MII_BMCR),
+ SERDES_MII_BLK);
+ bmsr = b53_serdes_read(dev, lane, B53_SERDES_MII_REG(MII_BMSR),
+ SERDES_MII_BLK);
+
+ switch ((dig >> SPEED_STATUS_SHIFT) & SPEED_STATUS_MASK) {
+ case SPEED_STATUS_10:
+ state->speed = SPEED_10;
+ break;
+ case SPEED_STATUS_100:
+ state->speed = SPEED_100;
+ break;
+ case SPEED_STATUS_1000:
+ state->speed = SPEED_1000;
+ break;
+ default:
+ case SPEED_STATUS_2500:
+ state->speed = SPEED_2500;
+ break;
+ }
+
+ state->duplex = dig & DUPLEX_STATUS ? DUPLEX_FULL : DUPLEX_HALF;
+ state->an_enabled = !!(bmcr & BMCR_ANENABLE);
+ state->an_complete = !!(bmsr & BMSR_ANEGCOMPLETE);
+ state->link = !!(dig & LINK_STATUS);
+ if (dig & PAUSE_RESOLUTION_RX_SIDE)
+ state->pause |= MLO_PAUSE_RX;
+ if (dig & PAUSE_RESOLUTION_TX_SIDE)
+ state->pause |= MLO_PAUSE_TX;
+
+ return 0;
+}
+EXPORT_SYMBOL(b53_serdes_link_state);
+
+void b53_serdes_link_set(struct b53_device *dev, int port, unsigned int mode,
+ phy_interface_t interface, bool link_up)
+{
+ u8 lane = b53_serdes_map_lane(dev, port);
+ u16 reg;
+
+ if (lane == B53_INVALID_LANE)
+ return;
+
+ reg = b53_serdes_read(dev, lane, B53_SERDES_MII_REG(MII_BMCR),
+ SERDES_MII_BLK);
+ if (link_up)
+ reg &= ~BMCR_PDOWN;
+ else
+ reg |= BMCR_PDOWN;
+ b53_serdes_write(dev, lane, B53_SERDES_MII_REG(MII_BMCR),
+ SERDES_MII_BLK, reg);
+}
+EXPORT_SYMBOL(b53_serdes_link_set);
+
+void b53_serdes_phylink_validate(struct b53_device *dev, int port,
+ unsigned long *supported,
+ struct phylink_link_state *state)
+{
+ u8 lane = b53_serdes_map_lane(dev, port);
+
+ if (lane == B53_INVALID_LANE)
+ return;
+
+ switch (lane) {
+ case 0:
+ phylink_set(supported, 2500baseX_Full);
+ /* fallthrough */
+ case 1:
+ phylink_set(supported, 1000baseX_Full);
+ break;
+ default:
+ break;
+ }
+}
+EXPORT_SYMBOL(b53_serdes_phylink_validate);
+
+int b53_serdes_init(struct b53_device *dev, int port)
+{
+ u8 lane = b53_serdes_map_lane(dev, port);
+ u16 id0, msb, lsb;
+
+ if (lane == B53_INVALID_LANE)
+ return -EINVAL;
+
+ id0 = b53_serdes_read(dev, lane, B53_SERDES_ID0, SERDES_ID0);
+ msb = b53_serdes_read(dev, lane, B53_SERDES_MII_REG(MII_PHYSID1),
+ SERDES_MII_BLK);
+ lsb = b53_serdes_read(dev, lane, B53_SERDES_MII_REG(MII_PHYSID2),
+ SERDES_MII_BLK);
+ if (id0 == 0 || id0 == 0xffff) {
+ dev_err(dev->dev, "SerDes not initialized, check settings\n");
+ return -ENODEV;
+ }
+
+ dev_info(dev->dev,
+ "SerDes lane %d, model: %d, rev %c%d (OUI: 0x%08x)\n",
+ lane, id0 & SERDES_ID0_MODEL_MASK,
+ (id0 >> SERDES_ID0_REV_LETTER_SHIFT) + 0x41,
+ (id0 >> SERDES_ID0_REV_NUM_SHIFT) & SERDES_ID0_REV_NUM_MASK,
+ (u32)msb << 16 | lsb);
+
+ return 0;
+}
+EXPORT_SYMBOL(b53_serdes_init);
+
+MODULE_AUTHOR("Florian Fainelli <f.fainelli@gmail.com>");
+MODULE_DESCRIPTION("B53 Switch SerDes driver");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/dsa/b53/b53_serdes.h b/drivers/net/dsa/b53/b53_serdes.h
new file mode 100644
index 000000000000..e0674aa0167f
--- /dev/null
+++ b/drivers/net/dsa/b53/b53_serdes.h
@@ -0,0 +1,121 @@
+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause
+ *
+ * Northstar Plus switch SerDes/SGMII PHY definitions
+ *
+ * Copyright (C) 2018 Florian Fainelli <f.fainelli@gmail.com>
+ */
+
+#include <linux/phy.h>
+#include <linux/types.h>
+
+/* Non-standard page used to access SerDes PHY registers on NorthStar Plus */
+#define B53_SERDES_PAGE 0x16
+#define B53_SERDES_BLKADDR 0x3e
+#define B53_SERDES_LANE 0x3c
+
+#define B53_SERDES_ID0 0x20
+#define SERDES_ID0_MODEL_MASK 0x3f
+#define SERDES_ID0_REV_NUM_SHIFT 11
+#define SERDES_ID0_REV_NUM_MASK 0x7
+#define SERDES_ID0_REV_LETTER_SHIFT 14
+
+#define B53_SERDES_MII_REG(x) (0x20 + (x) * 2)
+#define B53_SERDES_DIGITAL_CONTROL(x) (0x18 + (x) * 2)
+#define B53_SERDES_DIGITAL_STATUS 0x28
+
+/* SERDES_DIGITAL_CONTROL1 */
+#define FIBER_MODE_1000X BIT(0)
+#define TBI_INTERFACE BIT(1)
+#define SIGNAL_DETECT_EN BIT(2)
+#define INVERT_SIGNAL_DETECT BIT(3)
+#define AUTODET_EN BIT(4)
+#define SGMII_MASTER_MODE BIT(5)
+#define DISABLE_DLL_PWRDOWN BIT(6)
+#define CRC_CHECKER_DIS BIT(7)
+#define COMMA_DET_EN BIT(8)
+#define ZERO_COMMA_DET_EN BIT(9)
+#define REMOTE_LOOPBACK BIT(10)
+#define SEL_RX_PKTS_FOR_CNTR BIT(11)
+#define MASTER_MDIO_PHY_SEL BIT(13)
+#define DISABLE_SIGNAL_DETECT_FLT BIT(14)
+
+/* SERDES_DIGITAL_CONTROL2 */
+#define EN_PARALLEL_DET BIT(0)
+#define DIS_FALSE_LINK BIT(1)
+#define FLT_FORCE_LINK BIT(2)
+#define EN_AUTONEG_ERR_TIMER BIT(3)
+#define DIS_REMOTE_FAULT_SENSING BIT(4)
+#define FORCE_XMIT_DATA BIT(5)
+#define AUTONEG_FAST_TIMERS BIT(6)
+#define DIS_CARRIER_EXTEND BIT(7)
+#define DIS_TRRR_GENERATION BIT(8)
+#define BYPASS_PCS_RX BIT(9)
+#define BYPASS_PCS_TX BIT(10)
+#define TEST_CNTR_EN BIT(11)
+#define TX_PACKET_SEQ_TEST BIT(12)
+#define TX_IDLE_JAM_SEQ_TEST BIT(13)
+#define CLR_BER_CNTR BIT(14)
+
+/* SERDES_DIGITAL_CONTROL3 */
+#define TX_FIFO_RST BIT(0)
+#define FIFO_ELAST_TX_RX_SHIFT 1
+#define FIFO_ELAST_TX_RX_5K 0
+#define FIFO_ELAST_TX_RX_10K 1
+#define FIFO_ELAST_TX_RX_13_5K 2
+#define FIFO_ELAST_TX_RX_18_5K 3
+#define BLOCK_TXEN_MODE BIT(9)
+#define JAM_FALSE_CARRIER_MODE BIT(10)
+#define EXT_PHY_CRS_MODE BIT(11)
+#define INVERT_EXT_PHY_CRS BIT(12)
+#define DISABLE_TX_CRS BIT(13)
+
+/* SERDES_DIGITAL_STATUS */
+#define SGMII_MODE BIT(0)
+#define LINK_STATUS BIT(1)
+#define DUPLEX_STATUS BIT(2)
+#define SPEED_STATUS_SHIFT 3
+#define SPEED_STATUS_10 0
+#define SPEED_STATUS_100 1
+#define SPEED_STATUS_1000 2
+#define SPEED_STATUS_2500 3
+#define SPEED_STATUS_MASK SPEED_STATUS_2500
+#define PAUSE_RESOLUTION_TX_SIDE BIT(5)
+#define PAUSE_RESOLUTION_RX_SIDE BIT(6)
+#define LINK_STATUS_CHANGE BIT(7)
+#define EARLY_END_EXT_DET BIT(8)
+#define CARRIER_EXT_ERR_DET BIT(9)
+#define RX_ERR_DET BIT(10)
+#define TX_ERR_DET BIT(11)
+#define CRC_ERR_DET BIT(12)
+#define FALSE_CARRIER_ERR_DET BIT(13)
+#define RXFIFO_ERR_DET BIT(14)
+#define TXFIFO_ERR_DET BIT(15)
+
+/* Block offsets */
+#define SERDES_DIGITAL_BLK 0x8300
+#define SERDES_ID0 0x8310
+#define SERDES_MII_BLK 0xffe0
+#define SERDES_XGXSBLK0_BLOCKADDRESS 0xffd0
+
+struct phylink_link_state;
+
+static inline u8 b53_serdes_map_lane(struct b53_device *dev, int port)
+{
+ if (!dev->ops->serdes_map_lane)
+ return B53_INVALID_LANE;
+
+ return dev->ops->serdes_map_lane(dev, port);
+}
+
+int b53_serdes_get_link(struct b53_device *dev, int port);
+int b53_serdes_link_state(struct b53_device *dev, int port,
+ struct phylink_link_state *state);
+void b53_serdes_config(struct b53_device *dev, int port, unsigned int mode,
+ const struct phylink_link_state *state);
+void b53_serdes_an_restart(struct b53_device *dev, int port);
+void b53_serdes_link_set(struct b53_device *dev, int port, unsigned int mode,
+ phy_interface_t interface, bool link_up);
+void b53_serdes_phylink_validate(struct b53_device *dev, int port,
+ unsigned long *supported,
+ struct phylink_link_state *state);
+int b53_serdes_init(struct b53_device *dev, int port);
diff --git a/drivers/net/dsa/b53/b53_srab.c b/drivers/net/dsa/b53/b53_srab.c
index 411b84f61903..383b8382d97c 100644
--- a/drivers/net/dsa/b53/b53_srab.c
+++ b/drivers/net/dsa/b53/b53_srab.c
@@ -23,8 +23,10 @@
#include <linux/platform_data/b53.h>
#include <linux/of.h>
#include <linux/workqueue.h>
+#include <net/dsa.h>
#include "b53_priv.h"
+#include "b53_serdes.h"
/* command and status register of the SRAB */
#define B53_SRAB_CMDSTAT 0x2c
@@ -62,16 +64,29 @@
#define B53_SRAB_P7_SLEEP_TIMER BIT(11)
#define B53_SRAB_IMP0_SLEEP_TIMER BIT(12)
+/* Port mux configuration registers */
+#define B53_MUX_CONFIG_P5 0x00
+#define MUX_CONFIG_SGMII 0
+#define MUX_CONFIG_MII_LITE 1
+#define MUX_CONFIG_RGMII 2
+#define MUX_CONFIG_GMII 3
+#define MUX_CONFIG_GPHY 4
+#define MUX_CONFIG_INTERNAL 5
+#define MUX_CONFIG_MASK 0x7
+#define B53_MUX_CONFIG_P4 0x04
+
struct b53_srab_port_priv {
struct work_struct irq_work;
int irq;
bool irq_enabled;
struct b53_device *dev;
unsigned int num;
+ phy_interface_t mode;
};
struct b53_srab_priv {
void __iomem *regs;
+ void __iomem *mux_config;
struct b53_srab_port_priv port_intrs[B53_N_PORTS];
};
@@ -357,6 +372,15 @@ static int b53_srab_write64(struct b53_device *dev, u8 page, u8 reg,
static void b53_srab_port_defer(struct work_struct *work)
{
+ struct b53_srab_port_priv *port;
+ struct b53_device *dev;
+ struct b53_srab_priv *priv;
+
+ port = container_of(work, struct b53_srab_port_priv, irq_work);
+ dev = port->dev;
+ priv = dev->priv;
+
+ b53_port_event(dev->ds, port->num);
}
static irqreturn_t b53_srab_port_isr(int irq, void *dev_id)
@@ -373,6 +397,24 @@ static irqreturn_t b53_srab_port_isr(int irq, void *dev_id)
return IRQ_HANDLED;
}
+static u8 b53_srab_serdes_map_lane(struct b53_device *dev, int port)
+{
+ struct b53_srab_priv *priv = dev->priv;
+ struct b53_srab_port_priv *p = &priv->port_intrs[port];
+
+ if (p->mode != PHY_INTERFACE_MODE_SGMII)
+ return B53_INVALID_LANE;
+
+ switch (port) {
+ case 5:
+ return 0;
+ case 4:
+ return 1;
+ default:
+ return B53_INVALID_LANE;
+ }
+}
+
static int b53_srab_irq_enable(struct b53_device *dev, int port)
{
struct b53_srab_priv *priv = dev->priv;
@@ -412,6 +454,17 @@ static const struct b53_io_ops b53_srab_ops = {
.write64 = b53_srab_write64,
.irq_enable = b53_srab_irq_enable,
.irq_disable = b53_srab_irq_disable,
+ .serdes_map_lane = b53_srab_serdes_map_lane,
+#if IS_ENABLED(CONFIG_B53_SERDES)
+ /* Functions below will only be called if serdes_map_lane returns a
+ * valid lane number
+ */
+ .serdes_link_state = b53_serdes_link_state,
+ .serdes_config = b53_serdes_config,
+ .serdes_an_restart = b53_serdes_an_restart,
+ .serdes_link_set = b53_serdes_link_set,
+ .serdes_phylink_validate = b53_serdes_phylink_validate,
+#endif
};
static const struct of_device_id b53_srab_of_match[] = {
@@ -483,6 +536,61 @@ static void b53_srab_prepare_irq(struct platform_device *pdev)
b53_srab_intr_set(priv, true);
}
+static void b53_srab_mux_init(struct platform_device *pdev)
+{
+ struct b53_device *dev = platform_get_drvdata(pdev);
+ struct b53_srab_priv *priv = dev->priv;
+ struct b53_srab_port_priv *p;
+ struct resource *r;
+ unsigned int port;
+ u32 reg, off = 0;
+ int ret;
+
+ if (dev->pdata && dev->pdata->chip_id != BCM58XX_DEVICE_ID)
+ return;
+
+ r = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ priv->mux_config = devm_ioremap_resource(&pdev->dev, r);
+ if (IS_ERR(priv->mux_config))
+ return;
+
+ /* Obtain the port mux configuration so we know which lanes
+ * actually map to SerDes lanes
+ */
+ for (port = 5; port > 3; port--, off += 4) {
+ p = &priv->port_intrs[port];
+
+ reg = readl(priv->mux_config + B53_MUX_CONFIG_P5 + off);
+ switch (reg & MUX_CONFIG_MASK) {
+ case MUX_CONFIG_SGMII:
+ p->mode = PHY_INTERFACE_MODE_SGMII;
+ ret = b53_serdes_init(dev, port);
+ if (ret)
+ continue;
+ break;
+ case MUX_CONFIG_MII_LITE:
+ p->mode = PHY_INTERFACE_MODE_MII;
+ break;
+ case MUX_CONFIG_GMII:
+ p->mode = PHY_INTERFACE_MODE_GMII;
+ break;
+ case MUX_CONFIG_RGMII:
+ p->mode = PHY_INTERFACE_MODE_RGMII;
+ break;
+ case MUX_CONFIG_INTERNAL:
+ p->mode = PHY_INTERFACE_MODE_INTERNAL;
+ break;
+ default:
+ p->mode = PHY_INTERFACE_MODE_NA;
+ break;
+ }
+
+ if (p->mode != PHY_INTERFACE_MODE_NA)
+ dev_info(&pdev->dev, "Port %d mode: %s\n",
+ port, phy_modes(p->mode));
+ }
+}
+
static int b53_srab_probe(struct platform_device *pdev)
{
struct b53_platform_data *pdata = pdev->dev.platform_data;
@@ -522,6 +630,7 @@ static int b53_srab_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, dev);
b53_srab_prepare_irq(pdev);
+ b53_srab_mux_init(pdev);
return b53_switch_register(dev);
}
--
2.17.1
^ permalink raw reply related
* [PATCH v2] tty: Change tty_{port|standard}_install() return type to void
From: Jaejoong Kim @ 2018-09-05 2:50 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby
Cc: Yisheng Xie, Nicolas Pitre, Ulf Hansson, Benjamin Herrenschmidt,
Heiko Carstens, Alexander Potapenko, Michael Ellerman,
open list:SPARC SERIAL DRIVERS, Thomas Meyer, Anton Ivanov,
open list:STAGING SUBSYSTEM, open list:S390, Arnd Bergmann,
Richard Weinberger, David Lin, open list:SERIAL DRIVERS,
Marcel Holtmann, Guenter Roeck, Adam Borowski, Kees Cook,
Mathias Nyman
Many drivers with tty use the tty_stand_install(). But, there is no
need to handle the error, since it always returns 0. So, change the
return type of tty_standard_install() and tty_port_install() to void
type and remove unnecessary exception handling where we use these
functions.
Signed-off-by: Jaejoong Kim <climbbb.kim@gmail.com>
---
Changes in v2:
- Update commit title
- Squash other patches into one
https://lkml.org/lkml/2018/9/4/70
arch/um/drivers/line.c | 7 +------
drivers/isdn/capi/capi.c | 10 ++++------
drivers/isdn/i4l/isdn_tty.c | 3 ++-
drivers/misc/pti.c | 28 +++++++++++++---------------
drivers/mmc/core/sdio_uart.c | 11 ++++-------
drivers/s390/char/con3215.c | 3 ++-
drivers/s390/char/tty3270.c | 7 +------
drivers/staging/fwserial/fwserial.c | 22 ++++++++--------------
drivers/staging/gdm724x/gdm_tty.c | 11 +++--------
drivers/staging/greybus/uart.c | 10 ++--------
drivers/tty/hvc/hvc_console.c | 7 ++-----
drivers/tty/hvc/hvcs.c | 10 ++--------
drivers/tty/mips_ejtag_fdc.c | 4 +++-
drivers/tty/n_gsm.c | 9 +--------
drivers/tty/nozomi.c | 8 +++-----
drivers/tty/serial/kgdb_nmi.c | 11 +----------
drivers/tty/synclink.c | 3 ++-
drivers/tty/synclinkmp.c | 3 ++-
drivers/tty/tty_io.c | 10 ++++++----
drivers/tty/tty_port.c | 4 ++--
drivers/tty/vcc.c | 5 +----
drivers/tty/vt/vt.c | 5 +----
drivers/usb/class/cdc-acm.c | 10 +---------
drivers/usb/host/xhci-dbgtty.c | 3 ++-
drivers/usb/serial/usb-serial.c | 6 +-----
include/linux/tty.h | 4 ++--
net/bluetooth/rfcomm/tty.c | 7 +------
27 files changed, 73 insertions(+), 148 deletions(-)
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index 8d80b27..47058cf 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -338,12 +338,7 @@ int line_open(struct tty_struct *tty, struct file *filp)
int line_install(struct tty_driver *driver, struct tty_struct *tty,
struct line *line)
{
- int ret;
-
- ret = tty_standard_install(driver, tty);
- if (ret)
- return ret;
-
+ tty_standard_install(driver, tty);
tty->driver_data = line;
return 0;
diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c
index ef5560b..08daf3a 100644
--- a/drivers/isdn/capi/capi.c
+++ b/drivers/isdn/capi/capi.c
@@ -999,13 +999,11 @@ static int
capinc_tty_install(struct tty_driver *driver, struct tty_struct *tty)
{
struct capiminor *mp = capiminor_get(tty->index);
- int ret = tty_standard_install(driver, tty);
- if (ret == 0)
- tty->driver_data = mp;
- else
- capiminor_put(mp);
- return ret;
+ tty_standard_install(driver, tty);
+ tty->driver_data = mp;
+
+ return 0;
}
static void capinc_tty_cleanup(struct tty_struct *tty)
diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c
index b730037..3d6b24e 100644
--- a/drivers/isdn/i4l/isdn_tty.c
+++ b/drivers/isdn/i4l/isdn_tty.c
@@ -1481,8 +1481,9 @@ static int isdn_tty_install(struct tty_driver *driver, struct tty_struct *tty)
return -ENODEV;
tty->driver_data = info;
+ tty_port_install(&info->port, driver, tty);
- return tty_port_install(&info->port, driver, tty);
+ return 0;
}
/*
diff --git a/drivers/misc/pti.c b/drivers/misc/pti.c
index 41f2a9f..5c885a1 100644
--- a/drivers/misc/pti.c
+++ b/drivers/misc/pti.c
@@ -462,26 +462,24 @@ static int pti_tty_install(struct tty_driver *driver, struct tty_struct *tty)
{
int idx = tty->index;
struct pti_tty *pti_tty_data;
- int ret = tty_standard_install(driver, tty);
- if (ret == 0) {
- pti_tty_data = kmalloc(sizeof(struct pti_tty), GFP_KERNEL);
- if (pti_tty_data == NULL)
- return -ENOMEM;
+ tty_standard_install(driver, tty);
+ pti_tty_data = kmalloc(sizeof(struct pti_tty), GFP_KERNEL);
+ if (pti_tty_data == NULL)
+ return -ENOMEM;
- if (idx == PTITTY_MINOR_START)
- pti_tty_data->mc = pti_request_masterchannel(0, NULL);
- else
- pti_tty_data->mc = pti_request_masterchannel(2, NULL);
+ if (idx == PTITTY_MINOR_START)
+ pti_tty_data->mc = pti_request_masterchannel(0, NULL);
+ else
+ pti_tty_data->mc = pti_request_masterchannel(2, NULL);
- if (pti_tty_data->mc == NULL) {
- kfree(pti_tty_data);
- return -ENXIO;
- }
- tty->driver_data = pti_tty_data;
+ if (pti_tty_data->mc == NULL) {
+ kfree(pti_tty_data);
+ return -ENXIO;
}
+ tty->driver_data = pti_tty_data;
- return ret;
+ return 0;
}
/**
diff --git a/drivers/mmc/core/sdio_uart.c b/drivers/mmc/core/sdio_uart.c
index 25e1130..b727186 100644
--- a/drivers/mmc/core/sdio_uart.c
+++ b/drivers/mmc/core/sdio_uart.c
@@ -731,14 +731,11 @@ static int sdio_uart_install(struct tty_driver *driver, struct tty_struct *tty)
{
int idx = tty->index;
struct sdio_uart_port *port = sdio_uart_port_get(idx);
- int ret = tty_standard_install(driver, tty);
- if (ret == 0)
- /* This is the ref sdio_uart_port get provided */
- tty->driver_data = port;
- else
- sdio_uart_port_put(port);
- return ret;
+ tty_standard_install(driver, tty);
+ tty->driver_data = port;
+
+ return 0;
}
/**
diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c
index 8c9d412..6a9f6d9 100644
--- a/drivers/s390/char/con3215.c
+++ b/drivers/s390/char/con3215.c
@@ -965,8 +965,9 @@ static int tty3215_install(struct tty_driver *driver, struct tty_struct *tty)
return -ENODEV;
tty->driver_data = raw;
+ tty_port_install(&raw->port, driver, tty);
- return tty_port_install(&raw->port, driver, tty);
+ return 0;
}
/*
diff --git a/drivers/s390/char/tty3270.c b/drivers/s390/char/tty3270.c
index 5b8af27..2915f95 100644
--- a/drivers/s390/char/tty3270.c
+++ b/drivers/s390/char/tty3270.c
@@ -1017,12 +1017,7 @@ static int tty3270_install(struct tty_driver *driver, struct tty_struct *tty)
raw3270_activate_view(&tp->view);
port_install:
- rc = tty_port_install(&tp->port, driver, tty);
- if (rc) {
- raw3270_put_view(&tp->view);
- return rc;
- }
-
+ tty_port_install(&tp->port, driver, tty);
tty->driver_data = tp;
return 0;
diff --git a/drivers/staging/fwserial/fwserial.c b/drivers/staging/fwserial/fwserial.c
index fa0dd42..5134019 100644
--- a/drivers/staging/fwserial/fwserial.c
+++ b/drivers/staging/fwserial/fwserial.c
@@ -1064,27 +1064,21 @@ static void fwtty_cleanup(struct tty_struct *tty)
static int fwtty_install(struct tty_driver *driver, struct tty_struct *tty)
{
struct fwtty_port *port = fwtty_port_get(tty->index);
- int err;
- err = tty_standard_install(driver, tty);
- if (!err)
- tty->driver_data = port;
- else
- fwtty_port_put(port);
- return err;
+ tty_standard_install(driver, tty);
+ tty->driver_data = port;
+
+ return 0;
}
static int fwloop_install(struct tty_driver *driver, struct tty_struct *tty)
{
struct fwtty_port *port = fwtty_port_get(table_idx(tty->index));
- int err;
- err = tty_standard_install(driver, tty);
- if (!err)
- tty->driver_data = port;
- else
- fwtty_port_put(port);
- return err;
+ tty_standard_install(driver, tty);
+ tty->driver_data = port;
+
+ return 0;
}
static int fwtty_write(struct tty_struct *tty, const unsigned char *buf, int c)
diff --git a/drivers/staging/gdm724x/gdm_tty.c b/drivers/staging/gdm724x/gdm_tty.c
index 6e81369..d6348df 100644
--- a/drivers/staging/gdm724x/gdm_tty.c
+++ b/drivers/staging/gdm724x/gdm_tty.c
@@ -62,6 +62,7 @@ static int gdm_tty_install(struct tty_driver *driver, struct tty_struct *tty)
return -ENODEV;
mutex_lock(&gdm_table_lock);
+
gdm = gdm_table[ret][tty->index];
if (!gdm) {
mutex_unlock(&gdm_table_lock);
@@ -69,15 +70,9 @@ static int gdm_tty_install(struct tty_driver *driver, struct tty_struct *tty)
}
tty_port_get(&gdm->port);
-
- ret = tty_standard_install(driver, tty);
- if (ret) {
- tty_port_put(&gdm->port);
- mutex_unlock(&gdm_table_lock);
- return ret;
- }
-
+ tty_standard_install(driver, tty);
tty->driver_data = gdm;
+
mutex_unlock(&gdm_table_lock);
return 0;
diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c
index 8a00632..182155b 100644
--- a/drivers/staging/greybus/uart.c
+++ b/drivers/staging/greybus/uart.c
@@ -393,21 +393,15 @@ static void release_minor(struct gb_tty *gb_tty)
static int gb_tty_install(struct tty_driver *driver, struct tty_struct *tty)
{
struct gb_tty *gb_tty;
- int retval;
gb_tty = get_gb_by_minor(tty->index);
if (!gb_tty)
return -ENODEV;
- retval = tty_standard_install(driver, tty);
- if (retval)
- goto error;
-
+ tty_standard_install(driver, tty);
tty->driver_data = gb_tty;
+
return 0;
-error:
- tty_port_put(&gb_tty->port);
- return retval;
}
static int gb_tty_open(struct tty_struct *tty, struct file *file)
diff --git a/drivers/tty/hvc/hvc_console.c b/drivers/tty/hvc/hvc_console.c
index 5414c4a..13fad62 100644
--- a/drivers/tty/hvc/hvc_console.c
+++ b/drivers/tty/hvc/hvc_console.c
@@ -329,7 +329,6 @@ static void hvc_unthrottle(struct tty_struct *tty)
static int hvc_install(struct tty_driver *driver, struct tty_struct *tty)
{
struct hvc_struct *hp;
- int rc;
/* Auto increments kref reference if found. */
hp = hvc_get_by_index(tty->index);
@@ -337,11 +336,9 @@ static int hvc_install(struct tty_driver *driver, struct tty_struct *tty)
return -ENODEV;
tty->driver_data = hp;
+ tty_port_install(&hp->port, driver, tty);
- rc = tty_port_install(&hp->port, driver, tty);
- if (rc)
- tty_port_put(&hp->port);
- return rc;
+ return 0;
}
/*
diff --git a/drivers/tty/hvc/hvcs.c b/drivers/tty/hvc/hvcs.c
index cb4db1b..4dfa70c 100644
--- a/drivers/tty/hvc/hvcs.c
+++ b/drivers/tty/hvc/hvcs.c
@@ -1140,16 +1140,10 @@ static int hvcs_install(struct tty_driver *driver, struct tty_struct *tty)
goto err_put;
}
- retval = tty_port_install(&hvcsd->port, driver, tty);
- if (retval)
- goto err_irq;
+ tty_port_install(&hvcsd->port, driver, tty);
return 0;
-err_irq:
- spin_lock_irqsave(&hvcsd->lock, flags);
- vio_disable_interrupts(hvcsd->vdev);
- spin_unlock_irqrestore(&hvcsd->lock, flags);
- free_irq(irq, hvcsd);
+
err_put:
tty_port_put(&hvcsd->port);
diff --git a/drivers/tty/mips_ejtag_fdc.c b/drivers/tty/mips_ejtag_fdc.c
index 4c1cd49..33e06b4 100644
--- a/drivers/tty/mips_ejtag_fdc.c
+++ b/drivers/tty/mips_ejtag_fdc.c
@@ -763,7 +763,9 @@ static int mips_ejtag_fdc_tty_install(struct tty_driver *driver,
struct mips_ejtag_fdc_tty *priv = driver->driver_state;
tty->driver_data = &priv->ports[tty->index];
- return tty_port_install(&priv->ports[tty->index].port, driver, tty);
+ tty_port_install(&priv->ports[tty->index].port, driver, tty);
+
+ return 0;
}
static int mips_ejtag_fdc_tty_open(struct tty_struct *tty, struct file *filp)
diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c
index 86b7e20..c52fa2d 100644
--- a/drivers/tty/n_gsm.c
+++ b/drivers/tty/n_gsm.c
@@ -2917,7 +2917,6 @@ static int gsmtty_install(struct tty_driver *driver, struct tty_struct *tty)
unsigned int line = tty->index;
unsigned int mux = line >> 6;
bool alloc = false;
- int ret;
line = line & 0x3F;
@@ -2949,14 +2948,8 @@ static int gsmtty_install(struct tty_driver *driver, struct tty_struct *tty)
mutex_unlock(&gsm->mutex);
return -ENOMEM;
}
- ret = tty_port_install(&dlci->port, driver, tty);
- if (ret) {
- if (alloc)
- dlci_put(dlci);
- mutex_unlock(&gsm->mutex);
- return ret;
- }
+ tty_port_install(&dlci->port, driver, tty);
dlci_get(dlci);
dlci_get(gsm->dlci[0]);
mux_get(gsm);
diff --git a/drivers/tty/nozomi.c b/drivers/tty/nozomi.c
index fed820e..479583d 100644
--- a/drivers/tty/nozomi.c
+++ b/drivers/tty/nozomi.c
@@ -1555,13 +1555,11 @@ static int ntty_install(struct tty_driver *driver, struct tty_struct *tty)
{
struct port *port = get_port_by_tty(tty);
struct nozomi *dc = get_dc_by_tty(tty);
- int ret;
if (!port || !dc || dc->state != NOZOMI_STATE_READY)
return -ENODEV;
- ret = tty_standard_install(driver, tty);
- if (ret == 0)
- tty->driver_data = port;
- return ret;
+ tty_standard_install(driver, tty);
+ tty->driver_data = port;
+ return 0;
}
static void ntty_cleanup(struct tty_struct *tty)
diff --git a/drivers/tty/serial/kgdb_nmi.c b/drivers/tty/serial/kgdb_nmi.c
index 4029272..ed8f806 100644
--- a/drivers/tty/serial/kgdb_nmi.c
+++ b/drivers/tty/serial/kgdb_nmi.c
@@ -234,7 +234,6 @@ static const struct tty_port_operations kgdb_nmi_tty_port_ops = {
static int kgdb_nmi_tty_install(struct tty_driver *drv, struct tty_struct *tty)
{
struct kgdb_nmi_tty_priv *priv;
- int ret;
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv)
@@ -245,17 +244,9 @@ static int kgdb_nmi_tty_install(struct tty_driver *drv, struct tty_struct *tty)
tty_port_init(&priv->port);
priv->port.ops = &kgdb_nmi_tty_port_ops;
tty->driver_data = priv;
+ tty_port_install(&priv->port, drv, tty);
- ret = tty_port_install(&priv->port, drv, tty);
- if (ret) {
- pr_err("%s: can't install tty port: %d\n", __func__, ret);
- goto err;
- }
return 0;
-err:
- tty_port_destroy(&priv->port);
- kfree(priv);
- return ret;
}
static void kgdb_nmi_tty_cleanup(struct tty_struct *tty)
diff --git a/drivers/tty/synclink.c b/drivers/tty/synclink.c
index fbdf4d0..6e7e4d6 100644
--- a/drivers/tty/synclink.c
+++ b/drivers/tty/synclink.c
@@ -3355,8 +3355,9 @@ static int mgsl_install(struct tty_driver *driver, struct tty_struct *tty)
if (mgsl_paranoia_check(info, tty->name, "mgsl_open"))
return -ENODEV;
tty->driver_data = info;
+ tty_port_install(&info->port, driver, tty);
- return tty_port_install(&info->port, driver, tty);
+ return 0;
}
/* mgsl_open()
diff --git a/drivers/tty/synclinkmp.c b/drivers/tty/synclinkmp.c
index 1e4d5b9..2d99a5b 100644
--- a/drivers/tty/synclinkmp.c
+++ b/drivers/tty/synclinkmp.c
@@ -734,8 +734,9 @@ static int install(struct tty_driver *driver, struct tty_struct *tty)
}
tty->driver_data = info;
+ tty_port_install(&info->port, driver, tty);
- return tty_port_install(&info->port, driver, tty);
+ return 0;
}
/* Called when a port is opened. Init and enable port.
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index 32bc3e3..b01cec8 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -1196,13 +1196,12 @@ void tty_init_termios(struct tty_struct *tty)
}
EXPORT_SYMBOL_GPL(tty_init_termios);
-int tty_standard_install(struct tty_driver *driver, struct tty_struct *tty)
+void tty_standard_install(struct tty_driver *driver, struct tty_struct *tty)
{
tty_init_termios(tty);
tty_driver_kref_get(driver);
tty->count++;
driver->ttys[tty->index] = tty;
- return 0;
}
EXPORT_SYMBOL_GPL(tty_standard_install);
@@ -1221,8 +1220,11 @@ EXPORT_SYMBOL_GPL(tty_standard_install);
static int tty_driver_install_tty(struct tty_driver *driver,
struct tty_struct *tty)
{
- return driver->ops->install ? driver->ops->install(driver, tty) :
- tty_standard_install(driver, tty);
+ if (driver->ops->install)
+ return driver->ops->install(driver, tty);
+
+ tty_standard_install(driver, tty);
+ return 0;
}
/**
diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c
index 25d7368..fd8d40d 100644
--- a/drivers/tty/tty_port.c
+++ b/drivers/tty/tty_port.c
@@ -656,11 +656,11 @@ EXPORT_SYMBOL(tty_port_close);
* to a concrete tty specified by @tty. Use this or tty_port_register_device
* (or both). Call tty_port_link_device as a last resort.
*/
-int tty_port_install(struct tty_port *port, struct tty_driver *driver,
+void tty_port_install(struct tty_port *port, struct tty_driver *driver,
struct tty_struct *tty)
{
tty->port = port;
- return tty_standard_install(driver, tty);
+ tty_standard_install(driver, tty);
}
EXPORT_SYMBOL_GPL(tty_port_install);
diff --git a/drivers/tty/vcc.c b/drivers/tty/vcc.c
index 58b454c..ce32631 100644
--- a/drivers/tty/vcc.c
+++ b/drivers/tty/vcc.c
@@ -987,7 +987,6 @@ static int vcc_install(struct tty_driver *driver, struct tty_struct *tty)
{
struct vcc_port *port_vcc;
struct tty_port *port_tty;
- int ret;
if (unlikely(!tty)) {
pr_err("VCC: install: Invalid TTY handle\n");
@@ -997,9 +996,7 @@ static int vcc_install(struct tty_driver *driver, struct tty_struct *tty)
if (tty->index >= VCC_MAX_PORTS)
return -EINVAL;
- ret = tty_standard_install(driver, tty);
- if (ret)
- return ret;
+ tty_standard_install(driver, tty);
port_tty = kzalloc(sizeof(struct tty_port), GFP_KERNEL);
if (!port_tty)
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 5f1183b..cc72254 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -3222,10 +3222,7 @@ static int con_install(struct tty_driver *driver, struct tty_struct *tty)
goto unlock;
}
- ret = tty_port_install(&vc->port, driver, tty);
- if (ret)
- goto unlock;
-
+ tty_port_install(&vc->port, driver, tty);
tty->driver_data = vc;
vc->port.tty = tty;
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 27346d6..de6a27e 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -572,23 +572,15 @@ static void acm_softint(struct work_struct *work)
static int acm_tty_install(struct tty_driver *driver, struct tty_struct *tty)
{
struct acm *acm;
- int retval;
acm = acm_get_by_minor(tty->index);
if (!acm)
return -ENODEV;
- retval = tty_standard_install(driver, tty);
- if (retval)
- goto error_init_termios;
-
+ tty_standard_install(driver, tty);
tty->driver_data = acm;
return 0;
-
-error_init_termios:
- tty_port_put(&acm->port);
- return retval;
}
static int acm_tty_open(struct tty_struct *tty, struct file *filp)
diff --git a/drivers/usb/host/xhci-dbgtty.c b/drivers/usb/host/xhci-dbgtty.c
index aff79ff..18d661c 100644
--- a/drivers/usb/host/xhci-dbgtty.c
+++ b/drivers/usb/host/xhci-dbgtty.c
@@ -174,8 +174,9 @@ static int dbc_tty_install(struct tty_driver *driver, struct tty_struct *tty)
struct dbc_port *port = driver->driver_state;
tty->driver_data = port;
+ tty_port_install(&port->port, driver, tty);
- return tty_port_install(&port->port, driver, tty);
+ return 0;
}
static int dbc_tty_open(struct tty_struct *tty, struct file *file)
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index f7aaa7f..5cfc2ca 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -192,9 +192,7 @@ static int serial_install(struct tty_driver *driver, struct tty_struct *tty)
if (retval)
goto error_get_interface;
- retval = tty_standard_install(driver, tty);
- if (retval)
- goto error_init_termios;
+ tty_standard_install(driver, tty);
mutex_unlock(&serial->disc_mutex);
@@ -206,8 +204,6 @@ static int serial_install(struct tty_driver *driver, struct tty_struct *tty)
return retval;
- error_init_termios:
- usb_autopm_put_interface(serial->interface);
error_get_interface:
module_put(serial->type->driver.owner);
error_module_get:
diff --git a/include/linux/tty.h b/include/linux/tty.h
index c56e397..63cdac1 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -556,7 +556,7 @@ extern struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx);
extern void tty_release_struct(struct tty_struct *tty, int idx);
extern int tty_release(struct inode *inode, struct file *filp);
extern void tty_init_termios(struct tty_struct *tty);
-extern int tty_standard_install(struct tty_driver *driver,
+extern void tty_standard_install(struct tty_driver *driver,
struct tty_struct *tty);
extern struct mutex tty_mutex;
@@ -688,7 +688,7 @@ extern int tty_port_close_start(struct tty_port *port,
extern void tty_port_close_end(struct tty_port *port, struct tty_struct *tty);
extern void tty_port_close(struct tty_port *port,
struct tty_struct *tty, struct file *filp);
-extern int tty_port_install(struct tty_port *port, struct tty_driver *driver,
+extern void tty_port_install(struct tty_port *port, struct tty_driver *driver,
struct tty_struct *tty);
extern int tty_port_open(struct tty_port *port,
struct tty_struct *tty, struct file *filp);
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
index 5e44d84..b654420 100644
--- a/net/bluetooth/rfcomm/tty.c
+++ b/net/bluetooth/rfcomm/tty.c
@@ -710,7 +710,6 @@ static int rfcomm_tty_install(struct tty_driver *driver, struct tty_struct *tty)
{
struct rfcomm_dev *dev;
struct rfcomm_dlc *dlc;
- int err;
dev = rfcomm_dev_get(tty->index);
if (!dev)
@@ -725,11 +724,7 @@ static int rfcomm_tty_install(struct tty_driver *driver, struct tty_struct *tty)
set_bit(RFCOMM_TTY_ATTACHED, &dev->flags);
/* install the tty_port */
- err = tty_port_install(&dev->port, driver, tty);
- if (err) {
- rfcomm_tty_cleanup(tty);
- return err;
- }
+ tty_port_install(&dev->port, driver, tty);
/* take over the tty_port reference if the port was created with the
* flag RFCOMM_RELEASE_ONHUP. This will force the release of the port
--
2.7.4
^ permalink raw reply related
* ATTENTION!Board of Directors
From: Aminata Idrissa Coulibaly @ 2018-09-04 22:36 UTC (permalink / raw)
From: Mrs. Aminata Idrissa Coulibaly
My Telephone Number:+229 68 58 13 53
Residence Address is:Bp. Rue` de`207 Avenue 102 Cotonou
Republic De` Benin.
Partnership investment
My introduction to you, I am Mrs. Aminata Idrissa Coulibaly, a
financial consultant of Mrs.Simone Gbagbo the wife of the former
president of Cote`D Ivoire Laurent Gbagbo. Actually Mrs. Gbagbo has the
sum of USD$6.500, 000.00($6.5 Million dollars) under my care, to invest
in real estate. The present government of Cote d' Ivoire (Ivory Coast)
has impounded all assets and cash belonging to family of ex President
Laurent Gbagbo and these funds is still safe because it was already
moved to a Separate and secured financial institution. During my last
visit to her in prison, she advised that I make an arrangement to move
the money out immediately and invest the money abroad which was why I
contacted you.
I choose to contact a complete stranger for this transaction because so
many people have betrayed them since they are no longer in power. I
need someone who can be tTrusted because this is the only thing left
for this family and for the future of their family, since all have
lost. I need your urgent response so that I can give you more details
to enable us move forward. We shall give you 25% of the total sum for
this sincere assistant’s assure You that you will never regret your
efforts, this transaction is programmed to be completed within 10 days,
Please do forward your information as listed below if you are willing
to handle this transaction.
Your full name: Your contact address: Occupation; Your phone number:
Date and Place of Birth: Country of Origin:
I wait to read from you on, and keep this information top secret.
Best Regards,
Mrs. Aminata Idrissa Coulibaly
^ permalink raw reply
* [PATCH net-next v2] openvswitch: Derive IP protocol number for IPv6 later frags
From: Yi-Hung Wei @ 2018-09-04 22:33 UTC (permalink / raw)
To: netdev, pshelar, u9012063; +Cc: Yi-Hung Wei
Currently, OVS only parses the IP protocol number for the first
IPv6 fragment, but sets the IP protocol number for the later fragments
to be NEXTHDF_FRAGMENT. This patch tries to derive the IP protocol
number for the IPV6 later frags so that we can match that.
Signed-off-by: Yi-Hung Wei <yihung.wei@gmail.com>
---
net/openvswitch/flow.c | 22 +++++++++-------------
1 file changed, 9 insertions(+), 13 deletions(-)
diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
index 56b8e7167790..35966da84769 100644
--- a/net/openvswitch/flow.c
+++ b/net/openvswitch/flow.c
@@ -254,21 +254,18 @@ static bool icmphdr_ok(struct sk_buff *skb)
static int parse_ipv6hdr(struct sk_buff *skb, struct sw_flow_key *key)
{
+ unsigned short frag_off;
+ unsigned int payload_ofs = 0;
unsigned int nh_ofs = skb_network_offset(skb);
unsigned int nh_len;
- int payload_ofs;
struct ipv6hdr *nh;
- uint8_t nexthdr;
- __be16 frag_off;
- int err;
+ int err, nexthdr, flags = 0;
err = check_header(skb, nh_ofs + sizeof(*nh));
if (unlikely(err))
return err;
nh = ipv6_hdr(skb);
- nexthdr = nh->nexthdr;
- payload_ofs = (u8 *)(nh + 1) - skb->data;
key->ip.proto = NEXTHDR_NONE;
key->ip.tos = ipv6_get_dsfield(nh);
@@ -277,10 +274,9 @@ static int parse_ipv6hdr(struct sk_buff *skb, struct sw_flow_key *key)
key->ipv6.addr.src = nh->saddr;
key->ipv6.addr.dst = nh->daddr;
- payload_ofs = ipv6_skip_exthdr(skb, payload_ofs, &nexthdr, &frag_off);
-
- if (frag_off) {
- if (frag_off & htons(~0x7))
+ nexthdr = ipv6_find_hdr(skb, &payload_ofs, -1, &frag_off, &flags);
+ if (flags & IP6_FH_F_FRAG) {
+ if (frag_off)
key->ip.frag = OVS_FRAG_TYPE_LATER;
else
key->ip.frag = OVS_FRAG_TYPE_FIRST;
@@ -288,11 +284,11 @@ static int parse_ipv6hdr(struct sk_buff *skb, struct sw_flow_key *key)
key->ip.frag = OVS_FRAG_TYPE_NONE;
}
- /* Delayed handling of error in ipv6_skip_exthdr() as it
- * always sets frag_off to a valid value which may be
+ /* Delayed handling of error in ipv6_find_hdr() as it
+ * always sets flags and frag_off to a valid value which may be
* used to set key->ip.frag above.
*/
- if (unlikely(payload_ofs < 0))
+ if (unlikely(nexthdr < 0))
return -EPROTO;
nh_len = payload_ofs - nh_ofs;
--
2.7.4
^ permalink raw reply related
* Re: [PATCH net-next] net: sched: change tcf_del_walker() to use concurrent-safe delete
From: Cong Wang @ 2018-09-04 22:41 UTC (permalink / raw)
To: Vlad Buslov
Cc: Linux Kernel Network Developers, Jamal Hadi Salim, Jiri Pirko,
David Miller
In-Reply-To: <vbfsh2q2ueh.fsf@reg-r-vrt-018-180.mtr.labs.mlnx>
On Mon, Sep 3, 2018 at 1:33 PM Vlad Buslov <vladbu@mellanox.com> wrote:
>
>
> On Mon 03 Sep 2018 at 18:50, Cong Wang <xiyou.wangcong@gmail.com> wrote:
> > On Mon, Sep 3, 2018 at 12:06 AM Vlad Buslov <vladbu@mellanox.com> wrote:
> >>
> >> Action API was changed to work with actions and action_idr in concurrency
> >> safe manner, however tcf_del_walker() still uses actions without taking
> >> reference to them first and deletes them directly, disregarding possible
> >> concurrent delete.
> >>
> >> Change tcf_del_walker() to use tcf_idr_delete_index() that doesn't require
> >> caller to hold reference to action and accepts action id as argument,
> >> instead of direct action pointer.
> >
> > Hmm, why doesn't tcf_del_walker() just take idrinfo->lock? At least
> > tcf_dump_walker() already does.
>
> Because tcf_del_walker() calls __tcf_idr_release(), which take
> idrinfo->lock itself (deadlock). It also calls sleeping functions like
Deadlock can be easily resolved by moving the lock out.
> tcf_action_goto_chain_fini(), so just implementing function that
> releases action without taking idrinfo->lock is not enough.
Sleeping can be resolved either by making it atomic or
deferring it to a work queue.
None of your arguments here is a blocker to locking
idrinfo->lock. You really should focus on if it is really
necessary to lock idrinfo->lock in tcf_del_walker(), rather
than these details.
For me, if you need idrinfo->lock for dump walker, you must
need it for delete walker too, because deletion is a writer
which should require stronger protection than the dumper,
which merely a reader.
^ permalink raw reply
* Re: [Patch net v3] tipc: call start and done ops directly in __tipc_nl_compat_dumpit()
From: Ying Xue @ 2018-09-05 3:19 UTC (permalink / raw)
To: Cong Wang, netdev; +Cc: tipc-discussion
In-Reply-To: <20180904215455.3985-1-xiyou.wangcong@gmail.com>
On 09/05/2018 05:54 AM, Cong Wang wrote:
> __tipc_nl_compat_dumpit() uses a netlink_callback on stack,
> so the only way to align it with other ->dumpit() call path
> is calling tipc_dump_start() and tipc_dump_done() directly
> inside it. Otherwise ->dumpit() would always get NULL from
> cb->args[].
>
> But tipc_dump_start() uses sock_net(cb->skb->sk) to retrieve
> net pointer, the cb->skb here doesn't set skb->sk, the net pointer
> is saved in msg->net instead, so introduce a helper function
> __tipc_dump_start() to pass in msg->net.
>
> Ying pointed out cb->args[0...3] are already used by other
> callbacks on this call path, so we can't use cb->args[0] any
> more, use cb->args[4] instead.
It's a common mechanism to save rhashtable iterator pointer in cb->args
after tipc_dump_start() and tipc_dump_done() are introduced. Someday
probably we will involve new dumpit function. In order to lower the risk
that rhashtable iterator pointer saved is overwritten, it's better to
use the last slot, ie, cb->args[5].
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
^ permalink raw reply
* Re: [PATCH net-next 2/5] net: dsa: b53: Make SRAB driver manage port interrupts
From: Andrew Lunn @ 2018-09-04 22:59 UTC (permalink / raw)
To: Florian Fainelli; +Cc: netdev, vivien.didelot, davem
In-Reply-To: <20180904221120.13018-3-f.fainelli@gmail.com>
> +static irqreturn_t b53_srab_port_isr(int irq, void *dev_id)
> +{
> + struct b53_srab_port_priv *port = dev_id;
> + struct b53_device *dev = port->dev;
> + struct b53_srab_priv *priv = dev->priv;
> +
> + /* Acknowledge the interrupt */
> + writel(BIT(port->num), priv->regs + B53_SRAB_INTR);
> +
> + schedule_work(&port->irq_work);
> +
> + return IRQ_HANDLED;
> +}
> +
> +static int b53_srab_irq_enable(struct b53_device *dev, int port)
> +{
> + struct b53_srab_priv *priv = dev->priv;
> + struct b53_srab_port_priv *p = &priv->port_intrs[port];
> + int ret;
> +
> + ret = request_irq(p->irq, b53_srab_port_isr, 0,
> + dev_name(dev->dev), p);
Hi Florian
Could you use a threaded interrupt? Save you from having to implement
your own work queue. I think you can have a function called in both
interrupt context in order to acknowledged the interrupt, and thread
context to do the remaining work.
Andrew
^ permalink raw reply
* Re: [RFC/PATCH] net: nixge: Add PHYLINK support
From: Moritz Fischer @ 2018-09-05 3:27 UTC (permalink / raw)
To: Andrew Lunn
Cc: netdev, David S. Miller, Florian Fainelli, Alex Williams,
Linux Kernel Mailing List
In-Reply-To: <20180905010100.GN29121@lunn.ch>
Hi Andrew,
On Tue, Sep 4, 2018 at 6:01 PM, Andrew Lunn <andrew@lunn.ch> wrote:
>> 3) I'm again not sure about the 'select PHYLINK', wouldn't
>> wanna break the build again...
>
> Hi Moritz
>
> I think it is safe. PHYLINK has no stated dependencies on OF. But i
> suspect it currently is pretty useless without OF.
Ok, great. Thanks!
>> @@ -1286,7 +1329,13 @@ static int nixge_probe(struct platform_device *pdev)
>> priv->coalesce_count_rx = XAXIDMA_DFT_RX_THRESHOLD;
>> priv->coalesce_count_tx = XAXIDMA_DFT_TX_THRESHOLD;
>>
>> - err = nixge_mdio_setup(priv, pdev->dev.of_node);
>> + mn = of_get_child_by_name(pdev->dev.of_node, "mdio");
>> + if (!mn) {
>> + dev_warn(&pdev->dev, "No \"mdio\" subnode found, defaulting to legacy\n");
>> + mn = pdev->dev.of_node;
>> + }
>> +
>> + err = nixge_mdio_setup(priv, mn);
>
> I would suggest making this a patch of its own.
Yeah, will do.
> Also, do you need the legacy behaviour? If there are no boards out in
> the wild which this will break, just make the change.
Well all users basically use devicetree overlays that we distribute
with the FPGA images
as part of a filesystem update. So I suppose it wouldn't break anyone,
yet... It would certainly
make the code easier to read.
> Please also update the device tree binding documentation.
Yeah will do.
Thanks for the feedback,
Moritz
^ permalink raw reply
* Re: [PATCH net-next 5/5] net: dsa: b53: Add SerDes support
From: Andrew Lunn @ 2018-09-04 23:15 UTC (permalink / raw)
To: Florian Fainelli; +Cc: netdev, vivien.didelot, davem
In-Reply-To: <20180904221120.13018-6-f.fainelli@gmail.com>
On Tue, Sep 04, 2018 at 03:11:20PM -0700, Florian Fainelli wrote:
> Add support for the Northstar Plus SerDes which is accessed through a
> special page of the switch. Since this is something that most people
> probably will not want to use, make it a configurable option.
>
> The SerDes supports both SGMII and 1000baseX modes, and is internally
> looking like a seemingly standard MII PHY, except for the few bits that
> got repurposed.
Hi Florian
The SERDES in the 6352 also look very similar to a standard MII PHYs.
Maybe at some point, we should look at the SERDES drivers we have
embedded in different MAC drivers, and see if we can pull them out,
maybe put them in drivers/net/phy. Any SERDES driver being used in
combination with phylink probably has the same API.
Andrew
^ permalink raw reply
* Re: [PATCH net-next 5/5] net: dsa: b53: Add SerDes support
From: Andrew Lunn @ 2018-09-04 23:32 UTC (permalink / raw)
To: Florian Fainelli; +Cc: netdev, vivien.didelot, davem
In-Reply-To: <20180904221120.13018-6-f.fainelli@gmail.com>
> +void b53_serdes_phylink_validate(struct b53_device *dev, int port,
> + unsigned long *supported,
> + struct phylink_link_state *state)
> +{
> + u8 lane = b53_serdes_map_lane(dev, port);
> +
> + if (lane == B53_INVALID_LANE)
> + return;
> +
> + switch (lane) {
> + case 0:
> + phylink_set(supported, 2500baseX_Full);
Hi Florian
Could you also use it for 2500BaseT_Full with an appropriate copper
PHY?
Andrew
^ permalink raw reply
* Re: [PATCH net-next 2/5] net: dsa: b53: Make SRAB driver manage port interrupts
From: Florian Fainelli @ 2018-09-04 23:46 UTC (permalink / raw)
To: Andrew Lunn; +Cc: netdev, vivien.didelot, davem
In-Reply-To: <20180904225955.GH29121@lunn.ch>
On 09/04/2018 03:59 PM, Andrew Lunn wrote:
>> +static irqreturn_t b53_srab_port_isr(int irq, void *dev_id)
>> +{
>> + struct b53_srab_port_priv *port = dev_id;
>> + struct b53_device *dev = port->dev;
>> + struct b53_srab_priv *priv = dev->priv;
>> +
>> + /* Acknowledge the interrupt */
>> + writel(BIT(port->num), priv->regs + B53_SRAB_INTR);
>> +
>> + schedule_work(&port->irq_work);
>> +
>> + return IRQ_HANDLED;
>> +}
>> +
>> +static int b53_srab_irq_enable(struct b53_device *dev, int port)
>> +{
>> + struct b53_srab_priv *priv = dev->priv;
>> + struct b53_srab_port_priv *p = &priv->port_intrs[port];
>> + int ret;
>> +
>> + ret = request_irq(p->irq, b53_srab_port_isr, 0,
>> + dev_name(dev->dev), p);
>
> Hi Florian
>
> Could you use a threaded interrupt? Save you from having to implement
> your own work queue. I think you can have a function called in both
> interrupt context in order to acknowledged the interrupt, and thread
> context to do the remaining work.
Indeed, this works nicely actually, thanks for the suggestion.
--
Florian
^ permalink raw reply
* Re: [PATCH net-next 5/5] net: dsa: b53: Add SerDes support
From: Florian Fainelli @ 2018-09-04 23:55 UTC (permalink / raw)
To: Andrew Lunn; +Cc: netdev, vivien.didelot, davem
In-Reply-To: <20180904233222.GJ29121@lunn.ch>
On 09/04/2018 04:32 PM, Andrew Lunn wrote:
>
>
>> +void b53_serdes_phylink_validate(struct b53_device *dev, int port,
>> + unsigned long *supported,
>> + struct phylink_link_state *state)
>> +{
>> + u8 lane = b53_serdes_map_lane(dev, port);
>> +
>> + if (lane == B53_INVALID_LANE)
>> + return;
>> +
>> + switch (lane) {
>> + case 0:
>> + phylink_set(supported, 2500baseX_Full);
>
> Hi Florian
>
> Could you also use it for 2500BaseT_Full with an appropriate copper
> PHY?
My reading of the datasheet (which only mentions 2.5G with no further
mention) make me think that is not possible to do copper at 2.5G and
only 2500baseX since it only talks about fiber and not copper.
Would you recommend a specific SFP that allows that? Like this one:
https://www.flexoptix.net/en/sfp-t-transceiver-2h-gigabit-cat-5e-rj-45-100m-100m-1000m-2500-base-t.html?co8829=85744
--
Florian
^ permalink raw reply
* Re: [PATCH net-next 5/5] net: dsa: b53: Add SerDes support
From: Florian Fainelli @ 2018-09-05 0:02 UTC (permalink / raw)
To: Andrew Lunn; +Cc: netdev, vivien.didelot, davem
In-Reply-To: <20180904231543.GI29121@lunn.ch>
On 09/04/2018 04:15 PM, Andrew Lunn wrote:
> On Tue, Sep 04, 2018 at 03:11:20PM -0700, Florian Fainelli wrote:
>> Add support for the Northstar Plus SerDes which is accessed through a
>> special page of the switch. Since this is something that most people
>> probably will not want to use, make it a configurable option.
>>
>> The SerDes supports both SGMII and 1000baseX modes, and is internally
>> looking like a seemingly standard MII PHY, except for the few bits that
>> got repurposed.
>
> Hi Florian
>
> The SERDES in the 6352 also look very similar to a standard MII PHYs.
>
> Maybe at some point, we should look at the SERDES drivers we have
> embedded in different MAC drivers, and see if we can pull them out,
> maybe put them in drivers/net/phy. Any SERDES driver being used in
> combination with phylink probably has the same API.
Yes, that would sound like a good move forward. The SerDes on the
Northstar Plus does have a bunch of MII standard registers, but not a
whole lot (BMSR, BMCR, MII_PHYSID1/2, AUTONEGADV, AUTONEGLPABIL) and
then, it's all custom.
It would be good to have possibly a third vendor (Mediatek? Qualcomm?)
and see how they did it so we can define an appropriate API.
--
Florian
^ permalink raw reply
* Re: [PATCH net-next 5/5] net: dsa: b53: Add SerDes support
From: Andrew Lunn @ 2018-09-05 0:06 UTC (permalink / raw)
To: Florian Fainelli; +Cc: netdev, vivien.didelot, davem
In-Reply-To: <57632a74-e3dd-893f-2573-d0450d6b290a@gmail.com>
On Tue, Sep 04, 2018 at 04:55:26PM -0700, Florian Fainelli wrote:
> On 09/04/2018 04:32 PM, Andrew Lunn wrote:
> >
> >
> >> +void b53_serdes_phylink_validate(struct b53_device *dev, int port,
> >> + unsigned long *supported,
> >> + struct phylink_link_state *state)
> >> +{
> >> + u8 lane = b53_serdes_map_lane(dev, port);
> >> +
> >> + if (lane == B53_INVALID_LANE)
> >> + return;
> >> +
> >> + switch (lane) {
> >> + case 0:
> >> + phylink_set(supported, 2500baseX_Full);
> >
> > Hi Florian
> >
> > Could you also use it for 2500BaseT_Full with an appropriate copper
> > PHY?
>
> My reading of the datasheet (which only mentions 2.5G with no further
> mention) make me think that is not possible to do copper at 2.5G and
> only 2500baseX since it only talks about fiber and not copper.
>
> Would you recommend a specific SFP that allows that? Like this one:
>
> https://www.flexoptix.net/en/sfp-t-transceiver-2h-gigabit-cat-5e-rj-45-100m-100m-1000m-2500-base-t.html?co8829=85744
I was actually thinking of a 'plain old' copper PHY with a SERDES
interface which can do 25000Base-T. The Marvell 88x3310 or the
Aquantia 10G PHY, for example.
Russell might be able to make a recommendation. I don't have any
Copper SFP modules.
Andrew
^ permalink raw reply
* Re: Why not use all the syn queues? in the function "tcp_conn_request", I have some questions.
From: Ttttabcd @ 2018-09-05 0:20 UTC (permalink / raw)
To: Neal Cardwell; +Cc: Netdev
In-Reply-To: <CADVnQy=neWRer8AZBimf2c+iFzn=1iRoBwcsAYgjj=SJXQj7jg@mail.gmail.com>
Sent with ProtonMail Secure Email.
‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐
On 4 September 2018 9:06 PM, Neal Cardwell <ncardwell@google.com> wrote:
> On Tue, Sep 4, 2018 at 1:48 AM Ttttabcd ttttabcd@protonmail.com wrote:
>
> > Hello everyone,recently I am looking at the source code for handling TCP three-way handshake(Linux Kernel version 4.18.5).
> > I found some strange places in the source code for handling syn messages.
> > in the function "tcp_conn_request"
> > This code will be executed when we don't enable the syn cookies.
> >
> > if (!net->ipv4.sysctl_tcp_syncookies &&
> > (net->ipv4.sysctl_max_syn_backlog - inet_csk_reqsk_queue_len(sk) <
> > (net->ipv4.sysctl_max_syn_backlog >> 2)) &&
> > !tcp_peer_is_proven(req, dst)) {
> > /* Without syncookies last quarter of
> > * backlog is filled with destinations,
> > * proven to be alive.
> > * It means that we continue to communicate
> > * to destinations, already remembered
> > * to the moment of synflood.
> > */
> > pr_drop_req(req, ntohs(tcp_hdr(skb)->source),
> > rsk_ops->family);
> > goto drop_and_release;
> > }
> >
> >
> > But why don't we use all the syn queues?
>
> If tcp_peer_is_proven() returns true then we do allow ourselves to use
> the whole queue.
>
> > Why do we need to leave the size of (net->ipv4.sysctl_max_syn_backlog >> 2) in the queue?
> > Even if the system is attacked by a syn flood, there is no need to leave a part. Why do we need to leave a part?
>
> The comment describes the rationale. If syncookies are disabled, then
> the last quarter of the backlog is reserved for filling with
> destinations that were proven to be alive, according to
> tcp_peer_is_proven() (which uses RTTs measured in previous
> connections). The idea is that if there is a SYN flood, we do not want
> to use all of our queue budget on attack traffic but instead want to
> reserve some queue space for SYNs from real remote machines that we
> have actually contacted in the past.
>
> > The value of sysctl_max_syn_backlog is the maximum length of the queue only if syn cookies are enabled.
>
> Even if syncookies are disabled, sysctl_max_syn_backlog is the maximum
> length of the queue.
>
> > This is the first strange place, here is another strange place
> >
> > __u32 isn = TCP_SKB_CB(skb)->tcp_tw_isn;
> >
> > if ((net->ipv4.sysctl_tcp_syncookies == 2 ||
> > inet_csk_reqsk_queue_is_full(sk)) && !isn) {
> >
> > if (!want_cookie && !isn) {
> >
> >
> > The value of "isn" comes from TCP_SKB_CB(skb)->tcp_tw_isn, then it is judged twice whether its value is indeed 0.
> > But "tcp_tw_isn" is initialized in the function "tcp_v4_fill_cb"
> >
> > TCP_SKB_CB(skb)->tcp_tw_isn = 0;
> >
> >
> > So it has always been 0, I used printk to test, and the result is always 0.
>
> That field is also set in tcp_timewait_state_process():
>
> TCP_SKB_CB(skb)->tcp_tw_isn = isn;
>
> So there can be cases where it is not 0.
>
> Hope that helps,
> neal
Thank you very much, I understand
^ permalink raw reply
* [RFC/PATCH] net: nixge: Add PHYLINK support
From: Moritz Fischer @ 2018-09-05 0:15 UTC (permalink / raw)
To: netdev
Cc: davem, f.fainelli, andrew, alex.williams, moritz.fischer,
linux-kernel, Moritz Fischer
Add basic PHYLINK support to driver.
Suggested-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Moritz Fischer <mdf@kernel.org>
---
Hi all,
as Andrew suggested in order to enable SFP as
well as fixed-link support add PHYLINK support.
A couple of questions are still open (hence the RFC):
1) It seems odd to implement PHYLINK callbacks that
are all empty? If so, should we have generic empty
ones in drivers/net/phy/phylink.c like we have for
genphys?
2) If this is ok, then I'll go ahead rework this with
a DT binding update to deprecate the non-'mdio'-subnode
case (since there are no in-tree users we might just
change the binding)?
3) I'm again not sure about the 'select PHYLINK', wouldn't
wanna break the build again...
Thanks again for your time!
Moritz
---
drivers/net/ethernet/ni/Kconfig | 1 +
drivers/net/ethernet/ni/nixge.c | 115 +++++++++++++++++++++++---------
2 files changed, 83 insertions(+), 33 deletions(-)
diff --git a/drivers/net/ethernet/ni/Kconfig b/drivers/net/ethernet/ni/Kconfig
index c73978474c4b..80cd72948551 100644
--- a/drivers/net/ethernet/ni/Kconfig
+++ b/drivers/net/ethernet/ni/Kconfig
@@ -21,6 +21,7 @@ config NI_XGE_MANAGEMENT_ENET
depends on HAS_IOMEM && HAS_DMA
select PHYLIB
select OF_MDIO if OF
+ select PHYLINK
help
Simple LAN device for debug or management purposes. Can
support either 10G or 1G PHYs via SFP+ ports.
diff --git a/drivers/net/ethernet/ni/nixge.c b/drivers/net/ethernet/ni/nixge.c
index 74cf52e3fb09..a0e790d07b1c 100644
--- a/drivers/net/ethernet/ni/nixge.c
+++ b/drivers/net/ethernet/ni/nixge.c
@@ -11,6 +11,7 @@
#include <linux/of_mdio.h>
#include <linux/of_net.h>
#include <linux/of_platform.h>
+#include <linux/phylink.h>
#include <linux/of_irq.h>
#include <linux/skbuff.h>
#include <linux/phy.h>
@@ -165,7 +166,7 @@ struct nixge_priv {
struct device *dev;
/* Connection to PHY device */
- struct device_node *phy_node;
+ struct phylink *phylink;
phy_interface_t phy_mode;
int link;
@@ -416,20 +417,6 @@ static void nixge_device_reset(struct net_device *ndev)
netif_trans_update(ndev);
}
-static void nixge_handle_link_change(struct net_device *ndev)
-{
- struct nixge_priv *priv = netdev_priv(ndev);
- struct phy_device *phydev = ndev->phydev;
-
- if (phydev->link != priv->link || phydev->speed != priv->speed ||
- phydev->duplex != priv->duplex) {
- priv->link = phydev->link;
- priv->speed = phydev->speed;
- priv->duplex = phydev->duplex;
- phy_print_status(phydev);
- }
-}
-
static void nixge_tx_skb_unmap(struct nixge_priv *priv,
struct nixge_tx_skb *tx_skb)
{
@@ -859,17 +846,15 @@ static void nixge_dma_err_handler(unsigned long data)
static int nixge_open(struct net_device *ndev)
{
struct nixge_priv *priv = netdev_priv(ndev);
- struct phy_device *phy;
int ret;
nixge_device_reset(ndev);
- phy = of_phy_connect(ndev, priv->phy_node,
- &nixge_handle_link_change, 0, priv->phy_mode);
- if (!phy)
- return -ENODEV;
+ ret = phylink_of_phy_connect(priv->phylink, priv->dev->of_node, 0);
+ if (ret < 0)
+ return ret;
- phy_start(phy);
+ phylink_start(priv->phylink);
/* Enable tasklets for Axi DMA error handling */
tasklet_init(&priv->dma_err_tasklet, nixge_dma_err_handler,
@@ -893,8 +878,7 @@ static int nixge_open(struct net_device *ndev)
err_rx_irq:
free_irq(priv->tx_irq, ndev);
err_tx_irq:
- phy_stop(phy);
- phy_disconnect(phy);
+ phylink_disconnect_phy(priv->phylink);
tasklet_kill(&priv->dma_err_tasklet);
netdev_err(ndev, "request_irq() failed\n");
return ret;
@@ -908,9 +892,9 @@ static int nixge_stop(struct net_device *ndev)
netif_stop_queue(ndev);
napi_disable(&priv->napi);
- if (ndev->phydev) {
- phy_stop(ndev->phydev);
- phy_disconnect(ndev->phydev);
+ if (priv->phylink) {
+ phylink_stop(priv->phylink);
+ phylink_disconnect_phy(priv->phylink);
}
cr = nixge_dma_read_reg(priv, XAXIDMA_RX_CR_OFFSET);
@@ -1076,13 +1060,31 @@ static int nixge_ethtools_set_phys_id(struct net_device *ndev,
return 0;
}
+static int
+nixge_ethtool_set_link_ksettings(struct net_device *ndev,
+ const struct ethtool_link_ksettings *cmd)
+{
+ struct nixge_priv *priv = netdev_priv(ndev);
+
+ return phylink_ethtool_ksettings_set(priv->phylink, cmd);
+}
+
+static int
+nixge_ethtool_get_link_ksettings(struct net_device *ndev,
+ struct ethtool_link_ksettings *cmd)
+{
+ struct nixge_priv *priv = netdev_priv(ndev);
+
+ return phylink_ethtool_ksettings_get(priv->phylink, cmd);
+}
+
static const struct ethtool_ops nixge_ethtool_ops = {
.get_drvinfo = nixge_ethtools_get_drvinfo,
.get_coalesce = nixge_ethtools_get_coalesce,
.set_coalesce = nixge_ethtools_set_coalesce,
.set_phys_id = nixge_ethtools_set_phys_id,
- .get_link_ksettings = phy_ethtool_get_link_ksettings,
- .set_link_ksettings = phy_ethtool_set_link_ksettings,
+ .get_link_ksettings = nixge_ethtool_get_link_ksettings,
+ .set_link_ksettings = nixge_ethtool_set_link_ksettings,
.get_link = ethtool_op_get_link,
};
@@ -1225,11 +1227,52 @@ static void *nixge_get_nvmem_address(struct device *dev)
return mac;
}
+static void nixge_validate(struct net_device *ndev, unsigned long *supported,
+ struct phylink_link_state *state)
+{
+}
+
+static int nixge_mac_link_state(struct net_device *ndev,
+ struct phylink_link_state *state)
+{
+ return 0;
+}
+
+static void nixge_mac_config(struct net_device *ndev, unsigned int mode,
+ const struct phylink_link_state *state)
+{
+}
+
+static void nixge_mac_an_restart(struct net_device *ndev)
+{
+}
+
+static void nixge_mac_link_down(struct net_device *ndev, unsigned int mode,
+ phy_interface_t interface)
+{
+}
+
+static void nixge_mac_link_up(struct net_device *ndev, unsigned int mode,
+ phy_interface_t interface,
+ struct phy_device *phy)
+{
+}
+
+static const struct phylink_mac_ops nixge_phylink_ops = {
+ .validate = nixge_validate,
+ .mac_link_state = nixge_mac_link_state,
+ .mac_an_restart = nixge_mac_an_restart,
+ .mac_config = nixge_mac_config,
+ .mac_link_down = nixge_mac_link_down,
+ .mac_link_up = nixge_mac_link_up,
+};
+
static int nixge_probe(struct platform_device *pdev)
{
struct nixge_priv *priv;
struct net_device *ndev;
struct resource *dmares;
+ struct device_node *mn;
const u8 *mac_addr;
int err;
@@ -1286,7 +1329,13 @@ static int nixge_probe(struct platform_device *pdev)
priv->coalesce_count_rx = XAXIDMA_DFT_RX_THRESHOLD;
priv->coalesce_count_tx = XAXIDMA_DFT_TX_THRESHOLD;
- err = nixge_mdio_setup(priv, pdev->dev.of_node);
+ mn = of_get_child_by_name(pdev->dev.of_node, "mdio");
+ if (!mn) {
+ dev_warn(&pdev->dev, "No \"mdio\" subnode found, defaulting to legacy\n");
+ mn = pdev->dev.of_node;
+ }
+
+ err = nixge_mdio_setup(priv, mn);
if (err) {
netdev_err(ndev, "error registering mdio bus");
goto free_netdev;
@@ -1299,10 +1348,10 @@ static int nixge_probe(struct platform_device *pdev)
goto unregister_mdio;
}
- priv->phy_node = of_parse_phandle(pdev->dev.of_node, "phy-handle", 0);
- if (!priv->phy_node) {
- netdev_err(ndev, "not find \"phy-handle\" property\n");
- err = -EINVAL;
+ priv->phylink = phylink_create(ndev, pdev->dev.fwnode, priv->phy_mode,
+ &nixge_phylink_ops);
+ if (IS_ERR(priv->phylink)) {
+ err = PTR_ERR(priv->phylink);
goto unregister_mdio;
}
--
2.18.0
^ permalink raw reply related
* I wait for your prompt response.
From: Aziz Dake @ 2018-09-05 0:44 UTC (permalink / raw)
Good day,
I am Mr. Aziz Dake, from Burkina Faso a Minister confide on me to
look for foreign partner who will assist him to invest the sum of
Thirty Million Dollars ($30,000,000) in your country.
He has investment interest in mining, exotic properties for commercial
resident, development properties, hotels and any other viable
investment opportunities in your country based on your recommendation
will be highly welcomed.
Hence your co -operation is highly needed to actualize this investment project
I wait for your prompt response.
Sincerely yours
Mr Aziz Dake.
^ permalink raw reply
* Planned downtime for ozlabs.org
From: Stephen Rothwell @ 2018-09-05 0:55 UTC (permalink / raw)
To: users
Cc: Stephen Finucane, David Miller, richard.weinberger, rdunlap,
andrew.donnellan, jeffrey.t.kirsher, jk, patchwork, netdev,
miquel.raynal
[-- Attachment #1: Type: text/plain, Size: 610 bytes --]
Hi all,
There will be a (hopefully) short outage of
{bilbo,patchwork,lists,irc,mail,mx}.ozlabs.org tomorrow (Thu Sep 6) at
around 11am Canberra time (+1000) to (hopefully) fix the problem with
our router port that has been causing some of the recent connectivity
problems.
I may take the opportunity to also reboot the server for useful kernel
updates.
We also currently have no IPv6 connectivity (and no ETA for recovery)
so I have removed the IPv6 addresses from most of our public facing
services. I will put them back when we have our connectivity back.
--
Cheers,
Stephen Rothwell
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply
* Re: [RFC/PATCH] net: nixge: Add PHYLINK support
From: Andrew Lunn @ 2018-09-05 1:07 UTC (permalink / raw)
To: Moritz Fischer
Cc: netdev, davem, f.fainelli, alex.williams, moritz.fischer,
linux-kernel
In-Reply-To: <20180905001535.19168-1-mdf@kernel.org>
> -static void nixge_handle_link_change(struct net_device *ndev)
> -{
> - struct nixge_priv *priv = netdev_priv(ndev);
> - struct phy_device *phydev = ndev->phydev;
> -
> - if (phydev->link != priv->link || phydev->speed != priv->speed ||
> - phydev->duplex != priv->duplex) {
> - priv->link = phydev->link;
> - priv->speed = phydev->speed;
> - priv->duplex = phydev->duplex;
> - phy_print_status(phydev);
> - }
> -}
I think this is why you are having trouble with the phylink
callbacks. You currently don't have any configuration of the MAC. You
normally need to tell the MAC what speed it should be doing. What
duplex it should be doing, if the link is up or down, if it should do
pause, or asym pause or no pause, etc.
Andrew
^ permalink raw reply
* Re: [PATCH] net: ethernet: i40e: fix build error
From: Wang, Dongsheng @ 2018-09-05 1:32 UTC (permalink / raw)
To: Sergei Shtylyov, jeffrey.t.kirsher@intel.com
Cc: jacob.e.keller@intel.com, davem@davemloft.net,
intel-wired-lan@lists.osuosl.org, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org
In-Reply-To: <84982f95-940e-d278-f6a2-13a9f76823c9@cogentembedded.com>
On 2018/9/4 18:54, Sergei Shtylyov wrote:
> On 9/4/2018 12:48 PM, Wang Dongsheng wrote:
>
>> Remove "inline" from __i40e_add_stat_strings.
>>
>> In file included from
>> drivers/net/ethernet/intel/i40e/i40e_ethtool.c:9:0:
>> drivers/net/ethernet/intel/i40e/i40e_ethtool.c: In function
>> ‘__i40e_add_stat_strings’:
>> drivers/net/ethernet/intel/i40e/i40e_ethtool_stats.h:193:20: error:
>> function ‘__i40e_add_stat_strings’ can never be inlined because it uses
>> variable argument lists
>> static inline void __i40e_add_stat_strings(u8 **p, const struct
>> i40e_stats stats[],
>>
>> Signed-off-by: Wang Dongsheng <dongsheng.wang@hxt-semitech.com>
>> ---
>> drivers/net/ethernet/intel/i40e/i40e_ethtool_stats.h | 2 +-
>> 1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool_stats.h b/drivers/net/ethernet/intel/i40e/i40e_ethtool_stats.h
>> index bba1cb0..0290ade 100644
>> --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool_stats.h
>> +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool_stats.h
>> @@ -190,7 +190,7 @@ struct i40e_stats {
>> * Format and copy the strings described by stats into the buffer pointed at
>> * by p.
>> **/
>> -static inline void __i40e_add_stat_strings(u8 **p, const struct i40e_stats stats[],
>> +static void __i40e_add_stat_strings(u8 **p, const struct i40e_stats stats[],
> You can't have non-inline function in a header file. Please move it,
> leaving only prototype here.
:(. Oops, a stupid mistake...fix an error and bring in another
error...Thanks.
Cheers,
-Dongsheng
>> const unsigned int size, ...)
>> {
>> unsigned int i;
> MBR, Sergei
>
^ permalink raw reply
* Re: [Patch net v3] tipc: call start and done ops directly in __tipc_nl_compat_dumpit()
From: Ying Xue @ 2018-09-05 6:04 UTC (permalink / raw)
To: Cong Wang; +Cc: Linux Kernel Network Developers, tipc-discussion
In-Reply-To: <CAM_iQpXvwy1vR9extqOYk2J6zk=xajH+5L8mabwgd1N_JkfPAQ@mail.gmail.com>
On 09/05/2018 01:49 PM, Cong Wang wrote:
> On Tue, Sep 4, 2018 at 8:25 PM Ying Xue <ying.xue@windriver.com> wrote:
>>
>> On 09/05/2018 05:54 AM, Cong Wang wrote:
>>> __tipc_nl_compat_dumpit() uses a netlink_callback on stack,
>>> so the only way to align it with other ->dumpit() call path
>>> is calling tipc_dump_start() and tipc_dump_done() directly
>>> inside it. Otherwise ->dumpit() would always get NULL from
>>> cb->args[].
>>>
>>> But tipc_dump_start() uses sock_net(cb->skb->sk) to retrieve
>>> net pointer, the cb->skb here doesn't set skb->sk, the net pointer
>>> is saved in msg->net instead, so introduce a helper function
>>> __tipc_dump_start() to pass in msg->net.
>>>
>>> Ying pointed out cb->args[0...3] are already used by other
>>> callbacks on this call path, so we can't use cb->args[0] any
>>> more, use cb->args[4] instead.
>>
>> It's a common mechanism to save rhashtable iterator pointer in cb->args
>> after tipc_dump_start() and tipc_dump_done() are introduced. Someday
>> probably we will involve new dumpit function. In order to lower the risk
>> that rhashtable iterator pointer saved is overwritten, it's better to
>> use the last slot, ie, cb->args[5].
>
> I don't understand, currently only cb->args[0..3] are used at most,
> therefore cb->args[4] is pretty safe in current code base, there is
> no reason to be so defensive to use cb->args[5].
>
Yes, at present cb->args[4] is safe.
> If you really worry about future, you probably want to extend cb->args
> from 6 to whatever larger, rather than just skipping cb->args[4].
>
When we have to use the fifth slot of cb->args[] in the future, we need
to skip sb->args[4], which is a bit wried. This is the reason why I
suggested we could use the last one.
> I don't see any reason to do so.
As I said, the current version is safe. If you think it's unnecessary to
change, it's okay to me.
Acked-by: Ying Xue <ying.xue@windriver.com>
>
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
^ permalink raw reply
* Re: [PATCH bpf-next v2] libbpf: Remove the duplicate checking of function storage
From: Alexei Starovoitov @ 2018-09-05 6:11 UTC (permalink / raw)
To: Jakub Kicinski
Cc: Taeung Song, Daniel Borkmann, Alexei Starovoitov, netdev,
linux-kernel
In-Reply-To: <20180904110745.3ab4dc3e@cakuba>
On Tue, Sep 04, 2018 at 11:07:45AM +0200, Jakub Kicinski wrote:
> On Mon, 3 Sep 2018 08:30:07 +0900, Taeung Song wrote:
> > After the commit eac7d84519a3 ("tools: libbpf: don't return '.text'
> > as a program for multi-function programs"), bpf_program__next()
> > in bpf_object__for_each_program skips the function storage such as .text,
> > so eliminate the duplicate checking.
> >
> > Cc: Jakub Kicinski <jakub.kicinski@netronome.com>
> > Signed-off-by: Taeung Song <treeze.taeung@gmail.com>
>
> Acked-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Applied, Thanks
^ permalink raw reply
* Re: [PATCH bpf-next] bpf/verifier: properly clear union members after a ctx read
From: Alexei Starovoitov @ 2018-09-05 2:23 UTC (permalink / raw)
To: Edward Cree; +Cc: daniel, ast, netdev
In-Reply-To: <0b724ba4-9ddf-e635-0bd5-201658355cf5@solarflare.com>
On Tue, Sep 04, 2018 at 03:19:52PM +0100, Edward Cree wrote:
> In check_mem_access(), for the PTR_TO_CTX case, after check_ctx_access()
> has supplied a reg_type, the other members of the register state are set
> appropriately. Previously reg.range was set to 0, but as it is in a
> union with reg.map_ptr, which is larger, upper bytes of the latter were
> left in place. This then caused the memcmp() in regsafe() to fail,
> preventing some branches from being pruned (and occasionally causing the
> same program to take a varying number of processed insns on repeated
> verifier runs).
>
> Signed-off-by: Edward Cree <ecree@solarflare.com>
> ---
> Possibly something might need adding to __mark_reg_unknown() as well to
> clear map_ptr/range, I'm not sure (though doing so did not affect the
> processed insn count on the cilium programs).
>
> kernel/bpf/verifier.c | 6 +++---
> 1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index f4ff0c569e54..49e4ea66fdd3 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
> @@ -1640,9 +1640,9 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn
> else
> mark_reg_known_zero(env, regs,
> value_regno);
> - regs[value_regno].id = 0;
> - regs[value_regno].off = 0;
> - regs[value_regno].range = 0;
> + /* Clear id, off, and union(map_ptr, range) */
> + memset(regs + value_regno, 0,
> + offsetof(struct bpf_reg_state, var_off));
> regs[value_regno].type = reg_type;
> }
Awesome! Thanks a bunch for tracking it down.
I vaguely remember thinking about overlapping map_ptr with other fields
and not clearing map_ptr explicitly, because it was unnecessary...
Doing a bit of git-archaeology...
Looks like commit f1174f77b50c ("bpf/verifier: rework value tracking")
removed 'imm' from that union, so that __mark_reg_unknown_value()
that was clearing both 'imm' and 'map_ptr' before was no longer happening.
So old sequence:
mark_reg_unknown_value_and_range(); // which called __mark_reg_unknown_value()
// which cleared 'imm' (and id|off|range)
state->regs[value_regno].type = reg_type;
got replaced with
mark_reg_known_zero();
state->regs[value_regno].id = 0;
state->regs[value_regno].off = 0;
state->regs[value_regno].range = 0;
state->regs[value_regno].type = reg_type;
which made map_ptr contain junk in upper bits.
I bet the comment "note that reg.[id|off|range] == 0" few lines before
that was deleted by that commit probably caused that bug :)
That comment I added as part of commit 969bf05eb3ce ("bpf: direct packet access")
What I was trying to express in that comment that
"mark_reg_unknown_value() that is called right before that comment
also clears id|off|range that are included as part of bigger 'imm' field
that mark_reg_unknown_value() clears, so these three fields don't need
to be cleared separately"
Sorry for confusion that that comment caused and painful debugging.
So would you agree it's fair to add
Fixes: f1174f77b50c ("bpf/verifier: rework value tracking")
?
Also I think it's better to do this memset() in both
__mark_reg_unknown() and in __mark_reg_known()
instead of open coding it here in check_mem_access().
While at it we would also need to adjust this:
static void __mark_reg_const_zero(struct bpf_reg_state *reg)
{
__mark_reg_known(reg, 0);
reg->off = 0;
reg->type = SCALAR_VALUE;
}
since line reg->off = 0; wouldn't make sense after memset() is added
and few other places.
btw the 4 byte hole:
enum bpf_reg_type type; /* 0 4 */
/* XXX 4 bytes hole, try to pack */
union {
u16 range; /* 2 */
struct bpf_map * map_ptr; /* 8 */
}; /* 8 8 */
doesn't cause instability issues, since we kzalloc verifier reg state.
How about patch like the following:
------------
>From 422fd975ed78645ab67d2eb50ff6e1ff6fb3de32 Mon Sep 17 00:00:00 2001
From: Alexei Starovoitov <ast@kernel.org>
Date: Tue, 4 Sep 2018 19:13:44 -0700
Subject: [PATCH] bpf/verifier: fix verifier instability
Fixes: f1174f77b50c ("bpf/verifier: rework value tracking")
Debugged-by: Edward Cree <ecree@solarflare.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
---
kernel/bpf/verifier.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index f4ff0c569e54..6ff1bac1795d 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -570,7 +570,9 @@ static void __mark_reg_not_init(struct bpf_reg_state *reg);
*/
static void __mark_reg_known(struct bpf_reg_state *reg, u64 imm)
{
- reg->id = 0;
+ /* Clear id, off, and union(map_ptr, range) */
+ memset(((u8 *)reg) + sizeof(reg->type), 0,
+ offsetof(struct bpf_reg_state, var_off) - sizeof(reg->type));
reg->var_off = tnum_const(imm);
reg->smin_value = (s64)imm;
reg->smax_value = (s64)imm;
@@ -589,7 +591,6 @@ static void __mark_reg_known_zero(struct bpf_reg_state *reg)
static void __mark_reg_const_zero(struct bpf_reg_state *reg)
{
__mark_reg_known(reg, 0);
- reg->off = 0;
reg->type = SCALAR_VALUE;
}
@@ -700,9 +701,12 @@ static void __mark_reg_unbounded(struct bpf_reg_state *reg)
/* Mark a register as having a completely unknown (scalar) value. */
static void __mark_reg_unknown(struct bpf_reg_state *reg)
{
+ /*
+ * Clear type, id, off, and union(map_ptr, range) and
+ * padding between 'type' and union
+ */
+ memset(reg, 0, offsetof(struct bpf_reg_state, var_off));
reg->type = SCALAR_VALUE;
- reg->id = 0;
- reg->off = 0;
reg->var_off = tnum_unknown;
reg->frameno = 0;
__mark_reg_unbounded(reg);
@@ -1640,9 +1644,6 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn
else
mark_reg_known_zero(env, regs,
value_regno);
- regs[value_regno].id = 0;
- regs[value_regno].off = 0;
- regs[value_regno].range = 0;
regs[value_regno].type = reg_type;
}
@@ -2495,7 +2496,6 @@ static int check_helper_call(struct bpf_verifier_env *env, int func_id, int insn
regs[BPF_REG_0].type = PTR_TO_MAP_VALUE_OR_NULL;
/* There is no offset yet applied, variable or fixed */
mark_reg_known_zero(env, regs, BPF_REG_0);
- regs[BPF_REG_0].off = 0;
/* remember map_ptr, so that check_map_access()
* can check 'value_size' boundary of memory access
* to map element returned from bpf_map_lookup_elem()
--
2.17.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox