From 8b32a91deffcc4cded99b366449c8139eea39690 Mon Sep 17 00:00:00 2001 From: Eyal Harari Date: Wed, 23 Oct 2013 17:48:43 +0300 Subject: FMD: DSAR: Establish the auto-response driver - New code for auto-response - Changed parser init - Added DsarCheckParams and fm_port_dsar_dump_regs - Added snmp support - Added statistics features - Fixed SNMP oid table - Removed usage of create_proc_entry - for merging to master Change-Id: Icd6292c8d68ddb4ee60ecfed87419c1f4cbf5e74 Signed-off-by: Eyal Harari Reviewed-on: http://git.am.freescale.net:8181/8711 Reviewed-by: Madalin-Cristian Bucur Reviewed-by: Mandy Lavi Reviewed-by: Jose Rivera Tested-by: Jose Rivera Reviewed-on: http://git.am.freescale.net:8181/9445 diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_prs.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_prs.c index e198afd..1666865 100644 --- a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_prs.c +++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_prs.c @@ -191,6 +191,14 @@ void PrsDisable(t_FmPcd *p_FmPcd) fman_prs_disable(PrsRegs); } +int PrsIsEnabled(t_FmPcd *p_FmPcd) +{ + struct fman_prs_regs *PrsRegs = (struct fman_prs_regs *)p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs; + + ASSERT_COND(p_FmPcd->guestId == NCSW_MASTER_ID); + return fman_prs_is_enabled(PrsRegs); +} + t_Error PrsIncludePortInStatistics(t_FmPcd *p_FmPcd, uint8_t hardwarePortId, bool include) { struct fman_prs_regs *PrsRegs; diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fman_prs.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fman_prs.c index caa1d28..108779d 100644 --- a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fman_prs.c +++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fman_prs.c @@ -110,6 +110,11 @@ void fman_prs_disable(struct fman_prs_regs *regs) iowrite32be(tmp, ®s->fmpr_rpimac); } +int fman_prs_is_enabled(struct fman_prs_regs *regs) +{ + return ioread32be(®s->fmpr_rpimac) & FM_PCD_PRS_RPIMAC_EN; +} + void fman_prs_set_stst_port_msk(struct fman_prs_regs *regs, uint32_t pid_msk) { iowrite32be(pid_msk, ®s->fmpr_ppsc); diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Port/fm_port.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Port/fm_port.c index bfa05c5..4949b79 100644 --- a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Port/fm_port.c +++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Port/fm_port.c @@ -45,12 +45,13 @@ #include "fman_common.h" #include "fm_port.h" - +#include "fm_port_dsar.h" #include "common/general.h" /****************************************/ /* static functions */ /****************************************/ +static t_Error FmPortConfigAutoResForDeepSleepSupport1(t_FmPort *p_FmPort); static t_Error CheckInitParameters(t_FmPort *p_FmPort) { @@ -2252,6 +2253,9 @@ t_Handle FM_PORT_Config(t_FmPortParams *p_FmPortParams) return p_FmPort; } +t_FmPort *rx_port = 0; +t_FmPort *tx_port = 0; + /**************************************************************************//** @Function FM_PORT_Init @@ -2443,7 +2447,10 @@ t_Error FM_PORT_Init(t_Handle h_FmPort) #endif /* FM_ERROR_VSP_NO_MATCH_SW006 */ } #endif /* (DPAA_VERSION >= 11) */ - + + if (p_FmPort->deepSleepVars.autoResMaxSizes) + FmPortConfigAutoResForDeepSleepSupport1(p_FmPort); + return E_OK; } @@ -5183,3 +5190,656 @@ t_Error FM_PORT_GetIPv4OptionsCount(t_Handle h_FmPort, uint32_t *p_Ipv4OptionsCo } #endif /* (DPAA_VERSION >= 11) */ +t_Error FM_PORT_ConfigDsarSupport(t_Handle h_FmPortRx, t_FmPortDsarTablesSizes *params) +{ + t_FmPort *p_FmPort= (t_FmPort *)h_FmPortRx; + p_FmPort->deepSleepVars.autoResMaxSizes = XX_Malloc(sizeof(struct t_FmPortDsarTablesSizes)); + memcpy(p_FmPort->deepSleepVars.autoResMaxSizes, params, sizeof(struct t_FmPortDsarTablesSizes)); + return E_OK; +} + +static t_Error FmPortConfigAutoResForDeepSleepSupport1(t_FmPort *p_FmPort) +{ + uint32_t *param_page; + t_FmPortDsarTablesSizes *params = p_FmPort->deepSleepVars.autoResMaxSizes; + t_ArCommonDesc *ArCommonDescPtr; + uint32_t size = sizeof(t_ArCommonDesc); + // ARP + // should put here if (params->max_num_of_arp_entries)? + size = ROUND_UP(size,4); + size += sizeof(t_DsarArpDescriptor); + size += sizeof(t_DsarArpBindingEntry) * params->maxNumOfArpEntries; + size += sizeof(t_DsarArpStatistics); + //ICMPV4 + size = ROUND_UP(size,4); + size += sizeof(t_DsarIcmpV4Descriptor); + size += sizeof(t_DsarIcmpV4BindingEntry) * params->maxNumOfEchoIpv4Entries; + size += sizeof(t_DsarIcmpV4Statistics); + //ICMPV6 + size = ROUND_UP(size,4); + size += sizeof(t_DsarIcmpV6Descriptor); + size += sizeof(t_DsarIcmpV6BindingEntry) * params->maxNumOfEchoIpv6Entries; + size += sizeof(t_DsarIcmpV6Statistics); + //ND + size = ROUND_UP(size,4); + size += sizeof(t_DsarNdDescriptor); + size += sizeof(t_DsarIcmpV6BindingEntry) * params->maxNumOfNdpEntries; + size += sizeof(t_DsarIcmpV6Statistics); + //SNMP + size = ROUND_UP(size,4); + size += sizeof(t_DsarSnmpDescriptor); + size += sizeof(t_DsarSnmpIpv4AddrTblEntry) * params->maxNumOfSnmpIPV4Entries; + size += sizeof(t_DsarSnmpIpv6AddrTblEntry) * params->maxNumOfSnmpIPV6Entries; + size += sizeof(t_OidsTblEntry) * params->maxNumOfSnmpOidEntries; + size += params->maxNumOfSnmpOidChar; + size += sizeof(t_DsarIcmpV6Statistics); + //filters + size = ROUND_UP(size,4); + size += params->maxNumOfIpProtFiltering; + size = ROUND_UP(size,4); + size += params->maxNumOfUdpPortFiltering * sizeof(t_PortTblEntry); + size = ROUND_UP(size,4); + size += params->maxNumOfTcpPortFiltering * sizeof(t_PortTblEntry); + + // add here for more protocols + + // statistics + size = ROUND_UP(size,4); + size += sizeof(t_ArStatistics); + + ArCommonDescPtr = FM_MURAM_AllocMem(p_FmPort->h_FmMuram, size, 0x10); + + param_page = XX_PhysToVirt(p_FmPort->fmMuramPhysBaseAddr + GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rgpr)); + WRITE_UINT32(*param_page, + (uint32_t)(XX_VirtToPhys(ArCommonDescPtr) - p_FmPort->fmMuramPhysBaseAddr)); + return E_OK; +} + +t_FmPortDsarTablesSizes* FM_PORT_GetDsarTablesMaxSizes(t_Handle h_FmPortRx) +{ + t_FmPort *p_FmPort= (t_FmPort *)h_FmPortRx; + return p_FmPort->deepSleepVars.autoResMaxSizes; +} + +struct arOffsets +{ + uint32_t arp; + uint32_t nd; + uint32_t icmpv4; + uint32_t icmpv6; + uint32_t snmp; + uint32_t stats; + uint32_t filtIp; + uint32_t filtUdp; + uint32_t filtTcp; +}; + +static uint32_t AR_ComputeOffsets(struct arOffsets* of, struct t_FmPortDsarParams *params, t_FmPort *p_FmPort) +{ + uint32_t size = sizeof(t_ArCommonDesc); + // ARP + if (params->p_AutoResArpInfo) + { + size = ROUND_UP(size,4); + of->arp = size; + size += sizeof(t_DsarArpDescriptor); + size += sizeof(t_DsarArpBindingEntry) * params->p_AutoResArpInfo->tableSize; + size += sizeof(t_DsarArpStatistics); + } + // ICMPV4 + if (params->p_AutoResEchoIpv4Info) + { + size = ROUND_UP(size,4); + of->icmpv4 = size; + size += sizeof(t_DsarIcmpV4Descriptor); + size += sizeof(t_DsarIcmpV4BindingEntry) * params->p_AutoResEchoIpv4Info->tableSize; + size += sizeof(t_DsarIcmpV4Statistics); + } + // ICMPV6 + if (params->p_AutoResEchoIpv6Info) + { + size = ROUND_UP(size,4); + of->icmpv6 = size; + size += sizeof(t_DsarIcmpV6Descriptor); + size += sizeof(t_DsarIcmpV6BindingEntry) * params->p_AutoResEchoIpv6Info->tableSize; + size += sizeof(t_DsarIcmpV6Statistics); + } + // ND + if (params->p_AutoResNdpInfo) + { + size = ROUND_UP(size,4); + of->nd = size; + size += sizeof(t_DsarNdDescriptor); + size += sizeof(t_DsarIcmpV6BindingEntry) * + (params->p_AutoResNdpInfo->tableSizeAssigned + params->p_AutoResNdpInfo->tableSizeTmp); + size += sizeof(t_DsarIcmpV6Statistics); + } + // SNMP + if (params->p_AutoResSnmpInfo) + { + size = ROUND_UP(size,4); + of->snmp = size; + size += sizeof(t_DsarSnmpDescriptor); + size += sizeof(t_DsarSnmpIpv4AddrTblEntry) * params->p_AutoResSnmpInfo->numOfIpv4Addresses; + size += sizeof(t_DsarSnmpIpv6AddrTblEntry) * params->p_AutoResSnmpInfo->numOfIpv6Addresses; + size += sizeof(t_OidsTblEntry) * params->p_AutoResSnmpInfo->oidsTblSize; + size += p_FmPort->deepSleepVars.autoResMaxSizes->maxNumOfSnmpOidChar; + size += sizeof(t_DsarIcmpV6Statistics); + } + //filters + size = ROUND_UP(size,4); + if (params->p_AutoResFilteringInfo) + { + of->filtIp = size; + size += params->p_AutoResFilteringInfo->ipProtTableSize; + size = ROUND_UP(size,4); + of->filtUdp = size; + size += params->p_AutoResFilteringInfo->udpPortsTableSize * sizeof(t_PortTblEntry); + size = ROUND_UP(size,4); + of->filtTcp = size; + size += params->p_AutoResFilteringInfo->tcpPortsTableSize * sizeof(t_PortTblEntry); + } + // add here for more protocols + // statistics + size = ROUND_UP(size,4); + of->stats = size; + size += sizeof(t_ArStatistics); + return size; +} + +uint32_t* ARDesc; +void PrsEnable(t_Handle p_FmPcd); +void PrsDisable(t_Handle p_FmPcd); +int PrsIsEnabled(t_Handle p_FmPcd); + +static t_Error DsarCheckParams(t_FmPortDsarParams *params, t_FmPortDsarTablesSizes *sizes) +{ + bool macInit = FALSE; + uint8_t mac[6]; + int i; + + // check table sizes + if (params->p_AutoResArpInfo && sizes->maxNumOfArpEntries < params->p_AutoResArpInfo->tableSize) + RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("DSAR: Arp table size exceeds the configured maximum size.")); + if (params->p_AutoResEchoIpv4Info && sizes->maxNumOfEchoIpv4Entries < params->p_AutoResEchoIpv4Info->tableSize) + RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("DSAR: EchoIpv4 table size exceeds the configured maximum size.")); + if (params->p_AutoResNdpInfo && sizes->maxNumOfNdpEntries < params->p_AutoResNdpInfo->tableSizeAssigned + params->p_AutoResNdpInfo->tableSizeTmp) + RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("DSAR: NDP table size exceeds the configured maximum size.")); + if (params->p_AutoResEchoIpv6Info && sizes->maxNumOfEchoIpv6Entries < params->p_AutoResEchoIpv6Info->tableSize) + RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("DSAR: EchoIpv6 table size exceeds the configured maximum size.")); + if (params->p_AutoResSnmpInfo && sizes->maxNumOfSnmpOidEntries < params->p_AutoResSnmpInfo->oidsTblSize) + RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("DSAR: Snmp Oid table size exceeds the configured maximum size.")); + if (params->p_AutoResSnmpInfo && sizes->maxNumOfSnmpIPV4Entries < params->p_AutoResSnmpInfo->numOfIpv4Addresses) + RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("DSAR: Snmp ipv4 table size exceeds the configured maximum size.")); + if (params->p_AutoResSnmpInfo && sizes->maxNumOfSnmpIPV6Entries < params->p_AutoResSnmpInfo->numOfIpv6Addresses) + RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("DSAR: Snmp ipv6 table size exceeds the configured maximum size.")); + if (params->p_AutoResFilteringInfo) + { + if (sizes->maxNumOfIpProtFiltering < params->p_AutoResFilteringInfo->ipProtTableSize) + RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("DSAR: ip filter table size exceeds the configured maximum size.")); + if (sizes->maxNumOfTcpPortFiltering < params->p_AutoResFilteringInfo->udpPortsTableSize) + RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("DSAR: udp filter table size exceeds the configured maximum size.")); + if (sizes->maxNumOfUdpPortFiltering < params->p_AutoResFilteringInfo->tcpPortsTableSize) + RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("DSAR: tcp filter table size exceeds the configured maximum size.")); + } + // check only 1 MAC address is configured (this is what ucode currently supports) + if (params->p_AutoResArpInfo && params->p_AutoResArpInfo->tableSize) + { + i = 0; + if (!macInit) + { + memcpy(mac, params->p_AutoResArpInfo->p_AutoResTable[0].mac, 6); + i = 1; + macInit = TRUE; + } + for (; i < params->p_AutoResArpInfo->tableSize; i++) + if (memcmp(mac, params->p_AutoResArpInfo->p_AutoResTable[i].mac, 6)) + RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("DSAR: Only 1 mac address is currently supported.")); + } + if (params->p_AutoResEchoIpv4Info && params->p_AutoResEchoIpv4Info->tableSize) + { + i = 0; + if (!macInit) + { + memcpy(mac, params->p_AutoResEchoIpv4Info->p_AutoResTable[0].mac, 6); + i = 1; + macInit = TRUE; + } + for (; i < params->p_AutoResEchoIpv4Info->tableSize; i++) + if (memcmp(mac, params->p_AutoResEchoIpv4Info->p_AutoResTable[i].mac, 6)) + RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("DSAR: Only 1 mac address is currently supported.")); + } + if (params->p_AutoResEchoIpv6Info && params->p_AutoResEchoIpv6Info->tableSize) + { + i = 0; + if (!macInit) + { + memcpy(mac, params->p_AutoResEchoIpv6Info->p_AutoResTable[0].mac, 6); + i = 1; + macInit = TRUE; + } + for (; i < params->p_AutoResEchoIpv6Info->tableSize; i++) + if (memcmp(mac, params->p_AutoResEchoIpv6Info->p_AutoResTable[i].mac, 6)) + RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("DSAR: Only 1 mac address is currently supported.")); + } + if (params->p_AutoResNdpInfo && params->p_AutoResNdpInfo->tableSizeAssigned) + { + i = 0; + if (!macInit) + { + memcpy(mac, params->p_AutoResNdpInfo->p_AutoResTableAssigned[0].mac, 6); + i = 1; + macInit = TRUE; + } + for (; i < params->p_AutoResNdpInfo->tableSizeAssigned; i++) + if (memcmp(mac, params->p_AutoResNdpInfo->p_AutoResTableAssigned[i].mac, 6)) + RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("DSAR: Only 1 mac address is currently supported.")); + } + if (params->p_AutoResNdpInfo && params->p_AutoResNdpInfo->tableSizeTmp) + { + i = 0; + if (!macInit) + { + memcpy(mac, params->p_AutoResNdpInfo->p_AutoResTableTmp[0].mac, 6); + i = 1; + macInit = TRUE; + } + for (; i < params->p_AutoResNdpInfo->tableSizeTmp; i++) + if (memcmp(mac, params->p_AutoResNdpInfo->p_AutoResTableTmp[i].mac, 6)) + RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("DSAR: Only 1 mac address is currently supported.")); + } + return E_OK; +} + +static int GetBERLen(uint8_t* buf) +{ + if (*buf & 0x80) + { + if ((*buf & 0x7F) == 1) + return buf[1]; + else + return *(uint16_t*)&buf[1]; // assuming max len is 2 + } + else + return buf[0]; +} +#define TOTAL_BER_LEN(len) (len < 128) ? len + 2 : len + 3 + +t_Error FM_PORT_EnterDsar(t_Handle h_FmPortRx, t_FmPortDsarParams *params) +{ + int i,j; + t_Error err; + uint32_t nia; + t_FmPort *p_FmPort= (t_FmPort *)h_FmPortRx; + t_FmPort *p_FmPortTx = (t_FmPort *)params->h_FmPortTx; + t_DsarArpDescriptor *ArpDescriptor; + t_DsarIcmpV4Descriptor* ICMPV4Descriptor; + t_DsarIcmpV6Descriptor* ICMPV6Descriptor; + t_DsarNdDescriptor* NDDescriptor; + uint64_t fmMuramVirtBaseAddr = (uint64_t)XX_PhysToVirt(p_FmPort->fmMuramPhysBaseAddr); + uint32_t *param_page = XX_PhysToVirt(p_FmPort->fmMuramPhysBaseAddr + GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rgpr)); + t_ArCommonDesc *ArCommonDescPtr = (t_ArCommonDesc*)(XX_PhysToVirt(p_FmPort->fmMuramPhysBaseAddr + GET_UINT32(*param_page))); + struct arOffsets* of; + uint8_t tmp = 0; + t_Handle *h_FmPcd; + + err = DsarCheckParams(params, p_FmPort->deepSleepVars.autoResMaxSizes); + if (err != E_OK) + return err; + + p_FmPort->deepSleepVars.autoResOffsets = XX_Malloc(sizeof(struct arOffsets)); + of = (struct arOffsets *)p_FmPort->deepSleepVars.autoResOffsets; + IOMemSet32(ArCommonDescPtr, 0, AR_ComputeOffsets(of, params, p_FmPort)); + + // common + WRITE_UINT8(ArCommonDescPtr->arTxPort, p_FmPortTx->hardwarePortId); + nia = GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfne); // bmi nia + if ((nia & 0x007C0000) == 0x00440000) // bmi nia is parser + WRITE_UINT32(ArCommonDescPtr->activeHPNIA, GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfpne)); + else + WRITE_UINT32(ArCommonDescPtr->activeHPNIA, nia); + WRITE_UINT16(ArCommonDescPtr->snmpPort, 161); + + // ARP + if (params->p_AutoResArpInfo) + { + t_DsarArpBindingEntry* arp_bindings; + ArpDescriptor = (t_DsarArpDescriptor*)(PTR_TO_UINT(ArCommonDescPtr) + of->arp); + WRITE_UINT32(ArCommonDescPtr->p_ArpDescriptor, PTR_TO_UINT(ArpDescriptor) - fmMuramVirtBaseAddr); + arp_bindings = (t_DsarArpBindingEntry*)(PTR_TO_UINT(ArpDescriptor) + sizeof(t_DsarArpDescriptor)); + WRITE_UINT16(ArpDescriptor->control, 0); + if (params->p_AutoResArpInfo->tableSize) + { + t_FmPortDsarArpEntry* arp_entry = params->p_AutoResArpInfo->p_AutoResTable; + WRITE_UINT16(*(uint16_t*)&ArCommonDescPtr->macStationAddr[0], *(uint16_t*)&arp_entry[0].mac[0]); + WRITE_UINT32(*(uint32_t*)&ArCommonDescPtr->macStationAddr[2], *(uint32_t*)&arp_entry[0].mac[2]); + WRITE_UINT16(ArpDescriptor->numOfBindings, params->p_AutoResArpInfo->tableSize); + + for (i = 0; i < params->p_AutoResArpInfo->tableSize; i++) + { + WRITE_UINT32(arp_bindings[i].ipv4Addr, arp_entry[i].ipAddress); + if (arp_entry[i].isVlan) + WRITE_UINT16(arp_bindings[i].vlanId, arp_entry[i].vid & 0xFFF); + } + WRITE_UINT32(ArpDescriptor->p_Bindings, PTR_TO_UINT(arp_bindings) - fmMuramVirtBaseAddr); + } + WRITE_UINT32(ArpDescriptor->p_Statistics, PTR_TO_UINT(arp_bindings) + + sizeof(t_DsarArpBindingEntry) * params->p_AutoResArpInfo->tableSize - fmMuramVirtBaseAddr); + } + + // ICMPV4 + if (params->p_AutoResEchoIpv4Info) + { + t_DsarIcmpV4BindingEntry* icmpv4_bindings; + ICMPV4Descriptor = (t_DsarIcmpV4Descriptor*)(PTR_TO_UINT(ArCommonDescPtr) + of->icmpv4); + WRITE_UINT32(ArCommonDescPtr->p_IcmpV4Descriptor, PTR_TO_UINT(ICMPV4Descriptor) - fmMuramVirtBaseAddr); + icmpv4_bindings = (t_DsarIcmpV4BindingEntry*)(PTR_TO_UINT(ICMPV4Descriptor) + sizeof(t_DsarIcmpV4Descriptor)); + WRITE_UINT16(ICMPV4Descriptor->control, 0); + if (params->p_AutoResEchoIpv4Info->tableSize) + { + t_FmPortDsarArpEntry* arp_entry = params->p_AutoResEchoIpv4Info->p_AutoResTable; + WRITE_UINT16(*(uint16_t*)&ArCommonDescPtr->macStationAddr[0], *(uint16_t*)&arp_entry[0].mac[0]); + WRITE_UINT32(*(uint32_t*)&ArCommonDescPtr->macStationAddr[2], *(uint32_t*)&arp_entry[0].mac[2]); + WRITE_UINT16(ICMPV4Descriptor->numOfBindings, params->p_AutoResEchoIpv4Info->tableSize); + + for (i = 0; i < params->p_AutoResEchoIpv4Info->tableSize; i++) + { + WRITE_UINT32(icmpv4_bindings[i].ipv4Addr, arp_entry[i].ipAddress); + if (arp_entry[i].isVlan) + WRITE_UINT16(icmpv4_bindings[i].vlanId, arp_entry[i].vid & 0xFFF); + } + WRITE_UINT32(ICMPV4Descriptor->p_Bindings, PTR_TO_UINT(icmpv4_bindings) - fmMuramVirtBaseAddr); + } + WRITE_UINT32(ICMPV4Descriptor->p_Statistics, PTR_TO_UINT(icmpv4_bindings) + + sizeof(t_DsarIcmpV4BindingEntry) * params->p_AutoResEchoIpv4Info->tableSize - fmMuramVirtBaseAddr); + } + + // ICMPV6 + if (params->p_AutoResEchoIpv6Info) + { + t_DsarIcmpV6BindingEntry* icmpv6_bindings; + ICMPV6Descriptor = (t_DsarIcmpV6Descriptor*)(PTR_TO_UINT(ArCommonDescPtr) + of->icmpv6); + WRITE_UINT32(ArCommonDescPtr->p_IcmpV6Descriptor, PTR_TO_UINT(ICMPV6Descriptor) - fmMuramVirtBaseAddr); + icmpv6_bindings = (t_DsarIcmpV6BindingEntry*)(PTR_TO_UINT(ICMPV6Descriptor) + sizeof(t_DsarIcmpV6Descriptor)); + WRITE_UINT16(ICMPV6Descriptor->control, 0); + if (params->p_AutoResEchoIpv6Info->tableSize) + { + t_FmPortDsarNdpEntry* ndp_entry = params->p_AutoResEchoIpv6Info->p_AutoResTable; + WRITE_UINT16(*(uint16_t*)&ArCommonDescPtr->macStationAddr[0], *(uint16_t*)&ndp_entry[0].mac[0]); + WRITE_UINT32(*(uint32_t*)&ArCommonDescPtr->macStationAddr[2], *(uint32_t*)&ndp_entry[0].mac[2]); + WRITE_UINT16(ICMPV6Descriptor->numOfBindings, params->p_AutoResEchoIpv6Info->tableSize); + + for (i = 0; i < params->p_AutoResEchoIpv6Info->tableSize; i++) + { + for (j = 0; j < 4; j++) + WRITE_UINT32(icmpv6_bindings[i].ipv6Addr[j], ndp_entry[i].ipAddress[j]); + if (ndp_entry[i].isVlan) + WRITE_UINT16(*(uint16_t*)&icmpv6_bindings[i].ipv6Addr[4], ndp_entry[i].vid & 0xFFF); // writing vlan + } + WRITE_UINT32(ICMPV6Descriptor->p_Bindings, PTR_TO_UINT(icmpv6_bindings) - fmMuramVirtBaseAddr); + } + WRITE_UINT32(ICMPV6Descriptor->p_Statistics, PTR_TO_UINT(icmpv6_bindings) + + sizeof(t_DsarIcmpV6BindingEntry) * params->p_AutoResEchoIpv6Info->tableSize - fmMuramVirtBaseAddr); + } + + // ND + if (params->p_AutoResNdpInfo) + { + t_DsarIcmpV6BindingEntry* icmpv6_bindings; + NDDescriptor = (t_DsarNdDescriptor*)(PTR_TO_UINT(ArCommonDescPtr) + of->nd); + WRITE_UINT32(ArCommonDescPtr->p_NdDescriptor, PTR_TO_UINT(NDDescriptor) - fmMuramVirtBaseAddr); + icmpv6_bindings = (t_DsarIcmpV6BindingEntry*)(PTR_TO_UINT(NDDescriptor) + sizeof(t_DsarNdDescriptor)); + WRITE_UINT16(NDDescriptor->control, 0); + if (params->p_AutoResNdpInfo->tableSizeAssigned + params->p_AutoResNdpInfo->tableSizeTmp) + { + t_FmPortDsarNdpEntry* ndp_entry = params->p_AutoResNdpInfo->p_AutoResTableAssigned; + WRITE_UINT16(*(uint16_t*)&ArCommonDescPtr->macStationAddr[0], *(uint16_t*)&ndp_entry[0].mac[0]); + WRITE_UINT32(*(uint32_t*)&ArCommonDescPtr->macStationAddr[2], *(uint32_t*)&ndp_entry[0].mac[2]); + WRITE_UINT16(NDDescriptor->numOfBindings, params->p_AutoResNdpInfo->tableSizeAssigned + + params->p_AutoResNdpInfo->tableSizeTmp); + + for (i = 0; i < params->p_AutoResNdpInfo->tableSizeAssigned; i++) + { + for (j = 0; j < 4; j++) + WRITE_UINT32(icmpv6_bindings[i].ipv6Addr[j], ndp_entry[i].ipAddress[j]); + if (ndp_entry[i].isVlan) + WRITE_UINT16(*(uint16_t*)&icmpv6_bindings[i].ipv6Addr[4], ndp_entry[i].vid & 0xFFF); // writing vlan + } + ndp_entry = params->p_AutoResNdpInfo->p_AutoResTableTmp; + for (i = 0; i < params->p_AutoResNdpInfo->tableSizeTmp; i++) + { + for (j = 0; j < 4; j++) + WRITE_UINT32(icmpv6_bindings[i + params->p_AutoResNdpInfo->tableSizeAssigned].ipv6Addr[j], ndp_entry[i].ipAddress[j]); + if (ndp_entry[i].isVlan) + WRITE_UINT16(*(uint16_t*)&icmpv6_bindings[i + params->p_AutoResNdpInfo->tableSizeAssigned].ipv6Addr[4], ndp_entry[i].vid & 0xFFF); // writing vlan + } + WRITE_UINT32(NDDescriptor->p_Bindings, PTR_TO_UINT(icmpv6_bindings) - fmMuramVirtBaseAddr); + } + WRITE_UINT32(NDDescriptor->p_Statistics, PTR_TO_UINT(icmpv6_bindings) + sizeof(t_DsarIcmpV6BindingEntry) + * (params->p_AutoResNdpInfo->tableSizeAssigned + params->p_AutoResNdpInfo->tableSizeTmp) + - fmMuramVirtBaseAddr); + WRITE_UINT32(NDDescriptor->solicitedAddr, 0xFFFFFFFF); + } + + // SNMP + if (params->p_AutoResSnmpInfo) + { + t_FmPortDsarSnmpInfo *snmpSrc = params->p_AutoResSnmpInfo; + t_DsarSnmpIpv4AddrTblEntry* snmpIpv4Addr; + t_DsarSnmpIpv6AddrTblEntry* snmpIpv6Addr; + t_OidsTblEntry* snmpOid; + uint8_t *charPointer; + int len; + t_DsarSnmpDescriptor* SnmpDescriptor = (t_DsarSnmpDescriptor*)(PTR_TO_UINT(ArCommonDescPtr) + of->snmp); + WRITE_UINT32(ArCommonDescPtr->p_SnmpDescriptor, PTR_TO_UINT(SnmpDescriptor) - fmMuramVirtBaseAddr); + WRITE_UINT16(SnmpDescriptor->control, snmpSrc->control); + WRITE_UINT16(SnmpDescriptor->maxSnmpMsgLength, snmpSrc->maxSnmpMsgLength); + snmpIpv4Addr = (t_DsarSnmpIpv4AddrTblEntry*)(PTR_TO_UINT(SnmpDescriptor) + sizeof(t_DsarSnmpDescriptor)); + if (snmpSrc->numOfIpv4Addresses) + { + t_FmPortDsarSnmpIpv4AddrTblEntry* snmpIpv4AddrSrc = snmpSrc->p_Ipv4AddrTbl; + WRITE_UINT16(SnmpDescriptor->numOfIpv4Addresses, snmpSrc->numOfIpv4Addresses); + for (i = 0; i < snmpSrc->numOfIpv4Addresses; i++) + { + WRITE_UINT32(snmpIpv4Addr[i].ipv4Addr, snmpIpv4AddrSrc[i].ipv4Addr); + if (snmpIpv4AddrSrc[i].isVlan) + WRITE_UINT16(snmpIpv4Addr[i].vlanId, snmpIpv4AddrSrc[i].vid & 0xFFF); + } + WRITE_UINT32(SnmpDescriptor->p_Ipv4AddrTbl, PTR_TO_UINT(snmpIpv4Addr) - fmMuramVirtBaseAddr); + } + snmpIpv6Addr = (t_DsarSnmpIpv6AddrTblEntry*)(PTR_TO_UINT(snmpIpv4Addr) + + sizeof(t_DsarSnmpIpv4AddrTblEntry) * snmpSrc->numOfIpv4Addresses); + if (snmpSrc->numOfIpv6Addresses) + { + t_FmPortDsarSnmpIpv6AddrTblEntry* snmpIpv6AddrSrc = snmpSrc->p_Ipv6AddrTbl; + WRITE_UINT16(SnmpDescriptor->numOfIpv6Addresses, snmpSrc->numOfIpv6Addresses); + for (i = 0; i < snmpSrc->numOfIpv6Addresses; i++) + { + for (j = 0; j < 4; j++) + WRITE_UINT32(snmpIpv6Addr[i].ipv6Addr[j], snmpIpv6AddrSrc[i].ipv6Addr[j]); + if (snmpIpv6AddrSrc[i].isVlan) + WRITE_UINT16(snmpIpv6Addr[i].vlanId, snmpIpv6AddrSrc[i].vid & 0xFFF); + } + WRITE_UINT32(SnmpDescriptor->p_Ipv6AddrTbl, PTR_TO_UINT(snmpIpv6Addr) - fmMuramVirtBaseAddr); + } + snmpOid = (t_OidsTblEntry*)(PTR_TO_UINT(snmpIpv6Addr) + + sizeof(t_DsarSnmpIpv6AddrTblEntry) * snmpSrc->numOfIpv6Addresses); + charPointer = (uint8_t*)(PTR_TO_UINT(snmpOid) + + sizeof(t_OidsTblEntry) * snmpSrc->oidsTblSize); + len = TOTAL_BER_LEN(GetBERLen(&snmpSrc->p_RdOnlyCommunityStr[1])); + Mem2IOCpy32(charPointer, snmpSrc->p_RdOnlyCommunityStr, len); + WRITE_UINT32(SnmpDescriptor->p_RdOnlyCommunityStr, PTR_TO_UINT(charPointer) - fmMuramVirtBaseAddr); + charPointer += len; + len = TOTAL_BER_LEN(GetBERLen(&snmpSrc->p_RdWrCommunityStr[1])); + Mem2IOCpy32(charPointer, snmpSrc->p_RdWrCommunityStr, len); + WRITE_UINT32(SnmpDescriptor->p_RdWrCommunityStr, PTR_TO_UINT(charPointer) - fmMuramVirtBaseAddr); + charPointer += len; + WRITE_UINT32(SnmpDescriptor->oidsTblSize, snmpSrc->oidsTblSize); + WRITE_UINT32(SnmpDescriptor->p_OidsTbl, PTR_TO_UINT(snmpOid) - fmMuramVirtBaseAddr); + for (i = 0; i < snmpSrc->oidsTblSize; i++) + { + WRITE_UINT16(snmpOid->oidSize, snmpSrc->p_OidsTbl[i].oidSize); + WRITE_UINT16(snmpOid->resSize, snmpSrc->p_OidsTbl[i].resSize); + Mem2IOCpy32(charPointer, snmpSrc->p_OidsTbl[i].p_Oid, snmpSrc->p_OidsTbl[i].oidSize); + WRITE_UINT32(snmpOid->p_Oid, PTR_TO_UINT(charPointer) - fmMuramVirtBaseAddr); + charPointer += snmpSrc->p_OidsTbl[i].oidSize; + if (snmpSrc->p_OidsTbl[i].resSize <= 4) + WRITE_UINT32(snmpOid->resValOrPtr, snmpSrc->p_OidsTbl[i].resValOrPtr); + else + { + Mem2IOCpy32(charPointer, UINT_TO_PTR(snmpSrc->p_OidsTbl[i].resValOrPtr), snmpSrc->p_OidsTbl[i].resSize); + WRITE_UINT32(snmpOid->resValOrPtr, PTR_TO_UINT(charPointer) - fmMuramVirtBaseAddr); + charPointer += snmpSrc->p_OidsTbl[i].resSize; + } + snmpOid++; + } + charPointer = UINT_TO_PTR(ROUND_UP(PTR_TO_UINT(charPointer),4)); + WRITE_UINT32(SnmpDescriptor->p_Statistics, PTR_TO_UINT(charPointer) - fmMuramVirtBaseAddr); + } + + // filtering + if (params->p_AutoResFilteringInfo) + { + if (params->p_AutoResFilteringInfo->ipProtDropOnHit) + tmp |= IP_PROT_TBL_PASS_MASK; + if (params->p_AutoResFilteringInfo->udpPortDropOnHit) + tmp |= UDP_PORT_TBL_PASS_MASK; + if (params->p_AutoResFilteringInfo->tcpPortDropOnHit) + tmp |= TCP_PORT_TBL_PASS_MASK; + WRITE_UINT8(ArCommonDescPtr->filterControl, tmp); + + // ip filtering + if (params->p_AutoResFilteringInfo->ipProtTableSize) + { + uint8_t* ip_tbl = (uint8_t*)(PTR_TO_UINT(ArCommonDescPtr) + of->filtIp); + WRITE_UINT8(ArCommonDescPtr->ipProtocolTblSize, params->p_AutoResFilteringInfo->ipProtTableSize); + for (i = 0; i < params->p_AutoResFilteringInfo->ipProtTableSize; i++) + WRITE_UINT8(ip_tbl[i], params->p_AutoResFilteringInfo->p_IpProtTablePtr[i]); + WRITE_UINT32(ArCommonDescPtr->p_IpProtocolFiltTbl, PTR_TO_UINT(ip_tbl) - fmMuramVirtBaseAddr); + } + + // udp filtering + if (params->p_AutoResFilteringInfo->udpPortsTableSize) + { + t_PortTblEntry* udp_tbl = (t_PortTblEntry*)(PTR_TO_UINT(ArCommonDescPtr) + of->filtUdp); + WRITE_UINT8(ArCommonDescPtr->udpPortTblSize, params->p_AutoResFilteringInfo->udpPortsTableSize); + for (i = 0; i < params->p_AutoResFilteringInfo->udpPortsTableSize; i++) + { + WRITE_UINT32(udp_tbl[i].Ports, + (params->p_AutoResFilteringInfo->p_UdpPortsTablePtr[i].srcPort << 16) + + params->p_AutoResFilteringInfo->p_UdpPortsTablePtr[i].dstPort); + WRITE_UINT32(udp_tbl[i].PortsMask, + (params->p_AutoResFilteringInfo->p_UdpPortsTablePtr[i].srcPortMask << 16) + + params->p_AutoResFilteringInfo->p_UdpPortsTablePtr[i].dstPortMask); + } + WRITE_UINT32(ArCommonDescPtr->p_UdpPortFiltTbl, PTR_TO_UINT(udp_tbl) - fmMuramVirtBaseAddr); + } + + // tcp filtering + if (params->p_AutoResFilteringInfo->tcpPortsTableSize) + { + t_PortTblEntry* tcp_tbl = (t_PortTblEntry*)(PTR_TO_UINT(ArCommonDescPtr) + of->filtTcp); + WRITE_UINT8(ArCommonDescPtr->tcpPortTblSize, params->p_AutoResFilteringInfo->tcpPortsTableSize); + for (i = 0; i < params->p_AutoResFilteringInfo->tcpPortsTableSize; i++) + { + WRITE_UINT32(tcp_tbl[i].Ports, + (params->p_AutoResFilteringInfo->p_TcpPortsTablePtr[i].srcPort << 16) + + params->p_AutoResFilteringInfo->p_TcpPortsTablePtr[i].dstPort); + WRITE_UINT32(tcp_tbl[i].PortsMask, + (params->p_AutoResFilteringInfo->p_TcpPortsTablePtr[i].srcPortMask << 16) + + params->p_AutoResFilteringInfo->p_TcpPortsTablePtr[i].dstPortMask); + } + WRITE_UINT32(ArCommonDescPtr->p_TcpPortFiltTbl, PTR_TO_UINT(tcp_tbl) - fmMuramVirtBaseAddr); + } + } + // common stats + WRITE_UINT32(ArCommonDescPtr->p_ArStats, PTR_TO_UINT(ArCommonDescPtr) + of->stats - fmMuramVirtBaseAddr); + + // get into Deep Sleep sequence: + // Stage 6: configure tx port to im + p_FmPort->deepSleepVars.fmbm_tcfg = GET_UINT32(p_FmPortTx->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tcfg); + WRITE_UINT32(p_FmPortTx->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tcfg, GET_UINT32(p_FmPortTx->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tcfg) | BMI_PORT_CFG_IM); + // ???? + p_FmPort->deepSleepVars.fmbm_tcmne = GET_UINT32(p_FmPortTx->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tcmne); + WRITE_UINT32(p_FmPortTx->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tcmne, 0xE); + // Stage 7:echo + p_FmPort->deepSleepVars.fmbm_rfne = GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfne); + WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfne, 0x440000); + p_FmPort->deepSleepVars.fmbm_rfpne = GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfpne); + h_FmPcd = FmGetPcd(p_FmPort->h_Fm); + if (!PrsIsEnabled(h_FmPcd)) + { + p_FmPort->deepSleepVars.dsarEnabledParser = TRUE; + PrsEnable(h_FmPcd); + } + else + p_FmPort->deepSleepVars.dsarEnabledParser = FALSE; + + WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfpne, 0x2E); + // Stage 8: We don't support magic packet for now. + // Stage 9: Accumulate mode +// WRITE_UINT32(p_FmPort->port.bmi_regs->rx.fmbm_rcfg, GET_UINT32(p_FmPort->port.bmi_regs->rx.fmbm_rcfg) | BMI_PORT_CFG_AM); + ARDesc = UINT_TO_PTR(XX_VirtToPhys(ArCommonDescPtr)); + return E_OK; +} + +void FM_PORT_Dsar_DumpRegs() +{ + uint32_t* hh = XX_PhysToVirt(PTR_TO_UINT(ARDesc)); + DUMP_MEMORY(hh, 0x180); +} + +void FM_PORT_ExitDsar(t_Handle h_FmPortRx, t_Handle h_FmPortTx) +{ + t_FmPort *p_FmPort = (t_FmPort *)h_FmPortRx; + t_FmPort *p_FmPortTx = (t_FmPort *)h_FmPortTx; + if (p_FmPort->deepSleepVars.autoResOffsets) + { + XX_Free(p_FmPort->deepSleepVars.autoResOffsets); + p_FmPort->deepSleepVars.autoResOffsets = 0; + } + if (p_FmPort->deepSleepVars.autoResMaxSizes) + { + XX_Free(p_FmPort->deepSleepVars.autoResMaxSizes); + p_FmPort->deepSleepVars.autoResMaxSizes = 0; + } + + if (p_FmPort->deepSleepVars.dsarEnabledParser) + PrsDisable(FmGetPcd(p_FmPort->h_Fm)); + WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfpne, p_FmPort->deepSleepVars.fmbm_rfpne); + WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfne, p_FmPort->deepSleepVars.fmbm_rfne); + WRITE_UINT32(p_FmPortTx->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tcmne, p_FmPort->deepSleepVars.fmbm_tcmne); + WRITE_UINT32(p_FmPortTx->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tcfg, p_FmPort->deepSleepVars.fmbm_tcfg); +} + +bool FM_PORT_IsInDsar(t_Handle h_FmPort) +{ + t_FmPort *p_FmPort = (t_FmPort *)h_FmPort; + return PTR_TO_UINT(p_FmPort->deepSleepVars.autoResOffsets); +} + +t_Error FM_PORT_GetDsarStats(t_Handle h_FmPortRx, t_FmPortDsarStats *stats) +{ + t_FmPort *p_FmPort = (t_FmPort *)h_FmPortRx; + struct arOffsets *of = (struct arOffsets*)p_FmPort->deepSleepVars.autoResOffsets; + uint8_t* fmMuramVirtBaseAddr = XX_PhysToVirt(p_FmPort->fmMuramPhysBaseAddr); + uint32_t *param_page = XX_PhysToVirt(p_FmPort->fmMuramPhysBaseAddr + GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rgpr)); + t_ArCommonDesc *ArCommonDescPtr = (t_ArCommonDesc*)(XX_PhysToVirt(p_FmPort->fmMuramPhysBaseAddr + GET_UINT32(*param_page))); + t_DsarArpDescriptor *ArpDescriptor = (t_DsarArpDescriptor*)(PTR_TO_UINT(ArCommonDescPtr) + of->arp); + t_DsarArpStatistics* arp_stats = (t_DsarArpStatistics*)(PTR_TO_UINT(ArpDescriptor->p_Statistics) + fmMuramVirtBaseAddr); + t_DsarIcmpV4Descriptor* ICMPV4Descriptor = (t_DsarIcmpV4Descriptor*)(PTR_TO_UINT(ArCommonDescPtr) + of->icmpv4); + t_DsarIcmpV4Statistics* icmpv4_stats = (t_DsarIcmpV4Statistics*)(PTR_TO_UINT(ICMPV4Descriptor->p_Statistics) + fmMuramVirtBaseAddr); + t_DsarNdDescriptor* NDDescriptor = (t_DsarNdDescriptor*)(PTR_TO_UINT(ArCommonDescPtr) + of->nd); + t_NdStatistics* nd_stats = (t_NdStatistics*)(PTR_TO_UINT(NDDescriptor->p_Statistics) + fmMuramVirtBaseAddr); + t_DsarIcmpV6Descriptor* ICMPV6Descriptor = (t_DsarIcmpV6Descriptor*)(PTR_TO_UINT(ArCommonDescPtr) + of->icmpv6); + t_DsarIcmpV6Statistics* icmpv6_stats = (t_DsarIcmpV6Statistics*)(PTR_TO_UINT(ICMPV6Descriptor->p_Statistics) + fmMuramVirtBaseAddr); + t_DsarSnmpDescriptor* SnmpDescriptor = (t_DsarSnmpDescriptor*)(PTR_TO_UINT(ArCommonDescPtr) + of->snmp); + t_DsarSnmpStatistics* snmp_stats = (t_DsarSnmpStatistics*)(PTR_TO_UINT(SnmpDescriptor->p_Statistics) + fmMuramVirtBaseAddr); + stats->arpArCnt = arp_stats->arCnt; + stats->echoIcmpv4ArCnt = icmpv4_stats->arCnt; + stats->ndpArCnt = nd_stats->arCnt; + stats->echoIcmpv6ArCnt = icmpv6_stats->arCnt; + stats->snmpGetCnt = snmp_stats->snmpGetReqCnt; + stats->snmpGetNextCnt = snmp_stats->snmpGetNextReqCnt; + return E_OK; +} diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Port/fm_port.h b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Port/fm_port.h index d4cc285..7568258 100644 --- a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Port/fm_port.h +++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Port/fm_port.h @@ -46,7 +46,7 @@ #include "fm_common.h" #include "fm_sp_common.h" #include "fsl_fman_sp.h" - +#include "fm_port_ext.h" #include "fsl_fman_port.h" #define __ERR_MODULE__ MODULE_FM_PORT @@ -854,6 +854,16 @@ typedef struct t_FmPortRxPoolsParams uint16_t largestBufSize; } t_FmPortRxPoolsParams; +typedef struct t_FmPortDsarVars { + t_Handle *autoResOffsets; + t_FmPortDsarTablesSizes *autoResMaxSizes; + uint32_t fmbm_tcfg; + uint32_t fmbm_tcmne; + uint32_t fmbm_rfne; + uint32_t fmbm_rfpne; + bool dsarEnabledParser; +} t_FmPortDsarVars; + typedef struct { struct fman_port port; t_Handle h_Fm; @@ -919,7 +929,7 @@ typedef struct { e_FmPortGprFuncType gprFunc; t_FmPcdCtrlParamsPage *p_ParamsPage; #endif /* (DPAA_VERSION >= 11) */ - + t_FmPortDsarVars deepSleepVars; t_FmPortDriverParam *p_FmPortDriverParam; } t_FmPort; @@ -970,5 +980,7 @@ static __inline__ uint16_t GetNextBdId(t_FmPort *p_FmPort, uint16_t id) return 0; } +void FM_PORT_Dsar_DumpRegs(void); + #endif /* __FM_PORT_H */ diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Port/fm_port_dsar.h b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Port/fm_port_dsar.h new file mode 100755 index 0000000..95619ef --- /dev/null +++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Port/fm_port_dsar.h @@ -0,0 +1,494 @@ +/* + * Copyright 2008-2012 Freescale Semiconductor Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Freescale Semiconductor nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") as published by the Free Software + * Foundation, either version 2 of that License or (at your option) any + * later version. + * + * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/**************************************************************************//** + @File fm_port_dsar.h + + @Description Deep Sleep Auto Response project - common module header file. + + Author - Eyal Harari + + @Cautions See the FMan Controller spec and design document for more information. +*//***************************************************************************/ + +#ifndef __FM_PORT_DSAR_H_ +#define __FM_PORT_DSAR_H_ + +#define DSAR_GETSER_MASK 0xFF0000FF + +#if defined(__MWERKS__) && !defined(__GNUC__) +#pragma pack(push,1) +#endif /* defined(__MWERKS__) && ... */ + +/**************************************************************************//** + @Description Deep Sleep Auto Response VLAN-IPv4 Binding Table (for ARP/ICMPv4) + Refer to the FMan Controller spec for more details. +*//***************************************************************************/ +typedef _Packed struct +{ + uint32_t ipv4Addr; /*!< 32 bit IPv4 Address. */ + uint16_t vlanId; /*!< 12 bits VLAN ID. The 4 left-most bits should be cleared */ + /*!< This field should be 0x0000 for an entry with no VLAN tag or a null VLAN ID. */ + uint16_t reserved; +} _PackedType t_DsarArpBindingEntry; + +/**************************************************************************//** + @Description Deep Sleep Auto Response Address Resolution Protocol Statistics Descriptor + Refer to the FMan Controller spec for more details. + 0x00 INVAL_CNT Invalid ARP IPv4-Ethernet counter + 0x04 ECHO_CNT Echo counter + 0x08 CD_CNT Conflict Detection counter + 0x0C AR_CNT Auto-Response counter + 0x10 RATM_CNT Replies Addressed To Me counter + 0x14 UKOP_CNT Unknown Operation counter + 0x18 NMTP_CNT Not my TPA counter + 0x1C NMVLAN_CNT Not My VLAN counter +*//***************************************************************************/ +typedef _Packed struct +{ + uint32_t invalCnt; /**< Invalid ARP IPv4-Ethernet counter. */ + uint32_t echoCnt; /**< Echo counter. */ + uint32_t cdCnt; /**< Conflict Detection counter. */ + uint32_t arCnt; /**< Auto-Response counter. */ + uint32_t ratmCnt; /**< Replies Addressed To Me counter. */ + uint32_t ukopCnt; /**< Unknown Operation counter. */ + uint32_t nmtpCnt; /**< Not my TPA counter. */ + uint32_t nmVlanCnt; /**< Not My VLAN counter */ +} _PackedType t_DsarArpStatistics; + + +/**************************************************************************//** + @Description Deep Sleep Auto Response Address Resolution Protocol Descriptor + 0x0 0-15 Control bits [0-15]. Bit 15 = CDEN. + 0x2 0-15 NumOfBindings Number of entries in the binding list. + 0x4 0-15 BindingsPointer Bindings Pointer. This points to an IPv4-MAC Addresses Bindings list. + 0x6 0-15 + 0x8 0-15 StatisticsPointer Statistics Pointer. This field points to the ARP Descriptors statistics data structure. + 0xA 0-15 + 0xC 0-15 Reserved Reserved. Must be cleared. + 0xE 015 + +*//***************************************************************************/ +typedef _Packed struct +{ + uint16_t control; /** Control bits [0-15]. Bit 15 = CDEN */ + uint16_t numOfBindings; /**< Number of VLAN-IPv4 */ + uint32_t p_Bindings; /**< VLAN-IPv4 Bindings table pointer. */ + uint32_t p_Statistics; /**< Statistics Data Structure pointer. */ + uint32_t reserved1; /**< Reserved. */ +} _PackedType t_DsarArpDescriptor; + + +/**************************************************************************//** + @Description Deep Sleep Auto Response VLAN-IPv4 Binding Table (for ARP/ICMPv4) + Refer to the FMan Controller spec for more details. +*//***************************************************************************/ +typedef _Packed struct +{ + uint32_t ipv4Addr; /*!< 32 bit IPv4 Address. */ + uint16_t vlanId; /*!< 12 bits VLAN ID. The 4 left-most bits should be cleared */ + /*!< This field should be 0x0000 for an entry with no VLAN tag or a null VLAN ID. */ + uint16_t reserved; +} _PackedType t_DsarIcmpV4BindingEntry; + +/**************************************************************************//** + @Description Deep Sleep Auto Response ICMPv4 Statistics Descriptor + Refer to the FMan Controller spec for more details. + 0x00 INVAL_CNT Invalid ICMPv4 header counter + 0x04 NMVLAN_CNT Not My VLAN counter + 0x08 NMIP_CNT Not My IP counter + 0x0C AR_CNT Auto-Response counter + 0x10 CSERR_CNT Checksum Error counter + 0x14 Reserved Reserved + 0x18 Reserved Reserved + 0x1C Reserved Reserved + +*//***************************************************************************/ +typedef _Packed struct +{ + uint32_t invalCnt; /**< Invalid ICMPv4 Echo counter. */ + uint32_t nmVlanCnt; /**< Not My VLAN counter */ + uint32_t nmIpCnt; /**< Not My IP counter */ + uint32_t arCnt; /**< Auto-Response counter */ + uint32_t cserrCnt; /**< Checksum Error counter */ + uint32_t reserved0; /**< Reserved */ + uint32_t reserved1; /**< Reserved */ + uint32_t reserved2; /**< Reserved */ +} _PackedType t_DsarIcmpV4Statistics; + + + +/**************************************************************************//** + @Description Deep Sleep Auto Response ICMPv4 Descriptor + 0x0 0-15 Control bits [0-15] + 0x2 0-15 NumOfBindings Number of entries in the binding list. + 0x4 0-15 BindingsPointer Bindings Pointer. This points to an VLAN-IPv4 Addresses Bindings list. + 0x6 0-15 + 0x8 0-15 StatisticsPointer Statistics Pointer. This field points to the ICMPv4 statistics data structure. + 0xA 0-15 + 0xC 0-15 Reserved Reserved. Must be cleared. + 0xE 015 + +*//***************************************************************************/ +typedef _Packed struct +{ + uint16_t control; /** Control bits [0-15]. */ + uint16_t numOfBindings; /**< Number of VLAN-IPv4 */ + uint32_t p_Bindings; /**< VLAN-IPv4 Bindings table pointer. */ + uint32_t p_Statistics; /**< Statistics Data Structure pointer. */ + uint32_t reserved1; /**< Reserved. */ +} _PackedType t_DsarIcmpV4Descriptor; + +/**************************************************************************//** + @Description Deep Sleep Auto Response VLAN-IPv4 Binding Table (for ARP/ICMPv4) + The 4 left-most bits (15:12) of the VlanId parameter are control flags. + Flags[3:1] (VlanId[15:13]): Reserved, should be cleared. + Flags[0] (VlanId[12]): Temporary address. + • 0 - Assigned IP address. + • 1- Temporary (tentative) IP address. + Refer to the FMan Controller spec for more details. +*//***************************************************************************/ +typedef _Packed struct +{ + uint32_t ipv6Addr[4]; /*!< 3 * 32 bit IPv4 Address. */ + uint16_t resFlags:4; /*!< reserved flags. should be cleared */ + uint16_t vlanId:12; /*!< 12 bits VLAN ID. */ + /*!< This field should be 0x000 for an entry with no VLAN tag or a null VLAN ID. */ + uint16_t reserved; +} _PackedType t_DsarIcmpV6BindingEntry; + +/**************************************************************************//** + @Description Deep Sleep Auto Response ICMPv4 Statistics Descriptor + Refer to the FMan Controller spec for more details. + 0x00 INVAL_CNT Invalid ICMPv4 header counter + 0x04 NMVLAN_CNT Not My VLAN counter + 0x08 NMIP_CNT Not My IP counter + 0x0C AR_CNT Auto-Response counter + 0x10 CSERR_CNT Checksum Error counter + 0x14 MCAST_CNT Multicast counter + 0x18 Reserved Reserved + 0x1C Reserved Reserved + +*//***************************************************************************/ +typedef _Packed struct +{ + uint32_t invalCnt; /**< Invalid ICMPv4 Echo counter. */ + uint32_t nmVlanCnt; /**< Not My VLAN counter */ + uint32_t nmIpCnt; /**< Not My IP counter */ + uint32_t arCnt; /**< Auto-Response counter */ + uint32_t reserved1; /**< Reserved */ + uint32_t reserved2; /**< Reserved */ + uint32_t reserved3; /**< Reserved */ + uint32_t reserved4; /**< Reserved */ +} _PackedType t_DsarIcmpV6Statistics; + +/**************************************************************************//** + @Description Deep Sleep Auto Response Neighbor Discovery Statistics Descriptor + 0x00 INVAL_CNT Invalid Neighbor Discovery message counter + 0x04 NMVLAN_CNT Not My VLAN counter + 0x08 NMIP_CNT Not My IP counter + 0x0C AR_CNT Auto-Response counter + 0x10 CSERR_CNT Checksum Error counter + 0x14 USADVERT_CNT Unsolicited Neighbor Advertisements counter + 0x18 NMMCAST_CNT Not My Multicast group counter + 0x1C NSLLA_CNT No Source Link-Layer Address counter. Indicates that there was a match on a Target + Address of a packet that its source IP address is a unicast address, but the ICMPv6 + Source Link-layer Address option is omitted +*//***************************************************************************/ +typedef _Packed struct +{ + uint32_t invalCnt; /**< Invalid ICMPv4 Echo counter. */ + uint32_t nmVlanCnt; /**< Not My VLAN counter */ + uint32_t nmIpCnt; /**< Not My IP counter */ + uint32_t arCnt; /**< Auto-Response counter */ + uint32_t reserved1; /**< Reserved */ + uint32_t usadvertCnt; /**< Unsolicited Neighbor Advertisements counter */ + uint32_t nmmcastCnt; /**< Not My Multicast group counter */ + uint32_t nsllaCnt; /**< No Source Link-Layer Address counter */ +} _PackedType t_NdStatistics; + +/**************************************************************************//** + @Description Deep Sleep Auto Response ICMPv6 Descriptor + 0x0 0-15 Control bits [0-15] + 0x2 0-15 NumOfBindings Number of entries in the binding list. + 0x4 0-15 BindingsPointer Bindings Pointer. This points to an VLAN-IPv4 Addresses Bindings list. + 0x6 0-15 + 0x8 0-15 StatisticsPointer Statistics Pointer. This field points to the ICMPv4 statistics data structure. + 0xA 0-15 + 0xC 0-15 Reserved Reserved. Must be cleared. + 0xE 015 + +*//***************************************************************************/ +typedef _Packed struct +{ + uint16_t control; /** Control bits [0-15]. */ + uint16_t numOfBindings; /**< Number of VLAN-IPv6 */ + uint32_t p_Bindings; /**< VLAN-IPv4 Bindings table pointer. */ + uint32_t p_Statistics; /**< Statistics Data Structure pointer. */ + uint32_t reserved1; /**< Reserved. */ +} _PackedType t_DsarIcmpV6Descriptor; + + +/**************************************************************************//** + @Description Internet Control Message Protocol (ICMPv6) Echo message header + The fields names are taken from RFC 4443. +*//***************************************************************************/ +/* 0 1 2 3 */ +/* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 */ +/* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ +/* | Type | Code | Checksum | */ +/* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ +/* | Identifier | Sequence Number | */ +/* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ +/* | Data ... */ +/* +-+-+-+-+- */ +typedef _Packed struct +{ + uint8_t type; + uint8_t code; + uint16_t checksum; + uint16_t identifier; + uint16_t sequenceNumber; +} _PackedType t_IcmpV6EchoHdr; + +/**************************************************************************//** + @Description Internet Control Message Protocol (ICMPv6) + Neighbor Solicitation/Advertisement header + The fields names are taken from RFC 4861. + The R/S/O fields are valid for Neighbor Advertisement only +*//***************************************************************************/ +/* 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Type | Code | Checksum | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |R|S|O| Reserved | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | | + * + + + * | | + * + Target Address + + * | | + * + + + * | | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Options ... + * +-+-+-+-+-+-+-+-+-+-+-+- + * + * Options Format: + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Type | Length | Link-Layer Address ... | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Link-Layer Address | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +*/ +typedef _Packed struct +{ + uint8_t type; + uint8_t code; + uint16_t checksum; + uint32_t router:1; + uint32_t solicited:1; + uint32_t override:1; + uint32_t reserved:29; + uint32_t targetAddr[4]; + uint8_t optionType; + uint8_t optionLength; + uint8_t linkLayerAddr[6]; +} _PackedType t_IcmpV6NdHdr; + +/**************************************************************************//** + @Description Deep Sleep Auto Response ICMPv6 Descriptor + 0x0 0-15 Control bits [0-15] + 0x2 0-15 NumOfBindings Number of entries in the binding list. + 0x4 0-15 BindingsPointer Bindings Pointer. This points to an VLAN-IPv4 Addresses Bindings list. + 0x6 0-15 + 0x8 0-15 StatisticsPointer Statistics Pointer. This field points to the ICMPv4 statistics data structure. + 0xA 0-15 + 0xC 0-15 Reserved Reserved. Must be cleared. + 0xE 015 + +*//***************************************************************************/ +typedef _Packed struct +{ + uint16_t control; /** Control bits [0-15]. */ + uint16_t numOfBindings; /**< Number of VLAN-IPv6 */ + uint32_t p_Bindings; /**< VLAN-IPv4 Bindings table pointer. */ + uint32_t p_Statistics; /**< Statistics Data Structure pointer. */ + uint32_t solicitedAddr; /**< Solicited Node Multicast Group Address */ +} _PackedType t_DsarNdDescriptor; + +/**************************************************************************//** +@Description Deep Sleep Auto Response SNMP OIDs table entry + +*//***************************************************************************/ +typedef struct { + uint16_t oidSize; /**< Size in octets of the OID. */ + uint16_t resSize; /**< Size in octets of the value that is attached to the OID. */ + uint32_t p_Oid; /**< Pointer to the OID. OID is encoded in BER but type and length are excluded. */ + uint32_t resValOrPtr; /**< Value (for up to 4 octets) or pointer to the Value. Encoded in BER. */ + uint32_t reserved; +} t_OidsTblEntry; + +/**************************************************************************//** + @Description Deep Sleep Auto Response SNMP IPv4 Addresses Table Entry + Refer to the FMan Controller spec for more details. +*//***************************************************************************/ +typedef struct +{ + uint32_t ipv4Addr; /*!< 32 bit IPv4 Address. */ + uint16_t vlanId; /*!< 12 bits VLAN ID. The 4 left-most bits should be cleared */ + /*!< This field should be 0x0000 for an entry with no VLAN tag or a null VLAN ID. */ + uint16_t reserved; +} t_DsarSnmpIpv4AddrTblEntry; + +/**************************************************************************//** + @Description Deep Sleep Auto Response SNMP IPv6 Addresses Table Entry + Refer to the FMan Controller spec for more details. +*//***************************************************************************/ +#pragma pack(push,1) +typedef struct +{ + uint32_t ipv6Addr[4]; /*!< 4 * 32 bit IPv6 Address. */ + uint16_t vlanId; /*!< 12 bits VLAN ID. The 4 left-most bits should be cleared */ + /*!< This field should be 0x0000 for an entry with no VLAN tag or a null VLAN ID. */ + uint16_t reserved; +} t_DsarSnmpIpv6AddrTblEntry; +#pragma pack(pop) + +/**************************************************************************//** +@Description Deep Sleep Auto Response SNMP statistics table + +*//***************************************************************************/ +typedef struct { + uint32_t snmpErrCnt; /**< Counts SNMP errors (wrong version, BER encoding, format). */ + uint32_t snmpCommunityErrCnt; /**< Counts messages that were dropped due to insufficient permission. */ + uint32_t snmpTotalDiscardCnt; /**< Counts any message that was dropped. */ + uint32_t snmpGetReqCnt; /**< Counts the number of get-request messages */ + uint32_t snmpGetNextReqCnt; /**< Counts the number of get-next-request messages */ +} t_DsarSnmpStatistics; + +/**************************************************************************//** + @Description Deep Sleep Auto Response SNMP Descriptor + +*//***************************************************************************/ +typedef struct +{ + uint16_t control; /**< Control bits [0-15]. */ + uint16_t maxSnmpMsgLength; /**< Maximal allowed SNMP message length. */ + uint16_t numOfIpv4Addresses; /**< Number of entries in IPv4 addresses table. */ + uint16_t numOfIpv6Addresses; /**< Number of entries in IPv6 addresses table. */ + uint32_t p_Ipv4AddrTbl; /**< Pointer to IPv4 addresses table. */ + uint32_t p_Ipv6AddrTbl; /**< Pointer to IPv6 addresses table. */ + uint32_t p_RdOnlyCommunityStr; /**< Pointer to the Read Only Community String. */ + uint32_t p_RdWrCommunityStr; /**< Pointer to the Read Write Community String. */ + uint32_t p_OidsTbl; /**< Pointer to OIDs table. */ + uint32_t oidsTblSize; /**< Number of entries in OIDs table. */ + uint32_t p_Statistics; /**< Pointer to SNMP statistics table. */ +} t_DsarSnmpDescriptor; + +/**************************************************************************//** +@Description Deep Sleep Auto Response (Common) Statistics + +*//***************************************************************************/ +typedef _Packed struct { + uint32_t dsarDiscarded; + uint32_t dsarErrDiscarded; + uint32_t dsarFragDiscarded; + uint32_t dsarTunnelDiscarded; + uint32_t dsarArpDiscarded; + uint32_t dsarIpDiscarded; + uint32_t dsarTcpDiscarded; + uint32_t dsarUdpDiscarded; + uint32_t dsarIcmpV6ChecksumErr; /* ICMPv6 Checksum Error counter */ + uint32_t dsarIcmpV6OtherType; /* ICMPv6 'Other' type (not Echo or Neighbor Solicitaion/Advertisement counter */ + uint32_t dsarIcmpV4OtherType; /* ICMPv4 'Other' type (not Echo) counter */ +} _PackedType t_ArStatistics; + + +/**************************************************************************//** +@Description Deep Sleep Auto Response TCP/UDP port filter table entry + +*//***************************************************************************/ +typedef _Packed struct { + uint32_t Ports; + uint32_t PortsMask; +} _PackedType t_PortTblEntry; + + + +/**************************************************************************//** +@Description Deep Sleep Auto Response Common Parameters Descriptor + +*//***************************************************************************/ +typedef _Packed struct { + uint8_t arTxPort; /* 0x00 0-7 Auto Response Transmit Port number */ + uint8_t controlBits; /* 0x00 8-15 Auto Response control bits */ + uint16_t res1; /* 0x00 16-31 Reserved */ + uint32_t activeHPNIA; /* 0x04 0-31 Active mode Hardware Parser NIA */ + uint16_t snmpPort; /* 0x08 0-15 SNMP Port. */ + uint8_t macStationAddr[6]; /* 0x08 16-31 and 0x0C 0-31 MAC Station Address */ + uint8_t res2; /* 0x10 0-7 Reserved */ + uint8_t filterControl; /* 0x10 8-15 Filtering Control Bits. */ + uint16_t tcpControlPass; /* 0x10 16-31 TCP control pass flags */ + uint8_t ipProtocolTblSize; /* 0x14 0-7 IP Protocol Table Size. */ + uint8_t udpPortTblSize; /* 0x14 8-15 UDP Port Table Size. */ + uint8_t tcpPortTblSize; /* 0x14 16-23 TCP Port Table Size. */ + uint8_t res3; /* 0x14 24-31 Reserved */ + uint32_t p_IpProtocolFiltTbl; /* 0x18 0-31 Pointer to IP Protocol Filter Table */ + uint32_t p_UdpPortFiltTbl; /* 0x1C 0-31 Pointer to UDP Port Filter Table */ + uint32_t p_TcpPortFiltTbl; /* 0x20 0-31 Pointer to TCP Port Filter Table */ + uint32_t res4; /* 0x24 Reserved */ + uint32_t p_ArpDescriptor; /* 0x28 0-31 ARP Descriptor Pointer. */ + uint32_t p_NdDescriptor; /* 0x2C 0-31 Neighbor Discovery Descriptor. */ + uint32_t p_IcmpV4Descriptor; /* 0x30 0-31 ICMPv4 Descriptor pointer. */ + uint32_t p_IcmpV6Descriptor; /* 0x34 0-31 ICMPv6 Descriptor pointer. */ + uint32_t p_SnmpDescriptor; /* 0x38 0-31 SNMP Descriptor pointer. */ + uint32_t p_ArStats; /* 0x3C 0-31 Pointer to Auto Response Statistics */ +} _PackedType t_ArCommonDesc; + +#if defined(__MWERKS__) && !defined(__GNUC__) +#pragma pack(pop) +#endif /* defined(__MWERKS__) && ... */ + +/* t_ArCommonDesc.filterControl bits */ +#define IP_PROT_TBL_PASS_MASK 0x08 +#define UDP_PORT_TBL_PASS_MASK 0x04 +#define TCP_PORT_TBL_PASS_MASK 0x02 + +/* Offset of TCF flags within TCP packet */ +#define TCP_FLAGS_OFFSET 12 + + +#endif /* __FM_PORT_DSAR_H_ */ diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/fm.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/fm.c index 5bb8282..17ac17e 100644 --- a/drivers/net/ethernet/freescale/fman/Peripherals/FM/fm.c +++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/fm.c @@ -5201,3 +5201,8 @@ t_Error FM_ForceIntr (t_Handle h_Fm, e_FmExceptions exception) return E_OK; } + +t_Handle FmGetPcd(t_Handle h_Fm) +{ + return ((t_Fm*)h_Fm)->h_Pcd; +} diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/inc/fm_common.h b/drivers/net/ethernet/freescale/fman/Peripherals/FM/inc/fm_common.h index 0d7bf55..a015900 100644 --- a/drivers/net/ethernet/freescale/fman/Peripherals/FM/inc/fm_common.h +++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/inc/fm_common.h @@ -658,6 +658,8 @@ bool FmPcdIsAdvancedOffloadSupported(t_Handle h_FmPcd); bool FmPcdLockTryLockAll(t_Handle h_FmPcd); void FmPcdLockUnlockAll(t_Handle h_FmPcd); t_Error FmPcdHcSync(t_Handle h_FmPcd); +t_Handle FmGetPcd(t_Handle h_Fm); + /***********************************************************************/ /* Common API for FM-PCD KG module */ diff --git a/drivers/net/ethernet/freescale/fman/inc/Peripherals/fm_port_ext.h b/drivers/net/ethernet/freescale/fman/inc/Peripherals/fm_port_ext.h index 4d05857..3a62b8d 100644 --- a/drivers/net/ethernet/freescale/fman/inc/Peripherals/fm_port_ext.h +++ b/drivers/net/ethernet/freescale/fman/inc/Peripherals/fm_port_ext.h @@ -45,7 +45,6 @@ #include "fm_ext.h" #include "net_ext.h" - /**************************************************************************//** @Group FM_grp Frame Manager API @@ -435,9 +434,47 @@ typedef struct t_FmPortPerformanceCnt { uint32_t fifoCompVal; /**< Fifo compare value (in bytes) */ } t_FmPortPerformanceCnt; +/**************************************************************************//** + @Description A structure for defining the sizes of the Deep Sleep + the Auto Response tables +*//***************************************************************************/ +typedef struct t_FmPortDsarTablesSizes +{ + uint16_t maxNumOfArpEntries; + uint16_t maxNumOfEchoIpv4Entries; + uint16_t maxNumOfNdpEntries; + uint16_t maxNumOfEchoIpv6Entries; + uint16_t maxNumOfSnmpIPV4Entries; + uint16_t maxNumOfSnmpIPV6Entries; + uint16_t maxNumOfSnmpOidEntries; + uint16_t maxNumOfSnmpOidChar; /* total amount of character needed for the snmp table */ + + uint16_t maxNumOfIpProtFiltering; + uint16_t maxNumOfTcpPortFiltering; + uint16_t maxNumOfUdpPortFiltering; +} t_FmPortDsarTablesSizes; /**************************************************************************//** + @Function FM_PORT_ConfigDsarSupport + + @Description This function will allocate the amount of MURAM needed for + this max number of entries for Deep Sleep Auto Response. + it will calculate all needed MURAM for autoresponse including + necesary common stuff. + + + @Param[in] h_FmPort A handle to a FM Port module. + @Param[in] params A pointer to a structure containing the maximum + sizes of the auto response tables + + @Return E_OK on success; Error code otherwise. + + @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). +*//***************************************************************************/ +t_Error FM_PORT_ConfigDsarSupport(t_Handle h_FmPortRx, t_FmPortDsarTablesSizes *params); + +/**************************************************************************//** @Function FM_PORT_ConfigNumOfOpenDmas @Description Calling this routine changes the max number of open DMA's @@ -1277,6 +1314,256 @@ typedef struct t_FmPortCongestionGrps { #endif /* (DPAA_VERSION >= 11) */ } t_FmPortCongestionGrps; +/**************************************************************************//** + @Description Structure for Deep Sleep Auto Response ARP Entry +*//***************************************************************************/ +typedef struct t_FmPortDsarArpEntry +{ + uint32_t ipAddress; + uint8_t mac[6]; + bool isVlan; + uint16_t vid; +} t_FmPortDsarArpEntry; + +/**************************************************************************//** + @Description Structure for Deep Sleep Auto Response ARP info +*//***************************************************************************/ +typedef struct t_FmPortDsarArpInfo +{ + uint8_t tableSize; + t_FmPortDsarArpEntry *p_AutoResTable; + bool enableConflictDetection; /* when TRUE Conflict Detection will be checked and wake the host if needed */ +} t_FmPortDsarArpInfo; + +/**************************************************************************//** + @Description Structure for Deep Sleep Auto Response NDP Entry +*//***************************************************************************/ +typedef struct t_FmPortDsarNdpEntry +{ + uint32_t ipAddress[4]; + uint8_t mac[6]; + bool isVlan; + uint16_t vid; +} t_FmPortDsarNdpEntry; + +/**************************************************************************//** + @Description Structure for Deep Sleep Auto Response NDP info +*//***************************************************************************/ +typedef struct t_FmPortDsarNdpInfo +{ + uint32_t multicastGroup; + + uint8_t tableSizeAssigned; + t_FmPortDsarNdpEntry *p_AutoResTableAssigned; /* This list refer to solicitation IP addresses. + Note that all IP adresses must be from the same multicast group. + This will be checked and if not operation will fail. */ + uint8_t tableSizeTmp; + t_FmPortDsarNdpEntry *p_AutoResTableTmp; /* This list refer to temp IP addresses. + Note that all temp IP adresses must be from the same multicast group. + This will be checked and if not operation will fail. */ + + bool enableConflictDetection; /* when TRUE Conflict Detection will be checked and wake the host if needed */ + +} t_FmPortDsarNdpInfo; + +/**************************************************************************//** + @Description Structure for Deep Sleep Auto Response ICMPV4 info +*//***************************************************************************/ +typedef struct t_FmPortDsarEchoIpv4Info +{ + uint8_t tableSize; + t_FmPortDsarArpEntry *p_AutoResTable; +} t_FmPortDsarEchoIpv4Info; + +/**************************************************************************//** + @Description Structure for Deep Sleep Auto Response ICMPV6 info +*//***************************************************************************/ +typedef struct t_FmPortDsarEchoIpv6Info +{ + uint8_t tableSize; + t_FmPortDsarNdpEntry *p_AutoResTable; +} t_FmPortDsarEchoIpv6Info; + +/**************************************************************************//** +@Description Deep Sleep Auto Response SNMP OIDs table entry + +*//***************************************************************************/ +typedef struct { + uint16_t oidSize; /**< Size in octets of the OID. */ + uint16_t resSize; /**< Size in octets of the value that is attached to the OID. */ + uint8_t *p_Oid; /**< Pointer to the OID. OID is encoded in BER but type and length are excluded. */ + uint64_t resValOrPtr; /**< Value (for up to 4 octets) or pointer to the Value. Encoded in BER. */ +} t_FmPortDsarOidsEntry; + +/**************************************************************************//** + @Description Deep Sleep Auto Response SNMP IPv4 Addresses Table Entry + Refer to the FMan Controller spec for more details. +*//***************************************************************************/ +typedef struct +{ + uint32_t ipv4Addr; /*!< 32 bit IPv4 Address. */ + bool isVlan; + uint16_t vid; /*!< 12 bits VLAN ID. The 4 left-most bits should be cleared */ + /*!< This field should be 0x0000 for an entry with no VLAN tag or a null VLAN ID. */ +} t_FmPortDsarSnmpIpv4AddrTblEntry; + +/**************************************************************************//** + @Description Deep Sleep Auto Response SNMP IPv6 Addresses Table Entry + Refer to the FMan Controller spec for more details. +*//***************************************************************************/ +typedef struct +{ + uint32_t ipv6Addr[4]; /*!< 4 * 32 bit IPv6 Address. */ + bool isVlan; + uint16_t vid; /*!< 12 bits VLAN ID. The 4 left-most bits should be cleared */ + /*!< This field should be 0x0000 for an entry with no VLAN tag or a null VLAN ID. */ +} t_FmPortDsarSnmpIpv6AddrTblEntry; + +/**************************************************************************//** + @Description Deep Sleep Auto Response SNMP Descriptor + +*//***************************************************************************/ +typedef struct +{ + uint16_t control; /**< Control bits [0-15]. */ + uint16_t maxSnmpMsgLength; /**< Maximal allowed SNMP message length. */ + uint16_t numOfIpv4Addresses; /**< Number of entries in IPv4 addresses table. */ + uint16_t numOfIpv6Addresses; /**< Number of entries in IPv6 addresses table. */ + t_FmPortDsarSnmpIpv4AddrTblEntry *p_Ipv4AddrTbl; /**< Pointer to IPv4 addresses table. */ + t_FmPortDsarSnmpIpv6AddrTblEntry *p_Ipv6AddrTbl; /**< Pointer to IPv6 addresses table. */ + uint8_t *p_RdOnlyCommunityStr; /**< Pointer to the Read Only Community String. */ + uint8_t *p_RdWrCommunityStr; /**< Pointer to the Read Write Community String. */ + t_FmPortDsarOidsEntry *p_OidsTbl; /**< Pointer to OIDs table. */ + uint32_t oidsTblSize; /**< Number of entries in OIDs table. */ +} t_FmPortDsarSnmpInfo; + +/**************************************************************************//** + @Description Structure for Deep Sleep Auto Response filtering Entry +*//***************************************************************************/ +typedef struct t_FmPortDsarFilteringEntry +{ + uint16_t srcPort; + uint16_t dstPort; + uint16_t srcPortMask; + uint16_t dstPortMask; +} t_FmPortDsarFilteringEntry; + +/**************************************************************************//** + @Description Structure for Deep Sleep Auto Response filtering info +*//***************************************************************************/ +typedef struct t_FmPortDsarFilteringInfo +{ + /* IP protocol filtering parameters */ + uint8_t ipProtTableSize; + uint8_t *p_IpProtTablePtr; + bool ipProtDropOnHit; /* when TRUE, hit in the table will cause the packet to be droped, + miss will pass the packet to UDP/TCP filters if needed and if not + to the classification tree. If the classification tree will pass + the packet to a queue it will cause a wake interupt. + When FALSE it the other way around. */ + /* UDP port filtering parameters */ + uint8_t udpPortsTableSize; + t_FmPortDsarFilteringEntry *p_UdpPortsTablePtr; + bool udpPortDropOnHit; /* when TRUE, hit in the table will cause the packet to be droped, + miss will pass the packet to classification tree. + If the classification tree will pass the packet to a queue it + will cause a wake interupt. + When FALSE it the other way around. */ + /* TCP port filtering parameters */ + uint16_t tcpFlagsMask; + uint8_t tcpPortsTableSize; + t_FmPortDsarFilteringEntry *p_TcpPortsTablePtr; + bool tcpPortDropOnHit; /* when TRUE, hit in the table will cause the packet to be droped, + miss will pass the packet to classification tree. + If the classification tree will pass the packet to a queue it + will cause a wake interupt. + When FALSE it the other way around. */ +} t_FmPortDsarFilteringInfo; + +/**************************************************************************//** + @Description Structure for Deep Sleep Auto Response parameters +*//***************************************************************************/ +typedef struct t_FmPortDsarParams +{ + t_Handle h_FmPortTx; + t_FmPortDsarArpInfo *p_AutoResArpInfo; + t_FmPortDsarEchoIpv4Info *p_AutoResEchoIpv4Info; + t_FmPortDsarNdpInfo *p_AutoResNdpInfo; + t_FmPortDsarEchoIpv6Info *p_AutoResEchoIpv6Info; + t_FmPortDsarSnmpInfo *p_AutoResSnmpInfo; + t_FmPortDsarFilteringInfo *p_AutoResFilteringInfo; +} t_FmPortDsarParams; + +/**************************************************************************//** + @Function FM_PORT_EnterDsar + + @Description Enter Deep Sleep Auto Response mode. + This function write the apropriate values to in the relevant + tables in the MURAM. It then set the Tx port in independent + mode as needed and redirect the receive flow to go through the + Dsar Fman-ctrl code + + Calling this routine invalidates the descriptor. + + @Param[in] h_FmPortRx - FM PORT module descriptor + @Param[in] params - Auto Response parameters + + @Return E_OK on success; Error code otherwise. + + @Cautions Allowed only following FM_PORT_Init(). +*//***************************************************************************/ +t_Error FM_PORT_EnterDsar(t_Handle h_FmPortRx, t_FmPortDsarParams *params); + +/**************************************************************************//** + @Function FM_PORT_ExitDsar + + @Description Exit Deep Sleep Auto Response mode. + This function reverse the AR mode and put the ports back into + their original wake mode + + @Param[in] h_FmPortRx - FM PORT Rx module descriptor + @Param[in] h_FmPortTx - FM PORT Tx module descriptor + + @Return E_OK on success; Error code otherwise. + + @Cautions Allowed only following FM_PORT_EnterDsar(). +*//***************************************************************************/ +void FM_PORT_ExitDsar(t_Handle h_FmPortRx, t_Handle h_FmPortTx); + +/**************************************************************************//** + @Function FM_PORT_IsInDsar + + @Description This function returns TRUE if the port was set as Auto Response + and FALSE if not. Once Exit AR mode it will return FALSE as well + until re-enabled once more. + + @Param[in] h_FmPort - FM PORT module descriptor + + @Return E_OK on success; Error code otherwise. +*//***************************************************************************/ +bool FM_PORT_IsInDsar(t_Handle h_FmPort); + +typedef struct t_FmPortDsarStats +{ + uint32_t arpArCnt; + uint32_t echoIcmpv4ArCnt; + uint32_t ndpArCnt; + uint32_t echoIcmpv6ArCnt; + uint32_t snmpGetCnt; + uint32_t snmpGetNextCnt; +} t_FmPortDsarStats; + +/**************************************************************************//** + @Function FM_PORT_GetDsarStats + + @Description Return statistics for Deep Sleep Auto Response + + @Param[in] h_FmPortRx - FM PORT module descriptor + @Param[out] stats - structure containing the statistics counters + + @Return E_OK on success; Error code otherwise. +*//***************************************************************************/ +t_Error FM_PORT_GetDsarStats(t_Handle h_FmPortRx, t_FmPortDsarStats *stats); #if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) /**************************************************************************//** diff --git a/drivers/net/ethernet/freescale/fman/inc/flib/fsl_fman_prs.h b/drivers/net/ethernet/freescale/fman/inc/flib/fsl_fman_prs.h index 30d2ecf..b18997d 100644 --- a/drivers/net/ethernet/freescale/fman/inc/flib/fsl_fman_prs.h +++ b/drivers/net/ethernet/freescale/fman/inc/flib/fsl_fman_prs.h @@ -96,6 +96,7 @@ void fman_prs_defconfig(struct fman_prs_cfg *cfg); int fman_prs_init(struct fman_prs_regs *regs, struct fman_prs_cfg *cfg); void fman_prs_enable(struct fman_prs_regs *regs); void fman_prs_disable(struct fman_prs_regs *regs); +int fman_prs_is_enabled(struct fman_prs_regs *regs); void fman_prs_set_stst_port_msk(struct fman_prs_regs *regs, uint32_t pid_msk); void fman_prs_set_stst(struct fman_prs_regs *regs, bool enable); #endif /* __FSL_FMAN_PRS_H */ diff --git a/drivers/net/ethernet/freescale/fman/src/inc/wrapper/lnxwrp_fsl_fman.h b/drivers/net/ethernet/freescale/fman/src/inc/wrapper/lnxwrp_fsl_fman.h index f4fabbe..3a66493 100644 --- a/drivers/net/ethernet/freescale/fman/src/inc/wrapper/lnxwrp_fsl_fman.h +++ b/drivers/net/ethernet/freescale/fman/src/inc/wrapper/lnxwrp_fsl_fman.h @@ -350,6 +350,204 @@ int fm_port_set_rate_limit(struct fm_port *port, *//***************************************************************************/ int fm_port_del_rate_limit(struct fm_port *port); +struct auto_res_tables_sizes +{ + uint16_t max_num_of_arp_entries; + uint16_t max_num_of_echo_ipv4_entries; + uint16_t max_num_of_ndp_entries; + uint16_t max_num_of_echo_ipv6_entries; + uint16_t max_num_of_snmp_ipv4_entries; + uint16_t max_num_of_snmp_ipv6_entries; + uint16_t max_num_of_snmp_oid_entries; + uint16_t max_num_of_snmp_char; /* total amount of character needed + for the snmp table */ + uint16_t max_num_of_ip_prot_filtering; + uint16_t max_num_of_tcp_port_filtering; + uint16_t max_num_of_udp_port_filtering; +}; +/* ARP */ +struct auto_res_arp_entry +{ + uint32_t ip_address; + uint8_t mac[6]; + bool is_vlan; + uint16_t vid; +}; +struct auto_res_arp_info +{ + uint8_t table_size; + struct auto_res_arp_entry *auto_res_table; + bool enable_conflict_detection; /* when TRUE + Conflict Detection will be checked and wake the host if + needed */ +}; + +/* NDP */ +struct auto_res_ndp_entry +{ + uint32_t ip_address[4]; + uint8_t mac[6]; + bool is_vlan; + uint16_t vid; +}; +struct auto_res_ndp_info +{ + uint32_t multicast_group; + uint8_t table_size_assigned; + struct auto_res_ndp_entry *auto_res_table_assigned; /* This list + refer to solicitation IP addresses. Note that all IP adresses + must be from the same multicast group. This will be checked and + if not operation will fail. */ + uint8_t table_size_tmp; + struct auto_res_ndp_entry *auto_res_table_tmp; /* This list + refer to temp IP addresses. Note that all temp IP adresses must + be from the same multicast group. This will be checked and if + not operation will fail. */ + + bool enable_conflict_detection; /* when TRUE + Conflict Detection will be checked and wake the host if + needed */ +}; + +/* ICMP ECHO */ +struct auto_res_echo_ipv4_info +{ + uint8_t table_size; + struct auto_res_arp_entry *auto_res_table; +}; + +struct auto_res_echo_ipv6_info +{ + uint8_t table_size; + struct auto_res_ndp_entry *auto_res_table; +}; + +/* SNMP */ +struct auto_res_snmp_entry +{ + uint16_t oidSize; + uint8_t *oidVal; /* only the oid string */ + uint16_t resSize; + uint8_t *resVal; /* resVal will be the entire reply, + i.e. "Type|Length|Value" */ +}; + +/**************************************************************************//** + @Description Deep Sleep Auto Response SNMP IPv4 Addresses Table Entry + Refer to the FMan Controller spec for more details. +*//***************************************************************************/ +struct auto_res_snmp_ipv4addr_tbl_entry +{ + uint32_t ipv4addr; /*!< 32 bit IPv4 Address. */ + bool is_vlan; + uint16_t vid; /*!< 12 bits VLAN ID. The 4 left-most bits should be cleared */ + /*!< This field should be 0x0000 for an entry with no VLAN tag or a null VLAN ID. */ +}; + +/**************************************************************************//** + @Description Deep Sleep Auto Response SNMP IPv6 Addresses Table Entry + Refer to the FMan Controller spec for more details. +*//***************************************************************************/ +struct auto_res_snmp_ipv6addr_tbl_entry +{ + uint32_t ipv6Addr[4]; /*!< 4 * 32 bit IPv6 Address. */ + bool isVlan; + uint16_t vid; /*!< 12 bits VLAN ID. The 4 left-most bits should be cleared */ + /*!< This field should be 0x0000 for an entry with no VLAN tag or a null VLAN ID. */ +}; + +struct auto_res_snmp_info +{ + uint16_t control; /**< Control bits [0-15]. */ + uint16_t max_snmp_msg_length; /**< Maximal allowed SNMP message length. */ + uint16_t num_ipv4_addresses; /**< Number of entries in IPv4 addresses table. */ + uint16_t num_ipv6_addresses; /**< Number of entries in IPv6 addresses table. */ + struct auto_res_snmp_ipv4addr_tbl_entry *ipv4addr_tbl; /**< Pointer to IPv4 addresses table. */ + struct auto_res_snmp_ipv6addr_tbl_entry *ipv6addr_tbl; /**< Pointer to IPv6 addresses table. */ + char *community_read_write_string; + char *community_read_only_string; + struct auto_res_snmp_entry *oid_table; + uint32_t oid_table_size; +}; + +/* Filtering */ +struct auto_res_port_filtering_entry +{ + uint16_t src_port; + uint16_t dst_port; + uint16_t src_port_mask; + uint16_t dst_port_mask; +}; +struct auto_res_filtering_info +{ + /* IP protocol filtering parameters */ + uint8_t ip_prot_table_size; + uint8_t *ip_prot_table_ptr; + bool ip_prot_drop_on_hit; /* when TRUE, hit in the table will + cause the packet to be droped, miss will pass the packet to + UDP/TCP filters if needed and if not to the classification + tree. If the classification tree will pass the packet to a + queue it will cause a wake interupt. When FALSE it the other + way around. */ + /* UDP port filtering parameters */ + uint8_t udp_ports_table_size; + struct auto_res_port_filtering_entry *udp_ports_table_ptr; + bool udp_port_drop_on_hit; /* when TRUE, hit in the table will + cause the packet to be droped, miss will pass the packet to + classification tree. If the classification tree will pass the + packet to a queue it will cause a wake interupt. When FALSE it + the other way around. */ + /* TCP port filtering parameters */ + uint16_t tcp_flags_mask; + uint8_t tcp_ports_table_size; + struct auto_res_port_filtering_entry *tcp_ports_table_ptr; + bool tcp_port_drop_on_hit; /* when TRUE, hit in the table will + cause the packet to be droped, miss will pass the packet to + classification tree. If the classification tree will pass the + packet to a queue it will cause a wake interupt. When FALSE it + the other way around. */ +}; + +struct auto_res_port_params +{ + t_Handle h_FmPortTx; + struct auto_res_arp_info *p_auto_res_arp_info; + struct auto_res_echo_ipv4_info *p_auto_res_echo_ipv4_info; + struct auto_res_ndp_info *p_auto_res_ndp_info; + struct auto_res_echo_ipv6_info *p_auto_res_echo_ipv6_info; + struct auto_res_snmp_info *p_auto_res_snmp_info; + struct auto_res_filtering_info *p_auto_res_filtering_info; +}; + +struct auto_res_port_stats +{ + uint32_t arp_ar_cnt; + uint32_t echo_icmpv4_ar_cnt; + uint32_t ndp_ar_cnt; + uint32_t echo_icmpv6_ar_cnt; +}; + +int fm_port_config_autores_for_deepsleep_support(struct fm_port *port, + struct auto_res_tables_sizes *params); + +int fm_port_enter_autores_for_deepsleep(struct fm_port *port, + struct auto_res_port_params *params); + +void fm_port_exit_auto_res_for_deep_sleep(struct fm_port *port_rx, + struct fm_port *port_tx); + +bool fm_port_is_in_auto_res_mode(struct fm_port *port); + +struct auto_res_tables_sizes *fm_port_get_autores_maxsize( + struct fm_port *port); + +int fm_port_get_autores_stats(struct fm_port *port, struct auto_res_port_stats + *stats); + +int fm_port_resume(struct fm_port *port); + +int fm_port_suspend(struct fm_port *port); + /**************************************************************************//** @Function fm_mac_set_exception diff --git a/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_fm.c b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_fm.c old mode 100644 new mode 100755 index d161209..4cd0142 --- a/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_fm.c +++ b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_fm.c @@ -62,6 +62,7 @@ #include #include /* For file access mask */ #include +#include /* NetCommSw Headers --------------- */ #include "std_ext.h" @@ -707,7 +708,7 @@ static t_Error CheckNConfigFmAdvArgs (t_LnxWrpFmDev *p_LnxWrpFmDev) { struct device_node *dev_node; t_Error err = E_INVALID_VALUE; - /*const uint32_t *uint32_prop;*/ + const uint32_t *uint32_prop; const char *str_prop; int lenp; @@ -723,6 +724,16 @@ static t_Error CheckNConfigFmAdvArgs (t_LnxWrpFmDev *p_LnxWrpFmDev) err = FM_ConfigDmaAidMode(p_LnxWrpFmDev->h_Dev, e_FM_DMA_AID_OUT_TNUM); } + uint32_prop = (uint32_t *)of_get_property(dev_node, "tnum-aging-period", + &lenp); + if (uint32_prop) { + if (WARN_ON(lenp != sizeof(uint32_t))) + RETURN_ERROR(MINOR, E_INVALID_VALUE, NO_MSG); + + err = FM_ConfigTnumAgingPeriod(p_LnxWrpFmDev->h_Dev, + (uint16_t)uint32_prop[0]/*tnumAgingPeriod*/); + } + if (err != E_OK) RETURN_ERROR(MINOR, err, NO_MSG); @@ -1327,6 +1338,78 @@ int fm_port_del_rate_limit(struct fm_port *port) } EXPORT_SYMBOL(fm_port_del_rate_limit); +void FM_PORT_Dsar_DumpRegs(void); +int ar_showmem(struct file *file, const char __user *buffer, + unsigned long count, void *data) +{ + FM_PORT_Dsar_DumpRegs(); + return 2; +} + +struct auto_res_tables_sizes *fm_port_get_autores_maxsize( + struct fm_port *port) +{ + t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev *)port; + return &p_LnxWrpFmPortDev->dsar_table_sizes; +} +EXPORT_SYMBOL(fm_port_get_autores_maxsize); + +int fm_port_enter_autores_for_deepsleep(struct fm_port *port, + struct auto_res_port_params *params) +{ + t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev *)port; + /*Register other under /proc/autoresponse */ + if (WARN_ON(sizeof(t_FmPortDsarParams) != sizeof(struct auto_res_port_params))) + return -EFAULT; + + FM_PORT_EnterDsar(p_LnxWrpFmPortDev->h_Dev, (t_FmPortDsarParams*)params); + return 0; +} +EXPORT_SYMBOL(fm_port_enter_autores_for_deepsleep); + +void fm_port_exit_auto_res_for_deep_sleep(struct fm_port *port_rx, + struct fm_port *port_tx) +{ + FM_PORT_ExitDsar(port_rx, port_tx); +} +EXPORT_SYMBOL(fm_port_exit_auto_res_for_deep_sleep); + +int fm_port_get_autores_stats(struct fm_port *port, + struct auto_res_port_stats *stats) +{ + t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev *)port; + if (WARN_ON(sizeof(t_FmPortDsarStats) != sizeof(struct auto_res_port_stats))) + return -EFAULT; + return FM_PORT_GetDsarStats(p_LnxWrpFmPortDev->h_Dev, (t_FmPortDsarStats*)stats); +} +EXPORT_SYMBOL(fm_port_get_autores_stats); + +int fm_port_suspend(struct fm_port *port) +{ + t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev *)port; + if (!FM_PORT_IsInDsar(p_LnxWrpFmPortDev->h_Dev)) + return FM_PORT_Disable(p_LnxWrpFmPortDev->h_Dev); + else + return 0; +} +EXPORT_SYMBOL(fm_port_suspend); + +int fm_port_resume(struct fm_port *port) +{ + t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev *)port; + if (!FM_PORT_IsInDsar(p_LnxWrpFmPortDev->h_Dev)) + return FM_PORT_Enable(p_LnxWrpFmPortDev->h_Dev); + else + return 0; +} +EXPORT_SYMBOL(fm_port_resume); + +bool fm_port_is_in_auto_res_mode(struct fm_port *port) +{ + return FM_PORT_IsInDsar(port); +} +EXPORT_SYMBOL(fm_port_is_in_auto_res_mode); + int fm_mac_set_exception(struct fm_mac_dev *fm_mac_dev, e_FmMacExceptions exception, bool enable) { diff --git a/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_fm.h b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_fm.h index 30b6bf2..9c657ac 100644 --- a/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_fm.h +++ b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_fm.h @@ -118,6 +118,9 @@ typedef struct { #if (DPAA_VERSION >= 11) struct device_attribute *dev_attr_ipv4_opt; #endif + struct device_attribute *dev_attr_dsar_regs; + struct device_attribute *dev_attr_dsar_mem; + struct auto_res_tables_sizes dsar_table_sizes; } t_LnxWrpFmPortDev; typedef struct { diff --git a/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_fm_port.c b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_fm_port.c index a8cd7bf..6e135a2 100644 --- a/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_fm_port.c +++ b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_fm_port.c @@ -54,6 +54,7 @@ #include "sprint_ext.h" #include "fm_common.h" +#include "lnxwrp_fsl_fman.h" #include "fm_port_ext.h" #if (DPAA_VERSION >= 11) #include "fm_vsp_ext.h" @@ -501,6 +502,7 @@ static t_Error CheckNConfigFmPortAdvArgs (t_LnxWrpFmPortDev *p_LnxWrpFmPortDev) /*const char *str_prop;*/ int lenp; + fm_node = GetFmAdvArgsDevTreeNode(((t_LnxWrpFmDev *) p_LnxWrpFmPortDev->h_LnxWrpFmDev)->id); if (!fm_node) /* no advance parameters for FMan */ return E_OK; @@ -554,12 +556,61 @@ static t_Error CheckNConfigFmPortAdvArgs (t_LnxWrpFmPortDev *p_LnxWrpFmPortDev) if (uint32_prop) { if (WARN_ON(lenp != sizeof(uint32_t))) RETURN_ERROR(MINOR, E_INVALID_VALUE, NO_MSG); - if ((err = FM_PORT_ConfigErrorsToDiscard(p_LnxWrpFmPortDev->h_Dev, uint32_prop[0])) != E_OK) RETURN_ERROR(MINOR, err, NO_MSG); } + uint32_prop = (uint32_t *)of_get_property(port_node, "ar-tables-sizes", + &lenp); + if (uint32_prop) { + + if (WARN_ON(lenp != sizeof(uint32_t)*8)) + RETURN_ERROR(MINOR, E_INVALID_VALUE, NO_MSG); + if (WARN_ON(p_LnxWrpFmPortDev->settings.param.portType != + e_FM_PORT_TYPE_RX) && + (p_LnxWrpFmPortDev->settings.param.portType != + e_FM_PORT_TYPE_RX_10G)) + RETURN_ERROR(MINOR, E_INVALID_VALUE, + ("Auto Response is an Rx port atribute.")); + + memset(&p_LnxWrpFmPortDev->dsar_table_sizes, 0, sizeof(struct auto_res_tables_sizes)); + + p_LnxWrpFmPortDev->dsar_table_sizes.max_num_of_arp_entries = + (uint16_t)uint32_prop[0]; + p_LnxWrpFmPortDev->dsar_table_sizes.max_num_of_echo_ipv4_entries = + (uint16_t)uint32_prop[1]; + p_LnxWrpFmPortDev->dsar_table_sizes.max_num_of_ndp_entries = + (uint16_t)uint32_prop[2]; + p_LnxWrpFmPortDev->dsar_table_sizes.max_num_of_echo_ipv6_entries = + (uint16_t)uint32_prop[3]; + p_LnxWrpFmPortDev->dsar_table_sizes.max_num_of_snmp_ipv4_entries = + (uint16_t)uint32_prop[4]; + p_LnxWrpFmPortDev->dsar_table_sizes.max_num_of_snmp_ipv6_entries = + (uint16_t)uint32_prop[5]; + p_LnxWrpFmPortDev->dsar_table_sizes.max_num_of_snmp_oid_entries = + (uint16_t)uint32_prop[6]; + p_LnxWrpFmPortDev->dsar_table_sizes.max_num_of_snmp_char = + (uint16_t)uint32_prop[7]; + uint32_prop = (uint32_t *)of_get_property(port_node, + "ar-filters-sizes", &lenp); + if (uint32_prop) { + if (WARN_ON(lenp != sizeof(uint32_t)*3)) + RETURN_ERROR(MINOR, E_INVALID_VALUE, NO_MSG); + + p_LnxWrpFmPortDev->dsar_table_sizes.max_num_of_ip_prot_filtering = + (uint16_t)uint32_prop[0]; + p_LnxWrpFmPortDev->dsar_table_sizes.max_num_of_tcp_port_filtering = + (uint16_t)uint32_prop[1]; + p_LnxWrpFmPortDev->dsar_table_sizes.max_num_of_udp_port_filtering = + (uint16_t)uint32_prop[2]; + } + + if ((err = FM_PORT_ConfigDsarSupport(p_LnxWrpFmPortDev->h_Dev, + (t_FmPortDsarTablesSizes*)&p_LnxWrpFmPortDev->dsar_table_sizes)) != E_OK) + RETURN_ERROR(MINOR, err, NO_MSG); + } + of_node_put(port_node); of_node_put(fm_node); @@ -800,6 +851,14 @@ static t_Error InitFmPortDev(t_LnxWrpFmPortDev *p_LnxWrpFmPortDev) #endif #endif + if ((p_LnxWrpFmPortDev->settings.param.portType != e_FM_PORT_TYPE_TX) && + (p_LnxWrpFmPortDev->settings.param.portType != e_FM_PORT_TYPE_TX_10G)) { + if (FM_PORT_ConfigErrorsToDiscard(p_LnxWrpFmPortDev->h_Dev, (FM_PORT_FRM_ERR_IPRE | + FM_PORT_FRM_ERR_IPR_NCSP | + FM_PORT_FRM_ERR_CLS_DISCARD)) !=E_OK) + RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG); + } + if (CheckNConfigFmPortAdvArgs(p_LnxWrpFmPortDev) != E_OK) RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG); diff --git a/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_sysfs_fm_port.c b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_sysfs_fm_port.c index 73db24b..ead8c7a 100644 --- a/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_sysfs_fm_port.c +++ b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_sysfs_fm_port.c @@ -37,6 +37,7 @@ #include "lnxwrp_sysfs_fm.h" #include "../../fman/Peripherals/FM/Port/fm_port.h" +#include "../../fman/Peripherals/FM/Port/fm_port_dsar.h" #if defined(__ERR_MODULE__) #undef __ERR_MODULE__ @@ -276,7 +277,400 @@ static ssize_t show_fm_port_regs(struct device *dev, return n; #endif } +static int fm_port_dsar_dump_mem(void *h_dev, char *buf, int nn) +{ + t_FmPort *p_FmPort; + t_Fm *p_Fm; + uint8_t hardwarePortId; + uint32_t *param_page; + t_ArCommonDesc *ArCommonDescPtr; + uint32_t *mem; + int i, n = nn; + + p_FmPort = (t_FmPort *)h_dev; + hardwarePortId = p_FmPort->hardwarePortId; + p_Fm = (t_Fm *)p_FmPort->h_Fm; + + if (!FM_PORT_IsInDsar(p_FmPort)) + { + FM_DMP_LN(buf, n, "port %u is not a DSAR port\n", + hardwarePortId); + return n; + } + FM_DMP_LN(buf, n, "port %u DSAR mem\n", hardwarePortId); + FM_DMP_LN(buf, n, "========================\n"); + + /* do I need request_mem_region here? */ + param_page = ioremap(p_FmPort->fmMuramPhysBaseAddr + ioread32be(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rgpr), 4); + ArCommonDescPtr = (t_ArCommonDesc*)(ioremap(p_FmPort->fmMuramPhysBaseAddr + ioread32be(param_page), sizeof(t_ArCommonDesc))); /* this should be changed*/ + mem = (uint32_t*)ArCommonDescPtr; + for (i = 0; i < 100; i+=4) + FM_DMP_LN(buf, n, "%08x %08x %08x %08x\n", mem[i], mem[i + 1], mem[i + 2], mem[i + 3]); + iounmap(ArCommonDescPtr); + iounmap(param_page); + return n; +} + +static int fm_port_dsar_dump_regs(void *h_dev, char *buf, int nn) +{ + t_FmPort *p_FmPort; + t_Fm *p_Fm; + uint8_t hardwarePortId; + uint32_t *param_page; + t_ArCommonDesc *ArCommonDescPtr; + int i, n = nn; + p_FmPort = (t_FmPort *)h_dev; + hardwarePortId = p_FmPort->hardwarePortId; + p_Fm = (t_Fm *)p_FmPort->h_Fm; + + if (!FM_PORT_IsInDsar(p_FmPort)) + { + FM_DMP_LN(buf, n, "port %u is not a DSAR port\n", + hardwarePortId); + return n; + } + FM_DMP_LN(buf, n, "port %u DSAR information\n", hardwarePortId); + FM_DMP_LN(buf, n, "========================\n"); + + /* do I need request_mem_region here? */ + param_page = ioremap(p_FmPort->fmMuramPhysBaseAddr + ioread32be(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rgpr), 4); + ArCommonDescPtr = (t_ArCommonDesc*)(ioremap(p_FmPort->fmMuramPhysBaseAddr + ioread32be(param_page), sizeof(t_ArCommonDesc))); /* this should be changed*/ + FM_DMP_LN(buf, n, "Tx port: 0x%x\n", ArCommonDescPtr->arTxPort); + FM_DMP_LN(buf, n, "Active HPNIA: 0x%08x\n", ArCommonDescPtr->activeHPNIA); + FM_DMP_LN(buf, n, "Snmp port: 0x%x\n", ArCommonDescPtr->snmpPort); + FM_DMP_LN(buf, n, "MAC address: %02x:%02x:%02x:%02x:%02x:%02x\n", ArCommonDescPtr->macStationAddr[0], + ArCommonDescPtr->macStationAddr[1], ArCommonDescPtr->macStationAddr[2], + ArCommonDescPtr->macStationAddr[3], ArCommonDescPtr->macStationAddr[4], + ArCommonDescPtr->macStationAddr[5]); + FM_DMP_LN(buf, n, "filterControl: 0x%02x\n", ArCommonDescPtr->filterControl); + FM_DMP_LN(buf, n, "tcpControlPass: 0x%04x\n", ArCommonDescPtr->tcpControlPass); + FM_DMP_LN(buf, n, "ipProtocolTblSize: 0x%x\n", ArCommonDescPtr->ipProtocolTblSize); + FM_DMP_LN(buf, n, "udpPortTblSize: 0x%x\n", ArCommonDescPtr->udpPortTblSize); + FM_DMP_LN(buf, n, "tcpPortTblSize: 0x%x\n", ArCommonDescPtr->tcpPortTblSize); + if (ArCommonDescPtr->p_ArStats) + { + t_ArStatistics *arStatistics = (t_ArStatistics*) + ioremap(ioread32be(&ArCommonDescPtr->p_ArStats) + + p_FmPort->fmMuramPhysBaseAddr, + sizeof (t_ArStatistics)); + FM_DMP_LN(buf, n, "\nDSAR statistics\n"); + FM_DMP_LN(buf, n, "DSAR_Discarded: 0x%x\n", arStatistics->dsarDiscarded); + FM_DMP_LN(buf, n, "DSAR_Err_Discarded: 0x%x\n", arStatistics->dsarErrDiscarded); + FM_DMP_LN(buf, n, "DSAR_Frag_Discarded: 0x%x\n", arStatistics->dsarFragDiscarded); + FM_DMP_LN(buf, n, "DSAR_Tunnel_Discarded: 0x%x\n", arStatistics->dsarTunnelDiscarded); + FM_DMP_LN(buf, n, "DSAR_ARP_Discarded: 0x%x\n", arStatistics->dsarArpDiscarded); + FM_DMP_LN(buf, n, "DSAR_IP_Discarded: 0x%x\n", arStatistics->dsarIpDiscarded); + FM_DMP_LN(buf, n, "DSAR_TCP_Discarded: 0x%x\n", arStatistics->dsarTcpDiscarded); + FM_DMP_LN(buf, n, "DSAR_UDP_Discarded: 0x%x\n", arStatistics->dsarUdpDiscarded); + FM_DMP_LN(buf, n, "DSAR_ICMPv6_Checksum_Err: 0x%x\n", arStatistics->dsarIcmpV6ChecksumErr); + FM_DMP_LN(buf, n, "DSAR_ICMPv6_Other_Type: 0x%x\n", arStatistics->dsarIcmpV6OtherType); + FM_DMP_LN(buf, n, "DSAR_ICMPv4_Other_Type: 0x%x\n", arStatistics->dsarIcmpV4OtherType); + + iounmap(arStatistics); + } + if (ArCommonDescPtr->p_ArpDescriptor) + { + t_DsarArpDescriptor* ArpDescriptor = (t_DsarArpDescriptor*) + ioremap(ioread32be(&ArCommonDescPtr->p_ArpDescriptor) + + p_FmPort->fmMuramPhysBaseAddr, + sizeof (t_DsarArpDescriptor)); + FM_DMP_LN(buf, n, "\nARP\n"); + FM_DMP_LN(buf, n, "===\n"); + FM_DMP_LN(buf, n, "control bits 0x%04x\n", ArpDescriptor->control); + if (ArpDescriptor->numOfBindings) + { + char ip_str[20]; + t_DsarArpBindingEntry* bindings = ioremap( + ioread32be(&ArpDescriptor->p_Bindings) + + p_FmPort->fmMuramPhysBaseAddr, + ArpDescriptor->numOfBindings * + sizeof(t_DsarArpBindingEntry)); + uint8_t* ip_addr = (uint8_t*)&bindings->ipv4Addr; + FM_DMP_LN(buf, n, " ip vlan id\n"); + for (i = 0; i < ArpDescriptor->numOfBindings; i++) + { + n += sprintf(ip_str, "%d:%d:%d:%d", ip_addr[0], ip_addr[1], ip_addr[2], ip_addr[3]); + FM_DMP_LN(buf, n, "%-15s 0x%x\n", ip_str, bindings->vlanId); + } + iounmap(bindings); + } + if (ArpDescriptor->p_Statistics) + { + t_DsarArpStatistics* arpStats = ioremap( + ioread32be(&ArpDescriptor->p_Statistics) + + p_FmPort->fmMuramPhysBaseAddr, + sizeof(t_DsarArpStatistics)); + FM_DMP_LN(buf, n, "statistics\n"); + FM_DMP_LN(buf, n, "INVAL_CNT: 0x%x\n", arpStats->invalCnt); + FM_DMP_LN(buf, n, "ECHO_CNT: 0x%x\n", arpStats->echoCnt); + FM_DMP_LN(buf, n, "CD_CNT: 0x%x\n", arpStats->cdCnt); + FM_DMP_LN(buf, n, "AR_CNT: 0x%x\n", arpStats->arCnt); + FM_DMP_LN(buf, n, "RATM_CNT: 0x%x\n", arpStats->ratmCnt); + FM_DMP_LN(buf, n, "UKOP_CNT: 0x%x\n", arpStats->ukopCnt); + FM_DMP_LN(buf, n, "NMTP_CNT: 0x%x\n", arpStats->nmtpCnt); + FM_DMP_LN(buf, n, "NMVLAN_CNT: 0x%x\n", arpStats->nmVlanCnt); + iounmap(arpStats); + } + + iounmap(ArpDescriptor); + } + if (ArCommonDescPtr->p_IcmpV4Descriptor) + { + t_DsarIcmpV4Descriptor* ICMPV4Descriptor = + (t_DsarIcmpV4Descriptor*)ioremap(ioread32be( + &ArCommonDescPtr->p_IcmpV4Descriptor) + + p_FmPort->fmMuramPhysBaseAddr, + sizeof (t_DsarIcmpV4Descriptor)); + FM_DMP_LN(buf, n, "\nEcho ICMPv4\n"); + FM_DMP_LN(buf, n, "===========\n"); + FM_DMP_LN(buf, n, "control bits 0x%04x\n", ICMPV4Descriptor->control); + if (ICMPV4Descriptor->numOfBindings) + { + char ip_str[20]; + t_DsarArpBindingEntry* bindings = ioremap( + ioread32be(&ICMPV4Descriptor->p_Bindings) + + p_FmPort->fmMuramPhysBaseAddr, + ICMPV4Descriptor->numOfBindings * + sizeof(t_DsarArpBindingEntry)); + uint8_t* ip_addr = (uint8_t*)&bindings->ipv4Addr; + FM_DMP_LN(buf, n, " ip vlan id\n"); + for (i = 0; i < ICMPV4Descriptor->numOfBindings; i++) + { + n += sprintf(ip_str, "%d:%d:%d:%d", ip_addr[0], ip_addr[1], ip_addr[2], ip_addr[3]); + FM_DMP_LN(buf, n, "%-15s 0x%x\n", ip_str, bindings->vlanId); + } + iounmap(bindings); + } + if (ICMPV4Descriptor->p_Statistics) + { + t_DsarIcmpV4Statistics* icmpv4Stats = ioremap( + ioread32be(&ICMPV4Descriptor->p_Statistics) + + p_FmPort->fmMuramPhysBaseAddr, + sizeof(t_DsarIcmpV4Statistics)); + FM_DMP_LN(buf, n, "statistics\n"); + FM_DMP_LN(buf, n, "INVAL_CNT: 0x%x\n", icmpv4Stats->invalCnt); + FM_DMP_LN(buf, n, "NMVLAN_CNT: 0x%x\n", icmpv4Stats->nmVlanCnt); + FM_DMP_LN(buf, n, "NMIP_CNT: 0x%x\n", icmpv4Stats->nmIpCnt); + FM_DMP_LN(buf, n, "AR_CNT: 0x%x\n", icmpv4Stats->arCnt); + FM_DMP_LN(buf, n, "CSERR_CNT: 0x%x\n", icmpv4Stats->cserrCnt); + iounmap(icmpv4Stats); + } + iounmap(ICMPV4Descriptor); + } + if (ArCommonDescPtr->p_NdDescriptor) + { + t_DsarNdDescriptor *NDDescriptor = + (t_DsarNdDescriptor*)ioremap(ioread32be( + &ArCommonDescPtr->p_NdDescriptor) + p_FmPort-> + fmMuramPhysBaseAddr, sizeof (t_DsarNdDescriptor)); + FM_DMP_LN(buf, n, "\nNDP\n"); + FM_DMP_LN(buf, n, "===\n"); + FM_DMP_LN(buf, n, "control bits 0x%04x\n", NDDescriptor->control); + FM_DMP_LN(buf, n, "solicited address 0x%08x\n", NDDescriptor->solicitedAddr); + if (NDDescriptor->numOfBindings) + { + char ip_str[20]; + t_DsarIcmpV6BindingEntry* bindings = ioremap( + ioread32be(&NDDescriptor->p_Bindings) + + p_FmPort->fmMuramPhysBaseAddr, + NDDescriptor->numOfBindings * + sizeof(t_DsarIcmpV6BindingEntry)); + uint16_t* ip_addr = (uint16_t*)&bindings->ipv6Addr; + FM_DMP_LN(buf, n, " ip vlan id\n"); + for (i = 0; i < NDDescriptor->numOfBindings; i++) + { + n += sprintf(ip_str, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", + ip_addr[0], ip_addr[1], ip_addr[2], ip_addr[3], + ip_addr[4], ip_addr[5], ip_addr[6], ip_addr[7]); + FM_DMP_LN(buf, n, "%s 0x%x\n", ip_str, bindings->vlanId); + } + iounmap(bindings); + } + if (NDDescriptor->p_Statistics) + { + t_NdStatistics* ndStats = ioremap( + ioread32be(&NDDescriptor->p_Statistics) + + p_FmPort->fmMuramPhysBaseAddr, + sizeof(t_NdStatistics)); + FM_DMP_LN(buf, n, "statistics\n"); + FM_DMP_LN(buf, n, "INVAL_CNT: 0x%x\n", ndStats->invalCnt); + FM_DMP_LN(buf, n, "NMVLAN_CNT: 0x%x\n", ndStats->nmVlanCnt); + FM_DMP_LN(buf, n, "NMIP_CNT: 0x%x\n", ndStats->nmIpCnt); + FM_DMP_LN(buf, n, "AR_CNT: 0x%x\n", ndStats->arCnt); + FM_DMP_LN(buf, n, "USADVERT_CNT: 0x%x\n", ndStats->usadvertCnt); + FM_DMP_LN(buf, n, "NMMCAST_CNT: 0x%x\n", ndStats->nmmcastCnt); + FM_DMP_LN(buf, n, "NSLLA_CNT: 0x%x\n", ndStats->nsllaCnt); + iounmap(ndStats); + } + iounmap(NDDescriptor); + } + if (ArCommonDescPtr->p_IcmpV6Descriptor) + { + t_DsarIcmpV6Descriptor *ICMPV6Descriptor = + (t_DsarIcmpV6Descriptor*)ioremap(ioread32be( + &ArCommonDescPtr->p_IcmpV6Descriptor) + p_FmPort-> + fmMuramPhysBaseAddr, sizeof (t_DsarIcmpV6Descriptor)); + FM_DMP_LN(buf, n, "\nEcho ICMPv6\n"); + FM_DMP_LN(buf, n, "===========\n"); + FM_DMP_LN(buf, n, "control bits 0x%04x\n", ICMPV6Descriptor->control); + if (ICMPV6Descriptor->numOfBindings) + { + char ip_str[20]; + t_DsarIcmpV6BindingEntry* bindings = ioremap( + ioread32be(&ICMPV6Descriptor->p_Bindings) + + p_FmPort->fmMuramPhysBaseAddr, + ICMPV6Descriptor->numOfBindings * + sizeof(t_DsarIcmpV6BindingEntry)); + uint16_t* ip_addr = (uint16_t*)&bindings->ipv6Addr; + FM_DMP_LN(buf, n, " ip vlan id\n"); + for (i = 0; i < ICMPV6Descriptor->numOfBindings; i++) + { + n += sprintf(ip_str, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", + ip_addr[0], ip_addr[1], ip_addr[2], ip_addr[3], + ip_addr[4], ip_addr[5], ip_addr[6], ip_addr[7]); + FM_DMP_LN(buf, n, "%s 0x%x\n", ip_str, bindings->vlanId); + } + iounmap(bindings); + } + if (ICMPV6Descriptor->p_Statistics) + { + t_DsarIcmpV6Statistics* icmpv6Stats = ioremap( + ioread32be(&ICMPV6Descriptor->p_Statistics) + + p_FmPort->fmMuramPhysBaseAddr, + sizeof(t_DsarIcmpV6Statistics)); + FM_DMP_LN(buf, n, "statistics\n"); + FM_DMP_LN(buf, n, "INVAL_CNT: 0x%x\n", icmpv6Stats->invalCnt); + FM_DMP_LN(buf, n, "NMVLAN_CNT: 0x%x\n", icmpv6Stats->nmVlanCnt); + FM_DMP_LN(buf, n, "NMIP_CNT: 0x%x\n", icmpv6Stats->nmIpCnt); + FM_DMP_LN(buf, n, "AR_CNT: 0x%x\n", icmpv6Stats->arCnt); + iounmap(icmpv6Stats); + } + iounmap(ICMPV6Descriptor); + } + if (ArCommonDescPtr->p_SnmpDescriptor) + { + t_DsarSnmpDescriptor *SnmpDescriptor = + (t_DsarSnmpDescriptor*)ioremap(ioread32be( + &ArCommonDescPtr->p_SnmpDescriptor) + p_FmPort-> + fmMuramPhysBaseAddr, sizeof (t_DsarSnmpDescriptor)); + FM_DMP_LN(buf, n, "\nSNMP\n"); + FM_DMP_LN(buf, n, "===========\n"); + FM_DMP_LN(buf, n, "control bits 0x%04x\n", SnmpDescriptor->control); + FM_DMP_LN(buf, n, "max message length 0x%04x\n", SnmpDescriptor->maxSnmpMsgLength); + if (SnmpDescriptor->numOfIpv4Addresses) + { + char ip_str[20]; + t_DsarSnmpIpv4AddrTblEntry* addrs = ioremap( + ioread32be(&SnmpDescriptor->p_Ipv4AddrTbl) + + p_FmPort->fmMuramPhysBaseAddr, + SnmpDescriptor->numOfIpv4Addresses * + sizeof(t_DsarSnmpIpv4AddrTblEntry)); + uint8_t* ip_addr = (uint8_t*)&addrs->ipv4Addr; + FM_DMP_LN(buf, n, " ip vlan id\n"); + for (i = 0; i < SnmpDescriptor->numOfIpv4Addresses; i++) + { + n += sprintf(ip_str, "%d:%d:%d:%d", ip_addr[0], ip_addr[1], ip_addr[2], ip_addr[3]); + FM_DMP_LN(buf, n, "%-15s 0x%x\n", ip_str, addrs->vlanId); + } + iounmap(addrs); + } + if (SnmpDescriptor->p_Statistics) + { + t_DsarSnmpStatistics* snmpStats = ioremap( + ioread32be(&SnmpDescriptor->p_Statistics) + + p_FmPort->fmMuramPhysBaseAddr, + sizeof(t_DsarSnmpStatistics)); + FM_DMP_LN(buf, n, "statistics\n"); + FM_DMP_LN(buf, n, "snmpErrCnt: 0x%x\n", snmpStats->snmpErrCnt); + FM_DMP_LN(buf, n, "snmpCommunityErrCnt: 0x%x\n", snmpStats->snmpCommunityErrCnt); + FM_DMP_LN(buf, n, "snmpTotalDiscardCnt: 0x%x\n", snmpStats->snmpTotalDiscardCnt); + FM_DMP_LN(buf, n, "snmpGetReqCnt: 0x%x\n", snmpStats->snmpGetReqCnt); + FM_DMP_LN(buf, n, "snmpGetNextReqCnt: 0x%x\n", snmpStats->snmpGetNextReqCnt); + iounmap(snmpStats); + } + iounmap(SnmpDescriptor); + } + iounmap(ArCommonDescPtr); + iounmap(param_page); + return n; +} + +static ssize_t show_fm_port_dsar_mem(struct device *dev, + struct device_attribute *attr, char *buf) +{ + unsigned long flags; + unsigned n = 0; +#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) + t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = + (t_LnxWrpFmPortDev *) dev_get_drvdata(dev); +#endif + if (attr == NULL || buf == NULL || dev == NULL) + return -EINVAL; + +#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) + local_irq_save(flags); + + if (!p_LnxWrpFmPortDev->h_Dev) { + n = snprintf(buf, PAGE_SIZE, "\tFM Port not configured...\n"); + return n; + } else { + n = snprintf(buf, PAGE_SIZE, + "FM port driver registers dump.\n"); + n = fm_port_dsar_dump_mem(p_LnxWrpFmPortDev->h_Dev, buf, n); + } + + local_irq_restore(flags); + + return n; +#else + + local_irq_save(flags); + n = snprintf(buf, PAGE_SIZE, + "Debug level is too low to dump registers!!!\n"); + local_irq_restore(flags); + + return n; +#endif +} + +static ssize_t show_fm_port_dsar_regs(struct device *dev, + struct device_attribute *attr, char *buf) +{ + unsigned long flags; + unsigned n = 0; +#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) + t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = + (t_LnxWrpFmPortDev *) dev_get_drvdata(dev); +#endif + if (attr == NULL || buf == NULL || dev == NULL) + return -EINVAL; + +#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) + local_irq_save(flags); + + if (!p_LnxWrpFmPortDev->h_Dev) { + n = snprintf(buf, PAGE_SIZE, "\tFM Port not configured...\n"); + return n; + } else { + n = snprintf(buf, PAGE_SIZE, + "FM port driver registers dump.\n"); + n = fm_port_dsar_dump_regs(p_LnxWrpFmPortDev->h_Dev, buf, n); + } + + local_irq_restore(flags); + + return n; +#else + + local_irq_save(flags); + n = snprintf(buf, PAGE_SIZE, + "Debug level is too low to dump registers!!!\n"); + local_irq_restore(flags); + + return n; +#endif +} #if (DPAA_VERSION >= 11) static ssize_t show_fm_port_ipv4_options(struct device *dev, @@ -404,6 +798,8 @@ static DEVICE_ATTR(fm_port_bmi_regs, 0x644, show_fm_port_bmi_regs, NULL); #if (DPAA_VERSION >= 11) static DEVICE_ATTR(fm_port_ipv4_opt, 0x644, show_fm_port_ipv4_options, NULL); #endif +static DEVICE_ATTR(fm_port_dsar_regs, 0x644, show_fm_port_dsar_regs, NULL); +static DEVICE_ATTR(fm_port_dsar_mem, 0x644, show_fm_port_dsar_mem, NULL); int fm_port_sysfs_create(struct device *dev) { @@ -423,6 +819,8 @@ int fm_port_sysfs_create(struct device *dev) #if (DPAA_VERSION >= 11) p_LnxWrpFmPortDev->dev_attr_ipv4_opt = &dev_attr_fm_port_ipv4_opt; #endif + p_LnxWrpFmPortDev->dev_attr_dsar_regs = &dev_attr_fm_port_dsar_regs; + p_LnxWrpFmPortDev->dev_attr_dsar_mem = &dev_attr_fm_port_dsar_mem; /* Registers dump entry - in future will be moved to debugfs */ if (device_create_file(dev, &dev_attr_fm_port_regs) != 0) return -EIO; @@ -434,6 +832,10 @@ int fm_port_sysfs_create(struct device *dev) if (device_create_file(dev, &dev_attr_fm_port_ipv4_opt) != 0) return -EIO; #endif + if (device_create_file(dev, &dev_attr_fm_port_dsar_regs) != 0) + return -EIO; + if (device_create_file(dev, &dev_attr_fm_port_dsar_mem) != 0) + return -EIO; /* FM Ports statistics */ switch (p_LnxWrpFmPortDev->settings.param.portType) { @@ -504,6 +906,8 @@ void fm_port_sysfs_destroy(struct device *dev) #if (DPAA_VERSION >= 11) device_remove_file(dev, p_LnxWrpFmPortDev->dev_attr_ipv4_opt); #endif + device_remove_file(dev, p_LnxWrpFmPortDev->dev_attr_dsar_regs); + device_remove_file(dev, p_LnxWrpFmPortDev->dev_attr_dsar_mem); } -- cgit v0.10.2