Skip to content

Commit 1adf7ea

Browse files
jacob-kellerJeff Kirsher
authored andcommitted
ice: enable initial devlink support
Begin implementing support for the devlink interface with the ice driver. The pf structure is currently memory managed through devres, via a devm_alloc. To mimic this behavior, after allocating the devlink pointer, use devm_add_action to add a teardown action for releasing the devlink memory on exit. The ice hardware is a multi-function PCIe device. Thus, each physical function will get its own devlink instance. This means that each function will be treated independently, with its own parameters and configuration. This is done because the ice driver loads a separate instance for each function. Due to this, the implementation does not enable devlink to manage device-wide resources or configuration, as each physical function will be treated independently. This is done for simplicity, as managing a devlink instance across multiple driver instances would significantly increase the complexity for minimal gain. Signed-off-by: Jacob Keller <[email protected]> Reviewed-by: Jesse Brandeburg <[email protected]> Tested-by: Andrew Bowers <[email protected]> Signed-off-by: Jeff Kirsher <[email protected]>
1 parent 84a2479 commit 1adf7ea

File tree

6 files changed

+166
-4
lines changed

6 files changed

+166
-4
lines changed

drivers/net/ethernet/intel/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,7 @@ config ICE
294294
tristate "Intel(R) Ethernet Connection E800 Series Support"
295295
default n
296296
depends on PCI_MSI
297+
select NET_DEVLINK
297298
---help---
298299
This driver supports Intel(R) Ethernet Connection E800 Series of
299300
devices. For more information on how to identify your adapter, go

drivers/net/ethernet/intel/ice/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ ice-y := ice_main.o \
1919
ice_txrx.o \
2020
ice_flex_pipe.o \
2121
ice_flow.o \
22+
ice_devlink.o \
2223
ice_ethtool.o
2324
ice-$(CONFIG_PCI_IOV) += ice_virtchnl_pf.o ice_sriov.o
2425
ice-$(CONFIG_DCB) += ice_dcb.o ice_dcb_nl.o ice_dcb_lib.o

drivers/net/ethernet/intel/ice/ice.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include <linux/ctype.h>
3535
#include <linux/bpf.h>
3636
#include <linux/avf/virtchnl.h>
37+
#include <net/devlink.h>
3738
#include <net/ipv6.h>
3839
#include <net/xdp_sock.h>
3940
#include "ice_devids.h"
@@ -347,6 +348,9 @@ enum ice_pf_flags {
347348
struct ice_pf {
348349
struct pci_dev *pdev;
349350

351+
/* devlink port data */
352+
struct devlink_port devlink_port;
353+
350354
/* OS reserved IRQ details */
351355
struct msix_entry *msix_entries;
352356
struct ice_res_tracker *irq_tracker;
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/* Copyright (c) 2020, Intel Corporation. */
3+
4+
#include "ice.h"
5+
#include "ice_devlink.h"
6+
7+
static const struct devlink_ops ice_devlink_ops = {
8+
};
9+
10+
static void ice_devlink_free(void *devlink_ptr)
11+
{
12+
devlink_free((struct devlink *)devlink_ptr);
13+
}
14+
15+
/**
16+
* ice_allocate_pf - Allocate devlink and return PF structure pointer
17+
* @dev: the device to allocate for
18+
*
19+
* Allocate a devlink instance for this device and return the private area as
20+
* the PF structure. The devlink memory is kept track of through devres by
21+
* adding an action to remove it when unwinding.
22+
*/
23+
struct ice_pf *ice_allocate_pf(struct device *dev)
24+
{
25+
struct devlink *devlink;
26+
27+
devlink = devlink_alloc(&ice_devlink_ops, sizeof(struct ice_pf));
28+
if (!devlink)
29+
return NULL;
30+
31+
/* Add an action to teardown the devlink when unwinding the driver */
32+
if (devm_add_action(dev, ice_devlink_free, devlink)) {
33+
devlink_free(devlink);
34+
return NULL;
35+
}
36+
37+
return devlink_priv(devlink);
38+
}
39+
40+
/**
41+
* ice_devlink_register - Register devlink interface for this PF
42+
* @pf: the PF to register the devlink for.
43+
*
44+
* Register the devlink instance associated with this physical function.
45+
*
46+
* Return: zero on success or an error code on failure.
47+
*/
48+
int ice_devlink_register(struct ice_pf *pf)
49+
{
50+
struct devlink *devlink = priv_to_devlink(pf);
51+
struct device *dev = ice_pf_to_dev(pf);
52+
int err;
53+
54+
err = devlink_register(devlink, dev);
55+
if (err) {
56+
dev_err(dev, "devlink registration failed: %d\n", err);
57+
return err;
58+
}
59+
60+
return 0;
61+
}
62+
63+
/**
64+
* ice_devlink_unregister - Unregister devlink resources for this PF.
65+
* @pf: the PF structure to cleanup
66+
*
67+
* Releases resources used by devlink and cleans up associated memory.
68+
*/
69+
void ice_devlink_unregister(struct ice_pf *pf)
70+
{
71+
devlink_unregister(priv_to_devlink(pf));
72+
}
73+
74+
/**
75+
* ice_devlink_create_port - Create a devlink port for this PF
76+
* @pf: the PF to create a port for
77+
*
78+
* Create and register a devlink_port for this PF. Note that although each
79+
* physical function is connected to a separate devlink instance, the port
80+
* will still be numbered according to the physical function id.
81+
*
82+
* Return: zero on success or an error code on failure.
83+
*/
84+
int ice_devlink_create_port(struct ice_pf *pf)
85+
{
86+
struct devlink *devlink = priv_to_devlink(pf);
87+
struct ice_vsi *vsi = ice_get_main_vsi(pf);
88+
struct device *dev = ice_pf_to_dev(pf);
89+
int err;
90+
91+
if (!vsi) {
92+
dev_err(dev, "%s: unable to find main VSI\n", __func__);
93+
return -EIO;
94+
}
95+
96+
devlink_port_attrs_set(&pf->devlink_port, DEVLINK_PORT_FLAVOUR_PHYSICAL,
97+
pf->hw.pf_id, false, 0, NULL, 0);
98+
err = devlink_port_register(devlink, &pf->devlink_port, pf->hw.pf_id);
99+
if (err) {
100+
dev_err(dev, "devlink_port_register failed: %d\n", err);
101+
return err;
102+
}
103+
104+
return 0;
105+
}
106+
107+
/**
108+
* ice_devlink_destroy_port - Destroy the devlink_port for this PF
109+
* @pf: the PF to cleanup
110+
*
111+
* Unregisters the devlink_port structure associated with this PF.
112+
*/
113+
void ice_devlink_destroy_port(struct ice_pf *pf)
114+
{
115+
devlink_port_type_clear(&pf->devlink_port);
116+
devlink_port_unregister(&pf->devlink_port);
117+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
/* Copyright (c) 2019, Intel Corporation. */
3+
4+
#ifndef _ICE_DEVLINK_H_
5+
#define _ICE_DEVLINK_H_
6+
7+
struct ice_pf *ice_allocate_pf(struct device *dev);
8+
9+
int ice_devlink_register(struct ice_pf *pf);
10+
void ice_devlink_unregister(struct ice_pf *pf);
11+
int ice_devlink_create_port(struct ice_pf *pf);
12+
void ice_devlink_destroy_port(struct ice_pf *pf);
13+
14+
#endif /* _ICE_DEVLINK_H_ */

drivers/net/ethernet/intel/ice/ice_main.c

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "ice_lib.h"
1111
#include "ice_dcb_lib.h"
1212
#include "ice_dcb_nl.h"
13+
#include "ice_devlink.h"
1314

1415
#define DRV_VERSION_MAJOR 0
1516
#define DRV_VERSION_MINOR 8
@@ -2371,10 +2372,16 @@ static int ice_cfg_netdev(struct ice_vsi *vsi)
23712372
u8 mac_addr[ETH_ALEN];
23722373
int err;
23732374

2375+
err = ice_devlink_create_port(pf);
2376+
if (err)
2377+
return err;
2378+
23742379
netdev = alloc_etherdev_mqs(sizeof(*np), vsi->alloc_txq,
23752380
vsi->alloc_rxq);
2376-
if (!netdev)
2377-
return -ENOMEM;
2381+
if (!netdev) {
2382+
err = -ENOMEM;
2383+
goto err_destroy_devlink_port;
2384+
}
23782385

23792386
vsi->netdev = netdev;
23802387
np = netdev_priv(netdev);
@@ -2404,14 +2411,21 @@ static int ice_cfg_netdev(struct ice_vsi *vsi)
24042411

24052412
err = register_netdev(vsi->netdev);
24062413
if (err)
2407-
return err;
2414+
goto err_destroy_devlink_port;
2415+
2416+
devlink_port_type_eth_set(&pf->devlink_port, vsi->netdev);
24082417

24092418
netif_carrier_off(vsi->netdev);
24102419

24112420
/* make sure transmit queues start off as stopped */
24122421
netif_tx_stop_all_queues(vsi->netdev);
24132422

24142423
return 0;
2424+
2425+
err_destroy_devlink_port:
2426+
ice_devlink_destroy_port(pf);
2427+
2428+
return err;
24152429
}
24162430

24172431
/**
@@ -3184,7 +3198,7 @@ ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent)
31843198
return err;
31853199
}
31863200

3187-
pf = devm_kzalloc(dev, sizeof(*pf), GFP_KERNEL);
3201+
pf = ice_allocate_pf(dev);
31883202
if (!pf)
31893203
return -ENOMEM;
31903204

@@ -3222,6 +3236,12 @@ ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent)
32223236

32233237
pf->msg_enable = netif_msg_init(debug, ICE_DFLT_NETIF_M);
32243238

3239+
err = ice_devlink_register(pf);
3240+
if (err) {
3241+
dev_err(dev, "ice_devlink_register failed: %d\n", err);
3242+
goto err_exit_unroll;
3243+
}
3244+
32253245
#ifndef CONFIG_DYNAMIC_DEBUG
32263246
if (debug < -1)
32273247
hw->debug_mask = debug;
@@ -3354,6 +3374,7 @@ ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent)
33543374
return 0;
33553375

33563376
err_alloc_sw_unroll:
3377+
ice_devlink_destroy_port(pf);
33573378
set_bit(__ICE_SERVICE_DIS, pf->state);
33583379
set_bit(__ICE_DOWN, pf->state);
33593380
devm_kfree(dev, pf->first_sw);
@@ -3366,6 +3387,7 @@ ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent)
33663387
ice_deinit_pf(pf);
33673388
ice_deinit_hw(hw);
33683389
err_exit_unroll:
3390+
ice_devlink_unregister(pf);
33693391
pci_disable_pcie_error_reporting(pdev);
33703392
return err;
33713393
}
@@ -3396,6 +3418,7 @@ static void ice_remove(struct pci_dev *pdev)
33963418
set_bit(__ICE_DOWN, pf->state);
33973419
ice_service_task_stop(pf);
33983420

3421+
ice_devlink_destroy_port(pf);
33993422
ice_vsi_release_all(pf);
34003423
ice_free_irq_msix_misc(pf);
34013424
ice_for_each_vsi(pf, i) {
@@ -3405,6 +3428,8 @@ static void ice_remove(struct pci_dev *pdev)
34053428
}
34063429
ice_deinit_pf(pf);
34073430
ice_deinit_hw(&pf->hw);
3431+
ice_devlink_unregister(pf);
3432+
34083433
/* Issue a PFR as part of the prescribed driver unload flow. Do not
34093434
* do it via ice_schedule_reset() since there is no need to rebuild
34103435
* and the service task is already stopped.

0 commit comments

Comments
 (0)