Loading drivers/net/niu.c +158 −0 Original line number Diff line number Diff line Loading @@ -6385,6 +6385,162 @@ static int niu_get_eeprom(struct net_device *dev, return 0; } static int niu_ethflow_to_class(int flow_type, u64 *class) { switch (flow_type) { case TCP_V4_FLOW: *class = CLASS_CODE_TCP_IPV4; break; case UDP_V4_FLOW: *class = CLASS_CODE_UDP_IPV4; break; case AH_ESP_V4_FLOW: *class = CLASS_CODE_AH_ESP_IPV4; break; case SCTP_V4_FLOW: *class = CLASS_CODE_SCTP_IPV4; break; case TCP_V6_FLOW: *class = CLASS_CODE_TCP_IPV6; break; case UDP_V6_FLOW: *class = CLASS_CODE_UDP_IPV6; break; case AH_ESP_V6_FLOW: *class = CLASS_CODE_AH_ESP_IPV6; break; case SCTP_V6_FLOW: *class = CLASS_CODE_SCTP_IPV6; break; default: return -1; } return 1; } static u64 niu_flowkey_to_ethflow(u64 flow_key) { u64 ethflow = 0; if (flow_key & FLOW_KEY_PORT) ethflow |= RXH_DEV_PORT; if (flow_key & FLOW_KEY_L2DA) ethflow |= RXH_L2DA; if (flow_key & FLOW_KEY_VLAN) ethflow |= RXH_VLAN; if (flow_key & FLOW_KEY_IPSA) ethflow |= RXH_IP_SRC; if (flow_key & FLOW_KEY_IPDA) ethflow |= RXH_IP_DST; if (flow_key & FLOW_KEY_PROTO) ethflow |= RXH_L3_PROTO; if (flow_key & (FLOW_KEY_L4_BYTE12 << FLOW_KEY_L4_0_SHIFT)) ethflow |= RXH_L4_B_0_1; if (flow_key & (FLOW_KEY_L4_BYTE12 << FLOW_KEY_L4_1_SHIFT)) ethflow |= RXH_L4_B_2_3; return ethflow; } static int niu_ethflow_to_flowkey(u64 ethflow, u64 *flow_key) { u64 key = 0; if (ethflow & RXH_DEV_PORT) key |= FLOW_KEY_PORT; if (ethflow & RXH_L2DA) key |= FLOW_KEY_L2DA; if (ethflow & RXH_VLAN) key |= FLOW_KEY_VLAN; if (ethflow & RXH_IP_SRC) key |= FLOW_KEY_IPSA; if (ethflow & RXH_IP_DST) key |= FLOW_KEY_IPDA; if (ethflow & RXH_L3_PROTO) key |= FLOW_KEY_PROTO; if (ethflow & RXH_L4_B_0_1) key |= (FLOW_KEY_L4_BYTE12 << FLOW_KEY_L4_0_SHIFT); if (ethflow & RXH_L4_B_2_3) key |= (FLOW_KEY_L4_BYTE12 << FLOW_KEY_L4_1_SHIFT); *flow_key = key; return 1; } static int niu_get_hash_opts(struct net_device *dev, struct ethtool_rxnfc *cmd) { struct niu *np = netdev_priv(dev); u64 class; cmd->data = 0; if (!niu_ethflow_to_class(cmd->flow_type, &class)) return -EINVAL; if (np->parent->tcam_key[class - CLASS_CODE_USER_PROG1] & TCAM_KEY_DISC) cmd->data = RXH_DISCARD; else cmd->data = niu_flowkey_to_ethflow(np->parent->flow_key[class - CLASS_CODE_USER_PROG1]); return 0; } static int niu_set_hash_opts(struct net_device *dev, struct ethtool_rxnfc *cmd) { struct niu *np = netdev_priv(dev); u64 class; u64 flow_key = 0; unsigned long flags; if (!niu_ethflow_to_class(cmd->flow_type, &class)) return -EINVAL; if (class < CLASS_CODE_USER_PROG1 || class > CLASS_CODE_SCTP_IPV6) return -EINVAL; if (cmd->data & RXH_DISCARD) { niu_lock_parent(np, flags); flow_key = np->parent->tcam_key[class - CLASS_CODE_USER_PROG1]; flow_key |= TCAM_KEY_DISC; nw64(TCAM_KEY(class - CLASS_CODE_USER_PROG1), flow_key); np->parent->tcam_key[class - CLASS_CODE_USER_PROG1] = flow_key; niu_unlock_parent(np, flags); return 0; } else { /* Discard was set before, but is not set now */ if (np->parent->tcam_key[class - CLASS_CODE_USER_PROG1] & TCAM_KEY_DISC) { niu_lock_parent(np, flags); flow_key = np->parent->tcam_key[class - CLASS_CODE_USER_PROG1]; flow_key &= ~TCAM_KEY_DISC; nw64(TCAM_KEY(class - CLASS_CODE_USER_PROG1), flow_key); np->parent->tcam_key[class - CLASS_CODE_USER_PROG1] = flow_key; niu_unlock_parent(np, flags); } } if (!niu_ethflow_to_flowkey(cmd->data, &flow_key)) return -EINVAL; niu_lock_parent(np, flags); nw64(FLOW_KEY(class - CLASS_CODE_USER_PROG1), flow_key); np->parent->flow_key[class - CLASS_CODE_USER_PROG1] = flow_key; niu_unlock_parent(np, flags); return 0; } static const struct { const char string[ETH_GSTRING_LEN]; } niu_xmac_stat_keys[] = { Loading Loading @@ -6615,6 +6771,8 @@ static const struct ethtool_ops niu_ethtool_ops = { .get_stats_count = niu_get_stats_count, .get_ethtool_stats = niu_get_ethtool_stats, .phys_id = niu_phys_id, .get_rxhash = niu_get_hash_opts, .set_rxhash = niu_set_hash_opts, }; static int niu_ldg_assign_ldn(struct niu *np, struct niu_parent *parent, Loading Loading
drivers/net/niu.c +158 −0 Original line number Diff line number Diff line Loading @@ -6385,6 +6385,162 @@ static int niu_get_eeprom(struct net_device *dev, return 0; } static int niu_ethflow_to_class(int flow_type, u64 *class) { switch (flow_type) { case TCP_V4_FLOW: *class = CLASS_CODE_TCP_IPV4; break; case UDP_V4_FLOW: *class = CLASS_CODE_UDP_IPV4; break; case AH_ESP_V4_FLOW: *class = CLASS_CODE_AH_ESP_IPV4; break; case SCTP_V4_FLOW: *class = CLASS_CODE_SCTP_IPV4; break; case TCP_V6_FLOW: *class = CLASS_CODE_TCP_IPV6; break; case UDP_V6_FLOW: *class = CLASS_CODE_UDP_IPV6; break; case AH_ESP_V6_FLOW: *class = CLASS_CODE_AH_ESP_IPV6; break; case SCTP_V6_FLOW: *class = CLASS_CODE_SCTP_IPV6; break; default: return -1; } return 1; } static u64 niu_flowkey_to_ethflow(u64 flow_key) { u64 ethflow = 0; if (flow_key & FLOW_KEY_PORT) ethflow |= RXH_DEV_PORT; if (flow_key & FLOW_KEY_L2DA) ethflow |= RXH_L2DA; if (flow_key & FLOW_KEY_VLAN) ethflow |= RXH_VLAN; if (flow_key & FLOW_KEY_IPSA) ethflow |= RXH_IP_SRC; if (flow_key & FLOW_KEY_IPDA) ethflow |= RXH_IP_DST; if (flow_key & FLOW_KEY_PROTO) ethflow |= RXH_L3_PROTO; if (flow_key & (FLOW_KEY_L4_BYTE12 << FLOW_KEY_L4_0_SHIFT)) ethflow |= RXH_L4_B_0_1; if (flow_key & (FLOW_KEY_L4_BYTE12 << FLOW_KEY_L4_1_SHIFT)) ethflow |= RXH_L4_B_2_3; return ethflow; } static int niu_ethflow_to_flowkey(u64 ethflow, u64 *flow_key) { u64 key = 0; if (ethflow & RXH_DEV_PORT) key |= FLOW_KEY_PORT; if (ethflow & RXH_L2DA) key |= FLOW_KEY_L2DA; if (ethflow & RXH_VLAN) key |= FLOW_KEY_VLAN; if (ethflow & RXH_IP_SRC) key |= FLOW_KEY_IPSA; if (ethflow & RXH_IP_DST) key |= FLOW_KEY_IPDA; if (ethflow & RXH_L3_PROTO) key |= FLOW_KEY_PROTO; if (ethflow & RXH_L4_B_0_1) key |= (FLOW_KEY_L4_BYTE12 << FLOW_KEY_L4_0_SHIFT); if (ethflow & RXH_L4_B_2_3) key |= (FLOW_KEY_L4_BYTE12 << FLOW_KEY_L4_1_SHIFT); *flow_key = key; return 1; } static int niu_get_hash_opts(struct net_device *dev, struct ethtool_rxnfc *cmd) { struct niu *np = netdev_priv(dev); u64 class; cmd->data = 0; if (!niu_ethflow_to_class(cmd->flow_type, &class)) return -EINVAL; if (np->parent->tcam_key[class - CLASS_CODE_USER_PROG1] & TCAM_KEY_DISC) cmd->data = RXH_DISCARD; else cmd->data = niu_flowkey_to_ethflow(np->parent->flow_key[class - CLASS_CODE_USER_PROG1]); return 0; } static int niu_set_hash_opts(struct net_device *dev, struct ethtool_rxnfc *cmd) { struct niu *np = netdev_priv(dev); u64 class; u64 flow_key = 0; unsigned long flags; if (!niu_ethflow_to_class(cmd->flow_type, &class)) return -EINVAL; if (class < CLASS_CODE_USER_PROG1 || class > CLASS_CODE_SCTP_IPV6) return -EINVAL; if (cmd->data & RXH_DISCARD) { niu_lock_parent(np, flags); flow_key = np->parent->tcam_key[class - CLASS_CODE_USER_PROG1]; flow_key |= TCAM_KEY_DISC; nw64(TCAM_KEY(class - CLASS_CODE_USER_PROG1), flow_key); np->parent->tcam_key[class - CLASS_CODE_USER_PROG1] = flow_key; niu_unlock_parent(np, flags); return 0; } else { /* Discard was set before, but is not set now */ if (np->parent->tcam_key[class - CLASS_CODE_USER_PROG1] & TCAM_KEY_DISC) { niu_lock_parent(np, flags); flow_key = np->parent->tcam_key[class - CLASS_CODE_USER_PROG1]; flow_key &= ~TCAM_KEY_DISC; nw64(TCAM_KEY(class - CLASS_CODE_USER_PROG1), flow_key); np->parent->tcam_key[class - CLASS_CODE_USER_PROG1] = flow_key; niu_unlock_parent(np, flags); } } if (!niu_ethflow_to_flowkey(cmd->data, &flow_key)) return -EINVAL; niu_lock_parent(np, flags); nw64(FLOW_KEY(class - CLASS_CODE_USER_PROG1), flow_key); np->parent->flow_key[class - CLASS_CODE_USER_PROG1] = flow_key; niu_unlock_parent(np, flags); return 0; } static const struct { const char string[ETH_GSTRING_LEN]; } niu_xmac_stat_keys[] = { Loading Loading @@ -6615,6 +6771,8 @@ static const struct ethtool_ops niu_ethtool_ops = { .get_stats_count = niu_get_stats_count, .get_ethtool_stats = niu_get_ethtool_stats, .phys_id = niu_phys_id, .get_rxhash = niu_get_hash_opts, .set_rxhash = niu_set_hash_opts, }; static int niu_ldg_assign_ldn(struct niu *np, struct niu_parent *parent, Loading