iwlwifi: pcie: provide a way to stop configuration if it is forbidden
authorHaim Dreyfuss <haim.dreyfuss@intel.com>
Mon, 20 Jul 2015 11:16:21 +0000 (14:16 +0300)
committerEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Tue, 4 Aug 2015 07:11:49 +0000 (10:11 +0300)
The firmware debug infrastructure allows the user to
provide a firmware that will toggle a few registers to
configure the debugging capabilities.
On certain devices, certain operations are forbidden.
Executing a forbidden operation will cause the hardware to
die in a way that only driver unload / load will bring it
back to life.
Fortunately, there is a way to know in advance if those
operations will be accepted by the device. This is where
the new PRPH_BLOCKBIT operation plays its role. If the bit
X from PRPH register Y is set, then we should prevent any
further register configuration. When that happens, drop a
line in the kernel log since this is really an error state:
the user won't have his device configured as he expected.
Add operations that will be used in the future:
INDIRECT_ASSIGN, INDIRECT_SETBIT, and INDIRECT_CLEARBIT.

Other debugging configurations (such as destination
configuration for the monitor) will take place in any case.

Signed-off-by: Haim Dreyfuss <haim.dreyfuss@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
drivers/net/wireless/iwlwifi/iwl-fw-file.h
drivers/net/wireless/iwlwifi/pcie/trans.c

index f99ec4e22052a62de76be848a4e28b499b13de58..884825c705336ee8937bb214a36e81e05e94cb17 100644 (file)
@@ -412,6 +412,12 @@ enum iwl_fw_dbg_reg_operator {
        PRPH_ASSIGN,
        PRPH_SETBIT,
        PRPH_CLEARBIT,
+
+       INDIRECT_ASSIGN,
+       INDIRECT_SETBIT,
+       INDIRECT_CLEARBIT,
+
+       PRPH_BLOCKBIT,
 };
 
 /**
index 88ab79fc6249578b0e2a20a726664d2703fa700d..46e900e860e8d61f44b1ffd7ef467c31ccc3b823 100644 (file)
@@ -881,6 +881,14 @@ static void iwl_pcie_apply_destination(struct iwl_trans *trans)
                case PRPH_CLEARBIT:
                        iwl_clear_bits_prph(trans, addr, BIT(val));
                        break;
+               case PRPH_BLOCKBIT:
+                       if (iwl_read_prph(trans, addr) & BIT(val)) {
+                               IWL_ERR(trans,
+                                       "BIT(%u) in address 0x%x is 1, stopping FW configuration\n",
+                                       val, addr);
+                               goto monitor;
+                       }
+                       break;
                default:
                        IWL_ERR(trans, "FW debug - unknown OP %d\n",
                                dest->reg_ops[i].op);
@@ -888,6 +896,7 @@ static void iwl_pcie_apply_destination(struct iwl_trans *trans)
                }
        }
 
+monitor:
        if (dest->monitor_mode == EXTERNAL_MODE && trans_pcie->fw_mon_size) {
                iwl_write_prph(trans, le32_to_cpu(dest->base_reg),
                               trans_pcie->fw_mon_phys >> dest->base_shift);