diff options
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c | 96 |
1 files changed, 94 insertions, 2 deletions
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c index acfab86431b1..ecc8602c6799 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c | |||
@@ -296,7 +296,9 @@ static int __stmmac_test_loopback(struct stmmac_priv *priv, | |||
296 | tpriv->pt.dev = priv->dev; | 296 | tpriv->pt.dev = priv->dev; |
297 | tpriv->pt.af_packet_priv = tpriv; | 297 | tpriv->pt.af_packet_priv = tpriv; |
298 | tpriv->packet = attr; | 298 | tpriv->packet = attr; |
299 | dev_add_pack(&tpriv->pt); | 299 | |
300 | if (!attr->dont_wait) | ||
301 | dev_add_pack(&tpriv->pt); | ||
300 | 302 | ||
301 | skb = stmmac_test_get_udp_skb(priv, attr); | 303 | skb = stmmac_test_get_udp_skb(priv, attr); |
302 | if (!skb) { | 304 | if (!skb) { |
@@ -319,7 +321,8 @@ static int __stmmac_test_loopback(struct stmmac_priv *priv, | |||
319 | ret = !tpriv->ok; | 321 | ret = !tpriv->ok; |
320 | 322 | ||
321 | cleanup: | 323 | cleanup: |
322 | dev_remove_pack(&tpriv->pt); | 324 | if (!attr->dont_wait) |
325 | dev_remove_pack(&tpriv->pt); | ||
323 | kfree(tpriv); | 326 | kfree(tpriv); |
324 | return ret; | 327 | return ret; |
325 | } | 328 | } |
@@ -731,6 +734,9 @@ static int stmmac_test_vlan_validate(struct sk_buff *skb, | |||
731 | struct ethhdr *ehdr; | 734 | struct ethhdr *ehdr; |
732 | struct udphdr *uhdr; | 735 | struct udphdr *uhdr; |
733 | struct iphdr *ihdr; | 736 | struct iphdr *ihdr; |
737 | u16 proto; | ||
738 | |||
739 | proto = tpriv->double_vlan ? ETH_P_8021AD : ETH_P_8021Q; | ||
734 | 740 | ||
735 | skb = skb_unshare(skb, GFP_ATOMIC); | 741 | skb = skb_unshare(skb, GFP_ATOMIC); |
736 | if (!skb) | 742 | if (!skb) |
@@ -740,6 +746,12 @@ static int stmmac_test_vlan_validate(struct sk_buff *skb, | |||
740 | goto out; | 746 | goto out; |
741 | if (skb_headlen(skb) < (STMMAC_TEST_PKT_SIZE - ETH_HLEN)) | 747 | if (skb_headlen(skb) < (STMMAC_TEST_PKT_SIZE - ETH_HLEN)) |
742 | goto out; | 748 | goto out; |
749 | if (tpriv->vlan_id) { | ||
750 | if (skb->vlan_proto != htons(proto)) | ||
751 | goto out; | ||
752 | if (skb->vlan_tci != tpriv->vlan_id) | ||
753 | goto out; | ||
754 | } | ||
743 | 755 | ||
744 | ehdr = (struct ethhdr *)skb_mac_header(skb); | 756 | ehdr = (struct ethhdr *)skb_mac_header(skb); |
745 | if (!ether_addr_equal(ehdr->h_dest, tpriv->packet->dst)) | 757 | if (!ether_addr_equal(ehdr->h_dest, tpriv->packet->dst)) |
@@ -1084,6 +1096,78 @@ static int stmmac_test_reg_sar(struct stmmac_priv *priv) | |||
1084 | return ret; | 1096 | return ret; |
1085 | } | 1097 | } |
1086 | 1098 | ||
1099 | static int stmmac_test_vlanoff_common(struct stmmac_priv *priv, bool svlan) | ||
1100 | { | ||
1101 | struct stmmac_packet_attrs attr = { }; | ||
1102 | struct stmmac_test_priv *tpriv; | ||
1103 | struct sk_buff *skb = NULL; | ||
1104 | int ret = 0; | ||
1105 | u16 proto; | ||
1106 | |||
1107 | if (!priv->dma_cap.vlins) | ||
1108 | return -EOPNOTSUPP; | ||
1109 | |||
1110 | tpriv = kzalloc(sizeof(*tpriv), GFP_KERNEL); | ||
1111 | if (!tpriv) | ||
1112 | return -ENOMEM; | ||
1113 | |||
1114 | proto = svlan ? ETH_P_8021AD : ETH_P_8021Q; | ||
1115 | |||
1116 | tpriv->ok = false; | ||
1117 | tpriv->double_vlan = svlan; | ||
1118 | init_completion(&tpriv->comp); | ||
1119 | |||
1120 | tpriv->pt.type = svlan ? htons(ETH_P_8021Q) : htons(ETH_P_IP); | ||
1121 | tpriv->pt.func = stmmac_test_vlan_validate; | ||
1122 | tpriv->pt.dev = priv->dev; | ||
1123 | tpriv->pt.af_packet_priv = tpriv; | ||
1124 | tpriv->packet = &attr; | ||
1125 | tpriv->vlan_id = 0x123; | ||
1126 | dev_add_pack(&tpriv->pt); | ||
1127 | |||
1128 | ret = vlan_vid_add(priv->dev, htons(proto), tpriv->vlan_id); | ||
1129 | if (ret) | ||
1130 | goto cleanup; | ||
1131 | |||
1132 | attr.dst = priv->dev->dev_addr; | ||
1133 | |||
1134 | skb = stmmac_test_get_udp_skb(priv, &attr); | ||
1135 | if (!skb) { | ||
1136 | ret = -ENOMEM; | ||
1137 | goto vlan_del; | ||
1138 | } | ||
1139 | |||
1140 | __vlan_hwaccel_put_tag(skb, htons(proto), tpriv->vlan_id); | ||
1141 | skb->protocol = htons(proto); | ||
1142 | |||
1143 | skb_set_queue_mapping(skb, 0); | ||
1144 | ret = dev_queue_xmit(skb); | ||
1145 | if (ret) | ||
1146 | goto vlan_del; | ||
1147 | |||
1148 | wait_for_completion_timeout(&tpriv->comp, STMMAC_LB_TIMEOUT); | ||
1149 | ret = tpriv->ok ? 0 : -ETIMEDOUT; | ||
1150 | |||
1151 | vlan_del: | ||
1152 | vlan_vid_del(priv->dev, htons(proto), tpriv->vlan_id); | ||
1153 | cleanup: | ||
1154 | dev_remove_pack(&tpriv->pt); | ||
1155 | kfree(tpriv); | ||
1156 | return ret; | ||
1157 | } | ||
1158 | |||
1159 | static int stmmac_test_vlanoff(struct stmmac_priv *priv) | ||
1160 | { | ||
1161 | return stmmac_test_vlanoff_common(priv, false); | ||
1162 | } | ||
1163 | |||
1164 | static int stmmac_test_svlanoff(struct stmmac_priv *priv) | ||
1165 | { | ||
1166 | if (!priv->dma_cap.dvlan) | ||
1167 | return -EOPNOTSUPP; | ||
1168 | return stmmac_test_vlanoff_common(priv, true); | ||
1169 | } | ||
1170 | |||
1087 | #define STMMAC_LOOPBACK_NONE 0 | 1171 | #define STMMAC_LOOPBACK_NONE 0 |
1088 | #define STMMAC_LOOPBACK_MAC 1 | 1172 | #define STMMAC_LOOPBACK_MAC 1 |
1089 | #define STMMAC_LOOPBACK_PHY 2 | 1173 | #define STMMAC_LOOPBACK_PHY 2 |
@@ -1161,6 +1245,14 @@ static const struct stmmac_test { | |||
1161 | .name = "SA Replacement (reg)", | 1245 | .name = "SA Replacement (reg)", |
1162 | .lb = STMMAC_LOOPBACK_PHY, | 1246 | .lb = STMMAC_LOOPBACK_PHY, |
1163 | .fn = stmmac_test_reg_sar, | 1247 | .fn = stmmac_test_reg_sar, |
1248 | }, { | ||
1249 | .name = "VLAN TX Insertion ", | ||
1250 | .lb = STMMAC_LOOPBACK_PHY, | ||
1251 | .fn = stmmac_test_vlanoff, | ||
1252 | }, { | ||
1253 | .name = "SVLAN TX Insertion ", | ||
1254 | .lb = STMMAC_LOOPBACK_PHY, | ||
1255 | .fn = stmmac_test_svlanoff, | ||
1164 | }, | 1256 | }, |
1165 | }; | 1257 | }; |
1166 | 1258 | ||