linux/drivers/net/ethernet/aquantia/atlantic/aq_main.c
<<
>>
Prefs
   1/*
   2 * aQuantia Corporation Network Driver
   3 * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved
   4 *
   5 * This program is free software; you can redistribute it and/or modify it
   6 * under the terms and conditions of the GNU General Public License,
   7 * version 2, as published by the Free Software Foundation.
   8 */
   9
  10/* File aq_main.c: Main file for aQuantia Linux driver. */
  11
  12#include "aq_main.h"
  13#include "aq_nic.h"
  14#include "aq_pci_func.h"
  15#include "aq_ethtool.h"
  16#include "hw_atl/hw_atl_a0.h"
  17#include "hw_atl/hw_atl_b0.h"
  18
  19#include <linux/netdevice.h>
  20#include <linux/module.h>
  21
  22static const struct pci_device_id aq_pci_tbl[] = {
  23        { PCI_VDEVICE(AQUANTIA, HW_ATL_DEVICE_ID_0001), },
  24        { PCI_VDEVICE(AQUANTIA, HW_ATL_DEVICE_ID_D100), },
  25        { PCI_VDEVICE(AQUANTIA, HW_ATL_DEVICE_ID_D107), },
  26        { PCI_VDEVICE(AQUANTIA, HW_ATL_DEVICE_ID_D108), },
  27        { PCI_VDEVICE(AQUANTIA, HW_ATL_DEVICE_ID_D109), },
  28        {}
  29};
  30
  31MODULE_DEVICE_TABLE(pci, aq_pci_tbl);
  32
  33MODULE_LICENSE("GPL v2");
  34MODULE_VERSION(AQ_CFG_DRV_VERSION);
  35MODULE_AUTHOR(AQ_CFG_DRV_AUTHOR);
  36MODULE_DESCRIPTION(AQ_CFG_DRV_DESC);
  37
  38static struct aq_hw_ops *aq_pci_probe_get_hw_ops_by_id(struct pci_dev *pdev)
  39{
  40        struct aq_hw_ops *ops = NULL;
  41
  42        ops = hw_atl_a0_get_ops_by_id(pdev);
  43        if (!ops)
  44                ops = hw_atl_b0_get_ops_by_id(pdev);
  45
  46        return ops;
  47}
  48
  49static int aq_ndev_open(struct net_device *ndev)
  50{
  51        struct aq_nic_s *aq_nic = NULL;
  52        int err = 0;
  53
  54        aq_nic = aq_nic_alloc_hot(ndev);
  55        if (!aq_nic) {
  56                err = -ENOMEM;
  57                goto err_exit;
  58        }
  59        err = aq_nic_init(aq_nic);
  60        if (err < 0)
  61                goto err_exit;
  62        err = aq_nic_start(aq_nic);
  63        if (err < 0)
  64                goto err_exit;
  65
  66err_exit:
  67        if (err < 0)
  68                aq_nic_deinit(aq_nic);
  69        return err;
  70}
  71
  72static int aq_ndev_close(struct net_device *ndev)
  73{
  74        int err = 0;
  75        struct aq_nic_s *aq_nic = netdev_priv(ndev);
  76
  77        err = aq_nic_stop(aq_nic);
  78        if (err < 0)
  79                goto err_exit;
  80        aq_nic_deinit(aq_nic);
  81        aq_nic_free_hot_resources(aq_nic);
  82
  83err_exit:
  84        return err;
  85}
  86
  87static int aq_ndev_start_xmit(struct sk_buff *skb, struct net_device *ndev)
  88{
  89        struct aq_nic_s *aq_nic = netdev_priv(ndev);
  90
  91        return aq_nic_xmit(aq_nic, skb);
  92}
  93
  94static int aq_ndev_change_mtu(struct net_device *ndev, int new_mtu)
  95{
  96        struct aq_nic_s *aq_nic = netdev_priv(ndev);
  97        int err = aq_nic_set_mtu(aq_nic, new_mtu + ETH_HLEN);
  98
  99        if (err < 0)
 100                goto err_exit;
 101        ndev->mtu = new_mtu;
 102
 103err_exit:
 104        return err;
 105}
 106
 107static int aq_ndev_set_features(struct net_device *ndev,
 108                                netdev_features_t features)
 109{
 110        struct aq_nic_s *aq_nic = netdev_priv(ndev);
 111        struct aq_nic_cfg_s *aq_cfg = aq_nic_get_cfg(aq_nic);
 112        bool is_lro = false;
 113
 114        if (aq_cfg->hw_features & NETIF_F_LRO) {
 115                is_lro = features & NETIF_F_LRO;
 116
 117                if (aq_cfg->is_lro != is_lro) {
 118                        aq_cfg->is_lro = is_lro;
 119
 120                        if (netif_running(ndev)) {
 121                                aq_ndev_close(ndev);
 122                                aq_ndev_open(ndev);
 123                        }
 124                }
 125        }
 126
 127        return 0;
 128}
 129
 130static int aq_ndev_set_mac_address(struct net_device *ndev, void *addr)
 131{
 132        struct aq_nic_s *aq_nic = netdev_priv(ndev);
 133        int err = 0;
 134
 135        err = eth_mac_addr(ndev, addr);
 136        if (err < 0)
 137                goto err_exit;
 138        err = aq_nic_set_mac(aq_nic, ndev);
 139        if (err < 0)
 140                goto err_exit;
 141
 142err_exit:
 143        return err;
 144}
 145
 146static void aq_ndev_set_multicast_settings(struct net_device *ndev)
 147{
 148        struct aq_nic_s *aq_nic = netdev_priv(ndev);
 149        int err = 0;
 150
 151        err = aq_nic_set_packet_filter(aq_nic, ndev->flags);
 152        if (err < 0)
 153                goto err_exit;
 154
 155        if (netdev_mc_count(ndev)) {
 156                err = aq_nic_set_multicast_list(aq_nic, ndev);
 157                if (err < 0)
 158                        goto err_exit;
 159        }
 160
 161err_exit:;
 162}
 163
 164static const struct net_device_ops aq_ndev_ops = {
 165        .ndo_open = aq_ndev_open,
 166        .ndo_stop = aq_ndev_close,
 167        .ndo_start_xmit = aq_ndev_start_xmit,
 168        .ndo_set_rx_mode = aq_ndev_set_multicast_settings,
 169        .ndo_change_mtu = aq_ndev_change_mtu,
 170        .ndo_set_mac_address = aq_ndev_set_mac_address,
 171        .ndo_set_features = aq_ndev_set_features
 172};
 173
 174static int aq_pci_probe(struct pci_dev *pdev,
 175                        const struct pci_device_id *pci_id)
 176{
 177        struct aq_hw_ops *aq_hw_ops = NULL;
 178        struct aq_pci_func_s *aq_pci_func = NULL;
 179        int err = 0;
 180
 181        err = pci_enable_device(pdev);
 182        if (err < 0)
 183                goto err_exit;
 184        aq_hw_ops = aq_pci_probe_get_hw_ops_by_id(pdev);
 185        aq_pci_func = aq_pci_func_alloc(aq_hw_ops, pdev,
 186                                        &aq_ndev_ops, &aq_ethtool_ops);
 187        if (!aq_pci_func) {
 188                err = -ENOMEM;
 189                goto err_exit;
 190        }
 191        err = aq_pci_func_init(aq_pci_func);
 192        if (err < 0)
 193                goto err_exit;
 194
 195err_exit:
 196        if (err < 0) {
 197                if (aq_pci_func)
 198                        aq_pci_func_free(aq_pci_func);
 199        }
 200        return err;
 201}
 202
 203static void aq_pci_remove(struct pci_dev *pdev)
 204{
 205        struct aq_pci_func_s *aq_pci_func = pci_get_drvdata(pdev);
 206
 207        aq_pci_func_deinit(aq_pci_func);
 208        aq_pci_func_free(aq_pci_func);
 209}
 210
 211static int aq_pci_suspend(struct pci_dev *pdev, pm_message_t pm_msg)
 212{
 213        struct aq_pci_func_s *aq_pci_func = pci_get_drvdata(pdev);
 214
 215        return aq_pci_func_change_pm_state(aq_pci_func, &pm_msg);
 216}
 217
 218static int aq_pci_resume(struct pci_dev *pdev)
 219{
 220        struct aq_pci_func_s *aq_pci_func = pci_get_drvdata(pdev);
 221        pm_message_t pm_msg = PMSG_RESTORE;
 222
 223        return aq_pci_func_change_pm_state(aq_pci_func, &pm_msg);
 224}
 225
 226static struct pci_driver aq_pci_ops = {
 227        .name = AQ_CFG_DRV_NAME,
 228        .id_table = aq_pci_tbl,
 229        .probe = aq_pci_probe,
 230        .remove = aq_pci_remove,
 231        .suspend = aq_pci_suspend,
 232        .resume = aq_pci_resume,
 233};
 234
 235module_pci_driver(aq_pci_ops);
 236