Skip to content

Commit cacde27

Browse files
Yunsheng Lindavem330
authored andcommitted
net: hns3: Add hclge_dcb module for the support of DCB feature
The hclge_dcb module calls the interface from hclge_main/tm and provide interface for the dcb netlink interface. This patch also update Makefiles required to build the DCB supported code in HNS3 Ethernet driver and update the existing Kconfig file in the hisilicon folder. Signed-off-by: Yunsheng Lin <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 77f255c commit cacde27

File tree

7 files changed

+375
-6
lines changed

7 files changed

+375
-6
lines changed

drivers/net/ethernet/hisilicon/Kconfig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,4 +103,13 @@ config HNS3_ENET
103103
family of SoCs. This module depends upon HNAE3 driver to access the HNAE3
104104
devices and their associated operations.
105105

106+
config HNS3_DCB
107+
bool "Hisilicon HNS3 Data Center Bridge Support"
108+
default n
109+
depends on HNS3 && HNS3_HCLGE && DCB
110+
---help---
111+
Say Y here if you want to use Data Center Bridging (DCB) in the HNS3 driver.
112+
113+
If unsure, say N.
114+
106115
endif # NET_VENDOR_HISILICON

drivers/net/ethernet/hisilicon/hns3/hnae3.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
*/
2929

3030
#include <linux/acpi.h>
31+
#include <linux/dcbnl.h>
3132
#include <linux/delay.h>
3233
#include <linux/device.h>
3334
#include <linux/module.h>
@@ -131,6 +132,7 @@ struct hnae3_client_ops {
131132
int (*init_instance)(struct hnae3_handle *handle);
132133
void (*uninit_instance)(struct hnae3_handle *handle, bool reset);
133134
void (*link_status_change)(struct hnae3_handle *handle, bool state);
135+
int (*setup_tc)(struct hnae3_handle *handle, u8 tc);
134136
};
135137

136138
#define HNAE3_CLIENT_NAME_LENGTH 16
@@ -363,6 +365,20 @@ struct hnae3_ae_ops {
363365
u16 vlan, u8 qos, __be16 proto);
364366
};
365367

368+
struct hnae3_dcb_ops {
369+
/* IEEE 802.1Qaz std */
370+
int (*ieee_getets)(struct hnae3_handle *, struct ieee_ets *);
371+
int (*ieee_setets)(struct hnae3_handle *, struct ieee_ets *);
372+
int (*ieee_getpfc)(struct hnae3_handle *, struct ieee_pfc *);
373+
int (*ieee_setpfc)(struct hnae3_handle *, struct ieee_pfc *);
374+
375+
/* DCBX configuration */
376+
u8 (*getdcbx)(struct hnae3_handle *);
377+
u8 (*setdcbx)(struct hnae3_handle *, u8);
378+
379+
int (*map_update)(struct hnae3_handle *);
380+
};
381+
366382
struct hnae3_ae_algo {
367383
const struct hnae3_ae_ops *ops;
368384
struct list_head node;
@@ -394,6 +410,7 @@ struct hnae3_knic_private_info {
394410

395411
u16 num_tqps; /* total number of TQPs in this handle */
396412
struct hnae3_queue **tqp; /* array base of all TQPs in this instance */
413+
const struct hnae3_dcb_ops *dcb_ops;
397414
};
398415

399416
struct hnae3_roce_private_info {

drivers/net/ethernet/hisilicon/hns3/hns3pf/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,7 @@ ccflags-y := -Idrivers/net/ethernet/hisilicon/hns3
77
obj-$(CONFIG_HNS3_HCLGE) += hclge.o
88
hclge-objs = hclge_main.o hclge_cmd.o hclge_mdio.o hclge_tm.o
99

10+
hclge-$(CONFIG_HNS3_DCB) += hclge_dcb.o
11+
1012
obj-$(CONFIG_HNS3_ENET) += hns3.o
1113
hns3-objs = hns3_enet.o hns3_ethtool.o
Lines changed: 304 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,304 @@
1+
/*
2+
* Copyright (c) 2016-2017 Hisilicon Limited.
3+
*
4+
* This program is free software; you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation; either version 2 of the License, or
7+
* (at your option) any later version.
8+
*/
9+
10+
#include "hclge_main.h"
11+
#include "hclge_tm.h"
12+
#include "hnae3.h"
13+
14+
#define BW_PERCENT 100
15+
16+
static int hclge_ieee_ets_to_tm_info(struct hclge_dev *hdev,
17+
struct ieee_ets *ets)
18+
{
19+
u8 i;
20+
21+
for (i = 0; i < HNAE3_MAX_TC; i++) {
22+
switch (ets->tc_tsa[i]) {
23+
case IEEE_8021QAZ_TSA_STRICT:
24+
hdev->tm_info.tc_info[i].tc_sch_mode =
25+
HCLGE_SCH_MODE_SP;
26+
hdev->tm_info.pg_info[0].tc_dwrr[i] = 0;
27+
break;
28+
case IEEE_8021QAZ_TSA_ETS:
29+
hdev->tm_info.tc_info[i].tc_sch_mode =
30+
HCLGE_SCH_MODE_DWRR;
31+
hdev->tm_info.pg_info[0].tc_dwrr[i] =
32+
ets->tc_tx_bw[i];
33+
break;
34+
default:
35+
/* Hardware only supports SP (strict priority)
36+
* or ETS (enhanced transmission selection)
37+
* algorithms, if we receive some other value
38+
* from dcbnl, then throw an error.
39+
*/
40+
return -EINVAL;
41+
}
42+
}
43+
44+
return hclge_tm_prio_tc_info_update(hdev, ets->prio_tc);
45+
}
46+
47+
static void hclge_tm_info_to_ieee_ets(struct hclge_dev *hdev,
48+
struct ieee_ets *ets)
49+
{
50+
u32 i;
51+
52+
memset(ets, 0, sizeof(*ets));
53+
ets->willing = 1;
54+
ets->ets_cap = hdev->tc_max;
55+
56+
for (i = 0; i < HNAE3_MAX_TC; i++) {
57+
ets->prio_tc[i] = hdev->tm_info.prio_tc[i];
58+
ets->tc_tx_bw[i] = hdev->tm_info.pg_info[0].tc_dwrr[i];
59+
60+
if (hdev->tm_info.tc_info[i].tc_sch_mode ==
61+
HCLGE_SCH_MODE_SP)
62+
ets->tc_tsa[i] = IEEE_8021QAZ_TSA_STRICT;
63+
else
64+
ets->tc_tsa[i] = IEEE_8021QAZ_TSA_ETS;
65+
}
66+
}
67+
68+
/* IEEE std */
69+
static int hclge_ieee_getets(struct hnae3_handle *h, struct ieee_ets *ets)
70+
{
71+
struct hclge_vport *vport = hclge_get_vport(h);
72+
struct hclge_dev *hdev = vport->back;
73+
74+
hclge_tm_info_to_ieee_ets(hdev, ets);
75+
76+
return 0;
77+
}
78+
79+
static int hclge_ets_validate(struct hclge_dev *hdev, struct ieee_ets *ets,
80+
u8 *tc, bool *changed)
81+
{
82+
u32 total_ets_bw = 0;
83+
u8 max_tc = 0;
84+
u8 i;
85+
86+
for (i = 0; i < HNAE3_MAX_TC; i++) {
87+
if (ets->prio_tc[i] >= hdev->tc_max ||
88+
i >= hdev->tc_max)
89+
return -EINVAL;
90+
91+
if (ets->prio_tc[i] != hdev->tm_info.prio_tc[i])
92+
*changed = true;
93+
94+
if (ets->prio_tc[i] > max_tc)
95+
max_tc = ets->prio_tc[i];
96+
97+
switch (ets->tc_tsa[i]) {
98+
case IEEE_8021QAZ_TSA_STRICT:
99+
if (hdev->tm_info.tc_info[i].tc_sch_mode !=
100+
HCLGE_SCH_MODE_SP)
101+
*changed = true;
102+
break;
103+
case IEEE_8021QAZ_TSA_ETS:
104+
if (hdev->tm_info.tc_info[i].tc_sch_mode !=
105+
HCLGE_SCH_MODE_DWRR)
106+
*changed = true;
107+
108+
total_ets_bw += ets->tc_tx_bw[i];
109+
break;
110+
default:
111+
return -EINVAL;
112+
}
113+
}
114+
115+
if (total_ets_bw != BW_PERCENT)
116+
return -EINVAL;
117+
118+
*tc = max_tc + 1;
119+
if (*tc != hdev->tm_info.num_tc)
120+
*changed = true;
121+
122+
return 0;
123+
}
124+
125+
static int hclge_map_update(struct hnae3_handle *h)
126+
{
127+
struct hclge_vport *vport = hclge_get_vport(h);
128+
struct hclge_dev *hdev = vport->back;
129+
int ret;
130+
131+
ret = hclge_tm_map_cfg(hdev);
132+
if (ret)
133+
return ret;
134+
135+
ret = hclge_tm_schd_mode_hw(hdev);
136+
if (ret)
137+
return ret;
138+
139+
ret = hclge_pause_setup_hw(hdev);
140+
if (ret)
141+
return ret;
142+
143+
ret = hclge_buffer_alloc(hdev);
144+
if (ret)
145+
return ret;
146+
147+
return hclge_rss_init_hw(hdev);
148+
}
149+
150+
static int hclge_client_setup_tc(struct hclge_dev *hdev)
151+
{
152+
struct hclge_vport *vport = hdev->vport;
153+
struct hnae3_client *client;
154+
struct hnae3_handle *handle;
155+
int ret;
156+
u32 i;
157+
158+
for (i = 0; i < hdev->num_vmdq_vport + 1; i++) {
159+
handle = &vport[i].nic;
160+
client = handle->client;
161+
162+
if (!client || !client->ops || !client->ops->setup_tc)
163+
continue;
164+
165+
ret = client->ops->setup_tc(handle, hdev->tm_info.num_tc);
166+
if (ret)
167+
return ret;
168+
}
169+
170+
return 0;
171+
}
172+
173+
static int hclge_ieee_setets(struct hnae3_handle *h, struct ieee_ets *ets)
174+
{
175+
struct hclge_vport *vport = hclge_get_vport(h);
176+
struct hclge_dev *hdev = vport->back;
177+
bool map_changed = false;
178+
u8 num_tc = 0;
179+
int ret;
180+
181+
if (!(hdev->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))
182+
return -EINVAL;
183+
184+
ret = hclge_ets_validate(hdev, ets, &num_tc, &map_changed);
185+
if (ret)
186+
return ret;
187+
188+
hclge_tm_schd_info_update(hdev, num_tc);
189+
190+
ret = hclge_ieee_ets_to_tm_info(hdev, ets);
191+
if (ret)
192+
return ret;
193+
194+
if (map_changed) {
195+
ret = hclge_client_setup_tc(hdev);
196+
if (ret)
197+
return ret;
198+
}
199+
200+
return hclge_tm_dwrr_cfg(hdev);
201+
}
202+
203+
static int hclge_ieee_getpfc(struct hnae3_handle *h, struct ieee_pfc *pfc)
204+
{
205+
struct hclge_vport *vport = hclge_get_vport(h);
206+
struct hclge_dev *hdev = vport->back;
207+
u8 i, j, pfc_map, *prio_tc;
208+
209+
memset(pfc, 0, sizeof(*pfc));
210+
pfc->pfc_cap = hdev->pfc_max;
211+
prio_tc = hdev->tm_info.prio_tc;
212+
pfc_map = hdev->tm_info.hw_pfc_map;
213+
214+
/* Pfc setting is based on TC */
215+
for (i = 0; i < hdev->tm_info.num_tc; i++) {
216+
for (j = 0; j < HNAE3_MAX_USER_PRIO; j++) {
217+
if ((prio_tc[j] == i) && (pfc_map & BIT(i)))
218+
pfc->pfc_en |= BIT(j);
219+
}
220+
}
221+
222+
return 0;
223+
}
224+
225+
static int hclge_ieee_setpfc(struct hnae3_handle *h, struct ieee_pfc *pfc)
226+
{
227+
struct hclge_vport *vport = hclge_get_vport(h);
228+
struct hclge_dev *hdev = vport->back;
229+
u8 i, j, pfc_map, *prio_tc;
230+
231+
if (!(hdev->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))
232+
return -EINVAL;
233+
234+
prio_tc = hdev->tm_info.prio_tc;
235+
pfc_map = 0;
236+
237+
for (i = 0; i < hdev->tm_info.num_tc; i++) {
238+
for (j = 0; j < HNAE3_MAX_USER_PRIO; j++) {
239+
if ((prio_tc[j] == i) && (pfc->pfc_en & BIT(j))) {
240+
pfc_map |= BIT(i);
241+
break;
242+
}
243+
}
244+
}
245+
246+
if (pfc_map == hdev->tm_info.hw_pfc_map)
247+
return 0;
248+
249+
hdev->tm_info.hw_pfc_map = pfc_map;
250+
251+
return hclge_pause_setup_hw(hdev);
252+
}
253+
254+
/* DCBX configuration */
255+
static u8 hclge_getdcbx(struct hnae3_handle *h)
256+
{
257+
struct hclge_vport *vport = hclge_get_vport(h);
258+
struct hclge_dev *hdev = vport->back;
259+
260+
return hdev->dcbx_cap;
261+
}
262+
263+
static u8 hclge_setdcbx(struct hnae3_handle *h, u8 mode)
264+
{
265+
struct hclge_vport *vport = hclge_get_vport(h);
266+
struct hclge_dev *hdev = vport->back;
267+
268+
/* No support for LLD_MANAGED modes or CEE */
269+
if ((mode & DCB_CAP_DCBX_LLD_MANAGED) ||
270+
(mode & DCB_CAP_DCBX_VER_CEE) ||
271+
!(mode & DCB_CAP_DCBX_HOST))
272+
return 1;
273+
274+
hdev->dcbx_cap = mode;
275+
276+
return 0;
277+
}
278+
279+
static const struct hnae3_dcb_ops hns3_dcb_ops = {
280+
.ieee_getets = hclge_ieee_getets,
281+
.ieee_setets = hclge_ieee_setets,
282+
.ieee_getpfc = hclge_ieee_getpfc,
283+
.ieee_setpfc = hclge_ieee_setpfc,
284+
.getdcbx = hclge_getdcbx,
285+
.setdcbx = hclge_setdcbx,
286+
.map_update = hclge_map_update,
287+
};
288+
289+
void hclge_dcb_ops_set(struct hclge_dev *hdev)
290+
{
291+
struct hclge_vport *vport = hdev->vport;
292+
struct hnae3_knic_private_info *kinfo;
293+
294+
/* Hdev does not support DCB or vport is
295+
* not a pf, then dcb_ops is not set.
296+
*/
297+
if (!hnae3_dev_dcb_supported(hdev) ||
298+
vport->vport_id != 0)
299+
return;
300+
301+
kinfo = &vport->nic.kinfo;
302+
kinfo->dcb_ops = &hns3_dcb_ops;
303+
hdev->dcbx_cap = DCB_CAP_DCBX_VER_IEEE | DCB_CAP_DCBX_HOST;
304+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*
2+
* Copyright (c) 2016~2017 Hisilicon Limited.
3+
*
4+
* This program is free software; you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation; either version 2 of the License, or
7+
* (at your option) any later version.
8+
*/
9+
10+
#ifndef __HCLGE_DCB_H__
11+
#define __HCLGE_DCB_H__
12+
13+
#include "hclge_main.h"
14+
15+
#ifdef CONFIG_HNS3_DCB
16+
void hclge_dcb_ops_set(struct hclge_dev *hdev);
17+
#else
18+
static inline void hclge_dcb_ops_set(struct hclge_dev *hdev) {}
19+
#endif
20+
21+
#endif /* __HCLGE_DCB_H__ */

0 commit comments

Comments
 (0)