int t3_mac_set_rx_mode(struct cmac *mac, struct t3_rx_mode *rm) { u32 val, hash_lo, hash_hi; struct adapter *adap = mac->adapter; unsigned int oft = mac->offset; val = t3_read_reg(adap, A_XGM_RX_CFG + oft) & ~F_COPYALLFRAMES; if (rm->dev->flags & IFF_PROMISC) val |= F_COPYALLFRAMES; t3_write_reg(adap, A_XGM_RX_CFG + oft, val); if (rm->dev->flags & IFF_ALLMULTI) hash_lo = hash_hi = 0xffffffff; else { u8 *addr; int exact_addr_idx = mac->nucast; hash_lo = hash_hi = 0; while ((addr = t3_get_next_mcaddr(rm))) if (exact_addr_idx < EXACT_ADDR_FILTERS) set_addr_filter(mac, exact_addr_idx++, addr); else { int hash = hash_hw_addr(addr); if (hash < 32) hash_lo |= (1 << hash); else hash_hi |= (1 << (hash - 32)); } } t3_write_reg(adap, A_XGM_RX_HASH_LOW + oft, hash_lo); t3_write_reg(adap, A_XGM_RX_HASH_HIGH + oft, hash_hi); return 0; }
/** * t3_mac_set_rx_mode - set the Rx mode and address filters * @mac: the MAC to configure * @rm: structure containing the Rx mode and MAC addresses needed * * Configures the MAC Rx mode (promiscuity, etc) and exact and hash * address filters. */ int t3_mac_set_rx_mode(struct cmac *mac, struct t3_rx_mode *rm) { u32 hash_lo, hash_hi; adapter_t *adap = mac->adapter; unsigned int oft = mac->offset; if (promisc_rx_mode(rm)) mac->promisc_map |= 1 << mac->ext_port; else mac->promisc_map &= ~(1 << mac->ext_port); t3_set_reg_field(adap, A_XGM_RX_CFG + oft, F_COPYALLFRAMES, mac->promisc_map ? F_COPYALLFRAMES : 0); if (allmulti_rx_mode(rm) || mac->multiport) hash_lo = hash_hi = 0xffffffff; else { u8 *addr; int exact_addr_idx = mac->nucast; hash_lo = hash_hi = 0; while ((addr = t3_get_next_mcaddr(rm))) if (exact_addr_idx < EXACT_ADDR_FILTERS) set_addr_filter(mac, exact_addr_idx++, addr); else { int hash = hash_hw_addr(addr); if (hash < 32) hash_lo |= (1 << hash); else hash_hi |= (1 << (hash - 32)); } } t3_write_reg(adap, A_XGM_RX_HASH_LOW + oft, hash_lo); t3_write_reg(adap, A_XGM_RX_HASH_HIGH + oft, hash_hi); return 0; }