X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Faxgbe%2Faxgbe_dev.c;h=786288a7b0798d11e8a2224a3caf682a8f2f5c4c;hb=fdab8f2e17493192d555cd88cf28b06269174326;hp=5f0f1959234e3786c8c06bb3b19e1addd7eb7ef6;hpb=e01d9b2e980b3bc2c967b323a428432fad706e9a;p=dpdk.git diff --git a/drivers/net/axgbe/axgbe_dev.c b/drivers/net/axgbe/axgbe_dev.c index 5f0f195923..786288a7b0 100644 --- a/drivers/net/axgbe/axgbe_dev.c +++ b/drivers/net/axgbe/axgbe_dev.c @@ -8,6 +8,46 @@ #include "axgbe_phy.h" #include "axgbe_rxtx.h" +static uint32_t bitrev32(uint32_t x) +{ + x = (x >> 16) | (x << 16); + x = (((x & 0xff00ff00) >> 8) | ((x & 0x00ff00ff) << 8)); + x = (((x & 0xf0f0f0f0) >> 4) | ((x & 0x0f0f0f0f) << 4)); + x = (((x & 0xcccccccc) >> 2) | ((x & 0x33333333) << 2)); + x = (((x & 0xaaaaaaaa) >> 1) | ((x & 0x55555555) << 1)); + return x; +} + +/*MSB set bit from 32 to 1*/ +static int get_lastbit_set(int x) +{ + int r = 32; + + if (!x) + return 0; + if (!(x & 0xffff0000)) { + x <<= 16; + r -= 16; + } + if (!(x & 0xff000000)) { + x <<= 8; + r -= 8; + } + if (!(x & 0xf0000000)) { + x <<= 4; + r -= 4; + } + if (!(x & 0xc0000000)) { + x <<= 2; + r -= 2; + } + if (!(x & 0x80000000)) { + x <<= 1; + r -= 1; + } + return r; +} + static inline unsigned int axgbe_get_max_frame(struct axgbe_port *pdata) { return pdata->eth_dev->data->mtu + RTE_ETHER_HDR_LEN + @@ -407,6 +447,120 @@ static void axgbe_config_flow_control_threshold(struct axgbe_port *pdata) } } +static int axgbe_enable_rx_vlan_stripping(struct axgbe_port *pdata) +{ + /* Put the VLAN tag in the Rx descriptor */ + AXGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, EVLRXS, 1); + + /* Don't check the VLAN type */ + AXGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, DOVLTC, 1); + + /* Check only C-TAG (0x8100) packets */ + AXGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, ERSVLM, 0); + + /* Don't consider an S-TAG (0x88A8) packet as a VLAN packet */ + AXGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, ESVL, 0); + + /* Enable VLAN tag stripping */ + AXGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, EVLS, 0x3); + return 0; +} + +static int axgbe_disable_rx_vlan_stripping(struct axgbe_port *pdata) +{ + AXGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, EVLS, 0); + return 0; +} + +static int axgbe_enable_rx_vlan_filtering(struct axgbe_port *pdata) +{ + /* Enable VLAN filtering */ + AXGMAC_IOWRITE_BITS(pdata, MAC_PFR, VTFE, 1); + + /* Enable VLAN Hash Table filtering */ + AXGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, VTHM, 1); + + /* Disable VLAN tag inverse matching */ + AXGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, VTIM, 0); + + /* Only filter on the lower 12-bits of the VLAN tag */ + AXGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, ETV, 1); + + /* In order for the VLAN Hash Table filtering to be effective, + * the VLAN tag identifier in the VLAN Tag Register must not + * be zero. Set the VLAN tag identifier to "1" to enable the + * VLAN Hash Table filtering. This implies that a VLAN tag of + * 1 will always pass filtering. + */ + AXGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, VL, 1); + return 0; +} + +static int axgbe_disable_rx_vlan_filtering(struct axgbe_port *pdata) +{ + /* Disable VLAN filtering */ + AXGMAC_IOWRITE_BITS(pdata, MAC_PFR, VTFE, 0); + return 0; +} + +static u32 axgbe_vid_crc32_le(__le16 vid_le) +{ + u32 poly = 0xedb88320; /* CRCPOLY_LE */ + u32 crc = ~0; + u32 temp = 0; + unsigned char *data = (unsigned char *)&vid_le; + unsigned char data_byte = 0; + int i, bits; + + bits = get_lastbit_set(VLAN_VID_MASK); + for (i = 0; i < bits; i++) { + if ((i % 8) == 0) + data_byte = data[i / 8]; + + temp = ((crc & 1) ^ data_byte) & 1; + crc >>= 1; + data_byte >>= 1; + + if (temp) + crc ^= poly; + } + return crc; +} + +static int axgbe_update_vlan_hash_table(struct axgbe_port *pdata) +{ + u32 crc = 0; + u16 vid; + __le16 vid_le = 0; + u16 vlan_hash_table = 0; + unsigned int reg = 0; + unsigned long vid_idx, vid_valid; + + /* Generate the VLAN Hash Table value */ + for (vid = 0; vid < VLAN_N_VID; vid++) { + vid_idx = VLAN_TABLE_IDX(vid); + vid_valid = pdata->active_vlans[vid_idx]; + vid_valid = (unsigned long)vid_valid >> (vid - (64 * vid_idx)); + if (vid_valid & 1) + PMD_DRV_LOG(DEBUG, + "vid:%d pdata->active_vlans[%ld]=0x%lx\n", + vid, vid_idx, pdata->active_vlans[vid_idx]); + else + continue; + + vid_le = rte_cpu_to_le_16(vid); + crc = bitrev32(~axgbe_vid_crc32_le(vid_le)) >> 28; + vlan_hash_table |= (1 << crc); + PMD_DRV_LOG(DEBUG, "crc = %d vlan_hash_table = 0x%x\n", + crc, vlan_hash_table); + } + /* Set the VLAN Hash Table filtering register */ + AXGMAC_IOWRITE_BITS(pdata, MAC_VLANHTR, VLHT, vlan_hash_table); + reg = AXGMAC_IOREAD(pdata, MAC_VLANHTR); + PMD_DRV_LOG(DEBUG, "vlan_hash_table reg val = 0x%x\n", reg); + return 0; +} + static int __axgbe_exit(struct axgbe_port *pdata) { unsigned int count = 2000; @@ -614,7 +768,7 @@ static int axgbe_write_rss_reg(struct axgbe_port *pdata, unsigned int type, return -EBUSY; } -static int axgbe_write_rss_hash_key(struct axgbe_port *pdata) +int axgbe_write_rss_hash_key(struct axgbe_port *pdata) { struct rte_eth_rss_conf *rss_conf; unsigned int key_regs = sizeof(pdata->rss_key) / sizeof(u32); @@ -638,7 +792,7 @@ static int axgbe_write_rss_hash_key(struct axgbe_port *pdata) return 0; } -static int axgbe_write_rss_lookup_table(struct axgbe_port *pdata) +int axgbe_write_rss_lookup_table(struct axgbe_port *pdata) { unsigned int i; int ret; @@ -683,6 +837,7 @@ static void axgbe_rss_options(struct axgbe_port *pdata) uint64_t rss_hf; rss_conf = &pdata->eth_dev->data->dev_conf.rx_adv_conf.rss_conf; + pdata->rss_hf = rss_conf->rss_hf; rss_hf = rss_conf->rss_hf; if (rss_hf & (ETH_RSS_IPV4 | ETH_RSS_IPV6)) @@ -1008,16 +1163,6 @@ static void axgbe_enable_mtl_interrupts(struct axgbe_port *pdata) } } -static uint32_t bitrev32(uint32_t x) -{ - x = (x >> 16) | (x << 16); - x = (((x & 0xff00ff00) >> 8) | ((x & 0x00ff00ff) << 8)); - x = (((x & 0xf0f0f0f0) >> 4) | ((x & 0x0f0f0f0f) << 4)); - x = (((x & 0xcccccccc) >> 2) | ((x & 0x33333333) << 2)); - x = (((x & 0xaaaaaaaa) >> 1) | ((x & 0x55555555) << 1)); - return x; -} - static uint32_t crc32_le(uint32_t crc, uint8_t *p, uint32_t len) { int i; @@ -1217,4 +1362,11 @@ void axgbe_init_function_ptrs_dev(struct axgbe_hw_if *hw_if) /* For FLOW ctrl */ hw_if->config_tx_flow_control = axgbe_config_tx_flow_control; hw_if->config_rx_flow_control = axgbe_config_rx_flow_control; + + /*vlan*/ + hw_if->enable_rx_vlan_stripping = axgbe_enable_rx_vlan_stripping; + hw_if->disable_rx_vlan_stripping = axgbe_disable_rx_vlan_stripping; + hw_if->enable_rx_vlan_filtering = axgbe_enable_rx_vlan_filtering; + hw_if->disable_rx_vlan_filtering = axgbe_disable_rx_vlan_filtering; + hw_if->update_vlan_hash_table = axgbe_update_vlan_hash_table; }