root/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib_vlan.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mlx5i_pkey_qpn_ht_init
  2. mlx5i_pkey_qpn_ht_cleanup
  3. mlx5i_find_qpn_to_netdev_node
  4. mlx5i_pkey_add_qpn
  5. mlx5i_pkey_del_qpn
  6. mlx5i_pkey_get_netdev
  7. mlx5i_pkey_dev_init
  8. mlx5i_pkey_ioctl
  9. mlx5i_pkey_dev_cleanup
  10. mlx5i_pkey_open
  11. mlx5i_pkey_close
  12. mlx5i_pkey_change_mtu
  13. mlx5i_pkey_init
  14. mlx5i_pkey_cleanup
  15. mlx5i_pkey_init_tx
  16. mlx5i_pkey_cleanup_tx
  17. mlx5i_pkey_init_rx
  18. mlx5i_pkey_cleanup_rx
  19. mlx5i_pkey_get_profile

   1 /*
   2  * Copyright (c) 2017, 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 <linux/hash.h>
  34 #include "ipoib.h"
  35 
  36 #define MLX5I_MAX_LOG_PKEY_SUP 7
  37 
  38 struct qpn_to_netdev {
  39         struct net_device *netdev;
  40         struct hlist_node hlist;
  41         u32 underlay_qpn;
  42 };
  43 
  44 struct mlx5i_pkey_qpn_ht {
  45         struct hlist_head buckets[1 << MLX5I_MAX_LOG_PKEY_SUP];
  46         spinlock_t ht_lock; /* Synchronise with NAPI */
  47 };
  48 
  49 int mlx5i_pkey_qpn_ht_init(struct net_device *netdev)
  50 {
  51         struct mlx5i_priv *ipriv = netdev_priv(netdev);
  52         struct mlx5i_pkey_qpn_ht *qpn_htbl;
  53 
  54         qpn_htbl = kzalloc(sizeof(*qpn_htbl), GFP_KERNEL);
  55         if (!qpn_htbl)
  56                 return -ENOMEM;
  57 
  58         ipriv->qpn_htbl = qpn_htbl;
  59         spin_lock_init(&qpn_htbl->ht_lock);
  60 
  61         return 0;
  62 }
  63 
  64 void mlx5i_pkey_qpn_ht_cleanup(struct net_device *netdev)
  65 {
  66         struct mlx5i_priv *ipriv = netdev_priv(netdev);
  67 
  68         kfree(ipriv->qpn_htbl);
  69 }
  70 
  71 static struct qpn_to_netdev *mlx5i_find_qpn_to_netdev_node(struct hlist_head *buckets,
  72                                                            u32 qpn)
  73 {
  74         struct hlist_head *h = &buckets[hash_32(qpn, MLX5I_MAX_LOG_PKEY_SUP)];
  75         struct qpn_to_netdev *node;
  76 
  77         hlist_for_each_entry(node, h, hlist) {
  78                 if (node->underlay_qpn == qpn)
  79                         return node;
  80         }
  81 
  82         return NULL;
  83 }
  84 
  85 int mlx5i_pkey_add_qpn(struct net_device *netdev, u32 qpn)
  86 {
  87         struct mlx5i_priv *ipriv = netdev_priv(netdev);
  88         struct mlx5i_pkey_qpn_ht *ht = ipriv->qpn_htbl;
  89         u8 key = hash_32(qpn, MLX5I_MAX_LOG_PKEY_SUP);
  90         struct qpn_to_netdev *new_node;
  91 
  92         new_node = kzalloc(sizeof(*new_node), GFP_KERNEL);
  93         if (!new_node)
  94                 return -ENOMEM;
  95 
  96         new_node->netdev = netdev;
  97         new_node->underlay_qpn = qpn;
  98         spin_lock_bh(&ht->ht_lock);
  99         hlist_add_head(&new_node->hlist, &ht->buckets[key]);
 100         spin_unlock_bh(&ht->ht_lock);
 101 
 102         return 0;
 103 }
 104 
 105 int mlx5i_pkey_del_qpn(struct net_device *netdev, u32 qpn)
 106 {
 107         struct mlx5e_priv *epriv = mlx5i_epriv(netdev);
 108         struct mlx5i_priv *ipriv = epriv->ppriv;
 109         struct mlx5i_pkey_qpn_ht *ht = ipriv->qpn_htbl;
 110         struct qpn_to_netdev *node;
 111 
 112         node = mlx5i_find_qpn_to_netdev_node(ht->buckets, qpn);
 113         if (!node) {
 114                 mlx5_core_warn(epriv->mdev, "QPN to netdev delete from HT failed\n");
 115                 return -EINVAL;
 116         }
 117 
 118         spin_lock_bh(&ht->ht_lock);
 119         hlist_del_init(&node->hlist);
 120         spin_unlock_bh(&ht->ht_lock);
 121         kfree(node);
 122 
 123         return 0;
 124 }
 125 
 126 struct net_device *mlx5i_pkey_get_netdev(struct net_device *netdev, u32 qpn)
 127 {
 128         struct mlx5i_priv *ipriv = netdev_priv(netdev);
 129         struct qpn_to_netdev *node;
 130 
 131         node = mlx5i_find_qpn_to_netdev_node(ipriv->qpn_htbl->buckets, qpn);
 132         if (!node)
 133                 return NULL;
 134 
 135         return node->netdev;
 136 }
 137 
 138 static int mlx5i_pkey_open(struct net_device *netdev);
 139 static int mlx5i_pkey_close(struct net_device *netdev);
 140 static int mlx5i_pkey_dev_init(struct net_device *dev);
 141 static void mlx5i_pkey_dev_cleanup(struct net_device *netdev);
 142 static int mlx5i_pkey_change_mtu(struct net_device *netdev, int new_mtu);
 143 static int mlx5i_pkey_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
 144 
 145 static const struct net_device_ops mlx5i_pkey_netdev_ops = {
 146         .ndo_open                = mlx5i_pkey_open,
 147         .ndo_stop                = mlx5i_pkey_close,
 148         .ndo_init                = mlx5i_pkey_dev_init,
 149         .ndo_get_stats64         = mlx5i_get_stats,
 150         .ndo_uninit              = mlx5i_pkey_dev_cleanup,
 151         .ndo_change_mtu          = mlx5i_pkey_change_mtu,
 152         .ndo_do_ioctl            = mlx5i_pkey_ioctl,
 153 };
 154 
 155 /* Child NDOs */
 156 static int mlx5i_pkey_dev_init(struct net_device *dev)
 157 {
 158         struct mlx5e_priv *priv = mlx5i_epriv(dev);
 159         struct mlx5i_priv *ipriv, *parent_ipriv;
 160         struct net_device *parent_dev;
 161         int parent_ifindex;
 162 
 163         ipriv = priv->ppriv;
 164 
 165         /* Get QPN to netdevice hash table from parent */
 166         parent_ifindex = dev->netdev_ops->ndo_get_iflink(dev);
 167         parent_dev = dev_get_by_index(dev_net(dev), parent_ifindex);
 168         if (!parent_dev) {
 169                 mlx5_core_warn(priv->mdev, "failed to get parent device\n");
 170                 return -EINVAL;
 171         }
 172 
 173         parent_ipriv = netdev_priv(parent_dev);
 174         ipriv->qpn_htbl = parent_ipriv->qpn_htbl;
 175         dev_put(parent_dev);
 176 
 177         return mlx5i_dev_init(dev);
 178 }
 179 
 180 static int mlx5i_pkey_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 181 {
 182         return mlx5i_ioctl(dev, ifr, cmd);
 183 }
 184 
 185 static void mlx5i_pkey_dev_cleanup(struct net_device *netdev)
 186 {
 187         return mlx5i_dev_cleanup(netdev);
 188 }
 189 
 190 static int mlx5i_pkey_open(struct net_device *netdev)
 191 {
 192         struct mlx5e_priv *epriv = mlx5i_epriv(netdev);
 193         struct mlx5i_priv *ipriv = epriv->ppriv;
 194         struct mlx5_core_dev *mdev = epriv->mdev;
 195         int err;
 196 
 197         mutex_lock(&epriv->state_lock);
 198 
 199         set_bit(MLX5E_STATE_OPENED, &epriv->state);
 200 
 201         err = mlx5i_init_underlay_qp(epriv);
 202         if (err) {
 203                 mlx5_core_warn(mdev, "prepare child underlay qp state failed, %d\n", err);
 204                 goto err_release_lock;
 205         }
 206 
 207         err = mlx5_fs_add_rx_underlay_qpn(mdev, ipriv->qp.qpn);
 208         if (err) {
 209                 mlx5_core_warn(mdev, "attach child underlay qp to ft failed, %d\n", err);
 210                 goto err_unint_underlay_qp;
 211         }
 212 
 213         err = mlx5i_create_tis(mdev, ipriv->qp.qpn, &epriv->tisn[0][0]);
 214         if (err) {
 215                 mlx5_core_warn(mdev, "create child tis failed, %d\n", err);
 216                 goto err_remove_rx_uderlay_qp;
 217         }
 218 
 219         err = mlx5e_open_channels(epriv, &epriv->channels);
 220         if (err) {
 221                 mlx5_core_warn(mdev, "opening child channels failed, %d\n", err);
 222                 goto err_clear_state_opened_flag;
 223         }
 224         epriv->profile->update_rx(epriv);
 225         mlx5e_activate_priv_channels(epriv);
 226         mutex_unlock(&epriv->state_lock);
 227 
 228         return 0;
 229 
 230 err_clear_state_opened_flag:
 231         mlx5e_destroy_tis(mdev, epriv->tisn[0][0]);
 232 err_remove_rx_uderlay_qp:
 233         mlx5_fs_remove_rx_underlay_qpn(mdev, ipriv->qp.qpn);
 234 err_unint_underlay_qp:
 235         mlx5i_uninit_underlay_qp(epriv);
 236 err_release_lock:
 237         clear_bit(MLX5E_STATE_OPENED, &epriv->state);
 238         mutex_unlock(&epriv->state_lock);
 239         return err;
 240 }
 241 
 242 static int mlx5i_pkey_close(struct net_device *netdev)
 243 {
 244         struct mlx5e_priv *priv = mlx5i_epriv(netdev);
 245         struct mlx5i_priv *ipriv = priv->ppriv;
 246         struct mlx5_core_dev *mdev = priv->mdev;
 247 
 248         mutex_lock(&priv->state_lock);
 249 
 250         if (!test_bit(MLX5E_STATE_OPENED, &priv->state))
 251                 goto unlock;
 252 
 253         clear_bit(MLX5E_STATE_OPENED, &priv->state);
 254 
 255         netif_carrier_off(priv->netdev);
 256         mlx5_fs_remove_rx_underlay_qpn(mdev, ipriv->qp.qpn);
 257         mlx5i_uninit_underlay_qp(priv);
 258         mlx5e_deactivate_priv_channels(priv);
 259         mlx5e_close_channels(&priv->channels);
 260         mlx5e_destroy_tis(mdev, priv->tisn[0][0]);
 261 unlock:
 262         mutex_unlock(&priv->state_lock);
 263         return 0;
 264 }
 265 
 266 static int mlx5i_pkey_change_mtu(struct net_device *netdev, int new_mtu)
 267 {
 268         struct mlx5e_priv *priv = mlx5i_epriv(netdev);
 269 
 270         mutex_lock(&priv->state_lock);
 271         netdev->mtu = new_mtu;
 272         mutex_unlock(&priv->state_lock);
 273 
 274         return 0;
 275 }
 276 
 277 /* Called directly after IPoIB netdevice was created to initialize SW structs */
 278 static int mlx5i_pkey_init(struct mlx5_core_dev *mdev,
 279                            struct net_device *netdev,
 280                            const struct mlx5e_profile *profile,
 281                            void *ppriv)
 282 {
 283         struct mlx5e_priv *priv  = mlx5i_epriv(netdev);
 284         int err;
 285 
 286         err = mlx5i_init(mdev, netdev, profile, ppriv);
 287         if (err)
 288                 return err;
 289 
 290         /* Override parent ndo */
 291         netdev->netdev_ops = &mlx5i_pkey_netdev_ops;
 292 
 293         /* Set child limited ethtool support */
 294         netdev->ethtool_ops = &mlx5i_pkey_ethtool_ops;
 295 
 296         /* Use dummy rqs */
 297         priv->channels.params.log_rq_mtu_frames = MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE;
 298 
 299         return 0;
 300 }
 301 
 302 /* Called directly before IPoIB netdevice is destroyed to cleanup SW structs */
 303 static void mlx5i_pkey_cleanup(struct mlx5e_priv *priv)
 304 {
 305         mlx5i_cleanup(priv);
 306 }
 307 
 308 static int mlx5i_pkey_init_tx(struct mlx5e_priv *priv)
 309 {
 310         struct mlx5i_priv *ipriv = priv->ppriv;
 311         int err;
 312 
 313         err = mlx5i_create_underlay_qp(priv->mdev, &ipriv->qp);
 314         if (err) {
 315                 mlx5_core_warn(priv->mdev, "create child underlay QP failed, %d\n", err);
 316                 return err;
 317         }
 318 
 319         return 0;
 320 }
 321 
 322 static void mlx5i_pkey_cleanup_tx(struct mlx5e_priv *priv)
 323 {
 324         struct mlx5i_priv *ipriv = priv->ppriv;
 325 
 326         mlx5i_destroy_underlay_qp(priv->mdev, &ipriv->qp);
 327 }
 328 
 329 static int mlx5i_pkey_init_rx(struct mlx5e_priv *priv)
 330 {
 331         /* Since the rx resources are shared between child and parent, the
 332          * parent interface is taking care of rx resource allocation and init
 333          */
 334         return 0;
 335 }
 336 
 337 static void mlx5i_pkey_cleanup_rx(struct mlx5e_priv *priv)
 338 {
 339         /* Since the rx resources are shared between child and parent, the
 340          * parent interface is taking care of rx resource free and de-init
 341          */
 342 }
 343 
 344 static const struct mlx5e_profile mlx5i_pkey_nic_profile = {
 345         .init              = mlx5i_pkey_init,
 346         .cleanup           = mlx5i_pkey_cleanup,
 347         .init_tx           = mlx5i_pkey_init_tx,
 348         .cleanup_tx        = mlx5i_pkey_cleanup_tx,
 349         .init_rx           = mlx5i_pkey_init_rx,
 350         .cleanup_rx        = mlx5i_pkey_cleanup_rx,
 351         .enable            = NULL,
 352         .disable           = NULL,
 353         .update_rx         = mlx5e_update_nic_rx,
 354         .update_stats      = NULL,
 355         .rx_handlers.handle_rx_cqe       = mlx5i_handle_rx_cqe,
 356         .rx_handlers.handle_rx_cqe_mpwqe = NULL, /* Not supported */
 357         .max_tc            = MLX5I_MAX_NUM_TC,
 358         .rq_groups         = MLX5E_NUM_RQ_GROUPS(REGULAR),
 359 };
 360 
 361 const struct mlx5e_profile *mlx5i_pkey_get_profile(void)
 362 {
 363         return &mlx5i_pkey_nic_profile;
 364 }

/* [<][>][^][v][top][bottom][index][help] */