forked from Minki/linux
Merge branch 'hns3-next'
Peng Li says: ==================== add some features and fix some bugs for HNS3 driver This patchset adds some new feature support and fixes some bugs: [Patch 1/17 - 5/17] add the support to modify/query the tqp number through ethtool -L/l command, and also fix some related bugs for change tqp number. [Patch 6/17 - 9-17] add support vlan tag offload on tx&&rx direction for pf, and fix some related bugs. [patch 10/17 - 11/17] fix bugs for auto negotiation. [patch 12/17] adds support for ethtool command set_pauseparam. [patch 13/17 - 14/17] add support to update flow control settings after autoneg. [patch 15/17 - 17/17] fix some other bugs in net-next. --- Change Log: V4 -> V5: 1. change the name spelling of Peng Li. V3 -> V4: 1. change the name spelling of Mingguang Qu and Jian Shen. V2 -> V3: 1. order local variables requested by David Miller. 2. use "int" for index iteration loops requested by David Miller. V1 -> V2: 1. fix the comments from Sergei Shtylyov. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
a8038befce
@ -278,6 +278,8 @@ struct hnae3_ae_dev {
|
||||
* Set vlan filter config of Ports
|
||||
* set_vf_vlan_filter()
|
||||
* Set vlan filter config of vf
|
||||
* enable_hw_strip_rxvtag()
|
||||
* Enable/disable hardware strip vlan tag of packets received
|
||||
*/
|
||||
struct hnae3_ae_ops {
|
||||
int (*init_ae_dev)(struct hnae3_ae_dev *ae_dev);
|
||||
@ -384,8 +386,16 @@ struct hnae3_ae_ops {
|
||||
u16 vlan_id, bool is_kill);
|
||||
int (*set_vf_vlan_filter)(struct hnae3_handle *handle, int vfid,
|
||||
u16 vlan, u8 qos, __be16 proto);
|
||||
int (*enable_hw_strip_rxvtag)(struct hnae3_handle *handle, bool enable);
|
||||
void (*reset_event)(struct hnae3_handle *handle,
|
||||
enum hnae3_reset_type reset);
|
||||
void (*get_channels)(struct hnae3_handle *handle,
|
||||
struct ethtool_channels *ch);
|
||||
void (*get_tqps_and_rss_info)(struct hnae3_handle *h,
|
||||
u16 *free_tqps, u16 *max_rss_size);
|
||||
int (*set_channels)(struct hnae3_handle *handle, u32 new_tqps_num);
|
||||
void (*get_flowctrl_adv)(struct hnae3_handle *handle,
|
||||
u32 *flowctrl_adv);
|
||||
};
|
||||
|
||||
struct hnae3_dcb_ops {
|
||||
|
@ -723,6 +723,58 @@ static void hns3_set_txbd_baseinfo(u16 *bdtp_fe_sc_vld_ra_ri, int frag_end)
|
||||
hnae_set_field(*bdtp_fe_sc_vld_ra_ri, HNS3_TXD_SC_M, HNS3_TXD_SC_S, 0);
|
||||
}
|
||||
|
||||
static int hns3_fill_desc_vtags(struct sk_buff *skb,
|
||||
struct hns3_enet_ring *tx_ring,
|
||||
u32 *inner_vlan_flag,
|
||||
u32 *out_vlan_flag,
|
||||
u16 *inner_vtag,
|
||||
u16 *out_vtag)
|
||||
{
|
||||
#define HNS3_TX_VLAN_PRIO_SHIFT 13
|
||||
|
||||
if (skb->protocol == htons(ETH_P_8021Q) &&
|
||||
!(tx_ring->tqp->handle->kinfo.netdev->features &
|
||||
NETIF_F_HW_VLAN_CTAG_TX)) {
|
||||
/* When HW VLAN acceleration is turned off, and the stack
|
||||
* sets the protocol to 802.1q, the driver just need to
|
||||
* set the protocol to the encapsulated ethertype.
|
||||
*/
|
||||
skb->protocol = vlan_get_protocol(skb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (skb_vlan_tag_present(skb)) {
|
||||
u16 vlan_tag;
|
||||
|
||||
vlan_tag = skb_vlan_tag_get(skb);
|
||||
vlan_tag |= (skb->priority & 0x7) << HNS3_TX_VLAN_PRIO_SHIFT;
|
||||
|
||||
/* Based on hw strategy, use out_vtag in two layer tag case,
|
||||
* and use inner_vtag in one tag case.
|
||||
*/
|
||||
if (skb->protocol == htons(ETH_P_8021Q)) {
|
||||
hnae_set_bit(*out_vlan_flag, HNS3_TXD_OVLAN_B, 1);
|
||||
*out_vtag = vlan_tag;
|
||||
} else {
|
||||
hnae_set_bit(*inner_vlan_flag, HNS3_TXD_VLAN_B, 1);
|
||||
*inner_vtag = vlan_tag;
|
||||
}
|
||||
} else if (skb->protocol == htons(ETH_P_8021Q)) {
|
||||
struct vlan_ethhdr *vhdr;
|
||||
int rc;
|
||||
|
||||
rc = skb_cow_head(skb, 0);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
vhdr = (struct vlan_ethhdr *)skb->data;
|
||||
vhdr->h_vlan_TCI |= cpu_to_be16((skb->priority & 0x7)
|
||||
<< HNS3_TX_VLAN_PRIO_SHIFT);
|
||||
}
|
||||
|
||||
skb->protocol = vlan_get_protocol(skb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hns3_fill_desc(struct hns3_enet_ring *ring, void *priv,
|
||||
int size, dma_addr_t dma, int frag_end,
|
||||
enum hns_desc_type type)
|
||||
@ -733,6 +785,8 @@ static int hns3_fill_desc(struct hns3_enet_ring *ring, void *priv,
|
||||
u16 bdtp_fe_sc_vld_ra_ri = 0;
|
||||
u32 type_cs_vlan_tso = 0;
|
||||
struct sk_buff *skb;
|
||||
u16 inner_vtag = 0;
|
||||
u16 out_vtag = 0;
|
||||
u32 paylen = 0;
|
||||
u16 mss = 0;
|
||||
__be16 protocol;
|
||||
@ -756,15 +810,16 @@ static int hns3_fill_desc(struct hns3_enet_ring *ring, void *priv,
|
||||
skb = (struct sk_buff *)priv;
|
||||
paylen = skb->len;
|
||||
|
||||
ret = hns3_fill_desc_vtags(skb, ring, &type_cs_vlan_tso,
|
||||
&ol_type_vlan_len_msec,
|
||||
&inner_vtag, &out_vtag);
|
||||
if (unlikely(ret))
|
||||
return ret;
|
||||
|
||||
if (skb->ip_summed == CHECKSUM_PARTIAL) {
|
||||
skb_reset_mac_len(skb);
|
||||
protocol = skb->protocol;
|
||||
|
||||
/* vlan packet*/
|
||||
if (protocol == htons(ETH_P_8021Q)) {
|
||||
protocol = vlan_get_protocol(skb);
|
||||
skb->protocol = protocol;
|
||||
}
|
||||
ret = hns3_get_l4_protocol(skb, &ol4_proto, &il4_proto);
|
||||
if (ret)
|
||||
return ret;
|
||||
@ -790,6 +845,8 @@ static int hns3_fill_desc(struct hns3_enet_ring *ring, void *priv,
|
||||
cpu_to_le32(type_cs_vlan_tso);
|
||||
desc->tx.paylen = cpu_to_le32(paylen);
|
||||
desc->tx.mss = cpu_to_le16(mss);
|
||||
desc->tx.vlan_tag = cpu_to_le16(inner_vtag);
|
||||
desc->tx.outer_vlan_tag = cpu_to_le16(out_vtag);
|
||||
}
|
||||
|
||||
/* move ring pointer to next.*/
|
||||
@ -1032,6 +1089,9 @@ static int hns3_nic_set_features(struct net_device *netdev,
|
||||
netdev_features_t features)
|
||||
{
|
||||
struct hns3_nic_priv *priv = netdev_priv(netdev);
|
||||
struct hnae3_handle *h = priv->ae_handle;
|
||||
netdev_features_t changed;
|
||||
int ret;
|
||||
|
||||
if (features & (NETIF_F_TSO | NETIF_F_TSO6)) {
|
||||
priv->ops.fill_desc = hns3_fill_desc_tso;
|
||||
@ -1041,6 +1101,17 @@ static int hns3_nic_set_features(struct net_device *netdev,
|
||||
priv->ops.maybe_stop_tx = hns3_nic_maybe_stop_tx;
|
||||
}
|
||||
|
||||
changed = netdev->features ^ features;
|
||||
if (changed & NETIF_F_HW_VLAN_CTAG_RX) {
|
||||
if (features & NETIF_F_HW_VLAN_CTAG_RX)
|
||||
ret = h->ae_algo->ops->enable_hw_strip_rxvtag(h, true);
|
||||
else
|
||||
ret = h->ae_algo->ops->enable_hw_strip_rxvtag(h, false);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
netdev->features = features;
|
||||
return 0;
|
||||
}
|
||||
@ -1492,6 +1563,7 @@ static void hns3_set_default_feature(struct net_device *netdev)
|
||||
|
||||
netdev->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
|
||||
NETIF_F_HW_VLAN_CTAG_FILTER |
|
||||
NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX |
|
||||
NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_GSO |
|
||||
NETIF_F_GRO | NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_GSO_GRE |
|
||||
NETIF_F_GSO_GRE_CSUM | NETIF_F_GSO_UDP_TUNNEL |
|
||||
@ -1506,6 +1578,7 @@ static void hns3_set_default_feature(struct net_device *netdev)
|
||||
|
||||
netdev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
|
||||
NETIF_F_HW_VLAN_CTAG_FILTER |
|
||||
NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX |
|
||||
NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_GSO |
|
||||
NETIF_F_GRO | NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_GSO_GRE |
|
||||
NETIF_F_GSO_GRE_CSUM | NETIF_F_GSO_UDP_TUNNEL |
|
||||
@ -2085,6 +2158,22 @@ static int hns3_handle_rx_bd(struct hns3_enet_ring *ring,
|
||||
|
||||
prefetchw(skb->data);
|
||||
|
||||
/* Based on hw strategy, the tag offloaded will be stored at
|
||||
* ot_vlan_tag in two layer tag case, and stored at vlan_tag
|
||||
* in one layer tag case.
|
||||
*/
|
||||
if (netdev->features & NETIF_F_HW_VLAN_CTAG_RX) {
|
||||
u16 vlan_tag;
|
||||
|
||||
vlan_tag = le16_to_cpu(desc->rx.ot_vlan_tag);
|
||||
if (!(vlan_tag & VLAN_VID_MASK))
|
||||
vlan_tag = le16_to_cpu(desc->rx.vlan_tag);
|
||||
if (vlan_tag & VLAN_VID_MASK)
|
||||
__vlan_hwaccel_put_tag(skb,
|
||||
htons(ETH_P_8021Q),
|
||||
vlan_tag);
|
||||
}
|
||||
|
||||
bnum = 1;
|
||||
if (length <= HNS3_RX_HEAD_SIZE) {
|
||||
memcpy(__skb_put(skb, length), va, ALIGN(length, sizeof(long)));
|
||||
@ -2651,6 +2740,19 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void hns3_put_ring_config(struct hns3_nic_priv *priv)
|
||||
{
|
||||
struct hnae3_handle *h = priv->ae_handle;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < h->kinfo.num_tqps; i++) {
|
||||
devm_kfree(priv->dev, priv->ring_data[i].ring);
|
||||
devm_kfree(priv->dev,
|
||||
priv->ring_data[i + h->kinfo.num_tqps].ring);
|
||||
}
|
||||
devm_kfree(priv->dev, priv->ring_data);
|
||||
}
|
||||
|
||||
static int hns3_alloc_ring_memory(struct hns3_enet_ring *ring)
|
||||
{
|
||||
int ret;
|
||||
@ -2787,8 +2889,12 @@ int hns3_uninit_all_ring(struct hns3_nic_priv *priv)
|
||||
h->ae_algo->ops->reset_queue(h, i);
|
||||
|
||||
hns3_fini_ring(priv->ring_data[i].ring);
|
||||
devm_kfree(priv->dev, priv->ring_data[i].ring);
|
||||
hns3_fini_ring(priv->ring_data[i + h->kinfo.num_tqps].ring);
|
||||
devm_kfree(priv->dev,
|
||||
priv->ring_data[i + h->kinfo.num_tqps].ring);
|
||||
}
|
||||
devm_kfree(priv->dev, priv->ring_data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -3162,6 +3268,115 @@ static int hns3_reset_notify(struct hnae3_handle *handle,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u16 hns3_get_max_available_channels(struct net_device *netdev)
|
||||
{
|
||||
struct hnae3_handle *h = hns3_get_handle(netdev);
|
||||
u16 free_tqps, max_rss_size, max_tqps;
|
||||
|
||||
h->ae_algo->ops->get_tqps_and_rss_info(h, &free_tqps, &max_rss_size);
|
||||
max_tqps = h->kinfo.num_tc * max_rss_size;
|
||||
|
||||
return min_t(u16, max_tqps, (free_tqps + h->kinfo.num_tqps));
|
||||
}
|
||||
|
||||
static int hns3_modify_tqp_num(struct net_device *netdev, u16 new_tqp_num)
|
||||
{
|
||||
struct hns3_nic_priv *priv = netdev_priv(netdev);
|
||||
struct hnae3_handle *h = hns3_get_handle(netdev);
|
||||
int ret;
|
||||
|
||||
ret = h->ae_algo->ops->set_channels(h, new_tqp_num);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = hns3_get_ring_config(priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = hns3_nic_init_vector_data(priv);
|
||||
if (ret)
|
||||
goto err_uninit_vector;
|
||||
|
||||
ret = hns3_init_all_ring(priv);
|
||||
if (ret)
|
||||
goto err_put_ring;
|
||||
|
||||
return 0;
|
||||
|
||||
err_put_ring:
|
||||
hns3_put_ring_config(priv);
|
||||
err_uninit_vector:
|
||||
hns3_nic_uninit_vector_data(priv);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int hns3_adjust_tqps_num(u8 num_tc, u32 new_tqp_num)
|
||||
{
|
||||
return (new_tqp_num / num_tc) * num_tc;
|
||||
}
|
||||
|
||||
int hns3_set_channels(struct net_device *netdev,
|
||||
struct ethtool_channels *ch)
|
||||
{
|
||||
struct hns3_nic_priv *priv = netdev_priv(netdev);
|
||||
struct hnae3_handle *h = hns3_get_handle(netdev);
|
||||
struct hnae3_knic_private_info *kinfo = &h->kinfo;
|
||||
bool if_running = netif_running(netdev);
|
||||
u32 new_tqp_num = ch->combined_count;
|
||||
u16 org_tqp_num;
|
||||
int ret;
|
||||
|
||||
if (ch->rx_count || ch->tx_count)
|
||||
return -EINVAL;
|
||||
|
||||
if (new_tqp_num > hns3_get_max_available_channels(netdev) ||
|
||||
new_tqp_num < kinfo->num_tc) {
|
||||
dev_err(&netdev->dev,
|
||||
"Change tqps fail, the tqp range is from %d to %d",
|
||||
kinfo->num_tc,
|
||||
hns3_get_max_available_channels(netdev));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
new_tqp_num = hns3_adjust_tqps_num(kinfo->num_tc, new_tqp_num);
|
||||
if (kinfo->num_tqps == new_tqp_num)
|
||||
return 0;
|
||||
|
||||
if (if_running)
|
||||
dev_close(netdev);
|
||||
|
||||
hns3_clear_all_ring(h);
|
||||
|
||||
ret = hns3_nic_uninit_vector_data(priv);
|
||||
if (ret) {
|
||||
dev_err(&netdev->dev,
|
||||
"Unbind vector with tqp fail, nothing is changed");
|
||||
goto open_netdev;
|
||||
}
|
||||
|
||||
hns3_uninit_all_ring(priv);
|
||||
|
||||
org_tqp_num = h->kinfo.num_tqps;
|
||||
ret = hns3_modify_tqp_num(netdev, new_tqp_num);
|
||||
if (ret) {
|
||||
ret = hns3_modify_tqp_num(netdev, org_tqp_num);
|
||||
if (ret) {
|
||||
/* If revert to old tqp failed, fatal error occurred */
|
||||
dev_err(&netdev->dev,
|
||||
"Revert to old tqp num fail, ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
dev_info(&netdev->dev,
|
||||
"Change tqp num fail, Revert to old tqp num");
|
||||
}
|
||||
|
||||
open_netdev:
|
||||
if (if_running)
|
||||
dev_open(netdev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct hnae3_client_ops client_ops = {
|
||||
.init_instance = hns3_client_init,
|
||||
.uninit_instance = hns3_client_uninit,
|
||||
|
@ -595,6 +595,8 @@ static inline void hns3_write_reg(void __iomem *base, u32 reg, u32 value)
|
||||
(((struct hns3_nic_priv *)netdev_priv(ndev))->ae_handle)
|
||||
|
||||
void hns3_ethtool_set_ops(struct net_device *netdev);
|
||||
int hns3_set_channels(struct net_device *netdev,
|
||||
struct ethtool_channels *ch);
|
||||
|
||||
bool hns3_clean_tx_ring(struct hns3_enet_ring *ring, int budget);
|
||||
int hns3_init_all_ring(struct hns3_nic_priv *priv);
|
||||
|
@ -559,10 +559,23 @@ static void hns3_get_pauseparam(struct net_device *netdev,
|
||||
¶m->rx_pause, ¶m->tx_pause);
|
||||
}
|
||||
|
||||
static int hns3_set_pauseparam(struct net_device *netdev,
|
||||
struct ethtool_pauseparam *param)
|
||||
{
|
||||
struct hnae3_handle *h = hns3_get_handle(netdev);
|
||||
|
||||
if (h->ae_algo->ops->set_pauseparam)
|
||||
return h->ae_algo->ops->set_pauseparam(h, param->autoneg,
|
||||
param->rx_pause,
|
||||
param->tx_pause);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static int hns3_get_link_ksettings(struct net_device *netdev,
|
||||
struct ethtool_link_ksettings *cmd)
|
||||
{
|
||||
struct hnae3_handle *h = hns3_get_handle(netdev);
|
||||
u32 flowctrl_adv = 0;
|
||||
u32 supported_caps;
|
||||
u32 advertised_caps;
|
||||
u8 media_type = HNAE3_MEDIA_TYPE_UNKNOWN;
|
||||
@ -638,6 +651,8 @@ static int hns3_get_link_ksettings(struct net_device *netdev,
|
||||
if (!cmd->base.autoneg)
|
||||
advertised_caps &= ~HNS3_LM_AUTONEG_BIT;
|
||||
|
||||
advertised_caps &= ~HNS3_LM_PAUSE_BIT;
|
||||
|
||||
/* now, map driver link modes to ethtool link modes */
|
||||
hns3_driv_to_eth_caps(supported_caps, cmd, false);
|
||||
hns3_driv_to_eth_caps(advertised_caps, cmd, true);
|
||||
@ -650,6 +665,18 @@ static int hns3_get_link_ksettings(struct net_device *netdev,
|
||||
/* 4.mdio_support */
|
||||
cmd->base.mdio_support = ETH_MDIO_SUPPORTS_C22;
|
||||
|
||||
/* 5.get flow control setttings */
|
||||
if (h->ae_algo->ops->get_flowctrl_adv)
|
||||
h->ae_algo->ops->get_flowctrl_adv(h, &flowctrl_adv);
|
||||
|
||||
if (flowctrl_adv & ADVERTISED_Pause)
|
||||
ethtool_link_ksettings_add_link_mode(cmd, advertising,
|
||||
Pause);
|
||||
|
||||
if (flowctrl_adv & ADVERTISED_Asym_Pause)
|
||||
ethtool_link_ksettings_add_link_mode(cmd, advertising,
|
||||
Asym_Pause);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -730,7 +757,7 @@ static int hns3_get_rxnfc(struct net_device *netdev,
|
||||
|
||||
switch (cmd->cmd) {
|
||||
case ETHTOOL_GRXRINGS:
|
||||
cmd->data = h->kinfo.num_tc * h->kinfo.rss_size;
|
||||
cmd->data = h->kinfo.rss_size;
|
||||
break;
|
||||
case ETHTOOL_GRXFH:
|
||||
return h->ae_algo->ops->get_rss_tuple(h, cmd);
|
||||
@ -849,6 +876,15 @@ static int hns3_nway_reset(struct net_device *netdev)
|
||||
return genphy_restart_aneg(phy);
|
||||
}
|
||||
|
||||
void hns3_get_channels(struct net_device *netdev,
|
||||
struct ethtool_channels *ch)
|
||||
{
|
||||
struct hnae3_handle *h = hns3_get_handle(netdev);
|
||||
|
||||
if (h->ae_algo->ops->get_channels)
|
||||
h->ae_algo->ops->get_channels(h, ch);
|
||||
}
|
||||
|
||||
static const struct ethtool_ops hns3vf_ethtool_ops = {
|
||||
.get_drvinfo = hns3_get_drvinfo,
|
||||
.get_ringparam = hns3_get_ringparam,
|
||||
@ -871,6 +907,7 @@ static const struct ethtool_ops hns3_ethtool_ops = {
|
||||
.get_ringparam = hns3_get_ringparam,
|
||||
.set_ringparam = hns3_set_ringparam,
|
||||
.get_pauseparam = hns3_get_pauseparam,
|
||||
.set_pauseparam = hns3_set_pauseparam,
|
||||
.get_strings = hns3_get_strings,
|
||||
.get_ethtool_stats = hns3_get_stats,
|
||||
.get_sset_count = hns3_get_sset_count,
|
||||
@ -883,6 +920,8 @@ static const struct ethtool_ops hns3_ethtool_ops = {
|
||||
.get_link_ksettings = hns3_get_link_ksettings,
|
||||
.set_link_ksettings = hns3_set_link_ksettings,
|
||||
.nway_reset = hns3_nway_reset,
|
||||
.get_channels = hns3_get_channels,
|
||||
.set_channels = hns3_set_channels,
|
||||
};
|
||||
|
||||
void hns3_ethtool_set_ops(struct net_device *netdev)
|
||||
|
@ -180,6 +180,10 @@ enum hclge_opcode_type {
|
||||
/* Promisuous mode command */
|
||||
HCLGE_OPC_CFG_PROMISC_MODE = 0x0E01,
|
||||
|
||||
/* Vlan offload command */
|
||||
HCLGE_OPC_VLAN_PORT_TX_CFG = 0x0F01,
|
||||
HCLGE_OPC_VLAN_PORT_RX_CFG = 0x0F02,
|
||||
|
||||
/* Interrupts cmd */
|
||||
HCLGE_OPC_ADD_RING_TO_VECTOR = 0x1503,
|
||||
HCLGE_OPC_DEL_RING_TO_VECTOR = 0x1504,
|
||||
@ -191,6 +195,7 @@ enum hclge_opcode_type {
|
||||
HCLGE_OPC_MAC_VLAN_INSERT = 0x1003,
|
||||
HCLGE_OPC_MAC_ETHTYPE_ADD = 0x1010,
|
||||
HCLGE_OPC_MAC_ETHTYPE_REMOVE = 0x1011,
|
||||
HCLGE_OPC_MAC_VLAN_MASK_SET = 0x1012,
|
||||
|
||||
/* Multicast linear table cmd */
|
||||
HCLGE_OPC_MTA_MAC_MODE_CFG = 0x1020,
|
||||
@ -399,6 +404,8 @@ struct hclge_pf_res_cmd {
|
||||
#define HCLGE_CFG_MAC_ADDR_H_M GENMASK(15, 0)
|
||||
#define HCLGE_CFG_DEFAULT_SPEED_S 16
|
||||
#define HCLGE_CFG_DEFAULT_SPEED_M GENMASK(23, 16)
|
||||
#define HCLGE_CFG_RSS_SIZE_S 24
|
||||
#define HCLGE_CFG_RSS_SIZE_M GENMASK(31, 24)
|
||||
|
||||
struct hclge_cfg_param_cmd {
|
||||
__le32 offset;
|
||||
@ -587,6 +594,15 @@ struct hclge_mac_vlan_tbl_entry_cmd {
|
||||
u8 rsv2[6];
|
||||
};
|
||||
|
||||
#define HCLGE_VLAN_MASK_EN_B 0x0
|
||||
struct hclge_mac_vlan_mask_entry_cmd {
|
||||
u8 rsv0[2];
|
||||
u8 vlan_mask;
|
||||
u8 rsv1;
|
||||
u8 mac_mask[6];
|
||||
u8 rsv2[14];
|
||||
};
|
||||
|
||||
#define HCLGE_CFG_MTA_MAC_SEL_S 0x0
|
||||
#define HCLGE_CFG_MTA_MAC_SEL_M GENMASK(1, 0)
|
||||
#define HCLGE_CFG_MTA_MAC_EN_B 0x7
|
||||
@ -658,6 +674,47 @@ struct hclge_vlan_filter_vf_cfg_cmd {
|
||||
u8 vf_bitmap[16];
|
||||
};
|
||||
|
||||
#define HCLGE_ACCEPT_TAG_B 0
|
||||
#define HCLGE_ACCEPT_UNTAG_B 1
|
||||
#define HCLGE_PORT_INS_TAG1_EN_B 2
|
||||
#define HCLGE_PORT_INS_TAG2_EN_B 3
|
||||
#define HCLGE_CFG_NIC_ROCE_SEL_B 4
|
||||
struct hclge_vport_vtag_tx_cfg_cmd {
|
||||
u8 vport_vlan_cfg;
|
||||
u8 vf_offset;
|
||||
u8 rsv1[2];
|
||||
__le16 def_vlan_tag1;
|
||||
__le16 def_vlan_tag2;
|
||||
u8 vf_bitmap[8];
|
||||
u8 rsv2[8];
|
||||
};
|
||||
|
||||
#define HCLGE_REM_TAG1_EN_B 0
|
||||
#define HCLGE_REM_TAG2_EN_B 1
|
||||
#define HCLGE_SHOW_TAG1_EN_B 2
|
||||
#define HCLGE_SHOW_TAG2_EN_B 3
|
||||
struct hclge_vport_vtag_rx_cfg_cmd {
|
||||
u8 vport_vlan_cfg;
|
||||
u8 vf_offset;
|
||||
u8 rsv1[6];
|
||||
u8 vf_bitmap[8];
|
||||
u8 rsv2[8];
|
||||
};
|
||||
|
||||
struct hclge_tx_vlan_type_cfg_cmd {
|
||||
__le16 ot_vlan_type;
|
||||
__le16 in_vlan_type;
|
||||
u8 rsv[20];
|
||||
};
|
||||
|
||||
struct hclge_rx_vlan_type_cfg_cmd {
|
||||
__le16 ot_fst_vlan_type;
|
||||
__le16 ot_sec_vlan_type;
|
||||
__le16 in_fst_vlan_type;
|
||||
__le16 in_sec_vlan_type;
|
||||
u8 rsv[16];
|
||||
};
|
||||
|
||||
struct hclge_cfg_com_tqp_queue_cmd {
|
||||
__le16 tqp_id;
|
||||
__le16 stream_id;
|
||||
|
@ -982,6 +982,10 @@ static void hclge_parse_cfg(struct hclge_cfg *cfg, struct hclge_desc *desc)
|
||||
cfg->default_speed = hnae_get_field(__le32_to_cpu(req->param[3]),
|
||||
HCLGE_CFG_DEFAULT_SPEED_M,
|
||||
HCLGE_CFG_DEFAULT_SPEED_S);
|
||||
cfg->rss_size_max = hnae_get_field(__le32_to_cpu(req->param[3]),
|
||||
HCLGE_CFG_RSS_SIZE_M,
|
||||
HCLGE_CFG_RSS_SIZE_S);
|
||||
|
||||
for (i = 0; i < ETH_ALEN; i++)
|
||||
cfg->mac_addr[i] = (mac_addr_tmp >> (8 * i)) & 0xff;
|
||||
|
||||
@ -1059,7 +1063,7 @@ static int hclge_configure(struct hclge_dev *hdev)
|
||||
|
||||
hdev->num_vmdq_vport = cfg.vmdq_vport_num;
|
||||
hdev->base_tqp_pid = 0;
|
||||
hdev->rss_size_max = 1;
|
||||
hdev->rss_size_max = cfg.rss_size_max;
|
||||
hdev->rx_buf_len = cfg.rx_buf_len;
|
||||
ether_addr_copy(hdev->hw.mac.mac_addr, cfg.mac_addr);
|
||||
hdev->hw.mac.media_type = cfg.media_type;
|
||||
@ -1096,10 +1100,7 @@ static int hclge_configure(struct hclge_dev *hdev)
|
||||
for (i = 0; i < hdev->tm_info.num_tc; i++)
|
||||
hnae_set_bit(hdev->hw_tc_map, i, 1);
|
||||
|
||||
if (!hdev->num_vmdq_vport && !hdev->num_req_vfs)
|
||||
hdev->tx_sch_mode = HCLGE_FLAG_TC_BASE_SCH_MODE;
|
||||
else
|
||||
hdev->tx_sch_mode = HCLGE_FLAG_VNET_BASE_SCH_MODE;
|
||||
hdev->tx_sch_mode = HCLGE_FLAG_TC_BASE_SCH_MODE;
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -2133,28 +2134,6 @@ static int hclge_query_mac_an_speed_dup(struct hclge_dev *hdev, int *speed,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hclge_query_autoneg_result(struct hclge_dev *hdev)
|
||||
{
|
||||
struct hclge_mac *mac = &hdev->hw.mac;
|
||||
struct hclge_query_an_speed_dup_cmd *req;
|
||||
struct hclge_desc desc;
|
||||
int ret;
|
||||
|
||||
req = (struct hclge_query_an_speed_dup_cmd *)desc.data;
|
||||
|
||||
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_QUERY_AN_RESULT, true);
|
||||
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
|
||||
if (ret) {
|
||||
dev_err(&hdev->pdev->dev,
|
||||
"autoneg result query cmd failed %d.\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
mac->autoneg = hnae_get_bit(req->an_syn_dup_speed, HCLGE_QUERY_AN_B);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hclge_set_autoneg_en(struct hclge_dev *hdev, bool enable)
|
||||
{
|
||||
struct hclge_config_auto_neg_cmd *req;
|
||||
@ -2190,15 +2169,42 @@ static int hclge_get_autoneg(struct hnae3_handle *handle)
|
||||
{
|
||||
struct hclge_vport *vport = hclge_get_vport(handle);
|
||||
struct hclge_dev *hdev = vport->back;
|
||||
struct phy_device *phydev = hdev->hw.mac.phydev;
|
||||
|
||||
hclge_query_autoneg_result(hdev);
|
||||
if (phydev)
|
||||
return phydev->autoneg;
|
||||
|
||||
return hdev->hw.mac.autoneg;
|
||||
}
|
||||
|
||||
static int hclge_set_default_mac_vlan_mask(struct hclge_dev *hdev,
|
||||
bool mask_vlan,
|
||||
u8 *mac_mask)
|
||||
{
|
||||
struct hclge_mac_vlan_mask_entry_cmd *req;
|
||||
struct hclge_desc desc;
|
||||
int status;
|
||||
|
||||
req = (struct hclge_mac_vlan_mask_entry_cmd *)desc.data;
|
||||
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_MAC_VLAN_MASK_SET, false);
|
||||
|
||||
hnae_set_bit(req->vlan_mask, HCLGE_VLAN_MASK_EN_B,
|
||||
mask_vlan ? 1 : 0);
|
||||
ether_addr_copy(req->mac_mask, mac_mask);
|
||||
|
||||
status = hclge_cmd_send(&hdev->hw, &desc, 1);
|
||||
if (status)
|
||||
dev_err(&hdev->pdev->dev,
|
||||
"Config mac_vlan_mask failed for cmd_send, ret =%d\n",
|
||||
status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int hclge_mac_init(struct hclge_dev *hdev)
|
||||
{
|
||||
struct hclge_mac *mac = &hdev->hw.mac;
|
||||
u8 mac_mask[ETH_ALEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
int ret;
|
||||
|
||||
ret = hclge_cfg_mac_speed_dup(hdev, hdev->hw.mac.speed, HCLGE_MAC_FULL);
|
||||
@ -2224,7 +2230,19 @@ static int hclge_mac_init(struct hclge_dev *hdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return hclge_cfg_func_mta_filter(hdev, 0, hdev->accept_mta_mc);
|
||||
ret = hclge_cfg_func_mta_filter(hdev, 0, hdev->accept_mta_mc);
|
||||
if (ret) {
|
||||
dev_err(&hdev->pdev->dev,
|
||||
"set mta filter mode fail ret=%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = hclge_set_default_mac_vlan_mask(hdev, true, mac_mask);
|
||||
if (ret)
|
||||
dev_err(&hdev->pdev->dev,
|
||||
"set default mac_vlan_mask fail ret=%d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void hclge_mbx_task_schedule(struct hclge_dev *hdev)
|
||||
@ -4339,27 +4357,185 @@ static int hclge_set_vf_vlan_filter(struct hnae3_handle *handle, int vfid,
|
||||
return hclge_set_vf_vlan_common(hdev, vfid, false, vlan, qos, proto);
|
||||
}
|
||||
|
||||
static int hclge_set_vlan_tx_offload_cfg(struct hclge_vport *vport)
|
||||
{
|
||||
struct hclge_tx_vtag_cfg *vcfg = &vport->txvlan_cfg;
|
||||
struct hclge_vport_vtag_tx_cfg_cmd *req;
|
||||
struct hclge_dev *hdev = vport->back;
|
||||
struct hclge_desc desc;
|
||||
int status;
|
||||
|
||||
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_VLAN_PORT_TX_CFG, false);
|
||||
|
||||
req = (struct hclge_vport_vtag_tx_cfg_cmd *)desc.data;
|
||||
req->def_vlan_tag1 = cpu_to_le16(vcfg->default_tag1);
|
||||
req->def_vlan_tag2 = cpu_to_le16(vcfg->default_tag2);
|
||||
hnae_set_bit(req->vport_vlan_cfg, HCLGE_ACCEPT_TAG_B,
|
||||
vcfg->accept_tag ? 1 : 0);
|
||||
hnae_set_bit(req->vport_vlan_cfg, HCLGE_ACCEPT_UNTAG_B,
|
||||
vcfg->accept_untag ? 1 : 0);
|
||||
hnae_set_bit(req->vport_vlan_cfg, HCLGE_PORT_INS_TAG1_EN_B,
|
||||
vcfg->insert_tag1_en ? 1 : 0);
|
||||
hnae_set_bit(req->vport_vlan_cfg, HCLGE_PORT_INS_TAG2_EN_B,
|
||||
vcfg->insert_tag2_en ? 1 : 0);
|
||||
hnae_set_bit(req->vport_vlan_cfg, HCLGE_CFG_NIC_ROCE_SEL_B, 0);
|
||||
|
||||
req->vf_offset = vport->vport_id / HCLGE_VF_NUM_PER_CMD;
|
||||
req->vf_bitmap[req->vf_offset] =
|
||||
1 << (vport->vport_id % HCLGE_VF_NUM_PER_BYTE);
|
||||
|
||||
status = hclge_cmd_send(&hdev->hw, &desc, 1);
|
||||
if (status)
|
||||
dev_err(&hdev->pdev->dev,
|
||||
"Send port txvlan cfg command fail, ret =%d\n",
|
||||
status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int hclge_set_vlan_rx_offload_cfg(struct hclge_vport *vport)
|
||||
{
|
||||
struct hclge_rx_vtag_cfg *vcfg = &vport->rxvlan_cfg;
|
||||
struct hclge_vport_vtag_rx_cfg_cmd *req;
|
||||
struct hclge_dev *hdev = vport->back;
|
||||
struct hclge_desc desc;
|
||||
int status;
|
||||
|
||||
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_VLAN_PORT_RX_CFG, false);
|
||||
|
||||
req = (struct hclge_vport_vtag_rx_cfg_cmd *)desc.data;
|
||||
hnae_set_bit(req->vport_vlan_cfg, HCLGE_REM_TAG1_EN_B,
|
||||
vcfg->strip_tag1_en ? 1 : 0);
|
||||
hnae_set_bit(req->vport_vlan_cfg, HCLGE_REM_TAG2_EN_B,
|
||||
vcfg->strip_tag2_en ? 1 : 0);
|
||||
hnae_set_bit(req->vport_vlan_cfg, HCLGE_SHOW_TAG1_EN_B,
|
||||
vcfg->vlan1_vlan_prionly ? 1 : 0);
|
||||
hnae_set_bit(req->vport_vlan_cfg, HCLGE_SHOW_TAG2_EN_B,
|
||||
vcfg->vlan2_vlan_prionly ? 1 : 0);
|
||||
|
||||
req->vf_offset = vport->vport_id / HCLGE_VF_NUM_PER_CMD;
|
||||
req->vf_bitmap[req->vf_offset] =
|
||||
1 << (vport->vport_id % HCLGE_VF_NUM_PER_BYTE);
|
||||
|
||||
status = hclge_cmd_send(&hdev->hw, &desc, 1);
|
||||
if (status)
|
||||
dev_err(&hdev->pdev->dev,
|
||||
"Send port rxvlan cfg command fail, ret =%d\n",
|
||||
status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int hclge_set_vlan_protocol_type(struct hclge_dev *hdev)
|
||||
{
|
||||
struct hclge_rx_vlan_type_cfg_cmd *rx_req;
|
||||
struct hclge_tx_vlan_type_cfg_cmd *tx_req;
|
||||
struct hclge_desc desc;
|
||||
int status;
|
||||
|
||||
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_MAC_VLAN_TYPE_ID, false);
|
||||
rx_req = (struct hclge_rx_vlan_type_cfg_cmd *)desc.data;
|
||||
rx_req->ot_fst_vlan_type =
|
||||
cpu_to_le16(hdev->vlan_type_cfg.rx_ot_fst_vlan_type);
|
||||
rx_req->ot_sec_vlan_type =
|
||||
cpu_to_le16(hdev->vlan_type_cfg.rx_ot_sec_vlan_type);
|
||||
rx_req->in_fst_vlan_type =
|
||||
cpu_to_le16(hdev->vlan_type_cfg.rx_in_fst_vlan_type);
|
||||
rx_req->in_sec_vlan_type =
|
||||
cpu_to_le16(hdev->vlan_type_cfg.rx_in_sec_vlan_type);
|
||||
|
||||
status = hclge_cmd_send(&hdev->hw, &desc, 1);
|
||||
if (status) {
|
||||
dev_err(&hdev->pdev->dev,
|
||||
"Send rxvlan protocol type command fail, ret =%d\n",
|
||||
status);
|
||||
return status;
|
||||
}
|
||||
|
||||
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_MAC_VLAN_INSERT, false);
|
||||
|
||||
tx_req = (struct hclge_tx_vlan_type_cfg_cmd *)&desc.data;
|
||||
tx_req->ot_vlan_type = cpu_to_le16(hdev->vlan_type_cfg.tx_ot_vlan_type);
|
||||
tx_req->in_vlan_type = cpu_to_le16(hdev->vlan_type_cfg.tx_in_vlan_type);
|
||||
|
||||
status = hclge_cmd_send(&hdev->hw, &desc, 1);
|
||||
if (status)
|
||||
dev_err(&hdev->pdev->dev,
|
||||
"Send txvlan protocol type command fail, ret =%d\n",
|
||||
status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int hclge_init_vlan_config(struct hclge_dev *hdev)
|
||||
{
|
||||
#define HCLGE_VLAN_TYPE_VF_TABLE 0
|
||||
#define HCLGE_VLAN_TYPE_PORT_TABLE 1
|
||||
#define HCLGE_FILTER_TYPE_VF 0
|
||||
#define HCLGE_FILTER_TYPE_PORT 1
|
||||
#define HCLGE_DEF_VLAN_TYPE 0x8100
|
||||
|
||||
struct hnae3_handle *handle;
|
||||
struct hclge_vport *vport;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
ret = hclge_set_vlan_filter_ctrl(hdev, HCLGE_VLAN_TYPE_VF_TABLE,
|
||||
true);
|
||||
ret = hclge_set_vlan_filter_ctrl(hdev, HCLGE_FILTER_TYPE_VF, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = hclge_set_vlan_filter_ctrl(hdev, HCLGE_VLAN_TYPE_PORT_TABLE,
|
||||
true);
|
||||
ret = hclge_set_vlan_filter_ctrl(hdev, HCLGE_FILTER_TYPE_PORT, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
hdev->vlan_type_cfg.rx_in_fst_vlan_type = HCLGE_DEF_VLAN_TYPE;
|
||||
hdev->vlan_type_cfg.rx_in_sec_vlan_type = HCLGE_DEF_VLAN_TYPE;
|
||||
hdev->vlan_type_cfg.rx_ot_fst_vlan_type = HCLGE_DEF_VLAN_TYPE;
|
||||
hdev->vlan_type_cfg.rx_ot_sec_vlan_type = HCLGE_DEF_VLAN_TYPE;
|
||||
hdev->vlan_type_cfg.tx_ot_vlan_type = HCLGE_DEF_VLAN_TYPE;
|
||||
hdev->vlan_type_cfg.tx_in_vlan_type = HCLGE_DEF_VLAN_TYPE;
|
||||
|
||||
ret = hclge_set_vlan_protocol_type(hdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < hdev->num_alloc_vport; i++) {
|
||||
vport = &hdev->vport[i];
|
||||
vport->txvlan_cfg.accept_tag = true;
|
||||
vport->txvlan_cfg.accept_untag = true;
|
||||
vport->txvlan_cfg.insert_tag1_en = false;
|
||||
vport->txvlan_cfg.insert_tag2_en = false;
|
||||
vport->txvlan_cfg.default_tag1 = 0;
|
||||
vport->txvlan_cfg.default_tag2 = 0;
|
||||
|
||||
ret = hclge_set_vlan_tx_offload_cfg(vport);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
vport->rxvlan_cfg.strip_tag1_en = false;
|
||||
vport->rxvlan_cfg.strip_tag2_en = true;
|
||||
vport->rxvlan_cfg.vlan1_vlan_prionly = false;
|
||||
vport->rxvlan_cfg.vlan2_vlan_prionly = false;
|
||||
|
||||
ret = hclge_set_vlan_rx_offload_cfg(vport);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
handle = &hdev->vport[0].nic;
|
||||
return hclge_set_port_vlan_filter(handle, htons(ETH_P_8021Q), 0, false);
|
||||
}
|
||||
|
||||
static int hclge_en_hw_strip_rxvtag(struct hnae3_handle *handle, bool enable)
|
||||
{
|
||||
struct hclge_vport *vport = hclge_get_vport(handle);
|
||||
|
||||
vport->rxvlan_cfg.strip_tag1_en = false;
|
||||
vport->rxvlan_cfg.strip_tag2_en = enable;
|
||||
vport->rxvlan_cfg.vlan1_vlan_prionly = false;
|
||||
vport->rxvlan_cfg.vlan2_vlan_prionly = false;
|
||||
|
||||
return hclge_set_vlan_rx_offload_cfg(vport);
|
||||
}
|
||||
|
||||
static int hclge_set_mtu(struct hnae3_handle *handle, int new_mtu)
|
||||
{
|
||||
struct hclge_vport *vport = hclge_get_vport(handle);
|
||||
@ -4481,6 +4657,103 @@ static u32 hclge_get_fw_version(struct hnae3_handle *handle)
|
||||
return hdev->fw_version;
|
||||
}
|
||||
|
||||
static void hclge_get_flowctrl_adv(struct hnae3_handle *handle,
|
||||
u32 *flowctrl_adv)
|
||||
{
|
||||
struct hclge_vport *vport = hclge_get_vport(handle);
|
||||
struct hclge_dev *hdev = vport->back;
|
||||
struct phy_device *phydev = hdev->hw.mac.phydev;
|
||||
|
||||
if (!phydev)
|
||||
return;
|
||||
|
||||
*flowctrl_adv |= (phydev->advertising & ADVERTISED_Pause) |
|
||||
(phydev->advertising & ADVERTISED_Asym_Pause);
|
||||
}
|
||||
|
||||
static void hclge_set_flowctrl_adv(struct hclge_dev *hdev, u32 rx_en, u32 tx_en)
|
||||
{
|
||||
struct phy_device *phydev = hdev->hw.mac.phydev;
|
||||
|
||||
if (!phydev)
|
||||
return;
|
||||
|
||||
phydev->advertising &= ~(ADVERTISED_Pause | ADVERTISED_Asym_Pause);
|
||||
|
||||
if (rx_en)
|
||||
phydev->advertising |= ADVERTISED_Pause | ADVERTISED_Asym_Pause;
|
||||
|
||||
if (tx_en)
|
||||
phydev->advertising ^= ADVERTISED_Asym_Pause;
|
||||
}
|
||||
|
||||
static int hclge_cfg_pauseparam(struct hclge_dev *hdev, u32 rx_en, u32 tx_en)
|
||||
{
|
||||
enum hclge_fc_mode fc_mode;
|
||||
int ret;
|
||||
|
||||
if (rx_en && tx_en)
|
||||
fc_mode = HCLGE_FC_FULL;
|
||||
else if (rx_en && !tx_en)
|
||||
fc_mode = HCLGE_FC_RX_PAUSE;
|
||||
else if (!rx_en && tx_en)
|
||||
fc_mode = HCLGE_FC_TX_PAUSE;
|
||||
else
|
||||
fc_mode = HCLGE_FC_NONE;
|
||||
|
||||
if (hdev->tm_info.fc_mode == HCLGE_FC_PFC) {
|
||||
hdev->fc_mode_last_time = fc_mode;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = hclge_mac_pause_en_cfg(hdev, tx_en, rx_en);
|
||||
if (ret) {
|
||||
dev_err(&hdev->pdev->dev, "configure pauseparam error, ret = %d.\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
hdev->tm_info.fc_mode = fc_mode;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hclge_cfg_flowctrl(struct hclge_dev *hdev)
|
||||
{
|
||||
struct phy_device *phydev = hdev->hw.mac.phydev;
|
||||
u16 remote_advertising = 0;
|
||||
u16 local_advertising = 0;
|
||||
u32 rx_pause, tx_pause;
|
||||
u8 flowctl;
|
||||
|
||||
if (!phydev->link || !phydev->autoneg)
|
||||
return 0;
|
||||
|
||||
if (phydev->advertising & ADVERTISED_Pause)
|
||||
local_advertising = ADVERTISE_PAUSE_CAP;
|
||||
|
||||
if (phydev->advertising & ADVERTISED_Asym_Pause)
|
||||
local_advertising |= ADVERTISE_PAUSE_ASYM;
|
||||
|
||||
if (phydev->pause)
|
||||
remote_advertising = LPA_PAUSE_CAP;
|
||||
|
||||
if (phydev->asym_pause)
|
||||
remote_advertising |= LPA_PAUSE_ASYM;
|
||||
|
||||
flowctl = mii_resolve_flowctrl_fdx(local_advertising,
|
||||
remote_advertising);
|
||||
tx_pause = flowctl & FLOW_CTRL_TX;
|
||||
rx_pause = flowctl & FLOW_CTRL_RX;
|
||||
|
||||
if (phydev->duplex == HCLGE_MAC_HALF) {
|
||||
tx_pause = 0;
|
||||
rx_pause = 0;
|
||||
}
|
||||
|
||||
return hclge_cfg_pauseparam(hdev, rx_pause, tx_pause);
|
||||
}
|
||||
|
||||
static void hclge_get_pauseparam(struct hnae3_handle *handle, u32 *auto_neg,
|
||||
u32 *rx_en, u32 *tx_en)
|
||||
{
|
||||
@ -4510,6 +4783,41 @@ static void hclge_get_pauseparam(struct hnae3_handle *handle, u32 *auto_neg,
|
||||
}
|
||||
}
|
||||
|
||||
static int hclge_set_pauseparam(struct hnae3_handle *handle, u32 auto_neg,
|
||||
u32 rx_en, u32 tx_en)
|
||||
{
|
||||
struct hclge_vport *vport = hclge_get_vport(handle);
|
||||
struct hclge_dev *hdev = vport->back;
|
||||
struct phy_device *phydev = hdev->hw.mac.phydev;
|
||||
u32 fc_autoneg;
|
||||
|
||||
/* Only support flow control negotiation for netdev with
|
||||
* phy attached for now.
|
||||
*/
|
||||
if (!phydev)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
fc_autoneg = hclge_get_autoneg(handle);
|
||||
if (auto_neg != fc_autoneg) {
|
||||
dev_info(&hdev->pdev->dev,
|
||||
"To change autoneg please use: ethtool -s <dev> autoneg <on|off>\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (hdev->tm_info.fc_mode == HCLGE_FC_PFC) {
|
||||
dev_info(&hdev->pdev->dev,
|
||||
"Priority flow control enabled. Cannot set link flow control.\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
hclge_set_flowctrl_adv(hdev, rx_en, tx_en);
|
||||
|
||||
if (!fc_autoneg)
|
||||
return hclge_cfg_pauseparam(hdev, rx_en, tx_en);
|
||||
|
||||
return phy_start_aneg(phydev);
|
||||
}
|
||||
|
||||
static void hclge_get_ksettings_an_result(struct hnae3_handle *handle,
|
||||
u8 *auto_neg, u32 *speed, u8 *duplex)
|
||||
{
|
||||
@ -5002,6 +5310,136 @@ static void hclge_uninit_ae_dev(struct hnae3_ae_dev *ae_dev)
|
||||
ae_dev->priv = NULL;
|
||||
}
|
||||
|
||||
static u32 hclge_get_max_channels(struct hnae3_handle *handle)
|
||||
{
|
||||
struct hnae3_knic_private_info *kinfo = &handle->kinfo;
|
||||
struct hclge_vport *vport = hclge_get_vport(handle);
|
||||
struct hclge_dev *hdev = vport->back;
|
||||
|
||||
return min_t(u32, hdev->rss_size_max * kinfo->num_tc, hdev->num_tqps);
|
||||
}
|
||||
|
||||
static void hclge_get_channels(struct hnae3_handle *handle,
|
||||
struct ethtool_channels *ch)
|
||||
{
|
||||
struct hclge_vport *vport = hclge_get_vport(handle);
|
||||
|
||||
ch->max_combined = hclge_get_max_channels(handle);
|
||||
ch->other_count = 1;
|
||||
ch->max_other = 1;
|
||||
ch->combined_count = vport->alloc_tqps;
|
||||
}
|
||||
|
||||
static void hclge_get_tqps_and_rss_info(struct hnae3_handle *handle,
|
||||
u16 *free_tqps, u16 *max_rss_size)
|
||||
{
|
||||
struct hclge_vport *vport = hclge_get_vport(handle);
|
||||
struct hclge_dev *hdev = vport->back;
|
||||
u16 temp_tqps = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < hdev->num_tqps; i++) {
|
||||
if (!hdev->htqp[i].alloced)
|
||||
temp_tqps++;
|
||||
}
|
||||
*free_tqps = temp_tqps;
|
||||
*max_rss_size = hdev->rss_size_max;
|
||||
}
|
||||
|
||||
static void hclge_release_tqp(struct hclge_vport *vport)
|
||||
{
|
||||
struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo;
|
||||
struct hclge_dev *hdev = vport->back;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < kinfo->num_tqps; i++) {
|
||||
struct hclge_tqp *tqp =
|
||||
container_of(kinfo->tqp[i], struct hclge_tqp, q);
|
||||
|
||||
tqp->q.handle = NULL;
|
||||
tqp->q.tqp_index = 0;
|
||||
tqp->alloced = false;
|
||||
}
|
||||
|
||||
devm_kfree(&hdev->pdev->dev, kinfo->tqp);
|
||||
kinfo->tqp = NULL;
|
||||
}
|
||||
|
||||
static int hclge_set_channels(struct hnae3_handle *handle, u32 new_tqps_num)
|
||||
{
|
||||
struct hclge_vport *vport = hclge_get_vport(handle);
|
||||
struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo;
|
||||
struct hclge_dev *hdev = vport->back;
|
||||
int cur_rss_size = kinfo->rss_size;
|
||||
int cur_tqps = kinfo->num_tqps;
|
||||
u16 tc_offset[HCLGE_MAX_TC_NUM];
|
||||
u16 tc_valid[HCLGE_MAX_TC_NUM];
|
||||
u16 tc_size[HCLGE_MAX_TC_NUM];
|
||||
u16 roundup_size;
|
||||
u32 *rss_indir;
|
||||
int ret, i;
|
||||
|
||||
hclge_release_tqp(vport);
|
||||
|
||||
ret = hclge_knic_setup(vport, new_tqps_num);
|
||||
if (ret) {
|
||||
dev_err(&hdev->pdev->dev, "setup nic fail, ret =%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = hclge_map_tqp_to_vport(hdev, vport);
|
||||
if (ret) {
|
||||
dev_err(&hdev->pdev->dev, "map vport tqp fail, ret =%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = hclge_tm_schd_init(hdev);
|
||||
if (ret) {
|
||||
dev_err(&hdev->pdev->dev, "tm schd init fail, ret =%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
roundup_size = roundup_pow_of_two(kinfo->rss_size);
|
||||
roundup_size = ilog2(roundup_size);
|
||||
/* Set the RSS TC mode according to the new RSS size */
|
||||
for (i = 0; i < HCLGE_MAX_TC_NUM; i++) {
|
||||
tc_valid[i] = 0;
|
||||
|
||||
if (!(hdev->hw_tc_map & BIT(i)))
|
||||
continue;
|
||||
|
||||
tc_valid[i] = 1;
|
||||
tc_size[i] = roundup_size;
|
||||
tc_offset[i] = kinfo->rss_size * i;
|
||||
}
|
||||
ret = hclge_set_rss_tc_mode(hdev, tc_valid, tc_size, tc_offset);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Reinitializes the rss indirect table according to the new RSS size */
|
||||
rss_indir = kcalloc(HCLGE_RSS_IND_TBL_SIZE, sizeof(u32), GFP_KERNEL);
|
||||
if (!rss_indir)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < HCLGE_RSS_IND_TBL_SIZE; i++)
|
||||
rss_indir[i] = i % kinfo->rss_size;
|
||||
|
||||
ret = hclge_set_rss(handle, rss_indir, NULL, 0);
|
||||
if (ret)
|
||||
dev_err(&hdev->pdev->dev, "set rss indir table fail, ret=%d\n",
|
||||
ret);
|
||||
|
||||
kfree(rss_indir);
|
||||
|
||||
if (!ret)
|
||||
dev_info(&hdev->pdev->dev,
|
||||
"Channels changed, rss_size from %d to %d, tqps from %d to %d",
|
||||
cur_rss_size, kinfo->rss_size,
|
||||
cur_tqps, kinfo->rss_size * kinfo->num_tc);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct hnae3_ae_ops hclge_ops = {
|
||||
.init_ae_dev = hclge_init_ae_dev,
|
||||
.uninit_ae_dev = hclge_uninit_ae_dev,
|
||||
@ -5035,6 +5473,7 @@ static const struct hnae3_ae_ops hclge_ops = {
|
||||
.set_autoneg = hclge_set_autoneg,
|
||||
.get_autoneg = hclge_get_autoneg,
|
||||
.get_pauseparam = hclge_get_pauseparam,
|
||||
.set_pauseparam = hclge_set_pauseparam,
|
||||
.set_mtu = hclge_set_mtu,
|
||||
.reset_queue = hclge_reset_tqp,
|
||||
.get_stats = hclge_get_stats,
|
||||
@ -5045,7 +5484,12 @@ static const struct hnae3_ae_ops hclge_ops = {
|
||||
.get_mdix_mode = hclge_get_mdix_mode,
|
||||
.set_vlan_filter = hclge_set_port_vlan_filter,
|
||||
.set_vf_vlan_filter = hclge_set_vf_vlan_filter,
|
||||
.enable_hw_strip_rxvtag = hclge_en_hw_strip_rxvtag,
|
||||
.reset_event = hclge_reset_event,
|
||||
.get_tqps_and_rss_info = hclge_get_tqps_and_rss_info,
|
||||
.set_channels = hclge_set_channels,
|
||||
.get_channels = hclge_get_channels,
|
||||
.get_flowctrl_adv = hclge_get_flowctrl_adv,
|
||||
};
|
||||
|
||||
static struct hnae3_ae_algo ae_algo = {
|
||||
|
@ -79,6 +79,10 @@
|
||||
#define HCLGE_PHY_MDIX_STATUS_B (6)
|
||||
#define HCLGE_PHY_SPEED_DUP_RESOLVE_B (11)
|
||||
|
||||
/* Factor used to calculate offset and bitmap of VF num */
|
||||
#define HCLGE_VF_NUM_PER_CMD 64
|
||||
#define HCLGE_VF_NUM_PER_BYTE 8
|
||||
|
||||
/* Reset related Registers */
|
||||
#define HCLGE_MISC_RESET_STS_REG 0x20700
|
||||
#define HCLGE_GLOBAL_RESET_REG 0x20A00
|
||||
@ -220,6 +224,7 @@ struct hclge_cfg {
|
||||
u8 tc_num;
|
||||
u16 tqp_desc_num;
|
||||
u16 rx_buf_len;
|
||||
u16 rss_size_max;
|
||||
u8 phy_addr;
|
||||
u8 media_type;
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
@ -423,6 +428,15 @@ struct hclge_hw_stats {
|
||||
struct hclge_32_bit_stats all_32_bit_stats;
|
||||
};
|
||||
|
||||
struct hclge_vlan_type_cfg {
|
||||
u16 rx_ot_fst_vlan_type;
|
||||
u16 rx_ot_sec_vlan_type;
|
||||
u16 rx_in_fst_vlan_type;
|
||||
u16 rx_in_sec_vlan_type;
|
||||
u16 tx_ot_vlan_type;
|
||||
u16 tx_in_vlan_type;
|
||||
};
|
||||
|
||||
struct hclge_dev {
|
||||
struct pci_dev *pdev;
|
||||
struct hnae3_ae_dev *ae_dev;
|
||||
@ -509,6 +523,26 @@ struct hclge_dev {
|
||||
enum hclge_mta_dmac_sel_type mta_mac_sel_type;
|
||||
bool enable_mta; /* Mutilcast filter enable */
|
||||
bool accept_mta_mc; /* Whether accept mta filter multicast */
|
||||
|
||||
struct hclge_vlan_type_cfg vlan_type_cfg;
|
||||
};
|
||||
|
||||
/* VPort level vlan tag configuration for TX direction */
|
||||
struct hclge_tx_vtag_cfg {
|
||||
bool accept_tag; /* Whether accept tagged packet from host */
|
||||
bool accept_untag; /* Whether accept untagged packet from host */
|
||||
bool insert_tag1_en; /* Whether insert inner vlan tag */
|
||||
bool insert_tag2_en; /* Whether insert outer vlan tag */
|
||||
u16 default_tag1; /* The default inner vlan tag to insert */
|
||||
u16 default_tag2; /* The default outer vlan tag to insert */
|
||||
};
|
||||
|
||||
/* VPort level vlan tag configuration for RX direction */
|
||||
struct hclge_rx_vtag_cfg {
|
||||
bool strip_tag1_en; /* Whether strip inner vlan tag */
|
||||
bool strip_tag2_en; /* Whether strip outer vlan tag */
|
||||
bool vlan1_vlan_prionly;/* Inner VLAN Tag up to descriptor Enable */
|
||||
bool vlan2_vlan_prionly;/* Outer VLAN Tag up to descriptor Enable */
|
||||
};
|
||||
|
||||
struct hclge_vport {
|
||||
@ -523,6 +557,9 @@ struct hclge_vport {
|
||||
u16 bw_limit; /* VSI BW Limit (0 = disabled) */
|
||||
u8 dwrr;
|
||||
|
||||
struct hclge_tx_vtag_cfg txvlan_cfg;
|
||||
struct hclge_rx_vtag_cfg rxvlan_cfg;
|
||||
|
||||
int vport_id;
|
||||
struct hclge_dev *back; /* Back reference to associated dev */
|
||||
struct hnae3_handle nic;
|
||||
@ -565,4 +602,5 @@ int hclge_rss_init_hw(struct hclge_dev *hdev);
|
||||
|
||||
void hclge_mbx_handler(struct hclge_dev *hdev);
|
||||
void hclge_reset_tqp(struct hnae3_handle *handle, u16 queue_id);
|
||||
int hclge_cfg_flowctrl(struct hclge_dev *hdev);
|
||||
#endif
|
||||
|
@ -17,6 +17,7 @@
|
||||
#define HCLGE_PHY_SUPPORTED_FEATURES (SUPPORTED_Autoneg | \
|
||||
SUPPORTED_TP | \
|
||||
SUPPORTED_Pause | \
|
||||
SUPPORTED_Asym_Pause | \
|
||||
PHY_10BT_FEATURES | \
|
||||
PHY_100BT_FEATURES | \
|
||||
PHY_1000BT_FEATURES)
|
||||
@ -183,6 +184,10 @@ static void hclge_mac_adjust_link(struct net_device *netdev)
|
||||
ret = hclge_cfg_mac_speed_dup(hdev, speed, duplex);
|
||||
if (ret)
|
||||
netdev_err(netdev, "failed to adjust link.\n");
|
||||
|
||||
ret = hclge_cfg_flowctrl(hdev);
|
||||
if (ret)
|
||||
netdev_err(netdev, "failed to configure flow control.\n");
|
||||
}
|
||||
|
||||
int hclge_mac_start_phy(struct hclge_dev *hdev)
|
||||
|
@ -23,8 +23,8 @@ enum hclge_shaper_level {
|
||||
HCLGE_SHAPER_LVL_PF = 1,
|
||||
};
|
||||
|
||||
#define HCLGE_SHAPER_BS_U_DEF 1
|
||||
#define HCLGE_SHAPER_BS_S_DEF 4
|
||||
#define HCLGE_SHAPER_BS_U_DEF 5
|
||||
#define HCLGE_SHAPER_BS_S_DEF 20
|
||||
|
||||
#define HCLGE_ETHER_MAX_RATE 100000
|
||||
|
||||
@ -112,7 +112,7 @@ static int hclge_shaper_para_calc(u32 ir, u8 shaper_level,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hclge_mac_pause_en_cfg(struct hclge_dev *hdev, bool tx, bool rx)
|
||||
int hclge_mac_pause_en_cfg(struct hclge_dev *hdev, bool tx, bool rx)
|
||||
{
|
||||
struct hclge_desc desc;
|
||||
|
||||
|
@ -118,4 +118,5 @@ void hclge_tm_schd_info_update(struct hclge_dev *hdev, u8 num_tc);
|
||||
int hclge_tm_dwrr_cfg(struct hclge_dev *hdev);
|
||||
int hclge_tm_map_cfg(struct hclge_dev *hdev);
|
||||
int hclge_tm_init_hw(struct hclge_dev *hdev);
|
||||
int hclge_mac_pause_en_cfg(struct hclge_dev *hdev, bool tx, bool rx);
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user