aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet
diff options
context:
space:
mode:
authorGreg Rose <gregory.v.rose@intel.com>2015-02-06 03:52:13 -0500
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2015-02-25 00:42:40 -0500
commit96664483a38d25b37de8911e2058b1d10af3d113 (patch)
tree66ef8ada970263d967d2c042e468ba203c2517a2 /drivers/net/ethernet
parentf4492db16df8a027cebc209c3905cbe421b53d3a (diff)
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 <gregory.v.rose@intel.com> Tested-By: Jim Young <james.m.young@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers/net/ethernet')
-rw-r--r--drivers/net/ethernet/intel/i40e/Makefile3
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e.h7
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_configfs.c354
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_main.c13
4 files changed, 369 insertions, 8 deletions
diff --git a/drivers/net/ethernet/intel/i40e/Makefile b/drivers/net/ethernet/intel/i40e/Makefile
index c40581999121..023e452aff8c 100644
--- a/drivers/net/ethernet/intel/i40e/Makefile
+++ b/drivers/net/ethernet/intel/i40e/Makefile
@@ -1,7 +1,7 @@
1################################################################################ 1################################################################################
2# 2#
3# Intel Ethernet Controller XL710 Family Linux Driver 3# Intel Ethernet Controller XL710 Family Linux Driver
4# Copyright(c) 2013 - 2014 Intel Corporation. 4# Copyright(c) 2013 - 2015 Intel Corporation.
5# 5#
6# This program is free software; you can redistribute it and/or modify it 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, 7# under the terms and conditions of the GNU General Public License,
@@ -37,6 +37,7 @@ i40e-objs := i40e_main.o \
37 i40e_hmc.o \ 37 i40e_hmc.o \
38 i40e_lan_hmc.o \ 38 i40e_lan_hmc.o \
39 i40e_nvm.o \ 39 i40e_nvm.o \
40 i40e_configfs.o \
40 i40e_debugfs.o \ 41 i40e_debugfs.o \
41 i40e_diag.o \ 42 i40e_diag.o \
42 i40e_txrx.o \ 43 i40e_txrx.o \
diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h
index 713e20e6a29e..21925876a633 100644
--- a/drivers/net/ethernet/intel/i40e/i40e.h
+++ b/drivers/net/ethernet/intel/i40e/i40e.h
@@ -688,6 +688,7 @@ int i40e_vlan_rx_add_vid(struct net_device *netdev,
688int i40e_vlan_rx_kill_vid(struct net_device *netdev, 688int i40e_vlan_rx_kill_vid(struct net_device *netdev,
689 __always_unused __be16 proto, u16 vid); 689 __always_unused __be16 proto, u16 vid);
690#endif 690#endif
691int i40e_open(struct net_device *netdev);
691int i40e_vsi_open(struct i40e_vsi *vsi); 692int i40e_vsi_open(struct i40e_vsi *vsi);
692void i40e_vlan_stripping_disable(struct i40e_vsi *vsi); 693void i40e_vlan_stripping_disable(struct i40e_vsi *vsi);
693int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid); 694int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid);
@@ -698,7 +699,6 @@ bool i40e_is_vsi_in_vlan(struct i40e_vsi *vsi);
698struct i40e_mac_filter *i40e_find_mac(struct i40e_vsi *vsi, u8 *macaddr, 699struct i40e_mac_filter *i40e_find_mac(struct i40e_vsi *vsi, u8 *macaddr,
699 bool is_vf, bool is_netdev); 700 bool is_vf, bool is_netdev);
700#ifdef I40E_FCOE 701#ifdef I40E_FCOE
701int i40e_open(struct net_device *netdev);
702int i40e_close(struct net_device *netdev); 702int i40e_close(struct net_device *netdev);
703int i40e_setup_tc(struct net_device *netdev, u8 tc); 703int i40e_setup_tc(struct net_device *netdev, u8 tc);
704void i40e_netpoll(struct net_device *netdev); 704void i40e_netpoll(struct net_device *netdev);
@@ -735,7 +735,10 @@ int i40e_ptp_set_ts_config(struct i40e_pf *pf, struct ifreq *ifr);
735int i40e_ptp_get_ts_config(struct i40e_pf *pf, struct ifreq *ifr); 735int i40e_ptp_get_ts_config(struct i40e_pf *pf, struct ifreq *ifr);
736void i40e_ptp_init(struct i40e_pf *pf); 736void i40e_ptp_init(struct i40e_pf *pf);
737void i40e_ptp_stop(struct i40e_pf *pf); 737void i40e_ptp_stop(struct i40e_pf *pf);
738 738#if IS_ENABLED(CONFIG_CONFIGFS_FS)
739int i40e_configfs_init(void);
740void i40e_configfs_exit(void);
741#endif /* CONFIG_CONFIGFS_FS */
739i40e_status i40e_get_npar_bw_setting(struct i40e_pf *pf); 742i40e_status i40e_get_npar_bw_setting(struct i40e_pf *pf);
740i40e_status i40e_set_npar_bw_setting(struct i40e_pf *pf); 743i40e_status i40e_set_npar_bw_setting(struct i40e_pf *pf);
741i40e_status i40e_commit_npar_bw_setting(struct i40e_pf *pf); 744i40e_status i40e_commit_npar_bw_setting(struct i40e_pf *pf);
diff --git a/drivers/net/ethernet/intel/i40e/i40e_configfs.c b/drivers/net/ethernet/intel/i40e/i40e_configfs.c
new file mode 100644
index 000000000000..3af4f14559d7
--- /dev/null
+++ b/drivers/net/ethernet/intel/i40e/i40e_configfs.c
@@ -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 <e1000-devel@lists.sourceforge.net>
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
46struct i40e_cfgfs_vsi {
47 struct config_item item;
48 struct i40e_vsi *vsi;
49};
50
51static 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
56static 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
62static 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
68static 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
74static 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
80static 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
86static 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 **/
101static 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 **/
142static 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 **/
197static void i40e_cfgfs_vsi_release(struct config_item *item)
198{
199 kfree(to_i40e_cfgfs_vsi(item));
200}
201
202static 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
208static 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
214struct 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 **/
222static inline struct i40e_cfgfs_group *
223to_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 **/
234static struct config_item *
235i40e_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
269static struct configfs_attribute i40e_cfgfs_group_attr_description = {
270 .ca_owner = THIS_MODULE,
271 .ca_name = "description",
272 .ca_mode = S_IRUGO,
273};
274
275static struct configfs_attribute *i40e_cfgfs_group_attrs[] = {
276 &i40e_cfgfs_group_attr_description,
277 NULL,
278};
279
280static 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
292static void i40e_cfgfs_group_release(struct config_item *item)
293{
294 kfree(to_i40e_cfgfs_group(item));
295}
296
297static 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 */
305static struct configfs_group_operations i40e_cfgfs_group_ops = {
306 .make_item = i40e_cfgfs_group_make_item,
307};
308
309static 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
316static 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 **/
328int 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 **/
350void i40e_configfs_exit(void)
351{
352 configfs_unregister_subsystem(&i40e_cfgfs_group_subsys);
353}
354#endif /* IS_ENABLED(CONFIG_CONFIGFS_FS) */
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index e3e48c3ae24a..eb2655f464b3 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -4835,11 +4835,7 @@ exit:
4835 * 4835 *
4836 * Returns 0 on success, negative value on failure 4836 * Returns 0 on success, negative value on failure
4837 **/ 4837 **/
4838#ifdef I40E_FCOE
4839int i40e_open(struct net_device *netdev) 4838int i40e_open(struct net_device *netdev)
4840#else
4841static int i40e_open(struct net_device *netdev)
4842#endif
4843{ 4839{
4844 struct i40e_netdev_priv *np = netdev_priv(netdev); 4840 struct i40e_netdev_priv *np = netdev_priv(netdev);
4845 struct i40e_vsi *vsi = np->vsi; 4841 struct i40e_vsi *vsi = np->vsi;
@@ -7741,7 +7737,7 @@ static int i40e_ndo_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
7741 return err; 7737 return err;
7742} 7738}
7743 7739
7744static const struct net_device_ops i40e_netdev_ops = { 7740const struct net_device_ops i40e_netdev_ops = {
7745 .ndo_open = i40e_open, 7741 .ndo_open = i40e_open,
7746 .ndo_stop = i40e_close, 7742 .ndo_stop = i40e_close,
7747 .ndo_start_xmit = i40e_lan_xmit_frame, 7743 .ndo_start_xmit = i40e_lan_xmit_frame,
@@ -9943,6 +9939,10 @@ static int __init i40e_init_module(void)
9943 pr_info("%s: %s - version %s\n", i40e_driver_name, 9939 pr_info("%s: %s - version %s\n", i40e_driver_name,
9944 i40e_driver_string, i40e_driver_version_str); 9940 i40e_driver_string, i40e_driver_version_str);
9945 pr_info("%s: %s\n", i40e_driver_name, i40e_copyright); 9941 pr_info("%s: %s\n", i40e_driver_name, i40e_copyright);
9942
9943#if IS_ENABLED(CONFIG_CONFIGFS_FS)
9944 i40e_configfs_init();
9945#endif /* CONFIG_CONFIGFS_FS */
9946 i40e_dbg_init(); 9946 i40e_dbg_init();
9947 return pci_register_driver(&i40e_driver); 9947 return pci_register_driver(&i40e_driver);
9948} 9948}
@@ -9958,5 +9958,8 @@ static void __exit i40e_exit_module(void)
9958{ 9958{
9959 pci_unregister_driver(&i40e_driver); 9959 pci_unregister_driver(&i40e_driver);
9960 i40e_dbg_exit(); 9960 i40e_dbg_exit();
9961#if IS_ENABLED(CONFIG_CONFIGFS_FS)
9962 i40e_configfs_exit();
9963#endif /* CONFIG_CONFIGFS_FS */
9961} 9964}
9962module_exit(i40e_exit_module); 9965module_exit(i40e_exit_module);