diff options
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/main.c | 117 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/mlx4.h | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/port.c | 25 | ||||
-rw-r--r-- | include/linux/mlx4/device.h | 1 |
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 | ||
650 | enum 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 | |||
658 | static 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 | |||
670 | static 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 | |||
682 | static 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 | |||
698 | static 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); | ||
737 | err_set_port: | ||
738 | mutex_unlock(&priv->port_mutex); | ||
739 | mlx4_start_sense(mdev); | ||
740 | return err ? err : count; | ||
741 | } | ||
742 | |||
650 | static int mlx4_load_fw(struct mlx4_dev *dev) | 743 | static 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 | ||
1538 | static int mlx4_init_steering(struct mlx4_dev *dev) | 1653 | static 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 */ | ||
770 | enum { | ||
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 | |||
769 | int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port) | 777 | int 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 | ||
320 | struct mlx4_buf_list { | 321 | struct mlx4_buf_list { |