static void want_buffer(struct ipath_devdata *dd, struct ipath_qp *qp) { if (!(dd->ipath_flags & IPATH_HAS_SEND_DMA) || qp->ibqp.qp_type == IB_QPT_SMI) { unsigned long flags; spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags); dd->ipath_sendctrl |= INFINIPATH_S_PIOINTBUFAVAIL; ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, dd->ipath_sendctrl); ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch); spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags); } }
static void ipath_chk_errormask(struct ipath_devdata *dd) { static u32 fixed; u32 ctrl; unsigned long errormask; unsigned long hwerrs; if (!dd->ipath_errormask || !(dd->ipath_flags & IPATH_INITTED)) return; errormask = ipath_read_kreg64(dd, dd->ipath_kregs->kr_errormask); if (errormask == dd->ipath_errormask) return; fixed++; hwerrs = ipath_read_kreg64(dd, dd->ipath_kregs->kr_hwerrstatus); ctrl = ipath_read_kreg32(dd, dd->ipath_kregs->kr_control); ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask, dd->ipath_errormask); if ((hwerrs & dd->ipath_hwerrmask) || (ctrl & INFINIPATH_C_FREEZEMODE)) { /* force re-interrupt of pending events, just in case */ ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrclear, 0ULL); ipath_write_kreg(dd, dd->ipath_kregs->kr_errorclear, 0ULL); ipath_write_kreg(dd, dd->ipath_kregs->kr_intclear, 0ULL); dev_info(&dd->pcidev->dev, "errormask fixed(%u) %lx -> %lx, ctrl %x hwerr %lx\n", fixed, errormask, (unsigned long)dd->ipath_errormask, ctrl, hwerrs); } else ipath_dbg("errormask fixed(%u) %lx -> %lx, no freeze\n", fixed, errormask, (unsigned long)dd->ipath_errormask); }
/* * Lemma to deal with race condition of write..read to epb regs */ static int epb_trans(struct ipath_devdata *dd, u16 reg, u64 i_val, u64 *o_vp) { int tries; u64 transval; ipath_write_kreg(dd, reg, i_val); /* Throw away first read, as RDY bit may be stale */ transval = ipath_read_kreg64(dd, reg); for (tries = EPB_TRANS_TRIES; tries; --tries) { transval = ipath_read_kreg32(dd, reg); if (transval & EPB_TRANS_RDY) break; udelay(5); } if (transval & EPB_TRANS_ERR) return -1; if (tries > 0 && o_vp) *o_vp = transval; return tries; }
static void ipath_sd_trimdone_monitor(struct ipath_devdata *dd, const char *where) { int ret, chn, baduns; u64 val; if (!where) where = "?"; /* give time for reset to settle out in EPB */ udelay(2); ret = ipath_resync_ibepb(dd); if (ret < 0) ipath_dev_err(dd, "not able to re-sync IB EPB (%s)\n", where); /* Do "sacrificial read" to get EPB in sane state after reset */ ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, IB_CTRL2(0), 0, 0); if (ret < 0) ipath_dev_err(dd, "Failed TRIMDONE 1st read, (%s)\n", where); /* Check/show "summary" Trim-done bit in IBCStatus */ val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_ibcstatus); if (val & (1ULL << 11)) ipath_cdbg(VERBOSE, "IBCS TRIMDONE set (%s)\n", where); else ipath_dev_err(dd, "IBCS TRIMDONE clear (%s)\n", where); udelay(2); ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, IB_MPREG6, 0x80, 0x80); if (ret < 0) ipath_dev_err(dd, "Failed Dummy RMW, (%s)\n", where); udelay(10); baduns = 0; for (chn = 3; chn >= 0; --chn) { /* Read CTRL reg for each channel to check TRIMDONE */ ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, IB_CTRL2(chn), 0, 0); if (ret < 0) ipath_dev_err(dd, "Failed checking TRIMDONE, chn %d" " (%s)\n", chn, where); if (!(ret & 0x10)) { int probe; baduns |= (1 << chn); ipath_dev_err(dd, "TRIMDONE cleared on chn %d (%02X)." " (%s)\n", chn, ret, where); probe = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, IB_PGUDP(0), 0, 0); ipath_dev_err(dd, "probe is %d (%02X)\n", probe, probe); probe = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, IB_CTRL2(chn), 0, 0); ipath_dev_err(dd, "re-read: %d (%02X)\n", probe, probe); ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, IB_CTRL2(chn), 0x10, 0x10); if (ret < 0) ipath_dev_err(dd, "Err on TRIMDONE rewrite1\n"); } } for (chn = 3; chn >= 0; --chn) { /* Read CTRL reg for each channel to check TRIMDONE */ if (baduns & (1 << chn)) { ipath_dev_err(dd, "Reseting TRIMDONE on chn %d (%s)\n", chn, where); ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, IB_CTRL2(chn), 0x10, 0x10); if (ret < 0) ipath_dev_err(dd, "Failed re-setting " "TRIMDONE, chn %d (%s)\n", chn, where); } } }
/* * Localize the stuff that should be done to change IB uC reset * returns <0 for errors. */ static int ipath_ibsd_reset(struct ipath_devdata *dd, int assert_rst) { u64 rst_val; int ret = 0; unsigned long flags; rst_val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_ibserdesctrl); if (assert_rst) { /* * Vendor recommends "interrupting" uC before reset, to * minimize possible glitches. */ spin_lock_irqsave(&dd->ipath_sdepb_lock, flags); epb_access(dd, IB_7220_SERDES, 1); rst_val |= 1ULL; /* Squelch possible parity error from _asserting_ reset */ ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask, dd->ipath_hwerrmask & ~INFINIPATH_HWE_IB_UC_MEMORYPARITYERR); ipath_write_kreg(dd, dd->ipath_kregs->kr_ibserdesctrl, rst_val); /* flush write, delay to ensure it took effect */ ipath_read_kreg32(dd, dd->ipath_kregs->kr_scratch); udelay(2); /* once it's reset, can remove interrupt */ epb_access(dd, IB_7220_SERDES, -1); spin_unlock_irqrestore(&dd->ipath_sdepb_lock, flags); } else { /* * Before we de-assert reset, we need to deal with * possible glitch on the Parity-error line. * Suppress it around the reset, both in chip-level * hwerrmask and in IB uC control reg. uC will allow * it again during startup. */ u64 val; rst_val &= ~(1ULL); ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask, dd->ipath_hwerrmask & ~INFINIPATH_HWE_IB_UC_MEMORYPARITYERR); ret = ipath_resync_ibepb(dd); if (ret < 0) ipath_dev_err(dd, "unable to re-sync IB EPB\n"); /* set uC control regs to suppress parity errs */ ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, IB_MPREG5, 1, 1); if (ret < 0) goto bail; /* IB uC code past Version 1.32.17 allow suppression of wdog */ ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, IB_MPREG6, 0x80, 0x80); if (ret < 0) { ipath_dev_err(dd, "Failed to set WDOG disable\n"); goto bail; } ipath_write_kreg(dd, dd->ipath_kregs->kr_ibserdesctrl, rst_val); /* flush write, delay for startup */ ipath_read_kreg32(dd, dd->ipath_kregs->kr_scratch); udelay(1); /* clear, then re-enable parity errs */ ipath_sd7220_clr_ibpar(dd); val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_hwerrstatus); if (val & INFINIPATH_HWE_IB_UC_MEMORYPARITYERR) { ipath_dev_err(dd, "IBUC Parity still set after RST\n"); dd->ipath_hwerrmask &= ~INFINIPATH_HWE_IB_UC_MEMORYPARITYERR; } ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask, dd->ipath_hwerrmask); } bail: return ret; }