]> git.proxmox.com Git - mirror_ubuntu-focal-kernel.git/blame - drivers/net/ethernet/aquantia/atlantic/aq_main.c
UBUNTU: Ubuntu-5.4.0-117.132
[mirror_ubuntu-focal-kernel.git] / drivers / net / ethernet / aquantia / atlantic / aq_main.c
CommitLineData
75a6faf6 1// SPDX-License-Identifier: GPL-2.0-only
97bde5c4
DV
2/*
3 * aQuantia Corporation Network Driver
4 * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved
97bde5c4
DV
5 */
6
7/* File aq_main.c: Main file for aQuantia Linux driver. */
8
9#include "aq_main.h"
10#include "aq_nic.h"
11#include "aq_pci_func.h"
12#include "aq_ethtool.h"
8d0bcb01 13#include "aq_filters.h"
97bde5c4
DV
14
15#include <linux/netdevice.h>
16#include <linux/module.h>
17
97bde5c4
DV
18MODULE_LICENSE("GPL v2");
19MODULE_VERSION(AQ_CFG_DRV_VERSION);
20MODULE_AUTHOR(AQ_CFG_DRV_AUTHOR);
21MODULE_DESCRIPTION(AQ_CFG_DRV_DESC);
22
44bec4b3 23static const char aq_ndev_driver_name[] = AQ_CFG_DRV_NAME;
58608082 24
5b97b0d1
IR
25static const struct net_device_ops aq_ndev_ops;
26
58608082
ND
27static struct workqueue_struct *aq_ndev_wq;
28
29void aq_ndev_schedule_work(struct work_struct *work)
30{
31 queue_work(aq_ndev_wq, work);
32}
33
5b97b0d1 34struct net_device *aq_ndev_alloc(void)
97bde5c4 35{
5b97b0d1
IR
36 struct net_device *ndev = NULL;
37 struct aq_nic_s *aq_nic = NULL;
97bde5c4 38
5b97b0d1
IR
39 ndev = alloc_etherdev_mq(sizeof(struct aq_nic_s), AQ_CFG_VECS_MAX);
40 if (!ndev)
41 return NULL;
97bde5c4 42
5b97b0d1
IR
43 aq_nic = netdev_priv(ndev);
44 aq_nic->ndev = ndev;
45 ndev->netdev_ops = &aq_ndev_ops;
46 ndev->ethtool_ops = &aq_ethtool_ops;
47
48 return ndev;
97bde5c4
DV
49}
50
51static int aq_ndev_open(struct net_device *ndev)
52{
97bde5c4 53 int err = 0;
23ee07ad 54 struct aq_nic_s *aq_nic = netdev_priv(ndev);
97bde5c4 55
97bde5c4
DV
56 err = aq_nic_init(aq_nic);
57 if (err < 0)
58 goto err_exit;
8d0bcb01
DB
59
60 err = aq_reapply_rxnfc_all_rules(aq_nic);
61 if (err < 0)
62 goto err_exit;
63
c2ef057e
DB
64 err = aq_filters_vlans_update(aq_nic);
65 if (err < 0)
66 goto err_exit;
67
97bde5c4 68 err = aq_nic_start(aq_nic);
9a08b107
NR
69 if (err < 0) {
70 aq_nic_stop(aq_nic);
97bde5c4 71 goto err_exit;
9a08b107 72 }
97bde5c4
DV
73
74err_exit:
75 if (err < 0)
76 aq_nic_deinit(aq_nic);
77 return err;
78}
79
80static int aq_ndev_close(struct net_device *ndev)
81{
82 int err = 0;
83 struct aq_nic_s *aq_nic = netdev_priv(ndev);
84
85 err = aq_nic_stop(aq_nic);
86 if (err < 0)
87 goto err_exit;
88 aq_nic_deinit(aq_nic);
97bde5c4
DV
89
90err_exit:
91 return err;
92}
93
94static int aq_ndev_start_xmit(struct sk_buff *skb, struct net_device *ndev)
95{
96 struct aq_nic_s *aq_nic = netdev_priv(ndev);
97bde5c4 97
362f37b2 98 return aq_nic_xmit(aq_nic, skb);
97bde5c4
DV
99}
100
101static int aq_ndev_change_mtu(struct net_device *ndev, int new_mtu)
102{
103 struct aq_nic_s *aq_nic = netdev_priv(ndev);
5513e164 104 int err = aq_nic_set_mtu(aq_nic, new_mtu + ETH_HLEN);
97bde5c4 105
97bde5c4
DV
106 if (err < 0)
107 goto err_exit;
bc9ab923 108 ndev->mtu = new_mtu;
97bde5c4 109
97bde5c4
DV
110err_exit:
111 return err;
112}
113
114static int aq_ndev_set_features(struct net_device *ndev,
115 netdev_features_t features)
116{
04f207fb
IR
117 bool is_vlan_rx_strip = !!(features & NETIF_F_HW_VLAN_CTAG_RX);
118 bool is_vlan_tx_insert = !!(features & NETIF_F_HW_VLAN_CTAG_TX);
97bde5c4 119 struct aq_nic_s *aq_nic = netdev_priv(ndev);
04f207fb
IR
120 bool need_ndev_restart = false;
121 struct aq_nic_cfg_s *aq_cfg;
97bde5c4 122 bool is_lro = false;
bbb67a44
DB
123 int err = 0;
124
04f207fb
IR
125 aq_cfg = aq_nic_get_cfg(aq_nic);
126
8d0bcb01
DB
127 if (!(features & NETIF_F_NTUPLE)) {
128 if (aq_nic->ndev->features & NETIF_F_NTUPLE) {
129 err = aq_clear_rxnfc_all_rules(aq_nic);
130 if (unlikely(err))
131 goto err_exit;
132 }
133 }
7975d2af
DB
134 if (!(features & NETIF_F_HW_VLAN_CTAG_FILTER)) {
135 if (aq_nic->ndev->features & NETIF_F_HW_VLAN_CTAG_FILTER) {
136 err = aq_filters_vlan_offload_off(aq_nic);
137 if (unlikely(err))
138 goto err_exit;
139 }
140 }
8d0bcb01 141
bbb67a44 142 aq_cfg->features = features;
97bde5c4 143
bbb67a44 144 if (aq_cfg->aq_hw_caps->hw_features & NETIF_F_LRO) {
97bde5c4
DV
145 is_lro = features & NETIF_F_LRO;
146
147 if (aq_cfg->is_lro != is_lro) {
148 aq_cfg->is_lro = is_lro;
04f207fb 149 need_ndev_restart = true;
97bde5c4
DV
150 }
151 }
04f207fb
IR
152
153 if ((aq_nic->ndev->features ^ features) & NETIF_F_RXCSUM) {
bbb67a44
DB
154 err = aq_nic->aq_hw_ops->hw_set_offload(aq_nic->aq_hw,
155 aq_cfg);
97bde5c4 156
04f207fb
IR
157 if (unlikely(err))
158 goto err_exit;
159 }
160
161 if (aq_cfg->is_vlan_rx_strip != is_vlan_rx_strip) {
162 aq_cfg->is_vlan_rx_strip = is_vlan_rx_strip;
163 need_ndev_restart = true;
164 }
165 if (aq_cfg->is_vlan_tx_insert != is_vlan_tx_insert) {
166 aq_cfg->is_vlan_tx_insert = is_vlan_tx_insert;
167 need_ndev_restart = true;
168 }
169
170 if (need_ndev_restart && netif_running(ndev)) {
171 aq_ndev_close(ndev);
172 aq_ndev_open(ndev);
173 }
174
8d0bcb01 175err_exit:
bbb67a44 176 return err;
97bde5c4
DV
177}
178
179static int aq_ndev_set_mac_address(struct net_device *ndev, void *addr)
180{
181 struct aq_nic_s *aq_nic = netdev_priv(ndev);
182 int err = 0;
183
184 err = eth_mac_addr(ndev, addr);
185 if (err < 0)
186 goto err_exit;
187 err = aq_nic_set_mac(aq_nic, ndev);
188 if (err < 0)
189 goto err_exit;
190
191err_exit:
192 return err;
193}
194
195static void aq_ndev_set_multicast_settings(struct net_device *ndev)
196{
197 struct aq_nic_s *aq_nic = netdev_priv(ndev);
97bde5c4 198
9f051db5 199 (void)aq_nic_set_multicast_list(aq_nic, ndev);
97bde5c4
DV
200}
201
7975d2af
DB
202static int aq_ndo_vlan_rx_add_vid(struct net_device *ndev, __be16 proto,
203 u16 vid)
204{
205 struct aq_nic_s *aq_nic = netdev_priv(ndev);
206
207 if (!aq_nic->aq_hw_ops->hw_filter_vlan_set)
208 return -EOPNOTSUPP;
209
210 set_bit(vid, aq_nic->active_vlans);
211
212 return aq_filters_vlans_update(aq_nic);
213}
214
215static int aq_ndo_vlan_rx_kill_vid(struct net_device *ndev, __be16 proto,
216 u16 vid)
217{
218 struct aq_nic_s *aq_nic = netdev_priv(ndev);
219
220 if (!aq_nic->aq_hw_ops->hw_filter_vlan_set)
221 return -EOPNOTSUPP;
222
223 clear_bit(vid, aq_nic->active_vlans);
224
225 if (-ENOENT == aq_del_fvlan_by_vlan(aq_nic, vid))
226 return aq_filters_vlans_update(aq_nic);
227
228 return 0;
229}
230
97bde5c4
DV
231static const struct net_device_ops aq_ndev_ops = {
232 .ndo_open = aq_ndev_open,
233 .ndo_stop = aq_ndev_close,
234 .ndo_start_xmit = aq_ndev_start_xmit,
235 .ndo_set_rx_mode = aq_ndev_set_multicast_settings,
236 .ndo_change_mtu = aq_ndev_change_mtu,
237 .ndo_set_mac_address = aq_ndev_set_mac_address,
7975d2af
DB
238 .ndo_set_features = aq_ndev_set_features,
239 .ndo_vlan_rx_add_vid = aq_ndo_vlan_rx_add_vid,
240 .ndo_vlan_rx_kill_vid = aq_ndo_vlan_rx_kill_vid,
97bde5c4 241};
58608082
ND
242
243static int __init aq_ndev_init_module(void)
244{
245 int ret;
246
247 aq_ndev_wq = create_singlethread_workqueue(aq_ndev_driver_name);
248 if (!aq_ndev_wq) {
249 pr_err("Failed to create workqueue\n");
250 return -ENOMEM;
251 }
252
253 ret = aq_pci_func_register_driver();
254 if (ret) {
255 destroy_workqueue(aq_ndev_wq);
256 return ret;
257 }
258
259 return 0;
260}
261
262static void __exit aq_ndev_exit_module(void)
263{
264 aq_pci_func_unregister_driver();
265
266 if (aq_ndev_wq) {
267 destroy_workqueue(aq_ndev_wq);
268 aq_ndev_wq = NULL;
269 }
270}
271
272module_init(aq_ndev_init_module);
273module_exit(aq_ndev_exit_module);