#include "iwl-prph.h"
 #include "internal.h"
 
+#define TRANS_CFG_MARKER BIT(0)
+#define _IS_A(cfg, _struct) __builtin_types_compatible_p(typeof(cfg),  \
+                                                        struct _struct)
+extern int _invalid_type;
+#define _TRANS_CFG_MARKER(cfg)                                         \
+       (__builtin_choose_expr(_IS_A(cfg, iwl_cfg_trans_params),        \
+                              TRANS_CFG_MARKER,                        \
+        __builtin_choose_expr(_IS_A(cfg, iwl_cfg), 0, _invalid_type)))
+#define _ASSIGN_CFG(cfg) (_TRANS_CFG_MARKER(cfg) + (kernel_ulong_t)&(cfg))
+
 #define IWL_PCI_DEVICE(dev, subdev, cfg) \
        .vendor = PCI_VENDOR_ID_INTEL,  .device = (dev), \
        .subvendor = PCI_ANY_ID, .subdevice = (subdev), \
-       .driver_data = (kernel_ulong_t)&(cfg)
+       .driver_data = _ASSIGN_CFG(cfg)
 
 /* Hardware specific file defines the PCI IDs table for that hardware module */
 static const struct pci_device_id iwl_hw_card_ids[] = {
 
 static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
-       const struct iwl_cfg_trans_params *trans =
-               (struct iwl_cfg_trans_params *)(ent->driver_data);
+       const struct iwl_cfg_trans_params *trans;
        const struct iwl_cfg *cfg_7265d __maybe_unused = NULL;
        struct iwl_trans *iwl_trans;
        struct iwl_trans_pcie *trans_pcie;
        int i, ret;
+       const struct iwl_cfg *cfg;
+
+       trans = (void *)(ent->driver_data & ~TRANS_CFG_MARKER);
+
        /*
         * This is needed for backwards compatibility with the old
         * tables, so we don't need to change all the config structs
         * at the same time.  The cfg is used to compare with the old
         * full cfg structs.
         */
-       const struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data);
+       cfg = (void *)(ent->driver_data & ~TRANS_CFG_MARKER);
 
        /* make sure trans is the first element in iwl_cfg */
        BUILD_BUG_ON(offsetof(struct iwl_cfg, trans));
 
 #endif
        /*
-        * If we didn't set the cfg yet, assume the trans is actually
-        * a full cfg from the old tables.
+        * If we didn't set the cfg yet, the PCI ID table entry should have
+        * been a full config - if yes, use it, otherwise fail.
         */
-       if (!iwl_trans->cfg)
+       if (!iwl_trans->cfg) {
+               if (ent->driver_data & TRANS_CFG_MARKER) {
+                       pr_err("No config found for PCI dev %04x/%04x, rev=0x%x, rfid=0x%x\n",
+                              pdev->device, pdev->subsystem_device,
+                              iwl_trans->hw_rev, iwl_trans->hw_rf_id);
+                       ret = -EINVAL;
+                       goto out_free_trans;
+               }
                iwl_trans->cfg = cfg;
+       }
 
        /* if we don't have a name yet, copy name from the old cfg */
        if (!iwl_trans->name)