int mlx5e_vport_rep_load(struct mlx5_eswitch *esw, struct mlx5_eswitch_rep *rep) { struct net_device *netdev; int err; netdev = mlx5e_create_netdev(esw->dev, &mlx5e_rep_profile, rep); if (!netdev) { pr_warn("Failed to create representor netdev for vport %d\n", rep->vport); return -EINVAL; } rep->priv_data = netdev_priv(netdev); err = mlx5e_attach_netdev(esw->dev, netdev); if (err) { pr_warn("Failed to attach representor netdev for vport %d\n", rep->vport); goto err_destroy_netdev; } err = register_netdev(netdev); if (err) { pr_warn("Failed to register representor netdev for vport %d\n", rep->vport); goto err_detach_netdev; } return 0; err_detach_netdev: mlx5e_detach_netdev(esw->dev, netdev); err_destroy_netdev: mlx5e_destroy_netdev(esw->dev, rep->priv_data); return err; }
struct net_device *mlx5_rdma_netdev_alloc(struct mlx5_core_dev *mdev, struct ib_device *ibdev, const char *name, void (*setup)(struct net_device *)) { const struct mlx5e_profile *profile; struct net_device *netdev; struct mlx5i_priv *ipriv; struct mlx5e_priv *epriv; struct rdma_netdev *rn; bool sub_interface; int nch; int err; if (mlx5i_check_required_hca_cap(mdev)) { mlx5_core_warn(mdev, "Accelerated mode is not supported\n"); return ERR_PTR(-EOPNOTSUPP); } /* TODO: Need to find a better way to check if child device*/ sub_interface = (mdev->mlx5e_res.pdn != 0); if (sub_interface) profile = mlx5i_pkey_get_profile(); else profile = &mlx5i_nic_profile; nch = profile->max_nch(mdev); netdev = alloc_netdev_mqs(sizeof(struct mlx5i_priv) + sizeof(struct mlx5e_priv), name, NET_NAME_UNKNOWN, setup, nch * MLX5E_MAX_NUM_TC, nch); if (!netdev) { mlx5_core_warn(mdev, "alloc_netdev_mqs failed\n"); return NULL; } ipriv = netdev_priv(netdev); epriv = mlx5i_epriv(netdev); epriv->wq = create_singlethread_workqueue("mlx5i"); if (!epriv->wq) goto err_free_netdev; ipriv->sub_interface = sub_interface; if (!ipriv->sub_interface) { err = mlx5i_pkey_qpn_ht_init(netdev); if (err) { mlx5_core_warn(mdev, "allocate qpn_to_netdev ht failed\n"); goto destroy_wq; } /* This should only be called once per mdev */ err = mlx5e_create_mdev_resources(mdev); if (err) goto destroy_ht; } profile->init(mdev, netdev, profile, ipriv); mlx5e_attach_netdev(epriv); netif_carrier_off(netdev); /* set rdma_netdev func pointers */ rn = &ipriv->rn; rn->hca = ibdev; rn->send = mlx5i_xmit; rn->attach_mcast = mlx5i_attach_mcast; rn->detach_mcast = mlx5i_detach_mcast; rn->set_id = mlx5i_set_pkey_index; return netdev; destroy_ht: mlx5i_pkey_qpn_ht_cleanup(netdev); destroy_wq: destroy_workqueue(epriv->wq); err_free_netdev: free_netdev(netdev); return NULL; }