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 103 if (aq_cfg->hw_features & NETIF_F_LRO) { 104 is_lro = features & NETIF_F_LRO; 105 106 if (aq_cfg->is_lro != is_lro) { 107 aq_cfg->is_lro = is_lro; 108 109 if (netif_running(ndev)) { 110 aq_ndev_close(ndev); 111 aq_ndev_open(ndev); 112 } 113 } 114 } 115 116 return 0; 117 } 118 119 static int aq_ndev_set_mac_address(struct net_device *ndev, void *addr) 120 { 121 struct aq_nic_s *aq_nic = netdev_priv(ndev); 122 int err = 0; 123 124 err = eth_mac_addr(ndev, addr); 125 if (err < 0) 126 goto err_exit; 127 err = aq_nic_set_mac(aq_nic, ndev); 128 if (err < 0) 129 goto err_exit; 130 131 err_exit: 132 return err; 133 } 134 135 static void aq_ndev_set_multicast_settings(struct net_device *ndev) 136 { 137 struct aq_nic_s *aq_nic = netdev_priv(ndev); 138 139 aq_nic_set_packet_filter(aq_nic, ndev->flags); 140 141 aq_nic_set_multicast_list(aq_nic, ndev); 142 } 143 144 static const struct net_device_ops aq_ndev_ops = { 145 .ndo_open = aq_ndev_open, 146 .ndo_stop = aq_ndev_close, 147 .ndo_start_xmit = aq_ndev_start_xmit, 148 .ndo_set_rx_mode = aq_ndev_set_multicast_settings, 149 .ndo_change_mtu = aq_ndev_change_mtu, 150 .ndo_set_mac_address = aq_ndev_set_mac_address, 151 .ndo_set_features = aq_ndev_set_features 152 }; 153