+#define ECORE_DORQ_ATTENTION_REASON_MASK (0xfffff)
+#define ECORE_DORQ_ATTENTION_OPAQUE_MASK (0xffff)
+#define ECORE_DORQ_ATTENTION_OPAQUE_SHIFT (0x0)
+#define ECORE_DORQ_ATTENTION_SIZE_MASK (0x7f)
+#define ECORE_DORQ_ATTENTION_SIZE_SHIFT (16)
+
+#define ECORE_DB_REC_COUNT 1000
+#define ECORE_DB_REC_INTERVAL 100
+
+static enum _ecore_status_t ecore_db_rec_flush_queue(struct ecore_hwfn *p_hwfn,
+ struct ecore_ptt *p_ptt)
+{
+ u32 count = ECORE_DB_REC_COUNT;
+ u32 usage = 1;
+
+ /* wait for usage to zero or count to run out. This is necessary since
+ * EDPM doorbell transactions can take multiple 64b cycles, and as such
+ * can "split" over the pci. Possibly, the doorbell drop can happen with
+ * half an EDPM in the queue and other half dropped. Another EDPM
+ * doorbell to the same address (from doorbell recovery mechanism or
+ * from the doorbelling entity) could have first half dropped and second
+ * half interperted as continuation of the first. To prevent such
+ * malformed doorbells from reaching the device, flush the queue before
+ * releaseing the overflow sticky indication.
+ */
+ while (count-- && usage) {
+ usage = ecore_rd(p_hwfn, p_ptt, DORQ_REG_PF_USAGE_CNT);
+ OSAL_UDELAY(ECORE_DB_REC_INTERVAL);
+ }
+
+ /* should have been depleted by now */
+ if (usage) {
+ DP_NOTICE(p_hwfn->p_dev, false,
+ "DB recovery: doorbell usage failed to zero after %d usec. usage was %x\n",
+ ECORE_DB_REC_INTERVAL * ECORE_DB_REC_COUNT, usage);
+ return ECORE_TIMEOUT;
+ }
+
+ return ECORE_SUCCESS;
+}
+
+enum _ecore_status_t ecore_db_rec_handler(struct ecore_hwfn *p_hwfn,
+ struct ecore_ptt *p_ptt)
+{
+ u32 overflow;
+ enum _ecore_status_t rc;
+
+ overflow = ecore_rd(p_hwfn, p_ptt, DORQ_REG_PF_OVFL_STICKY);
+ DP_NOTICE(p_hwfn, false, "PF Overflow sticky 0x%x\n", overflow);
+ if (!overflow) {
+ ecore_db_recovery_execute(p_hwfn, DB_REC_ONCE);
+ return ECORE_SUCCESS;
+ }
+
+ if (ecore_edpm_enabled(p_hwfn)) {
+ rc = ecore_db_rec_flush_queue(p_hwfn, p_ptt);
+ if (rc != ECORE_SUCCESS)
+ return rc;
+ }
+
+ /* flush any pedning (e)dpm as they may never arrive */
+ ecore_wr(p_hwfn, p_ptt, DORQ_REG_DPM_FORCE_ABORT, 0x1);
+
+ /* release overflow sticky indication (stop silently dropping
+ * everything)
+ */
+ ecore_wr(p_hwfn, p_ptt, DORQ_REG_PF_OVFL_STICKY, 0x0);
+
+ /* repeat all last doorbells (doorbell drop recovery) */
+ ecore_db_recovery_execute(p_hwfn, DB_REC_REAL_DEAL);
+
+ return ECORE_SUCCESS;
+}