xref: /openbmc/linux/drivers/net/ethernet/aquantia/atlantic/aq_main.c (revision 05cf4fe738242183f1237f1b3a28b4479348c0a1)
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