aboutsummaryrefslogtreecommitdiffstats
path: root/net/dsa
diff options
context:
space:
mode:
authorFlorian Fainelli <f.fainelli@gmail.com>2019-01-15 17:43:04 -0500
committerDavid S. Miller <davem@davemloft.net>2019-01-17 00:12:21 -0500
commitda7b9e9b00d4859d0fa563d7fe9a2b2dff59e852 (patch)
tree780c33a93ca4a8a13ca6dc3e5012e345fe5e5fe2 /net/dsa
parent44543f1dd2a39d56c9afdc3778aa050b5a4725b4 (diff)
net: dsa: Add ndo_get_phys_port_name() for CPU port
There is not currently way to infer the port number through sysfs that is being used as the CPU port number. Overlay a ndo_get_phys_port_name() operation onto the DSA master network device in order to retrieve that information. Signed-off-by: Florian Fainelli <f.fainelli@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/dsa')
-rw-r--r--net/dsa/master.c56
1 files changed, 55 insertions, 1 deletions
diff --git a/net/dsa/master.c b/net/dsa/master.c
index 71bb15f491c8..79e97d2f2d9b 100644
--- a/net/dsa/master.c
+++ b/net/dsa/master.c
@@ -126,6 +126,17 @@ static void dsa_master_get_strings(struct net_device *dev, uint32_t stringset,
126 } 126 }
127} 127}
128 128
129static int dsa_master_get_phys_port_name(struct net_device *dev,
130 char *name, size_t len)
131{
132 struct dsa_port *cpu_dp = dev->dsa_ptr;
133
134 if (snprintf(name, len, "p%d", cpu_dp->index) >= len)
135 return -EINVAL;
136
137 return 0;
138}
139
129static int dsa_master_ethtool_setup(struct net_device *dev) 140static int dsa_master_ethtool_setup(struct net_device *dev)
130{ 141{
131 struct dsa_port *cpu_dp = dev->dsa_ptr; 142 struct dsa_port *cpu_dp = dev->dsa_ptr;
@@ -158,6 +169,38 @@ static void dsa_master_ethtool_teardown(struct net_device *dev)
158 cpu_dp->orig_ethtool_ops = NULL; 169 cpu_dp->orig_ethtool_ops = NULL;
159} 170}
160 171
172static int dsa_master_ndo_setup(struct net_device *dev)
173{
174 struct dsa_port *cpu_dp = dev->dsa_ptr;
175 struct dsa_switch *ds = cpu_dp->ds;
176 struct net_device_ops *ops;
177
178 if (dev->netdev_ops->ndo_get_phys_port_name)
179 return 0;
180
181 ops = devm_kzalloc(ds->dev, sizeof(*ops), GFP_KERNEL);
182 if (!ops)
183 return -ENOMEM;
184
185 cpu_dp->orig_ndo_ops = dev->netdev_ops;
186 if (cpu_dp->orig_ndo_ops)
187 memcpy(ops, cpu_dp->orig_ndo_ops, sizeof(*ops));
188
189 ops->ndo_get_phys_port_name = dsa_master_get_phys_port_name;
190
191 dev->netdev_ops = ops;
192
193 return 0;
194}
195
196static void dsa_master_ndo_teardown(struct net_device *dev)
197{
198 struct dsa_port *cpu_dp = dev->dsa_ptr;
199
200 dev->netdev_ops = cpu_dp->orig_ndo_ops;
201 cpu_dp->orig_ndo_ops = NULL;
202}
203
161static ssize_t tagging_show(struct device *d, struct device_attribute *attr, 204static ssize_t tagging_show(struct device *d, struct device_attribute *attr,
162 char *buf) 205 char *buf)
163{ 206{
@@ -223,16 +266,27 @@ int dsa_master_setup(struct net_device *dev, struct dsa_port *cpu_dp)
223 if (ret) 266 if (ret)
224 return ret; 267 return ret;
225 268
269 ret = dsa_master_ndo_setup(dev);
270 if (ret)
271 goto out_err_ethtool_teardown;
272
226 ret = sysfs_create_group(&dev->dev.kobj, &dsa_group); 273 ret = sysfs_create_group(&dev->dev.kobj, &dsa_group);
227 if (ret) 274 if (ret)
228 dsa_master_ethtool_teardown(dev); 275 goto out_err_ndo_teardown;
276
277 return ret;
229 278
279out_err_ndo_teardown:
280 dsa_master_ndo_teardown(dev);
281out_err_ethtool_teardown:
282 dsa_master_ethtool_teardown(dev);
230 return ret; 283 return ret;
231} 284}
232 285
233void dsa_master_teardown(struct net_device *dev) 286void dsa_master_teardown(struct net_device *dev)
234{ 287{
235 sysfs_remove_group(&dev->dev.kobj, &dsa_group); 288 sysfs_remove_group(&dev->dev.kobj, &dsa_group);
289 dsa_master_ndo_teardown(dev);
236 dsa_master_ethtool_teardown(dev); 290 dsa_master_ethtool_teardown(dev);
237 dsa_master_reset_mtu(dev); 291 dsa_master_reset_mtu(dev);
238 292