]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
ice: use fixed adapter index for E825C embedded devices
authorJacob Keller <jacob.e.keller@intel.com>
Fri, 1 Aug 2025 22:27:12 +0000 (15:27 -0700)
committerTony Nguyen <anthony.l.nguyen@intel.com>
Mon, 25 Aug 2025 16:45:23 +0000 (09:45 -0700)
The ice_adapter structure is used by the ice driver to connect multiple
physical functions of a device in software. It was introduced by
commit 0e2bddf9e5f9 ("ice: add ice_adapter for shared data across PFs on
the same NIC") and is primarily used for PTP support, as well as for
handling certain cross-PF synchronization.

The original design of ice_adapter used PCI address information to
determine which devices should be connected. This was extended to support
E825C devices by commit fdb7f54700b1 ("ice: Initial support for E825C
hardware in ice_adapter"), which used the device ID for E825C devices
instead of the PCI address.

Later, commit 0093cb194a75 ("ice: use DSN instead of PCI BDF for
ice_adapter index") replaced the use of Bus/Device/Function addressing with
use of the device serial number.

E825C devices may appear in "Dual NAC" configuration which has multiple
physical devices tied to the same clock source and which need to use the
same ice_adapter. Unfortunately, each "NAC" has its own NVM which has its
own unique Device Serial Number. Thus, use of the DSN for connecting
ice_adapter does not work properly. It "worked" in the pre-production
systems because the DSN was not initialized on the test NVMs and all the
NACs had the same zero'd serial number.

Since we cannot rely on the DSN, lets fall back to the logic in the
original E825C support which used the device ID. This is safe for E825C
only because of the embedded nature of the device. It isn't a discreet
adapter that can be plugged into an arbitrary system. All E825C devices on
a given system are connected to the same clock source and need to be
configured through the same PTP clock.

To make this separation clear, reserve bit 63 of the 64-bit index values as
a "fixed index" indicator. Always clear this bit when using the device
serial number as an index.

For E825C, use a fixed value defined as the 0x579C E825C backplane device
ID bitwise ORed with the fixed index indicator. This is slightly different
than the original logic of just using the device ID directly. Doing so
prevents a potential issue with systems where only one of the NACs is
connected with an external PHY over SGMII. In that case, one NAC would
have the E825C_SGMII device ID, but the other would not.

Separate the determination of the full 64-bit index from the 32-bit
reduction logic. Provide both ice_adapter_index() and a wrapping
ice_adapter_xa_index() which handles reducing the index to a long on 32-bit
systems. As before, cache the full index value in the adapter structure to
warn about collisions.

This fixes issues with E825C not initializing PTP on both NACs, due to
failure to connect the appropriate devices to the same ice_adapter.

Fixes: 0093cb194a75 ("ice: use DSN instead of PCI BDF for ice_adapter index")
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Reviewed-by: Grzegorz Nitka <grzegorz.nitka@intel.com>
Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
Reviewed-by: Przemek Kitszel <przemyslaw.kitszel@intel.com>
Tested-by: Rinitha S <sx.rinitha@intel.com> (A Contingent worker at Intel)
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
drivers/net/ethernet/intel/ice/ice_adapter.c
drivers/net/ethernet/intel/ice/ice_adapter.h

index 9e4adc43e474c960b8ee4849380a691a0e5ef848..b53561c347082f725f2a9c10b0c262ceadbe815c 100644 (file)
 static DEFINE_XARRAY(ice_adapters);
 static DEFINE_MUTEX(ice_adapters_mutex);
 
-static unsigned long ice_adapter_index(u64 dsn)
+#define ICE_ADAPTER_FIXED_INDEX        BIT_ULL(63)
+
+#define ICE_ADAPTER_INDEX_E825C        \
+       (ICE_DEV_ID_E825C_BACKPLANE | ICE_ADAPTER_FIXED_INDEX)
+
+static u64 ice_adapter_index(struct pci_dev *pdev)
 {
+       switch (pdev->device) {
+       case ICE_DEV_ID_E825C_BACKPLANE:
+       case ICE_DEV_ID_E825C_QSFP:
+       case ICE_DEV_ID_E825C_SFP:
+       case ICE_DEV_ID_E825C_SGMII:
+               /* E825C devices have multiple NACs which are connected to the
+                * same clock source, and which must share the same
+                * ice_adapter structure. We can't use the serial number since
+                * each NAC has its own NVM generated with its own unique
+                * Device Serial Number. Instead, rely on the embedded nature
+                * of the E825C devices, and use a fixed index. This relies on
+                * the fact that all E825C physical functions in a given
+                * system are part of the same overall device.
+                */
+               return ICE_ADAPTER_INDEX_E825C;
+       default:
+               return pci_get_dsn(pdev) & ~ICE_ADAPTER_FIXED_INDEX;
+       }
+}
+
+static unsigned long ice_adapter_xa_index(struct pci_dev *pdev)
+{
+       u64 index = ice_adapter_index(pdev);
+
 #if BITS_PER_LONG == 64
-       return dsn;
+       return index;
 #else
-       return (u32)dsn ^ (u32)(dsn >> 32);
+       return (u32)index ^ (u32)(index >> 32);
 #endif
 }
 
-static struct ice_adapter *ice_adapter_new(u64 dsn)
+static struct ice_adapter *ice_adapter_new(struct pci_dev *pdev)
 {
        struct ice_adapter *adapter;
 
@@ -30,7 +59,7 @@ static struct ice_adapter *ice_adapter_new(u64 dsn)
        if (!adapter)
                return NULL;
 
-       adapter->device_serial_number = dsn;
+       adapter->index = ice_adapter_index(pdev);
        spin_lock_init(&adapter->ptp_gltsyn_time_lock);
        spin_lock_init(&adapter->txq_ctx_lock);
        refcount_set(&adapter->refcount, 1);
@@ -64,24 +93,23 @@ static void ice_adapter_free(struct ice_adapter *adapter)
  */
 struct ice_adapter *ice_adapter_get(struct pci_dev *pdev)
 {
-       u64 dsn = pci_get_dsn(pdev);
        struct ice_adapter *adapter;
        unsigned long index;
        int err;
 
-       index = ice_adapter_index(dsn);
+       index = ice_adapter_xa_index(pdev);
        scoped_guard(mutex, &ice_adapters_mutex) {
                err = xa_insert(&ice_adapters, index, NULL, GFP_KERNEL);
                if (err == -EBUSY) {
                        adapter = xa_load(&ice_adapters, index);
                        refcount_inc(&adapter->refcount);
-                       WARN_ON_ONCE(adapter->device_serial_number != dsn);
+                       WARN_ON_ONCE(adapter->index != ice_adapter_index(pdev));
                        return adapter;
                }
                if (err)
                        return ERR_PTR(err);
 
-               adapter = ice_adapter_new(dsn);
+               adapter = ice_adapter_new(pdev);
                if (!adapter)
                        return ERR_PTR(-ENOMEM);
                xa_store(&ice_adapters, index, adapter, GFP_KERNEL);
@@ -100,11 +128,10 @@ struct ice_adapter *ice_adapter_get(struct pci_dev *pdev)
  */
 void ice_adapter_put(struct pci_dev *pdev)
 {
-       u64 dsn = pci_get_dsn(pdev);
        struct ice_adapter *adapter;
        unsigned long index;
 
-       index = ice_adapter_index(dsn);
+       index = ice_adapter_xa_index(pdev);
        scoped_guard(mutex, &ice_adapters_mutex) {
                adapter = xa_load(&ice_adapters, index);
                if (WARN_ON(!adapter))
index db66d03c9f96f899ef18c7c7ab139a66db681a06..e95266c7f20bd29add4e3020ef6e9b6ad7a020e4 100644 (file)
@@ -33,7 +33,7 @@ struct ice_port_list {
  * @txq_ctx_lock: Spinlock protecting access to the GLCOMM_QTX_CNTX_CTL register
  * @ctrl_pf: Control PF of the adapter
  * @ports: Ports list
- * @device_serial_number: DSN cached for collision detection on 32bit systems
+ * @index: 64-bit index cached for collision detection on 32bit systems
  */
 struct ice_adapter {
        refcount_t refcount;
@@ -44,7 +44,7 @@ struct ice_adapter {
 
        struct ice_pf *ctrl_pf;
        struct ice_port_list ports;
-       u64 device_serial_number;
+       u64 index;
 };
 
 struct ice_adapter *ice_adapter_get(struct pci_dev *pdev);