int ipath_diag_add(struct ipath_devdata *dd) { char name[16]; int ret = 0; if (atomic_inc_return(&diagpkt_count) == 1) { ret = ipath_cdev_init(IPATH_DIAGPKT_MINOR, "ipath_diagpkt", &diagpkt_file_ops, &diagpkt_cdev, &diagpkt_class_dev); if (ret) { ipath_dev_err(dd, "Couldn't create ipath_diagpkt " "device: %d", ret); goto done; } } snprintf(name, sizeof(name), "ipath_diag%d", dd->ipath_unit); ret = ipath_cdev_init(IPATH_DIAG_MINOR_BASE + dd->ipath_unit, name, &diag_file_ops, &dd->diag_cdev, &dd->diag_class_dev); if (ret) ipath_dev_err(dd, "Couldn't create %s device: %d", name, ret); done: return ret; }
static ssize_t store_rx_pol_inv(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct ipath_devdata *dd = dev_get_drvdata(dev); int ret, r; u16 val; ret = ipath_parse_ushort(buf, &val); if (ret < 0) goto invalid; r = ipath_set_rx_pol_inv(dd, val); if (r < 0) { ret = r; goto bail; } goto bail; invalid: ipath_dev_err(dd, "attempt to set invalid Rx Polarity invert\n"); bail: return ret; }
static ssize_t store_link_state(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct ipath_devdata *dd = dev_get_drvdata(dev); int ret, r; u16 state; ret = ipath_parse_ushort(buf, &state); if (ret < 0) goto invalid; r = ipath_set_linkstate(dd, state); if (r < 0) { ret = r; goto bail; } goto bail; invalid: ipath_dev_err(dd, "attempt to set invalid link state\n"); bail: return ret; }
static ssize_t store_lid(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct ipath_devdata *dd = dev_get_drvdata(dev); u16 lid = 0; int ret; ret = ipath_parse_ushort(buf, &lid); if (ret < 0) goto invalid; if (lid == 0 || lid >= IPATH_MULTICAST_LID_BASE) { ret = -EINVAL; goto invalid; } ipath_set_lid(dd, lid, 0); goto bail; invalid: ipath_dev_err(dd, "attempt to set invalid LID 0x%x\n", lid); bail: return ret; }
static ssize_t store_enabled(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct ipath_devdata *dd = dev_get_drvdata(dev); ssize_t ret; u16 enable = 0; ret = ipath_parse_ushort(buf, &enable); if (ret < 0) { ipath_dev_err(dd, "attempt to use non-numeric on enable\n"); goto bail; } if (enable) { if (!(dd->ipath_flags & IPATH_DISABLED)) goto bail; dev_info(dev, "Enabling unit %d\n", dd->ipath_unit); /* same as post-reset */ ret = ipath_init_chip(dd, 1); if (ret) ipath_dev_err(dd, "Failed to enable unit %d\n", dd->ipath_unit); else { dd->ipath_flags &= ~IPATH_DISABLED; *dd->ipath_statusp &= ~IPATH_STATUS_ADMIN_DISABLED; } } else if (!(dd->ipath_flags & IPATH_DISABLED)) { dev_info(dev, "Disabling unit %d\n", dd->ipath_unit); ipath_shutdown_device(dd); dd->ipath_flags |= IPATH_DISABLED; *dd->ipath_statusp |= IPATH_STATUS_ADMIN_DISABLED; } bail: return ret; }
static ssize_t flash_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { struct ipath_devdata *dd; ssize_t ret; loff_t pos; char *tmp; pos = *ppos; if ( pos < 0) { ret = -EINVAL; goto bail; } if (pos >= sizeof(struct ipath_flash)) { ret = 0; goto bail; } if (count > sizeof(struct ipath_flash) - pos) count = sizeof(struct ipath_flash) - pos; tmp = kmalloc(count, GFP_KERNEL); if (!tmp) { ret = -ENOMEM; goto bail; } dd = file->f_path.dentry->d_inode->i_private; if (ipath_eeprom_read(dd, pos, tmp, count)) { ipath_dev_err(dd, "failed to read from flash\n"); ret = -ENXIO; goto bail_tmp; } if (copy_to_user(buf, tmp, count)) { ret = -EFAULT; goto bail_tmp; } *ppos = pos + count; ret = count; bail_tmp: kfree(tmp); bail: return ret; }
static ssize_t flash_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { struct ipath_devdata *dd; ssize_t ret; loff_t pos; char *tmp; pos = *ppos; if (pos != 0) { ret = -EINVAL; goto bail; } if (count != sizeof(struct ipath_flash)) { ret = -EINVAL; goto bail; } tmp = kmalloc(count, GFP_KERNEL); if (!tmp) { ret = -ENOMEM; goto bail; } if (copy_from_user(tmp, buf, count)) { ret = -EFAULT; goto bail_tmp; } dd = file->f_path.dentry->d_inode->i_private; if (ipath_eeprom_write(dd, pos, tmp, count)) { ret = -ENXIO; ipath_dev_err(dd, "failed to write to flash\n"); goto bail_tmp; } *ppos = pos + count; ret = count; bail_tmp: kfree(tmp); bail: return ret; }
static int ipath_resync_ibepb(struct ipath_devdata *dd) { int ret, pat, tries, chn; u32 loc; ret = -1; chn = 0; for (tries = 0; tries < (4 * IBSD_RESYNC_TRIES); ++tries) { loc = IB_PGUDP(chn); ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, loc, 0, 0); if (ret < 0) { ipath_dev_err(dd, "Failed read in resync\n"); continue; } if (ret != 0xF0 && ret != 0x55 && tries == 0) ipath_dev_err(dd, "unexpected pattern in resync\n"); pat = ret ^ 0xA5; /* alternate F0 and 55 */ ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, loc, pat, 0xFF); if (ret < 0) { ipath_dev_err(dd, "Failed write in resync\n"); continue; } ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, loc, 0, 0); if (ret < 0) { ipath_dev_err(dd, "Failed re-read in resync\n"); continue; } if (ret != pat) { ipath_dev_err(dd, "Failed compare1 in resync\n"); continue; } loc = IB_CMUDONE(chn); ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, loc, 0, 0); if (ret < 0) { ipath_dev_err(dd, "Failed CMUDONE rd in resync\n"); continue; } if ((ret & 0x70) != ((chn << 4) | 0x40)) { ipath_dev_err(dd, "Bad CMUDONE value %02X, chn %d\n", ret, chn); continue; } if (++chn == 4) break; /* Success */ } ipath_cdbg(VERBOSE, "Resync in %d tries\n", tries); return (ret > 0) ? 0 : ret; }
static ssize_t store_guid(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct ipath_devdata *dd = dev_get_drvdata(dev); ssize_t ret; unsigned short guid[8]; __be64 new_guid; u8 *ng; int i; if (sscanf(buf, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx", &guid[0], &guid[1], &guid[2], &guid[3], &guid[4], &guid[5], &guid[6], &guid[7]) != 8) goto invalid; ng = (u8 *) &new_guid; for (i = 0; i < 8; i++) { if (guid[i] > 0xff) goto invalid; ng[i] = guid[i]; } if (new_guid == 0) goto invalid; dd->ipath_guid = new_guid; dd->ipath_nguid = 1; ret = strlen(buf); goto bail; invalid: ipath_dev_err(dd, "attempt to set invalid GUID\n"); ret = -EINVAL; bail: return ret; }
static ssize_t store_mlid(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct ipath_devdata *dd = dev_get_drvdata(dev); u16 mlid; int ret; ret = ipath_parse_ushort(buf, &mlid); if (ret < 0 || mlid < IPATH_MULTICAST_LID_BASE) goto invalid; dd->ipath_mlid = mlid; goto bail; invalid: ipath_dev_err(dd, "attempt to set invalid MLID\n"); bail: return ret; }
static ssize_t flash_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { struct ipath_devdata *dd; ssize_t ret; loff_t pos; char *tmp; pos = *ppos; if (pos != 0) { ret = -EINVAL; goto bail; } if (count != sizeof(struct ipath_flash)) { ret = -EINVAL; goto bail; } tmp = memdup_user(buf, count); if (IS_ERR(tmp)) return PTR_ERR(tmp); dd = file_inode(file)->i_private; if (ipath_eeprom_write(dd, pos, tmp, count)) { ret = -ENXIO; ipath_dev_err(dd, "failed to write to flash\n"); goto bail_tmp; } *ppos = pos + count; ret = count; bail_tmp: kfree(tmp); bail: return ret; }
void ipath_sd7220_clr_ibpar(struct ipath_devdata *dd) { int ret; /* clear, then re-enable parity errs */ ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, IB_MPREG6, UC_PAR_CLR_D, UC_PAR_CLR_M); if (ret < 0) { ipath_dev_err(dd, "Failed clearing IBSerDes Parity err\n"); goto bail; } ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, IB_MPREG6, 0, UC_PAR_CLR_M); ipath_read_kreg32(dd, dd->ipath_kregs->kr_scratch); udelay(4); ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrclear, INFINIPATH_HWE_IB_UC_MEMORYPARITYERR); ipath_read_kreg32(dd, dd->ipath_kregs->kr_scratch); bail: return; }
static ssize_t store_mtu(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct ipath_devdata *dd = dev_get_drvdata(dev); ssize_t ret; u16 mtu = 0; int r; ret = ipath_parse_ushort(buf, &mtu); if (ret < 0) goto invalid; r = ipath_set_mtu(dd, mtu); if (r < 0) ret = r; goto bail; invalid: ipath_dev_err(dd, "attempt to set invalid MTU\n"); bail: return ret; }
/** * ipath_get_faststats - get word counters from chip before they overflow * @opaque - contains a pointer to the infinipath device ipath_devdata * * called from add_timer */ void ipath_get_faststats(unsigned long opaque) { struct ipath_devdata *dd = (struct ipath_devdata *) opaque; u32 val; static unsigned cnt; /* * don't access the chip while running diags, or memory diags can * fail */ if (!dd->ipath_kregbase || !(dd->ipath_flags & IPATH_PRESENT) || ipath_diag_inuse) /* but re-arm the timer, for diags case; won't hurt other */ goto done; if (dd->ipath_flags & IPATH_32BITCOUNTERS) { ipath_snap_cntr(dd, dd->ipath_cregs->cr_wordsendcnt); ipath_snap_cntr(dd, dd->ipath_cregs->cr_wordrcvcnt); ipath_snap_cntr(dd, dd->ipath_cregs->cr_pktsendcnt); ipath_snap_cntr(dd, dd->ipath_cregs->cr_pktrcvcnt); } ipath_qcheck(dd); /* * deal with repeat error suppression. Doesn't really matter if * last error was almost a full interval ago, or just a few usecs * ago; still won't get more than 2 per interval. We may want * longer intervals for this eventually, could do with mod, counter * or separate timer. Also see code in ipath_handle_errors() and * ipath_handle_hwerrors(). */ if (dd->ipath_lasterror) dd->ipath_lasterror = 0; if (dd->ipath_lasthwerror) dd->ipath_lasthwerror = 0; if ((dd->ipath_maskederrs & ~dd->ipath_ignorederrs) && time_after(jiffies, dd->ipath_unmasktime)) { char ebuf[256]; ipath_decode_err(ebuf, sizeof ebuf, (dd->ipath_maskederrs & ~dd-> ipath_ignorederrs)); if ((dd->ipath_maskederrs & ~dd->ipath_ignorederrs) & ~(INFINIPATH_E_RRCVEGRFULL | INFINIPATH_E_RRCVHDRFULL)) ipath_dev_err(dd, "Re-enabling masked errors " "(%s)\n", ebuf); else { /* * rcvegrfull and rcvhdrqfull are "normal", for some * types of processes (mostly benchmarks) that send * huge numbers of messages, while not processing * them. So only complain about these at debug * level. */ ipath_dbg("Disabling frequent queue full errors " "(%s)\n", ebuf); } dd->ipath_maskederrs = dd->ipath_ignorederrs; ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask, ~dd->ipath_maskederrs); } /* limit qfull messages to ~one per minute per port */ if ((++cnt & 0x10)) { for (val = dd->ipath_cfgports - 1; ((int)val) >= 0; val--) { if (dd->ipath_lastegrheads[val] != -1) dd->ipath_lastegrheads[val] = -1; if (dd->ipath_lastrcvhdrqtails[val] != -1) dd->ipath_lastrcvhdrqtails[val] = -1; } } if (dd->ipath_nosma_bufs) { dd->ipath_nosma_secs += 5; if (dd->ipath_nosma_secs >= 30) { ipath_cdbg(SMA, "No SMA bufs avail %u seconds; " "cancelling pending sends\n", dd->ipath_nosma_secs); /* * issue an abort as well, in case we have a packet * stuck in launch fifo. This could corrupt an * outgoing user packet in the worst case, * but this is a pretty catastrophic, anyway. */ ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, INFINIPATH_S_ABORT); ipath_disarm_piobufs(dd, dd->ipath_lastport_piobuf, dd->ipath_piobcnt2k + dd->ipath_piobcnt4k - dd->ipath_lastport_piobuf); /* start again, if necessary */ dd->ipath_nosma_secs = 0; } else ipath_cdbg(SMA, "No SMA bufs avail %u tries, " "after %u seconds\n", dd->ipath_nosma_bufs, dd->ipath_nosma_secs); } done: mod_timer(&dd->ipath_stats_timer, jiffies + HZ * 5); }
u64 ipath_snap_cntr(struct ipath_devdata *dd, ipath_creg creg) { u32 val, reg64 = 0; u64 val64; unsigned long t0, t1; u64 ret; unsigned long flags; t0 = jiffies; /* If fast increment counters are only 32 bits, snapshot them, * and maintain them as 64bit values in the driver */ if (!(dd->ipath_flags & IPATH_32BITCOUNTERS) && (creg == dd->ipath_cregs->cr_wordsendcnt || creg == dd->ipath_cregs->cr_wordrcvcnt || creg == dd->ipath_cregs->cr_pktsendcnt || creg == dd->ipath_cregs->cr_pktrcvcnt)) { val64 = ipath_read_creg(dd, creg); val = val64 == ~0ULL ? ~0U : 0; reg64 = 1; } else /* val64 just to keep gcc quiet... */ val64 = val = ipath_read_creg32(dd, creg); /* * See if a second has passed. This is just a way to detect things * that are quite broken. Normally this should take just a few * cycles (the check is for long enough that we don't care if we get * pre-empted.) An Opteron HT O read timeout is 4 seconds with * normal NB values */ t1 = jiffies; if (time_before(t0 + HZ, t1) && val == -1) { ipath_dev_err(dd, "Error! Read counter 0x%x timed out\n", creg); ret = 0ULL; goto bail; } if (reg64) { ret = val64; goto bail; } if (creg == dd->ipath_cregs->cr_wordsendcnt) { if (val != dd->ipath_lastsword) { dd->ipath_sword += val - dd->ipath_lastsword; spin_lock_irqsave(&dd->ipath_eep_st_lock, flags); dd->ipath_traffic_wds += val - dd->ipath_lastsword; spin_unlock_irqrestore(&dd->ipath_eep_st_lock, flags); dd->ipath_lastsword = val; } val64 = dd->ipath_sword; } else if (creg == dd->ipath_cregs->cr_wordrcvcnt) { if (val != dd->ipath_lastrword) { dd->ipath_rword += val - dd->ipath_lastrword; spin_lock_irqsave(&dd->ipath_eep_st_lock, flags); dd->ipath_traffic_wds += val - dd->ipath_lastrword; spin_unlock_irqrestore(&dd->ipath_eep_st_lock, flags); dd->ipath_lastrword = val; } val64 = dd->ipath_rword; } else if (creg == dd->ipath_cregs->cr_pktsendcnt) { if (val != dd->ipath_lastspkts) { dd->ipath_spkts += val - dd->ipath_lastspkts; dd->ipath_lastspkts = val; } val64 = dd->ipath_spkts; } else if (creg == dd->ipath_cregs->cr_pktrcvcnt) { if (val != dd->ipath_lastrpkts) { dd->ipath_rpkts += val - dd->ipath_lastrpkts; dd->ipath_lastrpkts = val; } val64 = dd->ipath_rpkts; } else val64 = (u64) val; ret = val64; bail: return ret; }
/** * ipath_get_faststats - get word counters from chip before they overflow * @opaque - contains a pointer to the infinipath device ipath_devdata * * called from add_timer */ void ipath_get_faststats(unsigned long opaque) { struct ipath_devdata *dd = (struct ipath_devdata *) opaque; u32 val; static unsigned cnt; unsigned long flags; /* * don't access the chip while running diags, or memory diags can * fail */ if (!dd->ipath_kregbase || !(dd->ipath_flags & IPATH_INITTED) || ipath_diag_inuse) /* but re-arm the timer, for diags case; won't hurt other */ goto done; /* * We now try to maintain a "active timer", based on traffic * exceeding a threshold, so we need to check the word-counts * even if they are 64-bit. */ ipath_snap_cntr(dd, dd->ipath_cregs->cr_wordsendcnt); ipath_snap_cntr(dd, dd->ipath_cregs->cr_wordrcvcnt); spin_lock_irqsave(&dd->ipath_eep_st_lock, flags); if (dd->ipath_traffic_wds >= IPATH_TRAFFIC_ACTIVE_THRESHOLD) atomic_add(5, &dd->ipath_active_time); /* S/B #define */ dd->ipath_traffic_wds = 0; spin_unlock_irqrestore(&dd->ipath_eep_st_lock, flags); if (dd->ipath_flags & IPATH_32BITCOUNTERS) { ipath_snap_cntr(dd, dd->ipath_cregs->cr_pktsendcnt); ipath_snap_cntr(dd, dd->ipath_cregs->cr_pktrcvcnt); } ipath_qcheck(dd); /* * deal with repeat error suppression. Doesn't really matter if * last error was almost a full interval ago, or just a few usecs * ago; still won't get more than 2 per interval. We may want * longer intervals for this eventually, could do with mod, counter * or separate timer. Also see code in ipath_handle_errors() and * ipath_handle_hwerrors(). */ if (dd->ipath_lasterror) dd->ipath_lasterror = 0; if (dd->ipath_lasthwerror) dd->ipath_lasthwerror = 0; if (dd->ipath_maskederrs && time_after(jiffies, dd->ipath_unmasktime)) { char ebuf[256]; int iserr; iserr = ipath_decode_err(ebuf, sizeof ebuf, dd->ipath_maskederrs); if (dd->ipath_maskederrs & ~(INFINIPATH_E_RRCVEGRFULL | INFINIPATH_E_RRCVHDRFULL | INFINIPATH_E_PKTERRS )) ipath_dev_err(dd, "Re-enabling masked errors " "(%s)\n", ebuf); else { /* * rcvegrfull and rcvhdrqfull are "normal", for some * types of processes (mostly benchmarks) that send * huge numbers of messages, while not processing * them. So only complain about these at debug * level. */ if (iserr) ipath_dbg("Re-enabling queue full errors (%s)\n", ebuf); else ipath_cdbg(ERRPKT, "Re-enabling packet" " problem interrupt (%s)\n", ebuf); } /* re-enable masked errors */ dd->ipath_errormask |= dd->ipath_maskederrs; ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask, dd->ipath_errormask); dd->ipath_maskederrs = 0; } /* limit qfull messages to ~one per minute per port */ if ((++cnt & 0x10)) { for (val = dd->ipath_cfgports - 1; ((int)val) >= 0; val--) { if (dd->ipath_lastegrheads[val] != -1) dd->ipath_lastegrheads[val] = -1; if (dd->ipath_lastrcvhdrqtails[val] != -1) dd->ipath_lastrcvhdrqtails[val] = -1; } } ipath_chk_errormask(dd); done: mod_timer(&dd->ipath_stats_timer, jiffies + HZ * 5); }
/* * 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; }
/* * Below is portion of IBA7220-specific bringup_serdes() that actually * deals with registers and memory within the SerDes itself. * Post IB uC code version 1.32.17, was_reset being 1 is not really * informative, so we double-check. */ int ipath_sd7220_init(struct ipath_devdata *dd, int was_reset) { int ret = 1; /* default to failure */ int first_reset; int val_stat; if (!was_reset) { /* entered with reset not asserted, we need to do it */ ipath_ibsd_reset(dd, 1); ipath_sd_trimdone_monitor(dd, "Driver-reload"); } /* Substitute our deduced value for was_reset */ ret = ipath_ibsd_ucode_loaded(dd); if (ret < 0) { ret = 1; goto done; } first_reset = !ret; /* First reset if IBSD uCode not yet loaded */ /* * Alter some regs per vendor latest doc, reset-defaults * are not right for IB. */ ret = ipath_sd_early(dd); if (ret < 0) { ipath_dev_err(dd, "Failed to set IB SERDES early defaults\n"); ret = 1; goto done; } /* * Set DAC manual trim IB. * We only do this once after chip has been reset (usually * same as once per system boot). */ if (first_reset) { ret = ipath_sd_dactrim(dd); if (ret < 0) { ipath_dev_err(dd, "Failed IB SERDES DAC trim\n"); ret = 1; goto done; } } /* * Set various registers (DDS and RXEQ) that will be * controlled by IBC (in 1.2 mode) to reasonable preset values * Calling the "internal" version avoids the "check for needed" * and "trimdone monitor" that might be counter-productive. */ ret = ipath_internal_presets(dd); if (ret < 0) { ipath_dev_err(dd, "Failed to set IB SERDES presets\n"); ret = 1; goto done; } ret = ipath_sd_trimself(dd, 0x80); if (ret < 0) { ipath_dev_err(dd, "Failed to set IB SERDES TRIMSELF\n"); ret = 1; goto done; } /* Load image, then try to verify */ ret = 0; /* Assume success */ if (first_reset) { int vfy; int trim_done; ipath_dbg("SerDes uC was reset, reloading PRAM\n"); ret = ipath_sd7220_ib_load(dd); if (ret < 0) { ipath_dev_err(dd, "Failed to load IB SERDES image\n"); ret = 1; goto done; } /* Loaded image, try to verify */ vfy = ipath_sd7220_ib_vfy(dd); if (vfy != ret) { ipath_dev_err(dd, "SERDES PRAM VFY failed\n"); ret = 1; goto done; } /* * Loaded and verified. Almost good... * hold "success" in ret */ ret = 0; /* * Prev steps all worked, continue bringup * De-assert RESET to uC, only in first reset, to allow * trimming. * * Since our default setup sets START_EQ1 to * PRESET, we need to clear that for this very first run. */ ret = ibsd_mod_allchnls(dd, START_EQ1(0), 0, 0x38); if (ret < 0) { ipath_dev_err(dd, "Failed clearing START_EQ1\n"); ret = 1; goto done; } ipath_ibsd_reset(dd, 0); /* * If this is not the first reset, trimdone should be set * already. */ trim_done = ipath_sd_trimdone_poll(dd); /* * Whether or not trimdone succeeded, we need to put the * uC back into reset to avoid a possible fight with the * IBC state-machine. */ ipath_ibsd_reset(dd, 1); if (!trim_done) { ipath_dev_err(dd, "No TRIMDONE seen\n"); ret = 1; goto done; } ipath_sd_trimdone_monitor(dd, "First-reset"); /* Remember so we do not re-do the load, dactrim, etc. */ dd->serdes_first_init_done = 1; } /* * Setup for channel training and load values for * RxEq and DDS in tables used by IBC in IB1.2 mode */ val_stat = ipath_sd_setvals(dd); if (val_stat < 0) ret = 1; done: /* start relock timer regardless, but start at 1 second */ ipath_set_relock_poll(dd, -1); return ret; }
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); } } }