aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJack Morgenstein <jackm@dev.mellanox.co.il>2014-05-27 02:26:38 -0400
committerDavid S. Miller <davem@davemloft.net>2014-05-30 19:57:52 -0400
commit111c6094bd7731cb1a415b2ea7d450fa23d6857c (patch)
tree2f56a2490bdf14350b36dead3a521e087bbea09c
parent09271db6e0f2b282f9bfe0ab6e8b644a93237c5e (diff)
net/mlx4_core: Reset RoCE VF gids when guest driver goes down
Reset the GIDs assigned to a VF in the port RoCE GID table when that guest goes down (either crashes or goes down cleanly). As part of this fix, we refactor the RoCE gid table driver copy, moving it to the mlx4_port_info structure (together with the MAC and VLAN tables). As with the MAC and VLAN tables, we now use a mutex per port for the GID table so that modifying the driver copy and modifying the firmware copy of a port GID table becomes an atomic operation (thus avoiding driver-copy/FW-copy mismatches). Signed-off-by: Jack Morgenstein <jackm@dev.mellanox.co.il> Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/main.c1
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/mlx4.h20
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/port.c117
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/resource_tracker.c3
4 files changed, 127 insertions, 14 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c
index 7cf9dadcb471..c187d748115f 100644
--- a/drivers/net/ethernet/mellanox/mlx4/main.c
+++ b/drivers/net/ethernet/mellanox/mlx4/main.c
@@ -2044,6 +2044,7 @@ static int mlx4_init_port_info(struct mlx4_dev *dev, int port)
2044 if (!mlx4_is_slave(dev)) { 2044 if (!mlx4_is_slave(dev)) {
2045 mlx4_init_mac_table(dev, &info->mac_table); 2045 mlx4_init_mac_table(dev, &info->mac_table);
2046 mlx4_init_vlan_table(dev, &info->vlan_table); 2046 mlx4_init_vlan_table(dev, &info->vlan_table);
2047 mlx4_init_roce_gid_table(dev, &info->gid_table);
2047 info->base_qpn = mlx4_get_base_qpn(dev, port); 2048 info->base_qpn = mlx4_get_base_qpn(dev, port);
2048 } 2049 }
2049 2050
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h
index 212cea440f90..8e9eb02e09cb 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h
+++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h
@@ -695,6 +695,17 @@ struct mlx4_mac_table {
695 int max; 695 int max;
696}; 696};
697 697
698#define MLX4_ROCE_GID_ENTRY_SIZE 16
699
700struct mlx4_roce_gid_entry {
701 u8 raw[MLX4_ROCE_GID_ENTRY_SIZE];
702};
703
704struct mlx4_roce_gid_table {
705 struct mlx4_roce_gid_entry roce_gids[MLX4_ROCE_MAX_GIDS];
706 struct mutex mutex;
707};
708
698#define MLX4_MAX_VLAN_NUM 128 709#define MLX4_MAX_VLAN_NUM 128
699#define MLX4_VLAN_TABLE_SIZE (MLX4_MAX_VLAN_NUM << 2) 710#define MLX4_VLAN_TABLE_SIZE (MLX4_MAX_VLAN_NUM << 2)
700 711
@@ -758,6 +769,7 @@ struct mlx4_port_info {
758 struct device_attribute port_mtu_attr; 769 struct device_attribute port_mtu_attr;
759 struct mlx4_mac_table mac_table; 770 struct mlx4_mac_table mac_table;
760 struct mlx4_vlan_table vlan_table; 771 struct mlx4_vlan_table vlan_table;
772 struct mlx4_roce_gid_table gid_table;
761 int base_qpn; 773 int base_qpn;
762}; 774};
763 775
@@ -788,10 +800,6 @@ enum {
788 MLX4_USE_RR = 1, 800 MLX4_USE_RR = 1,
789}; 801};
790 802
791struct mlx4_roce_gid_entry {
792 u8 raw[16];
793};
794
795struct mlx4_priv { 803struct mlx4_priv {
796 struct mlx4_dev dev; 804 struct mlx4_dev dev;
797 805
@@ -839,7 +847,6 @@ struct mlx4_priv {
839 int fs_hash_mode; 847 int fs_hash_mode;
840 u8 virt2phys_pkey[MLX4_MFUNC_MAX][MLX4_MAX_PORTS][MLX4_MAX_PORT_PKEYS]; 848 u8 virt2phys_pkey[MLX4_MFUNC_MAX][MLX4_MAX_PORTS][MLX4_MAX_PORT_PKEYS];
841 __be64 slave_node_guids[MLX4_MFUNC_MAX]; 849 __be64 slave_node_guids[MLX4_MFUNC_MAX];
842 struct mlx4_roce_gid_entry roce_gids[MLX4_MAX_PORTS][MLX4_ROCE_MAX_GIDS];
843 850
844 atomic_t opreq_count; 851 atomic_t opreq_count;
845 struct work_struct opreq_task; 852 struct work_struct opreq_task;
@@ -1140,6 +1147,8 @@ int mlx4_change_port_types(struct mlx4_dev *dev,
1140 1147
1141void mlx4_init_mac_table(struct mlx4_dev *dev, struct mlx4_mac_table *table); 1148void mlx4_init_mac_table(struct mlx4_dev *dev, struct mlx4_mac_table *table);
1142void mlx4_init_vlan_table(struct mlx4_dev *dev, struct mlx4_vlan_table *table); 1149void mlx4_init_vlan_table(struct mlx4_dev *dev, struct mlx4_vlan_table *table);
1150void mlx4_init_roce_gid_table(struct mlx4_dev *dev,
1151 struct mlx4_roce_gid_table *table);
1143void __mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, u16 vlan); 1152void __mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, u16 vlan);
1144int __mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index); 1153int __mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index);
1145 1154
@@ -1149,6 +1158,7 @@ int mlx4_get_slave_from_resource_id(struct mlx4_dev *dev,
1149 enum mlx4_resource resource_type, 1158 enum mlx4_resource resource_type,
1150 u64 resource_id, int *slave); 1159 u64 resource_id, int *slave);
1151void mlx4_delete_all_resources_for_slave(struct mlx4_dev *dev, int slave_id); 1160void mlx4_delete_all_resources_for_slave(struct mlx4_dev *dev, int slave_id);
1161void mlx4_reset_roce_gids(struct mlx4_dev *dev, int slave);
1152int mlx4_init_resource_tracker(struct mlx4_dev *dev); 1162int mlx4_init_resource_tracker(struct mlx4_dev *dev);
1153 1163
1154void mlx4_free_resource_tracker(struct mlx4_dev *dev, 1164void mlx4_free_resource_tracker(struct mlx4_dev *dev,
diff --git a/drivers/net/ethernet/mellanox/mlx4/port.c b/drivers/net/ethernet/mellanox/mlx4/port.c
index b5b3549b0c8d..5ec6f203c6e6 100644
--- a/drivers/net/ethernet/mellanox/mlx4/port.c
+++ b/drivers/net/ethernet/mellanox/mlx4/port.c
@@ -75,6 +75,16 @@ void mlx4_init_vlan_table(struct mlx4_dev *dev, struct mlx4_vlan_table *table)
75 table->total = 0; 75 table->total = 0;
76} 76}
77 77
78void mlx4_init_roce_gid_table(struct mlx4_dev *dev,
79 struct mlx4_roce_gid_table *table)
80{
81 int i;
82
83 mutex_init(&table->mutex);
84 for (i = 0; i < MLX4_ROCE_MAX_GIDS; i++)
85 memset(table->roce_gids[i].raw, 0, MLX4_ROCE_GID_ENTRY_SIZE);
86}
87
78static int validate_index(struct mlx4_dev *dev, 88static int validate_index(struct mlx4_dev *dev,
79 struct mlx4_mac_table *table, int index) 89 struct mlx4_mac_table *table, int index)
80{ 90{
@@ -584,6 +594,84 @@ int mlx4_get_base_gid_ix(struct mlx4_dev *dev, int slave, int port)
584} 594}
585EXPORT_SYMBOL_GPL(mlx4_get_base_gid_ix); 595EXPORT_SYMBOL_GPL(mlx4_get_base_gid_ix);
586 596
597static int mlx4_reset_roce_port_gids(struct mlx4_dev *dev, int slave,
598 int port, struct mlx4_cmd_mailbox *mailbox)
599{
600 struct mlx4_roce_gid_entry *gid_entry_mbox;
601 struct mlx4_priv *priv = mlx4_priv(dev);
602 int num_gids, base, offset;
603 int i, err;
604
605 num_gids = mlx4_get_slave_num_gids(dev, slave, port);
606 base = mlx4_get_base_gid_ix(dev, slave, port);
607
608 memset(mailbox->buf, 0, MLX4_MAILBOX_SIZE);
609
610 mutex_lock(&(priv->port[port].gid_table.mutex));
611 /* Zero-out gids belonging to that slave in the port GID table */
612 for (i = 0, offset = base; i < num_gids; offset++, i++)
613 memcpy(priv->port[port].gid_table.roce_gids[offset].raw,
614 zgid_entry.raw, MLX4_ROCE_GID_ENTRY_SIZE);
615
616 /* Now, copy roce port gids table to mailbox for passing to FW */
617 gid_entry_mbox = (struct mlx4_roce_gid_entry *)mailbox->buf;
618 for (i = 0; i < MLX4_ROCE_MAX_GIDS; gid_entry_mbox++, i++)
619 memcpy(gid_entry_mbox->raw,
620 priv->port[port].gid_table.roce_gids[i].raw,
621 MLX4_ROCE_GID_ENTRY_SIZE);
622
623 err = mlx4_cmd(dev, mailbox->dma,
624 ((u32)port) | (MLX4_SET_PORT_GID_TABLE << 8), 1,
625 MLX4_CMD_SET_PORT, MLX4_CMD_TIME_CLASS_B,
626 MLX4_CMD_NATIVE);
627 mutex_unlock(&(priv->port[port].gid_table.mutex));
628 return err;
629}
630
631
632void mlx4_reset_roce_gids(struct mlx4_dev *dev, int slave)
633{
634 struct mlx4_active_ports actv_ports;
635 struct mlx4_cmd_mailbox *mailbox;
636 int num_eth_ports, err;
637 int i;
638
639 if (slave < 0 || slave > dev->num_vfs)
640 return;
641
642 actv_ports = mlx4_get_active_ports(dev, slave);
643
644 for (i = 0, num_eth_ports = 0; i < dev->caps.num_ports; i++) {
645 if (test_bit(i, actv_ports.ports)) {
646 if (dev->caps.port_type[i + 1] != MLX4_PORT_TYPE_ETH)
647 continue;
648 num_eth_ports++;
649 }
650 }
651
652 if (!num_eth_ports)
653 return;
654
655 /* have ETH ports. Alloc mailbox for SET_PORT command */
656 mailbox = mlx4_alloc_cmd_mailbox(dev);
657 if (IS_ERR(mailbox))
658 return;
659
660 for (i = 0; i < dev->caps.num_ports; i++) {
661 if (test_bit(i, actv_ports.ports)) {
662 if (dev->caps.port_type[i + 1] != MLX4_PORT_TYPE_ETH)
663 continue;
664 err = mlx4_reset_roce_port_gids(dev, slave, i + 1, mailbox);
665 if (err)
666 mlx4_warn(dev, "Could not reset ETH port GID table for slave %d, port %d (%d)\n",
667 slave, i + 1, err);
668 }
669 }
670
671 mlx4_free_cmd_mailbox(dev, mailbox);
672 return;
673}
674
587static int mlx4_common_set_port(struct mlx4_dev *dev, int slave, u32 in_mod, 675static int mlx4_common_set_port(struct mlx4_dev *dev, int slave, u32 in_mod,
588 u8 op_mod, struct mlx4_cmd_mailbox *inbox) 676 u8 op_mod, struct mlx4_cmd_mailbox *inbox)
589{ 677{
@@ -692,10 +780,12 @@ static int mlx4_common_set_port(struct mlx4_dev *dev, int slave, u32 in_mod,
692 /* 2. Check that do not have duplicates in OTHER 780 /* 2. Check that do not have duplicates in OTHER
693 * entries in the port GID table 781 * entries in the port GID table
694 */ 782 */
783
784 mutex_lock(&(priv->port[port].gid_table.mutex));
695 for (i = 0; i < MLX4_ROCE_MAX_GIDS; i++) { 785 for (i = 0; i < MLX4_ROCE_MAX_GIDS; i++) {
696 if (i >= base && i < base + num_gids) 786 if (i >= base && i < base + num_gids)
697 continue; /* don't compare to slave's current gids */ 787 continue; /* don't compare to slave's current gids */
698 gid_entry_tbl = &priv->roce_gids[port - 1][i]; 788 gid_entry_tbl = &priv->port[port].gid_table.roce_gids[i];
699 if (!memcmp(gid_entry_tbl->raw, zgid_entry.raw, sizeof(zgid_entry))) 789 if (!memcmp(gid_entry_tbl->raw, zgid_entry.raw, sizeof(zgid_entry)))
700 continue; 790 continue;
701 gid_entry_mbox = (struct mlx4_roce_gid_entry *)(inbox->buf); 791 gid_entry_mbox = (struct mlx4_roce_gid_entry *)(inbox->buf);
@@ -709,6 +799,7 @@ static int mlx4_common_set_port(struct mlx4_dev *dev, int slave, u32 in_mod,
709 mlx4_warn(dev, "requested gid entry for slave:%d " 799 mlx4_warn(dev, "requested gid entry for slave:%d "
710 "is a duplicate of gid at index %d\n", 800 "is a duplicate of gid at index %d\n",
711 slave, i); 801 slave, i);
802 mutex_unlock(&(priv->port[port].gid_table.mutex));
712 return -EINVAL; 803 return -EINVAL;
713 } 804 }
714 } 805 }
@@ -717,16 +808,24 @@ static int mlx4_common_set_port(struct mlx4_dev *dev, int slave, u32 in_mod,
717 /* insert slave GIDs with memcpy, starting at slave's base index */ 808 /* insert slave GIDs with memcpy, starting at slave's base index */
718 gid_entry_mbox = (struct mlx4_roce_gid_entry *)(inbox->buf); 809 gid_entry_mbox = (struct mlx4_roce_gid_entry *)(inbox->buf);
719 for (i = 0, offset = base; i < num_gids; gid_entry_mbox++, offset++, i++) 810 for (i = 0, offset = base; i < num_gids; gid_entry_mbox++, offset++, i++)
720 memcpy(priv->roce_gids[port - 1][offset].raw, gid_entry_mbox->raw, 16); 811 memcpy(priv->port[port].gid_table.roce_gids[offset].raw,
812 gid_entry_mbox->raw, MLX4_ROCE_GID_ENTRY_SIZE);
721 813
722 /* Now, copy roce port gids table to current mailbox for passing to FW */ 814 /* Now, copy roce port gids table to current mailbox for passing to FW */
723 gid_entry_mbox = (struct mlx4_roce_gid_entry *)(inbox->buf); 815 gid_entry_mbox = (struct mlx4_roce_gid_entry *)(inbox->buf);
724 for (i = 0; i < MLX4_ROCE_MAX_GIDS; gid_entry_mbox++, i++) 816 for (i = 0; i < MLX4_ROCE_MAX_GIDS; gid_entry_mbox++, i++)
725 memcpy(gid_entry_mbox->raw, priv->roce_gids[port - 1][i].raw, 16); 817 memcpy(gid_entry_mbox->raw,
726 818 priv->port[port].gid_table.roce_gids[i].raw,
727 break; 819 MLX4_ROCE_GID_ENTRY_SIZE);
820
821 err = mlx4_cmd(dev, inbox->dma, in_mod & 0xffff, op_mod,
822 MLX4_CMD_SET_PORT, MLX4_CMD_TIME_CLASS_B,
823 MLX4_CMD_NATIVE);
824 mutex_unlock(&(priv->port[port].gid_table.mutex));
825 return err;
728 } 826 }
729 return mlx4_cmd(dev, inbox->dma, in_mod, op_mod, 827
828 return mlx4_cmd(dev, inbox->dma, in_mod & 0xffff, op_mod,
730 MLX4_CMD_SET_PORT, MLX4_CMD_TIME_CLASS_B, 829 MLX4_CMD_SET_PORT, MLX4_CMD_TIME_CLASS_B,
731 MLX4_CMD_NATIVE); 830 MLX4_CMD_NATIVE);
732 } 831 }
@@ -1099,7 +1198,8 @@ int mlx4_get_slave_from_roce_gid(struct mlx4_dev *dev, int port, u8 *gid,
1099 num_vfs = bitmap_weight(slaves_pport.slaves, dev->num_vfs + 1) - 1; 1198 num_vfs = bitmap_weight(slaves_pport.slaves, dev->num_vfs + 1) - 1;
1100 1199
1101 for (i = 0; i < MLX4_ROCE_MAX_GIDS; i++) { 1200 for (i = 0; i < MLX4_ROCE_MAX_GIDS; i++) {
1102 if (!memcmp(priv->roce_gids[port - 1][i].raw, gid, 16)) { 1201 if (!memcmp(priv->port[port].gid_table.roce_gids[i].raw, gid,
1202 MLX4_ROCE_GID_ENTRY_SIZE)) {
1103 found_ix = i; 1203 found_ix = i;
1104 break; 1204 break;
1105 } 1205 }
@@ -1187,7 +1287,8 @@ int mlx4_get_roce_gid_from_slave(struct mlx4_dev *dev, int port, int slave_id,
1187 if (!mlx4_is_master(dev)) 1287 if (!mlx4_is_master(dev))
1188 return -EINVAL; 1288 return -EINVAL;
1189 1289
1190 memcpy(gid, priv->roce_gids[port - 1][slave_id].raw, 16); 1290 memcpy(gid, priv->port[port].gid_table.roce_gids[slave_id].raw,
1291 MLX4_ROCE_GID_ENTRY_SIZE);
1191 return 0; 1292 return 0;
1192} 1293}
1193EXPORT_SYMBOL(mlx4_get_roce_gid_from_slave); 1294EXPORT_SYMBOL(mlx4_get_roce_gid_from_slave);
diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
index 8f1254a79832..f16e539749c4 100644
--- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
+++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
@@ -586,6 +586,7 @@ void mlx4_free_resource_tracker(struct mlx4_dev *dev,
586 } 586 }
587 /* free master's vlans */ 587 /* free master's vlans */
588 i = dev->caps.function; 588 i = dev->caps.function;
589 mlx4_reset_roce_gids(dev, i);
589 mutex_lock(&priv->mfunc.master.res_tracker.slave_list[i].mutex); 590 mutex_lock(&priv->mfunc.master.res_tracker.slave_list[i].mutex);
590 rem_slave_vlans(dev, i); 591 rem_slave_vlans(dev, i);
591 mutex_unlock(&priv->mfunc.master.res_tracker.slave_list[i].mutex); 592 mutex_unlock(&priv->mfunc.master.res_tracker.slave_list[i].mutex);
@@ -4681,7 +4682,7 @@ static void rem_slave_xrcdns(struct mlx4_dev *dev, int slave)
4681void mlx4_delete_all_resources_for_slave(struct mlx4_dev *dev, int slave) 4682void mlx4_delete_all_resources_for_slave(struct mlx4_dev *dev, int slave)
4682{ 4683{
4683 struct mlx4_priv *priv = mlx4_priv(dev); 4684 struct mlx4_priv *priv = mlx4_priv(dev);
4684 4685 mlx4_reset_roce_gids(dev, slave);
4685 mutex_lock(&priv->mfunc.master.res_tracker.slave_list[slave].mutex); 4686 mutex_lock(&priv->mfunc.master.res_tracker.slave_list[slave].mutex);
4686 rem_slave_vlans(dev, slave); 4687 rem_slave_vlans(dev, slave);
4687 rem_slave_macs(dev, slave); 4688 rem_slave_macs(dev, slave);