aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOr Gerlitz <ogerlitz@mellanox.com>2012-01-11 12:02:17 -0500
committerRoland Dreier <roland@purestorage.com>2012-03-12 19:24:59 -0400
commit096335b3f9830b90d13aee77252cf6f5f12a258c (patch)
tree08d90d43ff9b4db64bc977210b67f2b05a3d15d9
parenta9c766bb75ee2caad2735e41784387784ffd87db (diff)
mlx4_core: Allow dynamic MTU configuration for IB ports
Set the MTU for IB ports in the driver instead of using the firmware default of 2KB (the driver defaults to 4KB). Allow for dynamic mtu configuration through a new, per-port sysfs entry. Since there's a dependency between the port MTU and the max number of HW VLs the port can support, apply a mim/max approach, using a loop that goes down from the highest possible number of VLs to the lowest, using the firmware return status to know whether the requested number of VLs is possible with a given MTU. For now, as with the dynamic link type change / VPI support, the sysfs entry to change the mtu is exposed only when NOT running in SR-IOV mode. To allow changing the MTU for the master in SR-IOV mode, primary-function-initiated FLR (Function Level Reset) needs to be implemented. Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com> Signed-off-by: Roland Dreier <roland@purestorage.com>
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/main.c117
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/mlx4.h2
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/port.c25
-rw-r--r--include/linux/mlx4/device.h1
4 files changed, 141 insertions, 4 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c
index f0578961190c..e92cfae82e5a 100644
--- a/drivers/net/ethernet/mellanox/mlx4/main.c
+++ b/drivers/net/ethernet/mellanox/mlx4/main.c
@@ -647,6 +647,99 @@ out:
647 return err ? err : count; 647 return err ? err : count;
648} 648}
649 649
650enum ibta_mtu {
651 IB_MTU_256 = 1,
652 IB_MTU_512 = 2,
653 IB_MTU_1024 = 3,
654 IB_MTU_2048 = 4,
655 IB_MTU_4096 = 5
656};
657
658static inline int int_to_ibta_mtu(int mtu)
659{
660 switch (mtu) {
661 case 256: return IB_MTU_256;
662 case 512: return IB_MTU_512;
663 case 1024: return IB_MTU_1024;
664 case 2048: return IB_MTU_2048;
665 case 4096: return IB_MTU_4096;
666 default: return -1;
667 }
668}
669
670static inline int ibta_mtu_to_int(enum ibta_mtu mtu)
671{
672 switch (mtu) {
673 case IB_MTU_256: return 256;
674 case IB_MTU_512: return 512;
675 case IB_MTU_1024: return 1024;
676 case IB_MTU_2048: return 2048;
677 case IB_MTU_4096: return 4096;
678 default: return -1;
679 }
680}
681
682static ssize_t show_port_ib_mtu(struct device *dev,
683 struct device_attribute *attr,
684 char *buf)
685{
686 struct mlx4_port_info *info = container_of(attr, struct mlx4_port_info,
687 port_mtu_attr);
688 struct mlx4_dev *mdev = info->dev;
689
690 if (mdev->caps.port_type[info->port] == MLX4_PORT_TYPE_ETH)
691 mlx4_warn(mdev, "port level mtu is only used for IB ports\n");
692
693 sprintf(buf, "%d\n",
694 ibta_mtu_to_int(mdev->caps.port_ib_mtu[info->port]));
695 return strlen(buf);
696}
697
698static ssize_t set_port_ib_mtu(struct device *dev,
699 struct device_attribute *attr,
700 const char *buf, size_t count)
701{
702 struct mlx4_port_info *info = container_of(attr, struct mlx4_port_info,
703 port_mtu_attr);
704 struct mlx4_dev *mdev = info->dev;
705 struct mlx4_priv *priv = mlx4_priv(mdev);
706 int err, port, mtu, ibta_mtu = -1;
707
708 if (mdev->caps.port_type[info->port] == MLX4_PORT_TYPE_ETH) {
709 mlx4_warn(mdev, "port level mtu is only used for IB ports\n");
710 return -EINVAL;
711 }
712
713 err = sscanf(buf, "%d", &mtu);
714 if (err > 0)
715 ibta_mtu = int_to_ibta_mtu(mtu);
716
717 if (err <= 0 || ibta_mtu < 0) {
718 mlx4_err(mdev, "%s is invalid IBTA mtu\n", buf);
719 return -EINVAL;
720 }
721
722 mdev->caps.port_ib_mtu[info->port] = ibta_mtu;
723
724 mlx4_stop_sense(mdev);
725 mutex_lock(&priv->port_mutex);
726 mlx4_unregister_device(mdev);
727 for (port = 1; port <= mdev->caps.num_ports; port++) {
728 mlx4_CLOSE_PORT(mdev, port);
729 err = mlx4_SET_PORT(mdev, port);
730 if (err) {
731 mlx4_err(mdev, "Failed to set port %d, "
732 "aborting\n", port);
733 goto err_set_port;
734 }
735 }
736 err = mlx4_register_device(mdev);
737err_set_port:
738 mutex_unlock(&priv->port_mutex);
739 mlx4_start_sense(mdev);
740 return err ? err : count;
741}
742
650static int mlx4_load_fw(struct mlx4_dev *dev) 743static int mlx4_load_fw(struct mlx4_dev *dev)
651{ 744{
652 struct mlx4_priv *priv = mlx4_priv(dev); 745 struct mlx4_priv *priv = mlx4_priv(dev);
@@ -1362,7 +1455,10 @@ static int mlx4_setup_hca(struct mlx4_dev *dev)
1362 "ib capabilities (%d). Continuing " 1455 "ib capabilities (%d). Continuing "
1363 "with caps = 0\n", port, err); 1456 "with caps = 0\n", port, err);
1364 dev->caps.ib_port_def_cap[port] = ib_port_default_caps; 1457 dev->caps.ib_port_def_cap[port] = ib_port_default_caps;
1365 1458 if (mlx4_is_mfunc(dev))
1459 dev->caps.port_ib_mtu[port] = IB_MTU_2048;
1460 else
1461 dev->caps.port_ib_mtu[port] = IB_MTU_4096;
1366 err = mlx4_check_ext_port_caps(dev, port); 1462 err = mlx4_check_ext_port_caps(dev, port);
1367 if (err) 1463 if (err)
1368 mlx4_warn(dev, "failed to get port %d extended " 1464 mlx4_warn(dev, "failed to get port %d extended "
@@ -1524,6 +1620,24 @@ static int mlx4_init_port_info(struct mlx4_dev *dev, int port)
1524 info->port = -1; 1620 info->port = -1;
1525 } 1621 }
1526 1622
1623 sprintf(info->dev_mtu_name, "mlx4_port%d_mtu", port);
1624 info->port_mtu_attr.attr.name = info->dev_mtu_name;
1625 if (mlx4_is_mfunc(dev))
1626 info->port_mtu_attr.attr.mode = S_IRUGO;
1627 else {
1628 info->port_mtu_attr.attr.mode = S_IRUGO | S_IWUSR;
1629 info->port_mtu_attr.store = set_port_ib_mtu;
1630 }
1631 info->port_mtu_attr.show = show_port_ib_mtu;
1632 sysfs_attr_init(&info->port_mtu_attr.attr);
1633
1634 err = device_create_file(&dev->pdev->dev, &info->port_mtu_attr);
1635 if (err) {
1636 mlx4_err(dev, "Failed to create mtu file for port %d\n", port);
1637 device_remove_file(&info->dev->pdev->dev, &info->port_attr);
1638 info->port = -1;
1639 }
1640
1527 return err; 1641 return err;
1528} 1642}
1529 1643
@@ -1533,6 +1647,7 @@ static void mlx4_cleanup_port_info(struct mlx4_port_info *info)
1533 return; 1647 return;
1534 1648
1535 device_remove_file(&info->dev->pdev->dev, &info->port_attr); 1649 device_remove_file(&info->dev->pdev->dev, &info->port_attr);
1650 device_remove_file(&info->dev->pdev->dev, &info->port_mtu_attr);
1536} 1651}
1537 1652
1538static int mlx4_init_steering(struct mlx4_dev *dev) 1653static int mlx4_init_steering(struct mlx4_dev *dev)
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h
index ac2d6061268d..1aa362181a09 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h
+++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h
@@ -686,6 +686,8 @@ struct mlx4_port_info {
686 char dev_name[16]; 686 char dev_name[16];
687 struct device_attribute port_attr; 687 struct device_attribute port_attr;
688 enum mlx4_port_type tmp_type; 688 enum mlx4_port_type tmp_type;
689 char dev_mtu_name[16];
690 struct device_attribute port_mtu_attr;
689 struct mlx4_mac_table mac_table; 691 struct mlx4_mac_table mac_table;
690 struct radix_tree_root mac_tree; 692 struct radix_tree_root mac_tree;
691 struct mlx4_vlan_table vlan_table; 693 struct mlx4_vlan_table vlan_table;
diff --git a/drivers/net/ethernet/mellanox/mlx4/port.c b/drivers/net/ethernet/mellanox/mlx4/port.c
index f44ae555bf43..a6fd56451d7e 100644
--- a/drivers/net/ethernet/mellanox/mlx4/port.c
+++ b/drivers/net/ethernet/mellanox/mlx4/port.c
@@ -766,10 +766,18 @@ int mlx4_SET_PORT_wrapper(struct mlx4_dev *dev, int slave,
766 vhcr->op_modifier, inbox); 766 vhcr->op_modifier, inbox);
767} 767}
768 768
769/* bit locations for set port command with zero op modifier */
770enum {
771 MLX4_SET_PORT_VL_CAP = 4, /* bits 7:4 */
772 MLX4_SET_PORT_MTU_CAP = 12, /* bits 15:12 */
773 MLX4_CHANGE_PORT_VL_CAP = 21,
774 MLX4_CHANGE_PORT_MTU_CAP = 22,
775};
776
769int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port) 777int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port)
770{ 778{
771 struct mlx4_cmd_mailbox *mailbox; 779 struct mlx4_cmd_mailbox *mailbox;
772 int err; 780 int err, vl_cap;
773 781
774 if (dev->caps.port_type[port] == MLX4_PORT_TYPE_ETH) 782 if (dev->caps.port_type[port] == MLX4_PORT_TYPE_ETH)
775 return 0; 783 return 0;
@@ -781,8 +789,19 @@ int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port)
781 memset(mailbox->buf, 0, 256); 789 memset(mailbox->buf, 0, 256);
782 790
783 ((__be32 *) mailbox->buf)[1] = dev->caps.ib_port_def_cap[port]; 791 ((__be32 *) mailbox->buf)[1] = dev->caps.ib_port_def_cap[port];
784 err = mlx4_cmd(dev, mailbox->dma, port, 0, MLX4_CMD_SET_PORT, 792
785 MLX4_CMD_TIME_CLASS_B, MLX4_CMD_WRAPPED); 793 /* IB VL CAP enum isn't used by the firmware, just numerical values */
794 for (vl_cap = 8; vl_cap >= 1; vl_cap >>= 1) {
795 ((__be32 *) mailbox->buf)[0] = cpu_to_be32(
796 (1 << MLX4_CHANGE_PORT_MTU_CAP) |
797 (1 << MLX4_CHANGE_PORT_VL_CAP) |
798 (dev->caps.port_ib_mtu[port] << MLX4_SET_PORT_MTU_CAP) |
799 (vl_cap << MLX4_SET_PORT_VL_CAP));
800 err = mlx4_cmd(dev, mailbox->dma, port, 0, MLX4_CMD_SET_PORT,
801 MLX4_CMD_TIME_CLASS_B, MLX4_CMD_WRAPPED);
802 if (err != -ENOMEM)
803 break;
804 }
786 805
787 mlx4_free_cmd_mailbox(dev, mailbox); 806 mlx4_free_cmd_mailbox(dev, mailbox);
788 return err; 807 return err;
diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h
index 4b3fbf122533..b19fb9b901a2 100644
--- a/include/linux/mlx4/device.h
+++ b/include/linux/mlx4/device.h
@@ -315,6 +315,7 @@ struct mlx4_caps {
315 enum mlx4_port_type possible_type[MLX4_MAX_PORTS + 1]; 315 enum mlx4_port_type possible_type[MLX4_MAX_PORTS + 1];
316 u32 max_counters; 316 u32 max_counters;
317 u8 ext_port_cap[MLX4_MAX_PORTS + 1]; 317 u8 ext_port_cap[MLX4_MAX_PORTS + 1];
318 u8 port_ib_mtu[MLX4_MAX_PORTS + 1];
318}; 319};
319 320
320struct mlx4_buf_list { 321struct mlx4_buf_list {