net/mlx5e: Implement mlx5e interface attach/detach callbacks
[sfrench/cifs-2.6.git] / drivers / net / ethernet / mellanox / mlx5 / core / en_rep.c
1 /*
2  * Copyright (c) 2016, Mellanox Technologies. All rights reserved.
3  *
4  * This software is available to you under a choice of one of two
5  * licenses.  You may choose to be licensed under the terms of the GNU
6  * General Public License (GPL) Version 2, available from the file
7  * COPYING in the main directory of this source tree, or the
8  * OpenIB.org BSD license below:
9  *
10  *     Redistribution and use in source and binary forms, with or
11  *     without modification, are permitted provided that the following
12  *     conditions are met:
13  *
14  *      - Redistributions of source code must retain the above
15  *        copyright notice, this list of conditions and the following
16  *        disclaimer.
17  *
18  *      - Redistributions in binary form must reproduce the above
19  *        copyright notice, this list of conditions and the following
20  *        disclaimer in the documentation and/or other materials
21  *        provided with the distribution.
22  *
23  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30  * SOFTWARE.
31  */
32
33 #include <generated/utsrelease.h>
34 #include <linux/mlx5/fs.h>
35 #include <net/switchdev.h>
36 #include <net/pkt_cls.h>
37
38 #include "eswitch.h"
39 #include "en.h"
40 #include "en_tc.h"
41
42 static const char mlx5e_rep_driver_name[] = "mlx5e_rep";
43
44 static void mlx5e_rep_get_drvinfo(struct net_device *dev,
45                                   struct ethtool_drvinfo *drvinfo)
46 {
47         strlcpy(drvinfo->driver, mlx5e_rep_driver_name,
48                 sizeof(drvinfo->driver));
49         strlcpy(drvinfo->version, UTS_RELEASE, sizeof(drvinfo->version));
50 }
51
52 static const struct counter_desc sw_rep_stats_desc[] = {
53         { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_packets) },
54         { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_bytes) },
55         { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_packets) },
56         { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_bytes) },
57 };
58
59 #define NUM_VPORT_REP_COUNTERS  ARRAY_SIZE(sw_rep_stats_desc)
60
61 static void mlx5e_rep_get_strings(struct net_device *dev,
62                                   u32 stringset, uint8_t *data)
63 {
64         int i;
65
66         switch (stringset) {
67         case ETH_SS_STATS:
68                 for (i = 0; i < NUM_VPORT_REP_COUNTERS; i++)
69                         strcpy(data + (i * ETH_GSTRING_LEN),
70                                sw_rep_stats_desc[i].format);
71                 break;
72         }
73 }
74
75 static void mlx5e_update_sw_rep_counters(struct mlx5e_priv *priv)
76 {
77         struct mlx5e_sw_stats *s = &priv->stats.sw;
78         struct mlx5e_rq_stats *rq_stats;
79         struct mlx5e_sq_stats *sq_stats;
80         int i, j;
81
82         memset(s, 0, sizeof(*s));
83         for (i = 0; i < priv->params.num_channels; i++) {
84                 rq_stats = &priv->channel[i]->rq.stats;
85
86                 s->rx_packets   += rq_stats->packets;
87                 s->rx_bytes     += rq_stats->bytes;
88
89                 for (j = 0; j < priv->params.num_tc; j++) {
90                         sq_stats = &priv->channel[i]->sq[j].stats;
91
92                         s->tx_packets           += sq_stats->packets;
93                         s->tx_bytes             += sq_stats->bytes;
94                 }
95         }
96 }
97
98 static void mlx5e_rep_get_ethtool_stats(struct net_device *dev,
99                                         struct ethtool_stats *stats, u64 *data)
100 {
101         struct mlx5e_priv *priv = netdev_priv(dev);
102         int i;
103
104         if (!data)
105                 return;
106
107         mutex_lock(&priv->state_lock);
108         if (test_bit(MLX5E_STATE_OPENED, &priv->state))
109                 mlx5e_update_sw_rep_counters(priv);
110         mutex_unlock(&priv->state_lock);
111
112         for (i = 0; i < NUM_VPORT_REP_COUNTERS; i++)
113                 data[i] = MLX5E_READ_CTR64_CPU(&priv->stats.sw,
114                                                sw_rep_stats_desc, i);
115 }
116
117 static int mlx5e_rep_get_sset_count(struct net_device *dev, int sset)
118 {
119         switch (sset) {
120         case ETH_SS_STATS:
121                 return NUM_VPORT_REP_COUNTERS;
122         default:
123                 return -EOPNOTSUPP;
124         }
125 }
126
127 static const struct ethtool_ops mlx5e_rep_ethtool_ops = {
128         .get_drvinfo       = mlx5e_rep_get_drvinfo,
129         .get_link          = ethtool_op_get_link,
130         .get_strings       = mlx5e_rep_get_strings,
131         .get_sset_count    = mlx5e_rep_get_sset_count,
132         .get_ethtool_stats = mlx5e_rep_get_ethtool_stats,
133 };
134
135 int mlx5e_attr_get(struct net_device *dev, struct switchdev_attr *attr)
136 {
137         struct mlx5e_priv *priv = netdev_priv(dev);
138         struct mlx5_eswitch_rep *rep = priv->ppriv;
139         struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
140
141         if (esw->mode == SRIOV_NONE)
142                 return -EOPNOTSUPP;
143
144         switch (attr->id) {
145         case SWITCHDEV_ATTR_ID_PORT_PARENT_ID:
146                 attr->u.ppid.id_len = ETH_ALEN;
147                 ether_addr_copy(attr->u.ppid.id, rep->hw_id);
148                 break;
149         default:
150                 return -EOPNOTSUPP;
151         }
152
153         return 0;
154 }
155
156 int mlx5e_add_sqs_fwd_rules(struct mlx5e_priv *priv)
157
158 {
159         struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
160         struct mlx5_eswitch_rep *rep = priv->ppriv;
161         struct mlx5e_channel *c;
162         int n, tc, err, num_sqs = 0;
163         u16 *sqs;
164
165         sqs = kcalloc(priv->params.num_channels * priv->params.num_tc, sizeof(u16), GFP_KERNEL);
166         if (!sqs)
167                 return -ENOMEM;
168
169         for (n = 0; n < priv->params.num_channels; n++) {
170                 c = priv->channel[n];
171                 for (tc = 0; tc < c->num_tc; tc++)
172                         sqs[num_sqs++] = c->sq[tc].sqn;
173         }
174
175         err = mlx5_eswitch_sqs2vport_start(esw, rep, sqs, num_sqs);
176
177         kfree(sqs);
178         return err;
179 }
180
181 int mlx5e_nic_rep_load(struct mlx5_eswitch *esw, struct mlx5_eswitch_rep *rep)
182 {
183         struct mlx5e_priv *priv = rep->priv_data;
184
185         if (test_bit(MLX5E_STATE_OPENED, &priv->state))
186                 return mlx5e_add_sqs_fwd_rules(priv);
187         return 0;
188 }
189
190 void mlx5e_remove_sqs_fwd_rules(struct mlx5e_priv *priv)
191 {
192         struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
193         struct mlx5_eswitch_rep *rep = priv->ppriv;
194
195         mlx5_eswitch_sqs2vport_stop(esw, rep);
196 }
197
198 void mlx5e_nic_rep_unload(struct mlx5_eswitch *esw,
199                           struct mlx5_eswitch_rep *rep)
200 {
201         struct mlx5e_priv *priv = rep->priv_data;
202
203         if (test_bit(MLX5E_STATE_OPENED, &priv->state))
204                 mlx5e_remove_sqs_fwd_rules(priv);
205
206         /* clean (and re-init) existing uplink offloaded TC rules */
207         mlx5e_tc_cleanup(priv);
208         mlx5e_tc_init(priv);
209 }
210
211 static int mlx5e_rep_get_phys_port_name(struct net_device *dev,
212                                         char *buf, size_t len)
213 {
214         struct mlx5e_priv *priv = netdev_priv(dev);
215         struct mlx5_eswitch_rep *rep = priv->ppriv;
216         int ret;
217
218         ret = snprintf(buf, len, "%d", rep->vport - 1);
219         if (ret >= len)
220                 return -EOPNOTSUPP;
221
222         return 0;
223 }
224
225 static int mlx5e_rep_ndo_setup_tc(struct net_device *dev, u32 handle,
226                                   __be16 proto, struct tc_to_netdev *tc)
227 {
228         struct mlx5e_priv *priv = netdev_priv(dev);
229
230         if (TC_H_MAJ(handle) != TC_H_MAJ(TC_H_INGRESS))
231                 return -EOPNOTSUPP;
232
233         switch (tc->type) {
234         case TC_SETUP_CLSFLOWER:
235                 switch (tc->cls_flower->command) {
236                 case TC_CLSFLOWER_REPLACE:
237                         return mlx5e_configure_flower(priv, proto, tc->cls_flower);
238                 case TC_CLSFLOWER_DESTROY:
239                         return mlx5e_delete_flower(priv, tc->cls_flower);
240                 case TC_CLSFLOWER_STATS:
241                         return mlx5e_stats_flower(priv, tc->cls_flower);
242                 }
243         default:
244                 return -EOPNOTSUPP;
245         }
246 }
247
248 static const struct switchdev_ops mlx5e_rep_switchdev_ops = {
249         .switchdev_port_attr_get        = mlx5e_attr_get,
250 };
251
252 static const struct net_device_ops mlx5e_netdev_ops_rep = {
253         .ndo_open                = mlx5e_open,
254         .ndo_stop                = mlx5e_close,
255         .ndo_start_xmit          = mlx5e_xmit,
256         .ndo_get_phys_port_name  = mlx5e_rep_get_phys_port_name,
257         .ndo_setup_tc            = mlx5e_rep_ndo_setup_tc,
258         .ndo_get_stats64         = mlx5e_get_stats,
259 };
260
261 static void mlx5e_build_rep_netdev_priv(struct mlx5_core_dev *mdev,
262                                         struct net_device *netdev,
263                                         const struct mlx5e_profile *profile,
264                                         void *ppriv)
265 {
266         struct mlx5e_priv *priv = netdev_priv(netdev);
267         u8 cq_period_mode = MLX5_CAP_GEN(mdev, cq_period_start_from_cqe) ?
268                                          MLX5_CQ_PERIOD_MODE_START_FROM_CQE :
269                                          MLX5_CQ_PERIOD_MODE_START_FROM_EQE;
270
271         priv->params.log_sq_size           =
272                 MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE;
273         priv->params.rq_wq_type = MLX5_WQ_TYPE_LINKED_LIST;
274         priv->params.log_rq_size = MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE;
275
276         priv->params.min_rx_wqes = mlx5_min_rx_wqes(priv->params.rq_wq_type,
277                                             BIT(priv->params.log_rq_size));
278
279         priv->params.rx_am_enabled = MLX5_CAP_GEN(mdev, cq_moderation);
280         mlx5e_set_rx_cq_mode_params(&priv->params, cq_period_mode);
281
282         priv->params.tx_max_inline         = mlx5e_get_max_inline_cap(mdev);
283         priv->params.num_tc                = 1;
284
285         priv->params.lro_wqe_sz            =
286                 MLX5E_PARAMS_DEFAULT_LRO_WQE_SZ;
287
288         priv->mdev                         = mdev;
289         priv->netdev                       = netdev;
290         priv->params.num_channels          = profile->max_nch(mdev);
291         priv->profile                      = profile;
292         priv->ppriv                        = ppriv;
293
294         mutex_init(&priv->state_lock);
295
296         INIT_DELAYED_WORK(&priv->update_stats_work, mlx5e_update_stats_work);
297 }
298
299 static void mlx5e_build_rep_netdev(struct net_device *netdev)
300 {
301         netdev->netdev_ops = &mlx5e_netdev_ops_rep;
302
303         netdev->watchdog_timeo    = 15 * HZ;
304
305         netdev->ethtool_ops       = &mlx5e_rep_ethtool_ops;
306
307 #ifdef CONFIG_NET_SWITCHDEV
308         netdev->switchdev_ops = &mlx5e_rep_switchdev_ops;
309 #endif
310
311         netdev->features         |= NETIF_F_VLAN_CHALLENGED | NETIF_F_HW_TC;
312         netdev->hw_features      |= NETIF_F_HW_TC;
313
314         eth_hw_addr_random(netdev);
315 }
316
317 static void mlx5e_init_rep(struct mlx5_core_dev *mdev,
318                            struct net_device *netdev,
319                            const struct mlx5e_profile *profile,
320                            void *ppriv)
321 {
322         mlx5e_build_rep_netdev_priv(mdev, netdev, profile, ppriv);
323         mlx5e_build_rep_netdev(netdev);
324 }
325
326 static int mlx5e_init_rep_rx(struct mlx5e_priv *priv)
327 {
328         struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
329         struct mlx5_eswitch_rep *rep = priv->ppriv;
330         struct mlx5_core_dev *mdev = priv->mdev;
331         struct mlx5_flow_rule *flow_rule;
332         int err;
333         int i;
334
335         err = mlx5e_create_direct_rqts(priv);
336         if (err) {
337                 mlx5_core_warn(mdev, "create direct rqts failed, %d\n", err);
338                 return err;
339         }
340
341         err = mlx5e_create_direct_tirs(priv);
342         if (err) {
343                 mlx5_core_warn(mdev, "create direct tirs failed, %d\n", err);
344                 goto err_destroy_direct_rqts;
345         }
346
347         flow_rule = mlx5_eswitch_create_vport_rx_rule(esw,
348                                                       rep->vport,
349                                                       priv->direct_tir[0].tirn);
350         if (IS_ERR(flow_rule)) {
351                 err = PTR_ERR(flow_rule);
352                 goto err_destroy_direct_tirs;
353         }
354         rep->vport_rx_rule = flow_rule;
355
356         err = mlx5e_tc_init(priv);
357         if (err)
358                 goto err_del_flow_rule;
359
360         return 0;
361
362 err_del_flow_rule:
363         mlx5_del_flow_rule(rep->vport_rx_rule);
364 err_destroy_direct_tirs:
365         mlx5e_destroy_direct_tirs(priv);
366 err_destroy_direct_rqts:
367         for (i = 0; i < priv->params.num_channels; i++)
368                 mlx5e_destroy_rqt(priv, &priv->direct_tir[i].rqt);
369         return err;
370 }
371
372 static void mlx5e_cleanup_rep_rx(struct mlx5e_priv *priv)
373 {
374         struct mlx5_eswitch_rep *rep = priv->ppriv;
375         int i;
376
377         mlx5e_tc_cleanup(priv);
378         mlx5_del_flow_rule(rep->vport_rx_rule);
379         mlx5e_destroy_direct_tirs(priv);
380         for (i = 0; i < priv->params.num_channels; i++)
381                 mlx5e_destroy_rqt(priv, &priv->direct_tir[i].rqt);
382 }
383
384 static int mlx5e_init_rep_tx(struct mlx5e_priv *priv)
385 {
386         int err;
387
388         err = mlx5e_create_tises(priv);
389         if (err) {
390                 mlx5_core_warn(priv->mdev, "create tises failed, %d\n", err);
391                 return err;
392         }
393         return 0;
394 }
395
396 static int mlx5e_get_rep_max_num_channels(struct mlx5_core_dev *mdev)
397 {
398 #define MLX5E_PORT_REPRESENTOR_NCH 1
399         return MLX5E_PORT_REPRESENTOR_NCH;
400 }
401
402 static struct mlx5e_profile mlx5e_rep_profile = {
403         .init                   = mlx5e_init_rep,
404         .init_rx                = mlx5e_init_rep_rx,
405         .cleanup_rx             = mlx5e_cleanup_rep_rx,
406         .init_tx                = mlx5e_init_rep_tx,
407         .cleanup_tx             = mlx5e_cleanup_nic_tx,
408         .update_stats           = mlx5e_update_sw_rep_counters,
409         .max_nch                = mlx5e_get_rep_max_num_channels,
410         .max_tc                 = 1,
411 };
412
413 int mlx5e_vport_rep_load(struct mlx5_eswitch *esw,
414                          struct mlx5_eswitch_rep *rep)
415 {
416         struct net_device *netdev;
417         int err;
418
419         netdev = mlx5e_create_netdev(esw->dev, &mlx5e_rep_profile, rep);
420         if (!netdev) {
421                 pr_warn("Failed to create representor netdev for vport %d\n",
422                         rep->vport);
423                 return -EINVAL;
424         }
425
426         rep->priv_data = netdev_priv(netdev);
427
428         err = mlx5e_attach_netdev(esw->dev, netdev);
429         if (err) {
430                 pr_warn("Failed to attach representor netdev for vport %d\n",
431                         rep->vport);
432                 goto err_destroy_netdev;
433         }
434
435         err = register_netdev(netdev);
436         if (err) {
437                 pr_warn("Failed to register representor netdev for vport %d\n",
438                         rep->vport);
439                 goto err_detach_netdev;
440         }
441
442         return 0;
443
444 err_detach_netdev:
445         mlx5e_detach_netdev(esw->dev, netdev);
446
447 err_destroy_netdev:
448         mlx5e_destroy_netdev(esw->dev, rep->priv_data);
449
450         return err;
451
452 }
453
454 void mlx5e_vport_rep_unload(struct mlx5_eswitch *esw,
455                             struct mlx5_eswitch_rep *rep)
456 {
457         struct mlx5e_priv *priv = rep->priv_data;
458         struct net_device *netdev = priv->netdev;
459
460         mlx5e_detach_netdev(esw->dev, netdev);
461         mlx5e_destroy_netdev(esw->dev, priv);
462 }