diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/cmd.c | 37 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/en_netdev.c | 32 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/en_port.c | 77 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/en_port.h | 37 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/mcg.c | 4 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/mlx4.h | 53 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/port.c | 606 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/resource_tracker.c | 33 |
8 files changed, 621 insertions, 258 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx4/cmd.c b/drivers/net/ethernet/mellanox/mlx4/cmd.c index 0f2069d98274..8e6e4b20b0e2 100644 --- a/drivers/net/ethernet/mellanox/mlx4/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c | |||
@@ -654,6 +654,15 @@ static struct mlx4_cmd_info cmd_info[] = { | |||
654 | .wrapper = mlx4_QUERY_PORT_wrapper | 654 | .wrapper = mlx4_QUERY_PORT_wrapper |
655 | }, | 655 | }, |
656 | { | 656 | { |
657 | .opcode = MLX4_CMD_SET_PORT, | ||
658 | .has_inbox = true, | ||
659 | .has_outbox = false, | ||
660 | .out_is_imm = false, | ||
661 | .encode_slave_id = false, | ||
662 | .verify = NULL, | ||
663 | .wrapper = mlx4_SET_PORT_wrapper | ||
664 | }, | ||
665 | { | ||
657 | .opcode = MLX4_CMD_MAP_EQ, | 666 | .opcode = MLX4_CMD_MAP_EQ, |
658 | .has_inbox = false, | 667 | .has_inbox = false, |
659 | .has_outbox = false, | 668 | .has_outbox = false, |
@@ -1005,6 +1014,34 @@ static struct mlx4_cmd_info cmd_info[] = { | |||
1005 | .verify = NULL, | 1014 | .verify = NULL, |
1006 | .wrapper = mlx4_PROMISC_wrapper | 1015 | .wrapper = mlx4_PROMISC_wrapper |
1007 | }, | 1016 | }, |
1017 | /* Ethernet specific commands */ | ||
1018 | { | ||
1019 | .opcode = MLX4_CMD_SET_VLAN_FLTR, | ||
1020 | .has_inbox = true, | ||
1021 | .has_outbox = false, | ||
1022 | .out_is_imm = false, | ||
1023 | .encode_slave_id = false, | ||
1024 | .verify = NULL, | ||
1025 | .wrapper = mlx4_SET_VLAN_FLTR_wrapper | ||
1026 | }, | ||
1027 | { | ||
1028 | .opcode = MLX4_CMD_SET_MCAST_FLTR, | ||
1029 | .has_inbox = false, | ||
1030 | .has_outbox = false, | ||
1031 | .out_is_imm = false, | ||
1032 | .encode_slave_id = false, | ||
1033 | .verify = NULL, | ||
1034 | .wrapper = mlx4_SET_MCAST_FLTR_wrapper | ||
1035 | }, | ||
1036 | { | ||
1037 | .opcode = MLX4_CMD_DUMP_ETH_STATS, | ||
1038 | .has_inbox = false, | ||
1039 | .has_outbox = true, | ||
1040 | .out_is_imm = false, | ||
1041 | .encode_slave_id = false, | ||
1042 | .verify = NULL, | ||
1043 | .wrapper = mlx4_DUMP_ETH_STATS_wrapper | ||
1044 | }, | ||
1008 | { | 1045 | { |
1009 | .opcode = MLX4_CMD_INFORM_FLR_DONE, | 1046 | .opcode = MLX4_CMD_INFORM_FLR_DONE, |
1010 | .has_inbox = false, | 1047 | .has_inbox = false, |
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c index 2083f3b5d689..1db6fea495bf 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c | |||
@@ -136,7 +136,7 @@ static void mlx4_en_do_set_mac(struct work_struct *work) | |||
136 | if (priv->port_up) { | 136 | if (priv->port_up) { |
137 | /* Remove old MAC and insert the new one */ | 137 | /* Remove old MAC and insert the new one */ |
138 | err = mlx4_replace_mac(mdev->dev, priv->port, | 138 | err = mlx4_replace_mac(mdev->dev, priv->port, |
139 | priv->base_qpn, priv->mac, 0); | 139 | priv->base_qpn, priv->mac); |
140 | if (err) | 140 | if (err) |
141 | en_err(priv, "Failed changing HW MAC address\n"); | 141 | en_err(priv, "Failed changing HW MAC address\n"); |
142 | } else | 142 | } else |
@@ -207,6 +207,16 @@ static void mlx4_en_do_set_multicast(struct work_struct *work) | |||
207 | goto out; | 207 | goto out; |
208 | } | 208 | } |
209 | 209 | ||
210 | if (!netif_carrier_ok(dev)) { | ||
211 | if (!mlx4_en_QUERY_PORT(mdev, priv->port)) { | ||
212 | if (priv->port_state.link_state) { | ||
213 | priv->last_link_state = MLX4_DEV_EVENT_PORT_UP; | ||
214 | netif_carrier_on(dev); | ||
215 | en_dbg(LINK, priv, "Link Up\n"); | ||
216 | } | ||
217 | } | ||
218 | } | ||
219 | |||
210 | /* | 220 | /* |
211 | * Promsicuous mode: disable all filters | 221 | * Promsicuous mode: disable all filters |
212 | */ | 222 | */ |
@@ -602,12 +612,12 @@ int mlx4_en_start_port(struct net_device *dev) | |||
602 | ++rx_index; | 612 | ++rx_index; |
603 | } | 613 | } |
604 | 614 | ||
605 | /* Set port mac number */ | 615 | /* Set qp number */ |
606 | en_dbg(DRV, priv, "Setting mac for port %d\n", priv->port); | 616 | en_dbg(DRV, priv, "Getting qp number for port %d\n", priv->port); |
607 | err = mlx4_register_mac(mdev->dev, priv->port, | 617 | err = mlx4_get_eth_qp(mdev->dev, priv->port, |
608 | priv->mac, &priv->base_qpn, 0); | 618 | priv->mac, &priv->base_qpn); |
609 | if (err) { | 619 | if (err) { |
610 | en_err(priv, "Failed setting port mac\n"); | 620 | en_err(priv, "Failed getting eth qp\n"); |
611 | goto cq_err; | 621 | goto cq_err; |
612 | } | 622 | } |
613 | mdev->mac_removed[priv->port] = 0; | 623 | mdev->mac_removed[priv->port] = 0; |
@@ -702,7 +712,7 @@ tx_err: | |||
702 | 712 | ||
703 | mlx4_en_release_rss_steer(priv); | 713 | mlx4_en_release_rss_steer(priv); |
704 | mac_err: | 714 | mac_err: |
705 | mlx4_unregister_mac(mdev->dev, priv->port, priv->base_qpn); | 715 | mlx4_put_eth_qp(mdev->dev, priv->port, priv->mac, priv->base_qpn); |
706 | cq_err: | 716 | cq_err: |
707 | while (rx_index--) | 717 | while (rx_index--) |
708 | mlx4_en_deactivate_cq(priv, &priv->rx_cq[rx_index]); | 718 | mlx4_en_deactivate_cq(priv, &priv->rx_cq[rx_index]); |
@@ -748,10 +758,6 @@ void mlx4_en_stop_port(struct net_device *dev) | |||
748 | /* Flush multicast filter */ | 758 | /* Flush multicast filter */ |
749 | mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0, 1, MLX4_MCAST_CONFIG); | 759 | mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0, 1, MLX4_MCAST_CONFIG); |
750 | 760 | ||
751 | /* Unregister Mac address for the port */ | ||
752 | mlx4_unregister_mac(mdev->dev, priv->port, priv->base_qpn); | ||
753 | mdev->mac_removed[priv->port] = 1; | ||
754 | |||
755 | /* Free TX Rings */ | 761 | /* Free TX Rings */ |
756 | for (i = 0; i < priv->tx_ring_num; i++) { | 762 | for (i = 0; i < priv->tx_ring_num; i++) { |
757 | mlx4_en_deactivate_tx_ring(priv, &priv->tx_ring[i]); | 763 | mlx4_en_deactivate_tx_ring(priv, &priv->tx_ring[i]); |
@@ -765,6 +771,10 @@ void mlx4_en_stop_port(struct net_device *dev) | |||
765 | /* Free RSS qps */ | 771 | /* Free RSS qps */ |
766 | mlx4_en_release_rss_steer(priv); | 772 | mlx4_en_release_rss_steer(priv); |
767 | 773 | ||
774 | /* Unregister Mac address for the port */ | ||
775 | mlx4_put_eth_qp(mdev->dev, priv->port, priv->mac, priv->base_qpn); | ||
776 | mdev->mac_removed[priv->port] = 1; | ||
777 | |||
768 | /* Free RX Rings */ | 778 | /* Free RX Rings */ |
769 | for (i = 0; i < priv->rx_ring_num; i++) { | 779 | for (i = 0; i < priv->rx_ring_num; i++) { |
770 | mlx4_en_deactivate_rx_ring(priv, &priv->rx_ring[i]); | 780 | mlx4_en_deactivate_rx_ring(priv, &priv->rx_ring[i]); |
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_port.c b/drivers/net/ethernet/mellanox/mlx4/en_port.c index ae120effb8a5..331791467a22 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_port.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_port.c | |||
@@ -41,14 +41,6 @@ | |||
41 | #include "mlx4_en.h" | 41 | #include "mlx4_en.h" |
42 | 42 | ||
43 | 43 | ||
44 | int mlx4_SET_MCAST_FLTR(struct mlx4_dev *dev, u8 port, | ||
45 | u64 mac, u64 clear, u8 mode) | ||
46 | { | ||
47 | return mlx4_cmd(dev, (mac | (clear << 63)), port, mode, | ||
48 | MLX4_CMD_SET_MCAST_FLTR, MLX4_CMD_TIME_CLASS_B, | ||
49 | MLX4_CMD_WRAPPED); | ||
50 | } | ||
51 | |||
52 | int mlx4_SET_VLAN_FLTR(struct mlx4_dev *dev, struct mlx4_en_priv *priv) | 44 | int mlx4_SET_VLAN_FLTR(struct mlx4_dev *dev, struct mlx4_en_priv *priv) |
53 | { | 45 | { |
54 | struct mlx4_cmd_mailbox *mailbox; | 46 | struct mlx4_cmd_mailbox *mailbox; |
@@ -78,75 +70,6 @@ int mlx4_SET_VLAN_FLTR(struct mlx4_dev *dev, struct mlx4_en_priv *priv) | |||
78 | return err; | 70 | return err; |
79 | } | 71 | } |
80 | 72 | ||
81 | |||
82 | int mlx4_SET_PORT_general(struct mlx4_dev *dev, u8 port, int mtu, | ||
83 | u8 pptx, u8 pfctx, u8 pprx, u8 pfcrx) | ||
84 | { | ||
85 | struct mlx4_cmd_mailbox *mailbox; | ||
86 | struct mlx4_set_port_general_context *context; | ||
87 | int err; | ||
88 | u32 in_mod; | ||
89 | |||
90 | mailbox = mlx4_alloc_cmd_mailbox(dev); | ||
91 | if (IS_ERR(mailbox)) | ||
92 | return PTR_ERR(mailbox); | ||
93 | context = mailbox->buf; | ||
94 | memset(context, 0, sizeof *context); | ||
95 | |||
96 | context->flags = SET_PORT_GEN_ALL_VALID; | ||
97 | context->mtu = cpu_to_be16(mtu); | ||
98 | context->pptx = (pptx * (!pfctx)) << 7; | ||
99 | context->pfctx = pfctx; | ||
100 | context->pprx = (pprx * (!pfcrx)) << 7; | ||
101 | context->pfcrx = pfcrx; | ||
102 | |||
103 | in_mod = MLX4_SET_PORT_GENERAL << 8 | port; | ||
104 | err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT, | ||
105 | MLX4_CMD_TIME_CLASS_B, MLX4_CMD_WRAPPED); | ||
106 | |||
107 | mlx4_free_cmd_mailbox(dev, mailbox); | ||
108 | return err; | ||
109 | } | ||
110 | |||
111 | int mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn, | ||
112 | u8 promisc) | ||
113 | { | ||
114 | struct mlx4_cmd_mailbox *mailbox; | ||
115 | struct mlx4_set_port_rqp_calc_context *context; | ||
116 | int err; | ||
117 | u32 in_mod; | ||
118 | u32 m_promisc = (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER) ? | ||
119 | MCAST_DIRECT : MCAST_DEFAULT; | ||
120 | |||
121 | if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER && | ||
122 | dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER) | ||
123 | return 0; | ||
124 | |||
125 | mailbox = mlx4_alloc_cmd_mailbox(dev); | ||
126 | if (IS_ERR(mailbox)) | ||
127 | return PTR_ERR(mailbox); | ||
128 | context = mailbox->buf; | ||
129 | memset(context, 0, sizeof *context); | ||
130 | |||
131 | context->base_qpn = cpu_to_be32(base_qpn); | ||
132 | context->n_mac = dev->caps.log_num_macs; | ||
133 | context->promisc = cpu_to_be32(promisc << SET_PORT_PROMISC_SHIFT | | ||
134 | base_qpn); | ||
135 | context->mcast = cpu_to_be32(m_promisc << SET_PORT_MC_PROMISC_SHIFT | | ||
136 | base_qpn); | ||
137 | context->intra_no_vlan = 0; | ||
138 | context->no_vlan = MLX4_NO_VLAN_IDX; | ||
139 | context->intra_vlan_miss = 0; | ||
140 | context->vlan_miss = MLX4_VLAN_MISS_IDX; | ||
141 | |||
142 | in_mod = MLX4_SET_PORT_RQP_CALC << 8 | port; | ||
143 | err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT, | ||
144 | MLX4_CMD_TIME_CLASS_B, MLX4_CMD_WRAPPED); | ||
145 | |||
146 | mlx4_free_cmd_mailbox(dev, mailbox); | ||
147 | return err; | ||
148 | } | ||
149 | |||
150 | int mlx4_en_QUERY_PORT(struct mlx4_en_dev *mdev, u8 port) | 73 | int mlx4_en_QUERY_PORT(struct mlx4_en_dev *mdev, u8 port) |
151 | { | 74 | { |
152 | struct mlx4_en_query_port_context *qport_context; | 75 | struct mlx4_en_query_port_context *qport_context; |
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_port.h b/drivers/net/ethernet/mellanox/mlx4/en_port.h index c1bb834414b5..6934fd7e66ed 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_port.h +++ b/drivers/net/ethernet/mellanox/mlx4/en_port.h | |||
@@ -39,43 +39,6 @@ | |||
39 | #define SET_PORT_PROMISC_SHIFT 31 | 39 | #define SET_PORT_PROMISC_SHIFT 31 |
40 | #define SET_PORT_MC_PROMISC_SHIFT 30 | 40 | #define SET_PORT_MC_PROMISC_SHIFT 30 |
41 | 41 | ||
42 | enum { | ||
43 | MCAST_DIRECT_ONLY = 0, | ||
44 | MCAST_DIRECT = 1, | ||
45 | MCAST_DEFAULT = 2 | ||
46 | }; | ||
47 | |||
48 | struct mlx4_set_port_general_context { | ||
49 | u8 reserved[3]; | ||
50 | u8 flags; | ||
51 | u16 reserved2; | ||
52 | __be16 mtu; | ||
53 | u8 pptx; | ||
54 | u8 pfctx; | ||
55 | u16 reserved3; | ||
56 | u8 pprx; | ||
57 | u8 pfcrx; | ||
58 | u16 reserved4; | ||
59 | }; | ||
60 | |||
61 | struct mlx4_set_port_rqp_calc_context { | ||
62 | __be32 base_qpn; | ||
63 | u8 rererved; | ||
64 | u8 n_mac; | ||
65 | u8 n_vlan; | ||
66 | u8 n_prio; | ||
67 | u8 reserved2[3]; | ||
68 | u8 mac_miss; | ||
69 | u8 intra_no_vlan; | ||
70 | u8 no_vlan; | ||
71 | u8 intra_vlan_miss; | ||
72 | u8 vlan_miss; | ||
73 | u8 reserved3[3]; | ||
74 | u8 no_vlan_prio; | ||
75 | __be32 promisc; | ||
76 | __be32 mcast; | ||
77 | }; | ||
78 | |||
79 | #define VLAN_FLTR_SIZE 128 | 42 | #define VLAN_FLTR_SIZE 128 |
80 | struct mlx4_set_vlan_fltr_mbox { | 43 | struct mlx4_set_vlan_fltr_mbox { |
81 | __be32 entry[VLAN_FLTR_SIZE]; | 44 | __be32 entry[VLAN_FLTR_SIZE]; |
diff --git a/drivers/net/ethernet/mellanox/mlx4/mcg.c b/drivers/net/ethernet/mellanox/mlx4/mcg.c index b36c279bcca0..0785d9b2a265 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mcg.c +++ b/drivers/net/ethernet/mellanox/mlx4/mcg.c | |||
@@ -913,7 +913,7 @@ int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], | |||
913 | } | 913 | } |
914 | EXPORT_SYMBOL_GPL(mlx4_multicast_detach); | 914 | EXPORT_SYMBOL_GPL(mlx4_multicast_detach); |
915 | 915 | ||
916 | static int mlx4_unicast_attach(struct mlx4_dev *dev, | 916 | int mlx4_unicast_attach(struct mlx4_dev *dev, |
917 | struct mlx4_qp *qp, u8 gid[16], | 917 | struct mlx4_qp *qp, u8 gid[16], |
918 | int block_mcast_loopback, enum mlx4_protocol prot) | 918 | int block_mcast_loopback, enum mlx4_protocol prot) |
919 | { | 919 | { |
@@ -933,7 +933,7 @@ static int mlx4_unicast_attach(struct mlx4_dev *dev, | |||
933 | } | 933 | } |
934 | EXPORT_SYMBOL_GPL(mlx4_unicast_attach); | 934 | EXPORT_SYMBOL_GPL(mlx4_unicast_attach); |
935 | 935 | ||
936 | static int mlx4_unicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, | 936 | int mlx4_unicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, |
937 | u8 gid[16], enum mlx4_protocol prot) | 937 | u8 gid[16], enum mlx4_protocol prot) |
938 | { | 938 | { |
939 | if (prot == MLX4_PROT_ETH && | 939 | if (prot == MLX4_PROT_ETH && |
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h index a38ffc997367..abf65d8af48d 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h | |||
@@ -419,12 +419,23 @@ struct mlx4_comm { | |||
419 | u32 slave_read; | 419 | u32 slave_read; |
420 | }; | 420 | }; |
421 | 421 | ||
422 | enum { | ||
423 | MLX4_MCAST_CONFIG = 0, | ||
424 | MLX4_MCAST_DISABLE = 1, | ||
425 | MLX4_MCAST_ENABLE = 2, | ||
426 | }; | ||
427 | |||
422 | #define VLAN_FLTR_SIZE 128 | 428 | #define VLAN_FLTR_SIZE 128 |
423 | 429 | ||
424 | struct mlx4_vlan_fltr { | 430 | struct mlx4_vlan_fltr { |
425 | __be32 entry[VLAN_FLTR_SIZE]; | 431 | __be32 entry[VLAN_FLTR_SIZE]; |
426 | }; | 432 | }; |
427 | 433 | ||
434 | struct mlx4_mcast_entry { | ||
435 | struct list_head list; | ||
436 | u64 addr; | ||
437 | }; | ||
438 | |||
428 | struct mlx4_promisc_qp { | 439 | struct mlx4_promisc_qp { |
429 | struct list_head list; | 440 | struct list_head list; |
430 | u32 qpn; | 441 | u32 qpn; |
@@ -615,6 +626,48 @@ struct mlx4_vlan_table { | |||
615 | int max; | 626 | int max; |
616 | }; | 627 | }; |
617 | 628 | ||
629 | #define SET_PORT_GEN_ALL_VALID 0x7 | ||
630 | #define SET_PORT_PROMISC_SHIFT 31 | ||
631 | #define SET_PORT_MC_PROMISC_SHIFT 30 | ||
632 | |||
633 | enum { | ||
634 | MCAST_DIRECT_ONLY = 0, | ||
635 | MCAST_DIRECT = 1, | ||
636 | MCAST_DEFAULT = 2 | ||
637 | }; | ||
638 | |||
639 | |||
640 | struct mlx4_set_port_general_context { | ||
641 | u8 reserved[3]; | ||
642 | u8 flags; | ||
643 | u16 reserved2; | ||
644 | __be16 mtu; | ||
645 | u8 pptx; | ||
646 | u8 pfctx; | ||
647 | u16 reserved3; | ||
648 | u8 pprx; | ||
649 | u8 pfcrx; | ||
650 | u16 reserved4; | ||
651 | }; | ||
652 | |||
653 | struct mlx4_set_port_rqp_calc_context { | ||
654 | __be32 base_qpn; | ||
655 | u8 rererved; | ||
656 | u8 n_mac; | ||
657 | u8 n_vlan; | ||
658 | u8 n_prio; | ||
659 | u8 reserved2[3]; | ||
660 | u8 mac_miss; | ||
661 | u8 intra_no_vlan; | ||
662 | u8 no_vlan; | ||
663 | u8 intra_vlan_miss; | ||
664 | u8 vlan_miss; | ||
665 | u8 reserved3[3]; | ||
666 | u8 no_vlan_prio; | ||
667 | __be32 promisc; | ||
668 | __be32 mcast; | ||
669 | }; | ||
670 | |||
618 | struct mlx4_mac_entry { | 671 | struct mlx4_mac_entry { |
619 | u64 mac; | 672 | u64 mac; |
620 | }; | 673 | }; |
diff --git a/drivers/net/ethernet/mellanox/mlx4/port.c b/drivers/net/ethernet/mellanox/mlx4/port.c index da9f85c6da7e..00a9547773c1 100644 --- a/drivers/net/ethernet/mellanox/mlx4/port.c +++ b/drivers/net/ethernet/mellanox/mlx4/port.c | |||
@@ -70,41 +70,12 @@ void mlx4_init_vlan_table(struct mlx4_dev *dev, struct mlx4_vlan_table *table) | |||
70 | table->total = 0; | 70 | table->total = 0; |
71 | } | 71 | } |
72 | 72 | ||
73 | static int mlx4_set_port_mac_table(struct mlx4_dev *dev, u8 port, | 73 | static int mlx4_uc_steer_add(struct mlx4_dev *dev, u8 port, u64 mac, int *qpn) |
74 | __be64 *entries) | ||
75 | { | ||
76 | struct mlx4_cmd_mailbox *mailbox; | ||
77 | u32 in_mod; | ||
78 | int err; | ||
79 | |||
80 | mailbox = mlx4_alloc_cmd_mailbox(dev); | ||
81 | if (IS_ERR(mailbox)) | ||
82 | return PTR_ERR(mailbox); | ||
83 | |||
84 | memcpy(mailbox->buf, entries, MLX4_MAC_TABLE_SIZE); | ||
85 | |||
86 | in_mod = MLX4_SET_PORT_MAC_TABLE << 8 | port; | ||
87 | err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT, | ||
88 | MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE); | ||
89 | |||
90 | mlx4_free_cmd_mailbox(dev, mailbox); | ||
91 | return err; | ||
92 | } | ||
93 | |||
94 | static int mlx4_uc_steer_add(struct mlx4_dev *dev, u8 port, | ||
95 | u64 mac, int *qpn, u8 reserve) | ||
96 | { | 74 | { |
97 | struct mlx4_qp qp; | 75 | struct mlx4_qp qp; |
98 | u8 gid[16] = {0}; | 76 | u8 gid[16] = {0}; |
99 | int err; | 77 | int err; |
100 | 78 | ||
101 | if (reserve) { | ||
102 | err = mlx4_qp_reserve_range(dev, 1, 1, qpn); | ||
103 | if (err) { | ||
104 | mlx4_err(dev, "Failed to reserve qp for mac registration\n"); | ||
105 | return err; | ||
106 | } | ||
107 | } | ||
108 | qp.qpn = *qpn; | 79 | qp.qpn = *qpn; |
109 | 80 | ||
110 | mac &= 0xffffffffffffULL; | 81 | mac &= 0xffffffffffffULL; |
@@ -113,16 +84,15 @@ static int mlx4_uc_steer_add(struct mlx4_dev *dev, u8 port, | |||
113 | gid[5] = port; | 84 | gid[5] = port; |
114 | gid[7] = MLX4_UC_STEER << 1; | 85 | gid[7] = MLX4_UC_STEER << 1; |
115 | 86 | ||
116 | err = mlx4_qp_attach_common(dev, &qp, gid, 0, | 87 | err = mlx4_unicast_attach(dev, &qp, gid, 0, MLX4_PROT_ETH); |
117 | MLX4_PROT_ETH, MLX4_UC_STEER); | 88 | if (err) |
118 | if (err && reserve) | 89 | mlx4_warn(dev, "Failed Attaching Unicast\n"); |
119 | mlx4_qp_release_range(dev, *qpn, 1); | ||
120 | 90 | ||
121 | return err; | 91 | return err; |
122 | } | 92 | } |
123 | 93 | ||
124 | static void mlx4_uc_steer_release(struct mlx4_dev *dev, u8 port, | 94 | static void mlx4_uc_steer_release(struct mlx4_dev *dev, u8 port, |
125 | u64 mac, int qpn, u8 free) | 95 | u64 mac, int qpn) |
126 | { | 96 | { |
127 | struct mlx4_qp qp; | 97 | struct mlx4_qp qp; |
128 | u8 gid[16] = {0}; | 98 | u8 gid[16] = {0}; |
@@ -134,60 +104,164 @@ static void mlx4_uc_steer_release(struct mlx4_dev *dev, u8 port, | |||
134 | gid[5] = port; | 104 | gid[5] = port; |
135 | gid[7] = MLX4_UC_STEER << 1; | 105 | gid[7] = MLX4_UC_STEER << 1; |
136 | 106 | ||
137 | mlx4_qp_detach_common(dev, &qp, gid, MLX4_PROT_ETH, MLX4_UC_STEER); | 107 | mlx4_unicast_detach(dev, &qp, gid, MLX4_PROT_ETH); |
138 | if (free) | 108 | } |
139 | mlx4_qp_release_range(dev, qpn, 1); | 109 | |
110 | static int validate_index(struct mlx4_dev *dev, | ||
111 | struct mlx4_mac_table *table, int index) | ||
112 | { | ||
113 | int err = 0; | ||
114 | |||
115 | if (index < 0 || index >= table->max || !table->entries[index]) { | ||
116 | mlx4_warn(dev, "No valid Mac entry for the given index\n"); | ||
117 | err = -EINVAL; | ||
118 | } | ||
119 | return err; | ||
120 | } | ||
121 | |||
122 | static int find_index(struct mlx4_dev *dev, | ||
123 | struct mlx4_mac_table *table, u64 mac) | ||
124 | { | ||
125 | int i; | ||
126 | |||
127 | for (i = 0; i < MLX4_MAX_MAC_NUM; i++) { | ||
128 | if ((mac & MLX4_MAC_MASK) == | ||
129 | (MLX4_MAC_MASK & be64_to_cpu(table->entries[i]))) | ||
130 | return i; | ||
131 | } | ||
132 | /* Mac not found */ | ||
133 | return -EINVAL; | ||
140 | } | 134 | } |
141 | 135 | ||
142 | int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac, int *qpn, u8 wrap) | 136 | int mlx4_get_eth_qp(struct mlx4_dev *dev, u8 port, u64 mac, int *qpn) |
143 | { | 137 | { |
144 | struct mlx4_port_info *info = &mlx4_priv(dev)->port[port]; | 138 | struct mlx4_port_info *info = &mlx4_priv(dev)->port[port]; |
145 | struct mlx4_mac_table *table = &info->mac_table; | ||
146 | struct mlx4_mac_entry *entry; | 139 | struct mlx4_mac_entry *entry; |
147 | int i, err = 0; | 140 | int index = 0; |
148 | int free = -1; | 141 | int err = 0; |
149 | 142 | ||
150 | if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER) { | 143 | mlx4_dbg(dev, "Registering MAC: 0x%llx for adding\n", |
151 | err = mlx4_uc_steer_add(dev, port, mac, qpn, 1); | 144 | (unsigned long long) mac); |
152 | if (err) | 145 | index = mlx4_register_mac(dev, port, mac); |
153 | return err; | 146 | if (index < 0) { |
147 | err = index; | ||
148 | mlx4_err(dev, "Failed adding MAC: 0x%llx\n", | ||
149 | (unsigned long long) mac); | ||
150 | return err; | ||
151 | } | ||
154 | 152 | ||
155 | entry = kmalloc(sizeof *entry, GFP_KERNEL); | 153 | if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER)) { |
156 | if (!entry) { | 154 | *qpn = info->base_qpn + index; |
157 | mlx4_uc_steer_release(dev, port, mac, *qpn, 1); | 155 | return 0; |
158 | return -ENOMEM; | 156 | } |
159 | } | 157 | |
158 | err = mlx4_qp_reserve_range(dev, 1, 1, qpn); | ||
159 | mlx4_dbg(dev, "Reserved qp %d\n", *qpn); | ||
160 | if (err) { | ||
161 | mlx4_err(dev, "Failed to reserve qp for mac registration\n"); | ||
162 | goto qp_err; | ||
163 | } | ||
164 | |||
165 | err = mlx4_uc_steer_add(dev, port, mac, qpn); | ||
166 | if (err) | ||
167 | goto steer_err; | ||
168 | |||
169 | entry = kmalloc(sizeof *entry, GFP_KERNEL); | ||
170 | if (!entry) { | ||
171 | err = -ENOMEM; | ||
172 | goto alloc_err; | ||
173 | } | ||
174 | entry->mac = mac; | ||
175 | err = radix_tree_insert(&info->mac_tree, *qpn, entry); | ||
176 | if (err) | ||
177 | goto insert_err; | ||
178 | return 0; | ||
179 | |||
180 | insert_err: | ||
181 | kfree(entry); | ||
182 | |||
183 | alloc_err: | ||
184 | mlx4_uc_steer_release(dev, port, mac, *qpn); | ||
185 | |||
186 | steer_err: | ||
187 | mlx4_qp_release_range(dev, *qpn, 1); | ||
160 | 188 | ||
161 | entry->mac = mac; | 189 | qp_err: |
162 | err = radix_tree_insert(&info->mac_tree, *qpn, entry); | 190 | mlx4_unregister_mac(dev, port, mac); |
163 | if (err) { | 191 | return err; |
192 | } | ||
193 | EXPORT_SYMBOL_GPL(mlx4_get_eth_qp); | ||
194 | |||
195 | void mlx4_put_eth_qp(struct mlx4_dev *dev, u8 port, u64 mac, int qpn) | ||
196 | { | ||
197 | struct mlx4_port_info *info = &mlx4_priv(dev)->port[port]; | ||
198 | struct mlx4_mac_entry *entry; | ||
199 | |||
200 | mlx4_dbg(dev, "Registering MAC: 0x%llx for deleting\n", | ||
201 | (unsigned long long) mac); | ||
202 | mlx4_unregister_mac(dev, port, mac); | ||
203 | |||
204 | if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER) { | ||
205 | entry = radix_tree_lookup(&info->mac_tree, qpn); | ||
206 | if (entry) { | ||
207 | mlx4_dbg(dev, "Releasing qp: port %d, mac 0x%llx," | ||
208 | " qpn %d\n", port, | ||
209 | (unsigned long long) mac, qpn); | ||
210 | mlx4_uc_steer_release(dev, port, entry->mac, qpn); | ||
211 | mlx4_qp_release_range(dev, qpn, 1); | ||
212 | radix_tree_delete(&info->mac_tree, qpn); | ||
164 | kfree(entry); | 213 | kfree(entry); |
165 | mlx4_uc_steer_release(dev, port, mac, *qpn, 1); | ||
166 | return err; | ||
167 | } | 214 | } |
168 | } | 215 | } |
216 | } | ||
217 | EXPORT_SYMBOL_GPL(mlx4_put_eth_qp); | ||
218 | |||
219 | static int mlx4_set_port_mac_table(struct mlx4_dev *dev, u8 port, | ||
220 | __be64 *entries) | ||
221 | { | ||
222 | struct mlx4_cmd_mailbox *mailbox; | ||
223 | u32 in_mod; | ||
224 | int err; | ||
225 | |||
226 | mailbox = mlx4_alloc_cmd_mailbox(dev); | ||
227 | if (IS_ERR(mailbox)) | ||
228 | return PTR_ERR(mailbox); | ||
229 | |||
230 | memcpy(mailbox->buf, entries, MLX4_MAC_TABLE_SIZE); | ||
231 | |||
232 | in_mod = MLX4_SET_PORT_MAC_TABLE << 8 | port; | ||
169 | 233 | ||
170 | mlx4_dbg(dev, "Registering MAC: 0x%llx\n", (unsigned long long) mac); | 234 | err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT, |
235 | MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE); | ||
236 | |||
237 | mlx4_free_cmd_mailbox(dev, mailbox); | ||
238 | return err; | ||
239 | } | ||
240 | |||
241 | int __mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac) | ||
242 | { | ||
243 | struct mlx4_port_info *info = &mlx4_priv(dev)->port[port]; | ||
244 | struct mlx4_mac_table *table = &info->mac_table; | ||
245 | int i, err = 0; | ||
246 | int free = -1; | ||
247 | |||
248 | mlx4_dbg(dev, "Registering MAC: 0x%llx for port %d\n", | ||
249 | (unsigned long long) mac, port); | ||
171 | 250 | ||
172 | mutex_lock(&table->mutex); | 251 | mutex_lock(&table->mutex); |
173 | for (i = 0; i < MLX4_MAX_MAC_NUM - 1; i++) { | 252 | for (i = 0; i < MLX4_MAX_MAC_NUM; i++) { |
174 | if (free < 0 && !table->refs[i]) { | 253 | if (free < 0 && !table->entries[i]) { |
175 | free = i; | 254 | free = i; |
176 | continue; | 255 | continue; |
177 | } | 256 | } |
178 | 257 | ||
179 | if (mac == (MLX4_MAC_MASK & be64_to_cpu(table->entries[i]))) { | 258 | if (mac == (MLX4_MAC_MASK & be64_to_cpu(table->entries[i]))) { |
180 | /* MAC already registered, increase references count */ | 259 | /* MAC already registered, Must not have duplicates */ |
181 | ++table->refs[i]; | 260 | err = -EEXIST; |
182 | goto out; | 261 | goto out; |
183 | } | 262 | } |
184 | } | 263 | } |
185 | 264 | ||
186 | if (free < 0) { | ||
187 | err = -ENOMEM; | ||
188 | goto out; | ||
189 | } | ||
190 | |||
191 | mlx4_dbg(dev, "Free MAC index is %d\n", free); | 265 | mlx4_dbg(dev, "Free MAC index is %d\n", free); |
192 | 266 | ||
193 | if (table->total == table->max) { | 267 | if (table->total == table->max) { |
@@ -197,103 +271,103 @@ int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac, int *qpn, u8 wrap) | |||
197 | } | 271 | } |
198 | 272 | ||
199 | /* Register new MAC */ | 273 | /* Register new MAC */ |
200 | table->refs[free] = 1; | ||
201 | table->entries[free] = cpu_to_be64(mac | MLX4_MAC_VALID); | 274 | table->entries[free] = cpu_to_be64(mac | MLX4_MAC_VALID); |
202 | 275 | ||
203 | err = mlx4_set_port_mac_table(dev, port, table->entries); | 276 | err = mlx4_set_port_mac_table(dev, port, table->entries); |
204 | if (unlikely(err)) { | 277 | if (unlikely(err)) { |
205 | mlx4_err(dev, "Failed adding MAC: 0x%llx\n", (unsigned long long) mac); | 278 | mlx4_err(dev, "Failed adding MAC: 0x%llx\n", |
206 | table->refs[free] = 0; | 279 | (unsigned long long) mac); |
207 | table->entries[free] = 0; | 280 | table->entries[free] = 0; |
208 | goto out; | 281 | goto out; |
209 | } | 282 | } |
210 | 283 | ||
211 | if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER)) | 284 | err = free; |
212 | *qpn = info->base_qpn + free; | ||
213 | ++table->total; | 285 | ++table->total; |
214 | out: | 286 | out: |
215 | mutex_unlock(&table->mutex); | 287 | mutex_unlock(&table->mutex); |
216 | return err; | 288 | return err; |
217 | } | 289 | } |
218 | EXPORT_SYMBOL_GPL(mlx4_register_mac); | 290 | EXPORT_SYMBOL_GPL(__mlx4_register_mac); |
219 | 291 | ||
220 | static int validate_index(struct mlx4_dev *dev, | 292 | int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac) |
221 | struct mlx4_mac_table *table, int index) | ||
222 | { | 293 | { |
223 | int err = 0; | 294 | u64 out_param; |
295 | int err; | ||
224 | 296 | ||
225 | if (index < 0 || index >= table->max || !table->entries[index]) { | 297 | if (mlx4_is_mfunc(dev)) { |
226 | mlx4_warn(dev, "No valid Mac entry for the given index\n"); | 298 | set_param_l(&out_param, port); |
227 | err = -EINVAL; | 299 | err = mlx4_cmd_imm(dev, mac, &out_param, RES_MAC, |
228 | } | 300 | RES_OP_RESERVE_AND_MAP, MLX4_CMD_ALLOC_RES, |
229 | return err; | 301 | MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); |
230 | } | 302 | if (err) |
303 | return err; | ||
231 | 304 | ||
232 | static int find_index(struct mlx4_dev *dev, | 305 | return get_param_l(&out_param); |
233 | struct mlx4_mac_table *table, u64 mac) | ||
234 | { | ||
235 | int i; | ||
236 | for (i = 0; i < MLX4_MAX_MAC_NUM; i++) { | ||
237 | if (mac == (MLX4_MAC_MASK & be64_to_cpu(table->entries[i]))) | ||
238 | return i; | ||
239 | } | 306 | } |
240 | /* Mac not found */ | 307 | return __mlx4_register_mac(dev, port, mac); |
241 | return -EINVAL; | ||
242 | } | 308 | } |
309 | EXPORT_SYMBOL_GPL(mlx4_register_mac); | ||
310 | |||
243 | 311 | ||
244 | void mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, int qpn) | 312 | void __mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, u64 mac) |
245 | { | 313 | { |
246 | struct mlx4_port_info *info = &mlx4_priv(dev)->port[port]; | 314 | struct mlx4_port_info *info = &mlx4_priv(dev)->port[port]; |
247 | struct mlx4_mac_table *table = &info->mac_table; | 315 | struct mlx4_mac_table *table = &info->mac_table; |
248 | int index = qpn - info->base_qpn; | 316 | int index; |
249 | struct mlx4_mac_entry *entry; | ||
250 | 317 | ||
251 | if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER) { | 318 | index = find_index(dev, table, mac); |
252 | entry = radix_tree_lookup(&info->mac_tree, qpn); | ||
253 | if (entry) { | ||
254 | mlx4_uc_steer_release(dev, port, entry->mac, qpn, 1); | ||
255 | radix_tree_delete(&info->mac_tree, qpn); | ||
256 | index = find_index(dev, table, entry->mac); | ||
257 | kfree(entry); | ||
258 | } | ||
259 | } | ||
260 | 319 | ||
261 | mutex_lock(&table->mutex); | 320 | mutex_lock(&table->mutex); |
262 | 321 | ||
263 | if (validate_index(dev, table, index)) | 322 | if (validate_index(dev, table, index)) |
264 | goto out; | 323 | goto out; |
265 | 324 | ||
266 | /* Check whether this address has reference count */ | 325 | table->entries[index] = 0; |
267 | if (!(--table->refs[index])) { | 326 | mlx4_set_port_mac_table(dev, port, table->entries); |
268 | table->entries[index] = 0; | 327 | --table->total; |
269 | mlx4_set_port_mac_table(dev, port, table->entries); | ||
270 | --table->total; | ||
271 | } | ||
272 | out: | 328 | out: |
273 | mutex_unlock(&table->mutex); | 329 | mutex_unlock(&table->mutex); |
274 | } | 330 | } |
331 | EXPORT_SYMBOL_GPL(__mlx4_unregister_mac); | ||
332 | |||
333 | void mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, u64 mac) | ||
334 | { | ||
335 | u64 out_param; | ||
336 | int err; | ||
337 | |||
338 | if (mlx4_is_mfunc(dev)) { | ||
339 | set_param_l(&out_param, port); | ||
340 | err = mlx4_cmd_imm(dev, mac, &out_param, RES_MAC, | ||
341 | RES_OP_RESERVE_AND_MAP, MLX4_CMD_FREE_RES, | ||
342 | MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); | ||
343 | return; | ||
344 | } | ||
345 | __mlx4_unregister_mac(dev, port, mac); | ||
346 | return; | ||
347 | } | ||
275 | EXPORT_SYMBOL_GPL(mlx4_unregister_mac); | 348 | EXPORT_SYMBOL_GPL(mlx4_unregister_mac); |
276 | 349 | ||
277 | int mlx4_replace_mac(struct mlx4_dev *dev, u8 port, int qpn, u64 new_mac, u8 wrap) | 350 | int mlx4_replace_mac(struct mlx4_dev *dev, u8 port, int qpn, u64 new_mac) |
278 | { | 351 | { |
279 | struct mlx4_port_info *info = &mlx4_priv(dev)->port[port]; | 352 | struct mlx4_port_info *info = &mlx4_priv(dev)->port[port]; |
280 | struct mlx4_mac_table *table = &info->mac_table; | 353 | struct mlx4_mac_table *table = &info->mac_table; |
281 | int index = qpn - info->base_qpn; | ||
282 | struct mlx4_mac_entry *entry; | 354 | struct mlx4_mac_entry *entry; |
283 | int err; | 355 | int index = qpn - info->base_qpn; |
356 | int err = 0; | ||
284 | 357 | ||
285 | if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER) { | 358 | if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER) { |
286 | entry = radix_tree_lookup(&info->mac_tree, qpn); | 359 | entry = radix_tree_lookup(&info->mac_tree, qpn); |
287 | if (!entry) | 360 | if (!entry) |
288 | return -EINVAL; | 361 | return -EINVAL; |
289 | index = find_index(dev, table, entry->mac); | 362 | mlx4_uc_steer_release(dev, port, entry->mac, qpn); |
290 | mlx4_uc_steer_release(dev, port, entry->mac, qpn, 0); | 363 | mlx4_unregister_mac(dev, port, entry->mac); |
291 | entry->mac = new_mac; | 364 | entry->mac = new_mac; |
292 | err = mlx4_uc_steer_add(dev, port, entry->mac, &qpn, 0); | 365 | mlx4_register_mac(dev, port, new_mac); |
293 | if (err || index < 0) | 366 | err = mlx4_uc_steer_add(dev, port, entry->mac, &qpn); |
294 | return err; | 367 | return err; |
295 | } | 368 | } |
296 | 369 | ||
370 | /* CX1 doesn't support multi-functions */ | ||
297 | mutex_lock(&table->mutex); | 371 | mutex_lock(&table->mutex); |
298 | 372 | ||
299 | err = validate_index(dev, table, index); | 373 | err = validate_index(dev, table, index); |
@@ -304,7 +378,8 @@ int mlx4_replace_mac(struct mlx4_dev *dev, u8 port, int qpn, u64 new_mac, u8 wra | |||
304 | 378 | ||
305 | err = mlx4_set_port_mac_table(dev, port, table->entries); | 379 | err = mlx4_set_port_mac_table(dev, port, table->entries); |
306 | if (unlikely(err)) { | 380 | if (unlikely(err)) { |
307 | mlx4_err(dev, "Failed adding MAC: 0x%llx\n", (unsigned long long) new_mac); | 381 | mlx4_err(dev, "Failed adding MAC: 0x%llx\n", |
382 | (unsigned long long) new_mac); | ||
308 | table->entries[index] = 0; | 383 | table->entries[index] = 0; |
309 | } | 384 | } |
310 | out: | 385 | out: |
@@ -312,6 +387,7 @@ out: | |||
312 | return err; | 387 | return err; |
313 | } | 388 | } |
314 | EXPORT_SYMBOL_GPL(mlx4_replace_mac); | 389 | EXPORT_SYMBOL_GPL(mlx4_replace_mac); |
390 | |||
315 | static int mlx4_set_port_vlan_table(struct mlx4_dev *dev, u8 port, | 391 | static int mlx4_set_port_vlan_table(struct mlx4_dev *dev, u8 port, |
316 | __be32 *entries) | 392 | __be32 *entries) |
317 | { | 393 | { |
@@ -352,7 +428,8 @@ int mlx4_find_cached_vlan(struct mlx4_dev *dev, u8 port, u16 vid, int *idx) | |||
352 | } | 428 | } |
353 | EXPORT_SYMBOL_GPL(mlx4_find_cached_vlan); | 429 | EXPORT_SYMBOL_GPL(mlx4_find_cached_vlan); |
354 | 430 | ||
355 | int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index) | 431 | static int __mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, |
432 | int *index) | ||
356 | { | 433 | { |
357 | struct mlx4_vlan_table *table = &mlx4_priv(dev)->port[port].vlan_table; | 434 | struct mlx4_vlan_table *table = &mlx4_priv(dev)->port[port].vlan_table; |
358 | int i, err = 0; | 435 | int i, err = 0; |
@@ -387,7 +464,7 @@ int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index) | |||
387 | goto out; | 464 | goto out; |
388 | } | 465 | } |
389 | 466 | ||
390 | /* Register new MAC */ | 467 | /* Register new VLAN */ |
391 | table->refs[free] = 1; | 468 | table->refs[free] = 1; |
392 | table->entries[free] = cpu_to_be32(vlan | MLX4_VLAN_VALID); | 469 | table->entries[free] = cpu_to_be32(vlan | MLX4_VLAN_VALID); |
393 | 470 | ||
@@ -405,9 +482,27 @@ out: | |||
405 | mutex_unlock(&table->mutex); | 482 | mutex_unlock(&table->mutex); |
406 | return err; | 483 | return err; |
407 | } | 484 | } |
485 | |||
486 | int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index) | ||
487 | { | ||
488 | u64 out_param; | ||
489 | int err; | ||
490 | |||
491 | if (mlx4_is_mfunc(dev)) { | ||
492 | set_param_l(&out_param, port); | ||
493 | err = mlx4_cmd_imm(dev, vlan, &out_param, RES_VLAN, | ||
494 | RES_OP_RESERVE_AND_MAP, MLX4_CMD_ALLOC_RES, | ||
495 | MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); | ||
496 | if (!err) | ||
497 | *index = get_param_l(&out_param); | ||
498 | |||
499 | return err; | ||
500 | } | ||
501 | return __mlx4_register_vlan(dev, port, vlan, index); | ||
502 | } | ||
408 | EXPORT_SYMBOL_GPL(mlx4_register_vlan); | 503 | EXPORT_SYMBOL_GPL(mlx4_register_vlan); |
409 | 504 | ||
410 | void mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, int index) | 505 | static void __mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, int index) |
411 | { | 506 | { |
412 | struct mlx4_vlan_table *table = &mlx4_priv(dev)->port[port].vlan_table; | 507 | struct mlx4_vlan_table *table = &mlx4_priv(dev)->port[port].vlan_table; |
413 | 508 | ||
@@ -432,6 +527,25 @@ void mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, int index) | |||
432 | out: | 527 | out: |
433 | mutex_unlock(&table->mutex); | 528 | mutex_unlock(&table->mutex); |
434 | } | 529 | } |
530 | |||
531 | void mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, int index) | ||
532 | { | ||
533 | u64 in_param; | ||
534 | int err; | ||
535 | |||
536 | if (mlx4_is_mfunc(dev)) { | ||
537 | set_param_l(&in_param, port); | ||
538 | err = mlx4_cmd(dev, in_param, RES_VLAN, RES_OP_RESERVE_AND_MAP, | ||
539 | MLX4_CMD_FREE_RES, MLX4_CMD_TIME_CLASS_A, | ||
540 | MLX4_CMD_WRAPPED); | ||
541 | if (!err) | ||
542 | mlx4_warn(dev, "Failed freeing vlan at index:%d\n", | ||
543 | index); | ||
544 | |||
545 | return; | ||
546 | } | ||
547 | __mlx4_unregister_vlan(dev, port, index); | ||
548 | } | ||
435 | EXPORT_SYMBOL_GPL(mlx4_unregister_vlan); | 549 | EXPORT_SYMBOL_GPL(mlx4_unregister_vlan); |
436 | 550 | ||
437 | int mlx4_get_port_ib_caps(struct mlx4_dev *dev, u8 port, __be32 *caps) | 551 | int mlx4_get_port_ib_caps(struct mlx4_dev *dev, u8 port, __be32 *caps) |
@@ -514,6 +628,139 @@ int mlx4_check_ext_port_caps(struct mlx4_dev *dev, u8 port) | |||
514 | return err; | 628 | return err; |
515 | } | 629 | } |
516 | 630 | ||
631 | static int mlx4_common_set_port(struct mlx4_dev *dev, int slave, u32 in_mod, | ||
632 | u8 op_mod, struct mlx4_cmd_mailbox *inbox) | ||
633 | { | ||
634 | struct mlx4_priv *priv = mlx4_priv(dev); | ||
635 | struct mlx4_port_info *port_info; | ||
636 | struct mlx4_mfunc_master_ctx *master = &priv->mfunc.master; | ||
637 | struct mlx4_slave_state *slave_st = &master->slave_state[slave]; | ||
638 | struct mlx4_set_port_rqp_calc_context *qpn_context; | ||
639 | struct mlx4_set_port_general_context *gen_context; | ||
640 | int reset_qkey_viols; | ||
641 | int port; | ||
642 | int is_eth; | ||
643 | u32 in_modifier; | ||
644 | u32 promisc; | ||
645 | u16 mtu, prev_mtu; | ||
646 | int err; | ||
647 | int i; | ||
648 | __be32 agg_cap_mask; | ||
649 | __be32 slave_cap_mask; | ||
650 | __be32 new_cap_mask; | ||
651 | |||
652 | port = in_mod & 0xff; | ||
653 | in_modifier = in_mod >> 8; | ||
654 | is_eth = op_mod; | ||
655 | port_info = &priv->port[port]; | ||
656 | |||
657 | /* Slaves cannot perform SET_PORT operations except changing MTU */ | ||
658 | if (is_eth) { | ||
659 | if (slave != dev->caps.function && | ||
660 | in_modifier != MLX4_SET_PORT_GENERAL) { | ||
661 | mlx4_warn(dev, "denying SET_PORT for slave:%d\n", | ||
662 | slave); | ||
663 | return -EINVAL; | ||
664 | } | ||
665 | switch (in_modifier) { | ||
666 | case MLX4_SET_PORT_RQP_CALC: | ||
667 | qpn_context = inbox->buf; | ||
668 | qpn_context->base_qpn = | ||
669 | cpu_to_be32(port_info->base_qpn); | ||
670 | qpn_context->n_mac = 0x7; | ||
671 | promisc = be32_to_cpu(qpn_context->promisc) >> | ||
672 | SET_PORT_PROMISC_SHIFT; | ||
673 | qpn_context->promisc = cpu_to_be32( | ||
674 | promisc << SET_PORT_PROMISC_SHIFT | | ||
675 | port_info->base_qpn); | ||
676 | promisc = be32_to_cpu(qpn_context->mcast) >> | ||
677 | SET_PORT_MC_PROMISC_SHIFT; | ||
678 | qpn_context->mcast = cpu_to_be32( | ||
679 | promisc << SET_PORT_MC_PROMISC_SHIFT | | ||
680 | port_info->base_qpn); | ||
681 | break; | ||
682 | case MLX4_SET_PORT_GENERAL: | ||
683 | gen_context = inbox->buf; | ||
684 | /* Mtu is configured as the max MTU among all the | ||
685 | * the functions on the port. */ | ||
686 | mtu = be16_to_cpu(gen_context->mtu); | ||
687 | mtu = min_t(int, mtu, dev->caps.eth_mtu_cap[port]); | ||
688 | prev_mtu = slave_st->mtu[port]; | ||
689 | slave_st->mtu[port] = mtu; | ||
690 | if (mtu > master->max_mtu[port]) | ||
691 | master->max_mtu[port] = mtu; | ||
692 | if (mtu < prev_mtu && prev_mtu == | ||
693 | master->max_mtu[port]) { | ||
694 | slave_st->mtu[port] = mtu; | ||
695 | master->max_mtu[port] = mtu; | ||
696 | for (i = 0; i < dev->num_slaves; i++) { | ||
697 | master->max_mtu[port] = | ||
698 | max(master->max_mtu[port], | ||
699 | master->slave_state[i].mtu[port]); | ||
700 | } | ||
701 | } | ||
702 | |||
703 | gen_context->mtu = cpu_to_be16(master->max_mtu[port]); | ||
704 | break; | ||
705 | } | ||
706 | return mlx4_cmd(dev, inbox->dma, in_mod, op_mod, | ||
707 | MLX4_CMD_SET_PORT, MLX4_CMD_TIME_CLASS_B, | ||
708 | MLX4_CMD_NATIVE); | ||
709 | } | ||
710 | |||
711 | /* For IB, we only consider: | ||
712 | * - The capability mask, which is set to the aggregate of all | ||
713 | * slave function capabilities | ||
714 | * - The QKey violatin counter - reset according to each request. | ||
715 | */ | ||
716 | |||
717 | if (dev->flags & MLX4_FLAG_OLD_PORT_CMDS) { | ||
718 | reset_qkey_viols = (*(u8 *) inbox->buf) & 0x40; | ||
719 | new_cap_mask = ((__be32 *) inbox->buf)[2]; | ||
720 | } else { | ||
721 | reset_qkey_viols = ((u8 *) inbox->buf)[3] & 0x1; | ||
722 | new_cap_mask = ((__be32 *) inbox->buf)[1]; | ||
723 | } | ||
724 | |||
725 | agg_cap_mask = 0; | ||
726 | slave_cap_mask = | ||
727 | priv->mfunc.master.slave_state[slave].ib_cap_mask[port]; | ||
728 | priv->mfunc.master.slave_state[slave].ib_cap_mask[port] = new_cap_mask; | ||
729 | for (i = 0; i < dev->num_slaves; i++) | ||
730 | agg_cap_mask |= | ||
731 | priv->mfunc.master.slave_state[i].ib_cap_mask[port]; | ||
732 | |||
733 | /* only clear mailbox for guests. Master may be setting | ||
734 | * MTU or PKEY table size | ||
735 | */ | ||
736 | if (slave != dev->caps.function) | ||
737 | memset(inbox->buf, 0, 256); | ||
738 | if (dev->flags & MLX4_FLAG_OLD_PORT_CMDS) { | ||
739 | *(u8 *) inbox->buf = !!reset_qkey_viols << 6; | ||
740 | ((__be32 *) inbox->buf)[2] = agg_cap_mask; | ||
741 | } else { | ||
742 | ((u8 *) inbox->buf)[3] = !!reset_qkey_viols; | ||
743 | ((__be32 *) inbox->buf)[1] = agg_cap_mask; | ||
744 | } | ||
745 | |||
746 | err = mlx4_cmd(dev, inbox->dma, port, is_eth, MLX4_CMD_SET_PORT, | ||
747 | MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE); | ||
748 | if (err) | ||
749 | priv->mfunc.master.slave_state[slave].ib_cap_mask[port] = | ||
750 | slave_cap_mask; | ||
751 | return err; | ||
752 | } | ||
753 | |||
754 | int mlx4_SET_PORT_wrapper(struct mlx4_dev *dev, int slave, | ||
755 | struct mlx4_vhcr *vhcr, | ||
756 | struct mlx4_cmd_mailbox *inbox, | ||
757 | struct mlx4_cmd_mailbox *outbox, | ||
758 | struct mlx4_cmd_info *cmd) | ||
759 | { | ||
760 | return mlx4_common_set_port(dev, slave, vhcr->in_modifier, | ||
761 | vhcr->op_modifier, inbox); | ||
762 | } | ||
763 | |||
517 | int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port) | 764 | int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port) |
518 | { | 765 | { |
519 | struct mlx4_cmd_mailbox *mailbox; | 766 | struct mlx4_cmd_mailbox *mailbox; |
@@ -535,3 +782,122 @@ int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port) | |||
535 | mlx4_free_cmd_mailbox(dev, mailbox); | 782 | mlx4_free_cmd_mailbox(dev, mailbox); |
536 | return err; | 783 | return err; |
537 | } | 784 | } |
785 | |||
786 | static int mlx4_SET_PORT_general(struct mlx4_dev *dev, u8 port, int mtu, | ||
787 | u8 pptx, u8 pfctx, u8 pprx, u8 pfcrx) | ||
788 | { | ||
789 | struct mlx4_cmd_mailbox *mailbox; | ||
790 | struct mlx4_set_port_general_context *context; | ||
791 | int err; | ||
792 | u32 in_mod; | ||
793 | |||
794 | mailbox = mlx4_alloc_cmd_mailbox(dev); | ||
795 | if (IS_ERR(mailbox)) | ||
796 | return PTR_ERR(mailbox); | ||
797 | context = mailbox->buf; | ||
798 | memset(context, 0, sizeof *context); | ||
799 | |||
800 | context->flags = SET_PORT_GEN_ALL_VALID; | ||
801 | context->mtu = cpu_to_be16(mtu); | ||
802 | context->pptx = (pptx * (!pfctx)) << 7; | ||
803 | context->pfctx = pfctx; | ||
804 | context->pprx = (pprx * (!pfcrx)) << 7; | ||
805 | context->pfcrx = pfcrx; | ||
806 | |||
807 | in_mod = MLX4_SET_PORT_GENERAL << 8 | port; | ||
808 | err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT, | ||
809 | MLX4_CMD_TIME_CLASS_B, MLX4_CMD_WRAPPED); | ||
810 | |||
811 | mlx4_free_cmd_mailbox(dev, mailbox); | ||
812 | return err; | ||
813 | } | ||
814 | EXPORT_SYMBOL(mlx4_SET_PORT_general); | ||
815 | |||
816 | static int mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn, | ||
817 | u8 promisc) | ||
818 | { | ||
819 | struct mlx4_cmd_mailbox *mailbox; | ||
820 | struct mlx4_set_port_rqp_calc_context *context; | ||
821 | int err; | ||
822 | u32 in_mod; | ||
823 | u32 m_promisc = (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER) ? | ||
824 | MCAST_DIRECT : MCAST_DEFAULT; | ||
825 | |||
826 | if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER && | ||
827 | dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER) | ||
828 | return 0; | ||
829 | |||
830 | mailbox = mlx4_alloc_cmd_mailbox(dev); | ||
831 | if (IS_ERR(mailbox)) | ||
832 | return PTR_ERR(mailbox); | ||
833 | context = mailbox->buf; | ||
834 | memset(context, 0, sizeof *context); | ||
835 | |||
836 | context->base_qpn = cpu_to_be32(base_qpn); | ||
837 | context->n_mac = dev->caps.log_num_macs; | ||
838 | context->promisc = cpu_to_be32(promisc << SET_PORT_PROMISC_SHIFT | | ||
839 | base_qpn); | ||
840 | context->mcast = cpu_to_be32(m_promisc << SET_PORT_MC_PROMISC_SHIFT | | ||
841 | base_qpn); | ||
842 | context->intra_no_vlan = 0; | ||
843 | context->no_vlan = MLX4_NO_VLAN_IDX; | ||
844 | context->intra_vlan_miss = 0; | ||
845 | context->vlan_miss = MLX4_VLAN_MISS_IDX; | ||
846 | |||
847 | in_mod = MLX4_SET_PORT_RQP_CALC << 8 | port; | ||
848 | err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT, | ||
849 | MLX4_CMD_TIME_CLASS_B, MLX4_CMD_WRAPPED); | ||
850 | |||
851 | mlx4_free_cmd_mailbox(dev, mailbox); | ||
852 | return err; | ||
853 | } | ||
854 | EXPORT_SYMBOL(mlx4_SET_PORT_qpn_calc); | ||
855 | |||
856 | int mlx4_SET_MCAST_FLTR_wrapper(struct mlx4_dev *dev, int slave, | ||
857 | struct mlx4_vhcr *vhcr, | ||
858 | struct mlx4_cmd_mailbox *inbox, | ||
859 | struct mlx4_cmd_mailbox *outbox, | ||
860 | struct mlx4_cmd_info *cmd) | ||
861 | { | ||
862 | int err = 0; | ||
863 | |||
864 | return err; | ||
865 | } | ||
866 | |||
867 | int mlx4_SET_MCAST_FLTR(struct mlx4_dev *dev, u8 port, | ||
868 | u64 mac, u64 clear, u8 mode) | ||
869 | { | ||
870 | return mlx4_cmd(dev, (mac | (clear << 63)), port, mode, | ||
871 | MLX4_CMD_SET_MCAST_FLTR, MLX4_CMD_TIME_CLASS_B, | ||
872 | MLX4_CMD_WRAPPED); | ||
873 | } | ||
874 | EXPORT_SYMBOL(mlx4_SET_MCAST_FLTR); | ||
875 | |||
876 | int mlx4_SET_VLAN_FLTR_wrapper(struct mlx4_dev *dev, int slave, | ||
877 | struct mlx4_vhcr *vhcr, | ||
878 | struct mlx4_cmd_mailbox *inbox, | ||
879 | struct mlx4_cmd_mailbox *outbox, | ||
880 | struct mlx4_cmd_info *cmd) | ||
881 | { | ||
882 | int err = 0; | ||
883 | |||
884 | return err; | ||
885 | } | ||
886 | |||
887 | int mlx4_common_dump_eth_stats(struct mlx4_dev *dev, int slave, | ||
888 | u32 in_mod, struct mlx4_cmd_mailbox *outbox) | ||
889 | { | ||
890 | return mlx4_cmd_box(dev, 0, outbox->dma, in_mod, 0, | ||
891 | MLX4_CMD_DUMP_ETH_STATS, MLX4_CMD_TIME_CLASS_B, | ||
892 | MLX4_CMD_NATIVE); | ||
893 | } | ||
894 | |||
895 | int mlx4_DUMP_ETH_STATS_wrapper(struct mlx4_dev *dev, int slave, | ||
896 | struct mlx4_vhcr *vhcr, | ||
897 | struct mlx4_cmd_mailbox *inbox, | ||
898 | struct mlx4_cmd_mailbox *outbox, | ||
899 | struct mlx4_cmd_info *cmd) | ||
900 | { | ||
901 | return mlx4_common_dump_eth_stats(dev, slave, | ||
902 | vhcr->in_modifier, outbox); | ||
903 | } | ||
diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c index 59fc35ee66ad..0d99f57f9c8c 100644 --- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c +++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c | |||
@@ -223,17 +223,6 @@ static const char *ResourceType(enum mlx4_resource rt) | |||
223 | }; | 223 | }; |
224 | } | 224 | } |
225 | 225 | ||
226 | /* dummy procedures */ | ||
227 | int __mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac) | ||
228 | { | ||
229 | return 0; | ||
230 | } | ||
231 | |||
232 | void __mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, u64 mac) | ||
233 | { | ||
234 | } | ||
235 | /* end dummies */ | ||
236 | |||
237 | int mlx4_init_resource_tracker(struct mlx4_dev *dev) | 226 | int mlx4_init_resource_tracker(struct mlx4_dev *dev) |
238 | { | 227 | { |
239 | struct mlx4_priv *priv = mlx4_priv(dev); | 228 | struct mlx4_priv *priv = mlx4_priv(dev); |
@@ -1271,6 +1260,12 @@ static int mac_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd, | |||
1271 | return err; | 1260 | return err; |
1272 | } | 1261 | } |
1273 | 1262 | ||
1263 | static int vlan_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd, | ||
1264 | u64 in_param, u64 *out_param) | ||
1265 | { | ||
1266 | return 0; | ||
1267 | } | ||
1268 | |||
1274 | int mlx4_ALLOC_RES_wrapper(struct mlx4_dev *dev, int slave, | 1269 | int mlx4_ALLOC_RES_wrapper(struct mlx4_dev *dev, int slave, |
1275 | struct mlx4_vhcr *vhcr, | 1270 | struct mlx4_vhcr *vhcr, |
1276 | struct mlx4_cmd_mailbox *inbox, | 1271 | struct mlx4_cmd_mailbox *inbox, |
@@ -1311,6 +1306,11 @@ int mlx4_ALLOC_RES_wrapper(struct mlx4_dev *dev, int slave, | |||
1311 | vhcr->in_param, &vhcr->out_param); | 1306 | vhcr->in_param, &vhcr->out_param); |
1312 | break; | 1307 | break; |
1313 | 1308 | ||
1309 | case RES_VLAN: | ||
1310 | err = vlan_alloc_res(dev, slave, vhcr->op_modifier, alop, | ||
1311 | vhcr->in_param, &vhcr->out_param); | ||
1312 | break; | ||
1313 | |||
1314 | default: | 1314 | default: |
1315 | err = -EINVAL; | 1315 | err = -EINVAL; |
1316 | break; | 1316 | break; |
@@ -1487,6 +1487,12 @@ static int mac_free_res(struct mlx4_dev *dev, int slave, int op, int cmd, | |||
1487 | 1487 | ||
1488 | } | 1488 | } |
1489 | 1489 | ||
1490 | static int vlan_free_res(struct mlx4_dev *dev, int slave, int op, int cmd, | ||
1491 | u64 in_param, u64 *out_param) | ||
1492 | { | ||
1493 | return 0; | ||
1494 | } | ||
1495 | |||
1490 | int mlx4_FREE_RES_wrapper(struct mlx4_dev *dev, int slave, | 1496 | int mlx4_FREE_RES_wrapper(struct mlx4_dev *dev, int slave, |
1491 | struct mlx4_vhcr *vhcr, | 1497 | struct mlx4_vhcr *vhcr, |
1492 | struct mlx4_cmd_mailbox *inbox, | 1498 | struct mlx4_cmd_mailbox *inbox, |
@@ -1527,6 +1533,11 @@ int mlx4_FREE_RES_wrapper(struct mlx4_dev *dev, int slave, | |||
1527 | vhcr->in_param, &vhcr->out_param); | 1533 | vhcr->in_param, &vhcr->out_param); |
1528 | break; | 1534 | break; |
1529 | 1535 | ||
1536 | case RES_VLAN: | ||
1537 | err = vlan_free_res(dev, slave, vhcr->op_modifier, alop, | ||
1538 | vhcr->in_param, &vhcr->out_param); | ||
1539 | break; | ||
1540 | |||
1530 | default: | 1541 | default: |
1531 | break; | 1542 | break; |
1532 | } | 1543 | } |