1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright(c) 2013 - 2018 Intel Corporation. */
9 * i40e_get_pfc_delay - retrieve PFC Link Delay
10 * @hw: pointer to hardware struct
11 * @delay: holds the PFC Link delay value
13 * Returns PFC Link Delay from the PRTDCB_GENC.PFCLDA
15 static void i40e_get_pfc_delay(struct i40e_hw
*hw
, u16
*delay
)
19 val
= rd32(hw
, I40E_PRTDCB_GENC
);
20 *delay
= (u16
)((val
& I40E_PRTDCB_GENC_PFCLDA_MASK
) >>
21 I40E_PRTDCB_GENC_PFCLDA_SHIFT
);
25 * i40e_dcbnl_ieee_getets - retrieve local IEEE ETS configuration
26 * @dev: the corresponding netdev
27 * @ets: structure to hold the ETS information
29 * Returns local IEEE ETS configuration
31 static int i40e_dcbnl_ieee_getets(struct net_device
*dev
,
34 struct i40e_pf
*pf
= i40e_netdev_to_pf(dev
);
35 struct i40e_dcbx_config
*dcbxcfg
;
36 struct i40e_hw
*hw
= &pf
->hw
;
38 if (!(pf
->dcbx_cap
& DCB_CAP_DCBX_VER_IEEE
))
41 dcbxcfg
= &hw
->local_dcbx_config
;
42 ets
->willing
= dcbxcfg
->etscfg
.willing
;
43 ets
->ets_cap
= dcbxcfg
->etscfg
.maxtcs
;
44 ets
->cbs
= dcbxcfg
->etscfg
.cbs
;
45 memcpy(ets
->tc_tx_bw
, dcbxcfg
->etscfg
.tcbwtable
,
46 sizeof(ets
->tc_tx_bw
));
47 memcpy(ets
->tc_rx_bw
, dcbxcfg
->etscfg
.tcbwtable
,
48 sizeof(ets
->tc_rx_bw
));
49 memcpy(ets
->tc_tsa
, dcbxcfg
->etscfg
.tsatable
,
51 memcpy(ets
->prio_tc
, dcbxcfg
->etscfg
.prioritytable
,
52 sizeof(ets
->prio_tc
));
53 memcpy(ets
->tc_reco_bw
, dcbxcfg
->etsrec
.tcbwtable
,
54 sizeof(ets
->tc_reco_bw
));
55 memcpy(ets
->tc_reco_tsa
, dcbxcfg
->etsrec
.tsatable
,
56 sizeof(ets
->tc_reco_tsa
));
57 memcpy(ets
->reco_prio_tc
, dcbxcfg
->etscfg
.prioritytable
,
58 sizeof(ets
->reco_prio_tc
));
64 * i40e_dcbnl_ieee_getpfc - retrieve local IEEE PFC configuration
65 * @dev: the corresponding netdev
66 * @pfc: structure to hold the PFC information
68 * Returns local IEEE PFC configuration
70 static int i40e_dcbnl_ieee_getpfc(struct net_device
*dev
,
73 struct i40e_pf
*pf
= i40e_netdev_to_pf(dev
);
74 struct i40e_dcbx_config
*dcbxcfg
;
75 struct i40e_hw
*hw
= &pf
->hw
;
78 if (!(pf
->dcbx_cap
& DCB_CAP_DCBX_VER_IEEE
))
81 dcbxcfg
= &hw
->local_dcbx_config
;
82 pfc
->pfc_cap
= dcbxcfg
->pfc
.pfccap
;
83 pfc
->pfc_en
= dcbxcfg
->pfc
.pfcenable
;
84 pfc
->mbc
= dcbxcfg
->pfc
.mbc
;
85 i40e_get_pfc_delay(hw
, &pfc
->delay
);
87 /* Get Requests/Indicatiosn */
88 for (i
= 0; i
< I40E_MAX_TRAFFIC_CLASS
; i
++) {
89 pfc
->requests
[i
] = pf
->stats
.priority_xoff_tx
[i
];
90 pfc
->indications
[i
] = pf
->stats
.priority_xoff_rx
[i
];
97 * i40e_dcbnl_getdcbx - retrieve current DCBx capability
98 * @dev: the corresponding netdev
100 * Returns DCBx capability features
102 static u8
i40e_dcbnl_getdcbx(struct net_device
*dev
)
104 struct i40e_pf
*pf
= i40e_netdev_to_pf(dev
);
110 * i40e_dcbnl_get_perm_hw_addr - MAC address used by DCBx
111 * @dev: the corresponding netdev
112 * @perm_addr: buffer to store the MAC address
114 * Returns the SAN MAC address used for LLDP exchange
116 static void i40e_dcbnl_get_perm_hw_addr(struct net_device
*dev
,
119 struct i40e_pf
*pf
= i40e_netdev_to_pf(dev
);
122 memset(perm_addr
, 0xff, MAX_ADDR_LEN
);
124 for (i
= 0; i
< dev
->addr_len
; i
++)
125 perm_addr
[i
] = pf
->hw
.mac
.perm_addr
[i
];
127 for (j
= 0; j
< dev
->addr_len
; j
++, i
++)
128 perm_addr
[i
] = pf
->hw
.mac
.san_addr
[j
];
131 static const struct dcbnl_rtnl_ops dcbnl_ops
= {
132 .ieee_getets
= i40e_dcbnl_ieee_getets
,
133 .ieee_getpfc
= i40e_dcbnl_ieee_getpfc
,
134 .getdcbx
= i40e_dcbnl_getdcbx
,
135 .getpermhwaddr
= i40e_dcbnl_get_perm_hw_addr
,
139 * i40e_dcbnl_set_all - set all the apps and ieee data from DCBx config
140 * @vsi: the corresponding vsi
142 * Set up all the IEEE APPs in the DCBNL App Table and generate event for
145 void i40e_dcbnl_set_all(struct i40e_vsi
*vsi
)
147 struct net_device
*dev
= vsi
->netdev
;
148 struct i40e_pf
*pf
= i40e_netdev_to_pf(dev
);
149 struct i40e_dcbx_config
*dcbxcfg
;
150 struct i40e_hw
*hw
= &pf
->hw
;
155 /* DCB not enabled */
156 if (!(pf
->flags
& I40E_FLAG_DCB_ENABLED
))
159 /* MFP mode but not an iSCSI PF so return */
160 if ((pf
->flags
& I40E_FLAG_MFP_ENABLED
) && !(pf
->hw
.func_caps
.iscsi
))
163 dcbxcfg
= &hw
->local_dcbx_config
;
165 /* Set up all the App TLVs if DCBx is negotiated */
166 for (i
= 0; i
< dcbxcfg
->numapps
; i
++) {
167 prio
= dcbxcfg
->app
[i
].priority
;
168 tc_map
= BIT(dcbxcfg
->etscfg
.prioritytable
[prio
]);
170 /* Add APP only if the TC is enabled for this VSI */
171 if (tc_map
& vsi
->tc_config
.enabled_tc
) {
172 sapp
.selector
= dcbxcfg
->app
[i
].selector
;
173 sapp
.protocol
= dcbxcfg
->app
[i
].protocolid
;
174 sapp
.priority
= prio
;
175 dcb_ieee_setapp(dev
, &sapp
);
179 /* Notify user-space of the changes */
180 dcbnl_ieee_notify(dev
, RTM_SETDCB
, DCB_CMD_IEEE_SET
, 0, 0);
184 * i40e_dcbnl_vsi_del_app - Delete APP for given VSI
185 * @vsi: the corresponding vsi
186 * @app: APP to delete
188 * Delete given APP from the DCBNL APP table for given
191 static int i40e_dcbnl_vsi_del_app(struct i40e_vsi
*vsi
,
192 struct i40e_dcb_app_priority_table
*app
)
194 struct net_device
*dev
= vsi
->netdev
;
200 sapp
.selector
= app
->selector
;
201 sapp
.protocol
= app
->protocolid
;
202 sapp
.priority
= app
->priority
;
203 return dcb_ieee_delapp(dev
, &sapp
);
207 * i40e_dcbnl_del_app - Delete APP on all VSIs
208 * @pf: the corresponding PF
209 * @app: APP to delete
211 * Delete given APP from all the VSIs for given PF
213 static void i40e_dcbnl_del_app(struct i40e_pf
*pf
,
214 struct i40e_dcb_app_priority_table
*app
)
218 for (v
= 0; v
< pf
->num_alloc_vsi
; v
++) {
219 if (pf
->vsi
[v
] && pf
->vsi
[v
]->netdev
) {
220 err
= i40e_dcbnl_vsi_del_app(pf
->vsi
[v
], app
);
221 dev_dbg(&pf
->pdev
->dev
, "Deleting app for VSI seid=%d err=%d sel=%d proto=0x%x prio=%d\n",
222 pf
->vsi
[v
]->seid
, err
, app
->selector
,
223 app
->protocolid
, app
->priority
);
229 * i40e_dcbnl_find_app - Search APP in given DCB config
230 * @cfg: DCBX configuration data
231 * @app: APP to search for
233 * Find given APP in the DCB configuration
235 static bool i40e_dcbnl_find_app(struct i40e_dcbx_config
*cfg
,
236 struct i40e_dcb_app_priority_table
*app
)
240 for (i
= 0; i
< cfg
->numapps
; i
++) {
241 if (app
->selector
== cfg
->app
[i
].selector
&&
242 app
->protocolid
== cfg
->app
[i
].protocolid
&&
243 app
->priority
== cfg
->app
[i
].priority
)
251 * i40e_dcbnl_flush_apps - Delete all removed APPs
252 * @pf: the corresponding PF
253 * @old_cfg: old DCBX configuration data
254 * @new_cfg: new DCBX configuration data
256 * Find and delete all APPs that are not present in the passed
259 void i40e_dcbnl_flush_apps(struct i40e_pf
*pf
,
260 struct i40e_dcbx_config
*old_cfg
,
261 struct i40e_dcbx_config
*new_cfg
)
263 struct i40e_dcb_app_priority_table app
;
266 /* MFP mode but not an iSCSI PF so return */
267 if ((pf
->flags
& I40E_FLAG_MFP_ENABLED
) && !(pf
->hw
.func_caps
.iscsi
))
270 for (i
= 0; i
< old_cfg
->numapps
; i
++) {
271 app
= old_cfg
->app
[i
];
272 /* The APP is not available anymore delete it */
273 if (!i40e_dcbnl_find_app(new_cfg
, &app
))
274 i40e_dcbnl_del_app(pf
, &app
);
279 * i40e_dcbnl_setup - DCBNL setup
280 * @vsi: the corresponding vsi
282 * Set up DCBNL ops and initial APP TLVs
284 void i40e_dcbnl_setup(struct i40e_vsi
*vsi
)
286 struct net_device
*dev
= vsi
->netdev
;
287 struct i40e_pf
*pf
= i40e_netdev_to_pf(dev
);
289 /* Not DCB capable */
290 if (!(pf
->flags
& I40E_FLAG_DCB_CAPABLE
))
293 dev
->dcbnl_ops
= &dcbnl_ops
;
295 /* Set initial IEEE DCB settings */
296 i40e_dcbnl_set_all(vsi
);
298 #endif /* CONFIG_I40E_DCB */