From 2290482379278e0254e6edfdb681d88359143fd1 Mon Sep 17 00:00:00 2001 From: Richard Cochran Date: Mon, 9 Apr 2018 00:03:14 -0700 Subject: net: dsa: mv88e6xxx: Fix receive time stamp race condition. The DSA stack passes received PTP frames to this driver via mv88e6xxx_port_rxtstamp() for deferred delivery. The driver then queues the frame and kicks the worker thread. The work callback reads out the latched receive time stamp and then works through the queue, delivering any non-matching frames without a time stamp. If a new frame arrives after the worker thread has read out the time stamp register but enters the queue before the worker finishes processing the queue, that frame will be delivered without a time stamp. This patch fixes the race by moving the queue onto a list on the stack before reading out the latched time stamp value. Fixes: c6fe0ad2c3499 ("net: dsa: mv88e6xxx: add rx/tx timestamping support") Signed-off-by: Richard Cochran Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/hwtstamp.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'drivers/net/dsa/mv88e6xxx') diff --git a/drivers/net/dsa/mv88e6xxx/hwtstamp.c b/drivers/net/dsa/mv88e6xxx/hwtstamp.c index ac7694c71266..a036c490b7ce 100644 --- a/drivers/net/dsa/mv88e6xxx/hwtstamp.c +++ b/drivers/net/dsa/mv88e6xxx/hwtstamp.c @@ -285,10 +285,18 @@ static void mv88e6xxx_get_rxts(struct mv88e6xxx_chip *chip, struct sk_buff_head *rxq) { u16 buf[4] = { 0 }, status, seq_id; - u64 ns, timelo, timehi; struct skb_shared_hwtstamps *shwt; + struct sk_buff_head received; + u64 ns, timelo, timehi; + unsigned long flags; int err; + /* The latched timestamp belongs to one of the received frames. */ + __skb_queue_head_init(&received); + spin_lock_irqsave(&rxq->lock, flags); + skb_queue_splice_tail_init(rxq, &received); + spin_unlock_irqrestore(&rxq->lock, flags); + mutex_lock(&chip->reg_lock); err = mv88e6xxx_port_ptp_read(chip, ps->port_id, reg, buf, ARRAY_SIZE(buf)); @@ -311,7 +319,7 @@ static void mv88e6xxx_get_rxts(struct mv88e6xxx_chip *chip, /* Since the device can only handle one time stamp at a time, * we purge any extra frames from the queue. */ - for ( ; skb; skb = skb_dequeue(rxq)) { + for ( ; skb; skb = __skb_dequeue(&received)) { if (mv88e6xxx_ts_valid(status) && seq_match(skb, seq_id)) { ns = timehi << 16 | timelo; -- cgit From 89f09048348936a9a8c5131c8538cc6ed26fd44c Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 25 Apr 2018 12:12:50 -0700 Subject: net: dsa: Pass stringset to ethtool operations Up until now we largely assumed that we were interested in ETH_SS_STATS type of strings for all ethtool operations, this is about to change with the introduction of additional string sets, e.g: ETH_SS_PHY_STATS. Update all functions to take an appropriate stringset argument and act on it when it is different than ETH_SS_STATS for now. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers/net/dsa/mv88e6xxx') diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 3d2091099f7f..8f92ccc0dd54 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -742,11 +742,14 @@ static void mv88e6xxx_atu_vtu_get_strings(uint8_t *data) } static void mv88e6xxx_get_strings(struct dsa_switch *ds, int port, - uint8_t *data) + u32 stringset, uint8_t *data) { struct mv88e6xxx_chip *chip = ds->priv; int count = 0; + if (stringset != ETH_SS_STATS) + return; + mutex_lock(&chip->reg_lock); if (chip->info->ops->stats_get_strings) @@ -789,12 +792,15 @@ static int mv88e6320_stats_get_sset_count(struct mv88e6xxx_chip *chip) STATS_TYPE_BANK1); } -static int mv88e6xxx_get_sset_count(struct dsa_switch *ds, int port) +static int mv88e6xxx_get_sset_count(struct dsa_switch *ds, int port, int sset) { struct mv88e6xxx_chip *chip = ds->priv; int serdes_count = 0; int count = 0; + if (sset != ETH_SS_STATS) + return 0; + mutex_lock(&chip->reg_lock); if (chip->info->ops->stats_get_sset_count) count = chip->info->ops->stats_get_sset_count(chip); -- cgit From 6c3442f5f85827e40e314a74a24b1428e78748c8 Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Fri, 27 Apr 2018 16:18:58 +0800 Subject: drivers: net: replace UINT64_MAX with U64_MAX U64_MAX is well defined now while the UINT64_MAX is not, so we fall back to drivers' own definition as below: #ifndef UINT64_MAX #define UINT64_MAX (u64)(~((u64)0)) #endif I believe this is in one phy driver then copied and pasted to other phy drivers. Replace the UINT64_MAX with U64_MAX to clean up the source code. Signed-off-by: Jisheng Zhang Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 6 +++--- drivers/net/dsa/mv88e6xxx/chip.h | 4 ---- 2 files changed, 3 insertions(+), 7 deletions(-) (limited to 'drivers/net/dsa/mv88e6xxx') diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 8f92ccc0dd54..a13a7005ffa0 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -665,13 +665,13 @@ static uint64_t _mv88e6xxx_get_ethtool_stat(struct mv88e6xxx_chip *chip, case STATS_TYPE_PORT: err = mv88e6xxx_port_read(chip, port, s->reg, ®); if (err) - return UINT64_MAX; + return U64_MAX; low = reg; if (s->size == 4) { err = mv88e6xxx_port_read(chip, port, s->reg + 1, ®); if (err) - return UINT64_MAX; + return U64_MAX; high = reg; } break; @@ -685,7 +685,7 @@ static uint64_t _mv88e6xxx_get_ethtool_stat(struct mv88e6xxx_chip *chip, mv88e6xxx_g1_stats_read(chip, reg + 1, &high); break; default: - return UINT64_MAX; + return U64_MAX; } value = (((u64)high) << 16) | low; return value; diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h index 80490f66bc06..4163c8099d0b 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.h +++ b/drivers/net/dsa/mv88e6xxx/chip.h @@ -21,10 +21,6 @@ #include #include -#ifndef UINT64_MAX -#define UINT64_MAX (u64)(~((u64)0)) -#endif - #define SMI_CMD 0x00 #define SMI_CMD_BUSY BIT(15) #define SMI_CMD_CLAUSE_22 BIT(12) -- cgit From b28f872dc48a4d55cba9d51cf3bac03ca32b2747 Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Thu, 26 Apr 2018 21:56:44 -0400 Subject: net: dsa: mv88e6xxx: move trunk setup Move the trunking setup out of Global 2 specific setup into the top level mv88e6xxx_setup function. Note that the 88E6390 family calls this LAG instead of Trunk and supports 32 possible ID routing vectors, with LAG ID bit 4 being placed in Global 2 register 0x1D... We don't need Trunk (or LAG) IDs for the moment, thus keep it simple. Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 13 +++++++++++++ drivers/net/dsa/mv88e6xxx/global2.c | 7 +------ drivers/net/dsa/mv88e6xxx/global2.h | 7 +++++++ 3 files changed, 21 insertions(+), 6 deletions(-) (limited to 'drivers/net/dsa/mv88e6xxx') diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index a13a7005ffa0..02ff41338491 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -1026,6 +1026,15 @@ static void mv88e6xxx_port_stp_state_set(struct dsa_switch *ds, int port, dev_err(ds->dev, "p%d: failed to update state\n", port); } +static int mv88e6xxx_trunk_setup(struct mv88e6xxx_chip *chip) +{ + /* Clear all trunk masks and mapping */ + if (chip->info->global2_addr) + return mv88e6xxx_g2_trunk_clear(chip); + + return 0; +} + static int mv88e6xxx_pot_setup(struct mv88e6xxx_chip *chip) { if (chip->info->ops->pot_clear) @@ -2239,6 +2248,10 @@ static int mv88e6xxx_setup(struct dsa_switch *ds) if (err) goto unlock; + err = mv88e6xxx_trunk_setup(chip); + if (err) + goto unlock; + /* Setup PTP Hardware Clock and timestamping */ if (chip->info->ptp_support) { err = mv88e6xxx_ptp_setup(chip); diff --git a/drivers/net/dsa/mv88e6xxx/global2.c b/drivers/net/dsa/mv88e6xxx/global2.c index 0ce627fded48..3f24763aedc5 100644 --- a/drivers/net/dsa/mv88e6xxx/global2.c +++ b/drivers/net/dsa/mv88e6xxx/global2.c @@ -174,7 +174,7 @@ static int mv88e6xxx_g2_trunk_mapping_write(struct mv88e6xxx_chip *chip, int id, return mv88e6xxx_g2_update(chip, MV88E6XXX_G2_TRUNK_MAPPING, val); } -static int mv88e6xxx_g2_clear_trunk(struct mv88e6xxx_chip *chip) +int mv88e6xxx_g2_trunk_clear(struct mv88e6xxx_chip *chip) { const u16 port_mask = BIT(mv88e6xxx_num_ports(chip)) - 1; int i, err; @@ -1159,10 +1159,5 @@ int mv88e6xxx_g2_setup(struct mv88e6xxx_chip *chip) if (err) return err; - /* Clear all trunk masks and mapping. */ - err = mv88e6xxx_g2_clear_trunk(chip); - if (err) - return err; - return 0; } diff --git a/drivers/net/dsa/mv88e6xxx/global2.h b/drivers/net/dsa/mv88e6xxx/global2.h index 520ec70d32e8..7bd4ab31a93e 100644 --- a/drivers/net/dsa/mv88e6xxx/global2.h +++ b/drivers/net/dsa/mv88e6xxx/global2.h @@ -327,6 +327,8 @@ int mv88e6352_g2_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip); int mv88e6xxx_g2_pot_clear(struct mv88e6xxx_chip *chip); +int mv88e6xxx_g2_trunk_clear(struct mv88e6xxx_chip *chip); + extern const struct mv88e6xxx_irq_ops mv88e6097_watchdog_ops; extern const struct mv88e6xxx_irq_ops mv88e6390_watchdog_ops; @@ -495,6 +497,11 @@ static inline int mv88e6xxx_g2_scratch_gpio_set_smi(struct mv88e6xxx_chip *chip, return -EOPNOTSUPP; } +static inline int mv88e6xxx_g2_trunk_clear(struct mv88e6xxx_chip *chip) +{ + return -EOPNOTSUPP; +} + #endif /* CONFIG_NET_DSA_MV88E6XXX_GLOBAL2 */ #endif /* _MV88E6XXX_GLOBAL2_H */ -- cgit From c7f047b6c7bc3f6740a8fb1f2d03ecb19022fdc0 Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Thu, 26 Apr 2018 21:56:45 -0400 Subject: net: dsa: mv88e6xxx: move device mapping setup Move the Device Mapping setup out of the specific Global 2 code, into the top level device setup function. Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 27 +++++++++++++++++++++++++++ drivers/net/dsa/mv88e6xxx/global2.c | 37 ++++++------------------------------- drivers/net/dsa/mv88e6xxx/global2.h | 12 +++++++++++- 3 files changed, 44 insertions(+), 32 deletions(-) (limited to 'drivers/net/dsa/mv88e6xxx') diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 02ff41338491..d1ca4d6ef9be 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -1026,6 +1026,29 @@ static void mv88e6xxx_port_stp_state_set(struct dsa_switch *ds, int port, dev_err(ds->dev, "p%d: failed to update state\n", port); } +static int mv88e6xxx_devmap_setup(struct mv88e6xxx_chip *chip) +{ + int target, port; + int err; + + if (!chip->info->global2_addr) + return 0; + + /* Initialize the routing port to the 32 possible target devices */ + for (target = 0; target < 32; target++) { + port = 0x1f; + if (target < DSA_MAX_SWITCHES) + if (chip->ds->rtable[target] != DSA_RTABLE_NONE) + port = chip->ds->rtable[target]; + + err = mv88e6xxx_g2_device_mapping_write(chip, target, port); + if (err) + return err; + } + + return 0; +} + static int mv88e6xxx_trunk_setup(struct mv88e6xxx_chip *chip) { /* Clear all trunk masks and mapping */ @@ -2252,6 +2275,10 @@ static int mv88e6xxx_setup(struct dsa_switch *ds) if (err) goto unlock; + err = mv88e6xxx_devmap_setup(chip); + if (err) + goto unlock; + /* Setup PTP Hardware Clock and timestamping */ if (chip->info->ptp_support) { err = mv88e6xxx_ptp_setup(chip); diff --git a/drivers/net/dsa/mv88e6xxx/global2.c b/drivers/net/dsa/mv88e6xxx/global2.c index 3f24763aedc5..96e74d8d500d 100644 --- a/drivers/net/dsa/mv88e6xxx/global2.c +++ b/drivers/net/dsa/mv88e6xxx/global2.c @@ -119,37 +119,17 @@ int mv88e6352_g2_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip) /* Offset 0x06: Device Mapping Table register */ -static int mv88e6xxx_g2_device_mapping_write(struct mv88e6xxx_chip *chip, - int target, int port) +int mv88e6xxx_g2_device_mapping_write(struct mv88e6xxx_chip *chip, int target, + int port) { - u16 val = (target << 8) | (port & 0xf); + u16 val = (target << 8) | (port & 0x1f); + /* Modern chips use 5 bits to define a device mapping port, + * but bit 4 is reserved on older chips, so it is safe to use. + */ return mv88e6xxx_g2_update(chip, MV88E6XXX_G2_DEVICE_MAPPING, val); } -static int mv88e6xxx_g2_set_device_mapping(struct mv88e6xxx_chip *chip) -{ - int target, port; - int err; - - /* Initialize the routing port to the 32 possible target devices */ - for (target = 0; target < 32; ++target) { - port = 0xf; - - if (target < DSA_MAX_SWITCHES) { - port = chip->ds->rtable[target]; - if (port == DSA_RTABLE_NONE) - port = 0xf; - } - - err = mv88e6xxx_g2_device_mapping_write(chip, target, port); - if (err) - break; - } - - return err; -} - /* Offset 0x07: Trunk Mask Table register */ static int mv88e6xxx_g2_trunk_mask_write(struct mv88e6xxx_chip *chip, int num, @@ -1154,10 +1134,5 @@ int mv88e6xxx_g2_setup(struct mv88e6xxx_chip *chip) if (err) return err; - /* Program the DSA routing table. */ - err = mv88e6xxx_g2_set_device_mapping(chip); - if (err) - return err; - return 0; } diff --git a/drivers/net/dsa/mv88e6xxx/global2.h b/drivers/net/dsa/mv88e6xxx/global2.h index 7bd4ab31a93e..46913a289255 100644 --- a/drivers/net/dsa/mv88e6xxx/global2.h +++ b/drivers/net/dsa/mv88e6xxx/global2.h @@ -60,7 +60,8 @@ #define MV88E6XXX_G2_DEVICE_MAPPING 0x06 #define MV88E6XXX_G2_DEVICE_MAPPING_UPDATE 0x8000 #define MV88E6XXX_G2_DEVICE_MAPPING_DEV_MASK 0x1f00 -#define MV88E6XXX_G2_DEVICE_MAPPING_PORT_MASK 0x000f +#define MV88E6352_G2_DEVICE_MAPPING_PORT_MASK 0x000f +#define MV88E6390_G2_DEVICE_MAPPING_PORT_MASK 0x001f /* Offset 0x07: Trunk Mask Table Register */ #define MV88E6XXX_G2_TRUNK_MASK 0x07 @@ -329,6 +330,9 @@ int mv88e6xxx_g2_pot_clear(struct mv88e6xxx_chip *chip); int mv88e6xxx_g2_trunk_clear(struct mv88e6xxx_chip *chip); +int mv88e6xxx_g2_device_mapping_write(struct mv88e6xxx_chip *chip, int target, + int port); + extern const struct mv88e6xxx_irq_ops mv88e6097_watchdog_ops; extern const struct mv88e6xxx_irq_ops mv88e6390_watchdog_ops; @@ -502,6 +506,12 @@ static inline int mv88e6xxx_g2_trunk_clear(struct mv88e6xxx_chip *chip) return -EOPNOTSUPP; } +static inline int mv88e6xxx_g2_device_mapping_write(struct mv88e6xxx_chip *chip, + int target, int port) +{ + return -EOPNOTSUPP; +} + #endif /* CONFIG_NET_DSA_MV88E6XXX_GLOBAL2 */ #endif /* _MV88E6XXX_GLOBAL2_H */ -- cgit From 5d49d60307aaa69541beafdd17bd3d0ea238732b Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Thu, 26 Apr 2018 21:56:46 -0400 Subject: net: dsa: mv88e6xxx: remove Global 2 setup The remaining values written to the Switch Management Register in the mv88e6xxx_g2_setup function are specific to 88E6352 and older, and are the default values anyway. Thus remove completely this function. The mv88e6xxx driver no more contains setup code to access arbitrary Global 2 registers. Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 7 ------- drivers/net/dsa/mv88e6xxx/global2.c | 18 ------------------ drivers/net/dsa/mv88e6xxx/global2.h | 6 ------ 3 files changed, 31 deletions(-) (limited to 'drivers/net/dsa/mv88e6xxx') diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index d1ca4d6ef9be..9d62e4acc01b 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -2228,13 +2228,6 @@ static int mv88e6xxx_setup(struct dsa_switch *ds) if (err) goto unlock; - /* Setup Switch Global 2 Registers */ - if (chip->info->global2_addr) { - err = mv88e6xxx_g2_setup(chip); - if (err) - goto unlock; - } - err = mv88e6xxx_irl_setup(chip); if (err) goto unlock; diff --git a/drivers/net/dsa/mv88e6xxx/global2.c b/drivers/net/dsa/mv88e6xxx/global2.c index 96e74d8d500d..e6d658181b27 100644 --- a/drivers/net/dsa/mv88e6xxx/global2.c +++ b/drivers/net/dsa/mv88e6xxx/global2.c @@ -1118,21 +1118,3 @@ void mv88e6xxx_g2_irq_mdio_free(struct mv88e6xxx_chip *chip, for (phy = 0; phy < chip->info->num_internal_phys; phy++) irq_dispose_mapping(bus->irq[phy]); } - -int mv88e6xxx_g2_setup(struct mv88e6xxx_chip *chip) -{ - u16 reg; - int err; - - /* Ignore removed tag data on doubly tagged packets, disable - * flow control messages, force flow control priority to the - * highest, and send all special multicast frames to the CPU - * port at the highest priority. - */ - reg = MV88E6XXX_G2_SWITCH_MGMT_FORCE_FLOW_CTL_PRI | (0x7 << 4); - err = mv88e6xxx_g2_write(chip, MV88E6XXX_G2_SWITCH_MGMT, reg); - if (err) - return err; - - return 0; -} diff --git a/drivers/net/dsa/mv88e6xxx/global2.h b/drivers/net/dsa/mv88e6xxx/global2.h index 46913a289255..37e8ce2c72a0 100644 --- a/drivers/net/dsa/mv88e6xxx/global2.h +++ b/drivers/net/dsa/mv88e6xxx/global2.h @@ -314,7 +314,6 @@ int mv88e6xxx_g2_pvt_write(struct mv88e6xxx_chip *chip, int src_dev, int src_port, u16 data); int mv88e6xxx_g2_misc_4_bit_port(struct mv88e6xxx_chip *chip); -int mv88e6xxx_g2_setup(struct mv88e6xxx_chip *chip); int mv88e6xxx_g2_irq_setup(struct mv88e6xxx_chip *chip); void mv88e6xxx_g2_irq_free(struct mv88e6xxx_chip *chip); @@ -447,11 +446,6 @@ static inline int mv88e6xxx_g2_misc_4_bit_port(struct mv88e6xxx_chip *chip) return -EOPNOTSUPP; } -static inline int mv88e6xxx_g2_setup(struct mv88e6xxx_chip *chip) -{ - return -EOPNOTSUPP; -} - static inline int mv88e6xxx_g2_irq_setup(struct mv88e6xxx_chip *chip) { return -EOPNOTSUPP; -- cgit From 9255bacd57a5a247be91ce2b81ff09e15a0b8822 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Sat, 5 May 2018 20:58:22 +0200 Subject: net: dsa: mv88e6xxx: Fix PHY interrupts by parameterising PHY base address Most of the mv88e6xxx switches have the PHYs at address 0, 1, 2, ... The 6341 however has the PHYs at 0x10, 0x11, 0x12. Add a parameter to the info structure for this base address. Testing of 6f88284f3bd7 ("net: dsa: mv88e6xxx: Add MDIO interrupts for internal PHYs") was performed on the 6341. So it works only on the 6341. Use this base information to correctly set the interrupt. Fixes: 6f88284f3bd7 ("net: dsa: mv88e6xxx: Add MDIO interrupts for internal PHYs") Signed-off-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 26 ++++++++++++++++++++++++++ drivers/net/dsa/mv88e6xxx/chip.h | 1 + drivers/net/dsa/mv88e6xxx/global2.c | 2 +- 3 files changed, 28 insertions(+), 1 deletion(-) (limited to 'drivers/net/dsa/mv88e6xxx') diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 3d2091099f7f..5b4374f21d76 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -3370,6 +3370,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .num_internal_phys = 5, .max_vid = 4095, .port_base_addr = 0x10, + .phy_base_addr = 0x0, .global1_addr = 0x1b, .global2_addr = 0x1c, .age_time_coeff = 15000, @@ -3391,6 +3392,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .num_internal_phys = 0, .max_vid = 4095, .port_base_addr = 0x10, + .phy_base_addr = 0x0, .global1_addr = 0x1b, .global2_addr = 0x1c, .age_time_coeff = 15000, @@ -3410,6 +3412,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .num_internal_phys = 8, .max_vid = 4095, .port_base_addr = 0x10, + .phy_base_addr = 0x0, .global1_addr = 0x1b, .global2_addr = 0x1c, .age_time_coeff = 15000, @@ -3431,6 +3434,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .num_internal_phys = 5, .max_vid = 4095, .port_base_addr = 0x10, + .phy_base_addr = 0x0, .global1_addr = 0x1b, .global2_addr = 0x1c, .age_time_coeff = 15000, @@ -3452,6 +3456,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .num_internal_phys = 0, .max_vid = 4095, .port_base_addr = 0x10, + .phy_base_addr = 0x0, .global1_addr = 0x1b, .global2_addr = 0x1c, .age_time_coeff = 15000, @@ -3472,6 +3477,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .num_gpio = 11, .max_vid = 4095, .port_base_addr = 0x10, + .phy_base_addr = 0x10, .global1_addr = 0x1b, .global2_addr = 0x1c, .age_time_coeff = 3750, @@ -3493,6 +3499,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .num_internal_phys = 5, .max_vid = 4095, .port_base_addr = 0x10, + .phy_base_addr = 0x0, .global1_addr = 0x1b, .global2_addr = 0x1c, .age_time_coeff = 15000, @@ -3514,6 +3521,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .num_internal_phys = 0, .max_vid = 4095, .port_base_addr = 0x10, + .phy_base_addr = 0x0, .global1_addr = 0x1b, .global2_addr = 0x1c, .age_time_coeff = 15000, @@ -3535,6 +3543,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .num_internal_phys = 5, .max_vid = 4095, .port_base_addr = 0x10, + .phy_base_addr = 0x0, .global1_addr = 0x1b, .global2_addr = 0x1c, .age_time_coeff = 15000, @@ -3557,6 +3566,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .num_gpio = 15, .max_vid = 4095, .port_base_addr = 0x10, + .phy_base_addr = 0x0, .global1_addr = 0x1b, .global2_addr = 0x1c, .age_time_coeff = 15000, @@ -3578,6 +3588,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .num_internal_phys = 5, .max_vid = 4095, .port_base_addr = 0x10, + .phy_base_addr = 0x0, .global1_addr = 0x1b, .global2_addr = 0x1c, .age_time_coeff = 15000, @@ -3600,6 +3611,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .num_gpio = 15, .max_vid = 4095, .port_base_addr = 0x10, + .phy_base_addr = 0x0, .global1_addr = 0x1b, .global2_addr = 0x1c, .age_time_coeff = 15000, @@ -3621,6 +3633,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .num_internal_phys = 0, .max_vid = 4095, .port_base_addr = 0x10, + .phy_base_addr = 0x0, .global1_addr = 0x1b, .global2_addr = 0x1c, .age_time_coeff = 15000, @@ -3641,6 +3654,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .num_gpio = 16, .max_vid = 8191, .port_base_addr = 0x0, + .phy_base_addr = 0x0, .global1_addr = 0x1b, .global2_addr = 0x1c, .tag_protocol = DSA_TAG_PROTO_DSA, @@ -3663,6 +3677,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .num_gpio = 16, .max_vid = 8191, .port_base_addr = 0x0, + .phy_base_addr = 0x0, .global1_addr = 0x1b, .global2_addr = 0x1c, .age_time_coeff = 3750, @@ -3684,6 +3699,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .num_internal_phys = 11, .max_vid = 8191, .port_base_addr = 0x0, + .phy_base_addr = 0x0, .global1_addr = 0x1b, .global2_addr = 0x1c, .age_time_coeff = 3750, @@ -3707,6 +3723,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .num_gpio = 15, .max_vid = 4095, .port_base_addr = 0x10, + .phy_base_addr = 0x0, .global1_addr = 0x1b, .global2_addr = 0x1c, .age_time_coeff = 15000, @@ -3730,6 +3747,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .num_gpio = 16, .max_vid = 8191, .port_base_addr = 0x0, + .phy_base_addr = 0x0, .global1_addr = 0x1b, .global2_addr = 0x1c, .age_time_coeff = 3750, @@ -3753,6 +3771,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .num_gpio = 15, .max_vid = 4095, .port_base_addr = 0x10, + .phy_base_addr = 0x0, .global1_addr = 0x1b, .global2_addr = 0x1c, .age_time_coeff = 15000, @@ -3776,6 +3795,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .num_gpio = 15, .max_vid = 4095, .port_base_addr = 0x10, + .phy_base_addr = 0x0, .global1_addr = 0x1b, .global2_addr = 0x1c, .age_time_coeff = 15000, @@ -3798,6 +3818,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .num_gpio = 11, .max_vid = 4095, .port_base_addr = 0x10, + .phy_base_addr = 0x10, .global1_addr = 0x1b, .global2_addr = 0x1c, .age_time_coeff = 3750, @@ -3820,6 +3841,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .num_internal_phys = 5, .max_vid = 4095, .port_base_addr = 0x10, + .phy_base_addr = 0x0, .global1_addr = 0x1b, .global2_addr = 0x1c, .age_time_coeff = 15000, @@ -3841,6 +3863,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .num_internal_phys = 5, .max_vid = 4095, .port_base_addr = 0x10, + .phy_base_addr = 0x0, .global1_addr = 0x1b, .global2_addr = 0x1c, .age_time_coeff = 15000, @@ -3863,6 +3886,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .num_gpio = 15, .max_vid = 4095, .port_base_addr = 0x10, + .phy_base_addr = 0x0, .global1_addr = 0x1b, .global2_addr = 0x1c, .age_time_coeff = 15000, @@ -3885,6 +3909,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .num_gpio = 16, .max_vid = 8191, .port_base_addr = 0x0, + .phy_base_addr = 0x0, .global1_addr = 0x1b, .global2_addr = 0x1c, .age_time_coeff = 3750, @@ -3907,6 +3932,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .num_gpio = 16, .max_vid = 8191, .port_base_addr = 0x0, + .phy_base_addr = 0x0, .global1_addr = 0x1b, .global2_addr = 0x1c, .age_time_coeff = 3750, diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h index 80490f66bc06..12b7f4649b25 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.h +++ b/drivers/net/dsa/mv88e6xxx/chip.h @@ -114,6 +114,7 @@ struct mv88e6xxx_info { unsigned int num_gpio; unsigned int max_vid; unsigned int port_base_addr; + unsigned int phy_base_addr; unsigned int global1_addr; unsigned int global2_addr; unsigned int age_time_coeff; diff --git a/drivers/net/dsa/mv88e6xxx/global2.c b/drivers/net/dsa/mv88e6xxx/global2.c index 0ce627fded48..8d22d66d84b7 100644 --- a/drivers/net/dsa/mv88e6xxx/global2.c +++ b/drivers/net/dsa/mv88e6xxx/global2.c @@ -1118,7 +1118,7 @@ int mv88e6xxx_g2_irq_mdio_setup(struct mv88e6xxx_chip *chip, err = irq; goto out; } - bus->irq[chip->info->port_base_addr + phy] = irq; + bus->irq[chip->info->phy_base_addr + phy] = irq; } return 0; out: -- cgit From 5bafeb6e7e878ce41c834806239f8c629a59d40a Mon Sep 17 00:00:00 2001 From: Marek Behún Date: Fri, 4 May 2018 19:26:10 +0200 Subject: net: dsa: mv88e6xxx: 88E6141/6341 SERDES support The 88E6141/6341 switches (also known as Topaz) have 1 SGMII lane, which can be configured the same way as the SERDES lane on 88E6390. Signed-off-by: Marek Behun Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 2 ++ drivers/net/dsa/mv88e6xxx/serdes.c | 20 ++++++++++++++++++++ drivers/net/dsa/mv88e6xxx/serdes.h | 3 +++ 3 files changed, 25 insertions(+) (limited to 'drivers/net/dsa/mv88e6xxx') diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 9d62e4acc01b..e7e079b1888c 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -2529,6 +2529,7 @@ static const struct mv88e6xxx_ops mv88e6085_ops = { .reset = mv88e6185_g1_reset, .vtu_getnext = mv88e6352_g1_vtu_getnext, .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, + .serdes_power = mv88e6341_serdes_power, }; static const struct mv88e6xxx_ops mv88e6095_ops = { @@ -2848,6 +2849,7 @@ static const struct mv88e6xxx_ops mv88e6175_ops = { .reset = mv88e6352_g1_reset, .vtu_getnext = mv88e6352_g1_vtu_getnext, .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, + .serdes_power = mv88e6341_serdes_power, }; static const struct mv88e6xxx_ops mv88e6176_ops = { diff --git a/drivers/net/dsa/mv88e6xxx/serdes.c b/drivers/net/dsa/mv88e6xxx/serdes.c index fb058fd35c0d..880b2cf0a530 100644 --- a/drivers/net/dsa/mv88e6xxx/serdes.c +++ b/drivers/net/dsa/mv88e6xxx/serdes.c @@ -326,3 +326,23 @@ int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on) return 0; } + +int mv88e6341_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on) +{ + int err; + u8 cmode; + + if (port != 5) + return 0; + + err = mv88e6xxx_port_get_cmode(chip, port, &cmode); + if (err) + return err; + + if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASE_X || + cmode == MV88E6XXX_PORT_STS_CMODE_SGMII || + cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX) + return mv88e6390_serdes_sgmii(chip, MV88E6341_ADDR_SERDES, on); + + return 0; +} diff --git a/drivers/net/dsa/mv88e6xxx/serdes.h b/drivers/net/dsa/mv88e6xxx/serdes.h index 1897c01c6e19..b6e5fbd46b5e 100644 --- a/drivers/net/dsa/mv88e6xxx/serdes.h +++ b/drivers/net/dsa/mv88e6xxx/serdes.h @@ -19,6 +19,8 @@ #define MV88E6352_ADDR_SERDES 0x0f #define MV88E6352_SERDES_PAGE_FIBER 0x01 +#define MV88E6341_ADDR_SERDES 0x15 + #define MV88E6390_PORT9_LANE0 0x09 #define MV88E6390_PORT9_LANE1 0x12 #define MV88E6390_PORT9_LANE2 0x13 @@ -42,6 +44,7 @@ #define MV88E6390_SGMII_CONTROL_LOOPBACK BIT(14) #define MV88E6390_SGMII_CONTROL_PDOWN BIT(11) +int mv88e6341_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on); int mv88e6352_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on); int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on); int mv88e6352_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port); -- cgit From 02317e68369b0feecc18e791016d38a8e4df35f7 Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Wed, 9 May 2018 11:38:49 -0400 Subject: net: dsa: mv88e6xxx: add a cascade port op Only the 88E6185 family has bits 15:12 Cascade Port bits in the Global Control 2 register. Hence inconsistent values are actually written in this register for other families. Add a .set_cascade_port operation to isolate the 88E6185 case, and call it from the device mapping setup function. Signed-off-by: Vivien Didelot Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 10 +++++++++- drivers/net/dsa/mv88e6xxx/chip.h | 6 ++++++ drivers/net/dsa/mv88e6xxx/global1.c | 23 +++++++++++++++++++++++ drivers/net/dsa/mv88e6xxx/global1.h | 7 +++++-- 4 files changed, 43 insertions(+), 3 deletions(-) (limited to 'drivers/net/dsa/mv88e6xxx') diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index e7e079b1888c..9b61d5b65b0f 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -1046,6 +1046,13 @@ static int mv88e6xxx_devmap_setup(struct mv88e6xxx_chip *chip) return err; } + if (chip->info->ops->set_cascade_port) { + port = MV88E6XXX_CASCADE_PORT_MULTIPLE; + err = chip->info->ops->set_cascade_port(chip, port); + if (err) + return err; + } + return 0; } @@ -2158,7 +2165,6 @@ static int mv88e6xxx_g1_setup(struct mv88e6xxx_chip *chip) /* Disable remote management, and set the switch's DSA device number. */ err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL2, - MV88E6XXX_G1_CTL2_MULTIPLE_CASCADE | (ds->index & 0x1f)); if (err) return err; @@ -2643,6 +2649,7 @@ static const struct mv88e6xxx_ops mv88e6131_ops = { .watchdog_ops = &mv88e6097_watchdog_ops, .mgmt_rsvd2cpu = mv88e6185_g2_mgmt_rsvd2cpu, .ppu_enable = mv88e6185_g1_ppu_enable, + .set_cascade_port = mv88e6185_g1_set_cascade_port, .ppu_disable = mv88e6185_g1_ppu_disable, .reset = mv88e6185_g1_reset, .vtu_getnext = mv88e6185_g1_vtu_getnext, @@ -2911,6 +2918,7 @@ static const struct mv88e6xxx_ops mv88e6185_ops = { .set_egress_port = mv88e6095_g1_set_egress_port, .watchdog_ops = &mv88e6097_watchdog_ops, .mgmt_rsvd2cpu = mv88e6185_g2_mgmt_rsvd2cpu, + .set_cascade_port = mv88e6185_g1_set_cascade_port, .ppu_enable = mv88e6185_g1_ppu_enable, .ppu_disable = mv88e6185_g1_ppu_disable, .reset = mv88e6185_g1_reset, diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h index 4163c8099d0b..62234c2287a2 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.h +++ b/drivers/net/dsa/mv88e6xxx/chip.h @@ -401,6 +401,12 @@ struct mv88e6xxx_ops { uint64_t *data); int (*set_cpu_port)(struct mv88e6xxx_chip *chip, int port); int (*set_egress_port)(struct mv88e6xxx_chip *chip, int port); + +#define MV88E6XXX_CASCADE_PORT_NONE 0xe +#define MV88E6XXX_CASCADE_PORT_MULTIPLE 0xf + + int (*set_cascade_port)(struct mv88e6xxx_chip *chip, int port); + const struct mv88e6xxx_irq_ops *watchdog_ops; int (*mgmt_rsvd2cpu)(struct mv88e6xxx_chip *chip); diff --git a/drivers/net/dsa/mv88e6xxx/global1.c b/drivers/net/dsa/mv88e6xxx/global1.c index b43bd6476632..6eb4eca7ca5b 100644 --- a/drivers/net/dsa/mv88e6xxx/global1.c +++ b/drivers/net/dsa/mv88e6xxx/global1.c @@ -350,6 +350,29 @@ int mv88e6390_g1_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip) /* Offset 0x1c: Global Control 2 */ +static int mv88e6xxx_g1_ctl2_mask(struct mv88e6xxx_chip *chip, u16 mask, + u16 val) +{ + u16 reg; + int err; + + err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL2, ®); + if (err) + return err; + + reg &= ~mask; + reg |= val & mask; + + return mv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL2, reg); +} + +int mv88e6185_g1_set_cascade_port(struct mv88e6xxx_chip *chip, int port) +{ + const u16 mask = MV88E6185_G1_CTL2_CASCADE_PORT_MASK; + + return mv88e6xxx_g1_ctl2_mask(chip, mask, port << __bf_shf(mask)); +} + int mv88e6390_g1_stats_set_histogram(struct mv88e6xxx_chip *chip) { u16 val; diff --git a/drivers/net/dsa/mv88e6xxx/global1.h b/drivers/net/dsa/mv88e6xxx/global1.h index 6aee7316fea6..bcbb8046ad63 100644 --- a/drivers/net/dsa/mv88e6xxx/global1.h +++ b/drivers/net/dsa/mv88e6xxx/global1.h @@ -201,11 +201,12 @@ /* Offset 0x1C: Global Control 2 */ #define MV88E6XXX_G1_CTL2 0x1c -#define MV88E6XXX_G1_CTL2_NO_CASCADE 0xe000 -#define MV88E6XXX_G1_CTL2_MULTIPLE_CASCADE 0xf000 #define MV88E6XXX_G1_CTL2_HIST_RX 0x0040 #define MV88E6XXX_G1_CTL2_HIST_TX 0x0080 #define MV88E6XXX_G1_CTL2_HIST_RX_TX 0x00c0 +#define MV88E6185_G1_CTL2_CASCADE_PORT_MASK 0xf000 +#define MV88E6185_G1_CTL2_CASCADE_PORT_NONE 0xe000 +#define MV88E6185_G1_CTL2_CASCADE_PORT_MULTI 0xf000 /* Offset 0x1D: Stats Operation Register */ #define MV88E6XXX_G1_STATS_OP 0x1d @@ -253,6 +254,8 @@ int mv88e6095_g1_set_cpu_port(struct mv88e6xxx_chip *chip, int port); int mv88e6390_g1_set_cpu_port(struct mv88e6xxx_chip *chip, int port); int mv88e6390_g1_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip); +int mv88e6185_g1_set_cascade_port(struct mv88e6xxx_chip *chip, int port); + int mv88e6xxx_g1_atu_set_learn2all(struct mv88e6xxx_chip *chip, bool learn2all); int mv88e6xxx_g1_atu_set_age_time(struct mv88e6xxx_chip *chip, unsigned int msecs); -- cgit From 23c9891996959dbde59333b8ed997d66b44fb3ff Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Wed, 9 May 2018 11:38:50 -0400 Subject: net: dsa: mv88e6xxx: set device number All Marvell switches supported by mv88e6xxx have to set their device number in the Global Control 2 register. Extract this in a read then write function, called from the device mapping setup code. Signed-off-by: Vivien Didelot Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 11 ++++------- drivers/net/dsa/mv88e6xxx/global1.c | 7 +++++++ drivers/net/dsa/mv88e6xxx/global1.h | 3 +++ 3 files changed, 14 insertions(+), 7 deletions(-) (limited to 'drivers/net/dsa/mv88e6xxx') diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 9b61d5b65b0f..ef753ed89b30 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -1053,6 +1053,10 @@ static int mv88e6xxx_devmap_setup(struct mv88e6xxx_chip *chip) return err; } + err = mv88e6xxx_g1_set_device_number(chip, chip->ds->index); + if (err) + return err; + return 0; } @@ -2160,15 +2164,8 @@ static int mv88e6xxx_set_ageing_time(struct dsa_switch *ds, static int mv88e6xxx_g1_setup(struct mv88e6xxx_chip *chip) { - struct dsa_switch *ds = chip->ds; int err; - /* Disable remote management, and set the switch's DSA device number. */ - err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL2, - (ds->index & 0x1f)); - if (err) - return err; - /* Configure the IP ToS mapping registers. */ err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_IP_PRI_0, 0x0000); if (err) diff --git a/drivers/net/dsa/mv88e6xxx/global1.c b/drivers/net/dsa/mv88e6xxx/global1.c index 6eb4eca7ca5b..89c6330c53eb 100644 --- a/drivers/net/dsa/mv88e6xxx/global1.c +++ b/drivers/net/dsa/mv88e6xxx/global1.c @@ -389,6 +389,13 @@ int mv88e6390_g1_stats_set_histogram(struct mv88e6xxx_chip *chip) return err; } +int mv88e6xxx_g1_set_device_number(struct mv88e6xxx_chip *chip, int index) +{ + return mv88e6xxx_g1_ctl2_mask(chip, + MV88E6XXX_G1_CTL2_DEVICE_NUMBER_MASK, + index); +} + /* Offset 0x1d: Statistics Operation 2 */ int mv88e6xxx_g1_stats_wait(struct mv88e6xxx_chip *chip) diff --git a/drivers/net/dsa/mv88e6xxx/global1.h b/drivers/net/dsa/mv88e6xxx/global1.h index bcbb8046ad63..8b043e813761 100644 --- a/drivers/net/dsa/mv88e6xxx/global1.h +++ b/drivers/net/dsa/mv88e6xxx/global1.h @@ -207,6 +207,7 @@ #define MV88E6185_G1_CTL2_CASCADE_PORT_MASK 0xf000 #define MV88E6185_G1_CTL2_CASCADE_PORT_NONE 0xe000 #define MV88E6185_G1_CTL2_CASCADE_PORT_MULTI 0xf000 +#define MV88E6XXX_G1_CTL2_DEVICE_NUMBER_MASK 0x001f /* Offset 0x1D: Stats Operation Register */ #define MV88E6XXX_G1_STATS_OP 0x1d @@ -256,6 +257,8 @@ int mv88e6390_g1_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip); int mv88e6185_g1_set_cascade_port(struct mv88e6xxx_chip *chip, int port); +int mv88e6xxx_g1_set_device_number(struct mv88e6xxx_chip *chip, int index); + int mv88e6xxx_g1_atu_set_learn2all(struct mv88e6xxx_chip *chip, bool learn2all); int mv88e6xxx_g1_atu_set_age_time(struct mv88e6xxx_chip *chip, unsigned int msecs); -- cgit From 9e5baf9b363673a8f78508c99a9d815da6ea7133 Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Wed, 9 May 2018 11:38:51 -0400 Subject: net: dsa: mv88e6xxx: add RMU disable op The RMU mode bits moved a lot within the Global Control 2 register of the Marvell switch families. Add an .rmu_disable op to support at least 3 known alternatives. Signed-off-by: Vivien Didelot Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 24 ++++++++++++++++++++++++ drivers/net/dsa/mv88e6xxx/chip.h | 3 +++ drivers/net/dsa/mv88e6xxx/global1.c | 18 ++++++++++++++++++ drivers/net/dsa/mv88e6xxx/global1.h | 20 ++++++++++++++++++++ 4 files changed, 65 insertions(+) (limited to 'drivers/net/dsa/mv88e6xxx') diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index ef753ed89b30..5d933549dc49 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -1069,6 +1069,14 @@ static int mv88e6xxx_trunk_setup(struct mv88e6xxx_chip *chip) return 0; } +static int mv88e6xxx_rmu_setup(struct mv88e6xxx_chip *chip) +{ + if (chip->info->ops->rmu_disable) + return chip->info->ops->rmu_disable(chip); + + return 0; +} + static int mv88e6xxx_pot_setup(struct mv88e6xxx_chip *chip) { if (chip->info->ops->pot_clear) @@ -2263,6 +2271,10 @@ static int mv88e6xxx_setup(struct dsa_switch *ds) if (err) goto unlock; + err = mv88e6xxx_rmu_setup(chip); + if (err) + goto unlock; + err = mv88e6xxx_rsvd2cpu_setup(chip); if (err) goto unlock; @@ -2530,6 +2542,7 @@ static const struct mv88e6xxx_ops mv88e6085_ops = { .ppu_enable = mv88e6185_g1_ppu_enable, .ppu_disable = mv88e6185_g1_ppu_disable, .reset = mv88e6185_g1_reset, + .rmu_disable = mv88e6085_g1_rmu_disable, .vtu_getnext = mv88e6352_g1_vtu_getnext, .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, .serdes_power = mv88e6341_serdes_power, @@ -2588,6 +2601,7 @@ static const struct mv88e6xxx_ops mv88e6097_ops = { .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu, .pot_clear = mv88e6xxx_g2_pot_clear, .reset = mv88e6352_g1_reset, + .rmu_disable = mv88e6085_g1_rmu_disable, .vtu_getnext = mv88e6352_g1_vtu_getnext, .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, }; @@ -2815,6 +2829,7 @@ static const struct mv88e6xxx_ops mv88e6172_ops = { .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu, .pot_clear = mv88e6xxx_g2_pot_clear, .reset = mv88e6352_g1_reset, + .rmu_disable = mv88e6352_g1_rmu_disable, .vtu_getnext = mv88e6352_g1_vtu_getnext, .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, .serdes_power = mv88e6352_serdes_power, @@ -2888,6 +2903,7 @@ static const struct mv88e6xxx_ops mv88e6176_ops = { .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu, .pot_clear = mv88e6xxx_g2_pot_clear, .reset = mv88e6352_g1_reset, + .rmu_disable = mv88e6352_g1_rmu_disable, .vtu_getnext = mv88e6352_g1_vtu_getnext, .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, .serdes_power = mv88e6352_serdes_power, @@ -2953,6 +2969,7 @@ static const struct mv88e6xxx_ops mv88e6190_ops = { .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu, .pot_clear = mv88e6xxx_g2_pot_clear, .reset = mv88e6352_g1_reset, + .rmu_disable = mv88e6390_g1_rmu_disable, .vtu_getnext = mv88e6390_g1_vtu_getnext, .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge, .serdes_power = mv88e6390_serdes_power, @@ -2989,6 +3006,7 @@ static const struct mv88e6xxx_ops mv88e6190x_ops = { .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu, .pot_clear = mv88e6xxx_g2_pot_clear, .reset = mv88e6352_g1_reset, + .rmu_disable = mv88e6390_g1_rmu_disable, .vtu_getnext = mv88e6390_g1_vtu_getnext, .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge, .serdes_power = mv88e6390_serdes_power, @@ -3025,6 +3043,7 @@ static const struct mv88e6xxx_ops mv88e6191_ops = { .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu, .pot_clear = mv88e6xxx_g2_pot_clear, .reset = mv88e6352_g1_reset, + .rmu_disable = mv88e6390_g1_rmu_disable, .vtu_getnext = mv88e6390_g1_vtu_getnext, .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge, .serdes_power = mv88e6390_serdes_power, @@ -3062,6 +3081,7 @@ static const struct mv88e6xxx_ops mv88e6240_ops = { .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu, .pot_clear = mv88e6xxx_g2_pot_clear, .reset = mv88e6352_g1_reset, + .rmu_disable = mv88e6352_g1_rmu_disable, .vtu_getnext = mv88e6352_g1_vtu_getnext, .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, .serdes_power = mv88e6352_serdes_power, @@ -3100,6 +3120,7 @@ static const struct mv88e6xxx_ops mv88e6290_ops = { .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu, .pot_clear = mv88e6xxx_g2_pot_clear, .reset = mv88e6352_g1_reset, + .rmu_disable = mv88e6390_g1_rmu_disable, .vtu_getnext = mv88e6390_g1_vtu_getnext, .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge, .serdes_power = mv88e6390_serdes_power, @@ -3316,6 +3337,7 @@ static const struct mv88e6xxx_ops mv88e6352_ops = { .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu, .pot_clear = mv88e6xxx_g2_pot_clear, .reset = mv88e6352_g1_reset, + .rmu_disable = mv88e6352_g1_rmu_disable, .vtu_getnext = mv88e6352_g1_vtu_getnext, .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, .serdes_power = mv88e6352_serdes_power, @@ -3359,6 +3381,7 @@ static const struct mv88e6xxx_ops mv88e6390_ops = { .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu, .pot_clear = mv88e6xxx_g2_pot_clear, .reset = mv88e6352_g1_reset, + .rmu_disable = mv88e6390_g1_rmu_disable, .vtu_getnext = mv88e6390_g1_vtu_getnext, .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge, .serdes_power = mv88e6390_serdes_power, @@ -3399,6 +3422,7 @@ static const struct mv88e6xxx_ops mv88e6390x_ops = { .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu, .pot_clear = mv88e6xxx_g2_pot_clear, .reset = mv88e6352_g1_reset, + .rmu_disable = mv88e6390_g1_rmu_disable, .vtu_getnext = mv88e6390_g1_vtu_getnext, .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge, .serdes_power = mv88e6390_serdes_power, diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h index 62234c2287a2..a1bedb0a888b 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.h +++ b/drivers/net/dsa/mv88e6xxx/chip.h @@ -432,6 +432,9 @@ struct mv88e6xxx_ops { /* Interface to the AVB/PTP registers */ const struct mv88e6xxx_avb_ops *avb_ops; + + /* Remote Management Unit operations */ + int (*rmu_disable)(struct mv88e6xxx_chip *chip); }; struct mv88e6xxx_irq_ops { diff --git a/drivers/net/dsa/mv88e6xxx/global1.c b/drivers/net/dsa/mv88e6xxx/global1.c index 89c6330c53eb..244ee1ff9edc 100644 --- a/drivers/net/dsa/mv88e6xxx/global1.c +++ b/drivers/net/dsa/mv88e6xxx/global1.c @@ -373,6 +373,24 @@ int mv88e6185_g1_set_cascade_port(struct mv88e6xxx_chip *chip, int port) return mv88e6xxx_g1_ctl2_mask(chip, mask, port << __bf_shf(mask)); } +int mv88e6085_g1_rmu_disable(struct mv88e6xxx_chip *chip) +{ + return mv88e6xxx_g1_ctl2_mask(chip, MV88E6085_G1_CTL2_P10RM | + MV88E6085_G1_CTL2_RM_ENABLE, 0); +} + +int mv88e6352_g1_rmu_disable(struct mv88e6xxx_chip *chip) +{ + return mv88e6xxx_g1_ctl2_mask(chip, MV88E6352_G1_CTL2_RMU_MODE_MASK, + MV88E6352_G1_CTL2_RMU_MODE_DISABLED); +} + +int mv88e6390_g1_rmu_disable(struct mv88e6xxx_chip *chip) +{ + return mv88e6xxx_g1_ctl2_mask(chip, MV88E6390_G1_CTL2_RMU_MODE_MASK, + MV88E6390_G1_CTL2_RMU_MODE_DISABLED); +} + int mv88e6390_g1_stats_set_histogram(struct mv88e6xxx_chip *chip) { u16 val; diff --git a/drivers/net/dsa/mv88e6xxx/global1.h b/drivers/net/dsa/mv88e6xxx/global1.h index 8b043e813761..e186a026e1b1 100644 --- a/drivers/net/dsa/mv88e6xxx/global1.h +++ b/drivers/net/dsa/mv88e6xxx/global1.h @@ -207,6 +207,22 @@ #define MV88E6185_G1_CTL2_CASCADE_PORT_MASK 0xf000 #define MV88E6185_G1_CTL2_CASCADE_PORT_NONE 0xe000 #define MV88E6185_G1_CTL2_CASCADE_PORT_MULTI 0xf000 +#define MV88E6352_G1_CTL2_RMU_MODE_MASK 0x3000 +#define MV88E6352_G1_CTL2_RMU_MODE_DISABLED 0x0000 +#define MV88E6352_G1_CTL2_RMU_MODE_PORT_4 0x1000 +#define MV88E6352_G1_CTL2_RMU_MODE_PORT_5 0x2000 +#define MV88E6352_G1_CTL2_RMU_MODE_PORT_6 0x3000 +#define MV88E6085_G1_CTL2_DA_CHECK 0x4000 +#define MV88E6085_G1_CTL2_P10RM 0x2000 +#define MV88E6085_G1_CTL2_RM_ENABLE 0x1000 +#define MV88E6352_G1_CTL2_DA_CHECK 0x0800 +#define MV88E6390_G1_CTL2_RMU_MODE_MASK 0x0700 +#define MV88E6390_G1_CTL2_RMU_MODE_PORT_0 0x0000 +#define MV88E6390_G1_CTL2_RMU_MODE_PORT_1 0x0100 +#define MV88E6390_G1_CTL2_RMU_MODE_PORT_9 0x0200 +#define MV88E6390_G1_CTL2_RMU_MODE_PORT_10 0x0300 +#define MV88E6390_G1_CTL2_RMU_MODE_ALL_DSA 0x0600 +#define MV88E6390_G1_CTL2_RMU_MODE_DISABLED 0x0700 #define MV88E6XXX_G1_CTL2_DEVICE_NUMBER_MASK 0x001f /* Offset 0x1D: Stats Operation Register */ @@ -257,6 +273,10 @@ int mv88e6390_g1_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip); int mv88e6185_g1_set_cascade_port(struct mv88e6xxx_chip *chip, int port); +int mv88e6085_g1_rmu_disable(struct mv88e6xxx_chip *chip); +int mv88e6352_g1_rmu_disable(struct mv88e6xxx_chip *chip); +int mv88e6390_g1_rmu_disable(struct mv88e6xxx_chip *chip); + int mv88e6xxx_g1_set_device_number(struct mv88e6xxx_chip *chip, int index); int mv88e6xxx_g1_atu_set_learn2all(struct mv88e6xxx_chip *chip, bool learn2all); -- cgit From c9a2356f35409a667429254bc326b10f92c7ecce Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 10 May 2018 13:17:35 -0700 Subject: net: dsa: mv88e6xxx: add PHYLINK support Add rudimentary phylink support to mv88e6xxx. This allows the driver using user ports with fixed links to keep operating normally. User ports with normal PHYs are not affected since the switch automatically manages their link parameters. User facing ports which use a SFP/SFF with a non-fixed link mode might require a call to phylink_mac_change() to operate properly. Signed-off-by: Russell King [Andrew: fixed link setting after adding link polling] Signed-off-by: Andrew Lunn [florian: expand commit message] Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 83 ++++++++++++++++++++++++++++++++++++++++ drivers/net/dsa/mv88e6xxx/port.c | 39 +++++++++++++++++++ drivers/net/dsa/mv88e6xxx/port.h | 3 ++ 3 files changed, 125 insertions(+) (limited to 'drivers/net/dsa/mv88e6xxx') diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 5d933549dc49..1cebde80b101 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include "chip.h" @@ -580,6 +581,83 @@ static void mv88e6xxx_adjust_link(struct dsa_switch *ds, int port, dev_err(ds->dev, "p%d: failed to configure MAC\n", port); } +static void mv88e6xxx_validate(struct dsa_switch *ds, int port, + unsigned long *supported, + struct phylink_link_state *state) +{ +} + +static int mv88e6xxx_link_state(struct dsa_switch *ds, int port, + struct phylink_link_state *state) +{ + struct mv88e6xxx_chip *chip = ds->priv; + int err; + + mutex_lock(&chip->reg_lock); + err = mv88e6xxx_port_link_state(chip, port, state); + mutex_unlock(&chip->reg_lock); + + return err; +} + +static void mv88e6xxx_mac_config(struct dsa_switch *ds, int port, + unsigned int mode, + const struct phylink_link_state *state) +{ + struct mv88e6xxx_chip *chip = ds->priv; + int speed, duplex, link, err; + + if (mode == MLO_AN_PHY) + return; + + if (mode == MLO_AN_FIXED) { + link = LINK_FORCED_UP; + speed = state->speed; + duplex = state->duplex; + } else { + speed = SPEED_UNFORCED; + duplex = DUPLEX_UNFORCED; + link = LINK_UNFORCED; + } + + mutex_lock(&chip->reg_lock); + err = mv88e6xxx_port_setup_mac(chip, port, link, speed, duplex, + state->interface); + mutex_unlock(&chip->reg_lock); + + if (err && err != -EOPNOTSUPP) + dev_err(ds->dev, "p%d: failed to configure MAC\n", port); +} + +static void mv88e6xxx_mac_link_force(struct dsa_switch *ds, int port, int link) +{ + struct mv88e6xxx_chip *chip = ds->priv; + int err; + + mutex_lock(&chip->reg_lock); + err = chip->info->ops->port_set_link(chip, port, link); + mutex_unlock(&chip->reg_lock); + + if (err) + dev_err(chip->dev, "p%d: failed to force MAC link\n", port); +} + +static void mv88e6xxx_mac_link_down(struct dsa_switch *ds, int port, + unsigned int mode, + phy_interface_t interface) +{ + if (mode == MLO_AN_FIXED) + mv88e6xxx_mac_link_force(ds, port, LINK_FORCED_DOWN); +} + +static void mv88e6xxx_mac_link_up(struct dsa_switch *ds, int port, + unsigned int mode, phy_interface_t interface, + struct phy_device *phydev) +{ + if (mode == MLO_AN_FIXED) + mv88e6xxx_mac_link_force(ds, port, LINK_FORCED_UP); +} + static int mv88e6xxx_stats_snapshot(struct mv88e6xxx_chip *chip, int port) { if (!chip->info->ops->stats_snapshot) @@ -4169,6 +4247,11 @@ static const struct dsa_switch_ops mv88e6xxx_switch_ops = { .get_tag_protocol = mv88e6xxx_get_tag_protocol, .setup = mv88e6xxx_setup, .adjust_link = mv88e6xxx_adjust_link, + .phylink_validate = mv88e6xxx_validate, + .phylink_mac_link_state = mv88e6xxx_link_state, + .phylink_mac_config = mv88e6xxx_mac_config, + .phylink_mac_link_down = mv88e6xxx_mac_link_down, + .phylink_mac_link_up = mv88e6xxx_mac_link_up, .get_strings = mv88e6xxx_get_strings, .get_ethtool_stats = mv88e6xxx_get_ethtool_stats, .get_sset_count = mv88e6xxx_get_sset_count, diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c index 6315774d72b3..429d0ebcd5b1 100644 --- a/drivers/net/dsa/mv88e6xxx/port.c +++ b/drivers/net/dsa/mv88e6xxx/port.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "chip.h" #include "port.h" @@ -378,6 +379,44 @@ int mv88e6xxx_port_get_cmode(struct mv88e6xxx_chip *chip, int port, u8 *cmode) return 0; } +int mv88e6xxx_port_link_state(struct mv88e6xxx_chip *chip, int port, + struct phylink_link_state *state) +{ + int err; + u16 reg; + + err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, ®); + if (err) + return err; + + switch (reg & MV88E6XXX_PORT_STS_SPEED_MASK) { + case MV88E6XXX_PORT_STS_SPEED_10: + state->speed = SPEED_10; + break; + case MV88E6XXX_PORT_STS_SPEED_100: + state->speed = SPEED_100; + break; + case MV88E6XXX_PORT_STS_SPEED_1000: + state->speed = SPEED_1000; + break; + case MV88E6XXX_PORT_STS_SPEED_10000: + if ((reg &MV88E6XXX_PORT_STS_CMODE_MASK) == + MV88E6XXX_PORT_STS_CMODE_2500BASEX) + state->speed = SPEED_2500; + else + state->speed = SPEED_10000; + break; + } + + state->duplex = reg & MV88E6XXX_PORT_STS_DUPLEX ? + DUPLEX_FULL : DUPLEX_HALF; + state->link = !!(reg & MV88E6XXX_PORT_STS_LINK); + state->an_enabled = 1; + state->an_complete = state->link; + + return 0; +} + /* Offset 0x02: Jamming Control * * Do not limit the period of time that this port can be paused for by diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h index b16d5f0e6e9c..5e1db1b221ca 100644 --- a/drivers/net/dsa/mv88e6xxx/port.h +++ b/drivers/net/dsa/mv88e6xxx/port.h @@ -29,6 +29,7 @@ #define MV88E6XXX_PORT_STS_SPEED_10 0x0000 #define MV88E6XXX_PORT_STS_SPEED_100 0x0100 #define MV88E6XXX_PORT_STS_SPEED_1000 0x0200 +#define MV88E6XXX_PORT_STS_SPEED_10000 0x0300 #define MV88E6352_PORT_STS_EEE 0x0040 #define MV88E6165_PORT_STS_AM_DIS 0x0040 #define MV88E6185_PORT_STS_MGMII 0x0040 @@ -295,6 +296,8 @@ int mv88e6390_port_pause_limit(struct mv88e6xxx_chip *chip, int port, u8 in, int mv88e6390x_port_set_cmode(struct mv88e6xxx_chip *chip, int port, phy_interface_t mode); int mv88e6xxx_port_get_cmode(struct mv88e6xxx_chip *chip, int port, u8 *cmode); +int mv88e6xxx_port_link_state(struct mv88e6xxx_chip *chip, int port, + struct phylink_link_state *state); int mv88e6xxx_port_set_map_da(struct mv88e6xxx_chip *chip, int port); int mv88e6095_port_set_upstream_port(struct mv88e6xxx_chip *chip, int port, int upstream_port); -- cgit From 408d2debb03e15f3dd3063a5a14befd3390c6eab Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Fri, 11 May 2018 17:16:34 -0400 Subject: net: dsa: mv88e6xxx: use helper for 6390 histogram The Marvell 88E6390 model has its histogram mode bits moved in the Global 1 Control 2 register. Use the previously introduced mv88e6xxx_g1_ctl2_mask helper to set them. At the same time complete the documentation of the said register. Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/global1.c | 15 +++------------ drivers/net/dsa/mv88e6xxx/global1.h | 12 +++++++++--- 2 files changed, 12 insertions(+), 15 deletions(-) (limited to 'drivers/net/dsa/mv88e6xxx') diff --git a/drivers/net/dsa/mv88e6xxx/global1.c b/drivers/net/dsa/mv88e6xxx/global1.c index 244ee1ff9edc..0f2b05342c18 100644 --- a/drivers/net/dsa/mv88e6xxx/global1.c +++ b/drivers/net/dsa/mv88e6xxx/global1.c @@ -393,18 +393,9 @@ int mv88e6390_g1_rmu_disable(struct mv88e6xxx_chip *chip) int mv88e6390_g1_stats_set_histogram(struct mv88e6xxx_chip *chip) { - u16 val; - int err; - - err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL2, &val); - if (err) - return err; - - val |= MV88E6XXX_G1_CTL2_HIST_RX_TX; - - err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL2, val); - - return err; + return mv88e6xxx_g1_ctl2_mask(chip, MV88E6390_G1_CTL2_HIST_MODE_MASK, + MV88E6390_G1_CTL2_HIST_MODE_RX | + MV88E6390_G1_CTL2_HIST_MODE_TX); } int mv88e6xxx_g1_set_device_number(struct mv88e6xxx_chip *chip, int index) diff --git a/drivers/net/dsa/mv88e6xxx/global1.h b/drivers/net/dsa/mv88e6xxx/global1.h index e186a026e1b1..c357b3ca9a09 100644 --- a/drivers/net/dsa/mv88e6xxx/global1.h +++ b/drivers/net/dsa/mv88e6xxx/global1.h @@ -201,12 +201,13 @@ /* Offset 0x1C: Global Control 2 */ #define MV88E6XXX_G1_CTL2 0x1c -#define MV88E6XXX_G1_CTL2_HIST_RX 0x0040 -#define MV88E6XXX_G1_CTL2_HIST_TX 0x0080 -#define MV88E6XXX_G1_CTL2_HIST_RX_TX 0x00c0 #define MV88E6185_G1_CTL2_CASCADE_PORT_MASK 0xf000 #define MV88E6185_G1_CTL2_CASCADE_PORT_NONE 0xe000 #define MV88E6185_G1_CTL2_CASCADE_PORT_MULTI 0xf000 +#define MV88E6352_G1_CTL2_HEADER_TYPE_MASK 0xc000 +#define MV88E6352_G1_CTL2_HEADER_TYPE_ORIG 0x0000 +#define MV88E6352_G1_CTL2_HEADER_TYPE_MGMT 0x4000 +#define MV88E6390_G1_CTL2_HEADER_TYPE_LAG 0x8000 #define MV88E6352_G1_CTL2_RMU_MODE_MASK 0x3000 #define MV88E6352_G1_CTL2_RMU_MODE_DISABLED 0x0000 #define MV88E6352_G1_CTL2_RMU_MODE_PORT_4 0x1000 @@ -223,6 +224,11 @@ #define MV88E6390_G1_CTL2_RMU_MODE_PORT_10 0x0300 #define MV88E6390_G1_CTL2_RMU_MODE_ALL_DSA 0x0600 #define MV88E6390_G1_CTL2_RMU_MODE_DISABLED 0x0700 +#define MV88E6390_G1_CTL2_HIST_MODE_MASK 0x00c0 +#define MV88E6390_G1_CTL2_HIST_MODE_RX 0x0040 +#define MV88E6390_G1_CTL2_HIST_MODE_TX 0x0080 +#define MV88E6352_G1_CTL2_CTR_MODE_MASK 0x0060 +#define MV88E6390_G1_CTL2_CTR_MODE 0x0020 #define MV88E6XXX_G1_CTL2_DEVICE_NUMBER_MASK 0x001f /* Offset 0x1D: Stats Operation Register */ -- cgit From 93e18d61bfa950aaffff5fccde0f974e1e038f83 Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Fri, 11 May 2018 17:16:35 -0400 Subject: net: dsa: mv88e6xxx: add IEEE and IP mapping ops All Marvell switch families except 88E6390 have direct registers in Global 1 for IEEE and IP priorities override mapping. The 88E6390 uses indirect tables instead. Add .ieee_pri_map and .ip_pri_map ops to distinct that and call them from a mv88e6xxx_pri_setup helper. Only non-6390 are concerned ATM. Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 94 +++++++++++++++++++++++++------------ drivers/net/dsa/mv88e6xxx/chip.h | 3 ++ drivers/net/dsa/mv88e6xxx/global1.c | 58 +++++++++++++++++++++++ drivers/net/dsa/mv88e6xxx/global1.h | 3 ++ 4 files changed, 127 insertions(+), 31 deletions(-) (limited to 'drivers/net/dsa/mv88e6xxx') diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 2910f68c0e5c..ad456d18ce8a 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -1104,6 +1104,25 @@ static void mv88e6xxx_port_stp_state_set(struct dsa_switch *ds, int port, dev_err(ds->dev, "p%d: failed to update state\n", port); } +static int mv88e6xxx_pri_setup(struct mv88e6xxx_chip *chip) +{ + int err; + + if (chip->info->ops->ieee_pri_map) { + err = chip->info->ops->ieee_pri_map(chip); + if (err) + return err; + } + + if (chip->info->ops->ip_pri_map) { + err = chip->info->ops->ip_pri_map(chip); + if (err) + return err; + } + + return 0; +} + static int mv88e6xxx_devmap_setup(struct mv88e6xxx_chip *chip) { int target, port; @@ -2252,37 +2271,6 @@ static int mv88e6xxx_g1_setup(struct mv88e6xxx_chip *chip) { int err; - /* Configure the IP ToS mapping registers. */ - err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_IP_PRI_0, 0x0000); - if (err) - return err; - err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_IP_PRI_1, 0x0000); - if (err) - return err; - err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_IP_PRI_2, 0x5555); - if (err) - return err; - err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_IP_PRI_3, 0x5555); - if (err) - return err; - err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_IP_PRI_4, 0xaaaa); - if (err) - return err; - err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_IP_PRI_5, 0xaaaa); - if (err) - return err; - err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_IP_PRI_6, 0xffff); - if (err) - return err; - err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_IP_PRI_7, 0xffff); - if (err) - return err; - - /* Configure the IEEE 802.1p priority mapping register. */ - err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_IEEE_PRI, 0xfa41); - if (err) - return err; - /* Initialize the statistics unit */ err = mv88e6xxx_stats_set_histogram(chip); if (err) @@ -2365,6 +2353,10 @@ static int mv88e6xxx_setup(struct dsa_switch *ds) if (err) goto unlock; + err = mv88e6xxx_pri_setup(chip); + if (err) + goto unlock; + /* Setup PTP Hardware Clock and timestamping */ if (chip->info->ptp_support) { err = mv88e6xxx_ptp_setup(chip); @@ -2592,6 +2584,8 @@ static int mv88e6xxx_set_eeprom(struct dsa_switch *ds, static const struct mv88e6xxx_ops mv88e6085_ops = { /* MV88E6XXX_FAMILY_6097 */ + .ieee_pri_map = mv88e6085_g1_ieee_pri_map, + .ip_pri_map = mv88e6085_g1_ip_pri_map, .irl_init_all = mv88e6352_g2_irl_init_all, .set_switch_mac = mv88e6xxx_g1_set_switch_mac, .phy_read = mv88e6185_phy_ppu_read, @@ -2628,6 +2622,8 @@ static const struct mv88e6xxx_ops mv88e6085_ops = { static const struct mv88e6xxx_ops mv88e6095_ops = { /* MV88E6XXX_FAMILY_6095 */ + .ieee_pri_map = mv88e6085_g1_ieee_pri_map, + .ip_pri_map = mv88e6085_g1_ip_pri_map, .set_switch_mac = mv88e6xxx_g1_set_switch_mac, .phy_read = mv88e6185_phy_ppu_read, .phy_write = mv88e6185_phy_ppu_write, @@ -2652,6 +2648,8 @@ static const struct mv88e6xxx_ops mv88e6095_ops = { static const struct mv88e6xxx_ops mv88e6097_ops = { /* MV88E6XXX_FAMILY_6097 */ + .ieee_pri_map = mv88e6085_g1_ieee_pri_map, + .ip_pri_map = mv88e6085_g1_ip_pri_map, .irl_init_all = mv88e6352_g2_irl_init_all, .set_switch_mac = mv88e6xxx_g2_set_switch_mac, .phy_read = mv88e6xxx_g2_smi_phy_read, @@ -2686,6 +2684,8 @@ static const struct mv88e6xxx_ops mv88e6097_ops = { static const struct mv88e6xxx_ops mv88e6123_ops = { /* MV88E6XXX_FAMILY_6165 */ + .ieee_pri_map = mv88e6085_g1_ieee_pri_map, + .ip_pri_map = mv88e6085_g1_ip_pri_map, .irl_init_all = mv88e6352_g2_irl_init_all, .set_switch_mac = mv88e6xxx_g2_set_switch_mac, .phy_read = mv88e6xxx_g2_smi_phy_read, @@ -2714,6 +2714,8 @@ static const struct mv88e6xxx_ops mv88e6123_ops = { static const struct mv88e6xxx_ops mv88e6131_ops = { /* MV88E6XXX_FAMILY_6185 */ + .ieee_pri_map = mv88e6085_g1_ieee_pri_map, + .ip_pri_map = mv88e6085_g1_ip_pri_map, .set_switch_mac = mv88e6xxx_g1_set_switch_mac, .phy_read = mv88e6185_phy_ppu_read, .phy_write = mv88e6185_phy_ppu_write, @@ -2747,6 +2749,8 @@ static const struct mv88e6xxx_ops mv88e6131_ops = { static const struct mv88e6xxx_ops mv88e6141_ops = { /* MV88E6XXX_FAMILY_6341 */ + .ieee_pri_map = mv88e6085_g1_ieee_pri_map, + .ip_pri_map = mv88e6085_g1_ip_pri_map, .irl_init_all = mv88e6352_g2_irl_init_all, .get_eeprom = mv88e6xxx_g2_get_eeprom8, .set_eeprom = mv88e6xxx_g2_set_eeprom8, @@ -2784,6 +2788,8 @@ static const struct mv88e6xxx_ops mv88e6141_ops = { static const struct mv88e6xxx_ops mv88e6161_ops = { /* MV88E6XXX_FAMILY_6165 */ + .ieee_pri_map = mv88e6085_g1_ieee_pri_map, + .ip_pri_map = mv88e6085_g1_ip_pri_map, .irl_init_all = mv88e6352_g2_irl_init_all, .set_switch_mac = mv88e6xxx_g2_set_switch_mac, .phy_read = mv88e6xxx_g2_smi_phy_read, @@ -2817,6 +2823,8 @@ static const struct mv88e6xxx_ops mv88e6161_ops = { static const struct mv88e6xxx_ops mv88e6165_ops = { /* MV88E6XXX_FAMILY_6165 */ + .ieee_pri_map = mv88e6085_g1_ieee_pri_map, + .ip_pri_map = mv88e6085_g1_ip_pri_map, .irl_init_all = mv88e6352_g2_irl_init_all, .set_switch_mac = mv88e6xxx_g2_set_switch_mac, .phy_read = mv88e6165_phy_read, @@ -2843,6 +2851,8 @@ static const struct mv88e6xxx_ops mv88e6165_ops = { static const struct mv88e6xxx_ops mv88e6171_ops = { /* MV88E6XXX_FAMILY_6351 */ + .ieee_pri_map = mv88e6085_g1_ieee_pri_map, + .ip_pri_map = mv88e6085_g1_ip_pri_map, .irl_init_all = mv88e6352_g2_irl_init_all, .set_switch_mac = mv88e6xxx_g2_set_switch_mac, .phy_read = mv88e6xxx_g2_smi_phy_read, @@ -2877,6 +2887,8 @@ static const struct mv88e6xxx_ops mv88e6171_ops = { static const struct mv88e6xxx_ops mv88e6172_ops = { /* MV88E6XXX_FAMILY_6352 */ + .ieee_pri_map = mv88e6085_g1_ieee_pri_map, + .ip_pri_map = mv88e6085_g1_ip_pri_map, .irl_init_all = mv88e6352_g2_irl_init_all, .get_eeprom = mv88e6xxx_g2_get_eeprom16, .set_eeprom = mv88e6xxx_g2_set_eeprom16, @@ -2916,6 +2928,8 @@ static const struct mv88e6xxx_ops mv88e6172_ops = { static const struct mv88e6xxx_ops mv88e6175_ops = { /* MV88E6XXX_FAMILY_6351 */ + .ieee_pri_map = mv88e6085_g1_ieee_pri_map, + .ip_pri_map = mv88e6085_g1_ip_pri_map, .irl_init_all = mv88e6352_g2_irl_init_all, .set_switch_mac = mv88e6xxx_g2_set_switch_mac, .phy_read = mv88e6xxx_g2_smi_phy_read, @@ -2951,6 +2965,8 @@ static const struct mv88e6xxx_ops mv88e6175_ops = { static const struct mv88e6xxx_ops mv88e6176_ops = { /* MV88E6XXX_FAMILY_6352 */ + .ieee_pri_map = mv88e6085_g1_ieee_pri_map, + .ip_pri_map = mv88e6085_g1_ip_pri_map, .irl_init_all = mv88e6352_g2_irl_init_all, .get_eeprom = mv88e6xxx_g2_get_eeprom16, .set_eeprom = mv88e6xxx_g2_set_eeprom16, @@ -2990,6 +3006,8 @@ static const struct mv88e6xxx_ops mv88e6176_ops = { static const struct mv88e6xxx_ops mv88e6185_ops = { /* MV88E6XXX_FAMILY_6185 */ + .ieee_pri_map = mv88e6085_g1_ieee_pri_map, + .ip_pri_map = mv88e6085_g1_ip_pri_map, .set_switch_mac = mv88e6xxx_g1_set_switch_mac, .phy_read = mv88e6185_phy_ppu_read, .phy_write = mv88e6185_phy_ppu_write, @@ -3129,6 +3147,8 @@ static const struct mv88e6xxx_ops mv88e6191_ops = { static const struct mv88e6xxx_ops mv88e6240_ops = { /* MV88E6XXX_FAMILY_6352 */ + .ieee_pri_map = mv88e6085_g1_ieee_pri_map, + .ip_pri_map = mv88e6085_g1_ip_pri_map, .irl_init_all = mv88e6352_g2_irl_init_all, .get_eeprom = mv88e6xxx_g2_get_eeprom16, .set_eeprom = mv88e6xxx_g2_set_eeprom16, @@ -3208,6 +3228,8 @@ static const struct mv88e6xxx_ops mv88e6290_ops = { static const struct mv88e6xxx_ops mv88e6320_ops = { /* MV88E6XXX_FAMILY_6320 */ + .ieee_pri_map = mv88e6085_g1_ieee_pri_map, + .ip_pri_map = mv88e6085_g1_ip_pri_map, .irl_init_all = mv88e6352_g2_irl_init_all, .get_eeprom = mv88e6xxx_g2_get_eeprom16, .set_eeprom = mv88e6xxx_g2_set_eeprom16, @@ -3244,6 +3266,8 @@ static const struct mv88e6xxx_ops mv88e6320_ops = { static const struct mv88e6xxx_ops mv88e6321_ops = { /* MV88E6XXX_FAMILY_6320 */ + .ieee_pri_map = mv88e6085_g1_ieee_pri_map, + .ip_pri_map = mv88e6085_g1_ip_pri_map, .irl_init_all = mv88e6352_g2_irl_init_all, .get_eeprom = mv88e6xxx_g2_get_eeprom16, .set_eeprom = mv88e6xxx_g2_set_eeprom16, @@ -3278,6 +3302,8 @@ static const struct mv88e6xxx_ops mv88e6321_ops = { static const struct mv88e6xxx_ops mv88e6341_ops = { /* MV88E6XXX_FAMILY_6341 */ + .ieee_pri_map = mv88e6085_g1_ieee_pri_map, + .ip_pri_map = mv88e6085_g1_ip_pri_map, .irl_init_all = mv88e6352_g2_irl_init_all, .get_eeprom = mv88e6xxx_g2_get_eeprom8, .set_eeprom = mv88e6xxx_g2_set_eeprom8, @@ -3316,6 +3342,8 @@ static const struct mv88e6xxx_ops mv88e6341_ops = { static const struct mv88e6xxx_ops mv88e6350_ops = { /* MV88E6XXX_FAMILY_6351 */ + .ieee_pri_map = mv88e6085_g1_ieee_pri_map, + .ip_pri_map = mv88e6085_g1_ip_pri_map, .irl_init_all = mv88e6352_g2_irl_init_all, .set_switch_mac = mv88e6xxx_g2_set_switch_mac, .phy_read = mv88e6xxx_g2_smi_phy_read, @@ -3350,6 +3378,8 @@ static const struct mv88e6xxx_ops mv88e6350_ops = { static const struct mv88e6xxx_ops mv88e6351_ops = { /* MV88E6XXX_FAMILY_6351 */ + .ieee_pri_map = mv88e6085_g1_ieee_pri_map, + .ip_pri_map = mv88e6085_g1_ip_pri_map, .irl_init_all = mv88e6352_g2_irl_init_all, .set_switch_mac = mv88e6xxx_g2_set_switch_mac, .phy_read = mv88e6xxx_g2_smi_phy_read, @@ -3385,6 +3415,8 @@ static const struct mv88e6xxx_ops mv88e6351_ops = { static const struct mv88e6xxx_ops mv88e6352_ops = { /* MV88E6XXX_FAMILY_6352 */ + .ieee_pri_map = mv88e6085_g1_ieee_pri_map, + .ip_pri_map = mv88e6085_g1_ip_pri_map, .irl_init_all = mv88e6352_g2_irl_init_all, .get_eeprom = mv88e6xxx_g2_get_eeprom16, .set_eeprom = mv88e6xxx_g2_set_eeprom16, diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h index 8eb5dfe17f5c..012268046442 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.h +++ b/drivers/net/dsa/mv88e6xxx/chip.h @@ -294,6 +294,9 @@ struct mv88e6xxx_mdio_bus { }; struct mv88e6xxx_ops { + int (*ieee_pri_map)(struct mv88e6xxx_chip *chip); + int (*ip_pri_map)(struct mv88e6xxx_chip *chip); + /* Ingress Rate Limit unit (IRL) operations */ int (*irl_init_all)(struct mv88e6xxx_chip *chip, int port); diff --git a/drivers/net/dsa/mv88e6xxx/global1.c b/drivers/net/dsa/mv88e6xxx/global1.c index 0f2b05342c18..d721ccf7d8be 100644 --- a/drivers/net/dsa/mv88e6xxx/global1.c +++ b/drivers/net/dsa/mv88e6xxx/global1.c @@ -241,6 +241,64 @@ int mv88e6185_g1_ppu_disable(struct mv88e6xxx_chip *chip) return mv88e6185_g1_wait_ppu_disabled(chip); } +/* Offset 0x10: IP-PRI Mapping Register 0 + * Offset 0x11: IP-PRI Mapping Register 1 + * Offset 0x12: IP-PRI Mapping Register 2 + * Offset 0x13: IP-PRI Mapping Register 3 + * Offset 0x14: IP-PRI Mapping Register 4 + * Offset 0x15: IP-PRI Mapping Register 5 + * Offset 0x16: IP-PRI Mapping Register 6 + * Offset 0x17: IP-PRI Mapping Register 7 + */ + +int mv88e6085_g1_ip_pri_map(struct mv88e6xxx_chip *chip) +{ + int err; + + /* Reset the IP TOS/DiffServ/Traffic priorities to defaults */ + err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_IP_PRI_0, 0x0000); + if (err) + return err; + + err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_IP_PRI_1, 0x0000); + if (err) + return err; + + err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_IP_PRI_2, 0x5555); + if (err) + return err; + + err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_IP_PRI_3, 0x5555); + if (err) + return err; + + err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_IP_PRI_4, 0xaaaa); + if (err) + return err; + + err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_IP_PRI_5, 0xaaaa); + if (err) + return err; + + err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_IP_PRI_6, 0xffff); + if (err) + return err; + + err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_IP_PRI_7, 0xffff); + if (err) + return err; + + return 0; +} + +/* Offset 0x18: IEEE-PRI Register */ + +int mv88e6085_g1_ieee_pri_map(struct mv88e6xxx_chip *chip) +{ + /* Reset the IEEE Tag priorities to defaults */ + return mv88e6xxx_g1_write(chip, MV88E6XXX_G1_IEEE_PRI, 0xfa41); +} + /* Offset 0x1a: Monitor Control */ /* Offset 0x1a: Monitor & MGMT Control on some devices */ diff --git a/drivers/net/dsa/mv88e6xxx/global1.h b/drivers/net/dsa/mv88e6xxx/global1.h index c357b3ca9a09..7c791c1da4b9 100644 --- a/drivers/net/dsa/mv88e6xxx/global1.h +++ b/drivers/net/dsa/mv88e6xxx/global1.h @@ -277,6 +277,9 @@ int mv88e6095_g1_set_cpu_port(struct mv88e6xxx_chip *chip, int port); int mv88e6390_g1_set_cpu_port(struct mv88e6xxx_chip *chip, int port); int mv88e6390_g1_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip); +int mv88e6085_g1_ip_pri_map(struct mv88e6xxx_chip *chip); +int mv88e6085_g1_ieee_pri_map(struct mv88e6xxx_chip *chip); + int mv88e6185_g1_set_cascade_port(struct mv88e6xxx_chip *chip, int port); int mv88e6085_g1_rmu_disable(struct mv88e6xxx_chip *chip); -- cgit From 447b1bb84bb51603f57ae426973a620a7a66a0db Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Fri, 11 May 2018 17:16:36 -0400 Subject: net: dsa: mv88e6xxx: add a stats setup function Now that the Global 1 specific setup function only setup the statistics unit, kill it in favor of a mv88e6xxx_stats_setup function. Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) (limited to 'drivers/net/dsa/mv88e6xxx') diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index ad456d18ce8a..b23c11d9f4b2 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -995,14 +995,6 @@ static void mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds, int port, } -static int mv88e6xxx_stats_set_histogram(struct mv88e6xxx_chip *chip) -{ - if (chip->info->ops->stats_set_histogram) - return chip->info->ops->stats_set_histogram(chip); - - return 0; -} - static int mv88e6xxx_get_regs_len(struct dsa_switch *ds, int port) { return 32 * sizeof(u16); @@ -2267,14 +2259,16 @@ static int mv88e6xxx_set_ageing_time(struct dsa_switch *ds, return err; } -static int mv88e6xxx_g1_setup(struct mv88e6xxx_chip *chip) +static int mv88e6xxx_stats_setup(struct mv88e6xxx_chip *chip) { int err; /* Initialize the statistics unit */ - err = mv88e6xxx_stats_set_histogram(chip); - if (err) - return err; + if (chip->info->ops->stats_set_histogram) { + err = chip->info->ops->stats_set_histogram(chip); + if (err) + return err; + } return mv88e6xxx_g1_stats_clear(chip); } @@ -2300,11 +2294,6 @@ static int mv88e6xxx_setup(struct dsa_switch *ds) goto unlock; } - /* Setup Switch Global 1 Registers */ - err = mv88e6xxx_g1_setup(chip); - if (err) - goto unlock; - err = mv88e6xxx_irl_setup(chip); if (err) goto unlock; @@ -2368,6 +2357,10 @@ static int mv88e6xxx_setup(struct dsa_switch *ds) goto unlock; } + err = mv88e6xxx_stats_setup(chip); + if (err) + goto unlock; + unlock: mutex_unlock(&chip->reg_lock); -- cgit From 00e798c7d1ea5c4514401f17db8300db934291cb Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 15 May 2018 16:56:19 -0700 Subject: drivers: net: Remove device_node checks with of_mdiobus_register() A number of drivers have the following pattern: if (np) of_mdiobus_register() else mdiobus_register() which the implementation of of_mdiobus_register() now takes care of. Remove that pattern in drivers that strictly adhere to it. Signed-off-by: Florian Fainelli Reviewed-by: Grygorii Strashko Reviewed-by: Fugang Duan Reviewed-by: Antoine Tenart Reviewed-by: Jose Abreu Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/net/dsa/mv88e6xxx') diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index b23c11d9f4b2..2bb3f03ee1cb 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -2454,10 +2454,7 @@ static int mv88e6xxx_mdio_register(struct mv88e6xxx_chip *chip, return err; } - if (np) - err = of_mdiobus_register(bus, np); - else - err = mdiobus_register(bus); + err = of_mdiobus_register(bus, np); if (err) { dev_err(chip->dev, "Cannot register MDIO bus (%d)\n", err); mv88e6xxx_g2_irq_mdio_free(chip, bus); -- cgit From 577941eb56fe5fd95e1a60c6dba3dfaf606e3fde Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Sat, 19 May 2018 22:31:33 +0200 Subject: net: dsa: mv88e6xxx: Remove OF check for IRQ domain An IRQ domain will work without an OF node. It is not possible to reference interrupts via a phandle, but C code can still use irq_find_mapping() to get an interrupt from the domain. Signed-off-by: Andrew Lunn Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/global2.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/net/dsa/mv88e6xxx') diff --git a/drivers/net/dsa/mv88e6xxx/global2.c b/drivers/net/dsa/mv88e6xxx/global2.c index f9bde011a3e6..91a3cb2452ac 100644 --- a/drivers/net/dsa/mv88e6xxx/global2.c +++ b/drivers/net/dsa/mv88e6xxx/global2.c @@ -1047,9 +1047,6 @@ int mv88e6xxx_g2_irq_setup(struct mv88e6xxx_chip *chip) { int err, irq, virq; - if (!chip->dev->of_node) - return -EINVAL; - chip->g2_irq.domain = irq_domain_add_simple( chip->dev->of_node, 16, 0, &mv88e6xxx_g2_irq_domain_ops, chip); if (!chip->g2_irq.domain) -- cgit From 877b7cb0b6f283593a663134ee52703f12c895cc Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Sat, 19 May 2018 22:31:34 +0200 Subject: net: dsa: mv88e6xxx: Add minimal platform_data support Not all the world uses device tree. Some parts of the world still use platform devices and platform data. Add basic support for probing a Marvell switch via platform data. Signed-off-by: Andrew Lunn Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 56 +++++++++++++++++++++++++++++++++++----- 1 file changed, 49 insertions(+), 7 deletions(-) (limited to 'drivers/net/dsa/mv88e6xxx') diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 2bb3f03ee1cb..5b40382036ea 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -4350,6 +4351,7 @@ static int mv88e6xxx_register_switch(struct mv88e6xxx_chip *chip) return -ENOMEM; ds->priv = chip; + ds->dev = dev; ds->ops = &mv88e6xxx_switch_ops; ds->ageing_time_min = chip->info->age_time_coeff; ds->ageing_time_max = chip->info->age_time_coeff * U8_MAX; @@ -4364,36 +4366,73 @@ static void mv88e6xxx_unregister_switch(struct mv88e6xxx_chip *chip) dsa_unregister_switch(chip->ds); } +static const void *pdata_device_get_match_data(struct device *dev) +{ + const struct of_device_id *matches = dev->driver->of_match_table; + const struct dsa_mv88e6xxx_pdata *pdata = dev->platform_data; + + for (; matches->name[0] || matches->type[0] || matches->compatible[0]; + matches++) { + if (!strcmp(pdata->compatible, matches->compatible)) + return matches->data; + } + return NULL; +} + static int mv88e6xxx_probe(struct mdio_device *mdiodev) { + struct dsa_mv88e6xxx_pdata *pdata = mdiodev->dev.platform_data; struct device *dev = &mdiodev->dev; struct device_node *np = dev->of_node; const struct mv88e6xxx_info *compat_info; struct mv88e6xxx_chip *chip; u32 eeprom_len; + int port; int err; - compat_info = of_device_get_match_data(dev); + if (np) + compat_info = of_device_get_match_data(dev); + + if (pdata) { + compat_info = pdata_device_get_match_data(dev); + + if (!pdata->netdev) + return -EINVAL; + + for (port = 0; port < DSA_MAX_PORTS; port++) { + if (!(pdata->enabled_ports & (1 << port))) + continue; + if (strcmp(pdata->cd.port_names[port], "cpu")) + continue; + pdata->cd.netdev[port] = &pdata->netdev->dev; + break; + } + } + if (!compat_info) return -EINVAL; chip = mv88e6xxx_alloc_chip(dev); - if (!chip) - return -ENOMEM; + if (!chip) { + err = -ENOMEM; + goto out; + } chip->info = compat_info; err = mv88e6xxx_smi_init(chip, mdiodev->bus, mdiodev->addr); if (err) - return err; + goto out; chip->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); - if (IS_ERR(chip->reset)) - return PTR_ERR(chip->reset); + if (IS_ERR(chip->reset)) { + err = PTR_ERR(chip->reset); + goto out; + } err = mv88e6xxx_detect(chip); if (err) - return err; + goto out; mv88e6xxx_phy_init(chip); @@ -4468,6 +4507,9 @@ out_g1_irq: mv88e6xxx_irq_poll_free(chip); mutex_unlock(&chip->reg_lock); out: + if (pdata) + dev_put(pdata->netdev); + return err; } -- cgit From 00baabe5286c41d21ed4a78f479b021eba1f0d51 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Sat, 19 May 2018 22:31:35 +0200 Subject: net: dsa: mv88e6xxx: Add support for EEPROM via platform data Add the size of the EEPROM to the platform data, so it can also be instantiated by a platform device. Signed-off-by: Andrew Lunn Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 11 +++++++---- drivers/net/dsa/mv88e6xxx/chip.h | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) (limited to 'drivers/net/dsa/mv88e6xxx') diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 5b40382036ea..1fa1f820a437 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -4386,7 +4386,6 @@ static int mv88e6xxx_probe(struct mdio_device *mdiodev) struct device_node *np = dev->of_node; const struct mv88e6xxx_info *compat_info; struct mv88e6xxx_chip *chip; - u32 eeprom_len; int port; int err; @@ -4436,9 +4435,13 @@ static int mv88e6xxx_probe(struct mdio_device *mdiodev) mv88e6xxx_phy_init(chip); - if (chip->info->ops->get_eeprom && - !of_property_read_u32(np, "eeprom-length", &eeprom_len)) - chip->eeprom_len = eeprom_len; + if (chip->info->ops->get_eeprom) { + if (np) + of_property_read_u32(np, "eeprom-length", + &chip->eeprom_len); + else + chip->eeprom_len = pdata->eeprom_len; + } mutex_lock(&chip->reg_lock); err = mv88e6xxx_switch_reset(chip); diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h index 012268046442..8ac3fbb15352 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.h +++ b/drivers/net/dsa/mv88e6xxx/chip.h @@ -238,7 +238,7 @@ struct mv88e6xxx_chip { struct gpio_desc *reset; /* set to size of eeprom if supported by the switch */ - int eeprom_len; + u32 eeprom_len; /* List of mdio busses */ struct list_head mdios; -- cgit From 7ddae24f97f9fc8f151aae75f0371ced06a8cd99 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 20 May 2018 19:04:24 -0400 Subject: mv88e6xxx: Fix uninitialized variable warning. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In mv88e6xxx_probe(), ("np" or "pdata") might be an invariant but GCC can't see that, therefore: drivers/net/dsa/mv88e6xxx/chip.c: In function ‘mv88e6xxx_probe’: drivers/net/dsa/mv88e6xxx/chip.c:4420:13: warning: ‘compat_info’ may be used uninitialized in this function [-Wmaybe-uninitialized] chip->info = compat_info; Actually, it should have warned on the "if (!compat_info)" test, but whatever. Explicitly initialize to NULL in the variable declaration to deal with this. Fixes: 877b7cb0b6f2 ("net: dsa: mv88e6xxx: Add minimal platform_data support") Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/dsa/mv88e6xxx') diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 1fa1f820a437..12df00f593b7 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -4382,9 +4382,9 @@ static const void *pdata_device_get_match_data(struct device *dev) static int mv88e6xxx_probe(struct mdio_device *mdiodev) { struct dsa_mv88e6xxx_pdata *pdata = mdiodev->dev.platform_data; + const struct mv88e6xxx_info *compat_info = NULL; struct device *dev = &mdiodev->dev; struct device_node *np = dev->of_node; - const struct mv88e6xxx_info *compat_info; struct mv88e6xxx_chip *chip; int port; int err; -- cgit