Skip to content

Commit 0e2bddf

Browse files
michichanguy11
authored andcommitted
ice: add ice_adapter for shared data across PFs on the same NIC
There is a need for synchronization between ice PFs on the same physical adapter. Add a "struct ice_adapter" for holding data shared between PFs of the same multifunction PCI device. The struct is refcounted - each ice_pf holds a reference to it. Its first use will be for PTP. I expect it will be useful also to improve the ugliness that is ice_prot_id_tbl. Reviewed-by: Przemek Kitszel <[email protected]> Signed-off-by: Michal Schmidt <[email protected]> Tested-by: Pucha Himasekhar Reddy <[email protected]> (A Contingent worker at Intel) Signed-off-by: Tony Nguyen <[email protected]>
1 parent 3b4cf29 commit 0e2bddf

File tree

5 files changed

+148
-1
lines changed

5 files changed

+148
-1
lines changed

drivers/net/ethernet/intel/ice/Makefile

+2-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ ice-y := ice_main.o \
3636
ice_repr.o \
3737
ice_tc_lib.o \
3838
ice_fwlog.o \
39-
ice_debugfs.o
39+
ice_debugfs.o \
40+
ice_adapter.o
4041
ice-$(CONFIG_PCI_IOV) += \
4142
ice_sriov.o \
4243
ice_virtchnl.o \

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

+2
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777
#include "ice_gnss.h"
7878
#include "ice_irq.h"
7979
#include "ice_dpll.h"
80+
#include "ice_adapter.h"
8081

8182
#define ICE_BAR0 0
8283
#define ICE_REQ_DESC_MULTIPLE 32
@@ -537,6 +538,7 @@ struct ice_agg_node {
537538

538539
struct ice_pf {
539540
struct pci_dev *pdev;
541+
struct ice_adapter *adapter;
540542

541543
struct devlink_region *nvm_region;
542544
struct devlink_region *sram_region;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
// SPDX-FileCopyrightText: Copyright Red Hat
3+
4+
#include <linux/bitfield.h>
5+
#include <linux/cleanup.h>
6+
#include <linux/mutex.h>
7+
#include <linux/pci.h>
8+
#include <linux/slab.h>
9+
#include <linux/xarray.h>
10+
#include "ice_adapter.h"
11+
12+
static DEFINE_XARRAY(ice_adapters);
13+
14+
/* PCI bus number is 8 bits. Slot is 5 bits. Domain can have the rest. */
15+
#define INDEX_FIELD_DOMAIN GENMASK(BITS_PER_LONG - 1, 13)
16+
#define INDEX_FIELD_BUS GENMASK(12, 5)
17+
#define INDEX_FIELD_SLOT GENMASK(4, 0)
18+
19+
static unsigned long ice_adapter_index(const struct pci_dev *pdev)
20+
{
21+
unsigned int domain = pci_domain_nr(pdev->bus);
22+
23+
WARN_ON(domain > FIELD_MAX(INDEX_FIELD_DOMAIN));
24+
25+
return FIELD_PREP(INDEX_FIELD_DOMAIN, domain) |
26+
FIELD_PREP(INDEX_FIELD_BUS, pdev->bus->number) |
27+
FIELD_PREP(INDEX_FIELD_SLOT, PCI_SLOT(pdev->devfn));
28+
}
29+
30+
static struct ice_adapter *ice_adapter_new(void)
31+
{
32+
struct ice_adapter *adapter;
33+
34+
adapter = kzalloc(sizeof(*adapter), GFP_KERNEL);
35+
if (!adapter)
36+
return NULL;
37+
38+
refcount_set(&adapter->refcount, 1);
39+
40+
return adapter;
41+
}
42+
43+
static void ice_adapter_free(struct ice_adapter *adapter)
44+
{
45+
kfree(adapter);
46+
}
47+
48+
DEFINE_FREE(ice_adapter_free, struct ice_adapter*, if (_T) ice_adapter_free(_T))
49+
50+
/**
51+
* ice_adapter_get - Get a shared ice_adapter structure.
52+
* @pdev: Pointer to the pci_dev whose driver is getting the ice_adapter.
53+
*
54+
* Gets a pointer to a shared ice_adapter structure. Physical functions (PFs)
55+
* of the same multi-function PCI device share one ice_adapter structure.
56+
* The ice_adapter is reference-counted. The PF driver must use ice_adapter_put
57+
* to release its reference.
58+
*
59+
* Context: Process, may sleep.
60+
* Return: Pointer to ice_adapter on success.
61+
* ERR_PTR() on error. -ENOMEM is the only possible error.
62+
*/
63+
struct ice_adapter *ice_adapter_get(const struct pci_dev *pdev)
64+
{
65+
struct ice_adapter *ret, __free(ice_adapter_free) *adapter = NULL;
66+
unsigned long index = ice_adapter_index(pdev);
67+
68+
adapter = ice_adapter_new();
69+
if (!adapter)
70+
return ERR_PTR(-ENOMEM);
71+
72+
xa_lock(&ice_adapters);
73+
ret = __xa_cmpxchg(&ice_adapters, index, NULL, adapter, GFP_KERNEL);
74+
if (xa_is_err(ret)) {
75+
ret = ERR_PTR(xa_err(ret));
76+
goto unlock;
77+
}
78+
if (ret) {
79+
refcount_inc(&ret->refcount);
80+
goto unlock;
81+
}
82+
ret = no_free_ptr(adapter);
83+
unlock:
84+
xa_unlock(&ice_adapters);
85+
return ret;
86+
}
87+
88+
/**
89+
* ice_adapter_put - Release a reference to the shared ice_adapter structure.
90+
* @pdev: Pointer to the pci_dev whose driver is releasing the ice_adapter.
91+
*
92+
* Releases the reference to ice_adapter previously obtained with
93+
* ice_adapter_get.
94+
*
95+
* Context: Any.
96+
*/
97+
void ice_adapter_put(const struct pci_dev *pdev)
98+
{
99+
unsigned long index = ice_adapter_index(pdev);
100+
struct ice_adapter *adapter;
101+
102+
xa_lock(&ice_adapters);
103+
adapter = xa_load(&ice_adapters, index);
104+
if (WARN_ON(!adapter))
105+
goto unlock;
106+
107+
if (!refcount_dec_and_test(&adapter->refcount))
108+
goto unlock;
109+
110+
WARN_ON(__xa_erase(&ice_adapters, index) != adapter);
111+
ice_adapter_free(adapter);
112+
unlock:
113+
xa_unlock(&ice_adapters);
114+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/* SPDX-License-Identifier: GPL-2.0-only */
2+
/* SPDX-FileCopyrightText: Copyright Red Hat */
3+
4+
#ifndef _ICE_ADAPTER_H_
5+
#define _ICE_ADAPTER_H_
6+
7+
#include <linux/refcount_types.h>
8+
9+
struct pci_dev;
10+
11+
/**
12+
* struct ice_adapter - PCI adapter resources shared across PFs
13+
* @refcount: Reference count. struct ice_pf objects hold the references.
14+
*/
15+
struct ice_adapter {
16+
refcount_t refcount;
17+
};
18+
19+
struct ice_adapter *ice_adapter_get(const struct pci_dev *pdev);
20+
void ice_adapter_put(const struct pci_dev *pdev);
21+
22+
#endif /* _ICE_ADAPTER_H */

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

+8
Original file line numberDiff line numberDiff line change
@@ -5093,6 +5093,7 @@ static int
50935093
ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent)
50945094
{
50955095
struct device *dev = &pdev->dev;
5096+
struct ice_adapter *adapter;
50965097
struct ice_pf *pf;
50975098
struct ice_hw *hw;
50985099
int err;
@@ -5145,7 +5146,12 @@ ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent)
51455146

51465147
pci_set_master(pdev);
51475148

5149+
adapter = ice_adapter_get(pdev);
5150+
if (IS_ERR(adapter))
5151+
return PTR_ERR(adapter);
5152+
51485153
pf->pdev = pdev;
5154+
pf->adapter = adapter;
51495155
pci_set_drvdata(pdev, pf);
51505156
set_bit(ICE_DOWN, pf->state);
51515157
/* Disable service task until DOWN bit is cleared */
@@ -5196,6 +5202,7 @@ ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent)
51965202
err_load:
51975203
ice_deinit(pf);
51985204
err_init:
5205+
ice_adapter_put(pdev);
51995206
pci_disable_device(pdev);
52005207
return err;
52015208
}
@@ -5302,6 +5309,7 @@ static void ice_remove(struct pci_dev *pdev)
53025309
ice_setup_mc_magic_wake(pf);
53035310
ice_set_wake(pf);
53045311

5312+
ice_adapter_put(pdev);
53055313
pci_disable_device(pdev);
53065314
}
53075315

0 commit comments

Comments
 (0)