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 17 #include <linux/netdevice.h> 18 #include <linux/module.h> 19 20 MODULE_LICENSE("GPL v2"); 21 MODULE_VERSION(AQ_CFG_DRV_VERSION); 22 MODULE_AUTHOR(AQ_CFG_DRV_AUTHOR); 23 MODULE_DESCRIPTION(AQ_CFG_DRV_DESC); 24 25 static const struct net_device_ops aq_ndev_ops; 26 27 struct net_device *aq_ndev_alloc(void) 28 { 29 struct net_device *ndev = NULL; 30 struct aq_nic_s *aq_nic = NULL; 31 32 ndev = alloc_etherdev_mq(sizeof(struct aq_nic_s), AQ_CFG_VECS_MAX); 33 if (!ndev) 34 return NULL; 35 36 aq_nic = netdev_priv(ndev); 37 aq_nic->ndev = ndev; 38 ndev->netdev_ops = &aq_ndev_ops; 39 ndev->ethtool_ops = &aq_ethtool_ops; 40 41 return ndev; 42 } 43 44 static int aq_ndev_open(struct net_device *ndev) 45 { 46 int err = 0; 47 struct aq_nic_s *aq_nic = netdev_priv(ndev); 48 49 err = aq_nic_init(aq_nic); 50 if (err < 0) 51 goto err_exit; 52 err = aq_nic_start(aq_nic); 53 if (err < 0) 54 goto err_exit; 55 56 err_exit: 57 if (err < 0) 58 aq_nic_deinit(aq_nic); 59 return err; 60 } 61 62 static int aq_ndev_close(struct net_device *ndev) 63 { 64 int err = 0; 65 struct aq_nic_s *aq_nic = netdev_priv(ndev); 66 67 err = aq_nic_stop(aq_nic); 68 if (err < 0) 69 goto err_exit; 70 aq_nic_deinit(aq_nic); 71 72 err_exit: 73 return err; 74 } 75 76 static int aq_ndev_start_xmit(struct sk_buff *skb, struct net_device *ndev) 77 { 78 struct aq_nic_s *aq_nic = netdev_priv(ndev); 79 80 return aq_nic_xmit(aq_nic, skb); 81 } 82 83 static int aq_ndev_change_mtu(struct net_device *ndev, int new_mtu) 84 { 85 struct aq_nic_s *aq_nic = netdev_priv(ndev); 86 int err = aq_nic_set_mtu(aq_nic, new_mtu + ETH_HLEN); 87 88 if (err < 0) 89 goto err_exit; 90 ndev->mtu = new_mtu; 91 92 err_exit: 93 return err; 94 } 95 96 static int aq_ndev_set_features(struct net_device *ndev, 97 netdev_features_t features) 98 { 99 struct aq_nic_s *aq_nic = netdev_priv(ndev); 100 struct aq_nic_cfg_s *aq_cfg = aq_nic_get_cfg(aq_nic); 101 bool is_lro = false; 102 int err = 0; 103 104 aq_cfg->features = features; 105 106 if (aq_cfg->aq_hw_caps->hw_features & NETIF_F_LRO) { 107 is_lro = features & NETIF_F_LRO; 108 109 if (aq_cfg->is_lro != is_lro) { 110 aq_cfg->is_lro = is_lro; 111 112 if (netif_running(ndev)) { 113 aq_ndev_close(ndev); 114 aq_ndev_open(ndev); 115 } 116 } 117 } 118 if ((aq_nic->ndev->features ^ features) & NETIF_F_RXCSUM) 119 err = aq_nic->aq_hw_ops->hw_set_offload(aq_nic->aq_hw, 120 aq_cfg); 121 122 return err; 123 } 124 125 static int aq_ndev_set_mac_address(struct net_device *ndev, void *addr) 126 { 127 struct aq_nic_s *aq_nic = netdev_priv(ndev); 128 int err = 0; 129 130 err = eth_mac_addr(ndev, addr); 131 if (err < 0) 132 goto err_exit; 133 err = aq_nic_set_mac(aq_nic, ndev); 134 if (err < 0) 135 goto err_exit; 136 137 err_exit: 138 return err; 139 } 140 141 static void aq_ndev_set_multicast_settings(struct net_device *ndev) 142 { 143 struct aq_nic_s *aq_nic = netdev_priv(ndev); 144 145 aq_nic_set_packet_filter(aq_nic, ndev->flags); 146 147 aq_nic_set_multicast_list(aq_nic, ndev); 148 } 149 150 static const struct net_device_ops aq_ndev_ops = { 151 .ndo_open = aq_ndev_open, 152 .ndo_stop = aq_ndev_close, 153 .ndo_start_xmit = aq_ndev_start_xmit, 154 .ndo_set_rx_mode = aq_ndev_set_multicast_settings, 155 .ndo_change_mtu = aq_ndev_change_mtu, 156 .ndo_set_mac_address = aq_ndev_set_mac_address, 157 .ndo_set_features = aq_ndev_set_features 158 }; 159