CINXE.COM
LKML: Roland Dreier: [PATCH 07/13] [RFC] ipath core misc files
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>LKML: Roland Dreier: [PATCH 07/13] [RFC] ipath core misc files</title><link href="/css/message.css" rel="stylesheet" type="text/css" /><link href="/css/wrap.css" rel="alternate stylesheet" type="text/css" title="wrap" /><link href="/css/nowrap.css" rel="stylesheet" type="text/css" title="nowrap" /><link href="/favicon.ico" rel="shortcut icon" /><script src="/js/simple-calendar.js" type="text/javascript"></script><script src="/js/styleswitcher.js" type="text/javascript"></script><link rel="alternate" type="application/rss+xml" title="lkml.org : last 100 messages" href="/rss.php" /><link rel="alternate" type="application/rss+xml" title="lkml.org : last messages by Roland Dreier" href="/groupie.php?aid=3215" /><!--Matomo--><script> var _paq = window._paq = window._paq || []; /* tracker methods like "setCustomDimension" should be called before "trackPageView" */ _paq.push(["setDoNotTrack", true]); _paq.push(["disableCookies"]); _paq.push(['trackPageView']); _paq.push(['enableLinkTracking']); (function() { var u="//m.lkml.org/"; _paq.push(['setTrackerUrl', u+'matomo.php']); _paq.push(['setSiteId', '1']); var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0]; g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s); })(); </script><!--End Matomo Code--></head><body onload="es.jasper.simpleCalendar.init();" itemscope="itemscope" itemtype="http://schema.org/BlogPosting"><table border="0" cellpadding="0" cellspacing="0"><tr><td width="180" align="center"><a href="/"><img style="border:0;width:135px;height:32px" src="/images/toprowlk.gif" alt="lkml.org" /></a></td><td width="32">聽</td><td class="nb"><div><a class="nb" href="/lkml"> [lkml]</a> 聽 <a class="nb" href="/lkml/2005"> [2005]</a> 聽 <a class="nb" href="/lkml/2005/12"> [Dec]</a> 聽 <a class="nb" href="/lkml/2005/12/16"> [16]</a> 聽 <a class="nb" href="/lkml/last100"> [last100]</a> 聽 <a href="/rss.php"><img src="/images/rss-or.gif" border="0" alt="RSS Feed" /></a></div><div>Views: <a href="#" class="nowrap" onclick="setActiveStyleSheet('wrap');return false;">[wrap]</a><a href="#" class="wrap" onclick="setActiveStyleSheet('nowrap');return false;">[no wrap]</a> 聽 <a class="nb" href="/lkml/mheaders/2005/12/16/296" onclick="this.href='/lkml/headers'+'/2005/12/16/296';">[headers]</a>聽 <a href="/lkml/bounce/2005/12/16/296">[forward]</a>聽 </div></td><td width="32">聽</td></tr><tr><td valign="top"><div class="es-jasper-simpleCalendar" baseurl="/lkml/"></div><div class="threadlist">Messages in this thread</div><ul class="threadlist"><li class="root"><a href="/lkml/2005/12/16/290">First message in thread</a></li><li><a href="/lkml/2005/12/16/301">Roland Dreier</a><ul><li><a href="/lkml/2005/12/16/297">Roland Dreier</a><ul><li class="origin"><a href="/lkml/2005/12/16/305">Roland Dreier</a><ul><li><a href="/lkml/2005/12/16/305">Roland Dreier</a><ul><li><a href="/lkml/2005/12/16/299">Roland Dreier</a></li><li><a href="/lkml/2005/12/17/75">Andrew Morton</a></li></ul></li></ul></li><li><a href="/lkml/2005/12/17/74">Andrew Morton</a><ul><li><a href="/lkml/2005/12/17/87">Robert Walsh</a></li><li><a href="/lkml/2005/12/17/90">Robert Walsh</a><ul><li><a href="/lkml/2005/12/17/124">Andrew Morton</a></li></ul></li></ul></li></ul></li></ul></li></ul><div class="threadlist">Patch in this message</div><ul class="threadlist"><li><a href="/lkml/diff/2005/12/16/296/1">Get diff 1</a></li></ul></td><td width="32" rowspan="2" class="c" valign="top"><img src="/images/icornerl.gif" width="32" height="32" alt="/" /></td><td class="c" rowspan="2" valign="top" style="padding-top: 1em"><table><tr><td><table><tr><td class="lp">Subject</td><td class="rp" itemprop="name">[PATCH 07/13] [RFC] ipath core misc files</td></tr><tr><td class="lp">Date</td><td class="rp" itemprop="datePublished">Fri, 16 Dec 2005 15:48:55 -0800</td></tr><tr><td class="lp">From</td><td class="rp" itemprop="author">Roland Dreier <></td></tr></table></td><td></td></tr></table><pre itemprop="articleBody">Misc ipath LLD files<br /><br />---<br /><br /> drivers/infiniband/hw/ipath/ipath_ht400.c | 1164 +++++++++++++++++++++++++++++<br /> drivers/infiniband/hw/ipath/ipath_i2c.c | 472 ++++++++++++<br /> drivers/infiniband/hw/ipath/ipath_lib.c | 92 ++<br /> drivers/infiniband/hw/ipath/ipath_mlock.c | 139 +++<br /> 4 files changed, 1867 insertions(+), 0 deletions(-)<br /> create mode 100644 drivers/infiniband/hw/ipath/ipath_ht400.c<br /> create mode 100644 drivers/infiniband/hw/ipath/ipath_i2c.c<br /> create mode 100644 drivers/infiniband/hw/ipath/ipath_lib.c<br /> create mode 100644 drivers/infiniband/hw/ipath/ipath_mlock.c<br /><br />8d0f07cdb6b7e4f243e31f5ac9fddb4225908062<br />diff --git a/drivers/infiniband/hw/ipath/ipath_ht400.c b/drivers/infiniband/hw/ipath/ipath_ht400.c<br />new file mode 100644<br />index 0000000..2d5b795<br />--- /dev/null<br />+++ b/drivers/infiniband/hw/ipath/ipath_ht400.c<br />@@ -0,0 +1,1164 @@<br />+/*<br />+ * Copyright (c) 2003, 2004, 2005. PathScale, Inc. All rights reserved.<br />+ *<br />+ * This software is available to you under a choice of one of two<br />+ * licenses. You may choose to be licensed under the terms of the GNU<br />+ * General Public License (GPL) Version 2, available from the file<br />+ * COPYING in the main directory of this source tree, or the<br />+ * OpenIB.org BSD license below:<br />+ *<br />+ * Redistribution and use in source and binary forms, with or<br />+ * without modification, are permitted provided that the following<br />+ * conditions are met:<br />+ *<br />+ * - Redistributions of source code must retain the above<br />+ * copyright notice, this list of conditions and the following<br />+ * disclaimer.<br />+ *<br />+ * - Redistributions in binary form must reproduce the above<br />+ * copyright notice, this list of conditions and the following<br />+ * disclaimer in the documentation and/or other materials<br />+ * provided with the distribution.<br />+ *<br />+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,<br />+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF<br />+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND<br />+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS<br />+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN<br />+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN<br />+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE<br />+ * SOFTWARE.<br />+ *<br />+ * Patent licenses, if any, provided herein do not apply to<br />+ * combinations of this program with other software, or any other<br />+ * product whatsoever.<br />+ *<br />+ * $Id: ipath_ht400.c 4491 2005-12-15 22:20:31Z rjwalsh $<br />+ */<br />+<br />+/*<br />+ * The first part of this file is shared with the diags, the second<br />+ * part is used only in the kernel.<br />+ */<br />+<br />+#include <stddef.h> /* for offsetof */<br />+<br />+#ifdef __KERNEL__<br />+#include <linux/types.h><br />+#include <linux/time.h><br />+#include <linux/timer.h><br />+#include <linux/wait.h><br />+#include "ipath_kernel.h"<br />+#else<br />+#include <sys/types.h><br />+#include <stdint.h><br />+#endif<br />+<br />+#include "ipath_registers.h"<br />+#include "ipath_common.h"<br />+<br />+/*<br />+ * This lists the InfiniPath registers, in the actual chip layout. This<br />+ * structure should never be directly accessed. It is included by the<br />+ * user mode diags, and so must be able to be compiled in both user<br />+ * and kernel mode.<br />+ */<br />+struct _infinipath_do_not_use_kernel_regs {<br />+ unsigned long long Revision;<br />+ unsigned long long Control;<br />+ unsigned long long PageAlign;<br />+ unsigned long long PortCnt;<br />+ unsigned long long DebugPortSelect;<br />+ unsigned long long DebugPort;<br />+ unsigned long long SendRegBase;<br />+ unsigned long long UserRegBase;<br />+ unsigned long long CounterRegBase;<br />+ unsigned long long Scratch;<br />+ unsigned long long ReservedMisc1;<br />+ unsigned long long InterruptConfig;<br />+ unsigned long long IntBlocked;<br />+ unsigned long long IntMask;<br />+ unsigned long long IntStatus;<br />+ unsigned long long IntClear;<br />+ unsigned long long ErrorMask;<br />+ unsigned long long ErrorStatus;<br />+ unsigned long long ErrorClear;<br />+ unsigned long long HwErrMask;<br />+ unsigned long long HwErrStatus;<br />+ unsigned long long HwErrClear;<br />+ unsigned long long HwDiagCtrl;<br />+ unsigned long long MDIO;<br />+ unsigned long long IBCStatus;<br />+ unsigned long long IBCCtrl;<br />+ unsigned long long ExtStatus;<br />+ unsigned long long ExtCtrl;<br />+ unsigned long long GPIOOut;<br />+ unsigned long long GPIOMask;<br />+ unsigned long long GPIOStatus;<br />+ unsigned long long GPIOClear;<br />+ unsigned long long RcvCtrl;<br />+ unsigned long long RcvBTHQP;<br />+ unsigned long long RcvHdrSize;<br />+ unsigned long long RcvHdrCnt;<br />+ unsigned long long RcvHdrEntSize;<br />+ unsigned long long RcvTIDBase;<br />+ unsigned long long RcvTIDCnt;<br />+ unsigned long long RcvEgrBase;<br />+ unsigned long long RcvEgrCnt;<br />+ unsigned long long RcvBufBase;<br />+ unsigned long long RcvBufSize;<br />+ unsigned long long RxIntMemBase;<br />+ unsigned long long RxIntMemSize;<br />+ unsigned long long RcvPartitionKey;<br />+ unsigned long long ReservedRcv[10];<br />+ unsigned long long SendCtrl;<br />+ unsigned long long SendPIOBufBase;<br />+ unsigned long long SendPIOSize;<br />+ unsigned long long SendPIOBufCnt;<br />+ unsigned long long SendPIOAvailAddr;<br />+ unsigned long long TxIntMemBase;<br />+ unsigned long long TxIntMemSize;<br />+ unsigned long long ReservedSend[9];<br />+ unsigned long long SendBufferError;<br />+ unsigned long long SendBufferErrorCONT1;<br />+ unsigned long long SendBufferErrorCONT2;<br />+ unsigned long long SendBufferErrorCONT3;<br />+ unsigned long long ReservedSBE[4];<br />+ unsigned long long RcvHdrAddr0;<br />+ unsigned long long RcvHdrAddr1;<br />+ unsigned long long RcvHdrAddr2;<br />+ unsigned long long RcvHdrAddr3;<br />+ unsigned long long RcvHdrAddr4;<br />+ unsigned long long RcvHdrAddr5;<br />+ unsigned long long RcvHdrAddr6;<br />+ unsigned long long RcvHdrAddr7;<br />+ unsigned long long RcvHdrAddr8;<br />+ unsigned long long ReservedRHA[7];<br />+ unsigned long long RcvHdrTailAddr0;<br />+ unsigned long long RcvHdrTailAddr1;<br />+ unsigned long long RcvHdrTailAddr2;<br />+ unsigned long long RcvHdrTailAddr3;<br />+ unsigned long long RcvHdrTailAddr4;<br />+ unsigned long long RcvHdrTailAddr5;<br />+ unsigned long long RcvHdrTailAddr6;<br />+ unsigned long long RcvHdrTailAddr7;<br />+ unsigned long long RcvHdrTailAddr8;<br />+ unsigned long long ReservedRHTA[7];<br />+ unsigned long long Sync; /* Software only */<br />+ unsigned long long Dump; /* Software only */<br />+ unsigned long long SimVer; /* Software only */<br />+ unsigned long long ReservedSW[5];<br />+ unsigned long long SerdesConfig0;<br />+ unsigned long long SerdesConfig1;<br />+ unsigned long long SerdesStatus;<br />+ unsigned long long XGXSConfig;<br />+ unsigned long long ReservedSW2[4];<br />+};<br />+<br />+#ifdef __KERNEL__ /* kernel uses reg#; diags use offset in bytes, not reg # */<br />+#define IPATH_KREG_OFFSET(field) (offsetof(struct \<br />+ _infinipath_do_not_use_kernel_regs, field) / sizeof(uint64_t))<br />+#define IPATH_CREG_OFFSET(field) (offsetof( \<br />+ struct infinipath_counters, field) / sizeof(uint64_t))<br />+#else /* diags */<br />+#define IPATH_KREG_OFFSET(field) (offsetof(struct \<br />+ _infinipath_do_not_use_kernel_regs, field))<br />+#define IPATH_CREG_OFFSET(field) (offsetof( \<br />+ struct infinipath_counters, field))<br />+#endif /* __KERNEL__ */<br />+<br />+ipath_kreg<br />+ kr_control = IPATH_KREG_OFFSET(Control),<br />+ kr_counterregbase = IPATH_KREG_OFFSET(CounterRegBase),<br />+ kr_debugport = IPATH_KREG_OFFSET(DebugPort),<br />+ kr_debugportselect = IPATH_KREG_OFFSET(DebugPortSelect),<br />+ kr_errorclear = IPATH_KREG_OFFSET(ErrorClear),<br />+ kr_errormask = IPATH_KREG_OFFSET(ErrorMask),<br />+ kr_errorstatus = IPATH_KREG_OFFSET(ErrorStatus),<br />+ kr_extctrl = IPATH_KREG_OFFSET(ExtCtrl),<br />+ kr_extstatus = IPATH_KREG_OFFSET(ExtStatus),<br />+ kr_gpio_clear = IPATH_KREG_OFFSET(GPIOClear),<br />+ kr_gpio_mask = IPATH_KREG_OFFSET(GPIOMask),<br />+ kr_gpio_out = IPATH_KREG_OFFSET(GPIOOut),<br />+ kr_gpio_status = IPATH_KREG_OFFSET(GPIOStatus),<br />+ kr_hwdiagctrl = IPATH_KREG_OFFSET(HwDiagCtrl),<br />+ kr_hwerrclear = IPATH_KREG_OFFSET(HwErrClear),<br />+ kr_hwerrmask = IPATH_KREG_OFFSET(HwErrMask),<br />+ kr_hwerrstatus = IPATH_KREG_OFFSET(HwErrStatus),<br />+ kr_ibcctrl = IPATH_KREG_OFFSET(IBCCtrl),<br />+ kr_ibcstatus = IPATH_KREG_OFFSET(IBCStatus),<br />+ kr_intblocked = IPATH_KREG_OFFSET(IntBlocked),<br />+ kr_intclear = IPATH_KREG_OFFSET(IntClear),<br />+ kr_interruptconfig = IPATH_KREG_OFFSET(InterruptConfig),<br />+ kr_intmask = IPATH_KREG_OFFSET(IntMask),<br />+ kr_intstatus = IPATH_KREG_OFFSET(IntStatus),<br />+ kr_mdio = IPATH_KREG_OFFSET(MDIO),<br />+ kr_pagealign = IPATH_KREG_OFFSET(PageAlign),<br />+ kr_partitionkey = IPATH_KREG_OFFSET(RcvPartitionKey),<br />+ kr_portcnt = IPATH_KREG_OFFSET(PortCnt),<br />+ kr_rcvbthqp = IPATH_KREG_OFFSET(RcvBTHQP),<br />+ kr_rcvbufbase = IPATH_KREG_OFFSET(RcvBufBase),<br />+ kr_rcvbufsize = IPATH_KREG_OFFSET(RcvBufSize),<br />+ kr_rcvctrl = IPATH_KREG_OFFSET(RcvCtrl),<br />+ kr_rcvegrbase = IPATH_KREG_OFFSET(RcvEgrBase),<br />+ kr_rcvegrcnt = IPATH_KREG_OFFSET(RcvEgrCnt),<br />+ kr_rcvhdrcnt = IPATH_KREG_OFFSET(RcvHdrCnt),<br />+ kr_rcvhdrentsize = IPATH_KREG_OFFSET(RcvHdrEntSize),<br />+ kr_rcvhdrsize = IPATH_KREG_OFFSET(RcvHdrSize),<br />+ kr_rcvintmembase = IPATH_KREG_OFFSET(RxIntMemBase),<br />+ kr_rcvintmemsize = IPATH_KREG_OFFSET(RxIntMemSize),<br />+ kr_rcvtidbase = IPATH_KREG_OFFSET(RcvTIDBase),<br />+ kr_rcvtidcnt = IPATH_KREG_OFFSET(RcvTIDCnt),<br />+ kr_revision = IPATH_KREG_OFFSET(Revision),<br />+ kr_scratch = IPATH_KREG_OFFSET(Scratch),<br />+ kr_sendbuffererror = IPATH_KREG_OFFSET(SendBufferError),<br />+ kr_sendbuffererror1 = IPATH_KREG_OFFSET(SendBufferErrorCONT1),<br />+ kr_sendbuffererror2 = IPATH_KREG_OFFSET(SendBufferErrorCONT2),<br />+ kr_sendbuffererror3 = IPATH_KREG_OFFSET(SendBufferErrorCONT3),<br />+ kr_sendctrl = IPATH_KREG_OFFSET(SendCtrl),<br />+ kr_sendpioavailaddr = IPATH_KREG_OFFSET(SendPIOAvailAddr),<br />+ kr_sendpiobufbase = IPATH_KREG_OFFSET(SendPIOBufBase),<br />+ kr_sendpiobufcnt = IPATH_KREG_OFFSET(SendPIOBufCnt),<br />+ kr_sendpiosize = IPATH_KREG_OFFSET(SendPIOSize),<br />+ kr_sendregbase = IPATH_KREG_OFFSET(SendRegBase),<br />+ kr_txintmembase = IPATH_KREG_OFFSET(TxIntMemBase),<br />+ kr_txintmemsize = IPATH_KREG_OFFSET(TxIntMemSize),<br />+ kr_userregbase = IPATH_KREG_OFFSET(UserRegBase),<br />+ /* no simulator, register not used */<br />+ kr_sync = IPATH_KREG_OFFSET(Scratch),<br />+ /* no simulator, register not used */<br />+ kr_dump = IPATH_KREG_OFFSET(Scratch),<br />+ /* no simulator, register not used */<br />+ kr_simver = IPATH_KREG_OFFSET(Scratch),<br />+ /* onchip serdes */<br />+ kr_serdesconfig0 = IPATH_KREG_OFFSET(SerdesConfig0),<br />+ /* onchip serdes */<br />+ kr_serdesconfig1 = IPATH_KREG_OFFSET(SerdesConfig1),<br />+ /* onchip serdes */<br />+ kr_serdesstatus = IPATH_KREG_OFFSET(SerdesStatus),<br />+ /* onchip serdes */<br />+ kr_xgxsconfig = IPATH_KREG_OFFSET(XGXSConfig),<br />+ /*<br />+ * last valid direct use register other than diag-only registers<br />+ */<br />+ __kr_lastvaliddirect = IPATH_KREG_OFFSET(ReservedSW2[0]),<br />+ /* always invalid for initializing */<br />+ __kr_invalid = IPATH_KREG_OFFSET(ReservedSW2[0]) + 1,<br />+ /*<br />+ * These should not be used directly via ipath_kget_kreg64(),<br />+ * use them with ipath_kget_kreg64_port()<br />+ */<br />+ kr_rcvhdraddr = IPATH_KREG_OFFSET(RcvHdrAddr0), /* not for direct use */<br />+ /* not for direct use */<br />+ kr_rcvhdrtailaddr = IPATH_KREG_OFFSET(RcvHdrTailAddr0),<br />+ /* we define the full set for the diags, the kernel doesn't use them */<br />+ kr_rcvhdraddr1 = IPATH_KREG_OFFSET(RcvHdrAddr1),<br />+ kr_rcvhdraddr2 = IPATH_KREG_OFFSET(RcvHdrAddr2),<br />+ kr_rcvhdraddr3 = IPATH_KREG_OFFSET(RcvHdrAddr3),<br />+ kr_rcvhdraddr4 = IPATH_KREG_OFFSET(RcvHdrAddr4),<br />+ kr_rcvhdrtailaddr1 = IPATH_KREG_OFFSET(RcvHdrTailAddr1),<br />+ kr_rcvhdrtailaddr2 = IPATH_KREG_OFFSET(RcvHdrTailAddr2),<br />+ kr_rcvhdrtailaddr3 = IPATH_KREG_OFFSET(RcvHdrTailAddr3),<br />+ kr_rcvhdrtailaddr4 = IPATH_KREG_OFFSET(RcvHdrTailAddr4),<br />+ kr_rcvhdraddr5 = IPATH_KREG_OFFSET(RcvHdrAddr5),<br />+ kr_rcvhdraddr6 = IPATH_KREG_OFFSET(RcvHdrAddr6),<br />+ kr_rcvhdraddr7 = IPATH_KREG_OFFSET(RcvHdrAddr7),<br />+ kr_rcvhdraddr8 = IPATH_KREG_OFFSET(RcvHdrAddr8),<br />+ kr_rcvhdrtailaddr5 = IPATH_KREG_OFFSET(RcvHdrTailAddr5),<br />+ kr_rcvhdrtailaddr6 = IPATH_KREG_OFFSET(RcvHdrTailAddr6),<br />+ kr_rcvhdrtailaddr7 = IPATH_KREG_OFFSET(RcvHdrTailAddr7),<br />+ kr_rcvhdrtailaddr8 = IPATH_KREG_OFFSET(RcvHdrTailAddr8);<br />+<br />+/*<br />+ * first of the pioavail registers, the total number is<br />+ * (kr_sendpiobufcnt / 32); each buffer uses 2 bits<br />+ * More properly, it's:<br />+ * (kr_sendpiobufcnt / ((sizeof(uint64_t)*BITS_PER_BYTE)/2))<br />+ */<br />+ipath_sreg sr_sendpioavail = 0;<br />+<br />+ipath_creg<br />+ cr_badformatcnt = IPATH_CREG_OFFSET(RxBadFormatCnt),<br />+ cr_erricrccnt = IPATH_CREG_OFFSET(RxICRCErrCnt),<br />+ cr_errlinkcnt = IPATH_CREG_OFFSET(RxLinkProblemCnt),<br />+ cr_errlpcrccnt = IPATH_CREG_OFFSET(RxLPCRCErrCnt),<br />+ cr_errpkey = IPATH_CREG_OFFSET(RxPKeyMismatchCnt),<br />+ cr_errrcvflowctrlcnt = IPATH_CREG_OFFSET(RxFlowCtrlErrCnt),<br />+ cr_err_rlencnt = IPATH_CREG_OFFSET(RxLenErrCnt),<br />+ cr_errslencnt = IPATH_CREG_OFFSET(TxLenErrCnt),<br />+ cr_errtidfull = IPATH_CREG_OFFSET(RxTIDFullErrCnt),<br />+ cr_errtidvalid = IPATH_CREG_OFFSET(RxTIDValidErrCnt),<br />+ cr_errvcrccnt = IPATH_CREG_OFFSET(RxVCRCErrCnt),<br />+ cr_ibstatuschange = IPATH_CREG_OFFSET(IBStatusChangeCnt),<br />+ /* calc from Reg_CounterRegBase + offset */<br />+ cr_intcnt = IPATH_CREG_OFFSET(LBIntCnt),<br />+ cr_invalidrlencnt = IPATH_CREG_OFFSET(RxMaxMinLenErrCnt),<br />+ cr_invalidslencnt = IPATH_CREG_OFFSET(TxMaxMinLenErrCnt),<br />+ cr_lbflowstallcnt = IPATH_CREG_OFFSET(LBFlowStallCnt),<br />+ cr_pktrcvcnt = IPATH_CREG_OFFSET(RxDataPktCnt),<br />+ cr_pktrcvflowctrlcnt = IPATH_CREG_OFFSET(RxFlowPktCnt),<br />+ cr_pktsendcnt = IPATH_CREG_OFFSET(TxDataPktCnt),<br />+ cr_pktsendflowcnt = IPATH_CREG_OFFSET(TxFlowPktCnt),<br />+ cr_portovflcnt = IPATH_CREG_OFFSET(RxP0HdrEgrOvflCnt),<br />+ cr_portovflcnt1 = IPATH_CREG_OFFSET(RxP1HdrEgrOvflCnt),<br />+ cr_portovflcnt2 = IPATH_CREG_OFFSET(RxP2HdrEgrOvflCnt),<br />+ cr_portovflcnt3 = IPATH_CREG_OFFSET(RxP3HdrEgrOvflCnt),<br />+ cr_portovflcnt4 = IPATH_CREG_OFFSET(RxP4HdrEgrOvflCnt),<br />+ cr_portovflcnt5 = IPATH_CREG_OFFSET(RxP5HdrEgrOvflCnt),<br />+ cr_portovflcnt6 = IPATH_CREG_OFFSET(RxP6HdrEgrOvflCnt),<br />+ cr_portovflcnt7 = IPATH_CREG_OFFSET(RxP7HdrEgrOvflCnt),<br />+ cr_portovflcnt8 = IPATH_CREG_OFFSET(RxP8HdrEgrOvflCnt),<br />+ cr_rcvebpcnt = IPATH_CREG_OFFSET(RxEBPCnt),<br />+ cr_rcvovflcnt = IPATH_CREG_OFFSET(RxBufOvflCnt),<br />+ cr_senddropped = IPATH_CREG_OFFSET(TxDroppedPktCnt),<br />+ cr_sendstallcnt = IPATH_CREG_OFFSET(TxFlowStallCnt),<br />+ cr_sendunderruncnt = IPATH_CREG_OFFSET(TxUnderrunCnt),<br />+ cr_wordrcvcnt = IPATH_CREG_OFFSET(RxDwordCnt),<br />+ cr_wordsendcnt = IPATH_CREG_OFFSET(TxDwordCnt),<br />+ cr_unsupvlcnt = IPATH_CREG_OFFSET(TxUnsupVLErrCnt),<br />+ cr_rxdroppktcnt = IPATH_CREG_OFFSET(RxDroppedPktCnt),<br />+ cr_iblinkerrrecovcnt = IPATH_CREG_OFFSET(IBLinkErrRecoveryCnt),<br />+ cr_iblinkdowncnt = IPATH_CREG_OFFSET(IBLinkDownedCnt),<br />+ cr_ibsymbolerrcnt = IPATH_CREG_OFFSET(IBSymbolErrCnt);<br />+<br />+/* kr_sendctrl bits */<br />+#define INFINIPATH_S_DISARMPIOBUF_MASK 0xFF<br />+<br />+/* kr_rcvctrl bits */<br />+#define INFINIPATH_R_PORTENABLE_MASK 0x1FF<br />+#define INFINIPATH_R_INTRAVAIL_MASK 0x1FF<br />+<br />+/* kr_intstatus, kr_intclear, kr_intmask bits */<br />+#define INFINIPATH_I_RCVURG_MASK 0x1FF<br />+#define INFINIPATH_I_RCVAVAIL_MASK 0x1FF<br />+<br />+/* kr_hwerrclear, kr_hwerrmask, kr_hwerrstatus, bits */<br />+#define INFINIPATH_HWE_HTCMEMPARITYERR_MASK 0x3FFFFFULL<br />+#define INFINIPATH_HWE_HTCLNKABYTE0CRCERR 0x0000000000800000ULL<br />+#define INFINIPATH_HWE_HTCLNKABYTE1CRCERR 0x0000000001000000ULL<br />+#define INFINIPATH_HWE_HTCLNKBBYTE0CRCERR 0x0000000002000000ULL<br />+#define INFINIPATH_HWE_HTCLNKBBYTE1CRCERR 0x0000000004000000ULL<br />+#define INFINIPATH_HWE_HTCMISCERR4 0x0000000008000000ULL<br />+#define INFINIPATH_HWE_HTCMISCERR5 0x0000000010000000ULL<br />+#define INFINIPATH_HWE_HTCMISCERR6 0x0000000020000000ULL<br />+#define INFINIPATH_HWE_HTCMISCERR7 0x0000000040000000ULL<br />+#define INFINIPATH_HWE_MEMBISTFAILED 0x0040000000000000ULL<br />+#define INFINIPATH_HWE_COREPLL_FBSLIP 0x0080000000000000ULL<br />+#define INFINIPATH_HWE_COREPLL_RFSLIP 0x0100000000000000ULL<br />+#define INFINIPATH_HWE_HTBPLL_FBSLIP 0x0200000000000000ULL<br />+#define INFINIPATH_HWE_HTBPLL_RFSLIP 0x0400000000000000ULL<br />+#define INFINIPATH_HWE_HTAPLL_FBSLIP 0x0800000000000000ULL<br />+#define INFINIPATH_HWE_HTAPLL_RFSLIP 0x1000000000000000ULL<br />+#define INFINIPATH_HWE_EXTSERDESPLLFAILED 0x2000000000000000ULL<br />+<br />+/* kr_hwdiagctrl bits */<br />+#define INFINIPATH_DC_NUMHTMEMS 22<br />+<br />+/* kr_extstatus bits */<br />+#define INFINIPATH_EXTS_FREQSEL 0x2<br />+#define INFINIPATH_EXTS_SERDESSEL 0x4<br />+#define INFINIPATH_EXTS_MEMBIST_ENDTEST 0x0000000000004000<br />+#define INFINIPATH_EXTS_MEMBIST_CORRECT 0x0000000000008000<br />+<br />+/* kr_extctrl bits */<br />+<br />+/*<br />+ * masks and bits that are different in different chips, or present only<br />+ * in one<br />+ */<br />+const uint32_t infinipath_i_rcvavail_mask = INFINIPATH_I_RCVAVAIL_MASK;<br />+const uint32_t infinipath_i_rcvurg_mask = INFINIPATH_I_RCVURG_MASK;<br />+const uint64_t infinipath_hwe_htcmemparityerr_mask =<br />+ INFINIPATH_HWE_HTCMEMPARITYERR_MASK;<br />+<br />+const uint64_t infinipath_hwe_spibdcmlockfailed_mask = 0ULL;<br />+const uint64_t infinipath_hwe_sphtdcmlockfailed_mask = 0ULL;<br />+const uint64_t infinipath_hwe_htcdcmlockfailed_mask = 0ULL;<br />+const uint64_t infinipath_hwe_htcdcmlockfailed_shift = 0ULL;<br />+const uint64_t infinipath_hwe_sphtdcmlockfailed_shift = 0ULL;<br />+const uint64_t infinipath_hwe_spibdcmlockfailed_shift = 0ULL;<br />+<br />+const uint64_t infinipath_hwe_htclnkabyte0crcerr =<br />+ INFINIPATH_HWE_HTCLNKABYTE0CRCERR;<br />+const uint64_t infinipath_hwe_htclnkabyte1crcerr =<br />+ INFINIPATH_HWE_HTCLNKABYTE1CRCERR;<br />+const uint64_t infinipath_hwe_htclnkbbyte0crcerr =<br />+ INFINIPATH_HWE_HTCLNKBBYTE0CRCERR;<br />+const uint64_t infinipath_hwe_htclnkbbyte1crcerr =<br />+ INFINIPATH_HWE_HTCLNKBBYTE1CRCERR;<br />+<br />+const uint64_t infinipath_c_bitsextant =<br />+ (INFINIPATH_C_FREEZEMODE | INFINIPATH_C_LINKENABLE);<br />+<br />+const uint64_t infinipath_s_bitsextant =<br />+ (INFINIPATH_S_ABORT | INFINIPATH_S_PIOINTBUFAVAIL |<br />+ INFINIPATH_S_PIOBUFAVAILUPD | INFINIPATH_S_PIOENABLE |<br />+ INFINIPATH_S_DISARM |<br />+ (INFINIPATH_S_DISARMPIOBUF_MASK << INFINIPATH_S_DISARMPIOBUF_SHIFT));<br />+<br />+const uint64_t infinipath_r_bitsextant =<br />+ ((INFINIPATH_R_PORTENABLE_MASK << INFINIPATH_R_PORTENABLE_SHIFT) |<br />+ (INFINIPATH_R_INTRAVAIL_MASK << INFINIPATH_R_INTRAVAIL_SHIFT) |<br />+ INFINIPATH_R_TAILUPD);<br />+<br />+const uint64_t infinipath_i_bitsextant =<br />+ ((INFINIPATH_I_RCVURG_MASK << INFINIPATH_I_RCVURG_SHIFT) |<br />+ (INFINIPATH_I_RCVAVAIL_MASK << INFINIPATH_I_RCVAVAIL_SHIFT) |<br />+ INFINIPATH_I_ERROR | INFINIPATH_I_SPIOSENT |<br />+ INFINIPATH_I_SPIOBUFAVAIL | INFINIPATH_I_GPIO);<br />+<br />+const uint64_t infinipath_e_bitsextant =<br />+ (INFINIPATH_E_RFORMATERR | INFINIPATH_E_RVCRC | INFINIPATH_E_RICRC |<br />+ INFINIPATH_E_RMINPKTLEN | INFINIPATH_E_RMAXPKTLEN |<br />+ INFINIPATH_E_RLONGPKTLEN | INFINIPATH_E_RSHORTPKTLEN |<br />+ INFINIPATH_E_RUNEXPCHAR | INFINIPATH_E_RUNSUPVL | INFINIPATH_E_REBP |<br />+ INFINIPATH_E_RIBFLOW | INFINIPATH_E_RBADVERSION |<br />+ INFINIPATH_E_RRCVEGRFULL | INFINIPATH_E_RRCVHDRFULL |<br />+ INFINIPATH_E_RBADTID | INFINIPATH_E_RHDRLEN |<br />+ INFINIPATH_E_RHDR | INFINIPATH_E_RIBLOSTLINK |<br />+ INFINIPATH_E_SMINPKTLEN | INFINIPATH_E_SMAXPKTLEN |<br />+ INFINIPATH_E_SUNDERRUN | INFINIPATH_E_SPKTLEN |<br />+ INFINIPATH_E_SDROPPEDSMPPKT | INFINIPATH_E_SDROPPEDDATAPKT |<br />+ INFINIPATH_E_SPIOARMLAUNCH | INFINIPATH_E_SUNEXPERRPKTNUM |<br />+ INFINIPATH_E_SUNSUPVL | INFINIPATH_E_IBSTATUSCHANGED |<br />+ INFINIPATH_E_INVALIDADDR | INFINIPATH_E_RESET | INFINIPATH_E_HARDWARE);<br />+<br />+const uint64_t infinipath_hwe_bitsextant =<br />+ (INFINIPATH_HWE_HTCMEMPARITYERR_MASK <<<br />+ INFINIPATH_HWE_HTCMEMPARITYERR_SHIFT) |<br />+ (INFINIPATH_HWE_TXEMEMPARITYERR_MASK <<<br />+ INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT) |<br />+ (INFINIPATH_HWE_RXEMEMPARITYERR_MASK <<<br />+ INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT) |<br />+ INFINIPATH_HWE_HTCLNKABYTE0CRCERR |<br />+ INFINIPATH_HWE_HTCLNKABYTE1CRCERR | INFINIPATH_HWE_HTCLNKBBYTE0CRCERR |<br />+ INFINIPATH_HWE_HTCLNKBBYTE1CRCERR | INFINIPATH_HWE_HTCMISCERR4 |<br />+ INFINIPATH_HWE_HTCMISCERR5 | INFINIPATH_HWE_HTCMISCERR6 |<br />+ INFINIPATH_HWE_HTCMISCERR7 | INFINIPATH_HWE_HTCBUSTREQPARITYERR |<br />+ INFINIPATH_HWE_HTCBUSTRESPPARITYERR |<br />+ INFINIPATH_HWE_HTCBUSIREQPARITYERR |<br />+ INFINIPATH_HWE_RXDSYNCMEMPARITYERR | INFINIPATH_HWE_MEMBISTFAILED |<br />+ INFINIPATH_HWE_COREPLL_FBSLIP | INFINIPATH_HWE_COREPLL_RFSLIP |<br />+ INFINIPATH_HWE_HTBPLL_FBSLIP | INFINIPATH_HWE_HTBPLL_RFSLIP |<br />+ INFINIPATH_HWE_HTAPLL_FBSLIP | INFINIPATH_HWE_HTAPLL_RFSLIP |<br />+ INFINIPATH_HWE_EXTSERDESPLLFAILED |<br />+ INFINIPATH_HWE_IBCBUSTOSPCPARITYERR |<br />+ INFINIPATH_HWE_IBCBUSFRSPCPARITYERR;<br />+<br />+const uint64_t infinipath_dc_bitsextant =<br />+ (INFINIPATH_DC_FORCEHTCMEMPARITYERR_MASK <<<br />+ INFINIPATH_DC_FORCEHTCMEMPARITYERR_SHIFT) |<br />+ (INFINIPATH_DC_FORCETXEMEMPARITYERR_MASK <<<br />+ INFINIPATH_DC_FORCETXEMEMPARITYERR_SHIFT) |<br />+ (INFINIPATH_DC_FORCERXEMEMPARITYERR_MASK <<<br />+ INFINIPATH_DC_FORCERXEMEMPARITYERR_SHIFT) |<br />+ INFINIPATH_DC_FORCEHTCBUSTREQPARITYERR |<br />+ INFINIPATH_DC_FORCEHTCBUSTRESPPARITYERR |<br />+ INFINIPATH_DC_FORCEHTCBUSIREQPARITYERR |<br />+ INFINIPATH_DC_FORCERXDSYNCMEMPARITYERR |<br />+ INFINIPATH_DC_COUNTERDISABLE | INFINIPATH_DC_COUNTERWREN |<br />+ INFINIPATH_DC_FORCEIBCBUSTOSPCPARITYERR |<br />+ INFINIPATH_DC_FORCEIBCBUSFRSPCPARITYERR;<br />+<br />+const uint64_t infinipath_ibcc_bitsextant =<br />+ (INFINIPATH_IBCC_FLOWCTRLPERIOD_MASK <<<br />+ INFINIPATH_IBCC_FLOWCTRLPERIOD_SHIFT) |<br />+ (INFINIPATH_IBCC_FLOWCTRLWATERMARK_MASK <<<br />+ INFINIPATH_IBCC_FLOWCTRLWATERMARK_SHIFT) |<br />+ (INFINIPATH_IBCC_LINKINITCMD_MASK <<<br />+ INFINIPATH_IBCC_LINKINITCMD_SHIFT) |<br />+ (INFINIPATH_IBCC_LINKCMD_MASK << INFINIPATH_IBCC_LINKCMD_SHIFT) |<br />+ (INFINIPATH_IBCC_MAXPKTLEN_MASK << INFINIPATH_IBCC_MAXPKTLEN_SHIFT) |<br />+ (INFINIPATH_IBCC_PHYERRTHRESHOLD_MASK <<<br />+ INFINIPATH_IBCC_PHYERRTHRESHOLD_SHIFT) |<br />+ (INFINIPATH_IBCC_OVERRUNTHRESHOLD_MASK <<<br />+ INFINIPATH_IBCC_OVERRUNTHRESHOLD_SHIFT) |<br />+ (INFINIPATH_IBCC_CREDITSCALE_MASK <<<br />+ INFINIPATH_IBCC_CREDITSCALE_SHIFT) |<br />+ INFINIPATH_IBCC_LOOPBACK | INFINIPATH_IBCC_LINKDOWNDEFAULTSTATE;<br />+<br />+const uint64_t infinipath_mdio_bitsextant =<br />+ (INFINIPATH_MDIO_CLKDIV_MASK << INFINIPATH_MDIO_CLKDIV_SHIFT) |<br />+ (INFINIPATH_MDIO_COMMAND_MASK << INFINIPATH_MDIO_COMMAND_SHIFT) |<br />+ (INFINIPATH_MDIO_DEVADDR_MASK << INFINIPATH_MDIO_DEVADDR_SHIFT) |<br />+ (INFINIPATH_MDIO_REGADDR_MASK << INFINIPATH_MDIO_REGADDR_SHIFT) |<br />+ (INFINIPATH_MDIO_DATA_MASK << INFINIPATH_MDIO_DATA_SHIFT) |<br />+ INFINIPATH_MDIO_CMDVALID | INFINIPATH_MDIO_RDDATAVALID;<br />+<br />+const uint64_t infinipath_ibcs_bitsextant =<br />+ (INFINIPATH_IBCS_LINKTRAININGSTATE_MASK <<<br />+ INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) |<br />+ (INFINIPATH_IBCS_LINKSTATE_MASK << INFINIPATH_IBCS_LINKSTATE_SHIFT) |<br />+ INFINIPATH_IBCS_TXREADY | INFINIPATH_IBCS_TXCREDITOK;<br />+<br />+const uint64_t infinipath_extc_bitsextant =<br />+ (INFINIPATH_EXTC_GPIOINVERT_MASK << INFINIPATH_EXTC_GPIOINVERT_SHIFT) |<br />+ (INFINIPATH_EXTC_GPIOOE_MASK << INFINIPATH_EXTC_GPIOOE_SHIFT) |<br />+ INFINIPATH_EXTC_SERDESENABLE | INFINIPATH_EXTC_SERDESCONNECT |<br />+ INFINIPATH_EXTC_SERDESENTRUNKING | INFINIPATH_EXTC_SERDESDISRXFIFO |<br />+ INFINIPATH_EXTC_SERDESENPLPBK1 | INFINIPATH_EXTC_SERDESENPLPBK2 |<br />+ INFINIPATH_EXTC_SERDESENENCDEC | INFINIPATH_EXTC_LEDSECPORTGREENON |<br />+ INFINIPATH_EXTC_LEDSECPORTYELLOWON | INFINIPATH_EXTC_LEDPRIPORTGREENON |<br />+ INFINIPATH_EXTC_LEDPRIPORTYELLOWON | INFINIPATH_EXTC_LEDGBLOKGREENON |<br />+ INFINIPATH_EXTC_LEDGBLERRREDOFF;<br />+<br />+/* Start of Documentation block for SerDes registers<br />+ * serdes and xgxs register bits; not all have defines,<br />+ * since I haven't yet needed them all, and I'm lazy. Those that I needed<br />+ * are in ipath_registers.h<br />+<br />+serdesConfig0Out (R/W)<br />+ Default Value<br />+bit[3:0] - ResetA/B/C/D (4'b1111)<br />+bit[7:4] -L1PwrdnA/B/C/D (4'b0000)<br />+bit[11:8] - RxIdleEnX (4'b0000)<br />+bit[15:12] - TxIdleEnX (4'b0000)<br />+bit[19:16] - RxDetectEnX (4'b0000)<br />+bit[23:20] - BeaconTxEnX (4'b0000)<br />+bit[27:24] - RxTermEnX (4'b0000)<br />+bit[28] - ResetPLL (1'b0)<br />+bit[29] -L2Pwrdn (1'b0)<br />+bit[37:30] - Offset[7:0] (8'b00000000)<br />+bit[38] -OffsetEn (1'b0)<br />+bit[39] -ParLBPK (1'b0)<br />+bit[40] -ParReset (1'b0)<br />+bit[42:41] - RefSel (2'b10)<br />+bit[43] - PW (1'b0)<br />+bit[47:44] - LPBKA/B/C/D (4'b0000)<br />+bit[49:48] - ClkBufTermAdj (2'b0)<br />+bit[51:50] - RxTermAdj (2'b0)<br />+bit[53:52] - TxTermAdj (2'b0)<br />+bit[55:54] - RxEqCtl (2'b0)<br />+bit[63:56] - Reserved<br />+<br />+cce_wip_serdesConfig1Out[63:0] (R/W)<br />+bit[3:0] - HiDrvX (4'b0000)<br />+bit[7:4] - LoDrvX (4'b0000)<br />+bit[12:11] - DtxA[3:0] (4'b0000)<br />+bit[15:12] - DtxB[3:0] (4'b0000)<br />+bit[19:16] - DtxC[3:0] (4'b0000)<br />+bit[23:20] - DtxD[3:0] (4'b0000)<br />+bit[27:24] - DeqA[3:0] (4'b0000)<br />+bit[31:28] - DeqB[3:0] (4'b0000)<br />+bit[35:32] - DeqC[3:0] (4'b0000)<br />+bit[39:36] - DeqD[3:0] (4'b0000)<br />+Framer interface, bits 40-59, not used<br />+bit[44:40] - FmOffsetA[4:0] (5'b00000)<br />+bit[49:45] - FmOffsetB[4:0] (5'b00000)<br />+bit[54:50] - FmOffsetC[4:0] (5'b00000)<br />+bit[59:55] - FmOffsetD[4:0] (5'b00000)<br />+bit[63:60] - FmOffsetEnA/B/C/D (4'b0000)<br />+<br />+SerdesStatus[63:0] (RO)<br />+bit[3:0] - TxIdleDetectA/B/C/D<br />+bit[7:4] - RxDetectA/B/C/D<br />+bit[11:8] - BeaconDetectA/B/C/D<br />+bit[63:12] - Reserved<br />+<br />+XGXSConfigOut[63:0]<br />+bit[2:0] - Resets, init to 1; bit 0 unused?<br />+bit[3] - MDIO, select register bank for vendor specific register<br />+ (0x1e if set, else 0x1f); vendor-specific status in register 8<br />+ bits 0-3 lanes0-3 signal detect, 1 if detected<br />+ bits 4-7 lanes0-3 CTC fifo errors, 1 if detected (latched until read)<br />+bit[8:4] - MDIO port address<br />+bit[18:9] - lnk_sync_mask<br />+bit[22:19] - polarity inv<br />+<br />+Documentation end */<br />+<br />+/*<br />+ *<br />+ * General specs:<br />+ * ExtCtrl[63:48] = EXTC_GPIOOE[15:0]<br />+ * ExtCtrl[47:32] = EXTC_GPIOInvert[15:0]<br />+ * ExtStatus[63:48] = GpioIn[15:0]<br />+ *<br />+ * GPIO[1] = EEPROM_SDA<br />+ * GPIO[0] = EEPROM_SCL<br />+ */<br />+<br />+#define _IPATH_GPIO_SDA_NUM 1<br />+#define _IPATH_GPIO_SCL_NUM 0<br />+<br />+#define IPATH_GPIO_SDA \<br />+ (1UL << (_IPATH_GPIO_SDA_NUM+INFINIPATH_EXTC_GPIOOE_SHIFT))<br />+#define IPATH_GPIO_SCL \<br />+ (1UL << (_IPATH_GPIO_SCL_NUM+INFINIPATH_EXTC_GPIOOE_SHIFT))<br />+<br />+/*<br />+ * register bits for selecting i2c direction and values, used for I2C serial<br />+ * flash<br />+ */<br />+const uint16_t ipath_gpio_sda_num = _IPATH_GPIO_SDA_NUM;<br />+const uint16_t ipath_gpio_scl_num = _IPATH_GPIO_SCL_NUM;<br />+const uint64_t ipath_gpio_sda = IPATH_GPIO_SDA;<br />+const uint64_t ipath_gpio_scl = IPATH_GPIO_SCL;<br />+<br />+/* The remaining portion of this file is used only for the kernel */<br />+#ifdef __KERNEL__<br />+<br />+#include <linux/config.h><br />+#include <linux/kernel.h><br />+#include <linux/pci.h><br />+#include <linux/init.h><br />+#include <linux/string.h><br />+#include <linux/delay.h><br />+<br />+/*<br />+ * This file contains all of the code that is specific to the InfiniPath<br />+ * HT-400 chip.<br />+ */<br />+<br />+/* we support up to 4 chips per system */<br />+const uint32_t infinipath_max = 4;<br />+ipath_devdata devdata[4];<br />+static const char *ipath_unit_names[4] = {<br />+ "infinipath0", "infinipath1", "infinipath2", "infinipath3"<br />+};<br />+<br />+const char *ipath_get_unit_name(int unit)<br />+{<br />+ return ipath_unit_names[unit];<br />+}<br />+<br />+static void ipath_check_htlink(ipath_type t);<br />+<br />+/*<br />+ * display hardware errors. Use same msg buffer as regular errors to avoid<br />+ * excessive stack use. Most hardware errors are catastrophic, but for <br />+ * right now, we'll print them and continue.<br />+ * We reuse the same message buffer as ipath_handle_errors() to avoid<br />+ * excessive stack usage.<br />+ */<br />+void ipath_handle_hwerrors(const ipath_type t, char *msg, int msgl)<br />+{<br />+ uint64_t hwerrs = ipath_kget_kreg64(t, kr_hwerrstatus);<br />+ uint32_t bits, ctrl;<br />+ int isfatal = 0;<br />+ char bitsmsg[64];<br />+<br />+ if (!hwerrs) {<br />+ _IPATH_VDBG("Called but no hardware errors set\n");<br />+ /*<br />+ * better than printing cofusing messages<br />+ * This seems to be related to clearing the crc error, or<br />+ * the pll error during init.<br />+ */<br />+ return;<br />+ } else if (hwerrs == ~0ULL) {<br />+ _IPATH_UNIT_ERROR(t,<br />+ "Read of hardware error status failed (all bits set); ignoring\n");<br />+ return;<br />+ }<br />+ ipath_stats.sps_hwerrs++;<br />+<br />+ /*<br />+ * clear the error, regardless of whether we continue or stop using<br />+ * the chip.<br />+ */<br />+ ipath_kput_kreg(t, kr_hwerrclear, hwerrs);<br />+<br />+ hwerrs &= devdata[t].ipath_hwerrmask;<br />+<br />+ /*<br />+ * make sure we get this much out, unless told to be quiet,<br />+ * or it's occurred within the last 5 seconds<br />+ */<br />+ if ((hwerrs & ~devdata[t].ipath_lasthwerror) ||<br />+ (infinipath_debug & __IPATH_VERBDBG))<br />+ _IPATH_INFO("Hardware error: hwerr=0x%llx (cleared)\n", hwerrs);<br />+ devdata[t].ipath_lasthwerror |= hwerrs;<br />+<br />+ if (hwerrs & ~infinipath_hwe_bitsextant)<br />+ _IPATH_UNIT_ERROR(t,<br />+ "hwerror interrupt with unknown errors %llx set\n",<br />+ hwerrs & ~infinipath_hwe_bitsextant);<br />+<br />+ ctrl = ipath_kget_kreg32(t, kr_control);<br />+ if (ctrl & INFINIPATH_C_FREEZEMODE) {<br />+ if (hwerrs) {<br />+ /*<br />+ * if any set that we aren't ignoring<br />+ * only make the complaint once, in case it's stuck or<br />+ * recurring, and we get here multiple times<br />+ */<br />+ if (devdata[t].ipath_flags & IPATH_INITTED) {<br />+ _IPATH_UNIT_ERROR(t,<br />+ "Fatal Error (freezemode), no longer usable\n");<br />+ isfatal = 1;<br />+ }<br />+ *devdata[t].ipath_statusp &= ~IPATH_STATUS_IB_READY;<br />+ /* mark as having had error */<br />+ *devdata[t].ipath_statusp |= IPATH_STATUS_HWERROR;<br />+ /*<br />+ * mark as not usable, at a minimum until driver<br />+ * is reloaded, probably until reboot, since no<br />+ * other reset is possible.<br />+ */<br />+ devdata[t].ipath_flags &= ~IPATH_INITTED;<br />+ } else {<br />+ _IPATH_DBG<br />+ ("Clearing freezemode on ignored hardware error\n");<br />+ ctrl &= ~INFINIPATH_C_FREEZEMODE;<br />+ ipath_kput_kreg(t, kr_control, ctrl);<br />+ }<br />+ }<br />+<br />+ *msg = '\0';<br />+<br />+ /*<br />+ * may someday want to decode into which bits are which<br />+ * functional area for parity errors, etc.<br />+ */<br />+ if (hwerrs & (infinipath_hwe_htcmemparityerr_mask<br />+ << INFINIPATH_HWE_HTCMEMPARITYERR_SHIFT)) {<br />+ bits = (uint32_t) ((hwerrs >><br />+ INFINIPATH_HWE_HTCMEMPARITYERR_SHIFT) &<br />+ INFINIPATH_HWE_HTCMEMPARITYERR_MASK);<br />+ snprintf(bitsmsg, sizeof bitsmsg, "[HTC Parity Errs %x] ",<br />+ bits);<br />+ strlcat(msg, bitsmsg, msgl);<br />+ }<br />+ if (hwerrs & (INFINIPATH_HWE_RXEMEMPARITYERR_MASK<br />+ << INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT)) {<br />+ bits = (uint32_t) ((hwerrs >><br />+ INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT) &<br />+ INFINIPATH_HWE_RXEMEMPARITYERR_MASK);<br />+ snprintf(bitsmsg, sizeof bitsmsg, "[RXE Parity Errs %x] ",<br />+ bits);<br />+ strlcat(msg, bitsmsg, msgl);<br />+ }<br />+ if (hwerrs & (INFINIPATH_HWE_TXEMEMPARITYERR_MASK<br />+ << INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT)) {<br />+ bits = (uint32_t) ((hwerrs >><br />+ INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT) &<br />+ INFINIPATH_HWE_TXEMEMPARITYERR_MASK);<br />+ snprintf(bitsmsg, sizeof bitsmsg, "[TXE Parity Errs %x] ",<br />+ bits);<br />+ strlcat(msg, bitsmsg, msgl);<br />+ }<br />+ if (hwerrs & INFINIPATH_HWE_IBCBUSTOSPCPARITYERR)<br />+ strlcat(msg, "[IB2IPATH Parity]", msgl);<br />+ if (hwerrs & INFINIPATH_HWE_IBCBUSFRSPCPARITYERR)<br />+ strlcat(msg, "[IPATH2IB Parity]", msgl);<br />+ if (hwerrs & INFINIPATH_HWE_HTCBUSIREQPARITYERR)<br />+ strlcat(msg, "[HTC Ireq Parity]", msgl);<br />+ if (hwerrs & INFINIPATH_HWE_HTCBUSTREQPARITYERR)<br />+ strlcat(msg, "[HTC Treq Parity]", msgl);<br />+ if (hwerrs & INFINIPATH_HWE_HTCBUSTRESPPARITYERR)<br />+ strlcat(msg, "[HTC Tresp Parity]", msgl);<br />+<br />+/* keep the code below somewhat more readonable; not used elsewhere */<br />+#define _IPATH_HTLINK0_CRCBITS (infinipath_hwe_htclnkabyte0crcerr | \<br />+ infinipath_hwe_htclnkabyte1crcerr)<br />+#define _IPATH_HTLINK1_CRCBITS (infinipath_hwe_htclnkbbyte0crcerr | \<br />+ infinipath_hwe_htclnkbbyte1crcerr)<br />+#define _IPATH_HTLANE0_CRCBITS (infinipath_hwe_htclnkabyte0crcerr | \<br />+ infinipath_hwe_htclnkbbyte0crcerr)<br />+#define _IPATH_HTLANE1_CRCBITS (infinipath_hwe_htclnkabyte1crcerr | \<br />+ infinipath_hwe_htclnkbbyte1crcerr)<br />+ if (hwerrs & (_IPATH_HTLINK0_CRCBITS | _IPATH_HTLINK1_CRCBITS)) {<br />+ char bitsmsg[64];<br />+ uint64_t crcbits = hwerrs &<br />+ (_IPATH_HTLINK0_CRCBITS | _IPATH_HTLINK1_CRCBITS);<br />+ /* don't check if 8bit HT */<br />+ if (devdata[t].ipath_flags & IPATH_8BIT_IN_HT0)<br />+ crcbits &= ~infinipath_hwe_htclnkabyte1crcerr;<br />+ /* don't check if 8bit HT */<br />+ if (devdata[t].ipath_flags & IPATH_8BIT_IN_HT1)<br />+ crcbits &= ~infinipath_hwe_htclnkbbyte1crcerr;<br />+ /*<br />+ * we'll want to ignore link errors on link that is<br />+ * not in use, if any. For now, complain about both<br />+ */<br />+ if (crcbits) {<br />+ uint16_t ctrl0, ctrl1;<br />+ snprintf(bitsmsg, sizeof bitsmsg,<br />+ "[HT%s lane %s CRC (%llx); ignore till reload]",<br />+ !(crcbits & _IPATH_HTLINK1_CRCBITS) ?<br />+ "0 (A)" : (!(crcbits & _IPATH_HTLINK0_CRCBITS)<br />+ ? "1 (B)" : "0+1 (A+B)"),<br />+ !(crcbits & _IPATH_HTLANE1_CRCBITS) ? "0"<br />+ : (!(crcbits & _IPATH_HTLANE0_CRCBITS) ? "1" :<br />+ "0+1"), crcbits);<br />+ strlcat(msg, bitsmsg, msgl);<br />+<br />+ /*<br />+ * print extra info for debugging.<br />+ * slave/primary config word 4, 8 (link control 0, 1)<br />+ */<br />+<br />+ if (pci_read_config_word(devdata[t].pcidev,<br />+ devdata[t].ipath_ht_slave_off +<br />+ 0x4, &ctrl0))<br />+ _IPATH_INFO<br />+ ("Couldn't read linkctrl0 of slave/primary config block\n");<br />+ else if (!(ctrl0 & 1 << 6)) /* not if EOC bit set */<br />+ _IPATH_DBG("HT linkctrl0 0x%x%s%s\n", ctrl0,<br />+ ((ctrl0 >> 8) & 7) ? " CRC" : "",<br />+ ((ctrl0 >> 4) & 1) ? "linkfail" :<br />+ "");<br />+ if (pci_read_config_word<br />+ (devdata[t].pcidev,<br />+ devdata[t].ipath_ht_slave_off + 0x8, &ctrl1))<br />+ _IPATH_INFO<br />+ ("Couldn't read linkctrl1 of slave/primary config block\n");<br />+ else if (!(ctrl1 & 1 << 6)) /* not if EOC bit set */<br />+ _IPATH_DBG("HT linkctrl1 0x%x%s%s\n", ctrl1,<br />+ ((ctrl1 >> 8) & 7) ? " CRC" : "",<br />+ ((ctrl1 >> 4) & 1) ? "linkfail" :<br />+ "");<br />+<br />+ /* disable until driver reloaded */<br />+ devdata[t].ipath_hwerrmask &= ~crcbits;<br />+ ipath_kput_kreg(t, kr_hwerrmask,<br />+ devdata[t].ipath_hwerrmask);<br />+ _IPATH_DBG("HT crc errs: %s\n", msg);<br />+ } else<br />+ _IPATH_DBG<br />+ ("ignoring HT crc errors 0x%llx, not in use\n",<br />+ hwerrs & (_IPATH_HTLINK0_CRCBITS |<br />+ _IPATH_HTLINK1_CRCBITS));<br />+ }<br />+<br />+ if (hwerrs & INFINIPATH_HWE_HTCMISCERR5)<br />+ strlcat(msg, "[HT core Misc5]", msgl);<br />+ if (hwerrs & INFINIPATH_HWE_HTCMISCERR6)<br />+ strlcat(msg, "[HT core Misc6]", msgl);<br />+ if (hwerrs & INFINIPATH_HWE_HTCMISCERR7)<br />+ strlcat(msg, "[HT core Misc7]", msgl);<br />+ if (hwerrs & INFINIPATH_HWE_MEMBISTFAILED) {<br />+ strlcat(msg, "[Memory BIST test failed, HT-400 unusable]",<br />+ msgl);<br />+ /* ignore from now on, so disable until driver reloaded */<br />+ devdata[t].ipath_hwerrmask &= ~INFINIPATH_HWE_MEMBISTFAILED;<br />+ ipath_kput_kreg(t, kr_hwerrmask, devdata[t].ipath_hwerrmask);<br />+ }<br />+#define _IPATH_PLL_FAIL (INFINIPATH_HWE_COREPLL_FBSLIP | \<br />+ INFINIPATH_HWE_COREPLL_RFSLIP | \<br />+ INFINIPATH_HWE_HTBPLL_FBSLIP | \<br />+ INFINIPATH_HWE_HTBPLL_RFSLIP | \<br />+ INFINIPATH_HWE_HTAPLL_FBSLIP | \<br />+ INFINIPATH_HWE_HTAPLL_RFSLIP)<br />+<br />+ if (hwerrs & _IPATH_PLL_FAIL) {<br />+ snprintf(bitsmsg, sizeof bitsmsg,<br />+ "[PLL failed (%llx), HT-400 unusable]",<br />+ hwerrs & _IPATH_PLL_FAIL);<br />+ strlcat(msg, bitsmsg, msgl);<br />+ /* ignore from now on, so disable until driver reloaded */<br />+ devdata[t].ipath_hwerrmask &= ~(hwerrs & _IPATH_PLL_FAIL);<br />+ ipath_kput_kreg(t, kr_hwerrmask, devdata[t].ipath_hwerrmask);<br />+ }<br />+<br />+ if (hwerrs & INFINIPATH_HWE_EXTSERDESPLLFAILED) {<br />+ /*<br />+ * If it occurs, it is left masked since the eternal interface<br />+ * is unused<br />+ */<br />+ devdata[t].ipath_hwerrmask &=<br />+ ~INFINIPATH_HWE_EXTSERDESPLLFAILED;<br />+ ipath_kput_kreg(t, kr_hwerrmask, devdata[t].ipath_hwerrmask);<br />+ }<br />+<br />+ if (hwerrs & INFINIPATH_HWE_RXDSYNCMEMPARITYERR)<br />+ strlcat(msg, "[Rx Dsync]", msgl);<br />+ if (hwerrs & INFINIPATH_HWE_SERDESPLLFAILED)<br />+ strlcat(msg, "[SerDes PLL]", msgl);<br />+<br />+ _IPATH_UNIT_ERROR(t, "%s hardware error\n", msg);<br />+ if (isfatal && (!ipath_diags_enabled)) {<br />+ if (devdata[t].ipath_freezemsg) {<br />+ /*<br />+ * for proc status file ; if no trailing } is copied, we'll know<br />+ * it was truncated.<br />+ */<br />+ snprintf(devdata[t].ipath_freezemsg,<br />+ devdata[t].ipath_freezelen, "{%s}", msg);<br />+ }<br />+ }<br />+}<br />+<br />+/* fill in the board name, based on the board revision register */<br />+void ipath_ht_get_boardname(const ipath_type t, char *name, size_t namelen)<br />+{<br />+ char *n = NULL;<br />+ uint8_t boardrev = devdata[t].ipath_boardrev;<br />+<br />+ switch (boardrev) {<br />+ case 4: /* Ponderosa is one of the bringup boards */<br />+ n = "Ponderosa";<br />+ break;<br />+ case 5: /* HT-460 original production board */<br />+ n = "InfiniPath_HT-460";<br />+ break;<br />+ case 7: /* HT-460 small form factor production board */<br />+ n = "InfiniPath_HT-460-2";<br />+ break;<br />+ case 6:<br />+ n = "OEM_Board_3";<br />+ break;<br />+ case 8:<br />+ n = "LS/X-1";<br />+ break;<br />+ case 9: /* Comstock bringup test board */<br />+ n = "Comstock";<br />+ break;<br />+ case 10:<br />+ n = "OEM_Board_2";<br />+ break;<br />+ case 11:<br />+ n = "OEM_Board_4";<br />+ break;<br />+ default: /* don't know, just print the number */<br />+ _IPATH_ERROR("Don't yet know about board with ID %u\n",<br />+ boardrev);<br />+ snprintf(name, namelen, "UnknownBoardRev%u", boardrev);<br />+ break;<br />+ }<br />+ if (n)<br />+ snprintf(name, namelen, "%s", n);<br />+}<br />+<br />+int ipath_validate_rev(ipath_devdata * dd)<br />+{<br />+ if (dd->ipath_majrev != 3 || dd->ipath_minrev != 2) {<br />+ /*<br />+ * This version of the driver only supports the HT-400<br />+ * Rev 3.2<br />+ */<br />+ _IPATH_UNIT_ERROR(IPATH_UNIT(dd),<br />+ "Unsupported HT-400 revision %u.%u!\n",<br />+ dd->ipath_majrev, dd->ipath_minrev);<br />+ return 1;<br />+ }<br />+ if (dd->ipath_htspeed != 800)<br />+ _IPATH_UNIT_ERROR(IPATH_UNIT(dd),<br />+ "Incorrectly configured for HT @ %uMHz\n",<br />+ dd->ipath_htspeed);<br />+ if(dd->ipath_boardrev == 7 || dd->ipath_boardrev == 11 ||<br />+ dd->ipath_boardrev == 6)<br />+ dd->ipath_flags |= IPATH_GPIO_INTR;<br />+ else if (dd->ipath_boardrev == 8) { /* LS/X-1 */<br />+ uint64_t val;<br />+ val = ipath_kget_kreg64(dd->ipath_pd[0]->port_unit, kr_extstatus);<br />+ if(val & INFINIPATH_EXTS_SERDESSEL) { /* hardware disabled */<br />+ /* This means that the chip is hardware disabled, and will<br />+ * not be able to bring up the link, in any case. We special<br />+ * case this and abort early, to avoid later messages. We<br />+ * also set the DISABLED status bit<br />+ */<br />+ _IPATH_DBG("Unit %u is hardware-disabled\n", <br />+ dd->ipath_pd[0]->port_unit);<br />+ *dd->ipath_statusp |= IPATH_STATUS_DISABLED;<br />+ return 2; /* this value is handled differently */<br />+ }<br />+ }<br />+ return 0;<br />+}<br />+<br />+static void ipath_check_htlink(ipath_type t)<br />+{<br />+ uint8_t linkerr, link_off, i;<br />+<br />+ for (i = 0; i < 2; i++) {<br />+ link_off = devdata[t].ipath_ht_slave_off + i * 4 + 0xd;<br />+ if (pci_read_config_byte(devdata[t].pcidev, link_off, &linkerr))<br />+ _IPATH_INFO<br />+ ("Couldn't read linkerror%d of HT slave/primary block\n",<br />+ i);<br />+ else if (linkerr & 0xf0) {<br />+ _IPATH_VDBG("HT linkerr%d bits 0x%x set, clearing\n",<br />+ linkerr >> 4, i);<br />+ /*<br />+ * writing the linkerr bits that are set should<br />+ * clear them<br />+ */<br />+ if (pci_write_config_byte<br />+ (devdata[t].pcidev, link_off, linkerr))<br />+ _IPATH_DBG<br />+ ("Failed write to clear HT linkerror%d\n",<br />+ i);<br />+ if (pci_read_config_byte<br />+ (devdata[t].pcidev, link_off, &linkerr))<br />+ _IPATH_INFO<br />+ ("Couldn't reread linkerror%d of HT slave/primary block\n",<br />+ i);<br />+ else if (linkerr & 0xf0)<br />+ _IPATH_INFO<br />+ ("HT linkerror%d bits 0x%x couldn't be cleared\n",<br />+ i, linkerr >> 4);<br />+ }<br />+ }<br />+}<br />+<br />+/*<br />+ * now that we have finished initializing everything that might reasonably<br />+ * cause a hardware error, and cleared those errors bits as they occur,<br />+ * we can enable hardware errors in the mask (potentially enabling<br />+ * freeze mode), and enable hardware errors as errors (along with<br />+ * everything else) in errormask<br />+ */<br />+void ipath_clear_init_hwerrs(ipath_type t)<br />+{<br />+ uint64_t val, extsval;<br />+<br />+ extsval = ipath_kget_kreg64(t, kr_extstatus);<br />+<br />+ if (!(extsval & INFINIPATH_EXTS_MEMBIST_ENDTEST))<br />+ _IPATH_UNIT_ERROR(t, "MemBIST did not complete!\n");<br />+<br />+ ipath_check_htlink(t);<br />+<br />+ /* barring bugs, all hwerrors become interrupts, which can */<br />+ val = ~0ULL;<br />+ /* don't look at crc lane1 if 8 bit */<br />+ if (devdata[t].ipath_flags & IPATH_8BIT_IN_HT0)<br />+ val &= ~infinipath_hwe_htclnkabyte1crcerr;<br />+ /* don't look at crc lane1 if 8 bit */<br />+ if (devdata[t].ipath_flags & IPATH_8BIT_IN_HT1)<br />+ val &= ~infinipath_hwe_htclnkbbyte1crcerr;<br />+<br />+ /*<br />+ * disable RXDSYNCMEMPARITY because external serdes is unused,<br />+ * and therefore the logic will never be used or initialized,<br />+ * and uninitialized state will normally result in this error<br />+ * being asserted. Similarly for the external serdess pll<br />+ * lock signal.<br />+ */<br />+ val &=<br />+ ~(INFINIPATH_HWE_EXTSERDESPLLFAILED |<br />+ INFINIPATH_HWE_RXDSYNCMEMPARITYERR);<br />+<br />+ /*<br />+ * Disable MISCERR4 because of an inversion in the HT core<br />+ * logic checking for errors that cause this bit to be set.<br />+ * The errata can also cause the protocol error bit to be set<br />+ * in the HT config space linkerror register(s).<br />+ */<br />+ val &= ~INFINIPATH_HWE_HTCMISCERR4;<br />+<br />+ /*<br />+ * PLL ignored because MDIO interface has a logic problem for reads,<br />+ * on Comstock and Ponderosa. BRINGUP<br />+ */<br />+ if (devdata[t].ipath_boardrev == 4 || devdata[t].ipath_boardrev == 9)<br />+ val &= ~INFINIPATH_HWE_EXTSERDESPLLFAILED; /* BRINGUP */<br />+ devdata[t].ipath_hwerrmask = val;<br />+}<br />+<br />+/* bring up the serdes */<br />+int ipath_bringup_serdes(ipath_type t)<br />+{<br />+ uint64_t val, config1;<br />+ int ret = 0, change = 0;<br />+<br />+ _IPATH_DBG("Trying to bringup serdes\n");<br />+<br />+ if (ipath_kget_kreg64(t, kr_hwerrstatus) &<br />+ INFINIPATH_HWE_SERDESPLLFAILED) {<br />+ _IPATH_DBG<br />+ ("At start, serdes PLL failed bit set in hwerrstatus, clearing and continuing\n");<br />+ ipath_kput_kreg(t, kr_hwerrclear,<br />+ INFINIPATH_HWE_SERDESPLLFAILED);<br />+ }<br />+<br />+ val = ipath_kget_kreg64(t, kr_serdesconfig0);<br />+ config1 = ipath_kget_kreg64(t, kr_serdesconfig1);<br />+<br />+ _IPATH_VDBG<br />+ ("Initial serdes status is config0=%llx config1=%llx, sstatus=%llx xgxs %llx\n",<br />+ val, config1, ipath_kget_kreg64(t, kr_serdesstatus),<br />+ ipath_kget_kreg64(t, kr_xgxsconfig));<br />+<br />+ /* force reset on */<br />+ val |=<br />+ INFINIPATH_SERDC0_RESET_PLL /* | INFINIPATH_SERDC0_RESET_MASK */ ;<br />+ ipath_kput_kreg(t, kr_serdesconfig0, val);<br />+ udelay(15); /* need pll reset set at least for a bit */<br />+<br />+ if (val & INFINIPATH_SERDC0_RESET_PLL) {<br />+ uint64_t val2 = val &= ~INFINIPATH_SERDC0_RESET_PLL;<br />+ /* set lane resets, and tx idle, during pll reset */<br />+ val2 |= INFINIPATH_SERDC0_RESET_MASK | INFINIPATH_SERDC0_TXIDLE;<br />+ _IPATH_VDBG("Clearing serdes PLL reset (writing %llx)\n", val2);<br />+ ipath_kput_kreg(t, kr_serdesconfig0, val2);<br />+ /* be sure chip saw it */<br />+ val = ipath_kget_kreg64(t, kr_scratch);<br />+ /*<br />+ * need pll reset clear at least 11 usec before lane resets<br />+ * cleared; give it a few more<br />+ */<br />+ udelay(15);<br />+ val = val2; /* for check below */<br />+ }<br />+<br />+ if (val & (INFINIPATH_SERDC0_RESET_PLL | INFINIPATH_SERDC0_RESET_MASK<br />+ | INFINIPATH_SERDC0_TXIDLE)) {<br />+ val &=<br />+ ~(INFINIPATH_SERDC0_RESET_PLL | INFINIPATH_SERDC0_RESET_MASK<br />+ | INFINIPATH_SERDC0_TXIDLE);<br />+ ipath_kput_kreg(t, kr_serdesconfig0, val); /* clear them */<br />+ }<br />+<br />+ val = ipath_kget_kreg64(t, kr_xgxsconfig);<br />+ if (((val >> INFINIPATH_XGXS_MDIOADDR_SHIFT) &<br />+ INFINIPATH_XGXS_MDIOADDR_MASK) != 3) {<br />+ val &=<br />+ ~(INFINIPATH_XGXS_MDIOADDR_MASK <<<br />+ INFINIPATH_XGXS_MDIOADDR_SHIFT);<br />+ /* we use address 3 */<br />+ val |= 3ULL << INFINIPATH_XGXS_MDIOADDR_SHIFT;<br />+ change = 1;<br />+ }<br />+ if (val & INFINIPATH_XGXS_RESET) { /* normally true after boot */<br />+ val &= ~INFINIPATH_XGXS_RESET;<br />+ change = 1;<br />+ }<br />+ if (change)<br />+ ipath_kput_kreg(t, kr_xgxsconfig, val);<br />+<br />+ val = ipath_kget_kreg64(t, kr_serdesconfig0);<br />+<br />+ config1 &= ~0x0ffffffff00ULL; /* clear current and de-emphasis bits */<br />+ config1 |= 0x00000000000ULL; /* set current to 20ma */<br />+ config1 |= 0x0cccc000000ULL; /* set de-emphasis to -5.68dB */<br />+ ipath_kput_kreg(t, kr_serdesconfig1, config1);<br />+<br />+ _IPATH_VDBG<br />+ ("After setup: serdes status is config0=%llx config1=%llx, sstatus=%llx xgxs %llx\n",<br />+ val, config1, ipath_kget_kreg64(t, kr_serdesstatus),<br />+ ipath_kget_kreg64(t, kr_xgxsconfig));<br />+<br />+ if ((!ipath_waitfor_mdio_cmdready(t))) {<br />+ ipath_kput_kreg(t, kr_mdio, IPATH_MDIO_REQ(IPATH_MDIO_CMD_READ,<br />+ 31,<br />+ IPATH_MDIO_CTRL_XGXS_REG_8,<br />+ 0));<br />+ if (ipath_waitfor_complete<br />+ (t, kr_mdio, IPATH_MDIO_DATAVALID, &val))<br />+ _IPATH_DBG<br />+ ("Never got MDIO data for XGXS status read\n");<br />+ else<br />+ _IPATH_VDBG("MDIO Read reg8, 'bank' 31 %x\n",<br />+ (uint32_t) val);<br />+ } else<br />+ _IPATH_DBG("Never got MDIO cmdready for XGXS status read\n");<br />+<br />+ return ret; /* for now, say we always succeeded */<br />+}<br />+<br />+/* set serdes to txidle; driver is being unloaded */<br />+void ipath_quiet_serdes(const ipath_type t)<br />+{<br />+ uint64_t val = ipath_kget_kreg64(t, kr_serdesconfig0);<br />+<br />+ val |= INFINIPATH_SERDC0_TXIDLE;<br />+ _IPATH_DBG("Setting TxIdleEn on serdes (config0 = %llx)\n", val);<br />+ ipath_kput_kreg(t, kr_serdesconfig0, val);<br />+}<br />+<br />+EXPORT_SYMBOL(ipath_get_unit_name);<br />+<br />+#endif /* __KERNEL__ */<br />diff --git a/drivers/infiniband/hw/ipath/ipath_i2c.c b/drivers/infiniband/hw/ipath/ipath_i2c.c<br />new file mode 100644<br />index 0000000..4ee3d46<br />--- /dev/null<br />+++ b/drivers/infiniband/hw/ipath/ipath_i2c.c<br />@@ -0,0 +1,472 @@<br />+/*<br />+ * Copyright (c) 2003, 2004, 2005. PathScale, Inc. All rights reserved.<br />+ *<br />+ * This software is available to you under a choice of one of two<br />+ * licenses. You may choose to be licensed under the terms of the GNU<br />+ * General Public License (GPL) Version 2, available from the file<br />+ * COPYING in the main directory of this source tree, or the<br />+ * OpenIB.org BSD license below:<br />+ *<br />+ * Redistribution and use in source and binary forms, with or<br />+ * without modification, are permitted provided that the following<br />+ * conditions are met:<br />+ *<br />+ * - Redistributions of source code must retain the above<br />+ * copyright notice, this list of conditions and the following<br />+ * disclaimer.<br />+ *<br />+ * - Redistributions in binary form must reproduce the above<br />+ * copyright notice, this list of conditions and the following<br />+ * disclaimer in the documentation and/or other materials<br />+ * provided with the distribution.<br />+ *<br />+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,<br />+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF<br />+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND<br />+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS<br />+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN<br />+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN<br />+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE<br />+ * SOFTWARE.<br />+ *<br />+ * Patent licenses, if any, provided herein do not apply to<br />+ * combinations of this program with other software, or any other<br />+ * product whatsoever.<br />+ *<br />+ * $Id: ipath_i2c.c 4365 2005-12-10 00:04:16Z rjwalsh $<br />+ */<br />+<br />+#include <linux/config.h><br />+#include <linux/version.h><br />+#include <linux/kernel.h><br />+#include <linux/errno.h><br />+#include <linux/types.h><br />+#include <linux/mm.h><br />+#include <linux/string.h><br />+#include <linux/timer.h><br />+#include <linux/delay.h><br />+<br />+#include "ipath_kernel.h"<br />+#include "ips_common.h"<br />+#include "ipath_layer.h"<br />+<br />+/*<br />+ * InfiniPath I2C Driver for onboard flash<br />+ * Bus Master, Standard Speed only.<br />+ * HT-460 uses the Atmel AT24C01 I2C serial FLASH part.<br />+ * This part is a 1Kbit part, that uses no programmable address bits,<br />+ * (the address is 1010000b)<br />+ */<br />+<br />+typedef enum i2c_line_type_e {<br />+ i2c_line_scl = 0,<br />+ i2c_line_sda<br />+} ipath_i2c_type;<br />+<br />+typedef enum i2c_line_state_e {<br />+ i2c_line_low = 0,<br />+ i2c_line_high<br />+} ipath_i2c_state;<br />+<br />+#define READ_CMD 1<br />+#define WRITE_CMD 0<br />+<br />+static int ipath_eeprom_init;<br />+<br />+/*<br />+ * The gpioval manipulation really should be protected by spinlocks<br />+ * or be converted to use atomic operations (unfortunately, atomic.h<br />+ * doesn't cover 64 bit ops for some of them).<br />+ */<br />+<br />+int i2c_gpio_set(ipath_type dev, ipath_i2c_type line,<br />+ ipath_i2c_state new_line_state);<br />+int i2c_gpio_get(ipath_type dev, ipath_i2c_type line,<br />+ ipath_i2c_state * curr_statep);<br />+<br />+/*<br />+ * returns 0 if the line was set to the new state successfully, non-zero<br />+ * on error.<br />+ */<br />+int i2c_gpio_set(ipath_type dev, ipath_i2c_type line,<br />+ ipath_i2c_state new_line_state)<br />+{<br />+ uint64_t read_val, write_val, mask, *gpioval;<br />+<br />+ gpioval = &devdata[dev].ipath_gpio_out;<br />+ read_val = ipath_kget_kreg64(dev, kr_extctrl);<br />+ if (line == i2c_line_scl)<br />+ mask = ipath_gpio_scl;<br />+ else<br />+ mask = ipath_gpio_sda;<br />+<br />+ if (new_line_state == i2c_line_high)<br />+ /* tri-state the output rather than force high */<br />+ write_val = read_val & ~mask;<br />+ else<br />+ /* config line to be an output */<br />+ write_val = read_val | mask;<br />+ ipath_kput_kreg(dev, kr_extctrl, write_val);<br />+<br />+ /* set high and verify */<br />+ if (new_line_state == i2c_line_high)<br />+ write_val = 0x1UL;<br />+ else<br />+ write_val = 0x0UL;<br />+<br />+ if (line == i2c_line_scl) {<br />+ write_val <<= ipath_gpio_scl_num;<br />+ *gpioval = *gpioval & ~(1UL << ipath_gpio_scl_num);<br />+ *gpioval |= write_val;<br />+ } else {<br />+ write_val <<= ipath_gpio_sda_num;<br />+ *gpioval = *gpioval & ~(1UL << ipath_gpio_sda_num);<br />+ *gpioval |= write_val;<br />+ }<br />+ ipath_kput_kreg(dev, kr_gpio_out, *gpioval);<br />+<br />+ return 0;<br />+}<br />+<br />+/*<br />+ * returns 0 if the line was set to the new state successfully, non-zero<br />+ * on error. curr_state is not set on error.<br />+ */<br />+int i2c_gpio_get(ipath_type dev, ipath_i2c_type line,<br />+ ipath_i2c_state * curr_statep)<br />+{<br />+ uint64_t read_val, write_val, mask;<br />+<br />+ /* check args */<br />+ if (curr_statep == NULL)<br />+ return 1;<br />+<br />+ read_val = ipath_kget_kreg64(dev, kr_extctrl);<br />+ /* config line to be an input */<br />+ if (line == i2c_line_scl)<br />+ mask = ipath_gpio_scl;<br />+ else<br />+ mask = ipath_gpio_sda;<br />+ write_val = read_val & ~mask;<br />+ ipath_kput_kreg(dev, kr_extctrl, write_val);<br />+ read_val = ipath_kget_kreg64(dev, kr_extstatus);<br />+<br />+ if (read_val & mask)<br />+ *curr_statep = i2c_line_high;<br />+ else<br />+ *curr_statep = i2c_line_low;<br />+<br />+ return 0;<br />+}<br />+<br />+/*<br />+ * would prefer to not inline this, to avoid code bloat, and simplify debugging<br />+ * But when compiling against 2.6.10 kernel tree, it gets an error, so<br />+ * not for now.<br />+ */<br />+static void ipath_i2c_delay(ipath_type, int);<br />+<br />+/*<br />+ * we use this instead of udelay directly, so we can make sure<br />+ * that previous register writes have been flushed all the way<br />+ * to the chip. Since we are delaying anyway, the cost doesn't<br />+ * hurt, and makes the bit twiddling more regular<br />+ * If delay is negative, we'll do the chip read, to be sure write made it<br />+ * to our chip, but won't do udelay()<br />+ */<br />+static void ipath_i2c_delay(ipath_type dev, int dtime)<br />+{<br />+ /*<br />+ * This needs to be volatile, so that the compiler doesn't<br />+ * optimize away the read to the device's mapped memory.<br />+ */<br />+ volatile uint32_t read_val;<br />+ if (!dtime)<br />+ return;<br />+ read_val = ipath_kget_kreg32(dev, kr_scratch);<br />+ if (--dtime > 0) /* register read takes about .5 usec, itself */<br />+ udelay(dtime);<br />+}<br />+<br />+static void ipath_scl_out(ipath_type dev, uint8_t bit, int delay)<br />+{<br />+ i2c_gpio_set(dev, i2c_line_scl, bit ? i2c_line_high : i2c_line_low);<br />+<br />+ ipath_i2c_delay(dev, delay);<br />+}<br />+<br />+static void ipath_sda_out(ipath_type dev, uint8_t bit, int delay)<br />+{<br />+ i2c_gpio_set(dev, i2c_line_sda, bit ? i2c_line_high : i2c_line_low);<br />+<br />+ ipath_i2c_delay(dev, delay);<br />+}<br />+<br />+static uint8_t ipath_sda_in(ipath_type dev, int delay)<br />+{<br />+ ipath_i2c_state bit;<br />+<br />+ if (i2c_gpio_get(dev, i2c_line_sda, &bit))<br />+ _IPATH_DBG("get bit failed!\n");<br />+<br />+ ipath_i2c_delay(dev, delay);<br />+<br />+ return bit == i2c_line_high ? 1U : 0;<br />+}<br />+<br />+/* see if ack following write is true */<br />+static int ipath_i2c_ackrcv(ipath_type dev)<br />+{<br />+ uint8_t ack_received;<br />+<br />+ /* AT ENTRY SCL = LOW */<br />+ /* change direction, ignore data */<br />+ ack_received = ipath_sda_in(dev, 1);<br />+ ipath_scl_out(dev, i2c_line_high, 1);<br />+ ack_received = ipath_sda_in(dev, 1) == 0;<br />+ ipath_scl_out(dev, i2c_line_low, 1);<br />+ return ack_received;<br />+}<br />+<br />+/*<br />+ * write a byte, one bit at a time. Returns 0 if we got the following<br />+ * ack, otherwise 1<br />+ */<br />+static int ipath_wr_byte(ipath_type dev, uint8_t data)<br />+{<br />+ int bit_cntr;<br />+ uint8_t bit;<br />+<br />+ for (bit_cntr = 7; bit_cntr >= 0; bit_cntr--) {<br />+ bit = (data >> bit_cntr) & 1;<br />+ ipath_sda_out(dev, bit, 1);<br />+ ipath_scl_out(dev, i2c_line_high, 1);<br />+ ipath_scl_out(dev, i2c_line_low, 1);<br />+ }<br />+ if (!ipath_i2c_ackrcv(dev))<br />+ return 1;<br />+ return 0;<br />+}<br />+<br />+static void send_ack(ipath_type dev)<br />+{<br />+ ipath_sda_out(dev, i2c_line_low, 1);<br />+ ipath_scl_out(dev, i2c_line_high, 1);<br />+ ipath_scl_out(dev, i2c_line_low, 1);<br />+ ipath_sda_out(dev, i2c_line_high, 1);<br />+}<br />+<br />+/*<br />+ * ipath_i2c_startcmd - Transmit the start condition, followed by<br />+ * address/cmd<br />+ * (both clock/data high, clock high, data low while clock is high)<br />+ */<br />+static int ipath_i2c_startcmd(ipath_type dev, uint8_t offset_dir)<br />+{<br />+ int res;<br />+<br />+ /* issue start sequence */<br />+ ipath_sda_out(dev, i2c_line_high, 1);<br />+ ipath_scl_out(dev, i2c_line_high, 1);<br />+ ipath_sda_out(dev, i2c_line_low, 1);<br />+ ipath_scl_out(dev, i2c_line_low, 1);<br />+<br />+ /* issue length and direction byte */<br />+ res = ipath_wr_byte(dev, offset_dir);<br />+<br />+ if (res)<br />+ _IPATH_VDBG("No ack to complete start\n");<br />+ return res;<br />+}<br />+<br />+/*<br />+ * stop_cmd - Transmit the stop condition<br />+ * (both clock/data low, clock high, data high while clock is high)<br />+ */<br />+static void stop_cmd(ipath_type dev)<br />+{<br />+ ipath_scl_out(dev, i2c_line_low, 1);<br />+ ipath_sda_out(dev, i2c_line_low, 1);<br />+ ipath_scl_out(dev, i2c_line_high, 1);<br />+ ipath_sda_out(dev, i2c_line_high, 3);<br />+}<br />+<br />+/*<br />+ * ipath_eeprom_reset - reset I2C communication.<br />+ *<br />+ * eeprom: Atmel AT24C01<br />+ *<br />+ */<br />+<br />+static int ipath_eeprom_reset(ipath_type dev)<br />+{<br />+ int clock_cycles_left = 9;<br />+ uint64_t *gpioval = &devdata[dev].ipath_gpio_out;<br />+<br />+ ipath_eeprom_init = 1;<br />+ *gpioval = ipath_kget_kreg64(dev, kr_gpio_out);<br />+ _IPATH_VDBG("Resetting i2c flash; initial gpioout reg is %llx\n",<br />+ *gpioval);<br />+<br />+ /*<br />+ * This is to get the i2c into a known state, by first going low,<br />+ * then tristate sda (and then tristate scl as first thing in loop)<br />+ */<br />+ ipath_scl_out(dev, i2c_line_low, 1);<br />+ ipath_sda_out(dev, i2c_line_high, 1);<br />+<br />+ while (clock_cycles_left--) {<br />+ ipath_scl_out(dev, i2c_line_high, 1);<br />+<br />+ if (ipath_sda_in(dev, 0)) {<br />+ ipath_sda_out(dev, i2c_line_low, 1);<br />+ ipath_scl_out(dev, i2c_line_low, 1);<br />+ return 0;<br />+ }<br />+<br />+ ipath_scl_out(dev, i2c_line_low, 1);<br />+ }<br />+<br />+ return 1;<br />+}<br />+<br />+/*<br />+ * ipath_eeprom_read - Receives x # byte from the eeprom via I2C.<br />+ *<br />+ * eeprom: Atmel AT24C01<br />+ *<br />+ */<br />+<br />+int ipath_eeprom_read(ipath_type dev, uint8_t eeprom_offset, void *buffer,<br />+ int len)<br />+{<br />+ /* compiler complains unless initialized */<br />+ uint8_t single_byte = 0;<br />+ int bit_cntr;<br />+<br />+ if (!ipath_eeprom_init)<br />+ ipath_eeprom_reset(dev);<br />+<br />+ eeprom_offset = (eeprom_offset << 1) | READ_CMD;<br />+<br />+ if (ipath_i2c_startcmd(dev, eeprom_offset)) {<br />+ _IPATH_DBG("Failed startcmd\n");<br />+ stop_cmd(dev);<br />+ return 1;<br />+ }<br />+<br />+ /*<br />+ * flash keeps clocking data out as long as we ack, automatically<br />+ * incrementing the address.<br />+ */<br />+ while (len-- > 0) {<br />+ /* get data */<br />+ single_byte = 0;<br />+ for (bit_cntr = 8; bit_cntr; bit_cntr--) {<br />+ uint8_t bit;<br />+ ipath_scl_out(dev, i2c_line_high, 1);<br />+ bit = ipath_sda_in(dev, 0);<br />+ single_byte |= bit << (bit_cntr - 1);<br />+ ipath_scl_out(dev, i2c_line_low, 1);<br />+ }<br />+<br />+ /* send ack if not the last byte */<br />+ if (len)<br />+ send_ack(dev);<br />+<br />+ *((uint8_t *) buffer) = single_byte;<br />+ (uint8_t *) buffer++;<br />+ }<br />+<br />+ stop_cmd(dev);<br />+<br />+ return 0;<br />+}<br />+<br />+/*<br />+ * ipath_eeprom_write - writes data to the eeprom via I2C.<br />+ *<br />+*/<br />+int ipath_eeprom_write(ipath_type dev, uint8_t eeprom_offset, void *buffer,<br />+ int len)<br />+{<br />+ uint8_t single_byte;<br />+ int sub_len;<br />+ uint8_t *bp = buffer;<br />+ int max_wait_time, i;<br />+<br />+ if (!ipath_eeprom_init)<br />+ ipath_eeprom_reset(dev);<br />+<br />+ while (len > 0) {<br />+ if (ipath_i2c_startcmd(dev, (eeprom_offset << 1) | WRITE_CMD)) {<br />+ _IPATH_DBG("Failed to start cmd offset %u\n",<br />+ eeprom_offset);<br />+ goto failed_write;<br />+ }<br />+<br />+ sub_len = min(len, 4);<br />+ eeprom_offset += sub_len;<br />+ len -= sub_len;<br />+<br />+ for (i = 0; i < sub_len; i++) {<br />+ if (ipath_wr_byte(dev, *bp++)) {<br />+ _IPATH_DBG<br />+ ("no ack after byte %u/%u (%u total remain)\n",<br />+ i, sub_len, len + sub_len - i);<br />+ goto failed_write;<br />+ }<br />+ }<br />+<br />+ stop_cmd(dev);<br />+<br />+ /*<br />+ * wait for write complete by waiting for a successful<br />+ * read (the chip replies with a zero after the write<br />+ * cmd completes, and before it writes to the flash.<br />+ * The startcmd for the read will fail the ack until<br />+ * the writes have completed. We do this inline to avoid<br />+ * the debug prints that are in the real read routine<br />+ * if the startcmd fails.<br />+ */<br />+ max_wait_time = 100;<br />+ while (ipath_i2c_startcmd(dev, READ_CMD)) {<br />+ stop_cmd(dev);<br />+ if (!--max_wait_time) {<br />+ _IPATH_DBG<br />+ ("Did not get successful read to complete write\n");<br />+ goto failed_write;<br />+ }<br />+ }<br />+ /* now read the zero byte */<br />+ for (i = single_byte = 0; i < 8; i++) {<br />+ uint8_t bit;<br />+ ipath_scl_out(dev, i2c_line_high, 1);<br />+ bit = ipath_sda_in(dev, 0);<br />+ ipath_scl_out(dev, i2c_line_low, 1);<br />+ single_byte <<= 1;<br />+ single_byte |= bit;<br />+ }<br />+ stop_cmd(dev);<br />+ }<br />+<br />+ return 0;<br />+<br />+failed_write:<br />+ stop_cmd(dev);<br />+ return 1;<br />+}<br />+<br />+uint8_t ipath_flash_csum(struct ipath_flash * ifp, int adjust)<br />+{<br />+ uint8_t *ip = (uint8_t *) ifp;<br />+ uint8_t csum = 0, len;<br />+<br />+ for (len = 0; len < ifp->if_length; len++)<br />+ csum += *ip++;<br />+ csum -= ifp->if_csum;<br />+ csum = ~csum;<br />+ if (adjust)<br />+ ifp->if_csum = csum;<br />+ return csum;<br />+}<br />diff --git a/drivers/infiniband/hw/ipath/ipath_lib.c b/drivers/infiniband/hw/ipath/ipath_lib.c<br />new file mode 100644<br />index 0000000..d9a40b8<br />--- /dev/null<br />+++ b/drivers/infiniband/hw/ipath/ipath_lib.c<br />@@ -0,0 +1,92 @@<br />+/*<br />+ * Copyright (c) 2003, 2004, 2005. PathScale, Inc. All rights reserved.<br />+ *<br />+ * This software is available to you under a choice of one of two<br />+ * licenses. You may choose to be licensed under the terms of the GNU<br />+ * General Public License (GPL) Version 2, available from the file<br />+ * COPYING in the main directory of this source tree, or the<br />+ * OpenIB.org BSD license below:<br />+ *<br />+ * Redistribution and use in source and binary forms, with or<br />+ * without modification, are permitted provided that the following<br />+ * conditions are met:<br />+ *<br />+ * - Redistributions of source code must retain the above<br />+ * copyright notice, this list of conditions and the following<br />+ * disclaimer.<br />+ *<br />+ * - Redistributions in binary form must reproduce the above<br />+ * copyright notice, this list of conditions and the following<br />+ * disclaimer in the documentation and/or other materials<br />+ * provided with the distribution.<br />+ *<br />+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,<br />+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF<br />+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND<br />+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS<br />+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN<br />+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN<br />+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE<br />+ * SOFTWARE.<br />+ *<br />+ * Patent licenses, if any, provided herein do not apply to<br />+ * combinations of this program with other software, or any other<br />+ * product whatsoever.<br />+ *<br />+ * $Id: ipath_lib.c 4365 2005-12-10 00:04:16Z rjwalsh $<br />+ */<br />+<br />+/*<br />+ * This is library code for the driver, similar to what's in libinfinipath for<br />+ * usermode code.<br />+ */<br />+<br />+#include <linux/config.h><br />+#include <linux/version.h><br />+#include <linux/kernel.h><br />+#include <linux/errno.h><br />+#include <linux/types.h><br />+#include <linux/string.h><br />+#include <linux/delay.h><br />+#include <linux/timer.h><br />+#include <linux/fs.h><br />+#include <linux/poll.h><br />+#include <asm/io.h><br />+#include <asm/byteorder.h><br />+#include <asm/uaccess.h><br />+<br />+#include "ipath_kernel.h"<br />+<br />+unsigned infinipath_debug = __IPATH_INFO;<br />+<br />+uint32_t _ipath_pico_per_cycle; /* always present, for now */<br />+<br />+/*<br />+ * This isn't perfect, but it's close enough for timing work. We want this<br />+ * to work on systems where the cycle counter isn't the same as the clock<br />+ * frequency. The one msec spin is OK, since we execute this only once<br />+ * when first loaded. We don't use CURRENT_TIME because on some systems<br />+ * it only has jiffy resolution; we just assume udelay is well calibrated<br />+ * and that we aren't likely to be rescheduled. Do it multiple times,<br />+ * with a yield in between, to try to make sure we get the "true minimum"<br />+ * value.<br />+ * _ipath_pico_per_cycle isn't going to lead to completely accurate<br />+ * conversions from timestamps to nanoseconds, but it's close enough<br />+ * for our purposes, which is mainly to allow people to show events with<br />+ * nsecs or usecs if desired, rather than cycles.<br />+ */<br />+void ipath_init_picotime(void)<br />+{<br />+ int i;<br />+ u_int64_t ts, te, delta = -1ULL;<br />+<br />+ for (i = 0; i < 5; i++) {<br />+ ts = get_cycles();<br />+ udelay(250);<br />+ te = get_cycles();<br />+ if ((te - ts) < delta)<br />+ delta = te - ts;<br />+ yield();<br />+ }<br />+ _ipath_pico_per_cycle = 250000000 / delta;<br />+}<br />diff --git a/drivers/infiniband/hw/ipath/ipath_mlock.c b/drivers/infiniband/hw/ipath/ipath_mlock.c<br />new file mode 100644<br />index 0000000..72eb7c0<br />--- /dev/null<br />+++ b/drivers/infiniband/hw/ipath/ipath_mlock.c<br />@@ -0,0 +1,139 @@<br />+/*<br />+ * Copyright (c) 2003, 2004, 2005. PathScale, Inc. All rights reserved.<br />+ *<br />+ * This software is available to you under a choice of one of two<br />+ * licenses. You may choose to be licensed under the terms of the GNU<br />+ * General Public License (GPL) Version 2, available from the file<br />+ * COPYING in the main directory of this source tree, or the<br />+ * OpenIB.org BSD license below:<br />+ *<br />+ * Redistribution and use in source and binary forms, with or<br />+ * without modification, are permitted provided that the following<br />+ * conditions are met:<br />+ *<br />+ * - Redistributions of source code must retain the above<br />+ * copyright notice, this list of conditions and the following<br />+ * disclaimer.<br />+ *<br />+ * - Redistributions in binary form must reproduce the above<br />+ * copyright notice, this list of conditions and the following<br />+ * disclaimer in the documentation and/or other materials<br />+ * provided with the distribution.<br />+ *<br />+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,<br />+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF<br />+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND<br />+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS<br />+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN<br />+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN<br />+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE<br />+ * SOFTWARE.<br />+ *<br />+ * Patent licenses, if any, provided herein do not apply to<br />+ * combinations of this program with other software, or any other<br />+ * product whatsoever.<br />+ *<br />+ * $Id: ipath_mlock.c 4365 2005-12-10 00:04:16Z rjwalsh $<br />+ */<br />+<br />+#include <stddef.h><br />+<br />+#include <linux/config.h><br />+#include <linux/version.h><br />+#include <linux/kernel.h><br />+#include <linux/types.h><br />+#include <linux/string.h><br />+#include <linux/delay.h><br />+#include <linux/slab.h><br />+#include <linux/mm.h><br />+#include <linux/spinlock.h><br />+<br />+#include <asm/page.h><br />+#include <asm/io.h><br />+<br />+#include "ipath_kernel.h"<br />+<br />+/*<br />+ * Our version of the kernel mlock function. This function is no longer<br />+ * exposed, so we need to do it ourselves. It takes a given start page<br />+ * (page aligned user virtual address) and pins it and the following specified<br />+ * number of pages.<br />+ * For now, num_pages is always 1, but that will probably change at some<br />+ * point (because caller is doing expected sends on a single virtually<br />+ * contiguous buffer, so we can do all pages at once).<br />+ */<br />+int ipath_mlock(unsigned long start_page, size_t num_pages, struct page **p)<br />+{<br />+ int n;<br />+<br />+ _IPATH_VDBG("pin %lx pages from vaddr %lx\n", num_pages, start_page);<br />+ down_read(&current->mm->mmap_sem);<br />+ n = get_user_pages(current, current->mm, start_page, num_pages, 1, 1,<br />+ p, NULL);<br />+ up_read(&current->mm->mmap_sem);<br />+ if (n != num_pages) {<br />+ _IPATH_INFO<br />+ ("get_user_pages (0x%lx pages starting at 0x%lx failed with %d\n",<br />+ num_pages, start_page, n);<br />+ if (n < 0) /* it's an errno */<br />+ return n;<br />+ return -ENOMEM; /* no way to know actual error */<br />+ }<br />+<br />+ return 0;<br />+}<br />+<br />+/*<br />+ * this is similar to ipath_mlock, but it's always one page, and we mark<br />+ * the page as locked for i/o, and shared. This is used for the user process<br />+ * page that contains the destination address for the rcvhdrq tail update,<br />+ * so we need to have the vma. If we don't do this, the page can be taken<br />+ * away from us on fork, even if the child never touches it, and then<br />+ * the user process never sees the tail register updates.<br />+ */<br />+int ipath_mlock_nocopy(unsigned long start_page, struct page **p)<br />+{<br />+ int n;<br />+ struct vm_area_struct *vm = NULL;<br />+<br />+ down_read(&current->mm->mmap_sem);<br />+ n = get_user_pages(current, current->mm, start_page, 1, 1, 1, p, &vm);<br />+ up_read(&current->mm->mmap_sem);<br />+ if (n != 1) {<br />+ _IPATH_INFO("get_user_pages for 0x%lx failed with %d\n",<br />+ start_page, n);<br />+ if (n < 0) /* it's an errno */<br />+ return n;<br />+ return -ENOMEM; /* no way to know actual error */<br />+ }<br />+ vm->vm_flags |= VM_SHM | VM_LOCKED;<br />+<br />+ return 0;<br />+}<br />+<br />+/*<br />+ * Our version of the kernel munlock function. This function is no longer<br />+ * exposed, so we need to do it ourselves. It unpins the start page<br />+ * (a page aligned full user virtual address, not a page number)<br />+ * and pins it and the following specified number of pages.<br />+ */<br />+int ipath_munlock(size_t num_pages, struct page **p)<br />+{<br />+ int i;<br />+<br />+ for (i = 0; i < num_pages; i++) {<br />+ _IPATH_MMDBG("%u/%lu put_page %p\n", i, num_pages, p[i]);<br />+ SetPageDirty(p[i]);<br />+ put_page(p[i]);<br />+ }<br />+ return 0;<br />+}<br />+<br />+/*<br />+ * This routine frees up all the allocations made in this file; it's a nop<br />+ * now, but I'm leaving it in case we go back to a more sophisticated<br />+ * implementation later.<br />+ */<br />+void ipath_mlock_cleanup(ipath_portdata * pd)<br />+{<br />+}<br />-- <br />0.99.9n<br />-<br />To unsubscribe from this list: send the line "unsubscribe linux-kernel" in<br />the body of a message to majordomo@vger.kernel.org<br />More majordomo info at <a href="http://vger.kernel.org/majordomo-info.html">http://vger.kernel.org/majordomo-info.html</a><br />Please read the FAQ at <a href="http://www.tux.org/lkml/">http://www.tux.org/lkml/</a><br /></pre></td><td width="32" rowspan="2" class="c" valign="top"><img src="/images/icornerr.gif" width="32" height="32" alt="\" /></td></tr><tr><td align="right" valign="bottom"> 聽 </td></tr><tr><td align="right" valign="bottom">聽</td><td class="c" valign="bottom" style="padding-bottom: 0px"><img src="/images/bcornerl.gif" width="32" height="32" alt="\" /></td><td class="c">聽</td><td class="c" valign="bottom" style="padding-bottom: 0px"><img src="/images/bcornerr.gif" width="32" height="32" alt="/" /></td></tr><tr><td align="right" valign="top" colspan="2"> 聽 </td><td class="lm">Last update: 2005-12-17 00:57 聽聽 [from the cache]<br />漏2003-2020 <a href="http://blog.jasper.es/"><span itemprop="editor">Jasper Spaans</span></a>|hosted at <a href="https://www.digitalocean.com/?refcode=9a8e99d24cf9">Digital Ocean</a> and my Meterkast|<a href="http://blog.jasper.es/categories.html#lkml-ref">Read the blog</a></td><td>聽</td></tr></table><script language="javascript" src="/js/styleswitcher.js" type="text/javascript"></script></body></html>