Skip to content

Commit 9666448

Browse files
Greg RoseJeff Kirsher
authored andcommitted
i40e: Implement configfs for NPAR BW configuration
Add configfs controls to get, set and commit NPAR BW configurations. We export three controls: min_bw - Can take a value from 0 to 100 inclusive max_bw - Can take a value from 1 to 100 inclusive commit - A write-only control that accepts only a value of 1 and will cause the BW settings to be permanently committed to NVM so that they are persistent across power cycles and system resets The BW values are relative and are expressed as percentages. For more information on the interpretation of the BW settings see the Dell specifications for NPAR. Also update the copyright year. Change-ID: Id7496ca65630b5037e32ba6a5a748fbc1632881b Signed-off-by: Greg Rose <[email protected]> Tested-By: Jim Young <[email protected]> Signed-off-by: Jeff Kirsher <[email protected]>
1 parent f4492db commit 9666448

File tree

4 files changed

+369
-8
lines changed

4 files changed

+369
-8
lines changed

drivers/net/ethernet/intel/i40e/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
################################################################################
22
#
33
# Intel Ethernet Controller XL710 Family Linux Driver
4-
# Copyright(c) 2013 - 2014 Intel Corporation.
4+
# Copyright(c) 2013 - 2015 Intel Corporation.
55
#
66
# This program is free software; you can redistribute it and/or modify it
77
# under the terms and conditions of the GNU General Public License,
@@ -37,6 +37,7 @@ i40e-objs := i40e_main.o \
3737
i40e_hmc.o \
3838
i40e_lan_hmc.o \
3939
i40e_nvm.o \
40+
i40e_configfs.o \
4041
i40e_debugfs.o \
4142
i40e_diag.o \
4243
i40e_txrx.o \

drivers/net/ethernet/intel/i40e/i40e.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -688,6 +688,7 @@ int i40e_vlan_rx_add_vid(struct net_device *netdev,
688688
int i40e_vlan_rx_kill_vid(struct net_device *netdev,
689689
__always_unused __be16 proto, u16 vid);
690690
#endif
691+
int i40e_open(struct net_device *netdev);
691692
int i40e_vsi_open(struct i40e_vsi *vsi);
692693
void i40e_vlan_stripping_disable(struct i40e_vsi *vsi);
693694
int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid);
@@ -698,7 +699,6 @@ bool i40e_is_vsi_in_vlan(struct i40e_vsi *vsi);
698699
struct i40e_mac_filter *i40e_find_mac(struct i40e_vsi *vsi, u8 *macaddr,
699700
bool is_vf, bool is_netdev);
700701
#ifdef I40E_FCOE
701-
int i40e_open(struct net_device *netdev);
702702
int i40e_close(struct net_device *netdev);
703703
int i40e_setup_tc(struct net_device *netdev, u8 tc);
704704
void i40e_netpoll(struct net_device *netdev);
@@ -735,7 +735,10 @@ int i40e_ptp_set_ts_config(struct i40e_pf *pf, struct ifreq *ifr);
735735
int i40e_ptp_get_ts_config(struct i40e_pf *pf, struct ifreq *ifr);
736736
void i40e_ptp_init(struct i40e_pf *pf);
737737
void i40e_ptp_stop(struct i40e_pf *pf);
738-
738+
#if IS_ENABLED(CONFIG_CONFIGFS_FS)
739+
int i40e_configfs_init(void);
740+
void i40e_configfs_exit(void);
741+
#endif /* CONFIG_CONFIGFS_FS */
739742
i40e_status i40e_get_npar_bw_setting(struct i40e_pf *pf);
740743
i40e_status i40e_set_npar_bw_setting(struct i40e_pf *pf);
741744
i40e_status i40e_commit_npar_bw_setting(struct i40e_pf *pf);
Lines changed: 354 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,354 @@
1+
/*******************************************************************************
2+
*
3+
* Intel Ethernet Controller XL710 Family Linux Driver
4+
* Copyright(c) 2013 - 2015 Intel Corporation.
5+
*
6+
* This program is free software; you can redistribute it and/or modify it
7+
* under the terms and conditions of the GNU General Public License,
8+
* version 2, as published by the Free Software Foundation.
9+
*
10+
* This program is distributed in the hope it will be useful, but WITHOUT
11+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13+
* more details.
14+
*
15+
* You should have received a copy of the GNU General Public License along
16+
* with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*
18+
* The full GNU General Public License is included in this distribution in
19+
* the file called "COPYING".
20+
*
21+
* Contact Information:
22+
* e1000-devel Mailing List <[email protected]>
23+
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
24+
*
25+
******************************************************************************/
26+
27+
#include <linux/configfs.h>
28+
#include "i40e.h"
29+
30+
#if IS_ENABLED(CONFIG_CONFIGFS_FS)
31+
32+
/**
33+
* configfs structure for i40e
34+
*
35+
* This file adds code for configfs support for the i40e driver. This sets
36+
* up a filesystem under /sys/kernel/config in which configuration changes
37+
* can be made for the driver's netdevs.
38+
*
39+
* The initialization in this code creates the "i40e" entry in the configfs
40+
* system. After that, the user needs to use mkdir to create configurations
41+
* for specific netdev ports; for example "mkdir eth3". This code will verify
42+
* that such a netdev exists and that it is owned by i40e.
43+
*
44+
**/
45+
46+
struct i40e_cfgfs_vsi {
47+
struct config_item item;
48+
struct i40e_vsi *vsi;
49+
};
50+
51+
static inline struct i40e_cfgfs_vsi *to_i40e_cfgfs_vsi(struct config_item *item)
52+
{
53+
return item ? container_of(item, struct i40e_cfgfs_vsi, item) : NULL;
54+
}
55+
56+
static struct configfs_attribute i40e_cfgfs_vsi_attr_min_bw = {
57+
.ca_owner = THIS_MODULE,
58+
.ca_name = "min_bw",
59+
.ca_mode = S_IRUGO | S_IWUSR,
60+
};
61+
62+
static struct configfs_attribute i40e_cfgfs_vsi_attr_max_bw = {
63+
.ca_owner = THIS_MODULE,
64+
.ca_name = "max_bw",
65+
.ca_mode = S_IRUGO | S_IWUSR,
66+
};
67+
68+
static struct configfs_attribute i40e_cfgfs_vsi_attr_commit = {
69+
.ca_owner = THIS_MODULE,
70+
.ca_name = "commit",
71+
.ca_mode = S_IRUGO | S_IWUSR,
72+
};
73+
74+
static struct configfs_attribute i40e_cfgfs_vsi_attr_port_count = {
75+
.ca_owner = THIS_MODULE,
76+
.ca_name = "ports",
77+
.ca_mode = S_IRUGO | S_IWUSR,
78+
};
79+
80+
static struct configfs_attribute i40e_cfgfs_vsi_attr_part_count = {
81+
.ca_owner = THIS_MODULE,
82+
.ca_name = "partitions",
83+
.ca_mode = S_IRUGO | S_IWUSR,
84+
};
85+
86+
static struct configfs_attribute *i40e_cfgfs_vsi_attrs[] = {
87+
&i40e_cfgfs_vsi_attr_min_bw,
88+
&i40e_cfgfs_vsi_attr_max_bw,
89+
&i40e_cfgfs_vsi_attr_commit,
90+
&i40e_cfgfs_vsi_attr_port_count,
91+
&i40e_cfgfs_vsi_attr_part_count,
92+
NULL,
93+
};
94+
95+
/**
96+
* i40e_cfgfs_vsi_attr_show - Show a VSI's NPAR BW partition info
97+
* @item: A pointer back to the configfs item created on driver load
98+
* @attr: A pointer to this item's configuration attribute
99+
* @page: A pointer to the output buffer
100+
**/
101+
static ssize_t i40e_cfgfs_vsi_attr_show(struct config_item *item,
102+
struct configfs_attribute *attr,
103+
char *page)
104+
{
105+
struct i40e_cfgfs_vsi *i40e_cfgfs_vsi = to_i40e_cfgfs_vsi(item);
106+
struct i40e_pf *pf = i40e_cfgfs_vsi->vsi->back;
107+
ssize_t count;
108+
109+
if (i40e_cfgfs_vsi->vsi != pf->vsi[pf->lan_vsi])
110+
return 0;
111+
112+
if (strncmp(attr->ca_name, "min_bw", 6) == 0)
113+
count = sprintf(page, "%s %s %d%%\n",
114+
i40e_cfgfs_vsi->vsi->netdev->name,
115+
(pf->npar_min_bw & I40E_ALT_BW_RELATIVE_MASK) ?
116+
"Relative Min BW" : "Absolute Min BW",
117+
pf->npar_min_bw & I40E_ALT_BW_VALUE_MASK);
118+
else if (strncmp(attr->ca_name, "max_bw", 6) == 0)
119+
count = sprintf(page, "%s %s %d%%\n",
120+
i40e_cfgfs_vsi->vsi->netdev->name,
121+
(pf->npar_max_bw & I40E_ALT_BW_RELATIVE_MASK) ?
122+
"Relative Max BW" : "Absolute Max BW",
123+
pf->npar_max_bw & I40E_ALT_BW_VALUE_MASK);
124+
else if (strncmp(attr->ca_name, "ports", 5) == 0)
125+
count = sprintf(page, "%d\n",
126+
pf->hw.num_ports);
127+
else if (strncmp(attr->ca_name, "partitions", 10) == 0)
128+
count = sprintf(page, "%d\n",
129+
pf->hw.num_partitions);
130+
else
131+
return 0;
132+
133+
return count;
134+
}
135+
136+
/**
137+
* i40e_cfgfs_vsi_attr_store - Show a VSI's NPAR BW partition info
138+
* @item: A pointer back to the configfs item created on driver load
139+
* @attr: A pointer to this item's configuration attribute
140+
* @page: A pointer to the user input buffer holding the user input values
141+
**/
142+
static ssize_t i40e_cfgfs_vsi_attr_store(struct config_item *item,
143+
struct configfs_attribute *attr,
144+
const char *page, size_t count)
145+
{
146+
struct i40e_cfgfs_vsi *i40e_cfgfs_vsi = to_i40e_cfgfs_vsi(item);
147+
struct i40e_pf *pf = i40e_cfgfs_vsi->vsi->back;
148+
char *p = (char *)page;
149+
int rc;
150+
unsigned long tmp;
151+
152+
if (i40e_cfgfs_vsi->vsi != pf->vsi[pf->lan_vsi])
153+
return 0;
154+
155+
if (!p || (*p && (*p == '\n')))
156+
return -EINVAL;
157+
158+
rc = kstrtoul(p, 10, &tmp);
159+
if (rc)
160+
return rc;
161+
if (tmp > 100)
162+
return -ERANGE;
163+
164+
if (strncmp(attr->ca_name, "min_bw", 6) == 0) {
165+
if (tmp > (pf->npar_max_bw & I40E_ALT_BW_VALUE_MASK))
166+
return -ERANGE;
167+
/* Preserve the valid and relative BW bits - the rest is
168+
* don't care.
169+
*/
170+
pf->npar_min_bw &= (I40E_ALT_BW_RELATIVE_MASK |
171+
I40E_ALT_BW_VALID_MASK);
172+
pf->npar_min_bw |= (tmp & I40E_ALT_BW_VALUE_MASK);
173+
i40e_set_npar_bw_setting(pf);
174+
} else if (strncmp(attr->ca_name, "max_bw", 6) == 0) {
175+
if (tmp < 1 ||
176+
tmp < (pf->npar_min_bw & I40E_ALT_BW_VALUE_MASK))
177+
return -ERANGE;
178+
/* Preserve the valid and relative BW bits - the rest is
179+
* don't care.
180+
*/
181+
pf->npar_max_bw &= (I40E_ALT_BW_RELATIVE_MASK |
182+
I40E_ALT_BW_VALID_MASK);
183+
pf->npar_max_bw |= (tmp & I40E_ALT_BW_VALUE_MASK);
184+
i40e_set_npar_bw_setting(pf);
185+
} else if (strncmp(attr->ca_name, "commit", 6) == 0 && tmp == 1) {
186+
if (i40e_commit_npar_bw_setting(pf))
187+
return -EIO;
188+
}
189+
190+
return count;
191+
}
192+
193+
/**
194+
* i40e_cfgfs_vsi_release - Free up the configuration item memory
195+
* @item: A pointer back to the configfs item created on driver load
196+
**/
197+
static void i40e_cfgfs_vsi_release(struct config_item *item)
198+
{
199+
kfree(to_i40e_cfgfs_vsi(item));
200+
}
201+
202+
static struct configfs_item_operations i40e_cfgfs_vsi_item_ops = {
203+
.release = i40e_cfgfs_vsi_release,
204+
.show_attribute = i40e_cfgfs_vsi_attr_show,
205+
.store_attribute = i40e_cfgfs_vsi_attr_store,
206+
};
207+
208+
static struct config_item_type i40e_cfgfs_vsi_type = {
209+
.ct_item_ops = &i40e_cfgfs_vsi_item_ops,
210+
.ct_attrs = i40e_cfgfs_vsi_attrs,
211+
.ct_owner = THIS_MODULE,
212+
};
213+
214+
struct i40e_cfgfs_group {
215+
struct config_group group;
216+
};
217+
218+
/**
219+
* to_i40e_cfgfs_group - Get the group pointer from the config item
220+
* @item: A pointer back to the configfs item created on driver load
221+
**/
222+
static inline struct i40e_cfgfs_group *
223+
to_i40e_cfgfs_group(struct config_item *item)
224+
{
225+
return item ? container_of(to_config_group(item),
226+
struct i40e_cfgfs_group, group) : NULL;
227+
}
228+
229+
/**
230+
* i40e_cfgfs_group_make_item - Create the configfs item with group container
231+
* @group: A pointer to our configfs group
232+
* @name: A pointer to the nume of the device we're looking for
233+
**/
234+
static struct config_item *
235+
i40e_cfgfs_group_make_item(struct config_group *group, const char *name)
236+
{
237+
struct i40e_cfgfs_vsi *i40e_cfgfs_vsi;
238+
struct net_device *netdev;
239+
struct i40e_netdev_priv *np;
240+
241+
read_lock(&dev_base_lock);
242+
netdev = first_net_device(&init_net);
243+
while (netdev) {
244+
if (strncmp(netdev->name, name, sizeof(netdev->name)) == 0)
245+
break;
246+
netdev = next_net_device(netdev);
247+
}
248+
read_unlock(&dev_base_lock);
249+
250+
if (!netdev)
251+
return ERR_PTR(-ENODEV);
252+
253+
/* is this netdev owned by i40e? */
254+
if (netdev->netdev_ops->ndo_open != i40e_open)
255+
return ERR_PTR(-EACCES);
256+
257+
i40e_cfgfs_vsi = kzalloc(sizeof(*i40e_cfgfs_vsi), GFP_KERNEL);
258+
if (!i40e_cfgfs_vsi)
259+
return ERR_PTR(-ENOMEM);
260+
261+
np = netdev_priv(netdev);
262+
i40e_cfgfs_vsi->vsi = np->vsi;
263+
config_item_init_type_name(&i40e_cfgfs_vsi->item, name,
264+
&i40e_cfgfs_vsi_type);
265+
266+
return &i40e_cfgfs_vsi->item;
267+
}
268+
269+
static struct configfs_attribute i40e_cfgfs_group_attr_description = {
270+
.ca_owner = THIS_MODULE,
271+
.ca_name = "description",
272+
.ca_mode = S_IRUGO,
273+
};
274+
275+
static struct configfs_attribute *i40e_cfgfs_group_attrs[] = {
276+
&i40e_cfgfs_group_attr_description,
277+
NULL,
278+
};
279+
280+
static ssize_t i40e_cfgfs_group_attr_show(struct config_item *item,
281+
struct configfs_attribute *attr,
282+
char *page)
283+
{
284+
return sprintf(page,
285+
"i40e\n"
286+
"\n"
287+
"This subsystem allows the modification of network port configurations.\n"
288+
"To start, use the name of the network port to be configured in a 'mkdir'\n"
289+
"command, e.g. 'mkdir eth3'.\n");
290+
}
291+
292+
static void i40e_cfgfs_group_release(struct config_item *item)
293+
{
294+
kfree(to_i40e_cfgfs_group(item));
295+
}
296+
297+
static struct configfs_item_operations i40e_cfgfs_group_item_ops = {
298+
.release = i40e_cfgfs_group_release,
299+
.show_attribute = i40e_cfgfs_group_attr_show,
300+
};
301+
302+
/* Note that, since no extra work is required on ->drop_item(),
303+
* no ->drop_item() is provided.
304+
*/
305+
static struct configfs_group_operations i40e_cfgfs_group_ops = {
306+
.make_item = i40e_cfgfs_group_make_item,
307+
};
308+
309+
static struct config_item_type i40e_cfgfs_group_type = {
310+
.ct_item_ops = &i40e_cfgfs_group_item_ops,
311+
.ct_group_ops = &i40e_cfgfs_group_ops,
312+
.ct_attrs = i40e_cfgfs_group_attrs,
313+
.ct_owner = THIS_MODULE,
314+
};
315+
316+
static struct configfs_subsystem i40e_cfgfs_group_subsys = {
317+
.su_group = {
318+
.cg_item = {
319+
.ci_namebuf = "i40e",
320+
.ci_type = &i40e_cfgfs_group_type,
321+
},
322+
},
323+
};
324+
325+
/**
326+
* i40e_configfs_init - Initialize configfs support for our driver
327+
**/
328+
int i40e_configfs_init(void)
329+
{
330+
int ret;
331+
struct configfs_subsystem *subsys;
332+
333+
subsys = &i40e_cfgfs_group_subsys;
334+
335+
config_group_init(&subsys->su_group);
336+
mutex_init(&subsys->su_mutex);
337+
ret = configfs_register_subsystem(subsys);
338+
if (ret) {
339+
pr_err("Error %d while registering configfs subsystem %s\n",
340+
ret, subsys->su_group.cg_item.ci_namebuf);
341+
return ret;
342+
}
343+
344+
return 0;
345+
}
346+
347+
/**
348+
* i40e_configfs_init - Bail out - unregister configfs subsystem and release
349+
**/
350+
void i40e_configfs_exit(void)
351+
{
352+
configfs_unregister_subsystem(&i40e_cfgfs_group_subsys);
353+
}
354+
#endif /* IS_ENABLED(CONFIG_CONFIGFS_FS) */

0 commit comments

Comments
 (0)