diff options
Diffstat (limited to 'drivers/net/ethernet/mellanox')
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/main.c | 16 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/mcg.c | 106 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/mlx4.h | 76 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/resource_tracker.c | 116 |
4 files changed, 216 insertions, 98 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index 827b72dfce99..2f816c6aed72 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c | |||
@@ -1234,13 +1234,13 @@ static int mlx4_init_hca(struct mlx4_dev *dev) | |||
1234 | mlx4_info(dev, "non-primary physical function, skipping.\n"); | 1234 | mlx4_info(dev, "non-primary physical function, skipping.\n"); |
1235 | else | 1235 | else |
1236 | mlx4_err(dev, "QUERY_FW command failed, aborting.\n"); | 1236 | mlx4_err(dev, "QUERY_FW command failed, aborting.\n"); |
1237 | goto unmap_bf; | 1237 | return err; |
1238 | } | 1238 | } |
1239 | 1239 | ||
1240 | err = mlx4_load_fw(dev); | 1240 | err = mlx4_load_fw(dev); |
1241 | if (err) { | 1241 | if (err) { |
1242 | mlx4_err(dev, "Failed to start FW, aborting.\n"); | 1242 | mlx4_err(dev, "Failed to start FW, aborting.\n"); |
1243 | goto unmap_bf; | 1243 | return err; |
1244 | } | 1244 | } |
1245 | 1245 | ||
1246 | mlx4_cfg.log_pg_sz_m = 1; | 1246 | mlx4_cfg.log_pg_sz_m = 1; |
@@ -1304,7 +1304,7 @@ static int mlx4_init_hca(struct mlx4_dev *dev) | |||
1304 | err = mlx4_init_slave(dev); | 1304 | err = mlx4_init_slave(dev); |
1305 | if (err) { | 1305 | if (err) { |
1306 | mlx4_err(dev, "Failed to initialize slave\n"); | 1306 | mlx4_err(dev, "Failed to initialize slave\n"); |
1307 | goto unmap_bf; | 1307 | return err; |
1308 | } | 1308 | } |
1309 | 1309 | ||
1310 | err = mlx4_slave_cap(dev); | 1310 | err = mlx4_slave_cap(dev); |
@@ -1324,7 +1324,7 @@ static int mlx4_init_hca(struct mlx4_dev *dev) | |||
1324 | err = mlx4_QUERY_ADAPTER(dev, &adapter); | 1324 | err = mlx4_QUERY_ADAPTER(dev, &adapter); |
1325 | if (err) { | 1325 | if (err) { |
1326 | mlx4_err(dev, "QUERY_ADAPTER command failed, aborting.\n"); | 1326 | mlx4_err(dev, "QUERY_ADAPTER command failed, aborting.\n"); |
1327 | goto err_close; | 1327 | goto unmap_bf; |
1328 | } | 1328 | } |
1329 | 1329 | ||
1330 | priv->eq_table.inta_pin = adapter.inta_pin; | 1330 | priv->eq_table.inta_pin = adapter.inta_pin; |
@@ -1332,6 +1332,9 @@ static int mlx4_init_hca(struct mlx4_dev *dev) | |||
1332 | 1332 | ||
1333 | return 0; | 1333 | return 0; |
1334 | 1334 | ||
1335 | unmap_bf: | ||
1336 | unmap_bf_area(dev); | ||
1337 | |||
1335 | err_close: | 1338 | err_close: |
1336 | mlx4_close_hca(dev); | 1339 | mlx4_close_hca(dev); |
1337 | 1340 | ||
@@ -1344,8 +1347,6 @@ err_stop_fw: | |||
1344 | mlx4_UNMAP_FA(dev); | 1347 | mlx4_UNMAP_FA(dev); |
1345 | mlx4_free_icm(dev, priv->fw.fw_icm, 0); | 1348 | mlx4_free_icm(dev, priv->fw.fw_icm, 0); |
1346 | } | 1349 | } |
1347 | unmap_bf: | ||
1348 | unmap_bf_area(dev); | ||
1349 | return err; | 1350 | return err; |
1350 | } | 1351 | } |
1351 | 1352 | ||
@@ -1996,7 +1997,8 @@ static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1996 | } | 1997 | } |
1997 | 1998 | ||
1998 | slave_start: | 1999 | slave_start: |
1999 | if (mlx4_cmd_init(dev)) { | 2000 | err = mlx4_cmd_init(dev); |
2001 | if (err) { | ||
2000 | mlx4_err(dev, "Failed to init command interface, aborting.\n"); | 2002 | mlx4_err(dev, "Failed to init command interface, aborting.\n"); |
2001 | goto err_sriov; | 2003 | goto err_sriov; |
2002 | } | 2004 | } |
diff --git a/drivers/net/ethernet/mellanox/mlx4/mcg.c b/drivers/net/ethernet/mellanox/mlx4/mcg.c index a018ea2a43de..e151c21baf2b 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mcg.c +++ b/drivers/net/ethernet/mellanox/mlx4/mcg.c | |||
@@ -137,11 +137,11 @@ static int mlx4_GID_HASH(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox, | |||
137 | return err; | 137 | return err; |
138 | } | 138 | } |
139 | 139 | ||
140 | static struct mlx4_promisc_qp *get_promisc_qp(struct mlx4_dev *dev, u8 pf_num, | 140 | static struct mlx4_promisc_qp *get_promisc_qp(struct mlx4_dev *dev, u8 port, |
141 | enum mlx4_steer_type steer, | 141 | enum mlx4_steer_type steer, |
142 | u32 qpn) | 142 | u32 qpn) |
143 | { | 143 | { |
144 | struct mlx4_steer *s_steer = &mlx4_priv(dev)->steer[pf_num]; | 144 | struct mlx4_steer *s_steer = &mlx4_priv(dev)->steer[port - 1]; |
145 | struct mlx4_promisc_qp *pqp; | 145 | struct mlx4_promisc_qp *pqp; |
146 | 146 | ||
147 | list_for_each_entry(pqp, &s_steer->promisc_qps[steer], list) { | 147 | list_for_each_entry(pqp, &s_steer->promisc_qps[steer], list) { |
@@ -182,7 +182,7 @@ static int new_steering_entry(struct mlx4_dev *dev, u8 port, | |||
182 | /* If the given qpn is also a promisc qp, | 182 | /* If the given qpn is also a promisc qp, |
183 | * it should be inserted to duplicates list | 183 | * it should be inserted to duplicates list |
184 | */ | 184 | */ |
185 | pqp = get_promisc_qp(dev, 0, steer, qpn); | 185 | pqp = get_promisc_qp(dev, port, steer, qpn); |
186 | if (pqp) { | 186 | if (pqp) { |
187 | dqp = kmalloc(sizeof *dqp, GFP_KERNEL); | 187 | dqp = kmalloc(sizeof *dqp, GFP_KERNEL); |
188 | if (!dqp) { | 188 | if (!dqp) { |
@@ -256,7 +256,7 @@ static int existing_steering_entry(struct mlx4_dev *dev, u8 port, | |||
256 | 256 | ||
257 | s_steer = &mlx4_priv(dev)->steer[port - 1]; | 257 | s_steer = &mlx4_priv(dev)->steer[port - 1]; |
258 | 258 | ||
259 | pqp = get_promisc_qp(dev, 0, steer, qpn); | 259 | pqp = get_promisc_qp(dev, port, steer, qpn); |
260 | if (!pqp) | 260 | if (!pqp) |
261 | return 0; /* nothing to do */ | 261 | return 0; /* nothing to do */ |
262 | 262 | ||
@@ -302,7 +302,7 @@ static bool check_duplicate_entry(struct mlx4_dev *dev, u8 port, | |||
302 | s_steer = &mlx4_priv(dev)->steer[port - 1]; | 302 | s_steer = &mlx4_priv(dev)->steer[port - 1]; |
303 | 303 | ||
304 | /* if qp is not promisc, it cannot be duplicated */ | 304 | /* if qp is not promisc, it cannot be duplicated */ |
305 | if (!get_promisc_qp(dev, 0, steer, qpn)) | 305 | if (!get_promisc_qp(dev, port, steer, qpn)) |
306 | return false; | 306 | return false; |
307 | 307 | ||
308 | /* The qp is promisc qp so it is a duplicate on this index | 308 | /* The qp is promisc qp so it is a duplicate on this index |
@@ -352,7 +352,7 @@ static bool can_remove_steering_entry(struct mlx4_dev *dev, u8 port, | |||
352 | members_count = be32_to_cpu(mgm->members_count) & 0xffffff; | 352 | members_count = be32_to_cpu(mgm->members_count) & 0xffffff; |
353 | for (i = 0; i < members_count; i++) { | 353 | for (i = 0; i < members_count; i++) { |
354 | qpn = be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK; | 354 | qpn = be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK; |
355 | if (!get_promisc_qp(dev, 0, steer, qpn) && qpn != tqpn) { | 355 | if (!get_promisc_qp(dev, port, steer, qpn) && qpn != tqpn) { |
356 | /* the qp is not promisc, the entry can't be removed */ | 356 | /* the qp is not promisc, the entry can't be removed */ |
357 | goto out; | 357 | goto out; |
358 | } | 358 | } |
@@ -398,7 +398,7 @@ static int add_promisc_qp(struct mlx4_dev *dev, u8 port, | |||
398 | 398 | ||
399 | mutex_lock(&priv->mcg_table.mutex); | 399 | mutex_lock(&priv->mcg_table.mutex); |
400 | 400 | ||
401 | if (get_promisc_qp(dev, 0, steer, qpn)) { | 401 | if (get_promisc_qp(dev, port, steer, qpn)) { |
402 | err = 0; /* Noting to do, already exists */ | 402 | err = 0; /* Noting to do, already exists */ |
403 | goto out_mutex; | 403 | goto out_mutex; |
404 | } | 404 | } |
@@ -503,7 +503,7 @@ static int remove_promisc_qp(struct mlx4_dev *dev, u8 port, | |||
503 | s_steer = &mlx4_priv(dev)->steer[port - 1]; | 503 | s_steer = &mlx4_priv(dev)->steer[port - 1]; |
504 | mutex_lock(&priv->mcg_table.mutex); | 504 | mutex_lock(&priv->mcg_table.mutex); |
505 | 505 | ||
506 | pqp = get_promisc_qp(dev, 0, steer, qpn); | 506 | pqp = get_promisc_qp(dev, port, steer, qpn); |
507 | if (unlikely(!pqp)) { | 507 | if (unlikely(!pqp)) { |
508 | mlx4_warn(dev, "QP %x is not promiscuous QP\n", qpn); | 508 | mlx4_warn(dev, "QP %x is not promiscuous QP\n", qpn); |
509 | /* nothing to do */ | 509 | /* nothing to do */ |
@@ -650,13 +650,6 @@ static int find_entry(struct mlx4_dev *dev, u8 port, | |||
650 | return err; | 650 | return err; |
651 | } | 651 | } |
652 | 652 | ||
653 | struct mlx4_net_trans_rule_hw_ctrl { | ||
654 | __be32 ctrl; | ||
655 | __be32 vf_vep_port; | ||
656 | __be32 qpn; | ||
657 | __be32 reserved; | ||
658 | }; | ||
659 | |||
660 | static void trans_rule_ctrl_to_hw(struct mlx4_net_trans_rule *ctrl, | 653 | static void trans_rule_ctrl_to_hw(struct mlx4_net_trans_rule *ctrl, |
661 | struct mlx4_net_trans_rule_hw_ctrl *hw) | 654 | struct mlx4_net_trans_rule_hw_ctrl *hw) |
662 | { | 655 | { |
@@ -680,87 +673,18 @@ static void trans_rule_ctrl_to_hw(struct mlx4_net_trans_rule *ctrl, | |||
680 | hw->qpn = cpu_to_be32(ctrl->qpn); | 673 | hw->qpn = cpu_to_be32(ctrl->qpn); |
681 | } | 674 | } |
682 | 675 | ||
683 | struct mlx4_net_trans_rule_hw_ib { | 676 | const u16 __sw_id_hw[] = { |
684 | u8 size; | 677 | [MLX4_NET_TRANS_RULE_ID_ETH] = 0xE001, |
685 | u8 rsvd1; | 678 | [MLX4_NET_TRANS_RULE_ID_IB] = 0xE005, |
686 | __be16 id; | 679 | [MLX4_NET_TRANS_RULE_ID_IPV6] = 0xE003, |
687 | u32 rsvd2; | 680 | [MLX4_NET_TRANS_RULE_ID_IPV4] = 0xE002, |
688 | __be32 qpn; | 681 | [MLX4_NET_TRANS_RULE_ID_TCP] = 0xE004, |
689 | __be32 qpn_mask; | 682 | [MLX4_NET_TRANS_RULE_ID_UDP] = 0xE006 |
690 | u8 dst_gid[16]; | ||
691 | u8 dst_gid_msk[16]; | ||
692 | } __packed; | ||
693 | |||
694 | struct mlx4_net_trans_rule_hw_eth { | ||
695 | u8 size; | ||
696 | u8 rsvd; | ||
697 | __be16 id; | ||
698 | u8 rsvd1[6]; | ||
699 | u8 dst_mac[6]; | ||
700 | u16 rsvd2; | ||
701 | u8 dst_mac_msk[6]; | ||
702 | u16 rsvd3; | ||
703 | u8 src_mac[6]; | ||
704 | u16 rsvd4; | ||
705 | u8 src_mac_msk[6]; | ||
706 | u8 rsvd5; | ||
707 | u8 ether_type_enable; | ||
708 | __be16 ether_type; | ||
709 | __be16 vlan_id_msk; | ||
710 | __be16 vlan_id; | ||
711 | } __packed; | ||
712 | |||
713 | struct mlx4_net_trans_rule_hw_tcp_udp { | ||
714 | u8 size; | ||
715 | u8 rsvd; | ||
716 | __be16 id; | ||
717 | __be16 rsvd1[3]; | ||
718 | __be16 dst_port; | ||
719 | __be16 rsvd2; | ||
720 | __be16 dst_port_msk; | ||
721 | __be16 rsvd3; | ||
722 | __be16 src_port; | ||
723 | __be16 rsvd4; | ||
724 | __be16 src_port_msk; | ||
725 | } __packed; | ||
726 | |||
727 | struct mlx4_net_trans_rule_hw_ipv4 { | ||
728 | u8 size; | ||
729 | u8 rsvd; | ||
730 | __be16 id; | ||
731 | __be32 rsvd1; | ||
732 | __be32 dst_ip; | ||
733 | __be32 dst_ip_msk; | ||
734 | __be32 src_ip; | ||
735 | __be32 src_ip_msk; | ||
736 | } __packed; | ||
737 | |||
738 | struct _rule_hw { | ||
739 | union { | ||
740 | struct { | ||
741 | u8 size; | ||
742 | u8 rsvd; | ||
743 | __be16 id; | ||
744 | }; | ||
745 | struct mlx4_net_trans_rule_hw_eth eth; | ||
746 | struct mlx4_net_trans_rule_hw_ib ib; | ||
747 | struct mlx4_net_trans_rule_hw_ipv4 ipv4; | ||
748 | struct mlx4_net_trans_rule_hw_tcp_udp tcp_udp; | ||
749 | }; | ||
750 | }; | 683 | }; |
751 | 684 | ||
752 | static int parse_trans_rule(struct mlx4_dev *dev, struct mlx4_spec_list *spec, | 685 | static int parse_trans_rule(struct mlx4_dev *dev, struct mlx4_spec_list *spec, |
753 | struct _rule_hw *rule_hw) | 686 | struct _rule_hw *rule_hw) |
754 | { | 687 | { |
755 | static const u16 __sw_id_hw[] = { | ||
756 | [MLX4_NET_TRANS_RULE_ID_ETH] = 0xE001, | ||
757 | [MLX4_NET_TRANS_RULE_ID_IB] = 0xE005, | ||
758 | [MLX4_NET_TRANS_RULE_ID_IPV6] = 0xE003, | ||
759 | [MLX4_NET_TRANS_RULE_ID_IPV4] = 0xE002, | ||
760 | [MLX4_NET_TRANS_RULE_ID_TCP] = 0xE004, | ||
761 | [MLX4_NET_TRANS_RULE_ID_UDP] = 0xE006 | ||
762 | }; | ||
763 | |||
764 | static const size_t __rule_hw_sz[] = { | 688 | static const size_t __rule_hw_sz[] = { |
765 | [MLX4_NET_TRANS_RULE_ID_ETH] = | 689 | [MLX4_NET_TRANS_RULE_ID_ETH] = |
766 | sizeof(struct mlx4_net_trans_rule_hw_eth), | 690 | sizeof(struct mlx4_net_trans_rule_hw_eth), |
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h index 4d9df8f2a126..dba69d98734a 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h | |||
@@ -690,6 +690,82 @@ struct mlx4_steer { | |||
690 | struct list_head steer_entries[MLX4_NUM_STEERS]; | 690 | struct list_head steer_entries[MLX4_NUM_STEERS]; |
691 | }; | 691 | }; |
692 | 692 | ||
693 | struct mlx4_net_trans_rule_hw_ctrl { | ||
694 | __be32 ctrl; | ||
695 | __be32 vf_vep_port; | ||
696 | __be32 qpn; | ||
697 | __be32 reserved; | ||
698 | }; | ||
699 | |||
700 | struct mlx4_net_trans_rule_hw_ib { | ||
701 | u8 size; | ||
702 | u8 rsvd1; | ||
703 | __be16 id; | ||
704 | u32 rsvd2; | ||
705 | __be32 qpn; | ||
706 | __be32 qpn_mask; | ||
707 | u8 dst_gid[16]; | ||
708 | u8 dst_gid_msk[16]; | ||
709 | } __packed; | ||
710 | |||
711 | struct mlx4_net_trans_rule_hw_eth { | ||
712 | u8 size; | ||
713 | u8 rsvd; | ||
714 | __be16 id; | ||
715 | u8 rsvd1[6]; | ||
716 | u8 dst_mac[6]; | ||
717 | u16 rsvd2; | ||
718 | u8 dst_mac_msk[6]; | ||
719 | u16 rsvd3; | ||
720 | u8 src_mac[6]; | ||
721 | u16 rsvd4; | ||
722 | u8 src_mac_msk[6]; | ||
723 | u8 rsvd5; | ||
724 | u8 ether_type_enable; | ||
725 | __be16 ether_type; | ||
726 | __be16 vlan_id_msk; | ||
727 | __be16 vlan_id; | ||
728 | } __packed; | ||
729 | |||
730 | struct mlx4_net_trans_rule_hw_tcp_udp { | ||
731 | u8 size; | ||
732 | u8 rsvd; | ||
733 | __be16 id; | ||
734 | __be16 rsvd1[3]; | ||
735 | __be16 dst_port; | ||
736 | __be16 rsvd2; | ||
737 | __be16 dst_port_msk; | ||
738 | __be16 rsvd3; | ||
739 | __be16 src_port; | ||
740 | __be16 rsvd4; | ||
741 | __be16 src_port_msk; | ||
742 | } __packed; | ||
743 | |||
744 | struct mlx4_net_trans_rule_hw_ipv4 { | ||
745 | u8 size; | ||
746 | u8 rsvd; | ||
747 | __be16 id; | ||
748 | __be32 rsvd1; | ||
749 | __be32 dst_ip; | ||
750 | __be32 dst_ip_msk; | ||
751 | __be32 src_ip; | ||
752 | __be32 src_ip_msk; | ||
753 | } __packed; | ||
754 | |||
755 | struct _rule_hw { | ||
756 | union { | ||
757 | struct { | ||
758 | u8 size; | ||
759 | u8 rsvd; | ||
760 | __be16 id; | ||
761 | }; | ||
762 | struct mlx4_net_trans_rule_hw_eth eth; | ||
763 | struct mlx4_net_trans_rule_hw_ib ib; | ||
764 | struct mlx4_net_trans_rule_hw_ipv4 ipv4; | ||
765 | struct mlx4_net_trans_rule_hw_tcp_udp tcp_udp; | ||
766 | }; | ||
767 | }; | ||
768 | |||
693 | struct mlx4_priv { | 769 | struct mlx4_priv { |
694 | struct mlx4_dev dev; | 770 | struct mlx4_dev dev; |
695 | 771 | ||
diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c index 94ceddd17ab2..293c9e820c49 100644 --- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c +++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c | |||
@@ -42,6 +42,7 @@ | |||
42 | #include <linux/mlx4/cmd.h> | 42 | #include <linux/mlx4/cmd.h> |
43 | #include <linux/mlx4/qp.h> | 43 | #include <linux/mlx4/qp.h> |
44 | #include <linux/if_ether.h> | 44 | #include <linux/if_ether.h> |
45 | #include <linux/etherdevice.h> | ||
45 | 46 | ||
46 | #include "mlx4.h" | 47 | #include "mlx4.h" |
47 | #include "fw.h" | 48 | #include "fw.h" |
@@ -2776,18 +2777,133 @@ ex_put: | |||
2776 | return err; | 2777 | return err; |
2777 | } | 2778 | } |
2778 | 2779 | ||
2780 | /* | ||
2781 | * MAC validation for Flow Steering rules. | ||
2782 | * VF can attach rules only with a mac address which is assigned to it. | ||
2783 | */ | ||
2784 | static int validate_eth_header_mac(int slave, struct _rule_hw *eth_header, | ||
2785 | struct list_head *rlist) | ||
2786 | { | ||
2787 | struct mac_res *res, *tmp; | ||
2788 | __be64 be_mac; | ||
2789 | |||
2790 | /* make sure it isn't multicast or broadcast mac*/ | ||
2791 | if (!is_multicast_ether_addr(eth_header->eth.dst_mac) && | ||
2792 | !is_broadcast_ether_addr(eth_header->eth.dst_mac)) { | ||
2793 | list_for_each_entry_safe(res, tmp, rlist, list) { | ||
2794 | be_mac = cpu_to_be64(res->mac << 16); | ||
2795 | if (!memcmp(&be_mac, eth_header->eth.dst_mac, ETH_ALEN)) | ||
2796 | return 0; | ||
2797 | } | ||
2798 | pr_err("MAC %pM doesn't belong to VF %d, Steering rule rejected\n", | ||
2799 | eth_header->eth.dst_mac, slave); | ||
2800 | return -EINVAL; | ||
2801 | } | ||
2802 | return 0; | ||
2803 | } | ||
2804 | |||
2805 | /* | ||
2806 | * In case of missing eth header, append eth header with a MAC address | ||
2807 | * assigned to the VF. | ||
2808 | */ | ||
2809 | static int add_eth_header(struct mlx4_dev *dev, int slave, | ||
2810 | struct mlx4_cmd_mailbox *inbox, | ||
2811 | struct list_head *rlist, int header_id) | ||
2812 | { | ||
2813 | struct mac_res *res, *tmp; | ||
2814 | u8 port; | ||
2815 | struct mlx4_net_trans_rule_hw_ctrl *ctrl; | ||
2816 | struct mlx4_net_trans_rule_hw_eth *eth_header; | ||
2817 | struct mlx4_net_trans_rule_hw_ipv4 *ip_header; | ||
2818 | struct mlx4_net_trans_rule_hw_tcp_udp *l4_header; | ||
2819 | __be64 be_mac = 0; | ||
2820 | __be64 mac_msk = cpu_to_be64(MLX4_MAC_MASK << 16); | ||
2821 | |||
2822 | ctrl = (struct mlx4_net_trans_rule_hw_ctrl *)inbox->buf; | ||
2823 | port = be32_to_cpu(ctrl->vf_vep_port) & 0xff; | ||
2824 | eth_header = (struct mlx4_net_trans_rule_hw_eth *)(ctrl + 1); | ||
2825 | |||
2826 | /* Clear a space in the inbox for eth header */ | ||
2827 | switch (header_id) { | ||
2828 | case MLX4_NET_TRANS_RULE_ID_IPV4: | ||
2829 | ip_header = | ||
2830 | (struct mlx4_net_trans_rule_hw_ipv4 *)(eth_header + 1); | ||
2831 | memmove(ip_header, eth_header, | ||
2832 | sizeof(*ip_header) + sizeof(*l4_header)); | ||
2833 | break; | ||
2834 | case MLX4_NET_TRANS_RULE_ID_TCP: | ||
2835 | case MLX4_NET_TRANS_RULE_ID_UDP: | ||
2836 | l4_header = (struct mlx4_net_trans_rule_hw_tcp_udp *) | ||
2837 | (eth_header + 1); | ||
2838 | memmove(l4_header, eth_header, sizeof(*l4_header)); | ||
2839 | break; | ||
2840 | default: | ||
2841 | return -EINVAL; | ||
2842 | } | ||
2843 | list_for_each_entry_safe(res, tmp, rlist, list) { | ||
2844 | if (port == res->port) { | ||
2845 | be_mac = cpu_to_be64(res->mac << 16); | ||
2846 | break; | ||
2847 | } | ||
2848 | } | ||
2849 | if (!be_mac) { | ||
2850 | pr_err("Failed adding eth header to FS rule, Can't find matching MAC for port %d .\n", | ||
2851 | port); | ||
2852 | return -EINVAL; | ||
2853 | } | ||
2854 | |||
2855 | memset(eth_header, 0, sizeof(*eth_header)); | ||
2856 | eth_header->size = sizeof(*eth_header) >> 2; | ||
2857 | eth_header->id = cpu_to_be16(__sw_id_hw[MLX4_NET_TRANS_RULE_ID_ETH]); | ||
2858 | memcpy(eth_header->dst_mac, &be_mac, ETH_ALEN); | ||
2859 | memcpy(eth_header->dst_mac_msk, &mac_msk, ETH_ALEN); | ||
2860 | |||
2861 | return 0; | ||
2862 | |||
2863 | } | ||
2864 | |||
2779 | int mlx4_QP_FLOW_STEERING_ATTACH_wrapper(struct mlx4_dev *dev, int slave, | 2865 | int mlx4_QP_FLOW_STEERING_ATTACH_wrapper(struct mlx4_dev *dev, int slave, |
2780 | struct mlx4_vhcr *vhcr, | 2866 | struct mlx4_vhcr *vhcr, |
2781 | struct mlx4_cmd_mailbox *inbox, | 2867 | struct mlx4_cmd_mailbox *inbox, |
2782 | struct mlx4_cmd_mailbox *outbox, | 2868 | struct mlx4_cmd_mailbox *outbox, |
2783 | struct mlx4_cmd_info *cmd) | 2869 | struct mlx4_cmd_info *cmd) |
2784 | { | 2870 | { |
2871 | |||
2872 | struct mlx4_priv *priv = mlx4_priv(dev); | ||
2873 | struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker; | ||
2874 | struct list_head *rlist = &tracker->slave_list[slave].res_list[RES_MAC]; | ||
2785 | int err; | 2875 | int err; |
2876 | struct mlx4_net_trans_rule_hw_ctrl *ctrl; | ||
2877 | struct _rule_hw *rule_header; | ||
2878 | int header_id; | ||
2786 | 2879 | ||
2787 | if (dev->caps.steering_mode != | 2880 | if (dev->caps.steering_mode != |
2788 | MLX4_STEERING_MODE_DEVICE_MANAGED) | 2881 | MLX4_STEERING_MODE_DEVICE_MANAGED) |
2789 | return -EOPNOTSUPP; | 2882 | return -EOPNOTSUPP; |
2790 | 2883 | ||
2884 | ctrl = (struct mlx4_net_trans_rule_hw_ctrl *)inbox->buf; | ||
2885 | rule_header = (struct _rule_hw *)(ctrl + 1); | ||
2886 | header_id = map_hw_to_sw_id(be16_to_cpu(rule_header->id)); | ||
2887 | |||
2888 | switch (header_id) { | ||
2889 | case MLX4_NET_TRANS_RULE_ID_ETH: | ||
2890 | if (validate_eth_header_mac(slave, rule_header, rlist)) | ||
2891 | return -EINVAL; | ||
2892 | break; | ||
2893 | case MLX4_NET_TRANS_RULE_ID_IPV4: | ||
2894 | case MLX4_NET_TRANS_RULE_ID_TCP: | ||
2895 | case MLX4_NET_TRANS_RULE_ID_UDP: | ||
2896 | pr_warn("Can't attach FS rule without L2 headers, adding L2 header.\n"); | ||
2897 | if (add_eth_header(dev, slave, inbox, rlist, header_id)) | ||
2898 | return -EINVAL; | ||
2899 | vhcr->in_modifier += | ||
2900 | sizeof(struct mlx4_net_trans_rule_hw_eth) >> 2; | ||
2901 | break; | ||
2902 | default: | ||
2903 | pr_err("Corrupted mailbox.\n"); | ||
2904 | return -EINVAL; | ||
2905 | } | ||
2906 | |||
2791 | err = mlx4_cmd_imm(dev, inbox->dma, &vhcr->out_param, | 2907 | err = mlx4_cmd_imm(dev, inbox->dma, &vhcr->out_param, |
2792 | vhcr->in_modifier, 0, | 2908 | vhcr->in_modifier, 0, |
2793 | MLX4_QP_FLOW_STEERING_ATTACH, MLX4_CMD_TIME_CLASS_A, | 2909 | MLX4_QP_FLOW_STEERING_ATTACH, MLX4_CMD_TIME_CLASS_A, |