diff options
author | Matan Barak <matanb@mellanox.com> | 2014-03-19 12:11:52 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-03-20 16:18:30 -0400 |
commit | 449fc48866f7d84b0d9a19201de18a4dd4d3488c (patch) | |
tree | 20db12e2dd676c6c824a8173601c9023632d3c37 /drivers/net/ethernet/mellanox/mlx4/port.c | |
parent | f74462acf8f390528c8b7937f227c6c90d017f3b (diff) |
net/mlx4: Adapt code for N-Port VF
Adds support for N-Port VFs, this includes:
1. Adding support in the wrapped FW command
In wrapped commands, we need to verify and convert
the slave's port into the real physical port.
Furthermore, when sending the response back to the slave,
a reverse conversion should be made.
2. Adjusting sqpn for QP1 para-virtualization
The slave assumes that sqpn is used for QP1 communication.
If the slave is assigned to a port != (first port), we need
to adjust the sqpn that will direct its QP1 packets into the
correct endpoint.
3. Adjusting gid[5] to modify the port for raw ethernet
In B0 steering, gid[5] contains the port. It needs
to be adjusted into the physical port.
4. Adjusting number of ports in the query / ports caps in the FW commands
When a slave queries the hardware, it needs to view only
the physical ports it's assigned to.
5. Adjusting the sched_qp according to the port number
The QP port is encoded in the sched_qp, thus in modify_qp we need
to encode the correct port in sched_qp.
Signed-off-by: Matan Barak <matanb@mellanox.com>
Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/mellanox/mlx4/port.c')
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/port.c | 158 |
1 files changed, 138 insertions, 20 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx4/port.c b/drivers/net/ethernet/mellanox/mlx4/port.c index ece328166e94..2705b9ab9463 100644 --- a/drivers/net/ethernet/mellanox/mlx4/port.c +++ b/drivers/net/ethernet/mellanox/mlx4/port.c | |||
@@ -507,30 +507,82 @@ int mlx4_get_port_ib_caps(struct mlx4_dev *dev, u8 port, __be32 *caps) | |||
507 | } | 507 | } |
508 | static struct mlx4_roce_gid_entry zgid_entry; | 508 | static struct mlx4_roce_gid_entry zgid_entry; |
509 | 509 | ||
510 | int mlx4_get_slave_num_gids(struct mlx4_dev *dev, int slave) | 510 | int mlx4_get_slave_num_gids(struct mlx4_dev *dev, int slave, int port) |
511 | { | 511 | { |
512 | int vfs; | ||
513 | int slave_gid = slave; | ||
514 | unsigned i; | ||
515 | struct mlx4_slaves_pport slaves_pport; | ||
516 | struct mlx4_active_ports actv_ports; | ||
517 | unsigned max_port_p_one; | ||
518 | |||
512 | if (slave == 0) | 519 | if (slave == 0) |
513 | return MLX4_ROCE_PF_GIDS; | 520 | return MLX4_ROCE_PF_GIDS; |
514 | if (slave <= ((MLX4_ROCE_MAX_GIDS - MLX4_ROCE_PF_GIDS) % dev->num_vfs)) | 521 | |
515 | return ((MLX4_ROCE_MAX_GIDS - MLX4_ROCE_PF_GIDS) / dev->num_vfs) + 1; | 522 | /* Slave is a VF */ |
516 | return (MLX4_ROCE_MAX_GIDS - MLX4_ROCE_PF_GIDS) / dev->num_vfs; | 523 | slaves_pport = mlx4_phys_to_slaves_pport(dev, port); |
524 | actv_ports = mlx4_get_active_ports(dev, slave); | ||
525 | max_port_p_one = find_first_bit(actv_ports.ports, dev->caps.num_ports) + | ||
526 | bitmap_weight(actv_ports.ports, dev->caps.num_ports) + 1; | ||
527 | |||
528 | for (i = 1; i < max_port_p_one; i++) { | ||
529 | struct mlx4_active_ports exclusive_ports; | ||
530 | struct mlx4_slaves_pport slaves_pport_actv; | ||
531 | bitmap_zero(exclusive_ports.ports, dev->caps.num_ports); | ||
532 | set_bit(i - 1, exclusive_ports.ports); | ||
533 | if (i == port) | ||
534 | continue; | ||
535 | slaves_pport_actv = mlx4_phys_to_slaves_pport_actv( | ||
536 | dev, &exclusive_ports); | ||
537 | slave_gid -= bitmap_weight(slaves_pport_actv.slaves, | ||
538 | dev->num_vfs + 1); | ||
539 | } | ||
540 | vfs = bitmap_weight(slaves_pport.slaves, dev->num_vfs + 1) - 1; | ||
541 | if (slave_gid <= ((MLX4_ROCE_MAX_GIDS - MLX4_ROCE_PF_GIDS) % vfs)) | ||
542 | return ((MLX4_ROCE_MAX_GIDS - MLX4_ROCE_PF_GIDS) / vfs) + 1; | ||
543 | return (MLX4_ROCE_MAX_GIDS - MLX4_ROCE_PF_GIDS) / vfs; | ||
517 | } | 544 | } |
518 | 545 | ||
519 | int mlx4_get_base_gid_ix(struct mlx4_dev *dev, int slave) | 546 | int mlx4_get_base_gid_ix(struct mlx4_dev *dev, int slave, int port) |
520 | { | 547 | { |
521 | int gids; | 548 | int gids; |
549 | unsigned i; | ||
550 | int slave_gid = slave; | ||
522 | int vfs; | 551 | int vfs; |
523 | 552 | ||
524 | gids = MLX4_ROCE_MAX_GIDS - MLX4_ROCE_PF_GIDS; | 553 | struct mlx4_slaves_pport slaves_pport; |
525 | vfs = dev->num_vfs; | 554 | struct mlx4_active_ports actv_ports; |
555 | unsigned max_port_p_one; | ||
526 | 556 | ||
527 | if (slave == 0) | 557 | if (slave == 0) |
528 | return 0; | 558 | return 0; |
529 | if (slave <= gids % vfs) | ||
530 | return MLX4_ROCE_PF_GIDS + ((gids / vfs) + 1) * (slave - 1); | ||
531 | 559 | ||
532 | return MLX4_ROCE_PF_GIDS + (gids % vfs) + ((gids / vfs) * (slave - 1)); | 560 | slaves_pport = mlx4_phys_to_slaves_pport(dev, port); |
561 | actv_ports = mlx4_get_active_ports(dev, slave); | ||
562 | max_port_p_one = find_first_bit(actv_ports.ports, dev->caps.num_ports) + | ||
563 | bitmap_weight(actv_ports.ports, dev->caps.num_ports) + 1; | ||
564 | |||
565 | for (i = 1; i < max_port_p_one; i++) { | ||
566 | struct mlx4_active_ports exclusive_ports; | ||
567 | struct mlx4_slaves_pport slaves_pport_actv; | ||
568 | bitmap_zero(exclusive_ports.ports, dev->caps.num_ports); | ||
569 | set_bit(i - 1, exclusive_ports.ports); | ||
570 | if (i == port) | ||
571 | continue; | ||
572 | slaves_pport_actv = mlx4_phys_to_slaves_pport_actv( | ||
573 | dev, &exclusive_ports); | ||
574 | slave_gid -= bitmap_weight(slaves_pport_actv.slaves, | ||
575 | dev->num_vfs + 1); | ||
576 | } | ||
577 | gids = MLX4_ROCE_MAX_GIDS - MLX4_ROCE_PF_GIDS; | ||
578 | vfs = bitmap_weight(slaves_pport.slaves, dev->num_vfs + 1) - 1; | ||
579 | if (slave_gid <= gids % vfs) | ||
580 | return MLX4_ROCE_PF_GIDS + ((gids / vfs) + 1) * (slave_gid - 1); | ||
581 | |||
582 | return MLX4_ROCE_PF_GIDS + (gids % vfs) + | ||
583 | ((gids / vfs) * (slave_gid - 1)); | ||
533 | } | 584 | } |
585 | EXPORT_SYMBOL_GPL(mlx4_get_base_gid_ix); | ||
534 | 586 | ||
535 | static int mlx4_common_set_port(struct mlx4_dev *dev, int slave, u32 in_mod, | 587 | static int mlx4_common_set_port(struct mlx4_dev *dev, int slave, u32 in_mod, |
536 | u8 op_mod, struct mlx4_cmd_mailbox *inbox) | 588 | u8 op_mod, struct mlx4_cmd_mailbox *inbox) |
@@ -617,8 +669,8 @@ static int mlx4_common_set_port(struct mlx4_dev *dev, int slave, u32 in_mod, | |||
617 | * need a FOR-loop here over number of gids the guest has. | 669 | * need a FOR-loop here over number of gids the guest has. |
618 | * 1. Check no duplicates in gids passed by slave | 670 | * 1. Check no duplicates in gids passed by slave |
619 | */ | 671 | */ |
620 | num_gids = mlx4_get_slave_num_gids(dev, slave); | 672 | num_gids = mlx4_get_slave_num_gids(dev, slave, port); |
621 | base = mlx4_get_base_gid_ix(dev, slave); | 673 | base = mlx4_get_base_gid_ix(dev, slave, port); |
622 | gid_entry_mbox = (struct mlx4_roce_gid_entry *)(inbox->buf); | 674 | gid_entry_mbox = (struct mlx4_roce_gid_entry *)(inbox->buf); |
623 | for (i = 0; i < num_gids; gid_entry_mbox++, i++) { | 675 | for (i = 0; i < num_gids; gid_entry_mbox++, i++) { |
624 | if (!memcmp(gid_entry_mbox->raw, zgid_entry.raw, | 676 | if (!memcmp(gid_entry_mbox->raw, zgid_entry.raw, |
@@ -738,6 +790,15 @@ int mlx4_SET_PORT_wrapper(struct mlx4_dev *dev, int slave, | |||
738 | struct mlx4_cmd_mailbox *outbox, | 790 | struct mlx4_cmd_mailbox *outbox, |
739 | struct mlx4_cmd_info *cmd) | 791 | struct mlx4_cmd_info *cmd) |
740 | { | 792 | { |
793 | int port = mlx4_slave_convert_port( | ||
794 | dev, slave, vhcr->in_modifier & 0xFF); | ||
795 | |||
796 | if (port < 0) | ||
797 | return -EINVAL; | ||
798 | |||
799 | vhcr->in_modifier = (vhcr->in_modifier & ~0xFF) | | ||
800 | (port & 0xFF); | ||
801 | |||
741 | return mlx4_common_set_port(dev, slave, vhcr->in_modifier, | 802 | return mlx4_common_set_port(dev, slave, vhcr->in_modifier, |
742 | vhcr->op_modifier, inbox); | 803 | vhcr->op_modifier, inbox); |
743 | } | 804 | } |
@@ -1026,10 +1087,16 @@ int mlx4_get_slave_from_roce_gid(struct mlx4_dev *dev, int port, u8 *gid, | |||
1026 | struct mlx4_priv *priv = mlx4_priv(dev); | 1087 | struct mlx4_priv *priv = mlx4_priv(dev); |
1027 | int i, found_ix = -1; | 1088 | int i, found_ix = -1; |
1028 | int vf_gids = MLX4_ROCE_MAX_GIDS - MLX4_ROCE_PF_GIDS; | 1089 | int vf_gids = MLX4_ROCE_MAX_GIDS - MLX4_ROCE_PF_GIDS; |
1090 | struct mlx4_slaves_pport slaves_pport; | ||
1091 | unsigned num_vfs; | ||
1092 | int slave_gid; | ||
1029 | 1093 | ||
1030 | if (!mlx4_is_mfunc(dev)) | 1094 | if (!mlx4_is_mfunc(dev)) |
1031 | return -EINVAL; | 1095 | return -EINVAL; |
1032 | 1096 | ||
1097 | slaves_pport = mlx4_phys_to_slaves_pport(dev, port); | ||
1098 | num_vfs = bitmap_weight(slaves_pport.slaves, dev->num_vfs + 1) - 1; | ||
1099 | |||
1033 | for (i = 0; i < MLX4_ROCE_MAX_GIDS; i++) { | 1100 | for (i = 0; i < MLX4_ROCE_MAX_GIDS; i++) { |
1034 | if (!memcmp(priv->roce_gids[port - 1][i].raw, gid, 16)) { | 1101 | if (!memcmp(priv->roce_gids[port - 1][i].raw, gid, 16)) { |
1035 | found_ix = i; | 1102 | found_ix = i; |
@@ -1039,16 +1106,67 @@ int mlx4_get_slave_from_roce_gid(struct mlx4_dev *dev, int port, u8 *gid, | |||
1039 | 1106 | ||
1040 | if (found_ix >= 0) { | 1107 | if (found_ix >= 0) { |
1041 | if (found_ix < MLX4_ROCE_PF_GIDS) | 1108 | if (found_ix < MLX4_ROCE_PF_GIDS) |
1042 | *slave_id = 0; | 1109 | slave_gid = 0; |
1043 | else if (found_ix < MLX4_ROCE_PF_GIDS + (vf_gids % dev->num_vfs) * | 1110 | else if (found_ix < MLX4_ROCE_PF_GIDS + (vf_gids % num_vfs) * |
1044 | (vf_gids / dev->num_vfs + 1)) | 1111 | (vf_gids / num_vfs + 1)) |
1045 | *slave_id = ((found_ix - MLX4_ROCE_PF_GIDS) / | 1112 | slave_gid = ((found_ix - MLX4_ROCE_PF_GIDS) / |
1046 | (vf_gids / dev->num_vfs + 1)) + 1; | 1113 | (vf_gids / num_vfs + 1)) + 1; |
1047 | else | 1114 | else |
1048 | *slave_id = | 1115 | slave_gid = |
1049 | ((found_ix - MLX4_ROCE_PF_GIDS - | 1116 | ((found_ix - MLX4_ROCE_PF_GIDS - |
1050 | ((vf_gids % dev->num_vfs) * ((vf_gids / dev->num_vfs + 1)))) / | 1117 | ((vf_gids % num_vfs) * ((vf_gids / num_vfs + 1)))) / |
1051 | (vf_gids / dev->num_vfs)) + vf_gids % dev->num_vfs + 1; | 1118 | (vf_gids / num_vfs)) + vf_gids % num_vfs + 1; |
1119 | |||
1120 | if (slave_gid) { | ||
1121 | struct mlx4_active_ports exclusive_ports; | ||
1122 | struct mlx4_active_ports actv_ports; | ||
1123 | struct mlx4_slaves_pport slaves_pport_actv; | ||
1124 | unsigned max_port_p_one; | ||
1125 | int num_slaves_before = 1; | ||
1126 | |||
1127 | for (i = 1; i < port; i++) { | ||
1128 | bitmap_zero(exclusive_ports.ports, dev->caps.num_ports); | ||
1129 | set_bit(i, exclusive_ports.ports); | ||
1130 | slaves_pport_actv = | ||
1131 | mlx4_phys_to_slaves_pport_actv( | ||
1132 | dev, &exclusive_ports); | ||
1133 | num_slaves_before += bitmap_weight( | ||
1134 | slaves_pport_actv.slaves, | ||
1135 | dev->num_vfs + 1); | ||
1136 | } | ||
1137 | |||
1138 | if (slave_gid < num_slaves_before) { | ||
1139 | bitmap_zero(exclusive_ports.ports, dev->caps.num_ports); | ||
1140 | set_bit(port - 1, exclusive_ports.ports); | ||
1141 | slaves_pport_actv = | ||
1142 | mlx4_phys_to_slaves_pport_actv( | ||
1143 | dev, &exclusive_ports); | ||
1144 | slave_gid += bitmap_weight( | ||
1145 | slaves_pport_actv.slaves, | ||
1146 | dev->num_vfs + 1) - | ||
1147 | num_slaves_before; | ||
1148 | } | ||
1149 | actv_ports = mlx4_get_active_ports(dev, slave_gid); | ||
1150 | max_port_p_one = find_first_bit( | ||
1151 | actv_ports.ports, dev->caps.num_ports) + | ||
1152 | bitmap_weight(actv_ports.ports, | ||
1153 | dev->caps.num_ports) + 1; | ||
1154 | |||
1155 | for (i = 1; i < max_port_p_one; i++) { | ||
1156 | if (i == port) | ||
1157 | continue; | ||
1158 | bitmap_zero(exclusive_ports.ports, | ||
1159 | dev->caps.num_ports); | ||
1160 | set_bit(i - 1, exclusive_ports.ports); | ||
1161 | slaves_pport_actv = | ||
1162 | mlx4_phys_to_slaves_pport_actv( | ||
1163 | dev, &exclusive_ports); | ||
1164 | slave_gid += bitmap_weight( | ||
1165 | slaves_pport_actv.slaves, | ||
1166 | dev->num_vfs + 1); | ||
1167 | } | ||
1168 | } | ||
1169 | *slave_id = slave_gid; | ||
1052 | } | 1170 | } |
1053 | 1171 | ||
1054 | return (found_ix >= 0) ? 0 : -EINVAL; | 1172 | return (found_ix >= 0) ? 0 : -EINVAL; |