aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/layerscape/patches-5.4/701-net-0174-staging-fsl-dpaa2-mac-Add-autoneg-support.patch
blob: fb296c55e282d566930d29209cbf5a422728a2f3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
From 52ab0053f3f8ab374c48630dd03e44fec8138113 Mon Sep 17 00:00:00 2001
From: Ioana Radulescu <ruxandra.radulescu@nxp.com>
Date: Thu, 18 Oct 2018 18:59:41 +0300
Subject: [PATCH] staging: fsl-dpaa2/mac: Add autoneg support

For MC versions that support it, use the new DPMAC link APIs, which
allow setting/getting of advertised and supported link modes.

A mapping between DPMAC link modes and phydev ones is created to
help converting from one to the other.

Signed-off-by: Ioana Radulescu <ruxandra.radulescu@nxp.com>
Signed-off-by: Valentin Catalin Neacsu <valentin-catalin.neacsu@nxp.com>
---
 drivers/staging/fsl-dpaa2/mac/mac.c | 78 +++++++++++++++++++++++++++++++------
 1 file changed, 67 insertions(+), 11 deletions(-)

--- a/drivers/staging/fsl-dpaa2/mac/mac.c
+++ b/drivers/staging/fsl-dpaa2/mac/mac.c
@@ -1,4 +1,5 @@
 /* Copyright 2015 Freescale Semiconductor Inc.
+ * Copyright 2018 NXP
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
@@ -91,6 +92,43 @@ static int cmp_dpmac_ver(struct dpaa2_ma
 	return priv->dpmac_ver_major - ver_major;
 }
 
+#define DPMAC_LINK_AUTONEG_VER_MAJOR		4
+#define DPMAC_LINK_AUTONEG_VER_MINOR		3
+
+struct dpaa2_mac_link_mode_map {
+	u64 dpmac_lm;
+	u64 ethtool_lm;
+};
+
+static const struct dpaa2_mac_link_mode_map dpaa2_mac_lm_map[] = {
+	{DPMAC_ADVERTISED_10BASET_FULL, ETHTOOL_LINK_MODE_10baseT_Full_BIT},
+	{DPMAC_ADVERTISED_100BASET_FULL, ETHTOOL_LINK_MODE_100baseT_Full_BIT},
+	{DPMAC_ADVERTISED_1000BASET_FULL, ETHTOOL_LINK_MODE_1000baseT_Full_BIT},
+	{DPMAC_ADVERTISED_10000BASET_FULL, ETHTOOL_LINK_MODE_10000baseT_Full_BIT},
+	{DPMAC_ADVERTISED_2500BASEX_FULL, ETHTOOL_LINK_MODE_2500baseT_Full_BIT},
+	{DPMAC_ADVERTISED_AUTONEG, ETHTOOL_LINK_MODE_Autoneg_BIT},
+};
+
+static void link_mode_dpmac2phydev(u64 dpmac_lm, unsigned long *phydev_lm)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(dpaa2_mac_lm_map); i++) {
+		if (dpmac_lm & dpaa2_mac_lm_map[i].dpmac_lm)
+			linkmode_set_bit(dpaa2_mac_lm_map[i].ethtool_lm, phydev_lm);
+	}
+}
+
+static void link_mode_phydev2dpmac(unsigned long *phydev_lm, u64 *dpni_lm)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(dpaa2_mac_lm_map); i++) {
+		if (linkmode_test_bit(dpaa2_mac_lm_map[i].ethtool_lm, phydev_lm))
+			*dpni_lm |= dpaa2_mac_lm_map[i].dpmac_lm;
+	}
+}
+
 static void dpaa2_mac_link_changed(struct net_device *netdev)
 {
 	struct phy_device	*phydev;
@@ -122,11 +160,18 @@ static void dpaa2_mac_link_changed(struc
 		phy_print_status(phydev);
 	}
 
-	/* We must interrogate MC at all times, because we don't know
-	 * when and whether a potential DPNI may have read the link state.
-	 */
-	err = dpmac_set_link_state(priv->mc_dev->mc_io, 0,
-				   priv->mc_dev->mc_handle, &state);
+	if (cmp_dpmac_ver(priv, DPMAC_LINK_AUTONEG_VER_MAJOR,
+			  DPMAC_LINK_AUTONEG_VER_MINOR) < 0) {
+		err = dpmac_set_link_state(priv->mc_dev->mc_io, 0,
+					   priv->mc_dev->mc_handle, &state);
+	} else {
+		link_mode_phydev2dpmac(phydev->supported, &state.supported);
+		link_mode_phydev2dpmac(phydev->advertising, &state.advertising);
+		state.state_valid = 1;
+
+		err = dpmac_set_link_state_v2(priv->mc_dev->mc_io, 0,
+					      priv->mc_dev->mc_handle, &state);
+	}
 	if (unlikely(err))
 		dev_err(&priv->mc_dev->dev, "dpmac_set_link_state: %d\n", err);
 }
@@ -365,12 +410,17 @@ static void configure_link(struct dpaa2_
 	phydev->speed = cfg->rate;
 	phydev->duplex  = !!(cfg->options & DPMAC_LINK_OPT_HALF_DUPLEX);
 
+	if (cfg->advertising != 0) {
+		linkmode_zero(phydev->advertising);
+		link_mode_dpmac2phydev(cfg->advertising, phydev->advertising);
+	}
+
 	if (cfg->options & DPMAC_LINK_OPT_AUTONEG) {
-		phydev->autoneg = 1;
-		phydev->advertising |= ADVERTISED_Autoneg;
+		phydev->autoneg = AUTONEG_ENABLE;
+		linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->advertising);
 	} else {
-		phydev->autoneg = 0;
-		phydev->advertising &= ~ADVERTISED_Autoneg;
+		phydev->autoneg = AUTONEG_DISABLE;
+		linkmode_clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->advertising);
 	}
 
 	phy_start_aneg(phydev);
@@ -392,8 +442,14 @@ static irqreturn_t dpaa2_mac_irq_handler
 
 	/* DPNI-initiated link configuration; 'ifconfig up' also calls this */
 	if (status & DPMAC_IRQ_EVENT_LINK_CFG_REQ) {
-		err = dpmac_get_link_cfg(mc_dev->mc_io, 0, mc_dev->mc_handle,
-					 &link_cfg);
+		if (cmp_dpmac_ver(priv, DPMAC_LINK_AUTONEG_VER_MAJOR,
+				  DPMAC_LINK_AUTONEG_VER_MINOR) < 0)
+			err = dpmac_get_link_cfg(mc_dev->mc_io, 0,
+						 mc_dev->mc_handle, &link_cfg);
+		else
+			err = dpmac_get_link_cfg_v2(mc_dev->mc_io, 0,
+						    mc_dev->mc_handle,
+						    &link_cfg);
 		if (unlikely(err))
 			goto out;