diff options
-rw-r--r-- | drivers/infiniband/hw/mlx4/ah.c | 10 | ||||
-rw-r--r-- | drivers/infiniband/hw/mlx4/main.c | 99 | ||||
-rw-r--r-- | drivers/infiniband/hw/mlx4/qp.c | 79 | ||||
-rw-r--r-- | drivers/net/mlx4/en_netdev.c | 10 | ||||
-rw-r--r-- | drivers/net/mlx4/mlx4_en.h | 1 | ||||
-rw-r--r-- | drivers/net/mlx4/port.c | 19 | ||||
-rw-r--r-- | include/linux/mlx4/device.h | 1 | ||||
-rw-r--r-- | include/linux/mlx4/qp.h | 2 |
8 files changed, 193 insertions, 28 deletions
diff --git a/drivers/infiniband/hw/mlx4/ah.c b/drivers/infiniband/hw/mlx4/ah.c index 3bf3544c0aa0..4b8f9c49397e 100644 --- a/drivers/infiniband/hw/mlx4/ah.c +++ b/drivers/infiniband/hw/mlx4/ah.c | |||
@@ -31,6 +31,7 @@ | |||
31 | */ | 31 | */ |
32 | 32 | ||
33 | #include <rdma/ib_addr.h> | 33 | #include <rdma/ib_addr.h> |
34 | #include <rdma/ib_cache.h> | ||
34 | 35 | ||
35 | #include <linux/slab.h> | 36 | #include <linux/slab.h> |
36 | #include <linux/inet.h> | 37 | #include <linux/inet.h> |
@@ -91,17 +92,26 @@ static struct ib_ah *create_iboe_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr | |||
91 | { | 92 | { |
92 | struct mlx4_ib_dev *ibdev = to_mdev(pd->device); | 93 | struct mlx4_ib_dev *ibdev = to_mdev(pd->device); |
93 | struct mlx4_dev *dev = ibdev->dev; | 94 | struct mlx4_dev *dev = ibdev->dev; |
95 | union ib_gid sgid; | ||
94 | u8 mac[6]; | 96 | u8 mac[6]; |
95 | int err; | 97 | int err; |
96 | int is_mcast; | 98 | int is_mcast; |
99 | u16 vlan_tag; | ||
97 | 100 | ||
98 | err = mlx4_ib_resolve_grh(ibdev, ah_attr, mac, &is_mcast, ah_attr->port_num); | 101 | err = mlx4_ib_resolve_grh(ibdev, ah_attr, mac, &is_mcast, ah_attr->port_num); |
99 | if (err) | 102 | if (err) |
100 | return ERR_PTR(err); | 103 | return ERR_PTR(err); |
101 | 104 | ||
102 | memcpy(ah->av.eth.mac, mac, 6); | 105 | memcpy(ah->av.eth.mac, mac, 6); |
106 | err = ib_get_cached_gid(pd->device, ah_attr->port_num, ah_attr->grh.sgid_index, &sgid); | ||
107 | if (err) | ||
108 | return ERR_PTR(err); | ||
109 | vlan_tag = rdma_get_vlan_id(&sgid); | ||
110 | if (vlan_tag < 0x1000) | ||
111 | vlan_tag |= (ah_attr->sl & 7) << 13; | ||
103 | ah->av.eth.port_pd = cpu_to_be32(to_mpd(pd)->pdn | (ah_attr->port_num << 24)); | 112 | ah->av.eth.port_pd = cpu_to_be32(to_mpd(pd)->pdn | (ah_attr->port_num << 24)); |
104 | ah->av.eth.gid_index = ah_attr->grh.sgid_index; | 113 | ah->av.eth.gid_index = ah_attr->grh.sgid_index; |
114 | ah->av.eth.vlan = cpu_to_be16(vlan_tag); | ||
105 | if (ah_attr->static_rate) { | 115 | if (ah_attr->static_rate) { |
106 | ah->av.eth.stat_rate = ah_attr->static_rate + MLX4_STAT_RATE_OFFSET; | 116 | ah->av.eth.stat_rate = ah_attr->static_rate + MLX4_STAT_RATE_OFFSET; |
107 | while (ah->av.eth.stat_rate > IB_RATE_2_5_GBPS + MLX4_STAT_RATE_OFFSET && | 117 | while (ah->av.eth.stat_rate > IB_RATE_2_5_GBPS + MLX4_STAT_RATE_OFFSET && |
diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c index e65db73fc277..8736bd836dc0 100644 --- a/drivers/infiniband/hw/mlx4/main.c +++ b/drivers/infiniband/hw/mlx4/main.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <linux/netdevice.h> | 38 | #include <linux/netdevice.h> |
39 | #include <linux/inetdevice.h> | 39 | #include <linux/inetdevice.h> |
40 | #include <linux/rtnetlink.h> | 40 | #include <linux/rtnetlink.h> |
41 | #include <linux/if_vlan.h> | ||
41 | 42 | ||
42 | #include <rdma/ib_smi.h> | 43 | #include <rdma/ib_smi.h> |
43 | #include <rdma/ib_user_verbs.h> | 44 | #include <rdma/ib_user_verbs.h> |
@@ -79,6 +80,8 @@ static void init_query_mad(struct ib_smp *mad) | |||
79 | mad->method = IB_MGMT_METHOD_GET; | 80 | mad->method = IB_MGMT_METHOD_GET; |
80 | } | 81 | } |
81 | 82 | ||
83 | static union ib_gid zgid; | ||
84 | |||
82 | static int mlx4_ib_query_device(struct ib_device *ibdev, | 85 | static int mlx4_ib_query_device(struct ib_device *ibdev, |
83 | struct ib_device_attr *props) | 86 | struct ib_device_attr *props) |
84 | { | 87 | { |
@@ -755,12 +758,17 @@ static struct device_attribute *mlx4_class_attributes[] = { | |||
755 | &dev_attr_board_id | 758 | &dev_attr_board_id |
756 | }; | 759 | }; |
757 | 760 | ||
758 | static void mlx4_addrconf_ifid_eui48(u8 *eui, struct net_device *dev) | 761 | static void mlx4_addrconf_ifid_eui48(u8 *eui, u16 vlan_id, struct net_device *dev) |
759 | { | 762 | { |
760 | memcpy(eui, dev->dev_addr, 3); | 763 | memcpy(eui, dev->dev_addr, 3); |
761 | memcpy(eui + 5, dev->dev_addr + 3, 3); | 764 | memcpy(eui + 5, dev->dev_addr + 3, 3); |
762 | eui[3] = 0xFF; | 765 | if (vlan_id < 0x1000) { |
763 | eui[4] = 0xFE; | 766 | eui[3] = vlan_id >> 8; |
767 | eui[4] = vlan_id & 0xff; | ||
768 | } else { | ||
769 | eui[3] = 0xff; | ||
770 | eui[4] = 0xfe; | ||
771 | } | ||
764 | eui[0] ^= 2; | 772 | eui[0] ^= 2; |
765 | } | 773 | } |
766 | 774 | ||
@@ -802,28 +810,93 @@ static int update_ipv6_gids(struct mlx4_ib_dev *dev, int port, int clear) | |||
802 | { | 810 | { |
803 | struct net_device *ndev = dev->iboe.netdevs[port - 1]; | 811 | struct net_device *ndev = dev->iboe.netdevs[port - 1]; |
804 | struct update_gid_work *work; | 812 | struct update_gid_work *work; |
813 | struct net_device *tmp; | ||
814 | int i; | ||
815 | u8 *hits; | ||
816 | int ret; | ||
817 | union ib_gid gid; | ||
818 | int free; | ||
819 | int found; | ||
820 | int need_update = 0; | ||
821 | u16 vid; | ||
805 | 822 | ||
806 | work = kzalloc(sizeof *work, GFP_ATOMIC); | 823 | work = kzalloc(sizeof *work, GFP_ATOMIC); |
807 | if (!work) | 824 | if (!work) |
808 | return -ENOMEM; | 825 | return -ENOMEM; |
809 | 826 | ||
810 | if (!clear) { | 827 | hits = kzalloc(128, GFP_ATOMIC); |
811 | mlx4_addrconf_ifid_eui48(&work->gids[0].raw[8], ndev); | 828 | if (!hits) { |
812 | work->gids[0].global.subnet_prefix = cpu_to_be64(0xfe80000000000000LL); | 829 | ret = -ENOMEM; |
830 | goto out; | ||
831 | } | ||
832 | |||
833 | read_lock(&dev_base_lock); | ||
834 | for_each_netdev(&init_net, tmp) { | ||
835 | if (ndev && (tmp == ndev || rdma_vlan_dev_real_dev(tmp) == ndev)) { | ||
836 | gid.global.subnet_prefix = cpu_to_be64(0xfe80000000000000LL); | ||
837 | vid = rdma_vlan_dev_vlan_id(tmp); | ||
838 | mlx4_addrconf_ifid_eui48(&gid.raw[8], vid, ndev); | ||
839 | found = 0; | ||
840 | free = -1; | ||
841 | for (i = 0; i < 128; ++i) { | ||
842 | if (free < 0 && | ||
843 | !memcmp(&dev->iboe.gid_table[port - 1][i], &zgid, sizeof zgid)) | ||
844 | free = i; | ||
845 | if (!memcmp(&dev->iboe.gid_table[port - 1][i], &gid, sizeof gid)) { | ||
846 | hits[i] = 1; | ||
847 | found = 1; | ||
848 | break; | ||
849 | } | ||
850 | } | ||
851 | |||
852 | if (!found) { | ||
853 | if (tmp == ndev && | ||
854 | (memcmp(&dev->iboe.gid_table[port - 1][0], | ||
855 | &gid, sizeof gid) || | ||
856 | !memcmp(&dev->iboe.gid_table[port - 1][0], | ||
857 | &zgid, sizeof gid))) { | ||
858 | dev->iboe.gid_table[port - 1][0] = gid; | ||
859 | ++need_update; | ||
860 | hits[0] = 1; | ||
861 | } else if (free >= 0) { | ||
862 | dev->iboe.gid_table[port - 1][free] = gid; | ||
863 | hits[free] = 1; | ||
864 | ++need_update; | ||
865 | } | ||
866 | } | ||
867 | } | ||
813 | } | 868 | } |
869 | read_unlock(&dev_base_lock); | ||
870 | |||
871 | for (i = 0; i < 128; ++i) | ||
872 | if (!hits[i]) { | ||
873 | if (memcmp(&dev->iboe.gid_table[port - 1][i], &zgid, sizeof zgid)) | ||
874 | ++need_update; | ||
875 | dev->iboe.gid_table[port - 1][i] = zgid; | ||
876 | } | ||
814 | 877 | ||
815 | INIT_WORK(&work->work, update_gids_task); | 878 | if (need_update) { |
816 | work->port = port; | 879 | memcpy(work->gids, dev->iboe.gid_table[port - 1], sizeof work->gids); |
817 | work->dev = dev; | 880 | INIT_WORK(&work->work, update_gids_task); |
818 | queue_work(wq, &work->work); | 881 | work->port = port; |
882 | work->dev = dev; | ||
883 | queue_work(wq, &work->work); | ||
884 | } else | ||
885 | kfree(work); | ||
819 | 886 | ||
887 | kfree(hits); | ||
820 | return 0; | 888 | return 0; |
889 | |||
890 | out: | ||
891 | kfree(work); | ||
892 | return ret; | ||
821 | } | 893 | } |
822 | 894 | ||
823 | static void handle_en_event(struct mlx4_ib_dev *dev, int port, unsigned long event) | 895 | static void handle_en_event(struct mlx4_ib_dev *dev, int port, unsigned long event) |
824 | { | 896 | { |
825 | switch (event) { | 897 | switch (event) { |
826 | case NETDEV_UP: | 898 | case NETDEV_UP: |
899 | case NETDEV_CHANGEADDR: | ||
827 | update_ipv6_gids(dev, port, 0); | 900 | update_ipv6_gids(dev, port, 0); |
828 | break; | 901 | break; |
829 | 902 | ||
@@ -871,9 +944,11 @@ static int mlx4_ib_netdev_event(struct notifier_block *this, unsigned long event | |||
871 | } | 944 | } |
872 | } | 945 | } |
873 | 946 | ||
874 | if (dev == iboe->netdevs[0]) | 947 | if (dev == iboe->netdevs[0] || |
948 | (iboe->netdevs[0] && rdma_vlan_dev_real_dev(dev) == iboe->netdevs[0])) | ||
875 | handle_en_event(ibdev, 1, event); | 949 | handle_en_event(ibdev, 1, event); |
876 | else if (dev == iboe->netdevs[1]) | 950 | else if (dev == iboe->netdevs[1] |
951 | || (iboe->netdevs[1] && rdma_vlan_dev_real_dev(dev) == iboe->netdevs[1])) | ||
877 | handle_en_event(ibdev, 2, event); | 952 | handle_en_event(ibdev, 2, event); |
878 | 953 | ||
879 | spin_unlock(&iboe->lock); | 954 | spin_unlock(&iboe->lock); |
diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c index 269648445113..9a7794ac34c1 100644 --- a/drivers/infiniband/hw/mlx4/qp.c +++ b/drivers/infiniband/hw/mlx4/qp.c | |||
@@ -37,6 +37,7 @@ | |||
37 | 37 | ||
38 | #include <rdma/ib_cache.h> | 38 | #include <rdma/ib_cache.h> |
39 | #include <rdma/ib_pack.h> | 39 | #include <rdma/ib_pack.h> |
40 | #include <rdma/ib_addr.h> | ||
40 | 41 | ||
41 | #include <linux/mlx4/qp.h> | 42 | #include <linux/mlx4/qp.h> |
42 | 43 | ||
@@ -57,10 +58,11 @@ enum { | |||
57 | enum { | 58 | enum { |
58 | /* | 59 | /* |
59 | * Largest possible UD header: send with GRH and immediate | 60 | * Largest possible UD header: send with GRH and immediate |
60 | * data plus 14 bytes for an Ethernet header. (LRH would only | 61 | * data plus 18 bytes for an Ethernet header with VLAN/802.1Q |
61 | * use 8 bytes, so Ethernet is the biggest case) | 62 | * tag. (LRH would only use 8 bytes, so Ethernet is the |
63 | * biggest case) | ||
62 | */ | 64 | */ |
63 | MLX4_IB_UD_HEADER_SIZE = 78, | 65 | MLX4_IB_UD_HEADER_SIZE = 82, |
64 | MLX4_IB_LSO_HEADER_SPARE = 128, | 66 | MLX4_IB_LSO_HEADER_SPARE = 128, |
65 | }; | 67 | }; |
66 | 68 | ||
@@ -879,6 +881,8 @@ static int mlx4_set_path(struct mlx4_ib_dev *dev, const struct ib_ah_attr *ah, | |||
879 | IB_LINK_LAYER_ETHERNET; | 881 | IB_LINK_LAYER_ETHERNET; |
880 | u8 mac[6]; | 882 | u8 mac[6]; |
881 | int is_mcast; | 883 | int is_mcast; |
884 | u16 vlan_tag; | ||
885 | int vidx; | ||
882 | 886 | ||
883 | path->grh_mylmc = ah->src_path_bits & 0x7f; | 887 | path->grh_mylmc = ah->src_path_bits & 0x7f; |
884 | path->rlid = cpu_to_be16(ah->dlid); | 888 | path->rlid = cpu_to_be16(ah->dlid); |
@@ -907,10 +911,10 @@ static int mlx4_set_path(struct mlx4_ib_dev *dev, const struct ib_ah_attr *ah, | |||
907 | memcpy(path->rgid, ah->grh.dgid.raw, 16); | 911 | memcpy(path->rgid, ah->grh.dgid.raw, 16); |
908 | } | 912 | } |
909 | 913 | ||
910 | path->sched_queue = MLX4_IB_DEFAULT_SCHED_QUEUE | | ||
911 | ((port - 1) << 6) | ((ah->sl & 0xf) << 2); | ||
912 | |||
913 | if (is_eth) { | 914 | if (is_eth) { |
915 | path->sched_queue = MLX4_IB_DEFAULT_SCHED_QUEUE | | ||
916 | ((port - 1) << 6) | ((ah->sl & 7) << 3) | ((ah->sl & 8) >> 1); | ||
917 | |||
914 | if (!(ah->ah_flags & IB_AH_GRH)) | 918 | if (!(ah->ah_flags & IB_AH_GRH)) |
915 | return -1; | 919 | return -1; |
916 | 920 | ||
@@ -922,7 +926,18 @@ static int mlx4_set_path(struct mlx4_ib_dev *dev, const struct ib_ah_attr *ah, | |||
922 | path->ackto = MLX4_IB_LINK_TYPE_ETH; | 926 | path->ackto = MLX4_IB_LINK_TYPE_ETH; |
923 | /* use index 0 into MAC table for IBoE */ | 927 | /* use index 0 into MAC table for IBoE */ |
924 | path->grh_mylmc &= 0x80; | 928 | path->grh_mylmc &= 0x80; |
925 | } | 929 | |
930 | vlan_tag = rdma_get_vlan_id(&dev->iboe.gid_table[port - 1][ah->grh.sgid_index]); | ||
931 | if (vlan_tag < 0x1000) { | ||
932 | if (mlx4_find_cached_vlan(dev->dev, port, vlan_tag, &vidx)) | ||
933 | return -ENOENT; | ||
934 | |||
935 | path->vlan_index = vidx; | ||
936 | path->fl = 1 << 6; | ||
937 | } | ||
938 | } else | ||
939 | path->sched_queue = MLX4_IB_DEFAULT_SCHED_QUEUE | | ||
940 | ((port - 1) << 6) | ((ah->sl & 0xf) << 2); | ||
926 | 941 | ||
927 | return 0; | 942 | return 0; |
928 | } | 943 | } |
@@ -1277,13 +1292,16 @@ static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr, | |||
1277 | struct mlx4_wqe_mlx_seg *mlx = wqe; | 1292 | struct mlx4_wqe_mlx_seg *mlx = wqe; |
1278 | struct mlx4_wqe_inline_seg *inl = wqe + sizeof *mlx; | 1293 | struct mlx4_wqe_inline_seg *inl = wqe + sizeof *mlx; |
1279 | struct mlx4_ib_ah *ah = to_mah(wr->wr.ud.ah); | 1294 | struct mlx4_ib_ah *ah = to_mah(wr->wr.ud.ah); |
1295 | union ib_gid sgid; | ||
1280 | u16 pkey; | 1296 | u16 pkey; |
1281 | int send_size; | 1297 | int send_size; |
1282 | int header_size; | 1298 | int header_size; |
1283 | int spc; | 1299 | int spc; |
1284 | int i; | 1300 | int i; |
1285 | int is_eth; | 1301 | int is_eth; |
1302 | int is_vlan = 0; | ||
1286 | int is_grh; | 1303 | int is_grh; |
1304 | u16 vlan; | ||
1287 | 1305 | ||
1288 | send_size = 0; | 1306 | send_size = 0; |
1289 | for (i = 0; i < wr->num_sge; ++i) | 1307 | for (i = 0; i < wr->num_sge; ++i) |
@@ -1291,7 +1309,13 @@ static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr, | |||
1291 | 1309 | ||
1292 | is_eth = rdma_port_get_link_layer(sqp->qp.ibqp.device, sqp->qp.port) == IB_LINK_LAYER_ETHERNET; | 1310 | is_eth = rdma_port_get_link_layer(sqp->qp.ibqp.device, sqp->qp.port) == IB_LINK_LAYER_ETHERNET; |
1293 | is_grh = mlx4_ib_ah_grh_present(ah); | 1311 | is_grh = mlx4_ib_ah_grh_present(ah); |
1294 | ib_ud_header_init(send_size, !is_eth, is_eth, 0, is_grh, 0, &sqp->ud_header); | 1312 | if (is_eth) { |
1313 | ib_get_cached_gid(ib_dev, be32_to_cpu(ah->av.ib.port_pd) >> 24, | ||
1314 | ah->av.ib.gid_index, &sgid); | ||
1315 | vlan = rdma_get_vlan_id(&sgid); | ||
1316 | is_vlan = vlan < 0x1000; | ||
1317 | } | ||
1318 | ib_ud_header_init(send_size, !is_eth, is_eth, is_vlan, is_grh, 0, &sqp->ud_header); | ||
1295 | 1319 | ||
1296 | if (!is_eth) { | 1320 | if (!is_eth) { |
1297 | sqp->ud_header.lrh.service_level = | 1321 | sqp->ud_header.lrh.service_level = |
@@ -1345,7 +1369,15 @@ static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr, | |||
1345 | memcpy(sqp->ud_header.eth.smac_h, smac, 6); | 1369 | memcpy(sqp->ud_header.eth.smac_h, smac, 6); |
1346 | if (!memcmp(sqp->ud_header.eth.smac_h, sqp->ud_header.eth.dmac_h, 6)) | 1370 | if (!memcmp(sqp->ud_header.eth.smac_h, sqp->ud_header.eth.dmac_h, 6)) |
1347 | mlx->flags |= cpu_to_be32(MLX4_WQE_CTRL_FORCE_LOOPBACK); | 1371 | mlx->flags |= cpu_to_be32(MLX4_WQE_CTRL_FORCE_LOOPBACK); |
1348 | sqp->ud_header.eth.type = cpu_to_be16(MLX4_IB_IBOE_ETHERTYPE); | 1372 | if (!is_vlan) { |
1373 | sqp->ud_header.eth.type = cpu_to_be16(MLX4_IB_IBOE_ETHERTYPE); | ||
1374 | } else { | ||
1375 | u16 pcp; | ||
1376 | |||
1377 | sqp->ud_header.vlan.type = cpu_to_be16(MLX4_IB_IBOE_ETHERTYPE); | ||
1378 | pcp = (be32_to_cpu(ah->av.ib.sl_tclass_flowlabel) >> 27 & 3) << 13; | ||
1379 | sqp->ud_header.vlan.tag = cpu_to_be16(vlan | pcp); | ||
1380 | } | ||
1349 | } else { | 1381 | } else { |
1350 | sqp->ud_header.lrh.virtual_lane = !sqp->qp.ibqp.qp_num ? 15 : 0; | 1382 | sqp->ud_header.lrh.virtual_lane = !sqp->qp.ibqp.qp_num ? 15 : 0; |
1351 | if (sqp->ud_header.lrh.destination_lid == IB_LID_PERMISSIVE) | 1383 | if (sqp->ud_header.lrh.destination_lid == IB_LID_PERMISSIVE) |
@@ -1507,13 +1539,14 @@ static void set_masked_atomic_seg(struct mlx4_wqe_masked_atomic_seg *aseg, | |||
1507 | } | 1539 | } |
1508 | 1540 | ||
1509 | static void set_datagram_seg(struct mlx4_wqe_datagram_seg *dseg, | 1541 | static void set_datagram_seg(struct mlx4_wqe_datagram_seg *dseg, |
1510 | struct ib_send_wr *wr) | 1542 | struct ib_send_wr *wr, __be16 *vlan) |
1511 | { | 1543 | { |
1512 | memcpy(dseg->av, &to_mah(wr->wr.ud.ah)->av, sizeof (struct mlx4_av)); | 1544 | memcpy(dseg->av, &to_mah(wr->wr.ud.ah)->av, sizeof (struct mlx4_av)); |
1513 | dseg->dqpn = cpu_to_be32(wr->wr.ud.remote_qpn); | 1545 | dseg->dqpn = cpu_to_be32(wr->wr.ud.remote_qpn); |
1514 | dseg->qkey = cpu_to_be32(wr->wr.ud.remote_qkey); | 1546 | dseg->qkey = cpu_to_be32(wr->wr.ud.remote_qkey); |
1515 | dseg->vlan = to_mah(wr->wr.ud.ah)->av.eth.vlan; | 1547 | dseg->vlan = to_mah(wr->wr.ud.ah)->av.eth.vlan; |
1516 | memcpy(dseg->mac, to_mah(wr->wr.ud.ah)->av.eth.mac, 6); | 1548 | memcpy(dseg->mac, to_mah(wr->wr.ud.ah)->av.eth.mac, 6); |
1549 | *vlan = dseg->vlan; | ||
1517 | } | 1550 | } |
1518 | 1551 | ||
1519 | static void set_mlx_icrc_seg(void *dseg) | 1552 | static void set_mlx_icrc_seg(void *dseg) |
@@ -1616,6 +1649,7 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, | |||
1616 | __be32 uninitialized_var(lso_hdr_sz); | 1649 | __be32 uninitialized_var(lso_hdr_sz); |
1617 | __be32 blh; | 1650 | __be32 blh; |
1618 | int i; | 1651 | int i; |
1652 | __be16 vlan = cpu_to_be16(0xffff); | ||
1619 | 1653 | ||
1620 | spin_lock_irqsave(&qp->sq.lock, flags); | 1654 | spin_lock_irqsave(&qp->sq.lock, flags); |
1621 | 1655 | ||
@@ -1719,7 +1753,7 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, | |||
1719 | break; | 1753 | break; |
1720 | 1754 | ||
1721 | case IB_QPT_UD: | 1755 | case IB_QPT_UD: |
1722 | set_datagram_seg(wqe, wr); | 1756 | set_datagram_seg(wqe, wr, &vlan); |
1723 | wqe += sizeof (struct mlx4_wqe_datagram_seg); | 1757 | wqe += sizeof (struct mlx4_wqe_datagram_seg); |
1724 | size += sizeof (struct mlx4_wqe_datagram_seg) / 16; | 1758 | size += sizeof (struct mlx4_wqe_datagram_seg) / 16; |
1725 | 1759 | ||
@@ -1797,6 +1831,11 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, | |||
1797 | ctrl->owner_opcode = mlx4_ib_opcode[wr->opcode] | | 1831 | ctrl->owner_opcode = mlx4_ib_opcode[wr->opcode] | |
1798 | (ind & qp->sq.wqe_cnt ? cpu_to_be32(1 << 31) : 0) | blh; | 1832 | (ind & qp->sq.wqe_cnt ? cpu_to_be32(1 << 31) : 0) | blh; |
1799 | 1833 | ||
1834 | if (be16_to_cpu(vlan) < 0x1000) { | ||
1835 | ctrl->ins_vlan = 1 << 6; | ||
1836 | ctrl->vlan_tag = vlan; | ||
1837 | } | ||
1838 | |||
1800 | stamp = ind + qp->sq_spare_wqes; | 1839 | stamp = ind + qp->sq_spare_wqes; |
1801 | ind += DIV_ROUND_UP(size * 16, 1U << qp->sq.wqe_shift); | 1840 | ind += DIV_ROUND_UP(size * 16, 1U << qp->sq.wqe_shift); |
1802 | 1841 | ||
@@ -1946,17 +1985,27 @@ static int to_ib_qp_access_flags(int mlx4_flags) | |||
1946 | return ib_flags; | 1985 | return ib_flags; |
1947 | } | 1986 | } |
1948 | 1987 | ||
1949 | static void to_ib_ah_attr(struct mlx4_dev *dev, struct ib_ah_attr *ib_ah_attr, | 1988 | static void to_ib_ah_attr(struct mlx4_ib_dev *ibdev, struct ib_ah_attr *ib_ah_attr, |
1950 | struct mlx4_qp_path *path) | 1989 | struct mlx4_qp_path *path) |
1951 | { | 1990 | { |
1991 | struct mlx4_dev *dev = ibdev->dev; | ||
1992 | int is_eth; | ||
1993 | |||
1952 | memset(ib_ah_attr, 0, sizeof *ib_ah_attr); | 1994 | memset(ib_ah_attr, 0, sizeof *ib_ah_attr); |
1953 | ib_ah_attr->port_num = path->sched_queue & 0x40 ? 2 : 1; | 1995 | ib_ah_attr->port_num = path->sched_queue & 0x40 ? 2 : 1; |
1954 | 1996 | ||
1955 | if (ib_ah_attr->port_num == 0 || ib_ah_attr->port_num > dev->caps.num_ports) | 1997 | if (ib_ah_attr->port_num == 0 || ib_ah_attr->port_num > dev->caps.num_ports) |
1956 | return; | 1998 | return; |
1957 | 1999 | ||
2000 | is_eth = rdma_port_get_link_layer(&ibdev->ib_dev, ib_ah_attr->port_num) == | ||
2001 | IB_LINK_LAYER_ETHERNET; | ||
2002 | if (is_eth) | ||
2003 | ib_ah_attr->sl = ((path->sched_queue >> 3) & 0x7) | | ||
2004 | ((path->sched_queue & 4) << 1); | ||
2005 | else | ||
2006 | ib_ah_attr->sl = (path->sched_queue >> 2) & 0xf; | ||
2007 | |||
1958 | ib_ah_attr->dlid = be16_to_cpu(path->rlid); | 2008 | ib_ah_attr->dlid = be16_to_cpu(path->rlid); |
1959 | ib_ah_attr->sl = (path->sched_queue >> 2) & 0xf; | ||
1960 | ib_ah_attr->src_path_bits = path->grh_mylmc & 0x7f; | 2009 | ib_ah_attr->src_path_bits = path->grh_mylmc & 0x7f; |
1961 | ib_ah_attr->static_rate = path->static_rate ? path->static_rate - 5 : 0; | 2010 | ib_ah_attr->static_rate = path->static_rate ? path->static_rate - 5 : 0; |
1962 | ib_ah_attr->ah_flags = (path->grh_mylmc & (1 << 7)) ? IB_AH_GRH : 0; | 2011 | ib_ah_attr->ah_flags = (path->grh_mylmc & (1 << 7)) ? IB_AH_GRH : 0; |
@@ -2009,8 +2058,8 @@ int mlx4_ib_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, int qp_attr | |||
2009 | to_ib_qp_access_flags(be32_to_cpu(context.params2)); | 2058 | to_ib_qp_access_flags(be32_to_cpu(context.params2)); |
2010 | 2059 | ||
2011 | if (qp->ibqp.qp_type == IB_QPT_RC || qp->ibqp.qp_type == IB_QPT_UC) { | 2060 | if (qp->ibqp.qp_type == IB_QPT_RC || qp->ibqp.qp_type == IB_QPT_UC) { |
2012 | to_ib_ah_attr(dev->dev, &qp_attr->ah_attr, &context.pri_path); | 2061 | to_ib_ah_attr(dev, &qp_attr->ah_attr, &context.pri_path); |
2013 | to_ib_ah_attr(dev->dev, &qp_attr->alt_ah_attr, &context.alt_path); | 2062 | to_ib_ah_attr(dev, &qp_attr->alt_ah_attr, &context.alt_path); |
2014 | qp_attr->alt_pkey_index = context.alt_path.pkey_index & 0x7f; | 2063 | qp_attr->alt_pkey_index = context.alt_path.pkey_index & 0x7f; |
2015 | qp_attr->alt_port_num = qp_attr->alt_ah_attr.port_num; | 2064 | qp_attr->alt_port_num = qp_attr->alt_ah_attr.port_num; |
2016 | } | 2065 | } |
diff --git a/drivers/net/mlx4/en_netdev.c b/drivers/net/mlx4/en_netdev.c index a0d8a26f5a02..9a87c4f3bbbd 100644 --- a/drivers/net/mlx4/en_netdev.c +++ b/drivers/net/mlx4/en_netdev.c | |||
@@ -69,6 +69,7 @@ static void mlx4_en_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) | |||
69 | struct mlx4_en_priv *priv = netdev_priv(dev); | 69 | struct mlx4_en_priv *priv = netdev_priv(dev); |
70 | struct mlx4_en_dev *mdev = priv->mdev; | 70 | struct mlx4_en_dev *mdev = priv->mdev; |
71 | int err; | 71 | int err; |
72 | int idx; | ||
72 | 73 | ||
73 | if (!priv->vlgrp) | 74 | if (!priv->vlgrp) |
74 | return; | 75 | return; |
@@ -83,7 +84,10 @@ static void mlx4_en_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) | |||
83 | if (err) | 84 | if (err) |
84 | en_err(priv, "Failed configuring VLAN filter\n"); | 85 | en_err(priv, "Failed configuring VLAN filter\n"); |
85 | } | 86 | } |
87 | if (mlx4_register_vlan(mdev->dev, priv->port, vid, &idx)) | ||
88 | en_err(priv, "failed adding vlan %d\n", vid); | ||
86 | mutex_unlock(&mdev->state_lock); | 89 | mutex_unlock(&mdev->state_lock); |
90 | |||
87 | } | 91 | } |
88 | 92 | ||
89 | static void mlx4_en_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) | 93 | static void mlx4_en_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) |
@@ -91,6 +95,7 @@ static void mlx4_en_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) | |||
91 | struct mlx4_en_priv *priv = netdev_priv(dev); | 95 | struct mlx4_en_priv *priv = netdev_priv(dev); |
92 | struct mlx4_en_dev *mdev = priv->mdev; | 96 | struct mlx4_en_dev *mdev = priv->mdev; |
93 | int err; | 97 | int err; |
98 | int idx; | ||
94 | 99 | ||
95 | if (!priv->vlgrp) | 100 | if (!priv->vlgrp) |
96 | return; | 101 | return; |
@@ -101,6 +106,11 @@ static void mlx4_en_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) | |||
101 | 106 | ||
102 | /* Remove VID from port VLAN filter */ | 107 | /* Remove VID from port VLAN filter */ |
103 | mutex_lock(&mdev->state_lock); | 108 | mutex_lock(&mdev->state_lock); |
109 | if (!mlx4_find_cached_vlan(mdev->dev, priv->port, vid, &idx)) | ||
110 | mlx4_unregister_vlan(mdev->dev, priv->port, idx); | ||
111 | else | ||
112 | en_err(priv, "could not find vid %d in cache\n", vid); | ||
113 | |||
104 | if (mdev->device_up && priv->port_up) { | 114 | if (mdev->device_up && priv->port_up) { |
105 | err = mlx4_SET_VLAN_FLTR(mdev->dev, priv->port, priv->vlgrp); | 115 | err = mlx4_SET_VLAN_FLTR(mdev->dev, priv->port, priv->vlgrp); |
106 | if (err) | 116 | if (err) |
diff --git a/drivers/net/mlx4/mlx4_en.h b/drivers/net/mlx4/mlx4_en.h index 449210994ee9..dab5eafb8946 100644 --- a/drivers/net/mlx4/mlx4_en.h +++ b/drivers/net/mlx4/mlx4_en.h | |||
@@ -463,6 +463,7 @@ struct mlx4_en_priv { | |||
463 | char *mc_addrs; | 463 | char *mc_addrs; |
464 | int mc_addrs_cnt; | 464 | int mc_addrs_cnt; |
465 | struct mlx4_en_stat_out_mbox hw_stats; | 465 | struct mlx4_en_stat_out_mbox hw_stats; |
466 | int vids[128]; | ||
466 | }; | 467 | }; |
467 | 468 | ||
468 | 469 | ||
diff --git a/drivers/net/mlx4/port.c b/drivers/net/mlx4/port.c index 606aa58afdea..56371ef328ef 100644 --- a/drivers/net/mlx4/port.c +++ b/drivers/net/mlx4/port.c | |||
@@ -182,6 +182,25 @@ static int mlx4_set_port_vlan_table(struct mlx4_dev *dev, u8 port, | |||
182 | return err; | 182 | return err; |
183 | } | 183 | } |
184 | 184 | ||
185 | int mlx4_find_cached_vlan(struct mlx4_dev *dev, u8 port, u16 vid, int *idx) | ||
186 | { | ||
187 | struct mlx4_vlan_table *table = &mlx4_priv(dev)->port[port].vlan_table; | ||
188 | int i; | ||
189 | |||
190 | for (i = 0; i < MLX4_MAX_VLAN_NUM; ++i) { | ||
191 | if (table->refs[i] && | ||
192 | (vid == (MLX4_VLAN_MASK & | ||
193 | be32_to_cpu(table->entries[i])))) { | ||
194 | /* VLAN already registered, increase reference count */ | ||
195 | *idx = i; | ||
196 | return 0; | ||
197 | } | ||
198 | } | ||
199 | |||
200 | return -ENOENT; | ||
201 | } | ||
202 | EXPORT_SYMBOL_GPL(mlx4_find_cached_vlan); | ||
203 | |||
185 | int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index) | 204 | int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index) |
186 | { | 205 | { |
187 | struct mlx4_vlan_table *table = &mlx4_priv(dev)->port[port].vlan_table; | 206 | struct mlx4_vlan_table *table = &mlx4_priv(dev)->port[port].vlan_table; |
diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h index ca5645c43f61..ff9893a33e90 100644 --- a/include/linux/mlx4/device.h +++ b/include/linux/mlx4/device.h | |||
@@ -496,6 +496,7 @@ int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16]); | |||
496 | int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac, int *index); | 496 | int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac, int *index); |
497 | void mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, int index); | 497 | void mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, int index); |
498 | 498 | ||
499 | int mlx4_find_cached_vlan(struct mlx4_dev *dev, u8 port, u16 vid, int *idx); | ||
499 | int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index); | 500 | int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index); |
500 | void mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, int index); | 501 | void mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, int index); |
501 | 502 | ||
diff --git a/include/linux/mlx4/qp.h b/include/linux/mlx4/qp.h index 97cfdc8d7e2f..0eeb2a1a867c 100644 --- a/include/linux/mlx4/qp.h +++ b/include/linux/mlx4/qp.h | |||
@@ -109,7 +109,7 @@ struct mlx4_qp_path { | |||
109 | __be32 tclass_flowlabel; | 109 | __be32 tclass_flowlabel; |
110 | u8 rgid[16]; | 110 | u8 rgid[16]; |
111 | u8 sched_queue; | 111 | u8 sched_queue; |
112 | u8 snooper_flags; | 112 | u8 vlan_index; |
113 | u8 reserved3[2]; | 113 | u8 reserved3[2]; |
114 | u8 counter_index; | 114 | u8 counter_index; |
115 | u8 reserved4; | 115 | u8 reserved4; |