linux/drivers/net/ethernet/freescale/enetc/enetc_vf.c
<<
>>
Prefs
   1// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
   2/* Copyright 2017-2019 NXP */
   3
   4#include <linux/module.h>
   5#include "enetc.h"
   6
   7#define ENETC_DRV_VER_MAJ 1
   8#define ENETC_DRV_VER_MIN 0
   9
  10#define ENETC_DRV_VER_STR __stringify(ENETC_DRV_VER_MAJ) "." \
  11                          __stringify(ENETC_DRV_VER_MIN)
  12static const char enetc_drv_ver[] = ENETC_DRV_VER_STR;
  13#define ENETC_DRV_NAME_STR "ENETC VF driver"
  14static const char enetc_drv_name[] = ENETC_DRV_NAME_STR;
  15
  16/* Messaging */
  17static void enetc_msg_vsi_write_msg(struct enetc_hw *hw,
  18                                    struct enetc_msg_swbd *msg)
  19{
  20        u32 val;
  21
  22        val = enetc_vsi_set_msize(msg->size) | lower_32_bits(msg->dma);
  23        enetc_wr(hw, ENETC_VSIMSGSNDAR1, upper_32_bits(msg->dma));
  24        enetc_wr(hw, ENETC_VSIMSGSNDAR0, val);
  25}
  26
  27static int enetc_msg_vsi_send(struct enetc_si *si, struct enetc_msg_swbd *msg)
  28{
  29        int timeout = 100;
  30        u32 vsimsgsr;
  31
  32        enetc_msg_vsi_write_msg(&si->hw, msg);
  33
  34        do {
  35                vsimsgsr = enetc_rd(&si->hw, ENETC_VSIMSGSR);
  36                if (!(vsimsgsr & ENETC_VSIMSGSR_MB))
  37                        break;
  38
  39                usleep_range(1000, 2000);
  40        } while (--timeout);
  41
  42        if (!timeout)
  43                return -ETIMEDOUT;
  44
  45        /* check for message delivery error */
  46        if (vsimsgsr & ENETC_VSIMSGSR_MS) {
  47                dev_err(&si->pdev->dev, "VSI command execute error: %d\n",
  48                        ENETC_SIMSGSR_GET_MC(vsimsgsr));
  49                return -EIO;
  50        }
  51
  52        return 0;
  53}
  54
  55static int enetc_msg_vsi_set_primary_mac_addr(struct enetc_ndev_priv *priv,
  56                                              struct sockaddr *saddr)
  57{
  58        struct enetc_msg_cmd_set_primary_mac *cmd;
  59        struct enetc_msg_swbd msg;
  60        int err;
  61
  62        msg.size = ALIGN(sizeof(struct enetc_msg_cmd_set_primary_mac), 64);
  63        msg.vaddr = dma_alloc_coherent(priv->dev, msg.size, &msg.dma,
  64                                       GFP_KERNEL);
  65        if (!msg.vaddr) {
  66                dev_err(priv->dev, "Failed to alloc Tx msg (size: %d)\n",
  67                        msg.size);
  68                return -ENOMEM;
  69        }
  70
  71        cmd = (struct enetc_msg_cmd_set_primary_mac *)msg.vaddr;
  72        cmd->header.type = ENETC_MSG_CMD_MNG_MAC;
  73        cmd->header.id = ENETC_MSG_CMD_MNG_ADD;
  74        memcpy(&cmd->mac, saddr, sizeof(struct sockaddr));
  75
  76        /* send the command and wait */
  77        err = enetc_msg_vsi_send(priv->si, &msg);
  78
  79        dma_free_coherent(priv->dev, msg.size, msg.vaddr, msg.dma);
  80
  81        return err;
  82}
  83
  84static int enetc_vf_set_mac_addr(struct net_device *ndev, void *addr)
  85{
  86        struct enetc_ndev_priv *priv = netdev_priv(ndev);
  87        struct sockaddr *saddr = addr;
  88        int err;
  89
  90        if (!is_valid_ether_addr(saddr->sa_data))
  91                return -EADDRNOTAVAIL;
  92
  93        err = enetc_msg_vsi_set_primary_mac_addr(priv, saddr);
  94        if (err)
  95                return err;
  96
  97        return 0;
  98}
  99
 100static int enetc_vf_set_features(struct net_device *ndev,
 101                                 netdev_features_t features)
 102{
 103        return enetc_set_features(ndev, features);
 104}
 105
 106/* Probing/ Init */
 107static const struct net_device_ops enetc_ndev_ops = {
 108        .ndo_open               = enetc_open,
 109        .ndo_stop               = enetc_close,
 110        .ndo_start_xmit         = enetc_xmit,
 111        .ndo_get_stats          = enetc_get_stats,
 112        .ndo_set_mac_address    = enetc_vf_set_mac_addr,
 113        .ndo_set_features       = enetc_vf_set_features,
 114};
 115
 116static void enetc_vf_netdev_setup(struct enetc_si *si, struct net_device *ndev,
 117                                  const struct net_device_ops *ndev_ops)
 118{
 119        struct enetc_ndev_priv *priv = netdev_priv(ndev);
 120
 121        SET_NETDEV_DEV(ndev, &si->pdev->dev);
 122        priv->ndev = ndev;
 123        priv->si = si;
 124        priv->dev = &si->pdev->dev;
 125        si->ndev = ndev;
 126
 127        priv->msg_enable = (NETIF_MSG_IFUP << 1) - 1;
 128        ndev->netdev_ops = ndev_ops;
 129        enetc_set_ethtool_ops(ndev);
 130        ndev->watchdog_timeo = 5 * HZ;
 131        ndev->max_mtu = ENETC_MAX_MTU;
 132
 133        ndev->hw_features = NETIF_F_SG | NETIF_F_RXCSUM | NETIF_F_HW_CSUM |
 134                            NETIF_F_HW_VLAN_CTAG_TX |
 135                            NETIF_F_HW_VLAN_CTAG_RX;
 136        ndev->features = NETIF_F_HIGHDMA | NETIF_F_SG |
 137                         NETIF_F_RXCSUM | NETIF_F_HW_CSUM |
 138                         NETIF_F_HW_VLAN_CTAG_TX |
 139                         NETIF_F_HW_VLAN_CTAG_RX;
 140
 141        if (si->num_rss)
 142                ndev->hw_features |= NETIF_F_RXHASH;
 143
 144        if (si->errata & ENETC_ERR_TXCSUM) {
 145                ndev->hw_features &= ~NETIF_F_HW_CSUM;
 146                ndev->features &= ~NETIF_F_HW_CSUM;
 147        }
 148
 149        /* pick up primary MAC address from SI */
 150        enetc_get_primary_mac_addr(&si->hw, ndev->dev_addr);
 151}
 152
 153static int enetc_vf_probe(struct pci_dev *pdev,
 154                          const struct pci_device_id *ent)
 155{
 156        struct enetc_ndev_priv *priv;
 157        struct net_device *ndev;
 158        struct enetc_si *si;
 159        int err;
 160
 161        err = enetc_pci_probe(pdev, KBUILD_MODNAME, 0);
 162        if (err) {
 163                dev_err(&pdev->dev, "PCI probing failed\n");
 164                return err;
 165        }
 166
 167        si = pci_get_drvdata(pdev);
 168
 169        enetc_get_si_caps(si);
 170
 171        ndev = alloc_etherdev_mq(sizeof(*priv), ENETC_MAX_NUM_TXQS);
 172        if (!ndev) {
 173                err = -ENOMEM;
 174                dev_err(&pdev->dev, "netdev creation failed\n");
 175                goto err_alloc_netdev;
 176        }
 177
 178        enetc_vf_netdev_setup(si, ndev, &enetc_ndev_ops);
 179
 180        priv = netdev_priv(ndev);
 181
 182        enetc_init_si_rings_params(priv);
 183
 184        err = enetc_alloc_si_resources(priv);
 185        if (err) {
 186                dev_err(&pdev->dev, "SI resource alloc failed\n");
 187                goto err_alloc_si_res;
 188        }
 189
 190        err = enetc_alloc_msix(priv);
 191        if (err) {
 192                dev_err(&pdev->dev, "MSIX alloc failed\n");
 193                goto err_alloc_msix;
 194        }
 195
 196        err = register_netdev(ndev);
 197        if (err)
 198                goto err_reg_netdev;
 199
 200        netif_carrier_off(ndev);
 201
 202        netif_info(priv, probe, ndev, "%s v%s\n",
 203                   enetc_drv_name, enetc_drv_ver);
 204
 205        return 0;
 206
 207err_reg_netdev:
 208        enetc_free_msix(priv);
 209err_alloc_msix:
 210        enetc_free_si_resources(priv);
 211err_alloc_si_res:
 212        si->ndev = NULL;
 213        free_netdev(ndev);
 214err_alloc_netdev:
 215        enetc_pci_remove(pdev);
 216
 217        return err;
 218}
 219
 220static void enetc_vf_remove(struct pci_dev *pdev)
 221{
 222        struct enetc_si *si = pci_get_drvdata(pdev);
 223        struct enetc_ndev_priv *priv;
 224
 225        priv = netdev_priv(si->ndev);
 226        netif_info(priv, drv, si->ndev, "%s v%s remove\n",
 227                   enetc_drv_name, enetc_drv_ver);
 228        unregister_netdev(si->ndev);
 229
 230        enetc_free_msix(priv);
 231
 232        enetc_free_si_resources(priv);
 233
 234        free_netdev(si->ndev);
 235
 236        enetc_pci_remove(pdev);
 237}
 238
 239static const struct pci_device_id enetc_vf_id_table[] = {
 240        { PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, ENETC_DEV_ID_VF) },
 241        { 0, } /* End of table. */
 242};
 243MODULE_DEVICE_TABLE(pci, enetc_vf_id_table);
 244
 245static struct pci_driver enetc_vf_driver = {
 246        .name = KBUILD_MODNAME,
 247        .id_table = enetc_vf_id_table,
 248        .probe = enetc_vf_probe,
 249        .remove = enetc_vf_remove,
 250};
 251module_pci_driver(enetc_vf_driver);
 252
 253MODULE_DESCRIPTION(ENETC_DRV_NAME_STR);
 254MODULE_LICENSE("Dual BSD/GPL");
 255MODULE_VERSION(ENETC_DRV_VER_STR);
 256