1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16#include <linux/types.h>
17#include <linux/netdevice.h>
18#include <linux/etherdevice.h>
19#include <linux/if_vlan.h>
20#include <linux/pci.h>
21#include <linux/device.h>
22#include <linux/errno.h>
23
24#include "hinic_hw_if.h"
25#include "hinic_hw_dev.h"
26#include "hinic_port.h"
27#include "hinic_dev.h"
28
29#define HINIC_MIN_MTU_SIZE 256
30#define HINIC_MAX_JUMBO_FRAME_SIZE 15872
31
32enum mac_op {
33 MAC_DEL,
34 MAC_SET,
35};
36
37
38
39
40
41
42
43
44
45
46static int change_mac(struct hinic_dev *nic_dev, const u8 *addr,
47 u16 vlan_id, enum mac_op op)
48{
49 struct net_device *netdev = nic_dev->netdev;
50 struct hinic_hwdev *hwdev = nic_dev->hwdev;
51 struct hinic_port_mac_cmd port_mac_cmd;
52 struct hinic_hwif *hwif = hwdev->hwif;
53 struct pci_dev *pdev = hwif->pdev;
54 enum hinic_port_cmd cmd;
55 u16 out_size;
56 int err;
57
58 if (vlan_id >= VLAN_N_VID) {
59 netif_err(nic_dev, drv, netdev, "Invalid VLAN number\n");
60 return -EINVAL;
61 }
62
63 if (op == MAC_SET)
64 cmd = HINIC_PORT_CMD_SET_MAC;
65 else
66 cmd = HINIC_PORT_CMD_DEL_MAC;
67
68 port_mac_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
69 port_mac_cmd.vlan_id = vlan_id;
70 memcpy(port_mac_cmd.mac, addr, ETH_ALEN);
71
72 err = hinic_port_msg_cmd(hwdev, cmd, &port_mac_cmd,
73 sizeof(port_mac_cmd),
74 &port_mac_cmd, &out_size);
75 if (err || (out_size != sizeof(port_mac_cmd)) || port_mac_cmd.status) {
76 dev_err(&pdev->dev, "Failed to change MAC, ret = %d\n",
77 port_mac_cmd.status);
78 return -EFAULT;
79 }
80
81 return 0;
82}
83
84
85
86
87
88
89
90
91
92int hinic_port_add_mac(struct hinic_dev *nic_dev,
93 const u8 *addr, u16 vlan_id)
94{
95 return change_mac(nic_dev, addr, vlan_id, MAC_SET);
96}
97
98
99
100
101
102
103
104
105
106int hinic_port_del_mac(struct hinic_dev *nic_dev, const u8 *addr,
107 u16 vlan_id)
108{
109 return change_mac(nic_dev, addr, vlan_id, MAC_DEL);
110}
111
112
113
114
115
116
117
118
119int hinic_port_get_mac(struct hinic_dev *nic_dev, u8 *addr)
120{
121 struct hinic_hwdev *hwdev = nic_dev->hwdev;
122 struct hinic_port_mac_cmd port_mac_cmd;
123 struct hinic_hwif *hwif = hwdev->hwif;
124 struct pci_dev *pdev = hwif->pdev;
125 u16 out_size;
126 int err;
127
128 port_mac_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
129
130 err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_MAC,
131 &port_mac_cmd, sizeof(port_mac_cmd),
132 &port_mac_cmd, &out_size);
133 if (err || (out_size != sizeof(port_mac_cmd)) || port_mac_cmd.status) {
134 dev_err(&pdev->dev, "Failed to get mac, ret = %d\n",
135 port_mac_cmd.status);
136 return -EFAULT;
137 }
138
139 memcpy(addr, port_mac_cmd.mac, ETH_ALEN);
140 return 0;
141}
142
143
144
145
146
147
148
149
150int hinic_port_set_mtu(struct hinic_dev *nic_dev, int new_mtu)
151{
152 struct net_device *netdev = nic_dev->netdev;
153 struct hinic_hwdev *hwdev = nic_dev->hwdev;
154 struct hinic_port_mtu_cmd port_mtu_cmd;
155 struct hinic_hwif *hwif = hwdev->hwif;
156 struct pci_dev *pdev = hwif->pdev;
157 int err, max_frame;
158 u16 out_size;
159
160 if (new_mtu < HINIC_MIN_MTU_SIZE) {
161 netif_err(nic_dev, drv, netdev, "mtu < MIN MTU size");
162 return -EINVAL;
163 }
164
165 max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
166 if (max_frame > HINIC_MAX_JUMBO_FRAME_SIZE) {
167 netif_err(nic_dev, drv, netdev, "mtu > MAX MTU size");
168 return -EINVAL;
169 }
170
171 port_mtu_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
172 port_mtu_cmd.mtu = new_mtu;
173
174 err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_CHANGE_MTU,
175 &port_mtu_cmd, sizeof(port_mtu_cmd),
176 &port_mtu_cmd, &out_size);
177 if (err || (out_size != sizeof(port_mtu_cmd)) || port_mtu_cmd.status) {
178 dev_err(&pdev->dev, "Failed to set mtu, ret = %d\n",
179 port_mtu_cmd.status);
180 return -EFAULT;
181 }
182
183 return 0;
184}
185
186
187
188
189
190
191
192
193int hinic_port_add_vlan(struct hinic_dev *nic_dev, u16 vlan_id)
194{
195 struct hinic_hwdev *hwdev = nic_dev->hwdev;
196 struct hinic_port_vlan_cmd port_vlan_cmd;
197
198 port_vlan_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwdev->hwif);
199 port_vlan_cmd.vlan_id = vlan_id;
200
201 return hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_ADD_VLAN,
202 &port_vlan_cmd, sizeof(port_vlan_cmd),
203 NULL, NULL);
204}
205
206
207
208
209
210
211
212
213int hinic_port_del_vlan(struct hinic_dev *nic_dev, u16 vlan_id)
214{
215 struct hinic_hwdev *hwdev = nic_dev->hwdev;
216 struct hinic_port_vlan_cmd port_vlan_cmd;
217
218 port_vlan_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwdev->hwif);
219 port_vlan_cmd.vlan_id = vlan_id;
220
221 return hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_DEL_VLAN,
222 &port_vlan_cmd, sizeof(port_vlan_cmd),
223 NULL, NULL);
224}
225
226
227
228
229
230
231
232
233int hinic_port_set_rx_mode(struct hinic_dev *nic_dev, u32 rx_mode)
234{
235 struct hinic_hwdev *hwdev = nic_dev->hwdev;
236 struct hinic_port_rx_mode_cmd rx_mode_cmd;
237
238 rx_mode_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwdev->hwif);
239 rx_mode_cmd.rx_mode = rx_mode;
240
241 return hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_RX_MODE,
242 &rx_mode_cmd, sizeof(rx_mode_cmd),
243 NULL, NULL);
244}
245
246
247
248
249
250
251
252
253int hinic_port_link_state(struct hinic_dev *nic_dev,
254 enum hinic_port_link_state *link_state)
255{
256 struct hinic_hwdev *hwdev = nic_dev->hwdev;
257 struct hinic_hwif *hwif = hwdev->hwif;
258 struct hinic_port_link_cmd link_cmd;
259 struct pci_dev *pdev = hwif->pdev;
260 u16 out_size;
261 int err;
262
263 if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) {
264 dev_err(&pdev->dev, "unsupported PCI Function type\n");
265 return -EINVAL;
266 }
267
268 link_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
269
270 err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_LINK_STATE,
271 &link_cmd, sizeof(link_cmd),
272 &link_cmd, &out_size);
273 if (err || (out_size != sizeof(link_cmd)) || link_cmd.status) {
274 dev_err(&pdev->dev, "Failed to get link state, ret = %d\n",
275 link_cmd.status);
276 return -EINVAL;
277 }
278
279 *link_state = link_cmd.state;
280 return 0;
281}
282
283
284
285
286
287
288
289
290int hinic_port_set_state(struct hinic_dev *nic_dev, enum hinic_port_state state)
291{
292 struct hinic_hwdev *hwdev = nic_dev->hwdev;
293 struct hinic_port_state_cmd port_state;
294 struct hinic_hwif *hwif = hwdev->hwif;
295 struct pci_dev *pdev = hwif->pdev;
296 u16 out_size;
297 int err;
298
299 if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) {
300 dev_err(&pdev->dev, "unsupported PCI Function type\n");
301 return -EINVAL;
302 }
303
304 port_state.state = state;
305
306 err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_PORT_STATE,
307 &port_state, sizeof(port_state),
308 &port_state, &out_size);
309 if (err || (out_size != sizeof(port_state)) || port_state.status) {
310 dev_err(&pdev->dev, "Failed to set port state, ret = %d\n",
311 port_state.status);
312 return -EFAULT;
313 }
314
315 return 0;
316}
317
318
319
320
321
322
323
324
325int hinic_port_set_func_state(struct hinic_dev *nic_dev,
326 enum hinic_func_port_state state)
327{
328 struct hinic_port_func_state_cmd func_state;
329 struct hinic_hwdev *hwdev = nic_dev->hwdev;
330 struct hinic_hwif *hwif = hwdev->hwif;
331 struct pci_dev *pdev = hwif->pdev;
332 u16 out_size;
333 int err;
334
335 func_state.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
336 func_state.state = state;
337
338 err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_FUNC_STATE,
339 &func_state, sizeof(func_state),
340 &func_state, &out_size);
341 if (err || (out_size != sizeof(func_state)) || func_state.status) {
342 dev_err(&pdev->dev, "Failed to set port func state, ret = %d\n",
343 func_state.status);
344 return -EFAULT;
345 }
346
347 return 0;
348}
349
350
351
352
353
354
355
356
357int hinic_port_get_cap(struct hinic_dev *nic_dev,
358 struct hinic_port_cap *port_cap)
359{
360 struct hinic_hwdev *hwdev = nic_dev->hwdev;
361 struct hinic_hwif *hwif = hwdev->hwif;
362 struct pci_dev *pdev = hwif->pdev;
363 u16 out_size;
364 int err;
365
366 port_cap->func_idx = HINIC_HWIF_FUNC_IDX(hwif);
367
368 err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_CAP,
369 port_cap, sizeof(*port_cap),
370 port_cap, &out_size);
371 if (err || (out_size != sizeof(*port_cap)) || port_cap->status) {
372 dev_err(&pdev->dev,
373 "Failed to get port capabilities, ret = %d\n",
374 port_cap->status);
375 return -EINVAL;
376 }
377
378 return 0;
379}
380