diff options
Diffstat (limited to 'drivers/net/ethernet/wangxun')
| -rw-r--r-- | drivers/net/ethernet/wangxun/libwx/wx_ethtool.c | 73 | ||||
| -rw-r--r-- | drivers/net/ethernet/wangxun/libwx/wx_hw.c | 72 | ||||
| -rw-r--r-- | drivers/net/ethernet/wangxun/libwx/wx_lib.c | 143 | ||||
| -rw-r--r-- | drivers/net/ethernet/wangxun/libwx/wx_sriov.c | 4 | ||||
| -rw-r--r-- | drivers/net/ethernet/wangxun/libwx/wx_type.h | 55 | ||||
| -rw-r--r-- | drivers/net/ethernet/wangxun/libwx/wx_vf.h | 4 | ||||
| -rw-r--r-- | drivers/net/ethernet/wangxun/libwx/wx_vf_lib.c | 12 | ||||
| -rw-r--r-- | drivers/net/ethernet/wangxun/txgbe/txgbe_aml.c | 298 | ||||
| -rw-r--r-- | drivers/net/ethernet/wangxun/txgbe/txgbe_aml.h | 5 | ||||
| -rw-r--r-- | drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c | 38 | ||||
| -rw-r--r-- | drivers/net/ethernet/wangxun/txgbe/txgbe_irq.c | 10 | ||||
| -rw-r--r-- | drivers/net/ethernet/wangxun/txgbe/txgbe_main.c | 28 | ||||
| -rw-r--r-- | drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c | 2 | ||||
| -rw-r--r-- | drivers/net/ethernet/wangxun/txgbe/txgbe_type.h | 39 | ||||
| -rw-r--r-- | drivers/net/ethernet/wangxun/txgbevf/txgbevf_main.c | 12 |
15 files changed, 644 insertions, 151 deletions
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c index 06f401bd975c..f362e51c73ee 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c +++ b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c @@ -51,6 +51,11 @@ static const struct wx_stats wx_gstrings_fdir_stats[] = { WX_STAT("fdir_miss", stats.fdirmiss), }; +static const struct wx_stats wx_gstrings_rsc_stats[] = { + WX_STAT("rsc_aggregated", rsc_count), + WX_STAT("rsc_flushed", rsc_flush), +}; + /* drivers allocates num_tx_queues and num_rx_queues symmetrically so * we set the num_rx_queues to evaluate to num_tx_queues. This is * used because we do not have a good way to get the max number of @@ -64,16 +69,21 @@ static const struct wx_stats wx_gstrings_fdir_stats[] = { (sizeof(struct wx_queue_stats) / sizeof(u64))) #define WX_GLOBAL_STATS_LEN ARRAY_SIZE(wx_gstrings_stats) #define WX_FDIR_STATS_LEN ARRAY_SIZE(wx_gstrings_fdir_stats) +#define WX_RSC_STATS_LEN ARRAY_SIZE(wx_gstrings_rsc_stats) #define WX_STATS_LEN (WX_GLOBAL_STATS_LEN + WX_QUEUE_STATS_LEN) int wx_get_sset_count(struct net_device *netdev, int sset) { struct wx *wx = netdev_priv(netdev); + int len = WX_STATS_LEN; switch (sset) { case ETH_SS_STATS: - return (test_bit(WX_FLAG_FDIR_CAPABLE, wx->flags)) ? - WX_STATS_LEN + WX_FDIR_STATS_LEN : WX_STATS_LEN; + if (test_bit(WX_FLAG_FDIR_CAPABLE, wx->flags)) + len += WX_FDIR_STATS_LEN; + if (test_bit(WX_FLAG_RSC_CAPABLE, wx->flags)) + len += WX_RSC_STATS_LEN; + return len; default: return -EOPNOTSUPP; } @@ -94,6 +104,10 @@ void wx_get_strings(struct net_device *netdev, u32 stringset, u8 *data) for (i = 0; i < WX_FDIR_STATS_LEN; i++) ethtool_puts(&p, wx_gstrings_fdir_stats[i].stat_string); } + if (test_bit(WX_FLAG_RSC_CAPABLE, wx->flags)) { + for (i = 0; i < WX_RSC_STATS_LEN; i++) + ethtool_puts(&p, wx_gstrings_rsc_stats[i].stat_string); + } for (i = 0; i < netdev->num_tx_queues; i++) { ethtool_sprintf(&p, "tx_queue_%u_packets", i); ethtool_sprintf(&p, "tx_queue_%u_bytes", i); @@ -131,6 +145,13 @@ void wx_get_ethtool_stats(struct net_device *netdev, } } + if (test_bit(WX_FLAG_RSC_CAPABLE, wx->flags)) { + for (k = 0; k < WX_RSC_STATS_LEN; k++) { + p = (char *)wx + wx_gstrings_rsc_stats[k].stat_offset; + data[i++] = *(u64 *)p; + } + } + for (j = 0; j < netdev->num_tx_queues; j++) { ring = wx->tx_ring[j]; if (!ring) { @@ -219,9 +240,6 @@ int wx_nway_reset(struct net_device *netdev) { struct wx *wx = netdev_priv(netdev); - if (wx->mac.type == wx_mac_aml40) - return -EOPNOTSUPP; - return phylink_ethtool_nway_reset(wx->phylink); } EXPORT_SYMBOL(wx_nway_reset); @@ -240,9 +258,6 @@ int wx_set_link_ksettings(struct net_device *netdev, { struct wx *wx = netdev_priv(netdev); - if (wx->mac.type == wx_mac_aml40) - return -EOPNOTSUPP; - return phylink_ethtool_ksettings_set(wx->phylink, cmd); } EXPORT_SYMBOL(wx_set_link_ksettings); @@ -252,9 +267,6 @@ void wx_get_pauseparam(struct net_device *netdev, { struct wx *wx = netdev_priv(netdev); - if (wx->mac.type == wx_mac_aml40) - return; - phylink_ethtool_get_pauseparam(wx->phylink, pause); } EXPORT_SYMBOL(wx_get_pauseparam); @@ -264,9 +276,6 @@ int wx_set_pauseparam(struct net_device *netdev, { struct wx *wx = netdev_priv(netdev); - if (wx->mac.type == wx_mac_aml40) - return -EOPNOTSUPP; - return phylink_ethtool_set_pauseparam(wx->phylink, pause); } EXPORT_SYMBOL(wx_set_pauseparam); @@ -322,6 +331,40 @@ int wx_get_coalesce(struct net_device *netdev, } EXPORT_SYMBOL(wx_get_coalesce); +static void wx_update_rsc(struct wx *wx) +{ + struct net_device *netdev = wx->netdev; + bool need_reset = false; + + /* nothing to do if LRO or RSC are not enabled */ + if (!test_bit(WX_FLAG_RSC_CAPABLE, wx->flags) || + !(netdev->features & NETIF_F_LRO)) + return; + + /* check the feature flag value and enable RSC if necessary */ + if (wx->rx_itr_setting == 1 || + wx->rx_itr_setting > WX_MIN_RSC_ITR) { + if (!test_bit(WX_FLAG_RSC_ENABLED, wx->flags)) { + set_bit(WX_FLAG_RSC_ENABLED, wx->flags); + dev_info(&wx->pdev->dev, + "rx-usecs value high enough to re-enable RSC\n"); + + need_reset = true; + } + /* if interrupt rate is too high then disable RSC */ + } else if (test_bit(WX_FLAG_RSC_ENABLED, wx->flags)) { + clear_bit(WX_FLAG_RSC_ENABLED, wx->flags); + dev_info(&wx->pdev->dev, + "rx-usecs set too low, disabling RSC\n"); + + need_reset = true; + } + + /* reset the device to apply the new RSC setting */ + if (need_reset && wx->do_reset) + wx->do_reset(netdev); +} + int wx_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *ec, struct kernel_ethtool_coalesce *kernel_coal, @@ -414,6 +457,8 @@ int wx_set_coalesce(struct net_device *netdev, wx_write_eitr(q_vector); } + wx_update_rsc(wx); + return 0; } EXPORT_SYMBOL(wx_set_coalesce); diff --git a/drivers/net/ethernet/wangxun/libwx/wx_hw.c b/drivers/net/ethernet/wangxun/libwx/wx_hw.c index 1e2713f0c921..58b8300e3d2c 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_hw.c +++ b/drivers/net/ethernet/wangxun/libwx/wx_hw.c @@ -1779,7 +1779,9 @@ EXPORT_SYMBOL(wx_set_rx_mode); static void wx_set_rx_buffer_len(struct wx *wx) { struct net_device *netdev = wx->netdev; + struct wx_ring *rx_ring; u32 mhadd, max_frame; + int i; max_frame = netdev->mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN; /* adjust max frame to be at least the size of a standard frame */ @@ -1789,6 +1791,19 @@ static void wx_set_rx_buffer_len(struct wx *wx) mhadd = rd32(wx, WX_PSR_MAX_SZ); if (max_frame != mhadd) wr32(wx, WX_PSR_MAX_SZ, max_frame); + + /* + * Setup the HW Rx Head and Tail Descriptor Pointers and + * the Base and Length of the Rx Descriptor Ring + */ + for (i = 0; i < wx->num_rx_queues; i++) { + rx_ring = wx->rx_ring[i]; + rx_ring->rx_buf_len = WX_RXBUFFER_2K; +#if (PAGE_SIZE < 8192) + if (test_bit(WX_FLAG_RSC_ENABLED, wx->flags)) + rx_ring->rx_buf_len = WX_RXBUFFER_3K; +#endif + } } /** @@ -1865,11 +1880,27 @@ static void wx_configure_srrctl(struct wx *wx, srrctl |= WX_RXBUFFER_256 << WX_PX_RR_CFG_BHDRSIZE_SHIFT; /* configure the packet buffer length */ - srrctl |= WX_RX_BUFSZ >> WX_PX_RR_CFG_BSIZEPKT_SHIFT; + srrctl |= rx_ring->rx_buf_len >> WX_PX_RR_CFG_BSIZEPKT_SHIFT; wr32(wx, WX_PX_RR_CFG(reg_idx), srrctl); } +static void wx_configure_rscctl(struct wx *wx, + struct wx_ring *ring) +{ + u8 reg_idx = ring->reg_idx; + u32 rscctrl; + + if (!test_bit(WX_FLAG_RSC_ENABLED, wx->flags)) + return; + + rscctrl = rd32(wx, WX_PX_RR_CFG(reg_idx)); + rscctrl |= WX_PX_RR_CFG_RSC; + rscctrl |= WX_PX_RR_CFG_MAX_RSCBUF_16; + + wr32(wx, WX_PX_RR_CFG(reg_idx), rscctrl); +} + static void wx_configure_tx_ring(struct wx *wx, struct wx_ring *ring) { @@ -1905,6 +1936,15 @@ static void wx_configure_tx_ring(struct wx *wx, memset(ring->tx_buffer_info, 0, sizeof(struct wx_tx_buffer) * ring->count); + if (ring->headwb_mem) { + wr32(wx, WX_PX_TR_HEAD_ADDRL(reg_idx), + ring->headwb_dma & DMA_BIT_MASK(32)); + wr32(wx, WX_PX_TR_HEAD_ADDRH(reg_idx), + upper_32_bits(ring->headwb_dma)); + + txdctl |= WX_PX_TR_CFG_HEAD_WB; + } + /* enable queue */ wr32(wx, WX_PX_TR_CFG(reg_idx), txdctl); @@ -1935,6 +1975,10 @@ static void wx_configure_rx_ring(struct wx *wx, rxdctl |= (ring->count / 128) << WX_PX_RR_CFG_RR_SIZE_SHIFT; rxdctl |= 0x1 << WX_PX_RR_CFG_RR_THER_SHIFT; + + if (test_bit(WX_FLAG_RX_MERGE_ENABLED, wx->flags)) + rxdctl |= WX_PX_RR_CFG_DESC_MERGE; + wr32(wx, WX_PX_RR_CFG(reg_idx), rxdctl); /* reset head and tail pointers */ @@ -1943,6 +1987,7 @@ static void wx_configure_rx_ring(struct wx *wx, ring->tail = wx->hw_addr + WX_PX_RR_WP(reg_idx); wx_configure_srrctl(wx, ring); + wx_configure_rscctl(wx, ring); /* initialize rx_buffer_info */ memset(ring->rx_buffer_info, 0, @@ -2181,7 +2226,9 @@ void wx_configure_rx(struct wx *wx) /* RSC Setup */ psrctl = rd32(wx, WX_PSR_CTL); psrctl |= WX_PSR_CTL_RSC_ACK; /* Disable RSC for ACK packets */ - psrctl |= WX_PSR_CTL_RSC_DIS; + psrctl &= ~WX_PSR_CTL_RSC_DIS; + if (!test_bit(WX_FLAG_RSC_ENABLED, wx->flags)) + psrctl |= WX_PSR_CTL_RSC_DIS; wr32(wx, WX_PSR_CTL, psrctl); } @@ -2190,6 +2237,12 @@ void wx_configure_rx(struct wx *wx) /* set_rx_buffer_len must be called before ring initialization */ wx_set_rx_buffer_len(wx); + if (test_bit(WX_FLAG_RX_MERGE_ENABLED, wx->flags)) { + wr32(wx, WX_RDM_DCACHE_CTL, WX_RDM_DCACHE_CTL_EN); + wr32m(wx, WX_RDM_RSC_CTL, + WX_RDM_RSC_CTL_FREE_CTL | WX_RDM_RSC_CTL_FREE_CNT_DIS, + WX_RDM_RSC_CTL_FREE_CTL); + } /* Setup the HW Rx Head and Tail Descriptor Pointers and * the Base and Length of the Rx Descriptor Ring */ @@ -2427,7 +2480,8 @@ int wx_sw_init(struct wx *wx) wx->oem_svid = pdev->subsystem_vendor; wx->oem_ssid = pdev->subsystem_device; wx->bus.device = PCI_SLOT(pdev->devfn); - wx->bus.func = PCI_FUNC(pdev->devfn); + wx->bus.func = FIELD_GET(WX_CFG_PORT_ST_LANID, + rd32(wx, WX_CFG_PORT_ST)); if (wx->oem_svid == PCI_VENDOR_ID_WANGXUN || pdev->is_virtfn) { @@ -2805,6 +2859,18 @@ void wx_update_stats(struct wx *wx) wx->hw_csum_rx_error = hw_csum_rx_error; wx->hw_csum_rx_good = hw_csum_rx_good; + if (test_bit(WX_FLAG_RSC_ENABLED, wx->flags)) { + u64 rsc_count = 0; + u64 rsc_flush = 0; + + for (i = 0; i < wx->num_rx_queues; i++) { + rsc_count += wx->rx_ring[i]->rx_stats.rsc_count; + rsc_flush += wx->rx_ring[i]->rx_stats.rsc_flush; + } + wx->rsc_count = rsc_count; + wx->rsc_flush = rsc_flush; + } + for (i = 0; i < wx->num_tx_queues; i++) { struct wx_ring *tx_ring = wx->tx_ring[i]; diff --git a/drivers/net/ethernet/wangxun/libwx/wx_lib.c b/drivers/net/ethernet/wangxun/libwx/wx_lib.c index 3adf7048320a..32cadafa4b3b 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_lib.c +++ b/drivers/net/ethernet/wangxun/libwx/wx_lib.c @@ -235,7 +235,7 @@ static struct sk_buff *wx_build_skb(struct wx_ring *rx_ring, { unsigned int size = le16_to_cpu(rx_desc->wb.upper.length); #if (PAGE_SIZE < 8192) - unsigned int truesize = WX_RX_BUFSZ; + unsigned int truesize = wx_rx_pg_size(rx_ring) / 2; #else unsigned int truesize = ALIGN(size, L1_CACHE_BYTES); #endif @@ -341,7 +341,7 @@ void wx_alloc_rx_buffers(struct wx_ring *rx_ring, u16 cleaned_count) /* sync the buffer for use by the device */ dma_sync_single_range_for_device(rx_ring->dev, bi->dma, bi->page_offset, - WX_RX_BUFSZ, + rx_ring->rx_buf_len, DMA_FROM_DEVICE); rx_desc->read.pkt_addr = @@ -404,6 +404,7 @@ static bool wx_is_non_eop(struct wx_ring *rx_ring, union wx_rx_desc *rx_desc, struct sk_buff *skb) { + struct wx *wx = rx_ring->q_vector->wx; u32 ntc = rx_ring->next_to_clean + 1; /* fetch, update, and store next to clean */ @@ -412,6 +413,24 @@ static bool wx_is_non_eop(struct wx_ring *rx_ring, prefetch(WX_RX_DESC(rx_ring, ntc)); + /* update RSC append count if present */ + if (test_bit(WX_FLAG_RSC_ENABLED, wx->flags)) { + __le32 rsc_enabled = rx_desc->wb.lower.lo_dword.data & + cpu_to_le32(WX_RXD_RSCCNT_MASK); + + if (unlikely(rsc_enabled)) { + u32 rsc_cnt = le32_to_cpu(rsc_enabled); + + rsc_cnt >>= WX_RXD_RSCCNT_SHIFT; + WX_CB(skb)->append_cnt += rsc_cnt - 1; + + /* update ntc based on RSC value */ + ntc = le32_to_cpu(rx_desc->wb.upper.status_error); + ntc &= WX_RXD_NEXTP_MASK; + ntc >>= WX_RXD_NEXTP_SHIFT; + } + } + /* if we are the last buffer then there is nothing else to do */ if (likely(wx_test_staterr(rx_desc, WX_RXD_STAT_EOP))) return false; @@ -582,6 +601,33 @@ static void wx_rx_vlan(struct wx_ring *ring, union wx_rx_desc *rx_desc, } } +static void wx_set_rsc_gso_size(struct wx_ring *ring, + struct sk_buff *skb) +{ + u16 hdr_len = skb_headlen(skb); + + /* set gso_size to avoid messing up TCP MSS */ + skb_shinfo(skb)->gso_size = DIV_ROUND_UP((skb->len - hdr_len), + WX_CB(skb)->append_cnt); + skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4; +} + +static void wx_update_rsc_stats(struct wx_ring *rx_ring, + struct sk_buff *skb) +{ + /* if append_cnt is 0 then frame is not RSC */ + if (!WX_CB(skb)->append_cnt) + return; + + rx_ring->rx_stats.rsc_count += WX_CB(skb)->append_cnt; + rx_ring->rx_stats.rsc_flush++; + + wx_set_rsc_gso_size(rx_ring, skb); + + /* gso_size is computed using append_cnt so always clear it last */ + WX_CB(skb)->append_cnt = 0; +} + /** * wx_process_skb_fields - Populate skb header fields from Rx descriptor * @rx_ring: rx descriptor ring packet is being transacted on @@ -598,6 +644,9 @@ static void wx_process_skb_fields(struct wx_ring *rx_ring, { struct wx *wx = netdev_priv(rx_ring->netdev); + if (test_bit(WX_FLAG_RSC_CAPABLE, wx->flags)) + wx_update_rsc_stats(rx_ring, skb); + wx_rx_hash(rx_ring, rx_desc, skb); wx_rx_checksum(rx_ring, rx_desc, skb); @@ -735,9 +784,22 @@ static bool wx_clean_tx_irq(struct wx_q_vector *q_vector, /* prevent any other reads prior to eop_desc */ smp_rmb(); - /* if DD is not set pending work has not been completed */ - if (!(eop_desc->wb.status & cpu_to_le32(WX_TXD_STAT_DD))) + if (tx_ring->headwb_mem) { + u32 head = *tx_ring->headwb_mem; + + if (head == tx_ring->next_to_clean) + break; + else if (head > tx_ring->next_to_clean && + !(tx_buffer->next_eop >= tx_ring->next_to_clean && + tx_buffer->next_eop < head)) + break; + else if (!(tx_buffer->next_eop >= tx_ring->next_to_clean || + tx_buffer->next_eop < head)) + break; + } else if (!(eop_desc->wb.status & cpu_to_le32(WX_TXD_STAT_DD))) { + /* if DD is not set pending work has not been completed */ break; + } /* clear next_to_watch to prevent false hangs */ tx_buffer->next_to_watch = NULL; @@ -1075,6 +1137,10 @@ static int wx_tx_map(struct wx_ring *tx_ring, /* set next_to_watch value indicating a packet is present */ first->next_to_watch = tx_desc; + /* set next_eop for amlite tx head wb */ + if (tx_ring->headwb_mem) + first->next_eop = i; + i++; if (i == tx_ring->count) i = 0; @@ -2532,7 +2598,7 @@ static void wx_clean_rx_ring(struct wx_ring *rx_ring) dma_sync_single_range_for_cpu(rx_ring->dev, rx_buffer->dma, rx_buffer->page_offset, - WX_RX_BUFSZ, + rx_ring->rx_buf_len, DMA_FROM_DEVICE); /* free resources associated with mapping */ @@ -2683,6 +2749,16 @@ void wx_clean_all_tx_rings(struct wx *wx) } EXPORT_SYMBOL(wx_clean_all_tx_rings); +static void wx_free_headwb_resources(struct wx_ring *tx_ring) +{ + if (!tx_ring->headwb_mem) + return; + + dma_free_coherent(tx_ring->dev, sizeof(u32), + tx_ring->headwb_mem, tx_ring->headwb_dma); + tx_ring->headwb_mem = NULL; +} + /** * wx_free_tx_resources - Free Tx Resources per Queue * @tx_ring: Tx descriptor ring for a specific queue @@ -2702,6 +2778,8 @@ static void wx_free_tx_resources(struct wx_ring *tx_ring) dma_free_coherent(tx_ring->dev, tx_ring->size, tx_ring->desc, tx_ring->dma); tx_ring->desc = NULL; + + wx_free_headwb_resources(tx_ring); } /** @@ -2731,13 +2809,14 @@ static int wx_alloc_page_pool(struct wx_ring *rx_ring) struct page_pool_params pp_params = { .flags = PP_FLAG_DMA_MAP | PP_FLAG_DMA_SYNC_DEV, - .order = 0, - .pool_size = rx_ring->count, + .order = wx_rx_pg_order(rx_ring), + .pool_size = rx_ring->count * rx_ring->rx_buf_len / + wx_rx_pg_size(rx_ring), .nid = dev_to_node(rx_ring->dev), .dev = rx_ring->dev, .dma_dir = DMA_FROM_DEVICE, .offset = 0, - .max_len = PAGE_SIZE, + .max_len = wx_rx_pg_size(rx_ring), }; rx_ring->page_pool = page_pool_create(&pp_params); @@ -2840,6 +2919,24 @@ err_setup_rx: return err; } +static void wx_setup_headwb_resources(struct wx_ring *tx_ring) +{ + struct wx *wx = netdev_priv(tx_ring->netdev); + + if (!test_bit(WX_FLAG_TXHEAD_WB_ENABLED, wx->flags)) + return; + + if (!tx_ring->q_vector) + return; + + tx_ring->headwb_mem = dma_alloc_coherent(tx_ring->dev, + sizeof(u32), + &tx_ring->headwb_dma, + GFP_KERNEL); + if (!tx_ring->headwb_mem) + dev_info(tx_ring->dev, "Allocate headwb memory failed, disable it\n"); +} + /** * wx_setup_tx_resources - allocate Tx resources (Descriptors) * @tx_ring: tx descriptor ring (for a specific queue) to setup @@ -2880,6 +2977,8 @@ static int wx_setup_tx_resources(struct wx_ring *tx_ring) if (!tx_ring->desc) goto err; + wx_setup_headwb_resources(tx_ring); + tx_ring->next_to_use = 0; tx_ring->next_to_clean = 0; @@ -3026,8 +3125,25 @@ int wx_set_features(struct net_device *netdev, netdev_features_t features) else if (changed & (NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_FILTER)) wx_set_rx_mode(netdev); + if (test_bit(WX_FLAG_RSC_CAPABLE, wx->flags)) { + if (!(features & NETIF_F_LRO)) { + if (test_bit(WX_FLAG_RSC_ENABLED, wx->flags)) + need_reset = true; + clear_bit(WX_FLAG_RSC_ENABLED, wx->flags); + } else if (!(test_bit(WX_FLAG_RSC_ENABLED, wx->flags))) { + if (wx->rx_itr_setting == 1 || + wx->rx_itr_setting > WX_MIN_RSC_ITR) { + set_bit(WX_FLAG_RSC_ENABLED, wx->flags); + need_reset = true; + } else if (changed & NETIF_F_LRO) { + dev_info(&wx->pdev->dev, + "rx-usecs set too low, disable RSC\n"); + } + } + } + if (!(test_bit(WX_FLAG_FDIR_CAPABLE, wx->flags))) - return 0; + goto out; /* Check if Flow Director n-tuple support was enabled or disabled. If * the state changed, we need to reset. @@ -3053,6 +3169,7 @@ int wx_set_features(struct net_device *netdev, netdev_features_t features) break; } +out: if (need_reset && wx->do_reset) wx->do_reset(netdev); @@ -3102,6 +3219,14 @@ netdev_features_t wx_fix_features(struct net_device *netdev, } } + /* If Rx checksum is disabled, then RSC/LRO should also be disabled */ + if (!(features & NETIF_F_RXCSUM)) + features &= ~NETIF_F_LRO; + + /* Turn off LRO if not RSC capable */ + if (!test_bit(WX_FLAG_RSC_CAPABLE, wx->flags)) + features &= ~NETIF_F_LRO; + return features; } EXPORT_SYMBOL(wx_fix_features); diff --git a/drivers/net/ethernet/wangxun/libwx/wx_sriov.c b/drivers/net/ethernet/wangxun/libwx/wx_sriov.c index c6d158cd70da..493da5fffdb6 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_sriov.c +++ b/drivers/net/ethernet/wangxun/libwx/wx_sriov.c @@ -122,6 +122,10 @@ static int __wx_enable_sriov(struct wx *wx, u8 num_vfs) WX_CFG_PORT_CTL_NUM_VT_MASK, value); + /* Disable RSC when in SR-IOV mode */ + clear_bit(WX_FLAG_RSC_CAPABLE, wx->flags); + clear_bit(WX_FLAG_RSC_ENABLED, wx->flags); + return ret; } diff --git a/drivers/net/ethernet/wangxun/libwx/wx_type.h b/drivers/net/ethernet/wangxun/libwx/wx_type.h index d89b9b8a0a2c..29e5c5470c94 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_type.h +++ b/drivers/net/ethernet/wangxun/libwx/wx_type.h @@ -83,8 +83,13 @@ /*********************** Receive DMA registers **************************/ #define WX_RDM_VF_RE(_i) (0x12004 + ((_i) * 4)) +#define WX_RDM_RSC_CTL 0x1200C +#define WX_RDM_RSC_CTL_FREE_CNT_DIS BIT(8) +#define WX_RDM_RSC_CTL_FREE_CTL BIT(7) #define WX_RDM_PF_QDE(_i) (0x12080 + ((_i) * 4)) #define WX_RDM_VFRE_CLR(_i) (0x120A0 + ((_i) * 4)) +#define WX_RDM_DCACHE_CTL 0x120A8 +#define WX_RDM_DCACHE_CTL_EN BIT(0) #define WX_RDM_DRP_PKT 0x12500 #define WX_RDM_PKT_CNT 0x12504 #define WX_RDM_BYTE_CNT_LSB 0x12508 @@ -97,6 +102,8 @@ #define WX_CFG_PORT_CTL_DRV_LOAD BIT(3) #define WX_CFG_PORT_CTL_QINQ BIT(2) #define WX_CFG_PORT_CTL_D_VLAN BIT(0) /* double vlan*/ +#define WX_CFG_PORT_ST 0x14404 +#define WX_CFG_PORT_ST_LANID GENMASK(9, 8) #define WX_CFG_TAG_TPID(_i) (0x14430 + ((_i) * 4)) #define WX_CFG_PORT_CTL_NUM_VT_MASK GENMASK(13, 12) /* number of TVs */ @@ -419,6 +426,7 @@ enum WX_MSCA_CMD_value { #define WX_7K_ITR 595 #define WX_12K_ITR 336 #define WX_20K_ITR 200 +#define WX_MIN_RSC_ITR 24 #define WX_SP_MAX_EITR 0x00000FF8U #define WX_AML_MAX_EITR 0x00000FFFU #define WX_EM_MAX_EITR 0x00007FFCU @@ -429,12 +437,15 @@ enum WX_MSCA_CMD_value { #define WX_PX_TR_WP(_i) (0x03008 + ((_i) * 0x40)) #define WX_PX_TR_RP(_i) (0x0300C + ((_i) * 0x40)) #define WX_PX_TR_CFG(_i) (0x03010 + ((_i) * 0x40)) +#define WX_PX_TR_HEAD_ADDRL(_i) (0x03028 + ((_i) * 0x40)) +#define WX_PX_TR_HEAD_ADDRH(_i) (0x0302C + ((_i) * 0x40)) /* Transmit Config masks */ #define WX_PX_TR_CFG_ENABLE BIT(0) /* Ena specific Tx Queue */ #define WX_PX_TR_CFG_TR_SIZE_SHIFT 1 /* tx desc number per ring */ #define WX_PX_TR_CFG_SWFLSH BIT(26) /* Tx Desc. wr-bk flushing */ #define WX_PX_TR_CFG_WTHRESH_SHIFT 16 /* shift to WTHRESH bits */ #define WX_PX_TR_CFG_THRE_SHIFT 8 +#define WX_PX_TR_CFG_HEAD_WB BIT(27) /* Receive DMA Registers */ #define WX_PX_RR_BAL(_i) (0x01000 + ((_i) * 0x40)) @@ -446,7 +457,10 @@ enum WX_MSCA_CMD_value { /* PX_RR_CFG bit definitions */ #define WX_PX_RR_CFG_VLAN BIT(31) #define WX_PX_RR_CFG_DROP_EN BIT(30) +#define WX_PX_RR_CFG_RSC BIT(29) #define WX_PX_RR_CFG_SPLIT_MODE BIT(26) +#define WX_PX_RR_CFG_MAX_RSCBUF_16 FIELD_PREP(GENMASK(24, 23), 3) +#define WX_PX_RR_CFG_DESC_MERGE BIT(19) #define WX_PX_RR_CFG_RR_THER_SHIFT 16 #define WX_PX_RR_CFG_RR_HDR_SZ GENMASK(15, 12) #define WX_PX_RR_CFG_RR_BUF_SZ GENMASK(11, 8) @@ -542,14 +556,9 @@ enum WX_MSCA_CMD_value { /* Supported Rx Buffer Sizes */ #define WX_RXBUFFER_256 256 /* Used for skb receive header */ #define WX_RXBUFFER_2K 2048 +#define WX_RXBUFFER_3K 3072 #define WX_MAX_RXBUFFER 16384 /* largest size for single descriptor */ -#if MAX_SKB_FRAGS < 8 -#define WX_RX_BUFSZ ALIGN(WX_MAX_RXBUFFER / MAX_SKB_FRAGS, 1024) -#else -#define WX_RX_BUFSZ WX_RXBUFFER_2K -#endif - #define WX_RX_BUFFER_WRITE 16 /* Must be power of 2 */ #define WX_MAX_DATA_PER_TXD BIT(14) @@ -557,8 +566,6 @@ enum WX_MSCA_CMD_value { #define TXD_USE_COUNT(S) DIV_ROUND_UP((S), WX_MAX_DATA_PER_TXD) #define DESC_NEEDED (MAX_SKB_FRAGS + 4) -#define WX_CFG_PORT_ST 0x14404 - /******************* Receive Descriptor bit definitions **********************/ #define WX_RXD_STAT_DD BIT(0) /* Done */ #define WX_RXD_STAT_EOP BIT(1) /* End of Packet */ @@ -643,6 +650,12 @@ enum wx_l2_ptypes { #define WX_RXD_PKTTYPE(_rxd) \ ((le32_to_cpu((_rxd)->wb.lower.lo_dword.data) >> 9) & 0xFF) + +#define WX_RXD_RSCCNT_MASK GENMASK(20, 17) +#define WX_RXD_RSCCNT_SHIFT 17 +#define WX_RXD_NEXTP_MASK GENMASK(19, 4) +#define WX_RXD_NEXTP_SHIFT 4 + /*********************** Transmit Descriptor Config Masks ****************/ #define WX_TXD_STAT_DD BIT(0) /* Descriptor Done */ #define WX_TXD_DTYP_DATA 0 /* Adv Data Descriptor */ @@ -1005,6 +1018,7 @@ struct wx_tx_buffer { DEFINE_DMA_UNMAP_LEN(len); __be16 protocol; u32 tx_flags; + u32 next_eop; }; struct wx_rx_buffer { @@ -1029,6 +1043,8 @@ struct wx_rx_queue_stats { u64 csum_good_cnt; u64 csum_err; u64 alloc_rx_buff_failed; + u64 rsc_count; + u64 rsc_flush; }; /* iterator for handling rings in ring container */ @@ -1056,6 +1072,8 @@ struct wx_ring { }; u8 __iomem *tail; dma_addr_t dma; /* phys. address of descriptor ring */ + dma_addr_t headwb_dma; + u32 *headwb_mem; unsigned int size; /* length in bytes */ u16 count; /* amount of descriptors */ @@ -1069,6 +1087,7 @@ struct wx_ring { */ u16 next_to_use; u16 next_to_clean; + u16 rx_buf_len; union { u16 next_to_alloc; struct { @@ -1225,13 +1244,16 @@ enum wx_pf_flags { WX_FLAG_FDIR_HASH, WX_FLAG_FDIR_PERFECT, WX_FLAG_RSC_CAPABLE, + WX_FLAG_RSC_ENABLED, WX_FLAG_RX_HWTSTAMP_ENABLED, WX_FLAG_RX_HWTSTAMP_IN_REGISTER, WX_FLAG_PTP_PPS_ENABLED, WX_FLAG_NEED_LINK_CONFIG, - WX_FLAG_NEED_SFP_RESET, + WX_FLAG_NEED_MODULE_RESET, WX_FLAG_NEED_UPDATE_LINK, WX_FLAG_NEED_DO_RESET, + WX_FLAG_RX_MERGE_ENABLED, + WX_FLAG_TXHEAD_WB_ENABLED, WX_PF_FLAGS_NBITS /* must be last */ }; @@ -1271,8 +1293,6 @@ struct wx { /* PHY stuff */ bool notify_down; - int adv_speed; - int adv_duplex; unsigned int link; int speed; int duplex; @@ -1340,6 +1360,8 @@ struct wx { u64 hw_csum_rx_good; u64 hw_csum_rx_error; u64 alloc_rx_buff_failed; + u64 rsc_count; + u64 rsc_flush; unsigned int num_vfs; struct vf_data_storage *vfinfo; struct vf_macvlans vf_mvs; @@ -1471,4 +1493,15 @@ static inline int wx_set_state_reset(struct wx *wx) return 0; } +static inline unsigned int wx_rx_pg_order(struct wx_ring *ring) +{ +#if (PAGE_SIZE < 8192) + if (ring->rx_buf_len == WX_RXBUFFER_3K) + return 1; +#endif + return 0; +} + +#define wx_rx_pg_size(_ring) (PAGE_SIZE << wx_rx_pg_order(_ring)) + #endif /* _WX_TYPE_H_ */ diff --git a/drivers/net/ethernet/wangxun/libwx/wx_vf.h b/drivers/net/ethernet/wangxun/libwx/wx_vf.h index 3f16de0fa427..eb6ca3fe4e97 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_vf.h +++ b/drivers/net/ethernet/wangxun/libwx/wx_vf.h @@ -74,6 +74,7 @@ #define WX_VXRXDCTL_BUFSZ(f) FIELD_PREP(GENMASK(11, 8), f) #define WX_VXRXDCTL_HDRSZ_MASK GENMASK(15, 12) #define WX_VXRXDCTL_HDRSZ(f) FIELD_PREP(GENMASK(15, 12), f) +#define WX_VXRXDCTL_DESC_MERGE BIT(19) #define WX_VXRXDCTL_RSCMAX_MASK GENMASK(24, 23) #define WX_VXRXDCTL_RSCMAX(f) FIELD_PREP(GENMASK(24, 23), f) #define WX_VXRXDCTL_RSCEN BIT(29) @@ -91,6 +92,9 @@ #define WX_VXTXDCTL_PTHRESH(f) FIELD_PREP(GENMASK(11, 8), f) #define WX_VXTXDCTL_WTHRESH(f) FIELD_PREP(GENMASK(22, 16), f) #define WX_VXTXDCTL_FLUSH BIT(26) +#define WX_VXTXDCTL_HEAD_WB BIT(27) +#define WX_VXTXD_HEAD_ADDRL(r) (0x3028 + (0x40 * (r))) +#define WX_VXTXD_HEAD_ADDRH(r) (0x302C + (0x40 * (r))) #define WX_PFLINK_STATUS(g) FIELD_GET(BIT(0), g) #define WX_PFLINK_SPEED(g) FIELD_GET(GENMASK(31, 1), g) diff --git a/drivers/net/ethernet/wangxun/libwx/wx_vf_lib.c b/drivers/net/ethernet/wangxun/libwx/wx_vf_lib.c index a87887b9f8ee..aa8be036956c 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_vf_lib.c +++ b/drivers/net/ethernet/wangxun/libwx/wx_vf_lib.c @@ -132,6 +132,15 @@ static void wx_configure_tx_ring_vf(struct wx *wx, struct wx_ring *ring) txdctl |= WX_VXTXDCTL_BUFLEN(wx_buf_len(ring->count)); txdctl |= WX_VXTXDCTL_ENABLE; + if (ring->headwb_mem) { + wr32(wx, WX_VXTXD_HEAD_ADDRL(reg_idx), + ring->headwb_dma & DMA_BIT_MASK(32)); + wr32(wx, WX_VXTXD_HEAD_ADDRH(reg_idx), + upper_32_bits(ring->headwb_dma)); + + txdctl |= WX_VXTXDCTL_HEAD_WB; + } + /* reinitialize tx_buffer_info */ memset(ring->tx_buffer_info, 0, sizeof(struct wx_tx_buffer) * ring->count); @@ -272,6 +281,9 @@ void wx_configure_rx_ring_vf(struct wx *wx, struct wx_ring *ring) rxdctl |= WX_VXRXDCTL_RSCMAX(0); rxdctl |= WX_VXRXDCTL_RSCEN; + if (test_bit(WX_FLAG_RX_MERGE_ENABLED, wx->flags)) + rxdctl |= WX_VXRXDCTL_DESC_MERGE; + wr32(wx, WX_VXRXDCTL(reg_idx), rxdctl); /* pf/vf reuse */ diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_aml.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_aml.c index dc87ccad9652..62d7f47d4f8d 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_aml.c +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_aml.c @@ -17,10 +17,15 @@ void txgbe_gpio_init_aml(struct wx *wx) { - u32 status; + u32 status, mod_rst; + + if (wx->mac.type == wx_mac_aml40) + mod_rst = TXGBE_GPIOBIT_4; + else + mod_rst = TXGBE_GPIOBIT_2; - wr32(wx, WX_GPIO_INTTYPE_LEVEL, TXGBE_GPIOBIT_2 | TXGBE_GPIOBIT_3); - wr32(wx, WX_GPIO_INTEN, TXGBE_GPIOBIT_2 | TXGBE_GPIOBIT_3); + wr32(wx, WX_GPIO_INTTYPE_LEVEL, mod_rst); + wr32(wx, WX_GPIO_INTEN, mod_rst); status = rd32(wx, WX_GPIO_INTSTATUS); for (int i = 0; i < 6; i++) { @@ -33,20 +38,20 @@ irqreturn_t txgbe_gpio_irq_handler_aml(int irq, void *data) { struct txgbe *txgbe = data; struct wx *wx = txgbe->wx; - u32 status; + u32 status, mod_rst; + + if (wx->mac.type == wx_mac_aml40) + mod_rst = TXGBE_GPIOBIT_4; + else + mod_rst = TXGBE_GPIOBIT_2; wr32(wx, WX_GPIO_INTMASK, 0xFF); status = rd32(wx, WX_GPIO_INTSTATUS); - if (status & TXGBE_GPIOBIT_2) { - set_bit(WX_FLAG_NEED_SFP_RESET, wx->flags); - wr32(wx, WX_GPIO_EOI, TXGBE_GPIOBIT_2); + if (status & mod_rst) { + set_bit(WX_FLAG_NEED_MODULE_RESET, wx->flags); + wr32(wx, WX_GPIO_EOI, mod_rst); wx_service_event_schedule(wx); } - if (status & TXGBE_GPIOBIT_3) { - set_bit(WX_FLAG_NEED_LINK_CONFIG, wx->flags); - wx_service_event_schedule(wx); - wr32(wx, WX_GPIO_EOI, TXGBE_GPIOBIT_3); - } wr32(wx, WX_GPIO_INTMASK, 0); return IRQ_HANDLED; @@ -56,7 +61,7 @@ int txgbe_test_hostif(struct wx *wx) { struct txgbe_hic_ephy_getlink buffer; - if (wx->mac.type != wx_mac_aml) + if (wx->mac.type == wx_mac_sp) return 0; buffer.hdr.cmd = FW_PHY_GET_LINK_CMD; @@ -68,15 +73,49 @@ int txgbe_test_hostif(struct wx *wx) WX_HI_COMMAND_TIMEOUT, true); } -static int txgbe_identify_sfp_hostif(struct wx *wx, struct txgbe_hic_i2c_read *buffer) +int txgbe_read_eeprom_hostif(struct wx *wx, + struct txgbe_hic_i2c_read *buffer, + u32 length, u8 *data) { - buffer->hdr.cmd = FW_READ_SFP_INFO_CMD; + u32 dword_len, offset, value, i; + int err; + + buffer->hdr.cmd = FW_READ_EEPROM_CMD; buffer->hdr.buf_len = sizeof(struct txgbe_hic_i2c_read) - sizeof(struct wx_hic_hdr); buffer->hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED; + err = wx_host_interface_command(wx, (u32 *)buffer, + sizeof(struct txgbe_hic_i2c_read), + WX_HI_COMMAND_TIMEOUT, false); + if (err != 0) + return err; + + /* buffer length offset to read return data */ + offset = sizeof(struct txgbe_hic_i2c_read) >> 2; + dword_len = round_up(length, 4) >> 2; + + for (i = 0; i < dword_len; i++) { + value = rd32a(wx, WX_FW2SW_MBOX, i + offset); + le32_to_cpus(&value); + + memcpy(data, &value, 4); + data += 4; + } + + return 0; +} + +static int txgbe_identify_module_hostif(struct wx *wx, + struct txgbe_hic_get_module_info *buffer) +{ + buffer->hdr.cmd = FW_GET_MODULE_INFO_CMD; + buffer->hdr.buf_len = sizeof(struct txgbe_hic_get_module_info) - + sizeof(struct wx_hic_hdr); + buffer->hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED; + return wx_host_interface_command(wx, (u32 *)buffer, - sizeof(struct txgbe_hic_i2c_read), + sizeof(struct txgbe_hic_get_module_info), WX_HI_COMMAND_TIMEOUT, true); } @@ -90,12 +129,18 @@ static int txgbe_set_phy_link_hostif(struct wx *wx, int speed, int autoneg, int buffer.hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED; switch (speed) { + case SPEED_40000: + buffer.speed = TXGBE_LINK_SPEED_40GB_FULL; + break; case SPEED_25000: buffer.speed = TXGBE_LINK_SPEED_25GB_FULL; break; case SPEED_10000: buffer.speed = TXGBE_LINK_SPEED_10GB_FULL; break; + default: + buffer.speed = TXGBE_LINK_SPEED_UNKNOWN; + break; } buffer.fec_mode = TXGBE_PHY_FEC_AUTO; @@ -106,28 +151,33 @@ static int txgbe_set_phy_link_hostif(struct wx *wx, int speed, int autoneg, int WX_HI_COMMAND_TIMEOUT, true); } -static void txgbe_get_link_capabilities(struct wx *wx) +static void txgbe_get_link_capabilities(struct wx *wx, int *speed, + int *autoneg, int *duplex) { struct txgbe *txgbe = wx->priv; - if (test_bit(PHY_INTERFACE_MODE_25GBASER, txgbe->sfp_interfaces)) - wx->adv_speed = SPEED_25000; - else if (test_bit(PHY_INTERFACE_MODE_10GBASER, txgbe->sfp_interfaces)) - wx->adv_speed = SPEED_10000; + if (test_bit(PHY_INTERFACE_MODE_XLGMII, txgbe->link_interfaces)) + *speed = SPEED_40000; + else if (test_bit(PHY_INTERFACE_MODE_25GBASER, txgbe->link_interfaces)) + *speed = SPEED_25000; + else if (test_bit(PHY_INTERFACE_MODE_10GBASER, txgbe->link_interfaces)) + *speed = SPEED_10000; else - wx->adv_speed = SPEED_UNKNOWN; + *speed = SPEED_UNKNOWN; - wx->adv_duplex = wx->adv_speed == SPEED_UNKNOWN ? - DUPLEX_HALF : DUPLEX_FULL; + *autoneg = phylink_test(txgbe->advertising, Autoneg); + *duplex = *speed == SPEED_UNKNOWN ? DUPLEX_HALF : DUPLEX_FULL; } -static void txgbe_get_phy_link(struct wx *wx, int *speed) +static void txgbe_get_mac_link(struct wx *wx, int *speed) { u32 status; status = rd32(wx, TXGBE_CFG_PORT_ST); if (!(status & TXGBE_CFG_PORT_ST_LINK_UP)) *speed = SPEED_UNKNOWN; + else if (status & TXGBE_CFG_PORT_ST_LINK_AML_40G) + *speed = SPEED_40000; else if (status & TXGBE_CFG_PORT_ST_LINK_AML_25G) *speed = SPEED_25000; else if (status & TXGBE_CFG_PORT_ST_LINK_AML_10G) @@ -138,23 +188,11 @@ static void txgbe_get_phy_link(struct wx *wx, int *speed) int txgbe_set_phy_link(struct wx *wx) { - int speed, err; - u32 gpio; + int speed, autoneg, duplex, err; - /* Check RX signal */ - gpio = rd32(wx, WX_GPIO_EXT); - if (gpio & TXGBE_GPIOBIT_3) - return -ENODEV; + txgbe_get_link_capabilities(wx, &speed, &autoneg, &duplex); - txgbe_get_link_capabilities(wx); - if (wx->adv_speed == SPEED_UNKNOWN) - return -ENODEV; - - txgbe_get_phy_link(wx, &speed); - if (speed == wx->adv_speed) - return 0; - - err = txgbe_set_phy_link_hostif(wx, wx->adv_speed, 0, wx->adv_duplex); + err = txgbe_set_phy_link_hostif(wx, speed, autoneg, duplex); if (err) { wx_err(wx, "Failed to setup link\n"); return err; @@ -163,40 +201,128 @@ int txgbe_set_phy_link(struct wx *wx) return 0; } -static int txgbe_sfp_to_linkmodes(struct wx *wx, struct txgbe_sfp_id *id) +static int txgbe_sfp_to_linkmodes(struct wx *wx, struct txgbe_sff_id *id) { __ETHTOOL_DECLARE_LINK_MODE_MASK(modes) = { 0, }; DECLARE_PHY_INTERFACE_MASK(interfaces); struct txgbe *txgbe = wx->priv; - if (id->com_25g_code & (TXGBE_SFF_25GBASESR_CAPABLE | - TXGBE_SFF_25GBASEER_CAPABLE | - TXGBE_SFF_25GBASELR_CAPABLE)) { - phylink_set(modes, 25000baseSR_Full); + if (id->cable_tech & TXGBE_SFF_DA_PASSIVE_CABLE) { + txgbe->link_port = PORT_DA; + phylink_set(modes, Autoneg); + if (id->com_25g_code == TXGBE_SFF_25GBASECR_91FEC || + id->com_25g_code == TXGBE_SFF_25GBASECR_74FEC || + id->com_25g_code == TXGBE_SFF_25GBASECR_NOFEC) { + phylink_set(modes, 25000baseCR_Full); + phylink_set(modes, 10000baseCR_Full); + __set_bit(PHY_INTERFACE_MODE_25GBASER, interfaces); + __set_bit(PHY_INTERFACE_MODE_10GBASER, interfaces); + } else { + phylink_set(modes, 10000baseCR_Full); + __set_bit(PHY_INTERFACE_MODE_10GBASER, interfaces); + } + } else if (id->cable_tech & TXGBE_SFF_DA_ACTIVE_CABLE) { + txgbe->link_port = PORT_DA; + phylink_set(modes, Autoneg); + phylink_set(modes, 25000baseCR_Full); __set_bit(PHY_INTERFACE_MODE_25GBASER, interfaces); + } else { + if (id->com_25g_code == TXGBE_SFF_25GBASESR_CAPABLE || + id->com_25g_code == TXGBE_SFF_25GBASEER_CAPABLE || + id->com_25g_code == TXGBE_SFF_25GBASELR_CAPABLE) { + txgbe->link_port = PORT_FIBRE; + phylink_set(modes, 25000baseSR_Full); + __set_bit(PHY_INTERFACE_MODE_25GBASER, interfaces); + } + if (id->com_10g_code & TXGBE_SFF_10GBASESR_CAPABLE) { + txgbe->link_port = PORT_FIBRE; + phylink_set(modes, 10000baseSR_Full); + __set_bit(PHY_INTERFACE_MODE_10GBASER, interfaces); + } + if (id->com_10g_code & TXGBE_SFF_10GBASELR_CAPABLE) { + txgbe->link_port = PORT_FIBRE; + phylink_set(modes, 10000baseLR_Full); + __set_bit(PHY_INTERFACE_MODE_10GBASER, interfaces); + } } - if (id->com_10g_code & TXGBE_SFF_10GBASESR_CAPABLE) { - phylink_set(modes, 10000baseSR_Full); - __set_bit(PHY_INTERFACE_MODE_10GBASER, interfaces); + + if (phy_interface_empty(interfaces)) { + wx_err(wx, "unsupported SFP module\n"); + return -EINVAL; } - if (id->com_10g_code & TXGBE_SFF_10GBASELR_CAPABLE) { - phylink_set(modes, 10000baseLR_Full); + + phylink_set(modes, Pause); + phylink_set(modes, Asym_Pause); + phylink_set(modes, FIBRE); + + if (!linkmode_equal(txgbe->link_support, modes)) { + linkmode_copy(txgbe->link_support, modes); + phy_interface_and(txgbe->link_interfaces, + wx->phylink_config.supported_interfaces, + interfaces); + linkmode_copy(txgbe->advertising, modes); + + set_bit(WX_FLAG_NEED_LINK_CONFIG, wx->flags); + } + + return 0; +} + +static int txgbe_qsfp_to_linkmodes(struct wx *wx, struct txgbe_sff_id *id) +{ + __ETHTOOL_DECLARE_LINK_MODE_MASK(modes) = { 0, }; + DECLARE_PHY_INTERFACE_MASK(interfaces); + struct txgbe *txgbe = wx->priv; + + if (id->transceiver_type & TXGBE_SFF_ETHERNET_40G_CR4) { + txgbe->link_port = PORT_DA; + phylink_set(modes, Autoneg); + phylink_set(modes, 40000baseCR4_Full); + phylink_set(modes, 10000baseCR_Full); + __set_bit(PHY_INTERFACE_MODE_XLGMII, interfaces); __set_bit(PHY_INTERFACE_MODE_10GBASER, interfaces); } + if (id->transceiver_type & TXGBE_SFF_ETHERNET_40G_SR4) { + txgbe->link_port = PORT_FIBRE; + phylink_set(modes, 40000baseSR4_Full); + __set_bit(PHY_INTERFACE_MODE_XLGMII, interfaces); + } + if (id->transceiver_type & TXGBE_SFF_ETHERNET_40G_LR4) { + txgbe->link_port = PORT_FIBRE; + phylink_set(modes, 40000baseLR4_Full); + __set_bit(PHY_INTERFACE_MODE_XLGMII, interfaces); + } + if (id->transceiver_type & TXGBE_SFF_ETHERNET_40G_ACTIVE) { + txgbe->link_port = PORT_DA; + phylink_set(modes, Autoneg); + phylink_set(modes, 40000baseCR4_Full); + __set_bit(PHY_INTERFACE_MODE_XLGMII, interfaces); + } + if (id->transceiver_type & TXGBE_SFF_ETHERNET_RSRVD) { + if (id->sff_opt1 & TXGBE_SFF_ETHERNET_100G_CR4) { + txgbe->link_port = PORT_DA; + phylink_set(modes, Autoneg); + phylink_set(modes, 40000baseCR4_Full); + phylink_set(modes, 25000baseCR_Full); + phylink_set(modes, 10000baseCR_Full); + __set_bit(PHY_INTERFACE_MODE_XLGMII, interfaces); + __set_bit(PHY_INTERFACE_MODE_25GBASER, interfaces); + __set_bit(PHY_INTERFACE_MODE_10GBASER, interfaces); + } + } if (phy_interface_empty(interfaces)) { - wx_err(wx, "unsupported SFP module\n"); + wx_err(wx, "unsupported QSFP module\n"); return -EINVAL; } phylink_set(modes, Pause); phylink_set(modes, Asym_Pause); phylink_set(modes, FIBRE); - txgbe->link_port = PORT_FIBRE; - if (!linkmode_equal(txgbe->sfp_support, modes)) { - linkmode_copy(txgbe->sfp_support, modes); - phy_interface_and(txgbe->sfp_interfaces, + if (!linkmode_equal(txgbe->link_support, modes)) { + linkmode_copy(txgbe->link_support, modes); + phy_interface_and(txgbe->link_interfaces, wx->phylink_config.supported_interfaces, interfaces); linkmode_copy(txgbe->advertising, modes); @@ -207,47 +333,53 @@ static int txgbe_sfp_to_linkmodes(struct wx *wx, struct txgbe_sfp_id *id) return 0; } -int txgbe_identify_sfp(struct wx *wx) +int txgbe_identify_module(struct wx *wx) { - struct txgbe_hic_i2c_read buffer; - struct txgbe_sfp_id *id; + struct txgbe_hic_get_module_info buffer; + struct txgbe_sff_id *id; int err = 0; + u32 mod_abs; u32 gpio; + if (wx->mac.type == wx_mac_aml40) + mod_abs = TXGBE_GPIOBIT_4; + else + mod_abs = TXGBE_GPIOBIT_2; + gpio = rd32(wx, WX_GPIO_EXT); - if (gpio & TXGBE_GPIOBIT_2) + if (gpio & mod_abs) return -ENODEV; - err = txgbe_identify_sfp_hostif(wx, &buffer); + err = txgbe_identify_module_hostif(wx, &buffer); if (err) { - wx_err(wx, "Failed to identify SFP module\n"); + wx_err(wx, "Failed to identify module\n"); return err; } id = &buffer.id; - if (id->identifier != TXGBE_SFF_IDENTIFIER_SFP) { - wx_err(wx, "Invalid SFP module\n"); + if (id->identifier != TXGBE_SFF_IDENTIFIER_SFP && + id->identifier != TXGBE_SFF_IDENTIFIER_QSFP && + id->identifier != TXGBE_SFF_IDENTIFIER_QSFP_PLUS && + id->identifier != TXGBE_SFF_IDENTIFIER_QSFP28) { + wx_err(wx, "Invalid module\n"); return -ENODEV; } - err = txgbe_sfp_to_linkmodes(wx, id); - if (err) - return err; - - if (gpio & TXGBE_GPIOBIT_3) - set_bit(WX_FLAG_NEED_LINK_CONFIG, wx->flags); + if (id->transceiver_type == 0xFF) + return txgbe_sfp_to_linkmodes(wx, id); - return 0; + return txgbe_qsfp_to_linkmodes(wx, id); } void txgbe_setup_link(struct wx *wx) { struct txgbe *txgbe = wx->priv; - phy_interface_zero(txgbe->sfp_interfaces); - linkmode_zero(txgbe->sfp_support); + phy_interface_zero(txgbe->link_interfaces); + linkmode_zero(txgbe->link_support); - txgbe_identify_sfp(wx); + set_bit(WX_FLAG_NEED_MODULE_RESET, wx->flags); + wx_service_event_schedule(wx); } static void txgbe_get_link_state(struct phylink_config *config, @@ -256,7 +388,7 @@ static void txgbe_get_link_state(struct phylink_config *config, struct wx *wx = phylink_to_wx(config); int speed; - txgbe_get_phy_link(wx, &speed); + txgbe_get_mac_link(wx, &speed); state->link = speed != SPEED_UNKNOWN; state->speed = speed; state->duplex = state->link ? DUPLEX_FULL : DUPLEX_UNKNOWN; @@ -300,6 +432,9 @@ static void txgbe_mac_link_up_aml(struct phylink_config *config, txcfg &= ~TXGBE_AML_MAC_TX_CFG_SPEED_MASK; switch (speed) { + case SPEED_40000: + txcfg |= TXGBE_AML_MAC_TX_CFG_SPEED_40G; + break; case SPEED_25000: txcfg |= TXGBE_AML_MAC_TX_CFG_SPEED_25G; break; @@ -364,7 +499,18 @@ int txgbe_phylink_init_aml(struct txgbe *txgbe) MAC_SYM_PAUSE | MAC_ASYM_PAUSE; config->get_fixed_state = txgbe_get_link_state; - phy_mode = PHY_INTERFACE_MODE_25GBASER; + if (wx->mac.type == wx_mac_aml40) { + config->mac_capabilities |= MAC_40000FD; + phy_mode = PHY_INTERFACE_MODE_XLGMII; + __set_bit(PHY_INTERFACE_MODE_XLGMII, config->supported_interfaces); + state.speed = SPEED_40000; + state.duplex = DUPLEX_FULL; + } else { + phy_mode = PHY_INTERFACE_MODE_25GBASER; + state.speed = SPEED_25000; + state.duplex = DUPLEX_FULL; + } + __set_bit(PHY_INTERFACE_MODE_25GBASER, config->supported_interfaces); __set_bit(PHY_INTERFACE_MODE_10GBASER, config->supported_interfaces); @@ -372,8 +518,6 @@ int txgbe_phylink_init_aml(struct txgbe *txgbe) if (IS_ERR(phylink)) return PTR_ERR(phylink); - state.speed = SPEED_25000; - state.duplex = DUPLEX_FULL; err = phylink_set_fixed_link(phylink, &state); if (err) { wx_err(wx, "Failed to set fixed link\n"); diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_aml.h b/drivers/net/ethernet/wangxun/txgbe/txgbe_aml.h index 25d4971ca0d9..4f6df0ee860b 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_aml.h +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_aml.h @@ -7,8 +7,11 @@ void txgbe_gpio_init_aml(struct wx *wx); irqreturn_t txgbe_gpio_irq_handler_aml(int irq, void *data); int txgbe_test_hostif(struct wx *wx); +int txgbe_read_eeprom_hostif(struct wx *wx, + struct txgbe_hic_i2c_read *buffer, + u32 length, u8 *data); int txgbe_set_phy_link(struct wx *wx); -int txgbe_identify_sfp(struct wx *wx); +int txgbe_identify_module(struct wx *wx); void txgbe_setup_link(struct wx *wx); int txgbe_phylink_init_aml(struct txgbe *txgbe); diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c index e285b088c7b2..f3cb00109529 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c @@ -10,6 +10,7 @@ #include "../libwx/wx_lib.h" #include "txgbe_type.h" #include "txgbe_fdir.h" +#include "txgbe_aml.h" #include "txgbe_ethtool.h" int txgbe_get_link_ksettings(struct net_device *netdev, @@ -19,9 +20,6 @@ int txgbe_get_link_ksettings(struct net_device *netdev, struct txgbe *txgbe = wx->priv; int err; - if (wx->mac.type == wx_mac_aml40) - return -EOPNOTSUPP; - err = wx_get_link_ksettings(netdev, cmd); if (err) return err; @@ -30,8 +28,9 @@ int txgbe_get_link_ksettings(struct net_device *netdev, return 0; cmd->base.port = txgbe->link_port; - cmd->base.autoneg = AUTONEG_DISABLE; - linkmode_copy(cmd->link_modes.supported, txgbe->sfp_support); + cmd->base.autoneg = phylink_test(txgbe->advertising, Autoneg) ? + AUTONEG_ENABLE : AUTONEG_DISABLE; + linkmode_copy(cmd->link_modes.supported, txgbe->link_support); linkmode_copy(cmd->link_modes.advertising, txgbe->advertising); return 0; @@ -536,6 +535,34 @@ static int txgbe_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd) return ret; } +static int +txgbe_get_module_eeprom_by_page(struct net_device *netdev, + const struct ethtool_module_eeprom *page_data, + struct netlink_ext_ack *extack) +{ + struct wx *wx = netdev_priv(netdev); + struct txgbe_hic_i2c_read buffer; + int err; + + if (!test_bit(WX_FLAG_SWFW_RING, wx->flags)) + return -EOPNOTSUPP; + + buffer.length = cpu_to_be32(page_data->length); + buffer.offset = cpu_to_be32(page_data->offset); + buffer.page = page_data->page; + buffer.bank = page_data->bank; + buffer.i2c_address = page_data->i2c_address; + + err = txgbe_read_eeprom_hostif(wx, &buffer, page_data->length, + page_data->data); + if (err) { + wx_err(wx, "Failed to read module EEPROM\n"); + return err; + } + + return page_data->length; +} + static const struct ethtool_ops txgbe_ethtool_ops = { .supported_coalesce_params = ETHTOOL_COALESCE_USECS | ETHTOOL_COALESCE_TX_MAX_FRAMES_IRQ | @@ -570,6 +597,7 @@ static const struct ethtool_ops txgbe_ethtool_ops = { .set_msglevel = wx_set_msglevel, .get_ts_info = wx_get_ts_info, .get_ts_stats = wx_get_ptp_stats, + .get_module_eeprom_by_page = txgbe_get_module_eeprom_by_page, }; void txgbe_set_ethtool_ops(struct net_device *netdev) diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_irq.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_irq.c index 3885283681ec..aa14958d439a 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_irq.c +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_irq.c @@ -23,7 +23,7 @@ void txgbe_irq_enable(struct wx *wx, bool queues) { u32 misc_ien = TXGBE_PX_MISC_IEN_MASK; - if (wx->mac.type == wx_mac_aml) { + if (wx->mac.type != wx_mac_sp) { misc_ien |= TXGBE_PX_MISC_GPIO; txgbe_gpio_init_aml(wx); } @@ -201,10 +201,7 @@ static void txgbe_del_irq_domain(struct txgbe *txgbe) void txgbe_free_misc_irq(struct txgbe *txgbe) { - if (txgbe->wx->mac.type == wx_mac_aml40) - return; - - if (txgbe->wx->mac.type == wx_mac_aml) + if (txgbe->wx->mac.type != wx_mac_sp) free_irq(txgbe->gpio_irq, txgbe); free_irq(txgbe->link_irq, txgbe); @@ -219,9 +216,6 @@ int txgbe_setup_misc_irq(struct txgbe *txgbe) struct wx *wx = txgbe->wx; int hwirq, err; - if (wx->mac.type == wx_mac_aml40) - goto skip_sp_irq; - txgbe->misc.nirqs = TXGBE_IRQ_MAX; txgbe->misc.domain = irq_domain_create_simple(NULL, txgbe->misc.nirqs, 0, &txgbe_misc_irq_domain_ops, txgbe); diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c index c4c4d70d8466..0de051450a82 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c @@ -89,21 +89,21 @@ static int txgbe_enumerate_functions(struct wx *wx) return physfns; } -static void txgbe_sfp_detection_subtask(struct wx *wx) +static void txgbe_module_detection_subtask(struct wx *wx) { int err; - if (!test_bit(WX_FLAG_NEED_SFP_RESET, wx->flags)) + if (!test_bit(WX_FLAG_NEED_MODULE_RESET, wx->flags)) return; - /* wait for SFP module ready */ + /* wait for SFF module ready */ msleep(200); - err = txgbe_identify_sfp(wx); + err = txgbe_identify_module(wx); if (err) return; - clear_bit(WX_FLAG_NEED_SFP_RESET, wx->flags); + clear_bit(WX_FLAG_NEED_MODULE_RESET, wx->flags); } static void txgbe_link_config_subtask(struct wx *wx) @@ -128,7 +128,7 @@ static void txgbe_service_task(struct work_struct *work) { struct wx *wx = container_of(work, struct wx, service_task); - txgbe_sfp_detection_subtask(wx); + txgbe_module_detection_subtask(wx); txgbe_link_config_subtask(wx); wx_service_event_complete(wx); @@ -144,7 +144,6 @@ static void txgbe_init_service(struct wx *wx) static void txgbe_up_complete(struct wx *wx) { struct net_device *netdev = wx->netdev; - u32 reg; wx_control_hw(wx, true); wx_configure_vectors(wx); @@ -155,12 +154,8 @@ static void txgbe_up_complete(struct wx *wx) switch (wx->mac.type) { case wx_mac_aml40: - reg = rd32(wx, TXGBE_AML_MAC_TX_CFG); - reg &= ~TXGBE_AML_MAC_TX_CFG_SPEED_MASK; - reg |= TXGBE_AML_MAC_TX_CFG_SPEED_40G; - wr32(wx, WX_MAC_TX_CFG, reg); - txgbe_enable_sec_tx_path(wx); - netif_carrier_on(wx->netdev); + txgbe_setup_link(wx); + phylink_start(wx->phylink); break; case wx_mac_aml: /* Enable TX laser */ @@ -276,7 +271,7 @@ void txgbe_down(struct wx *wx) switch (wx->mac.type) { case wx_mac_aml40: - netif_carrier_off(wx->netdev); + phylink_stop(wx->phylink); break; case wx_mac_aml: phylink_stop(wx->phylink); @@ -398,6 +393,7 @@ static int txgbe_sw_init(struct wx *wx) wx->configure_fdir = txgbe_configure_fdir; set_bit(WX_FLAG_RSC_CAPABLE, wx->flags); + set_bit(WX_FLAG_RSC_ENABLED, wx->flags); set_bit(WX_FLAG_MULTI_64_FUNC, wx->flags); /* enable itr by default in dynamic mode */ @@ -423,6 +419,8 @@ static int txgbe_sw_init(struct wx *wx) break; case wx_mac_aml: case wx_mac_aml40: + set_bit(WX_FLAG_RX_MERGE_ENABLED, wx->flags); + set_bit(WX_FLAG_TXHEAD_WB_ENABLED, wx->flags); set_bit(WX_FLAG_SWFW_RING, wx->flags); wx->swfw_index = 0; break; @@ -801,6 +799,8 @@ static int txgbe_probe(struct pci_dev *pdev, netdev->features |= NETIF_F_HIGHDMA; netdev->hw_features |= NETIF_F_GRO; netdev->features |= NETIF_F_GRO; + netdev->hw_features |= NETIF_F_LRO; + netdev->features |= NETIF_F_LRO; netdev->features |= NETIF_F_RX_UDP_TUNNEL_PORT; netdev->priv_flags |= IFF_UNICAST_FLT; diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c index 03f1b9bc604d..8ea7aa07ae4e 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c @@ -579,7 +579,6 @@ int txgbe_init_phy(struct txgbe *txgbe) switch (wx->mac.type) { case wx_mac_aml40: - return 0; case wx_mac_aml: return txgbe_phylink_init_aml(txgbe); case wx_mac_sp: @@ -653,7 +652,6 @@ void txgbe_remove_phy(struct txgbe *txgbe) { switch (txgbe->wx->mac.type) { case wx_mac_aml40: - return; case wx_mac_aml: phylink_destroy(txgbe->wx->phylink); return; diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h b/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h index 41915d7dd372..82433e9cb0e3 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h @@ -98,6 +98,7 @@ /* Port cfg registers */ #define TXGBE_CFG_PORT_ST 0x14404 #define TXGBE_CFG_PORT_ST_LINK_UP BIT(0) +#define TXGBE_CFG_PORT_ST_LINK_AML_40G BIT(2) #define TXGBE_CFG_PORT_ST_LINK_AML_25G BIT(3) #define TXGBE_CFG_PORT_ST_LINK_AML_10G BIT(4) #define TXGBE_CFG_VXLAN 0x14410 @@ -314,10 +315,15 @@ void txgbe_up(struct wx *wx); int txgbe_setup_tc(struct net_device *dev, u8 tc); void txgbe_do_reset(struct net_device *netdev); +#define TXGBE_LINK_SPEED_UNKNOWN 0 #define TXGBE_LINK_SPEED_10GB_FULL 4 #define TXGBE_LINK_SPEED_25GB_FULL 0x10 +#define TXGBE_LINK_SPEED_40GB_FULL 0x20 #define TXGBE_SFF_IDENTIFIER_SFP 0x3 +#define TXGBE_SFF_IDENTIFIER_QSFP 0xC +#define TXGBE_SFF_IDENTIFIER_QSFP_PLUS 0xD +#define TXGBE_SFF_IDENTIFIER_QSFP28 0x11 #define TXGBE_SFF_DA_PASSIVE_CABLE 0x4 #define TXGBE_SFF_DA_ACTIVE_CABLE 0x8 #define TXGBE_SFF_DA_SPEC_ACTIVE_LIMIT 0x4 @@ -330,6 +336,12 @@ void txgbe_do_reset(struct net_device *netdev); #define TXGBE_SFF_25GBASECR_91FEC 0xB #define TXGBE_SFF_25GBASECR_74FEC 0xC #define TXGBE_SFF_25GBASECR_NOFEC 0xD +#define TXGBE_SFF_ETHERNET_RSRVD BIT(7) +#define TXGBE_SFF_ETHERNET_40G_CR4 BIT(3) +#define TXGBE_SFF_ETHERNET_40G_SR4 BIT(2) +#define TXGBE_SFF_ETHERNET_40G_LR4 BIT(1) +#define TXGBE_SFF_ETHERNET_40G_ACTIVE BIT(0) +#define TXGBE_SFF_ETHERNET_100G_CR4 0xB #define TXGBE_PHY_FEC_RS BIT(0) #define TXGBE_PHY_FEC_BASER BIT(1) @@ -340,9 +352,10 @@ void txgbe_do_reset(struct net_device *netdev); #define FW_PHY_GET_LINK_CMD 0xC0 #define FW_PHY_SET_LINK_CMD 0xC1 -#define FW_READ_SFP_INFO_CMD 0xC5 +#define FW_GET_MODULE_INFO_CMD 0xC5 +#define FW_READ_EEPROM_CMD 0xC6 -struct txgbe_sfp_id { +struct txgbe_sff_id { u8 identifier; /* A0H 0x00 */ u8 com_1g_code; /* A0H 0x06 */ u8 com_10g_code; /* A0H 0x03 */ @@ -352,12 +365,14 @@ struct txgbe_sfp_id { u8 vendor_oui0; /* A0H 0x25 */ u8 vendor_oui1; /* A0H 0x26 */ u8 vendor_oui2; /* A0H 0x27 */ - u8 reserved[3]; + u8 transceiver_type; /* A0H 0x83 */ + u8 sff_opt1; /* A0H 0xC0 */ + u8 reserved[5]; }; -struct txgbe_hic_i2c_read { +struct txgbe_hic_get_module_info { struct wx_hic_hdr hdr; - struct txgbe_sfp_id id; + struct txgbe_sff_id id; }; struct txgbe_hic_ephy_setlink { @@ -380,6 +395,16 @@ struct txgbe_hic_ephy_getlink { u8 resv[6]; }; +struct txgbe_hic_i2c_read { + struct wx_hic_hdr hdr; + __be32 offset; + __be32 length; + u8 page; + u8 bank; + u8 i2c_address; + u8 resv; +}; + #define NODE_PROP(_NAME, _PROP) \ (const struct software_node) { \ .name = _NAME, \ @@ -448,8 +473,8 @@ struct txgbe { int fdir_filter_count; spinlock_t fdir_perfect_lock; /* spinlock for FDIR */ - DECLARE_PHY_INTERFACE_MASK(sfp_interfaces); - __ETHTOOL_DECLARE_LINK_MODE_MASK(sfp_support); + DECLARE_PHY_INTERFACE_MASK(link_interfaces); + __ETHTOOL_DECLARE_LINK_MODE_MASK(link_support); __ETHTOOL_DECLARE_LINK_MODE_MASK(advertising); u8 link_port; }; diff --git a/drivers/net/ethernet/wangxun/txgbevf/txgbevf_main.c b/drivers/net/ethernet/wangxun/txgbevf/txgbevf_main.c index 72663e3c4205..37e4ec487afd 100644 --- a/drivers/net/ethernet/wangxun/txgbevf/txgbevf_main.c +++ b/drivers/net/ethernet/wangxun/txgbevf/txgbevf_main.c @@ -157,6 +157,18 @@ static int txgbevf_sw_init(struct wx *wx) wx->set_num_queues = txgbevf_set_num_queues; + switch (wx->mac.type) { + case wx_mac_sp: + break; + case wx_mac_aml: + case wx_mac_aml40: + set_bit(WX_FLAG_RX_MERGE_ENABLED, wx->flags); + set_bit(WX_FLAG_TXHEAD_WB_ENABLED, wx->flags); + break; + default: + break; + } + return 0; err_reset_hw: kfree(wx->vfinfo); |
