File Index
Files and directories
Sign in
FILE

ice_adapter.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/ethernet/intel/ice/ice_adapter.c C
  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
 13static DEFINE_XARRAY(ice_adapters);
 14static 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
 21static 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
 43static 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
 54static 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
 73static 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 */
 94struct 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		adapter = xa_load(&ice_adapters, index);
103		if (adapter) {
104			refcount_inc(&adapter->refcount);
105			WARN_ON_ONCE(adapter->index != ice_adapter_index(pdev));
106			return adapter;
107		}
108		err = xa_reserve(&ice_adapters, index, GFP_KERNEL);
109		if (err)
110			return ERR_PTR(err);
111
112		adapter = ice_adapter_new(pdev);
113		if (!adapter) {
114			xa_release(&ice_adapters, index);
115			return ERR_PTR(-ENOMEM);
116		}
117		xa_store(&ice_adapters, index, adapter, GFP_KERNEL);
118	}
119	return adapter;
120}
121
122/**
123 * ice_adapter_put - Release a reference to the shared ice_adapter structure.
124 * @pdev: Pointer to the pci_dev whose driver is releasing the ice_adapter.
125 *
126 * Releases the reference to ice_adapter previously obtained with
127 * ice_adapter_get.
128 *
129 * Context: Process, may sleep.
130 */
131void ice_adapter_put(struct pci_dev *pdev)
132{
133	struct ice_adapter *adapter;
134	unsigned long index;
135
136	index = ice_adapter_xa_index(pdev);
137	scoped_guard(mutex, &ice_adapters_mutex) {
138		adapter = xa_load(&ice_adapters, index);
139		if (WARN_ON(!adapter))
140			return;
141		if (!refcount_dec_and_test(&adapter->refcount))
142			return;
143
144		WARN_ON(xa_erase(&ice_adapters, index) != adapter);
145	}
146	ice_adapter_free(adapter);
147}
~/ Read-only file preview.