goto err_disable_msix;
        }
 
+       err = nfp_resource_table_init(pf->cpp);
+       if (err)
+               goto err_cpp_free;
+
        pf->hwinfo = nfp_hwinfo_read(pf->cpp);
 
        dev_info(&pdev->dev, "Assembly: %s%s%s-%s CPLD: %s\n",
        vfree(pf->dumpspec);
 err_hwinfo_free:
        kfree(pf->hwinfo);
+err_cpp_free:
        nfp_cpp_free(pf->cpp);
 err_disable_msix:
        destroy_workqueue(pf->wq);
 
 /* MAC Statistics Accumulator */
 #define NFP_RESOURCE_MAC_STATISTICS    "mac.stat"
 
+int nfp_resource_table_init(struct nfp_cpp *cpp);
+
 struct nfp_resource *
 nfp_resource_acquire(struct nfp_cpp *cpp, const char *name);
 
 
 int nfp_cpp_mutex_lock(struct nfp_cpp_mutex *mutex);
 int nfp_cpp_mutex_unlock(struct nfp_cpp_mutex *mutex);
 int nfp_cpp_mutex_trylock(struct nfp_cpp_mutex *mutex);
+int nfp_cpp_mutex_reclaim(struct nfp_cpp *cpp, int target,
+                         unsigned long long address);
 
 /**
  * nfp_cppcore_pcie_unit() - Get PCI Unit of a CPP handle
 
        return (u32)interface << 16 | 0x0000;
 }
 
+static u32 nfp_mutex_owner(u32 val)
+{
+       return val >> 16;
+}
+
 static bool nfp_mutex_is_locked(u32 val)
 {
        return (val & 0xffff) == 0x000f;
 
        return nfp_mutex_is_locked(tmp) ? -EBUSY : -EINVAL;
 }
+
+/**
+ * nfp_cpp_mutex_reclaim() - Unlock mutex if held by local endpoint
+ * @cpp:       NFP CPP handle
+ * @target:    NFP CPP target ID (ie NFP_CPP_TARGET_CLS or NFP_CPP_TARGET_MU)
+ * @address:   Offset into the address space of the NFP CPP target ID
+ *
+ * Release lock if held by local system.  Extreme care is advised, call only
+ * when no local lock users can exist.
+ *
+ * Return:      0 if the lock was OK, 1 if locked by us, -errno on invalid mutex
+ */
+int nfp_cpp_mutex_reclaim(struct nfp_cpp *cpp, int target,
+                         unsigned long long address)
+{
+       const u32 mur = NFP_CPP_ID(target, 3, 0);       /* atomic_read */
+       const u32 muw = NFP_CPP_ID(target, 4, 0);       /* atomic_write */
+       u16 interface = nfp_cpp_interface(cpp);
+       int err;
+       u32 tmp;
+
+       err = nfp_cpp_mutex_validate(interface, &target, address);
+       if (err)
+               return err;
+
+       /* Check lock */
+       err = nfp_cpp_readl(cpp, mur, address, &tmp);
+       if (err < 0)
+               return err;
+
+       if (nfp_mutex_is_unlocked(tmp) || nfp_mutex_owner(tmp) != interface)
+               return 0;
+
+       /* Bust the lock */
+       err = nfp_cpp_writel(cpp, muw, address, nfp_mutex_unlocked(interface));
+       if (err < 0)
+               return err;
+
+       return 1;
+}
 
 {
        return res->size;
 }
+
+/**
+ * nfp_resource_table_init() - Run initial checks on the resource table
+ * @cpp:       NFP CPP handle
+ *
+ * Start-of-day init procedure for resource table.  Must be called before
+ * any local resource table users may exist.
+ *
+ * Return: 0 on success, -errno on failure
+ */
+int nfp_resource_table_init(struct nfp_cpp *cpp)
+{
+       struct nfp_cpp_mutex *dev_mutex;
+       int i, err;
+
+       err = nfp_cpp_mutex_reclaim(cpp, NFP_RESOURCE_TBL_TARGET,
+                                   NFP_RESOURCE_TBL_BASE);
+       if (err < 0) {
+               nfp_err(cpp, "Error: failed to reclaim resource table mutex\n");
+               return err;
+       }
+       if (err)
+               nfp_warn(cpp, "Warning: busted main resource table mutex\n");
+
+       dev_mutex = nfp_cpp_mutex_alloc(cpp, NFP_RESOURCE_TBL_TARGET,
+                                       NFP_RESOURCE_TBL_BASE,
+                                       NFP_RESOURCE_TBL_KEY);
+       if (!dev_mutex)
+               return -ENOMEM;
+
+       if (nfp_cpp_mutex_lock(dev_mutex)) {
+               nfp_err(cpp, "Error: failed to claim resource table mutex\n");
+               nfp_cpp_mutex_free(dev_mutex);
+               return -EINVAL;
+       }
+
+       /* Resource 0 is the dev_mutex, start from 1 */
+       for (i = 1; i < NFP_RESOURCE_TBL_ENTRIES; i++) {
+               u64 addr = NFP_RESOURCE_TBL_BASE +
+                       sizeof(struct nfp_resource_entry) * i;
+
+               err = nfp_cpp_mutex_reclaim(cpp, NFP_RESOURCE_TBL_TARGET, addr);
+               if (err < 0) {
+                       nfp_err(cpp,
+                               "Error: failed to reclaim resource %d mutex\n",
+                               i);
+                       goto err_unlock;
+               }
+               if (err)
+                       nfp_warn(cpp, "Warning: busted resource %d mutex\n", i);
+       }
+
+       err = 0;
+err_unlock:
+       nfp_cpp_mutex_unlock(dev_mutex);
+       nfp_cpp_mutex_free(dev_mutex);
+
+       return err;
+}