xref: /linux/drivers/net/ethernet/intel/ice/ice_adapter.c (revision 9c736ace0666efe68efd53fcdfa2c6653c3e0e72)
1 // SPDX-License-Identifier: GPL-2.0-only
2 // SPDX-FileCopyrightText: Copyright Red Hat
3 
4 #include <linux/cleanup.h>
5 #include <linux/mutex.h>
6 #include <linux/pci.h>
7 #include <linux/slab.h>
8 #include <linux/spinlock.h>
9 #include <linux/xarray.h>
10 #include "ice_adapter.h"
11 #include "ice.h"
12 
13 static DEFINE_XARRAY(ice_adapters);
14 static DEFINE_MUTEX(ice_adapters_mutex);
15 
16 #define ICE_ADAPTER_FIXED_INDEX	BIT_ULL(63)
17 
18 #define ICE_ADAPTER_INDEX_E825C	\
19 	(ICE_DEV_ID_E825C_BACKPLANE | ICE_ADAPTER_FIXED_INDEX)
20 
ice_adapter_index(struct pci_dev * pdev)21 static u64 ice_adapter_index(struct pci_dev *pdev)
22 {
23 	switch (pdev->device) {
24 	case ICE_DEV_ID_E825C_BACKPLANE:
25 	case ICE_DEV_ID_E825C_QSFP:
26 	case ICE_DEV_ID_E825C_SFP:
27 	case ICE_DEV_ID_E825C_SGMII:
28 		/* E825C devices have multiple NACs which are connected to the
29 		 * same clock source, and which must share the same
30 		 * ice_adapter structure. We can't use the serial number since
31 		 * each NAC has its own NVM generated with its own unique
32 		 * Device Serial Number. Instead, rely on the embedded nature
33 		 * of the E825C devices, and use a fixed index. This relies on
34 		 * the fact that all E825C physical functions in a given
35 		 * system are part of the same overall device.
36 		 */
37 		return ICE_ADAPTER_INDEX_E825C;
38 	default:
39 		return pci_get_dsn(pdev) & ~ICE_ADAPTER_FIXED_INDEX;
40 	}
41 }
42 
ice_adapter_xa_index(struct pci_dev * pdev)43 static unsigned long ice_adapter_xa_index(struct pci_dev *pdev)
44 {
45 	u64 index = ice_adapter_index(pdev);
46 
47 #if BITS_PER_LONG == 64
48 	return index;
49 #else
50 	return (u32)index ^ (u32)(index >> 32);
51 #endif
52 }
53 
ice_adapter_new(struct pci_dev * pdev)54 static struct ice_adapter *ice_adapter_new(struct pci_dev *pdev)
55 {
56 	struct ice_adapter *adapter;
57 
58 	adapter = kzalloc(sizeof(*adapter), GFP_KERNEL);
59 	if (!adapter)
60 		return NULL;
61 
62 	adapter->index = ice_adapter_index(pdev);
63 	spin_lock_init(&adapter->ptp_gltsyn_time_lock);
64 	spin_lock_init(&adapter->txq_ctx_lock);
65 	refcount_set(&adapter->refcount, 1);
66 
67 	mutex_init(&adapter->ports.lock);
68 	INIT_LIST_HEAD(&adapter->ports.ports);
69 
70 	return adapter;
71 }
72 
ice_adapter_free(struct ice_adapter * adapter)73 static void ice_adapter_free(struct ice_adapter *adapter)
74 {
75 	WARN_ON(!list_empty(&adapter->ports.ports));
76 	mutex_destroy(&adapter->ports.lock);
77 
78 	kfree(adapter);
79 }
80 
81 /**
82  * ice_adapter_get - Get a shared ice_adapter structure.
83  * @pdev: Pointer to the pci_dev whose driver is getting the ice_adapter.
84  *
85  * Gets a pointer to a shared ice_adapter structure. Physical functions (PFs)
86  * of the same multi-function PCI device share one ice_adapter structure.
87  * The ice_adapter is reference-counted. The PF driver must use ice_adapter_put
88  * to release its reference.
89  *
90  * Context: Process, may sleep.
91  * Return:  Pointer to ice_adapter on success.
92  *          ERR_PTR() on error. -ENOMEM is the only possible error.
93  */
ice_adapter_get(struct pci_dev * pdev)94 struct ice_adapter *ice_adapter_get(struct pci_dev *pdev)
95 {
96 	struct ice_adapter *adapter;
97 	unsigned long index;
98 	int err;
99 
100 	index = ice_adapter_xa_index(pdev);
101 	scoped_guard(mutex, &ice_adapters_mutex) {
102 		err = xa_insert(&ice_adapters, index, NULL, GFP_KERNEL);
103 		if (err == -EBUSY) {
104 			adapter = xa_load(&ice_adapters, index);
105 			refcount_inc(&adapter->refcount);
106 			WARN_ON_ONCE(adapter->index != ice_adapter_index(pdev));
107 			return adapter;
108 		}
109 		if (err)
110 			return ERR_PTR(err);
111 
112 		adapter = ice_adapter_new(pdev);
113 		if (!adapter)
114 			return ERR_PTR(-ENOMEM);
115 		xa_store(&ice_adapters, index, adapter, GFP_KERNEL);
116 	}
117 	return adapter;
118 }
119 
120 /**
121  * ice_adapter_put - Release a reference to the shared ice_adapter structure.
122  * @pdev: Pointer to the pci_dev whose driver is releasing the ice_adapter.
123  *
124  * Releases the reference to ice_adapter previously obtained with
125  * ice_adapter_get.
126  *
127  * Context: Process, may sleep.
128  */
ice_adapter_put(struct pci_dev * pdev)129 void ice_adapter_put(struct pci_dev *pdev)
130 {
131 	struct ice_adapter *adapter;
132 	unsigned long index;
133 
134 	index = ice_adapter_xa_index(pdev);
135 	scoped_guard(mutex, &ice_adapters_mutex) {
136 		adapter = xa_load(&ice_adapters, index);
137 		if (WARN_ON(!adapter))
138 			return;
139 		if (!refcount_dec_and_test(&adapter->refcount))
140 			return;
141 
142 		WARN_ON(xa_erase(&ice_adapters, index) != adapter);
143 	}
144 	ice_adapter_free(adapter);
145 }
146