* [PATCH net-next 0/7] net: dsa: mv88e6xxx: prepare Wait Bit operation
From: Vivien Didelot @ 2019-08-09 22:47 UTC (permalink / raw)
To: netdev; +Cc: davem, f.fainelli, andrew, Vivien Didelot
The Remote Management Interface has its own implementation of a Wait
Bit operation, which requires a bit number and a value to wait for.
In order to prepare the introduction of this implementation, rework the
code waiting for bits and masks in mv88e6xxx to match this signature.
This has the benefit to unify the implementation of wait routines while
removing obsolete wait and update functions and also reducing the code.
Vivien Didelot (7):
net: dsa: mv88e6xxx: wait for 88E6185 PPU disabled
net: dsa: mv88e6xxx: introduce wait mask routine
net: dsa: mv88e6xxx: introduce wait bit routine
net: dsa: mv88e6xxx: wait for AVB Busy bit
net: dsa: mv88e6xxx: remove wait and update routines
net: dsa: mv88e6xxx: fix SMI bit checking
net: dsa: mv88e6xxx: add delay in direct SMI wait
drivers/net/dsa/mv88e6xxx/chip.c | 76 ++++++++---------
drivers/net/dsa/mv88e6xxx/chip.h | 7 +-
drivers/net/dsa/mv88e6xxx/global1.c | 95 ++++++---------------
drivers/net/dsa/mv88e6xxx/global1.h | 5 +-
drivers/net/dsa/mv88e6xxx/global1_atu.c | 7 +-
drivers/net/dsa/mv88e6xxx/global1_vtu.c | 6 +-
drivers/net/dsa/mv88e6xxx/global2.c | 72 +++++++++-------
drivers/net/dsa/mv88e6xxx/global2.h | 12 +--
drivers/net/dsa/mv88e6xxx/global2_avb.c | 29 ++++++-
drivers/net/dsa/mv88e6xxx/global2_scratch.c | 3 +-
drivers/net/dsa/mv88e6xxx/smi.c | 4 +-
11 files changed, 155 insertions(+), 161 deletions(-)
--
2.22.0
^ permalink raw reply
* [PATCH net-next 1/7] net: dsa: mv88e6xxx: wait for 88E6185 PPU disabled
From: Vivien Didelot @ 2019-08-09 22:47 UTC (permalink / raw)
To: netdev; +Cc: davem, f.fainelli, andrew, Vivien Didelot
In-Reply-To: <20190809224759.5743-1-vivien.didelot@gmail.com>
The PPU state of 88E6185 can be either "Disabled at Reset" or
"Disabled after Initialization". Because we intentionally clear the
PPU Enabled bit before checking its state, it is safe to wait for the
MV88E6185_G1_STS_PPU_STATE_DISABLED state explicitly instead of waiting
for any state different than MV88E6185_G1_STS_PPU_STATE_POLLING.
Signed-off-by: Vivien Didelot <vivien.didelot@gmail.com>
---
drivers/net/dsa/mv88e6xxx/global1.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/dsa/mv88e6xxx/global1.c b/drivers/net/dsa/mv88e6xxx/global1.c
index 1323ef30a5e9..bbd31c9f8b48 100644
--- a/drivers/net/dsa/mv88e6xxx/global1.c
+++ b/drivers/net/dsa/mv88e6xxx/global1.c
@@ -46,7 +46,7 @@ static int mv88e6185_g1_wait_ppu_disabled(struct mv88e6xxx_chip *chip)
/* Check the value of the PPUState bits 15:14 */
state &= MV88E6185_G1_STS_PPU_STATE_MASK;
- if (state != MV88E6185_G1_STS_PPU_STATE_POLLING)
+ if (state == MV88E6185_G1_STS_PPU_STATE_DISABLED)
return 0;
usleep_range(1000, 2000);
--
2.22.0
^ permalink raw reply related
* [PATCH net-next 2/7] net: dsa: mv88e6xxx: introduce wait mask routine
From: Vivien Didelot @ 2019-08-09 22:47 UTC (permalink / raw)
To: netdev; +Cc: davem, f.fainelli, andrew, Vivien Didelot
In-Reply-To: <20190809224759.5743-1-vivien.didelot@gmail.com>
The current mv88e6xxx_wait routine is used to wait for a given mask
to be cleared to zero. However in some cases, the driver may have
to wait for a given mask to be of a certain non-zero value.
Thus provide a generic wait mask routine that will be used to implement
the current mv88e6xxx_wait function, and use it to wait for 88E6185
PPU states.
Signed-off-by: Vivien Didelot <vivien.didelot@gmail.com>
---
drivers/net/dsa/mv88e6xxx/chip.c | 42 +++++++++++++++-----------
drivers/net/dsa/mv88e6xxx/chip.h | 2 ++
drivers/net/dsa/mv88e6xxx/global1.c | 47 ++++++++---------------------
drivers/net/dsa/mv88e6xxx/global1.h | 2 ++
4 files changed, 41 insertions(+), 52 deletions(-)
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index d3804ffd3d2a..bd61d0d3a245 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -80,6 +80,29 @@ int mv88e6xxx_write(struct mv88e6xxx_chip *chip, int addr, int reg, u16 val)
return 0;
}
+int mv88e6xxx_wait_mask(struct mv88e6xxx_chip *chip, int addr, int reg,
+ u16 mask, u16 val)
+{
+ u16 data;
+ int err;
+ int i;
+
+ /* There's no bus specific operation to wait for a mask */
+ for (i = 0; i < 16; i++) {
+ err = mv88e6xxx_read(chip, addr, reg, &data);
+ if (err)
+ return err;
+
+ if ((data & mask) == val)
+ return 0;
+
+ usleep_range(1000, 2000);
+ }
+
+ dev_err(chip->dev, "Timeout while waiting for switch\n");
+ return -ETIMEDOUT;
+}
+
struct mii_bus *mv88e6xxx_default_mdio_bus(struct mv88e6xxx_chip *chip)
{
struct mv88e6xxx_mdio_bus *mdio_bus;
@@ -365,24 +388,7 @@ static void mv88e6xxx_irq_poll_free(struct mv88e6xxx_chip *chip)
int mv88e6xxx_wait(struct mv88e6xxx_chip *chip, int addr, int reg, u16 mask)
{
- int i;
-
- for (i = 0; i < 16; i++) {
- u16 val;
- int err;
-
- err = mv88e6xxx_read(chip, addr, reg, &val);
- if (err)
- return err;
-
- if (!(val & mask))
- return 0;
-
- usleep_range(1000, 2000);
- }
-
- dev_err(chip->dev, "Timeout while waiting for switch\n");
- return -ETIMEDOUT;
+ return mv88e6xxx_wait_mask(chip, addr, reg, mask, 0x0000);
}
/* Indirect write to single pointer-data register with an Update bit */
diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h
index 8c6d3c906197..95b44532a282 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.h
+++ b/drivers/net/dsa/mv88e6xxx/chip.h
@@ -588,6 +588,8 @@ static inline bool mv88e6xxx_is_invalid_port(struct mv88e6xxx_chip *chip, int po
int mv88e6xxx_read(struct mv88e6xxx_chip *chip, int addr, int reg, u16 *val);
int mv88e6xxx_write(struct mv88e6xxx_chip *chip, int addr, int reg, u16 val);
+int mv88e6xxx_wait_mask(struct mv88e6xxx_chip *chip, int addr, int reg,
+ u16 mask, u16 val);
int mv88e6xxx_update(struct mv88e6xxx_chip *chip, int addr, int reg,
u16 update);
int mv88e6xxx_wait(struct mv88e6xxx_chip *chip, int addr, int reg, u16 mask);
diff --git a/drivers/net/dsa/mv88e6xxx/global1.c b/drivers/net/dsa/mv88e6xxx/global1.c
index bbd31c9f8b48..482f9f8465af 100644
--- a/drivers/net/dsa/mv88e6xxx/global1.c
+++ b/drivers/net/dsa/mv88e6xxx/global1.c
@@ -32,48 +32,27 @@ int mv88e6xxx_g1_wait(struct mv88e6xxx_chip *chip, int reg, u16 mask)
return mv88e6xxx_wait(chip, chip->info->global1_addr, reg, mask);
}
+int mv88e6xxx_g1_wait_mask(struct mv88e6xxx_chip *chip, int reg,
+ u16 mask, u16 val)
+{
+ return mv88e6xxx_wait_mask(chip, chip->info->global1_addr, reg,
+ mask, val);
+}
+
/* Offset 0x00: Switch Global Status Register */
static int mv88e6185_g1_wait_ppu_disabled(struct mv88e6xxx_chip *chip)
{
- u16 state;
- int i, err;
-
- for (i = 0; i < 16; i++) {
- err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STS, &state);
- if (err)
- return err;
-
- /* Check the value of the PPUState bits 15:14 */
- state &= MV88E6185_G1_STS_PPU_STATE_MASK;
- if (state == MV88E6185_G1_STS_PPU_STATE_DISABLED)
- return 0;
-
- usleep_range(1000, 2000);
- }
-
- return -ETIMEDOUT;
+ return mv88e6xxx_g1_wait_mask(chip, MV88E6XXX_G1_STS,
+ MV88E6185_G1_STS_PPU_STATE_MASK,
+ MV88E6185_G1_STS_PPU_STATE_DISABLED);
}
static int mv88e6185_g1_wait_ppu_polling(struct mv88e6xxx_chip *chip)
{
- u16 state;
- int i, err;
-
- for (i = 0; i < 16; ++i) {
- err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STS, &state);
- if (err)
- return err;
-
- /* Check the value of the PPUState bits 15:14 */
- state &= MV88E6185_G1_STS_PPU_STATE_MASK;
- if (state == MV88E6185_G1_STS_PPU_STATE_POLLING)
- return 0;
-
- usleep_range(1000, 2000);
- }
-
- return -ETIMEDOUT;
+ return mv88e6xxx_g1_wait_mask(chip, MV88E6XXX_G1_STS,
+ MV88E6185_G1_STS_PPU_STATE_MASK,
+ MV88E6185_G1_STS_PPU_STATE_POLLING);
}
static int mv88e6352_g1_wait_ppu_polling(struct mv88e6xxx_chip *chip)
diff --git a/drivers/net/dsa/mv88e6xxx/global1.h b/drivers/net/dsa/mv88e6xxx/global1.h
index d444266f7d78..48869d7984f4 100644
--- a/drivers/net/dsa/mv88e6xxx/global1.h
+++ b/drivers/net/dsa/mv88e6xxx/global1.h
@@ -250,6 +250,8 @@
int mv88e6xxx_g1_read(struct mv88e6xxx_chip *chip, int reg, u16 *val);
int mv88e6xxx_g1_write(struct mv88e6xxx_chip *chip, int reg, u16 val);
int mv88e6xxx_g1_wait(struct mv88e6xxx_chip *chip, int reg, u16 mask);
+int mv88e6xxx_g1_wait_mask(struct mv88e6xxx_chip *chip, int reg,
+ u16 mask, u16 val);
int mv88e6xxx_g1_set_switch_mac(struct mv88e6xxx_chip *chip, u8 *addr);
--
2.22.0
^ permalink raw reply related
* [PATCH net-next 4/7] net: dsa: mv88e6xxx: wait for AVB Busy bit
From: Vivien Didelot @ 2019-08-09 22:47 UTC (permalink / raw)
To: netdev; +Cc: davem, f.fainelli, andrew, Vivien Didelot
In-Reply-To: <20190809224759.5743-1-vivien.didelot@gmail.com>
The AVB is not an indirect table using an Update bit, but a unit using
a Busy bit. This means that we must ensure that this bit is cleared
before setting it and wait until it gets cleared again after writing
an operation. Reflect that.
Signed-off-by: Vivien Didelot <vivien.didelot@gmail.com>
---
drivers/net/dsa/mv88e6xxx/global2_avb.c | 29 +++++++++++++++++++++++--
1 file changed, 27 insertions(+), 2 deletions(-)
diff --git a/drivers/net/dsa/mv88e6xxx/global2_avb.c b/drivers/net/dsa/mv88e6xxx/global2_avb.c
index 116b8cf5a6e3..657783e043ff 100644
--- a/drivers/net/dsa/mv88e6xxx/global2_avb.c
+++ b/drivers/net/dsa/mv88e6xxx/global2_avb.c
@@ -11,6 +11,8 @@
* Brandon Streiff <brandon.streiff@ni.com>
*/
+#include <linux/bitfield.h>
+
#include "global2.h"
/* Offset 0x16: AVB Command Register
@@ -27,17 +29,33 @@
/* mv88e6xxx_g2_avb_read -- Read one or multiple 16-bit words.
* The hardware supports snapshotting up to four contiguous registers.
*/
+static int mv88e6xxx_g2_avb_wait(struct mv88e6xxx_chip *chip)
+{
+ int bit = __bf_shf(MV88E6352_G2_AVB_CMD_BUSY);
+
+ return mv88e6xxx_g2_wait_bit(chip, MV88E6352_G2_AVB_CMD, bit, 0);
+}
+
static int mv88e6xxx_g2_avb_read(struct mv88e6xxx_chip *chip, u16 readop,
u16 *data, int len)
{
int err;
int i;
+ err = mv88e6xxx_g2_avb_wait(chip);
+ if (err)
+ return err;
+
/* Hardware can only snapshot four words. */
if (len > 4)
return -E2BIG;
- err = mv88e6xxx_g2_update(chip, MV88E6352_G2_AVB_CMD, readop);
+ err = mv88e6xxx_g2_write(chip, MV88E6352_G2_AVB_CMD,
+ MV88E6352_G2_AVB_CMD_BUSY | readop);
+ if (err)
+ return err;
+
+ err = mv88e6xxx_g2_avb_wait(chip);
if (err)
return err;
@@ -57,11 +75,18 @@ static int mv88e6xxx_g2_avb_write(struct mv88e6xxx_chip *chip, u16 writeop,
{
int err;
+ err = mv88e6xxx_g2_avb_wait(chip);
+ if (err)
+ return err;
+
err = mv88e6xxx_g2_write(chip, MV88E6352_G2_AVB_DATA, data);
if (err)
return err;
- return mv88e6xxx_g2_update(chip, MV88E6352_G2_AVB_CMD, writeop);
+ err = mv88e6xxx_g2_write(chip, MV88E6352_G2_AVB_CMD,
+ MV88E6352_G2_AVB_CMD_BUSY | writeop);
+
+ return mv88e6xxx_g2_avb_wait(chip);
}
static int mv88e6352_g2_avb_port_ptp_read(struct mv88e6xxx_chip *chip,
--
2.22.0
^ permalink raw reply related
* [PATCH net-next 5/7] net: dsa: mv88e6xxx: remove wait and update routines
From: Vivien Didelot @ 2019-08-09 22:47 UTC (permalink / raw)
To: netdev; +Cc: davem, f.fainelli, andrew, Vivien Didelot
In-Reply-To: <20190809224759.5743-1-vivien.didelot@gmail.com>
Now that we have proper Wait Bit and Wait Mask routines, remove the
unused mv88e6xxx_wait routine and its Global 1 and Global 2 variants.
The indirect tables such as the Device Mapping Table or Priority
Override Table make use of an Update bit to distinguish reading (0)
from writing (1) operations. After a write operation occurs, the bit
self clears right away so there's no need to wait on it. Thus keep
things simple and remove the mv88e6xxx_update helper as well.
Signed-off-by: Vivien Didelot <vivien.didelot@gmail.com>
---
drivers/net/dsa/mv88e6xxx/chip.c | 22 -----------
drivers/net/dsa/mv88e6xxx/chip.h | 3 --
drivers/net/dsa/mv88e6xxx/global1.c | 5 ---
drivers/net/dsa/mv88e6xxx/global1.h | 1 -
drivers/net/dsa/mv88e6xxx/global2.c | 43 ++++++++++-----------
drivers/net/dsa/mv88e6xxx/global2.h | 12 ------
drivers/net/dsa/mv88e6xxx/global2_scratch.c | 3 +-
7 files changed, 22 insertions(+), 67 deletions(-)
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index b7e0513c675a..818a83eb2dcb 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -394,28 +394,6 @@ static void mv88e6xxx_irq_poll_free(struct mv88e6xxx_chip *chip)
mv88e6xxx_reg_unlock(chip);
}
-int mv88e6xxx_wait(struct mv88e6xxx_chip *chip, int addr, int reg, u16 mask)
-{
- return mv88e6xxx_wait_mask(chip, addr, reg, mask, 0x0000);
-}
-
-/* Indirect write to single pointer-data register with an Update bit */
-int mv88e6xxx_update(struct mv88e6xxx_chip *chip, int addr, int reg, u16 update)
-{
- u16 val;
- int err;
-
- /* Wait until the previous operation is completed */
- err = mv88e6xxx_wait(chip, addr, reg, BIT(15));
- if (err)
- return err;
-
- /* Set the Update bit to trigger a write operation */
- val = BIT(15) | update;
-
- return mv88e6xxx_write(chip, addr, reg, val);
-}
-
int mv88e6xxx_port_setup_mac(struct mv88e6xxx_chip *chip, int port, int link,
int speed, int duplex, int pause,
phy_interface_t mode)
diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h
index 9cdb6bfead25..a406be2f5652 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.h
+++ b/drivers/net/dsa/mv88e6xxx/chip.h
@@ -590,11 +590,8 @@ int mv88e6xxx_read(struct mv88e6xxx_chip *chip, int addr, int reg, u16 *val);
int mv88e6xxx_write(struct mv88e6xxx_chip *chip, int addr, int reg, u16 val);
int mv88e6xxx_wait_mask(struct mv88e6xxx_chip *chip, int addr, int reg,
u16 mask, u16 val);
-int mv88e6xxx_update(struct mv88e6xxx_chip *chip, int addr, int reg,
- u16 update);
int mv88e6xxx_wait_bit(struct mv88e6xxx_chip *chip, int addr, int reg,
int bit, int val);
-int mv88e6xxx_wait(struct mv88e6xxx_chip *chip, int addr, int reg, u16 mask);
int mv88e6xxx_port_setup_mac(struct mv88e6xxx_chip *chip, int port, int link,
int speed, int duplex, int pause,
phy_interface_t mode);
diff --git a/drivers/net/dsa/mv88e6xxx/global1.c b/drivers/net/dsa/mv88e6xxx/global1.c
index 5ace6490695b..25ec4c0ac589 100644
--- a/drivers/net/dsa/mv88e6xxx/global1.c
+++ b/drivers/net/dsa/mv88e6xxx/global1.c
@@ -27,11 +27,6 @@ int mv88e6xxx_g1_write(struct mv88e6xxx_chip *chip, int reg, u16 val)
return mv88e6xxx_write(chip, addr, reg, val);
}
-int mv88e6xxx_g1_wait(struct mv88e6xxx_chip *chip, int reg, u16 mask)
-{
- return mv88e6xxx_wait(chip, chip->info->global1_addr, reg, mask);
-}
-
int mv88e6xxx_g1_wait_bit(struct mv88e6xxx_chip *chip, int reg, int
bit, int val)
{
diff --git a/drivers/net/dsa/mv88e6xxx/global1.h b/drivers/net/dsa/mv88e6xxx/global1.h
index ffa11749fecb..78b9ae22d18c 100644
--- a/drivers/net/dsa/mv88e6xxx/global1.h
+++ b/drivers/net/dsa/mv88e6xxx/global1.h
@@ -249,7 +249,6 @@
int mv88e6xxx_g1_read(struct mv88e6xxx_chip *chip, int reg, u16 *val);
int mv88e6xxx_g1_write(struct mv88e6xxx_chip *chip, int reg, u16 val);
-int mv88e6xxx_g1_wait(struct mv88e6xxx_chip *chip, int reg, u16 mask);
int mv88e6xxx_g1_wait_bit(struct mv88e6xxx_chip *chip, int reg, int
bit, int val);
int mv88e6xxx_g1_wait_mask(struct mv88e6xxx_chip *chip, int reg,
diff --git a/drivers/net/dsa/mv88e6xxx/global2.c b/drivers/net/dsa/mv88e6xxx/global2.c
index b5acf45f30cb..bdbb72fc20ed 100644
--- a/drivers/net/dsa/mv88e6xxx/global2.c
+++ b/drivers/net/dsa/mv88e6xxx/global2.c
@@ -26,16 +26,6 @@ int mv88e6xxx_g2_write(struct mv88e6xxx_chip *chip, int reg, u16 val)
return mv88e6xxx_write(chip, chip->info->global2_addr, reg, val);
}
-int mv88e6xxx_g2_update(struct mv88e6xxx_chip *chip, int reg, u16 update)
-{
- return mv88e6xxx_update(chip, chip->info->global2_addr, reg, update);
-}
-
-int mv88e6xxx_g2_wait(struct mv88e6xxx_chip *chip, int reg, u16 mask)
-{
- return mv88e6xxx_wait(chip, chip->info->global2_addr, reg, mask);
-}
-
int mv88e6xxx_g2_wait_bit(struct mv88e6xxx_chip *chip, int reg, int
bit, int val)
{
@@ -130,7 +120,8 @@ int mv88e6xxx_g2_device_mapping_write(struct mv88e6xxx_chip *chip, int target,
* but bit 4 is reserved on older chips, so it is safe to use.
*/
- return mv88e6xxx_g2_update(chip, MV88E6XXX_G2_DEVICE_MAPPING, val);
+ return mv88e6xxx_g2_write(chip, MV88E6XXX_G2_DEVICE_MAPPING,
+ MV88E6XXX_G2_DEVICE_MAPPING_UPDATE | val);
}
/* Offset 0x07: Trunk Mask Table register */
@@ -143,7 +134,8 @@ static int mv88e6xxx_g2_trunk_mask_write(struct mv88e6xxx_chip *chip, int num,
if (hash)
val |= MV88E6XXX_G2_TRUNK_MASK_HASH;
- return mv88e6xxx_g2_update(chip, MV88E6XXX_G2_TRUNK_MASK, val);
+ return mv88e6xxx_g2_write(chip, MV88E6XXX_G2_TRUNK_MASK,
+ MV88E6XXX_G2_TRUNK_MASK_UPDATE | val);
}
/* Offset 0x08: Trunk Mapping Table register */
@@ -154,7 +146,8 @@ static int mv88e6xxx_g2_trunk_mapping_write(struct mv88e6xxx_chip *chip, int id,
const u16 port_mask = BIT(mv88e6xxx_num_ports(chip)) - 1;
u16 val = (id << 11) | (map & port_mask);
- return mv88e6xxx_g2_update(chip, MV88E6XXX_G2_TRUNK_MAPPING, val);
+ return mv88e6xxx_g2_write(chip, MV88E6XXX_G2_TRUNK_MAPPING,
+ MV88E6XXX_G2_TRUNK_MAPPING_UPDATE | val);
}
int mv88e6xxx_g2_trunk_clear(struct mv88e6xxx_chip *chip)
@@ -270,7 +263,8 @@ static int mv88e6xxx_g2_switch_mac_write(struct mv88e6xxx_chip *chip,
{
u16 val = (pointer << 8) | data;
- return mv88e6xxx_g2_update(chip, MV88E6XXX_G2_SWITCH_MAC, val);
+ return mv88e6xxx_g2_write(chip, MV88E6XXX_G2_SWITCH_MAC,
+ MV88E6XXX_G2_SWITCH_MAC_UPDATE | val);
}
int mv88e6xxx_g2_set_switch_mac(struct mv88e6xxx_chip *chip, u8 *addr)
@@ -293,7 +287,8 @@ static int mv88e6xxx_g2_pot_write(struct mv88e6xxx_chip *chip, int pointer,
{
u16 val = (pointer << 8) | (data & 0x7);
- return mv88e6xxx_g2_update(chip, MV88E6XXX_G2_PRIO_OVERRIDE, val);
+ return mv88e6xxx_g2_write(chip, MV88E6XXX_G2_PRIO_OVERRIDE,
+ MV88E6XXX_G2_PRIO_OVERRIDE_UPDATE | val);
}
int mv88e6xxx_g2_pot_clear(struct mv88e6xxx_chip *chip)
@@ -857,12 +852,13 @@ const struct mv88e6xxx_irq_ops mv88e6250_watchdog_ops = {
static int mv88e6390_watchdog_setup(struct mv88e6xxx_chip *chip)
{
- return mv88e6xxx_g2_update(chip, MV88E6390_G2_WDOG_CTL,
- MV88E6390_G2_WDOG_CTL_PTR_INT_ENABLE |
- MV88E6390_G2_WDOG_CTL_CUT_THROUGH |
- MV88E6390_G2_WDOG_CTL_QUEUE_CONTROLLER |
- MV88E6390_G2_WDOG_CTL_EGRESS |
- MV88E6390_G2_WDOG_CTL_FORCE_IRQ);
+ return mv88e6xxx_g2_write(chip, MV88E6390_G2_WDOG_CTL,
+ MV88E6390_G2_WDOG_CTL_UPDATE |
+ MV88E6390_G2_WDOG_CTL_PTR_INT_ENABLE |
+ MV88E6390_G2_WDOG_CTL_CUT_THROUGH |
+ MV88E6390_G2_WDOG_CTL_QUEUE_CONTROLLER |
+ MV88E6390_G2_WDOG_CTL_EGRESS |
+ MV88E6390_G2_WDOG_CTL_FORCE_IRQ);
}
static int mv88e6390_watchdog_action(struct mv88e6xxx_chip *chip, int irq)
@@ -895,8 +891,9 @@ static int mv88e6390_watchdog_action(struct mv88e6xxx_chip *chip, int irq)
static void mv88e6390_watchdog_free(struct mv88e6xxx_chip *chip)
{
- mv88e6xxx_g2_update(chip, MV88E6390_G2_WDOG_CTL,
- MV88E6390_G2_WDOG_CTL_PTR_INT_ENABLE);
+ mv88e6xxx_g2_write(chip, MV88E6390_G2_WDOG_CTL,
+ MV88E6390_G2_WDOG_CTL_UPDATE |
+ MV88E6390_G2_WDOG_CTL_PTR_INT_ENABLE);
}
const struct mv88e6xxx_irq_ops mv88e6390_watchdog_ops = {
diff --git a/drivers/net/dsa/mv88e6xxx/global2.h b/drivers/net/dsa/mv88e6xxx/global2.h
index f5574e463a92..42da4bca73e8 100644
--- a/drivers/net/dsa/mv88e6xxx/global2.h
+++ b/drivers/net/dsa/mv88e6xxx/global2.h
@@ -295,8 +295,6 @@ static inline int mv88e6xxx_g2_require(struct mv88e6xxx_chip *chip)
int mv88e6xxx_g2_read(struct mv88e6xxx_chip *chip, int reg, u16 *val);
int mv88e6xxx_g2_write(struct mv88e6xxx_chip *chip, int reg, u16 val);
-int mv88e6xxx_g2_update(struct mv88e6xxx_chip *chip, int reg, u16 update);
-int mv88e6xxx_g2_wait(struct mv88e6xxx_chip *chip, int reg, u16 mask);
int mv88e6xxx_g2_wait_bit(struct mv88e6xxx_chip *chip, int reg,
int bit, int val);
@@ -378,16 +376,6 @@ static inline int mv88e6xxx_g2_write(struct mv88e6xxx_chip *chip, int reg, u16 v
return -EOPNOTSUPP;
}
-static inline int mv88e6xxx_g2_update(struct mv88e6xxx_chip *chip, int reg, u16 update)
-{
- return -EOPNOTSUPP;
-}
-
-static inline int mv88e6xxx_g2_wait(struct mv88e6xxx_chip *chip, int reg, u16 mask)
-{
- return -EOPNOTSUPP;
-}
-
static inline int mv88e6xxx_g2_wait_bit(struct mv88e6xxx_chip *chip,
int reg, int bit, int val)
{
diff --git a/drivers/net/dsa/mv88e6xxx/global2_scratch.c b/drivers/net/dsa/mv88e6xxx/global2_scratch.c
index baddecadd8be..33b7b9570d29 100644
--- a/drivers/net/dsa/mv88e6xxx/global2_scratch.c
+++ b/drivers/net/dsa/mv88e6xxx/global2_scratch.c
@@ -37,7 +37,8 @@ static int mv88e6xxx_g2_scratch_write(struct mv88e6xxx_chip *chip, int reg,
{
u16 value = (reg << 8) | data;
- return mv88e6xxx_g2_update(chip, MV88E6XXX_G2_SCRATCH_MISC_MISC, value);
+ return mv88e6xxx_g2_write(chip, MV88E6XXX_G2_SCRATCH_MISC_MISC,
+ MV88E6XXX_G2_SCRATCH_MISC_UPDATE | value);
}
/**
--
2.22.0
^ permalink raw reply related
* [PATCH net-next 6/7] net: dsa: mv88e6xxx: fix SMI bit checking
From: Vivien Didelot @ 2019-08-09 22:47 UTC (permalink / raw)
To: netdev; +Cc: davem, f.fainelli, andrew, Vivien Didelot
In-Reply-To: <20190809224759.5743-1-vivien.didelot@gmail.com>
The current mv88e6xxx_smi_direct_wait function is only used to check
the 16th bit of the (16-bit) SMI Command register. But the bit shift
operation is not enough if we eventually use this function to check
other bits, thus replace it with a mask.
Fixes: e7ba0fad9c53 ("net: dsa: mv88e6xxx: refine SMI support")
Signed-off-by: Vivien Didelot <vivien.didelot@gmail.com>
---
drivers/net/dsa/mv88e6xxx/smi.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/dsa/mv88e6xxx/smi.c b/drivers/net/dsa/mv88e6xxx/smi.c
index 5fc78a063843..18e87a5a20a3 100644
--- a/drivers/net/dsa/mv88e6xxx/smi.c
+++ b/drivers/net/dsa/mv88e6xxx/smi.c
@@ -64,7 +64,7 @@ static int mv88e6xxx_smi_direct_wait(struct mv88e6xxx_chip *chip,
if (err)
return err;
- if (!!(data >> bit) == !!val)
+ if (!!(data & BIT(bit)) == !!val)
return 0;
}
--
2.22.0
^ permalink raw reply related
* [PATCH net-next 7/7] net: dsa: mv88e6xxx: add delay in direct SMI wait
From: Vivien Didelot @ 2019-08-09 22:47 UTC (permalink / raw)
To: netdev; +Cc: davem, f.fainelli, andrew, Vivien Didelot
In-Reply-To: <20190809224759.5743-1-vivien.didelot@gmail.com>
The mv88e6xxx_smi_direct_wait routine is used to wait on indirect
registers access. It is of no exception and must delay between read
attempts, like other wait routines.
Signed-off-by: Vivien Didelot <vivien.didelot@gmail.com>
---
drivers/net/dsa/mv88e6xxx/smi.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/net/dsa/mv88e6xxx/smi.c b/drivers/net/dsa/mv88e6xxx/smi.c
index 18e87a5a20a3..282fe08db050 100644
--- a/drivers/net/dsa/mv88e6xxx/smi.c
+++ b/drivers/net/dsa/mv88e6xxx/smi.c
@@ -66,6 +66,8 @@ static int mv88e6xxx_smi_direct_wait(struct mv88e6xxx_chip *chip,
if (!!(data & BIT(bit)) == !!val)
return 0;
+
+ usleep_range(1000, 2000);
}
return -ETIMEDOUT;
--
2.22.0
^ permalink raw reply related
* [PATCH net-next 3/7] net: dsa: mv88e6xxx: introduce wait bit routine
From: Vivien Didelot @ 2019-08-09 22:47 UTC (permalink / raw)
To: netdev; +Cc: davem, f.fainelli, andrew, Vivien Didelot
In-Reply-To: <20190809224759.5743-1-vivien.didelot@gmail.com>
Many portions of the driver need to wait until a given bit is set
or cleared. Some busses even have a specific implementation for this
operation. In preparation for such variant, implement a generic Wait
Bit routine that can be used by the driver core functions.
This allows us to get rid of the custom implementations we may find
in the driver. Note that for the EEPROM bits, BUSY and RUNNING bits
are independent, thus it is more efficient to wait independently for
each bit instead of waiting for their mask.
Signed-off-by: Vivien Didelot <vivien.didelot@gmail.com>
---
drivers/net/dsa/mv88e6xxx/chip.c | 14 ++++++-
drivers/net/dsa/mv88e6xxx/chip.h | 2 +
drivers/net/dsa/mv88e6xxx/global1.c | 49 +++++++------------------
drivers/net/dsa/mv88e6xxx/global1.h | 2 +
drivers/net/dsa/mv88e6xxx/global1_atu.c | 7 +++-
drivers/net/dsa/mv88e6xxx/global1_vtu.c | 6 ++-
drivers/net/dsa/mv88e6xxx/global2.c | 35 +++++++++++++-----
drivers/net/dsa/mv88e6xxx/global2.h | 8 ++++
8 files changed, 73 insertions(+), 50 deletions(-)
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index bd61d0d3a245..b7e0513c675a 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -10,6 +10,7 @@
* Vivien Didelot <vivien.didelot@savoirfairelinux.com>
*/
+#include <linux/bitfield.h>
#include <linux/delay.h>
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
@@ -103,6 +104,13 @@ int mv88e6xxx_wait_mask(struct mv88e6xxx_chip *chip, int addr, int reg,
return -ETIMEDOUT;
}
+int mv88e6xxx_wait_bit(struct mv88e6xxx_chip *chip, int addr, int reg,
+ int bit, int val)
+{
+ return mv88e6xxx_wait_mask(chip, addr, reg, BIT(bit),
+ val ? BIT(bit) : 0x0000);
+}
+
struct mii_bus *mv88e6xxx_default_mdio_bus(struct mv88e6xxx_chip *chip)
{
struct mv88e6xxx_mdio_bus *mdio_bus;
@@ -2360,8 +2368,10 @@ static int mv88e6390_hidden_write(struct mv88e6xxx_chip *chip, int port,
static int mv88e6390_hidden_wait(struct mv88e6xxx_chip *chip)
{
- return mv88e6xxx_wait(chip, PORT_RESERVED_1A_CTRL_PORT,
- PORT_RESERVED_1A, PORT_RESERVED_1A_BUSY);
+ int bit = __bf_shf(PORT_RESERVED_1A_BUSY);
+
+ return mv88e6xxx_wait_bit(chip, PORT_RESERVED_1A_CTRL_PORT,
+ PORT_RESERVED_1A, bit, 0);
}
diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h
index 95b44532a282..9cdb6bfead25 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.h
+++ b/drivers/net/dsa/mv88e6xxx/chip.h
@@ -592,6 +592,8 @@ int mv88e6xxx_wait_mask(struct mv88e6xxx_chip *chip, int addr, int reg,
u16 mask, u16 val);
int mv88e6xxx_update(struct mv88e6xxx_chip *chip, int addr, int reg,
u16 update);
+int mv88e6xxx_wait_bit(struct mv88e6xxx_chip *chip, int addr, int reg,
+ int bit, int val);
int mv88e6xxx_wait(struct mv88e6xxx_chip *chip, int addr, int reg, u16 mask);
int mv88e6xxx_port_setup_mac(struct mv88e6xxx_chip *chip, int port, int link,
int speed, int duplex, int pause,
diff --git a/drivers/net/dsa/mv88e6xxx/global1.c b/drivers/net/dsa/mv88e6xxx/global1.c
index 482f9f8465af..5ace6490695b 100644
--- a/drivers/net/dsa/mv88e6xxx/global1.c
+++ b/drivers/net/dsa/mv88e6xxx/global1.c
@@ -32,6 +32,13 @@ int mv88e6xxx_g1_wait(struct mv88e6xxx_chip *chip, int reg, u16 mask)
return mv88e6xxx_wait(chip, chip->info->global1_addr, reg, mask);
}
+int mv88e6xxx_g1_wait_bit(struct mv88e6xxx_chip *chip, int reg, int
+ bit, int val)
+{
+ return mv88e6xxx_wait_bit(chip, chip->info->global1_addr, reg,
+ bit, val);
+}
+
int mv88e6xxx_g1_wait_mask(struct mv88e6xxx_chip *chip, int reg,
u16 mask, u16 val)
{
@@ -57,49 +64,20 @@ static int mv88e6185_g1_wait_ppu_polling(struct mv88e6xxx_chip *chip)
static int mv88e6352_g1_wait_ppu_polling(struct mv88e6xxx_chip *chip)
{
- u16 state;
- int i, err;
+ int bit = __bf_shf(MV88E6352_G1_STS_PPU_STATE);
- for (i = 0; i < 16; ++i) {
- err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STS, &state);
- if (err)
- return err;
-
- /* Check the value of the PPUState (or InitState) bit 15 */
- if (state & MV88E6352_G1_STS_PPU_STATE)
- return 0;
-
- usleep_range(1000, 2000);
- }
-
- return -ETIMEDOUT;
+ return mv88e6xxx_g1_wait_bit(chip, MV88E6XXX_G1_STS, bit, 1);
}
static int mv88e6xxx_g1_wait_init_ready(struct mv88e6xxx_chip *chip)
{
- const unsigned long timeout = jiffies + 1 * HZ;
- u16 val;
- int err;
+ int bit = __bf_shf(MV88E6XXX_G1_STS_INIT_READY);
/* Wait up to 1 second for the switch to be ready. The InitReady bit 11
* is set to a one when all units inside the device (ATU, VTU, etc.)
* have finished their initialization and are ready to accept frames.
*/
- while (time_before(jiffies, timeout)) {
- err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STS, &val);
- if (err)
- return err;
-
- if (val & MV88E6XXX_G1_STS_INIT_READY)
- break;
-
- usleep_range(1000, 2000);
- }
-
- if (time_after(jiffies, timeout))
- return -ETIMEDOUT;
-
- return 0;
+ return mv88e6xxx_g1_wait_bit(chip, MV88E6XXX_G1_STS, bit, 1);
}
/* Offset 0x01: Switch MAC Address Register Bytes 0 & 1
@@ -455,8 +433,9 @@ int mv88e6xxx_g1_set_device_number(struct mv88e6xxx_chip *chip, int index)
static int mv88e6xxx_g1_stats_wait(struct mv88e6xxx_chip *chip)
{
- return mv88e6xxx_g1_wait(chip, MV88E6XXX_G1_STATS_OP,
- MV88E6XXX_G1_STATS_OP_BUSY);
+ int bit = __bf_shf(MV88E6XXX_G1_STATS_OP_BUSY);
+
+ return mv88e6xxx_g1_wait_bit(chip, MV88E6XXX_G1_STATS_OP, bit, 0);
}
int mv88e6095_g1_stats_set_histogram(struct mv88e6xxx_chip *chip)
diff --git a/drivers/net/dsa/mv88e6xxx/global1.h b/drivers/net/dsa/mv88e6xxx/global1.h
index 48869d7984f4..ffa11749fecb 100644
--- a/drivers/net/dsa/mv88e6xxx/global1.h
+++ b/drivers/net/dsa/mv88e6xxx/global1.h
@@ -250,6 +250,8 @@
int mv88e6xxx_g1_read(struct mv88e6xxx_chip *chip, int reg, u16 *val);
int mv88e6xxx_g1_write(struct mv88e6xxx_chip *chip, int reg, u16 val);
int mv88e6xxx_g1_wait(struct mv88e6xxx_chip *chip, int reg, u16 mask);
+int mv88e6xxx_g1_wait_bit(struct mv88e6xxx_chip *chip, int reg, int
+ bit, int val);
int mv88e6xxx_g1_wait_mask(struct mv88e6xxx_chip *chip, int reg,
u16 mask, u16 val);
diff --git a/drivers/net/dsa/mv88e6xxx/global1_atu.c b/drivers/net/dsa/mv88e6xxx/global1_atu.c
index 1cf388e9bd94..18b86515b6bc 100644
--- a/drivers/net/dsa/mv88e6xxx/global1_atu.c
+++ b/drivers/net/dsa/mv88e6xxx/global1_atu.c
@@ -5,6 +5,8 @@
* Copyright (c) 2008 Marvell Semiconductor
* Copyright (c) 2017 Savoir-faire Linux, Inc.
*/
+
+#include <linux/bitfield.h>
#include <linux/interrupt.h>
#include <linux/irqdomain.h>
@@ -75,8 +77,9 @@ int mv88e6xxx_g1_atu_set_age_time(struct mv88e6xxx_chip *chip,
static int mv88e6xxx_g1_atu_op_wait(struct mv88e6xxx_chip *chip)
{
- return mv88e6xxx_g1_wait(chip, MV88E6XXX_G1_ATU_OP,
- MV88E6XXX_G1_ATU_OP_BUSY);
+ int bit = __bf_shf(MV88E6XXX_G1_ATU_OP_BUSY);
+
+ return mv88e6xxx_g1_wait_bit(chip, MV88E6XXX_G1_ATU_OP, bit, 0);
}
static int mv88e6xxx_g1_atu_op(struct mv88e6xxx_chip *chip, u16 fid, u16 op)
diff --git a/drivers/net/dsa/mv88e6xxx/global1_vtu.c b/drivers/net/dsa/mv88e6xxx/global1_vtu.c
index 6cac997360e8..33056a609e96 100644
--- a/drivers/net/dsa/mv88e6xxx/global1_vtu.c
+++ b/drivers/net/dsa/mv88e6xxx/global1_vtu.c
@@ -7,6 +7,7 @@
* Copyright (c) 2017 Savoir-faire Linux, Inc.
*/
+#include <linux/bitfield.h>
#include <linux/interrupt.h>
#include <linux/irqdomain.h>
@@ -67,8 +68,9 @@ static int mv88e6xxx_g1_vtu_sid_write(struct mv88e6xxx_chip *chip,
static int mv88e6xxx_g1_vtu_op_wait(struct mv88e6xxx_chip *chip)
{
- return mv88e6xxx_g1_wait(chip, MV88E6XXX_G1_VTU_OP,
- MV88E6XXX_G1_VTU_OP_BUSY);
+ int bit = __bf_shf(MV88E6XXX_G1_VTU_OP_BUSY);
+
+ return mv88e6xxx_g1_wait_bit(chip, MV88E6XXX_G1_VTU_OP, bit, 0);
}
static int mv88e6xxx_g1_vtu_op(struct mv88e6xxx_chip *chip, u16 op)
diff --git a/drivers/net/dsa/mv88e6xxx/global2.c b/drivers/net/dsa/mv88e6xxx/global2.c
index 2305b94b3051..b5acf45f30cb 100644
--- a/drivers/net/dsa/mv88e6xxx/global2.c
+++ b/drivers/net/dsa/mv88e6xxx/global2.c
@@ -36,6 +36,13 @@ int mv88e6xxx_g2_wait(struct mv88e6xxx_chip *chip, int reg, u16 mask)
return mv88e6xxx_wait(chip, chip->info->global2_addr, reg, mask);
}
+int mv88e6xxx_g2_wait_bit(struct mv88e6xxx_chip *chip, int reg, int
+ bit, int val)
+{
+ return mv88e6xxx_wait_bit(chip, chip->info->global2_addr, reg,
+ bit, val);
+}
+
/* Offset 0x00: Interrupt Source Register */
static int mv88e6xxx_g2_int_source(struct mv88e6xxx_chip *chip, u16 *src)
@@ -178,8 +185,9 @@ int mv88e6xxx_g2_trunk_clear(struct mv88e6xxx_chip *chip)
static int mv88e6xxx_g2_irl_wait(struct mv88e6xxx_chip *chip)
{
- return mv88e6xxx_g2_wait(chip, MV88E6XXX_G2_IRL_CMD,
- MV88E6XXX_G2_IRL_CMD_BUSY);
+ int bit = __bf_shf(MV88E6XXX_G2_IRL_CMD_BUSY);
+
+ return mv88e6xxx_g2_wait_bit(chip, MV88E6XXX_G2_IRL_CMD, bit, 0);
}
static int mv88e6xxx_g2_irl_op(struct mv88e6xxx_chip *chip, u16 op, int port,
@@ -214,8 +222,9 @@ int mv88e6390_g2_irl_init_all(struct mv88e6xxx_chip *chip, int port)
static int mv88e6xxx_g2_pvt_op_wait(struct mv88e6xxx_chip *chip)
{
- return mv88e6xxx_g2_wait(chip, MV88E6XXX_G2_PVT_ADDR,
- MV88E6XXX_G2_PVT_ADDR_BUSY);
+ int bit = __bf_shf(MV88E6XXX_G2_PVT_ADDR_BUSY);
+
+ return mv88e6xxx_g2_wait_bit(chip, MV88E6XXX_G2_PVT_ADDR, bit, 0);
}
static int mv88e6xxx_g2_pvt_op(struct mv88e6xxx_chip *chip, int src_dev,
@@ -308,9 +317,16 @@ int mv88e6xxx_g2_pot_clear(struct mv88e6xxx_chip *chip)
static int mv88e6xxx_g2_eeprom_wait(struct mv88e6xxx_chip *chip)
{
- return mv88e6xxx_g2_wait(chip, MV88E6XXX_G2_EEPROM_CMD,
- MV88E6XXX_G2_EEPROM_CMD_BUSY |
- MV88E6XXX_G2_EEPROM_CMD_RUNNING);
+ int bit = __bf_shf(MV88E6XXX_G2_EEPROM_CMD_BUSY);
+ int err;
+
+ err = mv88e6xxx_g2_wait_bit(chip, MV88E6XXX_G2_EEPROM_CMD, bit, 0);
+ if (err)
+ return err;
+
+ bit = __bf_shf(MV88E6XXX_G2_EEPROM_CMD_RUNNING);
+
+ return mv88e6xxx_g2_wait_bit(chip, MV88E6XXX_G2_EEPROM_CMD, bit, 0);
}
static int mv88e6xxx_g2_eeprom_cmd(struct mv88e6xxx_chip *chip, u16 cmd)
@@ -572,8 +588,9 @@ int mv88e6xxx_g2_set_eeprom16(struct mv88e6xxx_chip *chip,
static int mv88e6xxx_g2_smi_phy_wait(struct mv88e6xxx_chip *chip)
{
- return mv88e6xxx_g2_wait(chip, MV88E6XXX_G2_SMI_PHY_CMD,
- MV88E6XXX_G2_SMI_PHY_CMD_BUSY);
+ int bit = __bf_shf(MV88E6XXX_G2_SMI_PHY_CMD_BUSY);
+
+ return mv88e6xxx_g2_wait_bit(chip, MV88E6XXX_G2_SMI_PHY_CMD, bit, 0);
}
static int mv88e6xxx_g2_smi_phy_cmd(struct mv88e6xxx_chip *chip, u16 cmd)
diff --git a/drivers/net/dsa/mv88e6xxx/global2.h b/drivers/net/dsa/mv88e6xxx/global2.h
index a664fc25f132..f5574e463a92 100644
--- a/drivers/net/dsa/mv88e6xxx/global2.h
+++ b/drivers/net/dsa/mv88e6xxx/global2.h
@@ -297,6 +297,8 @@ int mv88e6xxx_g2_read(struct mv88e6xxx_chip *chip, int reg, u16 *val);
int mv88e6xxx_g2_write(struct mv88e6xxx_chip *chip, int reg, u16 val);
int mv88e6xxx_g2_update(struct mv88e6xxx_chip *chip, int reg, u16 update);
int mv88e6xxx_g2_wait(struct mv88e6xxx_chip *chip, int reg, u16 mask);
+int mv88e6xxx_g2_wait_bit(struct mv88e6xxx_chip *chip, int reg,
+ int bit, int val);
int mv88e6352_g2_irl_init_all(struct mv88e6xxx_chip *chip, int port);
int mv88e6390_g2_irl_init_all(struct mv88e6xxx_chip *chip, int port);
@@ -386,6 +388,12 @@ static inline int mv88e6xxx_g2_wait(struct mv88e6xxx_chip *chip, int reg, u16 ma
return -EOPNOTSUPP;
}
+static inline int mv88e6xxx_g2_wait_bit(struct mv88e6xxx_chip *chip,
+ int reg, int bit, int val)
+{
+ return -EOPNOTSUPP;
+}
+
static inline int mv88e6352_g2_irl_init_all(struct mv88e6xxx_chip *chip,
int port)
{
--
2.22.0
^ permalink raw reply related
* Re: [PATCH net-next v2 4/4] net: phy: realtek: add support for the 2.5Gbps PHY in RTL8125
From: Andrew Lunn @ 2019-08-09 22:54 UTC (permalink / raw)
To: Heiner Kallweit; +Cc: Florian Fainelli, David Miller, netdev@vger.kernel.org
In-Reply-To: <c8e2b3e7-1d0b-eba3-6a36-8808641f3031@gmail.com>
On Fri, Aug 09, 2019 at 09:31:32PM +0200, Heiner Kallweit wrote:
> On 09.08.2019 21:18, Andrew Lunn wrote:
> >> + }, {
> >> + PHY_ID_MATCH_EXACT(0x001cca50),
> >
> > Hi Heiner
> >
> Hi Andrew,
>
> > With the Marvell driver, i looked at the range of IDs the PHYs where
> > using. The switch, being MDIO based, also has ID values. The PHY range
> > and the switch range are well separated, and it seems unlikely Marvell
> > would reuse a switch ID in a PHY which was not compatible with the
> > PHY.
> >
> > Could you explain why you picked this value for the PHY? What makes
> > you think it is not in use by another Realtek PHY?
> >
> 0x001cc800 being the Realtek OUI, I've seen only PHY's with ID
> 0x001cc8XX and 0x001cc9XX so far. Realtek doesn't seem to have such
> a clear separation between PHY and switch PHY ID's.
>
> Example:
> 0x001cc961 (RTL8366, switch)
> 0x001cc916 (RTL8211F, PHY)
>
> Last digit of the model is used as model number.
> I did the same and used 5 as model number (from RTL8125).
> Revision number is set to 0 because RTL8125 is brand-new.
>
> I chose a PHY ID in 0x001ccaXX range because it isn't used by
> Realtek AFAIK.
Hi Heiner
O.K.
This should also be something which is internal. If Realtek do happen
to use the ID, we can change both the MAC and the PHY to an new ID to
avoid the collision.
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Andrew
^ permalink raw reply
* [PATCH net-next] selftests: Fix detection of nettest command in fcnal-test
From: David Ahern @ 2019-08-09 23:13 UTC (permalink / raw)
To: davem; +Cc: netdev, David Ahern
From: David Ahern <dsahern@gmail.com>
Most of the tests run by fcnal-test.sh relies on the nettest command.
Rather than trying to cover all of the individual tests, check for the
binary only at the beginning.
Also removes the need for log_error which is undefined.
Fixes: 6f9d5cacfe07 ("selftests: Setup for functional tests for fib and socket lookups")
Signed-off-by: David Ahern <dsahern@gmail.com>
---
tools/testing/selftests/net/fcnal-test.sh | 38 +++++--------------------------
1 file changed, 6 insertions(+), 32 deletions(-)
diff --git a/tools/testing/selftests/net/fcnal-test.sh b/tools/testing/selftests/net/fcnal-test.sh
index bd6b564382ec..9fd3a0b97f0d 100755
--- a/tools/testing/selftests/net/fcnal-test.sh
+++ b/tools/testing/selftests/net/fcnal-test.sh
@@ -998,13 +998,6 @@ ipv4_tcp_vrf()
ipv4_tcp()
{
log_section "IPv4/TCP"
-
- which nettest >/dev/null
- if [ $? -ne 0 ]; then
- log_error "nettest not found; skipping tests"
- return
- fi
-
log_subsection "No VRF"
setup
@@ -1375,12 +1368,6 @@ ipv4_udp_vrf()
ipv4_udp()
{
- which nettest >/dev/null
- if [ $? -ne 0 ]; then
- log_error "nettest not found; skipping tests"
- return
- fi
-
log_section "IPv4/UDP"
log_subsection "No VRF"
@@ -2314,13 +2301,6 @@ ipv6_tcp_vrf()
ipv6_tcp()
{
log_section "IPv6/TCP"
-
- which nettest >/dev/null
- if [ $? -ne 0 ]; then
- log_error "nettest not found; skipping tests"
- return
- fi
-
log_subsection "No VRF"
setup
@@ -3156,12 +3136,6 @@ netfilter_icmp()
ipv4_netfilter()
{
- which nettest >/dev/null
- if [ $? -ne 0 ]; then
- log_error "nettest not found; skipping tests"
- return
- fi
-
log_section "IPv4 Netfilter"
log_subsection "TCP reset"
@@ -3219,12 +3193,6 @@ netfilter_icmp6()
ipv6_netfilter()
{
- which nettest >/dev/null
- if [ $? -ne 0 ]; then
- log_error "nettest not found; skipping tests"
- return
- fi
-
log_section "IPv6 Netfilter"
log_subsection "TCP reset"
@@ -3422,6 +3390,12 @@ elif [ "$TESTS" = "ipv6" ]; then
TESTS="$TESTS_IPV6"
fi
+which nettest >/dev/null
+if [ $? -ne 0 ]; then
+ echo "'nettest' command not found; skipping tests"
+ exit 0
+fi
+
declare -i nfail=0
declare -i nsuccess=0
--
2.11.0
^ permalink raw reply related
* Re: [PATCH v3] tools: bpftool: fix reading from /proc/config.gz
From: Peter Wu @ 2019-08-09 23:20 UTC (permalink / raw)
To: Jakub Kicinski
Cc: Stanislav Fomichev, Alexei Starovoitov, Daniel Borkmann, netdev,
Stanislav Fomichev, Quentin Monnet
In-Reply-To: <20190809145726.2972fa7a@cakuba.netronome.com>
Hi all,
Thanks for the lovely feedback :)
On Fri, Aug 09, 2019 at 02:57:26PM -0700, Jakub Kicinski wrote:
> On Fri, 9 Aug 2019 14:48:31 -0700, Stanislav Fomichev wrote:
> > I'm just being nit picky :-)
> > Because changelog says we already depend on -lz, but then in the patch
> > we explicitly add it.
What I meant by that is that zlib is not a new dependency since it is
already a mandatory dependency of libelf which is currently marked as
mandatory dependency in bpftool. That is why I did not bother with
adding a feature test either since it would be redundant.
Adding an explicit dependency helps if you want to build bpftool as
static binary, or if libelf somehow drops zlib in the future.
--
Kind regards,
Peter Wu
https://lekensteyn.nl
^ permalink raw reply
* Re: [PATCH v5 bpf-next] BPF: helpers: New helper to obtain namespacedata from current task
From: Yonghong Song @ 2019-08-09 23:30 UTC (permalink / raw)
To: Carlos Antonio Neira Bustos
Cc: Y Song, netdev@vger.kernel.org, ebiederm@xmission.com,
brouer@redhat.com, bpf, quentin.monnet@netronome.com
In-Reply-To: <20190809210332.3cxftmljxfhwotrz@dev00>
On 8/9/19 2:03 PM, Carlos Antonio Neira Bustos wrote:
> Yonghong,
>
> I have splitted the patch in 2 :
>
> - bpf_helper introduction :
>
>
> From 40ec0781525b82d5235c45f5066a7a79dea71065 Mon Sep 17 00:00:00 2001
> From: Carlos <cneirabustos@gmail.com>
> Date: Fri, 9 Aug 2019 12:20:52 -0700
> Subject: [PATCH 1/2] [PATCH v8 bpf-next 1/2] BPF: New helper to obtain
> namespace data from current task
Such a submission is not what kernel developer typically do.
You can read through the following docs for more details.
https://www.kernel.org/doc/html/v4.17/process/submitting-patches.html
Typically, I am using
git format-patch --cover-letter --subject-prefix="PATCH bpf-next
<version>" ...
to generate the patch set, you need edit patchset 0 with proper contents.
After patch set is properly prepared, you can use
git send-email --to <...> --to <...> --cc <...> --cc <...> <All your
patches>
to submit the patch.
I still prefer you to further split the patch into more than two
with my original suggestions. It might be difficult to do if you try
to attach the patches like below.
But it should become easier when you use the above
"git format-patch ..." and "git send-email ..." approach.
>
> This helper obtains the active namespace from current and returns pid, tgid,
> device and namespace id as seen from that namespace, allowing to instrument
> a process inside a container.
> Device is read from /proc/self/ns/pid, as in the future it's possible that
> different pid_ns files may belong to different devices, according
> to the discussion between Eric Biederman and Yonghong in 2017 linux plumbers
> conference.
> Currently bpf_get_current_pid_tgid(), is used to do pid filtering in bcc's
> scripts but this helper returns the pid as seen by the root namespace which is
> fine when a bcc script is not executed inside a container.
> When the process of interest is inside a container, pid filtering will not work
> if bpf_get_current_pid_tgid() is used. This helper addresses this limitation
> returning the pid as it's seen by the current namespace where the script is
> executing.
>
> This helper has the same use cases as bpf_get_current_pid_tgid() as it can be
> used to do pid filtering even inside a container.
>
> For example a bcc script using bpf_get_current_pid_tgid() (tools/funccount.py):
>
> u32 pid = bpf_get_current_pid_tgid() >> 32;
> if (pid != <pid_arg_passed_in>)
> return 0;
> Could be modified to use bpf_get_current_pidns_info() as follows:
>
> struct bpf_pidns pidns;
> bpf_get_current_pidns_info(&pidns, sizeof(struct bpf_pidns));
> u32 pid = pidns.tgid;
> u32 nsid = pidns.nsid;
> if ((pid != <pid_arg_passed_in>) && (nsid != <nsid_arg_passed_in>))
> return 0;
>
> To find out the name PID namespace id of a process, you could use this command:
>
> $ ps -h -o pidns -p <pid_of_interest>
>
> Or this other command:
>
> $ ls -Li /proc/<pid_of_interest>/ns/pid
>
> Signed-off-by: Carlos Neira <cneirabustos@gmail.com>
> ---
> fs/internal.h | 2 --
> fs/namei.c | 1 -
> include/linux/bpf.h | 1 +
> include/linux/namei.h | 4 +++
> include/uapi/linux/bpf.h | 31 +++++++++++++++++++-
> kernel/bpf/core.c | 1 +
> kernel/bpf/helpers.c | 64 ++++++++++++++++++++++++++++++++++++++++++
> kernel/trace/bpf_trace.c | 2 ++
> tools/include/uapi/linux/bpf.h | 31 +++++++++++++++++++-
> 9 files changed, 132 insertions(+), 5 deletions(-)
>
> diff --git a/fs/internal.h b/fs/internal.h
> index 315fcd8d237c..6647e15dd419 100644
> --- a/fs/internal.h
> +++ b/fs/internal.h
> @@ -59,8 +59,6 @@ extern int finish_clean_context(struct fs_context *fc);
> /*
> * namei.c
> */
> -extern int filename_lookup(int dfd, struct filename *name, unsigned flags,
> - struct path *path, struct path *root);
> extern int user_path_mountpoint_at(int, const char __user *, unsigned int, struct path *);
> extern int vfs_path_lookup(struct dentry *, struct vfsmount *,
> const char *, unsigned int, struct path *);
> diff --git a/fs/namei.c b/fs/namei.c
> index 209c51a5226c..a89fc72a4a10 100644
> --- a/fs/namei.c
> +++ b/fs/namei.c
> @@ -19,7 +19,6 @@
> #include <linux/export.h>
> #include <linux/kernel.h>
> #include <linux/slab.h>
> -#include <linux/fs.h>
> #include <linux/namei.h>
> #include <linux/pagemap.h>
> #include <linux/fsnotify.h>
> diff --git a/include/linux/bpf.h b/include/linux/bpf.h
> index f9a506147c8a..e4adf5e05afd 100644
> --- a/include/linux/bpf.h
> +++ b/include/linux/bpf.h
> @@ -1050,6 +1050,7 @@ extern const struct bpf_func_proto bpf_get_local_storage_proto;
> extern const struct bpf_func_proto bpf_strtol_proto;
> extern const struct bpf_func_proto bpf_strtoul_proto;
> extern const struct bpf_func_proto bpf_tcp_sock_proto;
> +extern const struct bpf_func_proto bpf_get_current_pidns_info_proto;
>
> /* Shared helpers among cBPF and eBPF. */
> void bpf_user_rnd_init_once(void);
> diff --git a/include/linux/namei.h b/include/linux/namei.h
> index 9138b4471dbf..b45c8b6f7cb4 100644
> --- a/include/linux/namei.h
> +++ b/include/linux/namei.h
> @@ -6,6 +6,7 @@
> #include <linux/path.h>
> #include <linux/fcntl.h>
> #include <linux/errno.h>
> +#include <linux/fs.h>
>
> enum { MAX_NESTED_LINKS = 8 };
>
> @@ -97,6 +98,9 @@ extern void unlock_rename(struct dentry *, struct dentry *);
>
> extern void nd_jump_link(struct path *path);
>
> +extern int filename_lookup(int dfd, struct filename *name, unsigned flags,
> + struct path *path, struct path *root);
> +
> static inline void nd_terminate_link(void *name, size_t len, size_t maxlen)
> {
> ((char *) name)[min(len, maxlen)] = '\0';
> diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
> index 4393bd4b2419..db241857ec15 100644
> --- a/include/uapi/linux/bpf.h
> +++ b/include/uapi/linux/bpf.h
> @@ -2741,6 +2741,28 @@ union bpf_attr {
> * **-EOPNOTSUPP** kernel configuration does not enable SYN cookies
> *
> * **-EPROTONOSUPPORT** IP packet version is not 4 or 6
> + *
> + * int bpf_get_current_pidns_info(struct bpf_pidns_info *pidns, u32 size_of_pidns)
> + * Description
> + * Copies into *pidns* pid, namespace id and tgid as seen by the
> + * current namespace and also device from /proc/self/ns/pid.
> + * *size_of_pidns* must be the size of *pidns*
> + *
> + * This helper is used when pid filtering is needed inside a
> + * container as bpf_get_current_tgid() helper returns always the
> + * pid id as seen by the root namespace.
> + * Return
> + * 0 on success
> + *
> + * **-EINVAL** if *size_of_pidns* is not valid or unable to get ns, pid
> + * or tgid of the current task.
> + *
> + * **-ECHILD** if /proc/self/ns/pid does not exists.
> + *
> + * **-ENOTDIR** if /proc/self/ns does not exists.
> + *
> + * **-ENOMEM** if allocation fails.
> + *
> */
> #define __BPF_FUNC_MAPPER(FN) \
> FN(unspec), \
> @@ -2853,7 +2875,8 @@ union bpf_attr {
> FN(sk_storage_get), \
> FN(sk_storage_delete), \
> FN(send_signal), \
> - FN(tcp_gen_syncookie),
> + FN(tcp_gen_syncookie), \
> + FN(get_current_pidns_info),
>
> /* integer value in 'imm' field of BPF_CALL instruction selects which helper
> * function eBPF program intends to call
> @@ -3604,4 +3627,10 @@ struct bpf_sockopt {
> __s32 retval;
> };
>
> +struct bpf_pidns_info {
> + __u32 dev;
> + __u32 nsid;
> + __u32 tgid;
> + __u32 pid;
> +};
> #endif /* _UAPI__LINUX_BPF_H__ */
> diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
> index 8191a7db2777..3159f2a0188c 100644
> --- a/kernel/bpf/core.c
> +++ b/kernel/bpf/core.c
> @@ -2038,6 +2038,7 @@ const struct bpf_func_proto bpf_get_current_uid_gid_proto __weak;
> const struct bpf_func_proto bpf_get_current_comm_proto __weak;
> const struct bpf_func_proto bpf_get_current_cgroup_id_proto __weak;
> const struct bpf_func_proto bpf_get_local_storage_proto __weak;
> +const struct bpf_func_proto bpf_get_current_pidns_info __weak;
>
> const struct bpf_func_proto * __weak bpf_get_trace_printk_proto(void)
> {
> diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
> index 5e28718928ca..41fbf1f28a48 100644
> --- a/kernel/bpf/helpers.c
> +++ b/kernel/bpf/helpers.c
> @@ -11,6 +11,12 @@
> #include <linux/uidgid.h>
> #include <linux/filter.h>
> #include <linux/ctype.h>
> +#include <linux/pid_namespace.h>
> +#include <linux/major.h>
> +#include <linux/stat.h>
> +#include <linux/namei.h>
> +#include <linux/version.h>
> +
>
> #include "../../lib/kstrtox.h"
>
> @@ -312,6 +318,64 @@ void copy_map_value_locked(struct bpf_map *map, void *dst, void *src,
> preempt_enable();
> }
>
> +BPF_CALL_2(bpf_get_current_pidns_info, struct bpf_pidns_info *, pidns_info, u32,
> + size)
> +{
> + const char *pidns_path = "/proc/self/ns/pid";
> + struct pid_namespace *pidns = NULL;
> + struct filename *tmp = NULL;
> + struct inode *inode;
> + struct path kp;
> + pid_t tgid = 0;
> + pid_t pid = 0;
> + int ret;
> + int len;
> +
> + if (unlikely(size != sizeof(struct bpf_pidns_info)))
> + return -EINVAL;
> + pidns = task_active_pid_ns(current);
> + if (unlikely(!pidns))
> + goto clear;
> + pidns_info->nsid = pidns->ns.inum;
> + pid = task_pid_nr_ns(current, pidns);
> + if (unlikely(!pid))
> + goto clear;
> + tgid = task_tgid_nr_ns(current, pidns);
> + if (unlikely(!tgid))
> + goto clear;
> + pidns_info->tgid = (u32) tgid;
> + pidns_info->pid = (u32) pid;
> + tmp = kmem_cache_alloc(names_cachep, GFP_ATOMIC);
> + if (unlikely(!tmp)) {
> + memset((void *)pidns_info, 0, (size_t) size);
> + return -ENOMEM;
> + }
> + len = strlen(pidns_path) + 1;
> + memcpy((char *)tmp->name, pidns_path, len);
> + tmp->uptr = NULL;
> + tmp->aname = NULL;
> + tmp->refcnt = 1;
> + ret = filename_lookup(AT_FDCWD, tmp, 0, &kp, NULL);
> + if (ret) {
> + memset((void *)pidns_info, 0, (size_t) size);
> + return ret;
> + }
> + inode = d_backing_inode(kp.dentry);
> + pidns_info->dev = inode->i_sb->s_dev;
> + return 0;
> +clear:
> + memset((void *)pidns_info, 0, (size_t) size);
> + return -EINVAL;
> +}
> +
> +const struct bpf_func_proto bpf_get_current_pidns_info_proto = {
> + .func = bpf_get_current_pidns_info,
> + .gpl_only = false,
> + .ret_type = RET_INTEGER,
> + .arg1_type = ARG_PTR_TO_UNINIT_MEM,
> + .arg2_type = ARG_CONST_SIZE,
> +};
> +
> #ifdef CONFIG_CGROUPS
> BPF_CALL_0(bpf_get_current_cgroup_id)
> {
> diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
> index ca1255d14576..5e1dc22765a5 100644
> --- a/kernel/trace/bpf_trace.c
> +++ b/kernel/trace/bpf_trace.c
> @@ -709,6 +709,8 @@ tracing_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
> #endif
> case BPF_FUNC_send_signal:
> return &bpf_send_signal_proto;
> + case BPF_FUNC_get_current_pidns_info:
> + return &bpf_get_current_pidns_info_proto;
> default:
> return NULL;
> }
> diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
> index 4393bd4b2419..db241857ec15 100644
> --- a/tools/include/uapi/linux/bpf.h
> +++ b/tools/include/uapi/linux/bpf.h
> @@ -2741,6 +2741,28 @@ union bpf_attr {
> * **-EOPNOTSUPP** kernel configuration does not enable SYN cookies
> *
> * **-EPROTONOSUPPORT** IP packet version is not 4 or 6
> + *
> + * int bpf_get_current_pidns_info(struct bpf_pidns_info *pidns, u32 size_of_pidns)
> + * Description
> + * Copies into *pidns* pid, namespace id and tgid as seen by the
> + * current namespace and also device from /proc/self/ns/pid.
> + * *size_of_pidns* must be the size of *pidns*
> + *
> + * This helper is used when pid filtering is needed inside a
> + * container as bpf_get_current_tgid() helper returns always the
> + * pid id as seen by the root namespace.
> + * Return
> + * 0 on success
> + *
> + * **-EINVAL** if *size_of_pidns* is not valid or unable to get ns, pid
> + * or tgid of the current task.
> + *
> + * **-ECHILD** if /proc/self/ns/pid does not exists.
> + *
> + * **-ENOTDIR** if /proc/self/ns does not exists.
> + *
> + * **-ENOMEM** if allocation fails.
> + *
> */
> #define __BPF_FUNC_MAPPER(FN) \
> FN(unspec), \
> @@ -2853,7 +2875,8 @@ union bpf_attr {
> FN(sk_storage_get), \
> FN(sk_storage_delete), \
> FN(send_signal), \
> - FN(tcp_gen_syncookie),
> + FN(tcp_gen_syncookie), \
> + FN(get_current_pidns_info),
>
> /* integer value in 'imm' field of BPF_CALL instruction selects which helper
> * function eBPF program intends to call
> @@ -3604,4 +3627,10 @@ struct bpf_sockopt {
> __s32 retval;
> };
>
> +struct bpf_pidns_info {
> + __u32 dev;
> + __u32 nsid;
> + __u32 tgid;
> + __u32 pid;
> +};
> #endif /* _UAPI__LINUX_BPF_H__ */
>
^ permalink raw reply
* [PATCH 0/2] iproute2: Improve usability of `ip nexthop`
From: Donald Sharp @ 2019-08-10 0:18 UTC (permalink / raw)
To: netdev, dsahern
First patch fixes a spacing issue and the second patch allows
the user to filter on the specificed protocol.
Donald Sharp (2):
ip nexthop: Add space to display properly when showing a group
ip nexthop: Allow flush|list operations to specify a specific protocol
ip/ipnexthop.c | 17 ++++++++++++++++-
1 file changed, 16 insertions(+), 1 deletion(-)
--
2.21.0
^ permalink raw reply
* [PATCH 1/2] ip nexthop: Add space to display properly when showing a group
From: Donald Sharp @ 2019-08-10 0:18 UTC (permalink / raw)
To: netdev, dsahern
When displaying a nexthop group made up of other nexthops, the display
line shows this when you have additional data at the end:
id 42 group 43/44/45/46/47/48/49/50/51/52/53/54/55/56/57/58/59/60/61/62/63/64/65/66/67/68/69/70/71/72/73/74proto zebra
Modify code so that it shows:
id 42 group 43/44/45/46/47/48/49/50/51/52/53/54/55/56/57/58/59/60/61/62/63/64/65/66/67/68/69/70/71/72/73/74 proto zebra
Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
---
ip/ipnexthop.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/ip/ipnexthop.c b/ip/ipnexthop.c
index 97f09e74..f35aab52 100644
--- a/ip/ipnexthop.c
+++ b/ip/ipnexthop.c
@@ -186,6 +186,7 @@ static void print_nh_group(FILE *fp, const struct rtattr *grps_attr)
close_json_object();
}
+ print_string(PRINT_FP, NULL, "%s", " ");
close_json_array(PRINT_JSON, NULL);
}
--
2.21.0
^ permalink raw reply related
* [PATCH 2/2] ip nexthop: Allow flush|list operations to specify a specific protocol
From: Donald Sharp @ 2019-08-10 0:18 UTC (permalink / raw)
To: netdev, dsahern
In the case where we have a large number of nexthops from a specific
protocol, allow the flush and list operations to take a protocol
to limit the commands scopes.
Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
---
ip/ipnexthop.c | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)
diff --git a/ip/ipnexthop.c b/ip/ipnexthop.c
index f35aab52..bc8ab431 100644
--- a/ip/ipnexthop.c
+++ b/ip/ipnexthop.c
@@ -19,6 +19,7 @@ static struct {
unsigned int groups;
unsigned int ifindex;
unsigned int master;
+ unsigned int proto;
} filter;
enum {
@@ -34,7 +35,7 @@ static void usage(void) __attribute__((noreturn));
static void usage(void)
{
fprintf(stderr,
- "Usage: ip nexthop { list | flush } SELECTOR\n"
+ "Usage: ip nexthop { list | flush } [ protocol ID ] SELECTOR\n"
" ip nexthop { add | replace } id ID NH [ protocol ID ]\n"
" ip nexthop { get| del } id ID\n"
"SELECTOR := [ id ID ] [ dev DEV ] [ vrf NAME ] [ master DEV ]\n"
@@ -109,6 +110,9 @@ static int flush_nexthop(struct nlmsghdr *nlh, void *arg)
return -1;
}
+ if (filter.proto && nhm->nh_protocol != filter.proto)
+ return 0;
+
parse_rtattr(tb, NHA_MAX, RTM_NHA(nhm), len);
if (tb[NHA_ID])
id = rta_getattr_u32(tb[NHA_ID]);
@@ -213,6 +217,9 @@ int print_nexthop(struct nlmsghdr *n, void *arg)
return -1;
}
+ if (filter.proto && filter.proto != nhm->nh_protocol)
+ return 0;
+
parse_rtattr(tb, NHA_MAX, RTM_NHA(nhm), len);
open_json_object(NULL);
@@ -473,6 +480,13 @@ static int ipnh_list_flush(int argc, char **argv, int action)
if (get_unsigned(&id, *argv, 0))
invarg("invalid id value", *argv);
return ipnh_get_id(id);
+ } else if (!matches(*argv, "protocol")) {
+ __u32 proto;
+
+ NEXT_ARG();
+ if (get_unsigned(&proto, *argv, 0))
+ invarg("invalid protocol value", *argv);
+ filter.proto = proto;
} else if (matches(*argv, "help") == 0) {
usage();
} else {
--
2.21.0
^ permalink raw reply related
* [PATCH net] net/tls: swap sk_write_space on close
From: Jakub Kicinski @ 2019-08-10 1:36 UTC (permalink / raw)
To: davem
Cc: netdev, willemb, davejwatson, borisp, aviadye, john.fastabend,
daniel, oss-drivers, Jakub Kicinski, syzbot+dcdc9deefaec44785f32
Now that we swap the original proto and clear the ULP pointer
on close we have to make sure no callback will try to access
the freed state. sk_write_space is not part of sk_prot, remember
to swap it.
Reported-by: syzbot+dcdc9deefaec44785f32@syzkaller.appspotmail.com
Fixes: 95fa145479fb ("bpf: sockmap/tls, close can race with map free")
Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
---
net/tls/tls_main.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/net/tls/tls_main.c b/net/tls/tls_main.c
index 9cbbae606ced..ce6ef56a65ef 100644
--- a/net/tls/tls_main.c
+++ b/net/tls/tls_main.c
@@ -308,6 +308,7 @@ static void tls_sk_proto_close(struct sock *sk, long timeout)
if (free_ctx)
icsk->icsk_ulp_data = NULL;
sk->sk_prot = ctx->sk_proto;
+ sk->sk_write_space = ctx->sk_write_space;
write_unlock_bh(&sk->sk_callback_lock);
release_sock(sk);
if (ctx->tx_conf == TLS_SW)
--
2.21.0
^ permalink raw reply related
* Re: [PATCH net-next] selftests: Fix detection of nettest command in fcnal-test
From: David Miller @ 2019-08-10 2:54 UTC (permalink / raw)
To: dsahern; +Cc: netdev, dsahern
In-Reply-To: <20190809231338.29105-1-dsahern@kernel.org>
From: David Ahern <dsahern@kernel.org>
Date: Fri, 9 Aug 2019 16:13:38 -0700
> From: David Ahern <dsahern@gmail.com>
>
> Most of the tests run by fcnal-test.sh relies on the nettest command.
> Rather than trying to cover all of the individual tests, check for the
> binary only at the beginning.
>
> Also removes the need for log_error which is undefined.
>
> Fixes: 6f9d5cacfe07 ("selftests: Setup for functional tests for fib and socket lookups")
> Signed-off-by: David Ahern <dsahern@gmail.com>
Applied, thanks David.
^ permalink raw reply
* Re: [PATCH net] net/tls: swap sk_write_space on close
From: David Miller @ 2019-08-10 2:56 UTC (permalink / raw)
To: jakub.kicinski
Cc: netdev, willemb, davejwatson, borisp, aviadye, john.fastabend,
daniel, oss-drivers, syzbot+dcdc9deefaec44785f32
In-Reply-To: <20190810013623.14707-1-jakub.kicinski@netronome.com>
From: Jakub Kicinski <jakub.kicinski@netronome.com>
Date: Fri, 9 Aug 2019 18:36:23 -0700
> Now that we swap the original proto and clear the ULP pointer
> on close we have to make sure no callback will try to access
> the freed state. sk_write_space is not part of sk_prot, remember
> to swap it.
>
> Reported-by: syzbot+dcdc9deefaec44785f32@syzkaller.appspotmail.com
> Fixes: 95fa145479fb ("bpf: sockmap/tls, close can race with map free")
> Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Applied, thanks Jakub.
^ permalink raw reply
* Re: [PATCH net-next 1/1] tc-testing: added tdc tests for matchall filter
From: David Miller @ 2019-08-10 2:59 UTC (permalink / raw)
To: mrv; +Cc: netdev, kernel, jhs, xiyou.wangcong, jiri
In-Reply-To: <1565390800-26061-1-git-send-email-mrv@mojatatu.com>
From: Roman Mashak <mrv@mojatatu.com>
Date: Fri, 9 Aug 2019 18:46:40 -0400
> Signed-off-by: Roman Mashak <mrv@mojatatu.com>
Applied.
^ permalink raw reply
* Re: [pull request][net-next 00/15] Mellanox, mlx5 tc flow handling for concurrent execution (Part 2)
From: David Miller @ 2019-08-10 3:11 UTC (permalink / raw)
To: saeedm; +Cc: netdev
In-Reply-To: <20190809220359.11516-1-saeedm@mellanox.com>
From: Saeed Mahameed <saeedm@mellanox.com>
Date: Fri, 9 Aug 2019 22:04:17 +0000
> This series, mostly from Vlad, is the 2nd part of 3 part series to
> improve mlx5 tc flow handling by removing dependency on rtnl_lock and
> providing a more fine-grained locking and rcu safe data structures to
> allow tc flow handling for concurrent execution.
>
> In this part Vlad handles hairpin, header rewrite and encapsulation
> offloads.
>
> For more information please see tag log below.
>
> Please pull and let me know if there is any problem.
Looks good, pulled, thanks.
^ permalink raw reply
* Re: [patch net-next] netdevsim: register couple of devlink params
From: Jiri Pirko @ 2019-08-10 6:06 UTC (permalink / raw)
To: Jakub Kicinski; +Cc: netdev, davem, mlxsw
In-Reply-To: <20190809142635.52a6275d@cakuba.netronome.com>
Fri, Aug 09, 2019 at 11:26:35PM CEST, jakub.kicinski@netronome.com wrote:
>On Fri, 9 Aug 2019 13:05:12 +0200, Jiri Pirko wrote:
>> From: Jiri Pirko <jiri@mellanox.com>
>>
>> Register couple of devlink params, one generic, one driver-specific.
>> Make the values available over debugfs.
>>
>> Example:
>> $ echo "111" > /sys/bus/netdevsim/new_device
>> $ devlink dev param
>> netdevsim/netdevsim111:
>> name max_macs type generic
>> values:
>> cmode driverinit value 32
>> name test1 type driver-specific
>> values:
>> cmode driverinit value true
>> $ cat /sys/kernel/debug/netdevsim/netdevsim111/max_macs
>> 32
>> $ cat /sys/kernel/debug/netdevsim/netdevsim111/test1
>> Y
>> $ devlink dev param set netdevsim/netdevsim111 name max_macs cmode driverinit value 16
>> $ devlink dev param set netdevsim/netdevsim111 name test1 cmode driverinit value false
>> $ devlink dev reload netdevsim/netdevsim111
>> $ cat /sys/kernel/debug/netdevsim/netdevsim111/max_macs
>> 16
>> $ cat /sys/kernel/debug/netdevsim/netdevsim111/test1
>>
>> Signed-off-by: Jiri Pirko <jiri@mellanox.com>
>
>The netdevsim patch looks good, what's the plan for tests?
I have this and a follow-up regions implementation for testing purposes
(netns notificatiosn). I will also need this for syzkaller. Selftest I
have scheduled right after.
>
>We don't need much perhaps what you have in the commit message
>as a script which can be run by automated bots would be sufficient?
^ permalink raw reply
* Re: [patch net-next rfc 3/7] net: rtnetlink: add commands to add and delete alternative ifnames
From: Jiri Pirko @ 2019-08-10 6:30 UTC (permalink / raw)
To: David Ahern
Cc: Roopa Prabhu, netdev, David Miller, Jakub Kicinski,
Stephen Hemminger, dcbw, Michal Kubecek, Andrew Lunn, parav,
Saeed Mahameed, mlxsw
In-Reply-To: <5e7270a1-8de6-1563-4e42-df37da161b98@gmail.com>
Fri, Aug 09, 2019 at 06:14:03PM CEST, dsahern@gmail.com wrote:
>On 8/9/19 9:40 AM, Roopa Prabhu wrote:
>>>>> diff --git a/include/uapi/linux/rtnetlink.h b/include/uapi/linux/rtnetlink.h
>>>>> index ce2a623abb75..b36cfd83eb76 100644
>>>>> --- a/include/uapi/linux/rtnetlink.h
>>>>> +++ b/include/uapi/linux/rtnetlink.h
>>>>> @@ -164,6 +164,13 @@ enum {
>>>>> RTM_GETNEXTHOP,
>>>>> #define RTM_GETNEXTHOP RTM_GETNEXTHOP
>>>>>
>>>>> + RTM_NEWALTIFNAME = 108,
>>>>> +#define RTM_NEWALTIFNAME RTM_NEWALTIFNAME
>>>>> + RTM_DELALTIFNAME,
>>>>> +#define RTM_DELALTIFNAME RTM_DELALTIFNAME
>>>>> + RTM_GETALTIFNAME,
>>>>> +#define RTM_GETALTIFNAME RTM_GETALTIFNAME
>>>>> +
>>>>
>>>> I might have missed the prior discussion, why do we need new commands
>>>> ?. can't this simply be part of RTM_*LINK and we use RTM_SETLINK to
>>>> set alternate names ?
>>>
>>> How? This is to add/remove. How do you suggest to to add/remove by
>>> setlink?
>>
>> to that point, I am also not sure why we have a new API For multiple
>> names. I mean why support more than two names (existing old name and
>> a new name to remove the length limitation) ?
>>
>> Your patch series addresses a very important problem (we run into this
>> limitation all the time and its hard to explain it to network
>> operators) and
>> its already unfortunate that we have to have more than one name
>> because we cannot resize the existing one.
>>
>> The best we can do for simpler transition/management from user-space
>> is to keep the api simple..
>> ie keep it close to the management of existing link attributes. Hence
>> the question.
>>
>> I assumed this would be like alias. A single new field that can be
>> referenced in lieu of the old one.
>>
>> Your series is very useful to many of us...but when i think about
>> changing our network manager to accommodate this, I am worried about
>> how many apps will have to change.
>> I agree they have to change regardless but now they will have to
>> listen to yet another notification and msg format for names ?
>>
>> (apologies for joining the thread late and if i missed prior discussion on this)
>
>I agree with Roopa. I do not understand why new RTM commands are needed.
>The existing IFLA + ifinfomsg struct give more than enough ways to id
>the device for adding / deleting an alternate name.
>
Could you please write me an example message of add/remove?
^ permalink raw reply
* Re: [patch net-next rfc 3/7] net: rtnetlink: add commands to add and delete alternative ifnames
From: Jiri Pirko @ 2019-08-10 6:32 UTC (permalink / raw)
To: Roopa Prabhu
Cc: netdev, David Miller, Jakub Kicinski, Stephen Hemminger,
David Ahern, dcbw, Michal Kubecek, Andrew Lunn, parav,
Saeed Mahameed, mlxsw
In-Reply-To: <CAJieiUj7nzHdRUjBpnfL5bKPszJL0b_hKjxpjM0RGd9ocF3EoA@mail.gmail.com>
Fri, Aug 09, 2019 at 05:40:25PM CEST, roopa@cumulusnetworks.com wrote:
>On Thu, Aug 8, 2019 at 11:25 PM Jiri Pirko <jiri@resnulli.us> wrote:
>>
>> Fri, Aug 09, 2019 at 06:11:30AM CEST, roopa@cumulusnetworks.com wrote:
>> >On Fri, Jul 19, 2019 at 4:00 AM Jiri Pirko <jiri@resnulli.us> wrote:
>> >>
>> >> From: Jiri Pirko <jiri@mellanox.com>
>> >>
>> >> Add two commands to add and delete alternative ifnames for net device.
>> >> Each net device can have multiple alternative names.
>> >>
>> >> Signed-off-by: Jiri Pirko <jiri@mellanox.com>
>> >> ---
>> >> include/linux/netdevice.h | 4 ++
>> >> include/uapi/linux/if.h | 1 +
>> >> include/uapi/linux/if_link.h | 1 +
>> >> include/uapi/linux/rtnetlink.h | 7 +++
>> >> net/core/dev.c | 58 ++++++++++++++++++-
>> >> net/core/rtnetlink.c | 102 +++++++++++++++++++++++++++++++++
>> >> security/selinux/nlmsgtab.c | 4 +-
>> >> 7 files changed, 175 insertions(+), 2 deletions(-)
>> >>
>> >> diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
>> >> index 74f99f127b0e..6922fdb483ca 100644
>> >> --- a/include/linux/netdevice.h
>> >> +++ b/include/linux/netdevice.h
>> >> @@ -920,10 +920,14 @@ struct tlsdev_ops;
>> >>
>> >> struct netdev_name_node {
>> >> struct hlist_node hlist;
>> >> + struct list_head list;
>> >> struct net_device *dev;
>> >> char *name;
>> >> };
>> >>
>> >> +int netdev_name_node_alt_create(struct net_device *dev, char *name);
>> >> +int netdev_name_node_alt_destroy(struct net_device *dev, char *name);
>> >> +
>> >> /*
>> >> * This structure defines the management hooks for network devices.
>> >> * The following hooks can be defined; unless noted otherwise, they are
>> >> diff --git a/include/uapi/linux/if.h b/include/uapi/linux/if.h
>> >> index 7fea0fd7d6f5..4bf33344aab1 100644
>> >> --- a/include/uapi/linux/if.h
>> >> +++ b/include/uapi/linux/if.h
>> >> @@ -33,6 +33,7 @@
>> >> #define IFNAMSIZ 16
>> >> #endif /* __UAPI_DEF_IF_IFNAMSIZ */
>> >> #define IFALIASZ 256
>> >> +#define ALTIFNAMSIZ 128
>> >> #include <linux/hdlc/ioctl.h>
>> >>
>> >> /* For glibc compatibility. An empty enum does not compile. */
>> >> diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
>> >> index 4a8c02cafa9a..92268946e04a 100644
>> >> --- a/include/uapi/linux/if_link.h
>> >> +++ b/include/uapi/linux/if_link.h
>> >> @@ -167,6 +167,7 @@ enum {
>> >> IFLA_NEW_IFINDEX,
>> >> IFLA_MIN_MTU,
>> >> IFLA_MAX_MTU,
>> >> + IFLA_ALT_IFNAME_MOD, /* Alternative ifname to add/delete */
>> >> __IFLA_MAX
>> >> };
>> >>
>> >> diff --git a/include/uapi/linux/rtnetlink.h b/include/uapi/linux/rtnetlink.h
>> >> index ce2a623abb75..b36cfd83eb76 100644
>> >> --- a/include/uapi/linux/rtnetlink.h
>> >> +++ b/include/uapi/linux/rtnetlink.h
>> >> @@ -164,6 +164,13 @@ enum {
>> >> RTM_GETNEXTHOP,
>> >> #define RTM_GETNEXTHOP RTM_GETNEXTHOP
>> >>
>> >> + RTM_NEWALTIFNAME = 108,
>> >> +#define RTM_NEWALTIFNAME RTM_NEWALTIFNAME
>> >> + RTM_DELALTIFNAME,
>> >> +#define RTM_DELALTIFNAME RTM_DELALTIFNAME
>> >> + RTM_GETALTIFNAME,
>> >> +#define RTM_GETALTIFNAME RTM_GETALTIFNAME
>> >> +
>> >
>> >I might have missed the prior discussion, why do we need new commands
>> >?. can't this simply be part of RTM_*LINK and we use RTM_SETLINK to
>> >set alternate names ?
>>
>> How? This is to add/remove. How do you suggest to to add/remove by
>> setlink?
>
>to that point, I am also not sure why we have a new API For multiple
>names. I mean why support more than two names (existing old name and
Please see the previous discussion in the rfc. The point is, udev can
provide multiple names according to multiple naming scheme (mac,
pciaddr, etc).
>a new name to remove the length limitation) ?
>
>Your patch series addresses a very important problem (we run into this
>limitation all the time and its hard to explain it to network
>operators) and
> its already unfortunate that we have to have more than one name
>because we cannot resize the existing one.
>
>The best we can do for simpler transition/management from user-space
>is to keep the api simple..
>ie keep it close to the management of existing link attributes. Hence
>the question.
>
>I assumed this would be like alias. A single new field that can be
>referenced in lieu of the old one.
>
>Your series is very useful to many of us...but when i think about
>changing our network manager to accommodate this, I am worried about
>how many apps will have to change.
>I agree they have to change regardless but now they will have to
>listen to yet another notification and msg format for names ?
>
>(apologies for joining the thread late and if i missed prior discussion on this)
>
>
>>
>>
>> >
>> >
>> >
>> >> __RTM_MAX,
>> >> #define RTM_MAX (((__RTM_MAX + 3) & ~3) - 1)
>> >> };
>> >> diff --git a/net/core/dev.c b/net/core/dev.c
>> >> index ad0d42fbdeee..2a3be2b279d3 100644
>> >> --- a/net/core/dev.c
>> >> +++ b/net/core/dev.c
>> >> @@ -244,7 +244,13 @@ static struct netdev_name_node *netdev_name_node_alloc(struct net_device *dev,
>> >> static struct netdev_name_node *
>> >> netdev_name_node_head_alloc(struct net_device *dev)
>> >> {
>> >> - return netdev_name_node_alloc(dev, dev->name);
>> >> + struct netdev_name_node *name_node;
>> >> +
>> >> + name_node = netdev_name_node_alloc(dev, dev->name);
>> >> + if (!name_node)
>> >> + return NULL;
>> >> + INIT_LIST_HEAD(&name_node->list);
>> >> + return name_node;
>> >> }
>> >>
>> >> static void netdev_name_node_free(struct netdev_name_node *name_node)
>> >> @@ -288,6 +294,55 @@ static struct netdev_name_node *netdev_name_node_lookup_rcu(struct net *net,
>> >> return NULL;
>> >> }
>> >>
>> >> +int netdev_name_node_alt_create(struct net_device *dev, char *name)
>> >> +{
>> >> + struct netdev_name_node *name_node;
>> >> + struct net *net = dev_net(dev);
>> >> +
>> >> + name_node = netdev_name_node_lookup(net, name);
>> >> + if (name_node)
>> >> + return -EEXIST;
>> >> + name_node = netdev_name_node_alloc(dev, name);
>> >> + if (!name_node)
>> >> + return -ENOMEM;
>> >> + netdev_name_node_add(net, name_node);
>> >> + /* The node that holds dev->name acts as a head of per-device list. */
>> >> + list_add_tail(&name_node->list, &dev->name_node->list);
>> >> +
>> >> + return 0;
>> >> +}
>> >> +EXPORT_SYMBOL(netdev_name_node_alt_create);
>> >> +
>> >> +static void __netdev_name_node_alt_destroy(struct netdev_name_node *name_node)
>> >> +{
>> >> + list_del(&name_node->list);
>> >> + netdev_name_node_del(name_node);
>> >> + kfree(name_node->name);
>> >> + netdev_name_node_free(name_node);
>> >> +}
>> >> +
>> >> +int netdev_name_node_alt_destroy(struct net_device *dev, char *name)
>> >> +{
>> >> + struct netdev_name_node *name_node;
>> >> + struct net *net = dev_net(dev);
>> >> +
>> >> + name_node = netdev_name_node_lookup(net, name);
>> >> + if (!name_node)
>> >> + return -ENOENT;
>> >> + __netdev_name_node_alt_destroy(name_node);
>> >> +
>> >> + return 0;
>> >> +}
>> >> +EXPORT_SYMBOL(netdev_name_node_alt_destroy);
>> >> +
>> >> +static void netdev_name_node_alt_flush(struct net_device *dev)
>> >> +{
>> >> + struct netdev_name_node *name_node, *tmp;
>> >> +
>> >> + list_for_each_entry_safe(name_node, tmp, &dev->name_node->list, list)
>> >> + __netdev_name_node_alt_destroy(name_node);
>> >> +}
>> >> +
>> >> /* Device list insertion */
>> >> static void list_netdevice(struct net_device *dev)
>> >> {
>> >> @@ -8258,6 +8313,7 @@ static void rollback_registered_many(struct list_head *head)
>> >> dev_uc_flush(dev);
>> >> dev_mc_flush(dev);
>> >>
>> >> + netdev_name_node_alt_flush(dev);
>> >> netdev_name_node_free(dev->name_node);
>> >>
>> >> if (dev->netdev_ops->ndo_uninit)
>> >> diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
>> >> index 1ee6460f8275..7a2010b16e10 100644
>> >> --- a/net/core/rtnetlink.c
>> >> +++ b/net/core/rtnetlink.c
>> >> @@ -1750,6 +1750,8 @@ static const struct nla_policy ifla_policy[IFLA_MAX+1] = {
>> >> [IFLA_CARRIER_DOWN_COUNT] = { .type = NLA_U32 },
>> >> [IFLA_MIN_MTU] = { .type = NLA_U32 },
>> >> [IFLA_MAX_MTU] = { .type = NLA_U32 },
>> >> + [IFLA_ALT_IFNAME_MOD] = { .type = NLA_STRING,
>> >> + .len = ALTIFNAMSIZ - 1 },
>> >> };
>> >>
>> >> static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = {
>> >> @@ -3373,6 +3375,103 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr *nlh,
>> >> return err;
>> >> }
>> >>
>> >> +static int rtnl_newaltifname(struct sk_buff *skb, struct nlmsghdr *nlh,
>> >> + struct netlink_ext_ack *extack)
>> >> +{
>> >> + struct net *net = sock_net(skb->sk);
>> >> + struct nlattr *tb[IFLA_MAX + 1];
>> >> + struct net_device *dev;
>> >> + struct ifinfomsg *ifm;
>> >> + char *new_alt_ifname;
>> >> + int err;
>> >> +
>> >> + err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy, extack);
>> >> + if (err)
>> >> + return err;
>> >> +
>> >> + err = rtnl_ensure_unique_netns(tb, extack, true);
>> >> + if (err)
>> >> + return err;
>> >> +
>> >> + ifm = nlmsg_data(nlh);
>> >> + if (ifm->ifi_index > 0) {
>> >> + dev = __dev_get_by_index(net, ifm->ifi_index);
>> >> + } else if (tb[IFLA_IFNAME]) {
>> >> + char ifname[IFNAMSIZ];
>> >> +
>> >> + nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ);
>> >> + dev = __dev_get_by_name(net, ifname);
>> >> + } else {
>> >> + return -EINVAL;
>> >> + }
>> >> +
>> >> + if (!dev)
>> >> + return -ENODEV;
>> >> +
>> >> + if (!tb[IFLA_ALT_IFNAME_MOD])
>> >> + return -EINVAL;
>> >> +
>> >> + new_alt_ifname = nla_strdup(tb[IFLA_ALT_IFNAME_MOD], GFP_KERNEL);
>> >> + if (!new_alt_ifname)
>> >> + return -ENOMEM;
>> >> +
>> >> + err = netdev_name_node_alt_create(dev, new_alt_ifname);
>> >> + if (err)
>> >> + goto out_free_new_alt_ifname;
>> >> +
>> >> + return 0;
>> >> +
>> >> +out_free_new_alt_ifname:
>> >> + kfree(new_alt_ifname);
>> >> + return err;
>> >> +}
>> >> +
>> >> +static int rtnl_delaltifname(struct sk_buff *skb, struct nlmsghdr *nlh,
>> >> + struct netlink_ext_ack *extack)
>> >> +{
>> >> + struct net *net = sock_net(skb->sk);
>> >> + struct nlattr *tb[IFLA_MAX + 1];
>> >> + struct net_device *dev;
>> >> + struct ifinfomsg *ifm;
>> >> + char *del_alt_ifname;
>> >> + int err;
>> >> +
>> >> + err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy, extack);
>> >> + if (err)
>> >> + return err;
>> >> +
>> >> + err = rtnl_ensure_unique_netns(tb, extack, true);
>> >> + if (err)
>> >> + return err;
>> >> +
>> >> + ifm = nlmsg_data(nlh);
>> >> + if (ifm->ifi_index > 0) {
>> >> + dev = __dev_get_by_index(net, ifm->ifi_index);
>> >> + } else if (tb[IFLA_IFNAME]) {
>> >> + char ifname[IFNAMSIZ];
>> >> +
>> >> + nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ);
>> >> + dev = __dev_get_by_name(net, ifname);
>> >> + } else {
>> >> + return -EINVAL;
>> >> + }
>> >> +
>> >> + if (!dev)
>> >> + return -ENODEV;
>> >> +
>> >> + if (!tb[IFLA_ALT_IFNAME_MOD])
>> >> + return -EINVAL;
>> >> +
>> >> + del_alt_ifname = nla_strdup(tb[IFLA_ALT_IFNAME_MOD], GFP_KERNEL);
>> >> + if (!del_alt_ifname)
>> >> + return -ENOMEM;
>> >> +
>> >> + err = netdev_name_node_alt_destroy(dev, del_alt_ifname);
>> >> + kfree(del_alt_ifname);
>> >> +
>> >> + return err;
>> >> +}
>> >> +
>> >> static u16 rtnl_calcit(struct sk_buff *skb, struct nlmsghdr *nlh)
>> >> {
>> >> struct net *net = sock_net(skb->sk);
>> >> @@ -5331,6 +5430,9 @@ void __init rtnetlink_init(void)
>> >> rtnl_register(PF_UNSPEC, RTM_GETROUTE, NULL, rtnl_dump_all, 0);
>> >> rtnl_register(PF_UNSPEC, RTM_GETNETCONF, NULL, rtnl_dump_all, 0);
>> >>
>> >> + rtnl_register(PF_UNSPEC, RTM_NEWALTIFNAME, rtnl_newaltifname, NULL, 0);
>> >> + rtnl_register(PF_UNSPEC, RTM_DELALTIFNAME, rtnl_delaltifname, NULL, 0);
>> >> +
>> >> rtnl_register(PF_BRIDGE, RTM_NEWNEIGH, rtnl_fdb_add, NULL, 0);
>> >> rtnl_register(PF_BRIDGE, RTM_DELNEIGH, rtnl_fdb_del, NULL, 0);
>> >> rtnl_register(PF_BRIDGE, RTM_GETNEIGH, rtnl_fdb_get, rtnl_fdb_dump, 0);
>> >> diff --git a/security/selinux/nlmsgtab.c b/security/selinux/nlmsgtab.c
>> >> index 58345ba0528e..a712b54c666c 100644
>> >> --- a/security/selinux/nlmsgtab.c
>> >> +++ b/security/selinux/nlmsgtab.c
>> >> @@ -83,6 +83,8 @@ static const struct nlmsg_perm nlmsg_route_perms[] =
>> >> { RTM_NEWNEXTHOP, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
>> >> { RTM_DELNEXTHOP, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
>> >> { RTM_GETNEXTHOP, NETLINK_ROUTE_SOCKET__NLMSG_READ },
>> >> + { RTM_NEWALTIFNAME, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
>> >> + { RTM_DELALTIFNAME, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
>> >> };
>> >>
>> >> static const struct nlmsg_perm nlmsg_tcpdiag_perms[] =
>> >> @@ -166,7 +168,7 @@ int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm)
>> >> * structures at the top of this file with the new mappings
>> >> * before updating the BUILD_BUG_ON() macro!
>> >> */
>> >> - BUILD_BUG_ON(RTM_MAX != (RTM_NEWNEXTHOP + 3));
>> >> + BUILD_BUG_ON(RTM_MAX != (RTM_NEWALTIFNAME + 3));
>> >> err = nlmsg_perm(nlmsg_type, perm, nlmsg_route_perms,
>> >> sizeof(nlmsg_route_perms));
>> >> break;
>> >> --
>> >> 2.21.0
>> >>
^ permalink raw reply
* [PATCH v4 0/2] perf: arm/arm64: Improve completeness for kernel address space
From: Leo Yan @ 2019-08-10 7:21 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo, Alexander Shishkin, Jiri Olsa,
Namhyung Kim, Alexei Starovoitov, Daniel Borkmann,
Martin KaFai Lau, Song Liu, Yonghong Song, David Miller,
Milian Wolff, Donald Yandt, Davidlohr Bueso, Wei Li,
Adrian Hunter, Mark Drayton, Tzvetomir Stoyanov (VMware),
linux-kernel, netdev, bpf, clang-built-linux, Mathieu Poirier
Cc: Leo Yan
This patch set is to improve completeness for kernel address space for
arm/arm64; it adds architecture specific tweaking for the kernel start
address, thus can include the memory regions which are prior to '_stext'
symbol. With this change, we can see the eBPF program can be parsed
properly on arm64.
This patch set is a following up version for the old patch "perf cs-etm:
Improve completeness for kernel address space" [1]; the old patch was
only to fix the issue for CoreSight ETM event; but the kernel address space
issue is not only limited to CoreSight event, it should be a common issue
for other events (e.g. PMU events), clock events for profiling eBPF
program. So this patch set tries to resolve it as a common issue for
arm/arm64 archs.
When implemented related code, I tried to use the API
machine__create_extra_kernel_maps(); but I found the 'perf script' tool
directly calls machine__get_kernel_start() instead of running into
the flow for machine__create_extra_kernel_maps(); this is the reason I
don't use machine__create_extra_kernel_maps() for tweaking kernel start
address and refactor machine__get_kernel_start() alternatively.
If there have better method to resolve this issue, any suggestions and
comments are very welcome!
[1] https://lkml.org/lkml/2019/6/19/1057
Leo Yan (2):
perf machine: Support arch's specific kernel start address
perf machine: arm/arm64: Improve completeness for kernel address space
tools/perf/Makefile.config | 22 ++++++++++++++++++++++
tools/perf/arch/arm/util/Build | 2 ++
tools/perf/arch/arm/util/machine.c | 17 +++++++++++++++++
tools/perf/arch/arm64/util/Build | 1 +
tools/perf/arch/arm64/util/machine.c | 17 +++++++++++++++++
tools/perf/arch/x86/util/machine.c | 10 ++++++++++
tools/perf/util/machine.c | 13 +++++++------
tools/perf/util/machine.h | 2 ++
8 files changed, 78 insertions(+), 6 deletions(-)
create mode 100644 tools/perf/arch/arm/util/machine.c
create mode 100644 tools/perf/arch/arm64/util/machine.c
--
2.17.1
^ permalink raw reply
* [PATCH v4 1/2] perf machine: Support arch's specific kernel start address
From: Leo Yan @ 2019-08-10 7:21 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo, Alexander Shishkin, Jiri Olsa,
Namhyung Kim, Alexei Starovoitov, Daniel Borkmann,
Martin KaFai Lau, Song Liu, Yonghong Song, David Miller,
Milian Wolff, Donald Yandt, Davidlohr Bueso, Wei Li,
Adrian Hunter, Mark Drayton, Tzvetomir Stoyanov (VMware),
linux-kernel, netdev, bpf, clang-built-linux, Mathieu Poirier
Cc: Leo Yan
In-Reply-To: <20190810072135.27072-1-leo.yan@linaro.org>
machine__get_kernel_start() gives out the kernel start address; some
architectures need to tweak the start address so that can reflect the
kernel start address correctly. This is not only for x86_64 arch, but
it is also required by other architectures, e.g. arm/arm64 needs to
tweak the kernel start address so can include the kernel memory regions
which are used before the '_stext' symbol.
This patch refactors machine__get_kernel_start() by adding a weak
arch__fix_kernel_text_start(), any architecture can implement it to
tweak its specific start address; this also allows the arch specific
code to be placed into 'arch' folder.
Signed-off-by: Leo Yan <leo.yan@linaro.org>
---
tools/perf/arch/x86/util/machine.c | 10 ++++++++++
tools/perf/util/machine.c | 13 +++++++------
tools/perf/util/machine.h | 2 ++
3 files changed, 19 insertions(+), 6 deletions(-)
diff --git a/tools/perf/arch/x86/util/machine.c b/tools/perf/arch/x86/util/machine.c
index 1e9ec783b9a1..9f012131534a 100644
--- a/tools/perf/arch/x86/util/machine.c
+++ b/tools/perf/arch/x86/util/machine.c
@@ -101,4 +101,14 @@ int machine__create_extra_kernel_maps(struct machine *machine,
return ret;
}
+void arch__fix_kernel_text_start(u64 *start)
+{
+ /*
+ * On x86_64, PTI entry trampolines are less than the
+ * start of kernel text, but still above 2^63. So leave
+ * kernel_start = 1ULL << 63 for x86_64.
+ */
+ *start = 1ULL << 63;
+}
+
#endif
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index f6ee7fbad3e4..603518835692 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -2671,6 +2671,10 @@ int machine__nr_cpus_avail(struct machine *machine)
return machine ? perf_env__nr_cpus_avail(machine->env) : 0;
}
+void __weak arch__fix_kernel_text_start(u64 *start __maybe_unused)
+{
+}
+
int machine__get_kernel_start(struct machine *machine)
{
struct map *map = machine__kernel_map(machine);
@@ -2687,14 +2691,11 @@ int machine__get_kernel_start(struct machine *machine)
machine->kernel_start = 1ULL << 63;
if (map) {
err = map__load(map);
- /*
- * On x86_64, PTI entry trampolines are less than the
- * start of kernel text, but still above 2^63. So leave
- * kernel_start = 1ULL << 63 for x86_64.
- */
- if (!err && !machine__is(machine, "x86_64"))
+ if (!err)
machine->kernel_start = map->start;
}
+
+ arch__fix_kernel_text_start(&machine->kernel_start);
return err;
}
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index ef803f08ae12..9cb459f4bfbc 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -278,6 +278,8 @@ void machine__get_kallsyms_filename(struct machine *machine, char *buf,
int machine__create_extra_kernel_maps(struct machine *machine,
struct dso *kernel);
+void arch__fix_kernel_text_start(u64 *start);
+
/* Kernel-space maps for symbols that are outside the main kernel map and module maps */
struct extra_kernel_map {
u64 start;
--
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