static ssize_t tcam_show(struct device *dev, struct device_attribute *attr, char *buf) { const char* name = attr->attr.name; unsigned int v, m; if (!capable(CAP_NET_ADMIN)) return -EPERM; if (!strcmp(name, "t_port")) { tcam_sw_get_port(&te, &v, &m); return mvOsSPrintf(buf, "value:0x%x mask:0x%x\n", v, m); } else if (!strcmp(name, "t_lookup")) { tcam_sw_get_lookup(&te, &v, &m); return mvOsSPrintf(buf, "value:0x%x mask:0x%x\n", v, m); } else if (!strcmp(name, "sw_dump")) return tcam_sw_dump(&te, buf); else if (!strcmp(name, "hw_dump")) return tcam_hw_dump(0); else if (!strcmp(name, "hw_dump_all")) return tcam_hw_dump(1); else if (!strcmp(name, "hw_regs")) mvNetaPncRegs(); else if (!strcmp(name, "hw_hits")) return tcam_hw_hits(buf); #ifdef CONFIG_MV_ETH_PNC_AGING else if (!strcmp(name, "age_dump")) mvPncAgingDump(0); else if (!strcmp(name, "age_dump_all")) mvPncAgingDump(1); else if (!strcmp(name, "age_scan")) mvPncAgingScannerDump(); else if (!strcmp(name, "age_reset")) mvPncAgingReset(); #endif /* CONFIG_MV_ETH_PNC_AGING */ else if (!strcmp(name, "help")) return tcam_help(buf); return 0; }
/* * pnc_mcast_all - Accept all MAC multicast of port * @port: ingress giga port number. * @en: 1 - Accept ALL MCAST, 0 - Discard ALL MCAST */ int pnc_mcast_all(unsigned int port, int en) { struct tcam_entry *te; unsigned int data, mask; te = pnc_tcam_entry_get(TE_MAC_MC_ALL); if (te == NULL) { mvOsPrintf("%s: MC_ALL entry (tid=%d) is invalid\n", __func__, TE_MAC_MC_ALL); return 1; } /* Update port mask */ tcam_sw_get_port(te, &data, &mask); mask = pnc_port_mask_update(mask, port, en); tcam_sw_set_port(te, data, mask); tcam_sw_text(te, "mcast_all"); tcam_hw_write(te, TE_MAC_MC_ALL); tcam_sw_free(te); return 0; }
/* * pnc_mcast_me - Add DA MAC address of port * @mac: Multicast MAC DA or NULL to delete all Multicast DAs for this port * @port: ingress giga port number */ int pnc_mcast_me(unsigned int port, unsigned char *mac) { struct tcam_entry *te; int tid, empty = -1; unsigned int data, mask; if (mac == NULL) { /* Delete all Multicast addresses for this port */ for (tid = (TE_MAC_MC_ALL + 1); tid <= TE_MAC_MC_L; tid++) { /* Check TCAM entry */ te = pnc_tcam_entry_get(tid); if (te != NULL) { /* delete entry if belong specific port */ tcam_sw_get_port(te, &data, &mask); mask = pnc_port_mask_update(mask, port, 0); if (mask == PORT_MASK) { /* No valid ports */ tcam_hw_inv(tid); } else { tcam_sw_set_port(te, data, mask); tcam_hw_write(te, tid); } tcam_sw_free(te); } } return 0; } /* Add new Multicast DA for this port */ for (tid = (TE_MAC_MC_ALL + 1); tid <= TE_MAC_MC_L; tid++) { te = pnc_tcam_entry_get(tid); /* Remember first Empty entry */ if (te == NULL) { if (empty == -1) empty = tid; continue; } /* Find existing TCAM entry with this DA */ if (tcam_sw_cmp_bytes(te, MV_ETH_MH_SIZE, MV_MAC_ADDR_SIZE, mac) == 0) { /* check and update port mask */ tcam_sw_get_port(te, &data, &mask); mask = pnc_port_mask_update(mask, port, 1); tcam_sw_set_port(te, data, mask); tcam_hw_write(te, tid); tcam_sw_free(te); return 0; } tcam_sw_free(te); } /* Not found existing entry and no free TCAM entry - Failed */ if (empty == -1) return 1; /* Not found existing entry - add to free TCAM entry */ te = pnc_mac_da(mac, MV_MAC_ADDR_SIZE, pnc_port_mask(port), rxq_mac_mc, RI_DA_MC); tcam_sw_text(te, "mcast_me"); tcam_hw_write(te, empty); tcam_sw_free(te); return 0; }