📄 skgesirq.c
字号:
/****************************************************************************** * * SkGePortCheckUp - Implementation of the Workaround for Errata #2 * * return: * 0 o.k. nothing needed * 1 Restart needed on this port * 2 Link came up */int SkGePortCheckUp(SK_AC *pAC, /* Adapter Context */SK_IOC IoC, /* IO Context */int Port) /* Which port should be checked */{ switch (pAC->GIni.GP[Port].PhyType) { case SK_PHY_XMAC: return (SkGePortCheckUpXmac(pAC, IoC, Port)); case SK_PHY_BCOM: return (SkGePortCheckUpBcom(pAC, IoC, Port)); case SK_PHY_LONE: return (SkGePortCheckUpLone(pAC, IoC, Port)); case SK_PHY_NAT: return (SkGePortCheckUpNat(pAC, IoC, Port)); } return (SK_HW_PS_NONE);} /* SkGePortCheckUp *//****************************************************************************** * * SkGePortCheckUpXmac - Implementing of the Workaround Errata # 2 * * return: * 0 o.k. nothing needed * 1 Restart needed on this port * 2 Link came up */static int SkGePortCheckUpXmac(SK_AC *pAC, /* Adapter Context */SK_IOC IoC, /* IO Context */int Port) /* Which port should be checked */{ SK_U64 Shorts; /* Short Event Counter */ SK_GEPORT *pPrt; /* GIni Port struct pointer */ unsigned Len; int Done; SK_U32 GpReg; /* General Purpose register value */ SK_U16 Isrc; /* Interrupt source register */ SK_U16 IsrcSum; /* Interrupt source register sum */ SK_U16 LpAb; /* Link Partner Ability */ SK_U16 ResAb; /* Resolved Ability */ SK_U16 ExtStat; /* Extended Status Register */ SK_BOOL AutoNeg; /* Is Autonegotiation used ? */ SK_U8 NextMode; /* Next AutoSensing Mode */ pPrt = &pAC->GIni.GP[Port]; if (pPrt->PHWLinkUp) { if (pPrt->PhyType != SK_PHY_XMAC) { return (SK_HW_PS_NONE); } else { return (SkGePortCheckShorts(pAC, IoC, Port)); } } IsrcSum = pPrt->PIsave; pPrt->PIsave = 0; /* Now wait for each port's link. */ if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) { AutoNeg = SK_FALSE; } else { AutoNeg = SK_TRUE; } if (pPrt->PLinkBroken) { /* Link was broken */ XM_IN32(IoC,Port,XM_GP_PORT, &GpReg); if ((GpReg & XM_GP_INP_ASS) == 0) { /* The Link is in sync */ XM_IN16(IoC,Port,XM_ISRC, &Isrc); IsrcSum |= Isrc; SkXmAutoNegLipaXmac(pAC, IoC, Port, IsrcSum); if ((Isrc & XM_IS_INP_ASS) == 0) { /* It has been in sync since last Time */ /* Restart the PORT */ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, ("Link in sync Restart Port %d\n", Port)); /* We now need to reinitialize the PrevShorts counter. */ Len = sizeof(SK_U64); SkPnmiGetVar(pAC, IoC, OID_SKGE_STAT_RX_SHORTS, (char *)&Shorts, &Len, (SK_U32)SK_PNMI_PORT_PHYS2INST(pAC, Port), pAC->Rlmt.Port[Port].Net->NetNumber); pPrt->PPrevShorts = Shorts; pAC->GIni.GP[Port].PLinkBroken = SK_FALSE; /* * Link Restart Workaround: * it may be possible that the other Link side * restarts its link as well an we detect * another LinkBroken. To prevent this * happening we check for a maximum number * of consecutive restart. If those happens, * we do NOT restart the active link and * check whether the lionk is now o.k. */ pAC->GIni.GP[Port].PLinkResCt ++; pPrt->PAutoNegTimeOut = 0; if (pAC->GIni.GP[Port].PLinkResCt < SK_MAX_LRESTART) { return (SK_HW_PS_RESTART); } SK_DBG_MSG(pAC,SK_DBGMOD_HWM,SK_DBGCAT_CTRL, ("Do NOT restart on Port %d %x %x\n", Port, Isrc, IsrcSum)); pAC->GIni.GP[Port].PLinkResCt = 0; } else { pPrt->PIsave = (SK_U16)(IsrcSum & (XM_IS_AND)); SK_DBG_MSG(pAC,SK_DBGMOD_HWM,SK_DBGCAT_CTRL, ("Save Sync/nosync Port %d %x %x\n", Port, Isrc, IsrcSum)); /* Do nothing more if link is broken */ return (SK_HW_PS_NONE); } } else { /* Do nothing more if link is broken */ return (SK_HW_PS_NONE); } } else { /* Link was not broken, check if it is */ XM_IN16(IoC, Port, XM_ISRC, &Isrc); IsrcSum |= Isrc; if ((Isrc & XM_IS_INP_ASS) == XM_IS_INP_ASS) { XM_IN16(IoC, Port, XM_ISRC, &Isrc); IsrcSum |= Isrc; if ((Isrc & XM_IS_INP_ASS) == XM_IS_INP_ASS) { XM_IN16(IoC, Port, XM_ISRC, &Isrc); IsrcSum |= Isrc; if ((Isrc & XM_IS_INP_ASS) == XM_IS_INP_ASS) { pPrt->PLinkBroken = SK_TRUE; /* * Re-Init Link partner Autoneg flag */ pPrt->PLipaAutoNeg = SK_LIPA_UNKNOWN; SK_DBG_MSG(pAC,SK_DBGMOD_HWM, SK_DBGCAT_IRQ, ("Link broken Port %d\n", Port)); /* Cable removed-> reinit sense mode. */ /* Init default sense mode. */ SkHWInitDefSense(pAC, IoC, Port); return (SK_HW_PS_RESTART); } } } else { SkXmAutoNegLipaXmac(pAC, IoC, Port, Isrc); if (SkGePortCheckShorts(pAC, IoC, Port) == SK_HW_PS_RESTART) { return (SK_HW_PS_RESTART); } } } /* * here we usually can check whether the link is in sync and * autonegotiation is done. */ XM_IN32(IoC, Port, XM_GP_PORT, &GpReg); XM_IN16(IoC, Port, XM_ISRC, &Isrc); IsrcSum |= Isrc; SkXmAutoNegLipaXmac(pAC, IoC, Port, IsrcSum); if ((GpReg & XM_GP_INP_ASS) != 0 || (IsrcSum & XM_IS_INP_ASS) != 0) { if ((GpReg & XM_GP_INP_ASS) == 0) { /* Save Autonegotiation Done interrupt only if link is in sync. */ pPrt->PIsave = (SK_U16)(IsrcSum & (XM_IS_AND)); }#ifdef DEBUG if (pPrt->PIsave & (XM_IS_AND)) { SK_DBG_MSG(pAC,SK_DBGMOD_HWM,SK_DBGCAT_CTRL, ("AutoNeg done rescheduled Port %d\n", Port)); }#endif return (SK_HW_PS_NONE); } if (AutoNeg) { if (IsrcSum & XM_IS_AND) { SkHWLinkUp(pAC, IoC, Port); Done = SkXmAutoNegDone(pAC,IoC,Port); if (Done != SK_AND_OK) { /* Get PHY parameters, for debuging only */ PHY_READ(IoC, pPrt, Port, PHY_XMAC_AUNE_LP, &LpAb); PHY_READ(IoC, pPrt, Port, PHY_XMAC_RES_ABI, &ResAb); SK_DBG_MSG(pAC,SK_DBGMOD_HWM,SK_DBGCAT_CTRL, ("AutoNeg FAIL Port %d (LpAb %x, ResAb %x)\n", Port, LpAb, ResAb)); /* Try next possible mode */ NextMode = SkHWSenseGetNext(pAC, IoC, Port); SkHWLinkDown(pAC, IoC, Port); if (Done == SK_AND_DUP_CAP) { /* GoTo next mode */ SkHWSenseSetNext(pAC, IoC, Port, NextMode); } return (SK_HW_PS_RESTART); } else { /* * Dummy Read extended status to prevent extra link down/ups * (clear Page Received bit if set) */ PHY_READ(IoC, pPrt, Port, PHY_XMAC_AUNE_EXP, &ExtStat); SK_DBG_MSG(pAC,SK_DBGMOD_HWM,SK_DBGCAT_CTRL, ("AutoNeg done Port %d\n", Port)); return (SK_HW_PS_LINK); } } /* * AutoNeg not done, but HW link is up. Check for timeouts */ pPrt->PAutoNegTimeOut ++; if (pPrt->PAutoNegTimeOut >= SK_AND_MAX_TO) { /* * Increase the Timeout counter. */ pPrt->PAutoNegTOCt ++; /* * Timeout occured. * What do we need now? */ SK_DBG_MSG(pAC,SK_DBGMOD_HWM, SK_DBGCAT_IRQ, ("AutoNeg timeout Port %d\n", Port)); if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE && pPrt->PLipaAutoNeg != SK_LIPA_AUTO) { /* * Timeout occured * Set Link manually up. */ SkHWSenseSetNext(pAC, IoC, Port, SK_LMODE_FULL); SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, ("Set manual full duplex Port %d\n", Port)); } if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE && pPrt->PLipaAutoNeg == SK_LIPA_AUTO && pPrt->PAutoNegTOCt >= SK_MAX_ANEG_TO) { /* * This is rather complicated. * we need to check here whether the LIPA_AUTO * we saw before is false alert. We saw at one * switch ( SR8800) that on boot time it sends * just one autoneg packet and does no further * autonegotiation. * Solution: we restart the autosensing after * a few timeouts. */ pPrt->PAutoNegTOCt = 0; pPrt->PLipaAutoNeg = SK_LIPA_UNKNOWN; SkHWInitDefSense(pAC, IoC, Port); } /* * Do the restart */ return (SK_HW_PS_RESTART); } } else { /* * Link is up and we don't need more. */#ifdef DEBUG if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) { SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, ("ERROR: Lipa auto detected on port %d\n", Port)); }#endif SK_DBG_MSG(pAC,SK_DBGMOD_HWM,SK_DBGCAT_IRQ, ("Link sync(GP), Port %d\n", Port)); SkHWLinkUp(pAC, IoC, Port); return (SK_HW_PS_LINK); } return (SK_HW_PS_NONE);} /* SkGePortCheckUpXmac *//****************************************************************************** * * SkGePortCheckUpBcom - Check, if the link is up * * return: * 0 o.k. nothing needed * 1 Restart needed on this port * 2 Link came up */static int SkGePortCheckUpBcom(SK_AC *pAC, /* Adapter Context */SK_IOC IoC, /* IO Context */int Port) /* Which port should be checked */{ SK_GEPORT *pPrt; /* GIni Port struct pointer */ int Done; SK_U16 Isrc; /* Interrupt source register */ SK_U16 PhyStat; /* Phy Status Register */ SK_U16 ResAb; /* Master/Slave resolution */ SK_U16 Ctrl; /* Broadcom control flags */#ifdef DEBUG SK_U16 LpAb; SK_U16 ExtStat;#endif /* DEBUG */ SK_BOOL AutoNeg; /* Is Autonegotiation used ? */ pPrt = &pAC->GIni.GP[Port]; /* Check for No HCD Link events (#10523) */ PHY_READ(IoC, pPrt, Port, PHY_BCOM_INT_STAT, &Isrc);#ifdef xDEBUG if ((Isrc & ~0x1800) == 0x70) { SK_U32 Stat1, Stat2, Stat3; Stat1 = 0; PHY_READ(pAC, pPrt, Port, PHY_BCOM_INT_MASK, &Stat1); CMSMPrintString( pAC->pConfigTable, MSG_TYPE_RUNTIME_INFO, "CheckUp1 - Stat: %x, Mask: %x", (void *)Isrc, (void *)Stat1); Stat1 = 0; PHY_READ(pAC, pPrt, Port, PHY_BCOM_CTRL, &Stat1); Stat2 = 0; PHY_READ(pAC, pPrt, Port, PHY_BCOM_STAT, &Stat2); Stat1 = Stat1 << 16 | Stat2; Stat2 = 0; PHY_READ(pAC, pPrt, Port, PHY_BCOM_AUNE_ADV, &Stat2); Stat3 = 0; PHY_READ(pAC, pPrt, Port, PHY_BCOM_AUNE_LP, &Stat3); Stat2 = Stat2 << 16 | Stat3; CMSMPrintString( pAC->pConfigTable, MSG_TYPE_RUNTIME_INFO, "Ctrl/Stat: %x, AN Adv/LP: %x", (void *)Stat1, (void *)Stat2); Stat1 = 0; PHY_READ(pAC, pPrt, Port, PHY_BCOM_AUNE_EXP, &Stat1); Stat2 = 0; PHY_READ(pAC, pPrt, Port, PHY_BCOM_EXT_STAT, &Stat2); Stat1 = Stat1 << 16 | Stat2; Stat2 = 0; PHY_READ(pAC, pPrt, Port, PHY_BCOM_1000T_CTRL, &Stat2); Stat3 = 0; PHY_READ(pAC, pPrt, Port, PHY_BCOM_1000T_STAT, &Stat3); Stat2 = Stat2 << 16 | Stat3; CMSMPrintString( pAC->pConfigTable, MSG_TYPE_RUNTIME_INFO, "AN Exp/IEEE Ext: %x, 1000T Ctrl/Stat: %x", (void *)Stat1, (void *)Stat2); Stat1 = 0; PHY_READ(pAC, pPrt, Port, PHY_BCOM_P_EXT_CTRL, &Stat1); Stat2 = 0; PHY_READ(pAC, pPrt, Port, PHY_BCOM_P_EXT_STAT, &Stat2); Stat1 = Stat1 << 16 | Stat2; Stat2 = 0; PHY_READ(pAC, pPrt, Port, PHY_BCOM_AUX_CTRL, &Stat2); Stat3 = 0; PHY_READ(pAC, pPrt, Port, PHY_BCOM_AUX_STAT, &Stat3); Stat2 = Stat2 << 16 | Stat3; CMSMPrintString( pAC->pConfigTable, MSG_TYPE_RUNTIME_INFO, "PHY Ext Ctrl/Stat: %x, Aux Ctrl/Stat: %x", (void *)Stat1, (void *)Stat2); }#endif /* DEBUG */ if ((Isrc & (PHY_B_IS_NO_HDCL /* | PHY_B_IS_NO_HDC */)) != 0) { /* * Workaround BCOM Errata: * enable and disable loopback mode if "NO HCD" occurs. */ PHY_READ(IoC, pPrt, Port, PHY_BCOM_CTRL, &Ctrl); PHY_WRITE(IoC, pPrt, Port, PHY_BCOM_CTRL, Ctrl | PHY_CT_LOOP); PHY_WRITE(IoC, pPrt, Port, PHY_BCOM_CTRL, Ctrl & ~PHY_CT_LOOP); SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, ("No HCD Link event, Port %d\n", Port));#ifdef xDEBUG CMSMPrintString( pAC->pConfigTable, MSG_TYPE_RUNTIME_INFO, "No HCD link event, port %d.", (void *)Port, (void *)NULL);#endif /* DEBUG */ } /* Not obsolete: link status bit is latched to 0 and autoclearing! */ PHY_READ(IoC, pPrt, Port, PHY_BCOM_STAT, &PhyStat); if (pPrt->PHWLinkUp) { return (SK_HW_PS_NONE); }#ifdef xDEBUG { SK_U32 Stat1, Stat2, Stat3; Stat1 = 0; PHY_READ(pAC, pPrt, Port, PHY_BCOM_INT_MASK, &Stat1); CMSMPrintString( pAC->pConfigTable, MSG_TYPE_RUNTIME_INFO, "CheckUp1a - Stat: %x, Mask: %x", (void *)Isrc, (void *)Stat1); Stat1 = 0; PHY_READ(pAC, pPrt, Port, PHY_BCOM_CTRL, &Stat1); Stat2 = 0; PHY_READ(pAC, pPrt, Port, PHY_BCOM_STAT, &PhyStat); Stat1 = Stat1 << 16 | PhyStat; Stat2 = 0; PHY_READ(pAC, pPrt, Port, PHY_BCOM_AUNE_ADV, &Stat2); Stat3 = 0; PHY_READ(pAC, pPrt, Port, PHY_BCOM_AUNE_LP, &Stat3); Stat2 = Stat2 << 16 | Stat3; CMSMPrintString( pAC->pConfigTable, MSG_TYPE_RUNTIME_INFO, "Ctrl/Stat: %x, AN Adv/LP: %x", (void *)Stat1, (void *)Stat2); Stat1 = 0; PHY_READ(pAC, pPrt, Port, PHY_BCOM_AUNE_EXP, &Stat1); Stat2 = 0; PHY_READ(pAC, pPrt, Port, PHY_BCOM_EXT_STAT, &Stat2); Stat1 = Stat1 << 16 | Stat2; Stat2 = 0; PHY_READ(pAC, pPrt, Port, PHY_BCOM_1000T_CTRL, &Stat2); Stat3 = 0; PHY_READ(pAC, pPrt, Port, PHY_BCOM_1000T_STAT, &ResAb); Stat2 = Stat2 << 16 | ResAb; CMSMPrintString( pAC->pConfigTable, MSG_TYPE_RUNTIME_INFO, "AN Exp/IEEE Ext: %x, 1000T Ctrl/Stat: %x", (void *)Stat1, (void *)Stat2); Stat1 = 0; PHY_READ(pAC, pPrt, Port, PHY_BCOM_P_EXT_CTRL, &Stat1); Stat2 = 0; PHY_READ(pAC, pPrt, Port, PHY_BCOM_P_EXT_STAT, &Stat2); Stat1 = Stat1 << 16 | Stat2; Stat2 = 0; PHY_READ(pAC, pPrt, Port, PHY_BCOM_AUX_CTRL, &Stat2); Stat3 = 0; PHY_READ(pAC, pPrt, Port, PHY_BCOM_AUX_STAT, &Stat3); Stat2 = Stat2 << 16 | Stat3; CMSMPrintString( pAC->pConfigTable, MSG_TYPE_RUNTIME_INFO, "PHY Ext Ctrl/Stat: %x, Aux Ctrl/Stat: %x", (void *)Stat1, (void *)Stat2); }#endif /* DEBUG */ /* Now wait for each port's link. */ if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) { AutoNeg = SK_FALSE; } else { AutoNeg = SK_TRUE; } /* * Here we usually can check whether the link is in sync and * autonegotiation is done. */#if 0/* RA;:;: obsolete */ XM_IN16(IoC, Port, XM_ISRC, &Isrc);#endif /* 0 */ PHY_READ(IoC, pPrt, Port, PHY_BCOM_STAT, &PhyStat);#ifdef xDEBUG if ((PhyStat & PHY_ST_LSYNC) >> 2 != (ExtStat & PHY_B_PES_LS) >> 8) { CMSMPrintString( pAC->pConfigTable, MSG_TYPE_RUNTIME_INFO, "PhyStat != ExtStat: %x %x", (void *)PhyStat, (void *)ExtStat); }#endif /* DEBUG */ SkXmAutoNegLipaBcom(pAC, IoC, Port, PhyStat); SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, ("AutoNeg:%d, PhyStat: %Xh.\n", AutoNeg, PhyStat)); PHY_READ(IoC, pPrt, Port, PHY_BCOM_1000T_STAT, &ResAb); if (ResAb & PHY_B_1000S_MSF) { /* Error */ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, ("Master/Slave Fault port %d\n", Port)); pPrt->PAutoNegFail = SK_TRUE; pPrt->PMSStatus = SK_MS_STAT_FAULT; return (SK_HW_PS_RESTART); } if ((PhyStat & PHY_ST_LSYNC) == 0) { return (SK_HW_PS_NONE); } else if (ResAb & PHY_B_1000S_MSR) { pPrt->PMSStatus = SK_MS_STAT_MASTER; } else { pPrt->PMSStatus = SK_MS_STAT_SLAVE; } SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, ("AutoNeg:%d, PhyStat: %Xh.\n", AutoNeg, PhyStat)); if (AutoNeg) { if (PhyStat & PHY_ST_AN_OVER) { SkHWLinkUp(pAC, IoC, Port); Done = SkXmAutoNegDone(pAC, IoC, Port); if (Done != SK_AND_OK) {#ifdef DEBUG /* Get PHY parameters, for debugging only. */ PHY_READ(IoC, pPrt, Port, PHY_BCOM_AUNE_LP, &LpAb); PHY_READ(IoC, pPrt, Port, PHY_BCOM_1000T_STAT, &ExtStat); SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, ("AutoNeg FAIL Port %d (LpAb %x, 1000TStat %x)\n", Port, LpAb, ExtStat));#endif /* DEBUG */ return (SK_HW_PS_RESTART); } else {#ifdef xDEBUG
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -