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 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 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 54 static struct ice_adapter *ice_adapter_new(struct pci_dev *pdev) 55 { 56 struct ice_adapter *adapter; 57 58 adapter = kzalloc_obj(*adapter); 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 for (int i = 0; i < ARRAY_SIZE(adapter->cpi_phy_lock); i++) 66 mutex_init(&adapter->cpi_phy_lock[i]); 67 refcount_set(&adapter->refcount, 1); 68 69 mutex_init(&adapter->ports.lock); 70 INIT_LIST_HEAD(&adapter->ports.ports); 71 72 return adapter; 73 } 74 75 static void ice_adapter_free(struct ice_adapter *adapter) 76 { 77 WARN_ON(!list_empty(&adapter->ports.ports)); 78 for (int i = 0; i < ARRAY_SIZE(adapter->cpi_phy_lock); i++) 79 mutex_destroy(&adapter->cpi_phy_lock[i]); 80 mutex_destroy(&adapter->ports.lock); 81 82 kfree(adapter); 83 } 84 85 /** 86 * ice_adapter_get - Get a shared ice_adapter structure. 87 * @pdev: Pointer to the pci_dev whose driver is getting the ice_adapter. 88 * 89 * Gets a pointer to a shared ice_adapter structure. Physical functions (PFs) 90 * of the same multi-function PCI device share one ice_adapter structure. 91 * The ice_adapter is reference-counted. The PF driver must use ice_adapter_put 92 * to release its reference. 93 * 94 * Context: Process, may sleep. 95 * Return: Pointer to ice_adapter on success. 96 * ERR_PTR() on error. -ENOMEM is the only possible error. 97 */ 98 struct ice_adapter *ice_adapter_get(struct pci_dev *pdev) 99 { 100 struct ice_adapter *adapter; 101 unsigned long index; 102 int err; 103 104 index = ice_adapter_xa_index(pdev); 105 scoped_guard(mutex, &ice_adapters_mutex) { 106 adapter = xa_load(&ice_adapters, index); 107 if (adapter) { 108 refcount_inc(&adapter->refcount); 109 WARN_ON_ONCE(adapter->index != ice_adapter_index(pdev)); 110 return adapter; 111 } 112 err = xa_reserve(&ice_adapters, index, GFP_KERNEL); 113 if (err) 114 return ERR_PTR(err); 115 116 adapter = ice_adapter_new(pdev); 117 if (!adapter) { 118 xa_release(&ice_adapters, index); 119 return ERR_PTR(-ENOMEM); 120 } 121 xa_store(&ice_adapters, index, adapter, GFP_KERNEL); 122 } 123 return adapter; 124 } 125 126 /** 127 * ice_adapter_put - Release a reference to the shared ice_adapter structure. 128 * @pdev: Pointer to the pci_dev whose driver is releasing the ice_adapter. 129 * 130 * Releases the reference to ice_adapter previously obtained with 131 * ice_adapter_get. 132 * 133 * Context: Process, may sleep. 134 */ 135 void ice_adapter_put(struct pci_dev *pdev) 136 { 137 struct ice_adapter *adapter; 138 unsigned long index; 139 140 index = ice_adapter_xa_index(pdev); 141 scoped_guard(mutex, &ice_adapters_mutex) { 142 adapter = xa_load(&ice_adapters, index); 143 if (WARN_ON(!adapter)) 144 return; 145 if (!refcount_dec_and_test(&adapter->refcount)) 146 return; 147 148 WARN_ON(xa_erase(&ice_adapters, index) != adapter); 149 } 150 ice_adapter_free(adapter); 151 } 152