Deleted Added
full compact
mlx5_main.c (331574) mlx5_main.c (331580)
1/*-
2 * Copyright (c) 2013-2017, Mellanox Technologies, Ltd. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.

--- 8 unchanged lines hidden (view full) ---

17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 *
1/*-
2 * Copyright (c) 2013-2017, Mellanox Technologies, Ltd. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.

--- 8 unchanged lines hidden (view full) ---

17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 *
25 * $FreeBSD: stable/11/sys/dev/mlx5/mlx5_core/mlx5_main.c 331574 2018-03-26 20:09:36Z hselasky $
25 * $FreeBSD: stable/11/sys/dev/mlx5/mlx5_core/mlx5_main.c 331580 2018-03-26 20:33:31Z hselasky $
26 */
27
28#define LINUXKPI_PARAM_PREFIX mlx5_
29
30#include <linux/kmod.h>
31#include <linux/module.h>
32#include <linux/errno.h>
33#include <linux/pci.h>

--- 24 unchanged lines hidden (view full) ---

58
59#define MLX5_DEFAULT_PROF 2
60static int prof_sel = MLX5_DEFAULT_PROF;
61module_param_named(prof_sel, prof_sel, int, 0444);
62MODULE_PARM_DESC(prof_sel, "profile selector. Valid range 0 - 2");
63
64#define NUMA_NO_NODE -1
65
26 */
27
28#define LINUXKPI_PARAM_PREFIX mlx5_
29
30#include <linux/kmod.h>
31#include <linux/module.h>
32#include <linux/errno.h>
33#include <linux/pci.h>

--- 24 unchanged lines hidden (view full) ---

58
59#define MLX5_DEFAULT_PROF 2
60static int prof_sel = MLX5_DEFAULT_PROF;
61module_param_named(prof_sel, prof_sel, int, 0444);
62MODULE_PARM_DESC(prof_sel, "profile selector. Valid range 0 - 2");
63
64#define NUMA_NO_NODE -1
65
66struct workqueue_struct *mlx5_core_wq;
67static LIST_HEAD(intf_list);
68static LIST_HEAD(dev_list);
69static DEFINE_MUTEX(intf_mutex);
70
71struct mlx5_device_context {
72 struct list_head list;
73 struct mlx5_interface *intf;
74 void *context;

--- 106 unchanged lines hidden (view full) ---

181 return err;
182 }
183 }
184
185 dma_set_max_seg_size(&pdev->dev, 2u * 1024 * 1024 * 1024);
186 return err;
187}
188
66static LIST_HEAD(intf_list);
67static LIST_HEAD(dev_list);
68static DEFINE_MUTEX(intf_mutex);
69
70struct mlx5_device_context {
71 struct list_head list;
72 struct mlx5_interface *intf;
73 void *context;

--- 106 unchanged lines hidden (view full) ---

180 return err;
181 }
182 }
183
184 dma_set_max_seg_size(&pdev->dev, 2u * 1024 * 1024 * 1024);
185 return err;
186}
187
188static int mlx5_pci_enable_device(struct mlx5_core_dev *dev)
189{
190 struct pci_dev *pdev = dev->pdev;
191 int err = 0;
192
193 mutex_lock(&dev->pci_status_mutex);
194 if (dev->pci_status == MLX5_PCI_STATUS_DISABLED) {
195 err = pci_enable_device(pdev);
196 if (!err)
197 dev->pci_status = MLX5_PCI_STATUS_ENABLED;
198 }
199 mutex_unlock(&dev->pci_status_mutex);
200
201 return err;
202}
203
204static void mlx5_pci_disable_device(struct mlx5_core_dev *dev)
205{
206 struct pci_dev *pdev = dev->pdev;
207
208 mutex_lock(&dev->pci_status_mutex);
209 if (dev->pci_status == MLX5_PCI_STATUS_ENABLED) {
210 pci_disable_device(pdev);
211 dev->pci_status = MLX5_PCI_STATUS_DISABLED;
212 }
213 mutex_unlock(&dev->pci_status_mutex);
214}
215
189static int request_bar(struct pci_dev *pdev)
190{
191 int err = 0;
192
193 if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
194 device_printf((&pdev->dev)->bsddev, "ERR: ""Missing registers BAR, aborting\n");
195 return -ENODEV;
196 }

--- 478 unchanged lines hidden (view full) ---

675 break;
676 }
677 msleep(FW_INIT_WAIT_MS);
678 }
679
680 return err;
681}
682
216static int request_bar(struct pci_dev *pdev)
217{
218 int err = 0;
219
220 if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
221 device_printf((&pdev->dev)->bsddev, "ERR: ""Missing registers BAR, aborting\n");
222 return -ENODEV;
223 }

--- 478 unchanged lines hidden (view full) ---

702 break;
703 }
704 msleep(FW_INIT_WAIT_MS);
705 }
706
707 return err;
708}
709
683static int mlx5_dev_init(struct mlx5_core_dev *dev, struct pci_dev *pdev)
710static void mlx5_add_device(struct mlx5_interface *intf, struct mlx5_priv *priv)
684{
711{
712 struct mlx5_device_context *dev_ctx;
713 struct mlx5_core_dev *dev = container_of(priv, struct mlx5_core_dev, priv);
714
715 dev_ctx = kzalloc(sizeof(*dev_ctx), GFP_KERNEL);
716 if (!dev_ctx)
717 return;
718
719 dev_ctx->intf = intf;
720 CURVNET_SET_QUIET(vnet0);
721 dev_ctx->context = intf->add(dev);
722 CURVNET_RESTORE();
723
724 if (dev_ctx->context) {
725 spin_lock_irq(&priv->ctx_lock);
726 list_add_tail(&dev_ctx->list, &priv->ctx_list);
727 spin_unlock_irq(&priv->ctx_lock);
728 } else {
729 kfree(dev_ctx);
730 }
731}
732
733static void mlx5_remove_device(struct mlx5_interface *intf, struct mlx5_priv *priv)
734{
735 struct mlx5_device_context *dev_ctx;
736 struct mlx5_core_dev *dev = container_of(priv, struct mlx5_core_dev, priv);
737
738 list_for_each_entry(dev_ctx, &priv->ctx_list, list)
739 if (dev_ctx->intf == intf) {
740 spin_lock_irq(&priv->ctx_lock);
741 list_del(&dev_ctx->list);
742 spin_unlock_irq(&priv->ctx_lock);
743
744 intf->remove(dev, dev_ctx->context);
745 kfree(dev_ctx);
746 return;
747 }
748}
749
750static int mlx5_register_device(struct mlx5_core_dev *dev)
751{
685 struct mlx5_priv *priv = &dev->priv;
752 struct mlx5_priv *priv = &dev->priv;
686 int err;
753 struct mlx5_interface *intf;
687
754
688 dev->pdev = pdev;
755 mutex_lock(&intf_mutex);
756 list_add_tail(&priv->dev_list, &dev_list);
757 list_for_each_entry(intf, &intf_list, list)
758 mlx5_add_device(intf, priv);
759 mutex_unlock(&intf_mutex);
760
761 return 0;
762}
763
764static void mlx5_unregister_device(struct mlx5_core_dev *dev)
765{
766 struct mlx5_priv *priv = &dev->priv;
767 struct mlx5_interface *intf;
768
769 mutex_lock(&intf_mutex);
770 list_for_each_entry(intf, &intf_list, list)
771 mlx5_remove_device(intf, priv);
772 list_del(&priv->dev_list);
773 mutex_unlock(&intf_mutex);
774}
775
776int mlx5_register_interface(struct mlx5_interface *intf)
777{
778 struct mlx5_priv *priv;
779
780 if (!intf->add || !intf->remove)
781 return -EINVAL;
782
783 mutex_lock(&intf_mutex);
784 list_add_tail(&intf->list, &intf_list);
785 list_for_each_entry(priv, &dev_list, dev_list)
786 mlx5_add_device(intf, priv);
787 mutex_unlock(&intf_mutex);
788
789 return 0;
790}
791EXPORT_SYMBOL(mlx5_register_interface);
792
793void mlx5_unregister_interface(struct mlx5_interface *intf)
794{
795 struct mlx5_priv *priv;
796
797 mutex_lock(&intf_mutex);
798 list_for_each_entry(priv, &dev_list, dev_list)
799 mlx5_remove_device(intf, priv);
800 list_del(&intf->list);
801 mutex_unlock(&intf_mutex);
802}
803EXPORT_SYMBOL(mlx5_unregister_interface);
804
805void *mlx5_get_protocol_dev(struct mlx5_core_dev *mdev, int protocol)
806{
807 struct mlx5_priv *priv = &mdev->priv;
808 struct mlx5_device_context *dev_ctx;
809 unsigned long flags;
810 void *result = NULL;
811
812 spin_lock_irqsave(&priv->ctx_lock, flags);
813
814 list_for_each_entry(dev_ctx, &mdev->priv.ctx_list, list)
815 if ((dev_ctx->intf->protocol == protocol) &&
816 dev_ctx->intf->get_dev) {
817 result = dev_ctx->intf->get_dev(dev_ctx->context);
818 break;
819 }
820
821 spin_unlock_irqrestore(&priv->ctx_lock, flags);
822
823 return result;
824}
825EXPORT_SYMBOL(mlx5_get_protocol_dev);
826
827static int mlx5_pci_init(struct mlx5_core_dev *dev, struct mlx5_priv *priv)
828{
829 struct pci_dev *pdev = dev->pdev;
830 int err = 0;
831
689 pci_set_drvdata(dev->pdev, dev);
690 strncpy(priv->name, dev_name(&pdev->dev), MLX5_MAX_NAME_LEN);
691 priv->name[MLX5_MAX_NAME_LEN - 1] = 0;
692
693 mutex_init(&priv->pgdir_mutex);
694 INIT_LIST_HEAD(&priv->pgdir_list);
695 spin_lock_init(&priv->mkey_lock);
696
697 priv->numa_node = NUMA_NO_NODE;
698
832 pci_set_drvdata(dev->pdev, dev);
833 strncpy(priv->name, dev_name(&pdev->dev), MLX5_MAX_NAME_LEN);
834 priv->name[MLX5_MAX_NAME_LEN - 1] = 0;
835
836 mutex_init(&priv->pgdir_mutex);
837 INIT_LIST_HEAD(&priv->pgdir_list);
838 spin_lock_init(&priv->mkey_lock);
839
840 priv->numa_node = NUMA_NO_NODE;
841
699 err = pci_enable_device(pdev);
842 err = mlx5_pci_enable_device(dev);
700 if (err) {
701 device_printf((&pdev->dev)->bsddev, "ERR: ""Cannot enable PCI device, aborting\n");
702 goto err_dbg;
703 }
704
705 err = request_bar(pdev);
706 if (err) {
707 device_printf((&pdev->dev)->bsddev, "ERR: ""error requesting BARs, aborting\n");

--- 10 unchanged lines hidden (view full) ---

718
719 dev->iseg_base = pci_resource_start(dev->pdev, 0);
720 dev->iseg = ioremap(dev->iseg_base, sizeof(*dev->iseg));
721 if (!dev->iseg) {
722 err = -ENOMEM;
723 device_printf((&pdev->dev)->bsddev, "ERR: ""Failed mapping initialization segment, aborting\n");
724 goto err_clr_master;
725 }
843 if (err) {
844 device_printf((&pdev->dev)->bsddev, "ERR: ""Cannot enable PCI device, aborting\n");
845 goto err_dbg;
846 }
847
848 err = request_bar(pdev);
849 if (err) {
850 device_printf((&pdev->dev)->bsddev, "ERR: ""error requesting BARs, aborting\n");

--- 10 unchanged lines hidden (view full) ---

861
862 dev->iseg_base = pci_resource_start(dev->pdev, 0);
863 dev->iseg = ioremap(dev->iseg_base, sizeof(*dev->iseg));
864 if (!dev->iseg) {
865 err = -ENOMEM;
866 device_printf((&pdev->dev)->bsddev, "ERR: ""Failed mapping initialization segment, aborting\n");
867 goto err_clr_master;
868 }
869
870 return 0;
871
872err_clr_master:
873 pci_clear_master(dev->pdev);
874 release_bar(dev->pdev);
875err_disable:
876 mlx5_pci_disable_device(dev);
877err_dbg:
878 return err;
879}
880
881static void mlx5_pci_close(struct mlx5_core_dev *dev, struct mlx5_priv *priv)
882{
883 iounmap(dev->iseg);
884 pci_clear_master(dev->pdev);
885 release_bar(dev->pdev);
886 mlx5_pci_disable_device(dev);
887}
888
889static int mlx5_load_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv)
890{
891 struct pci_dev *pdev = dev->pdev;
892 int err;
893
894 mutex_lock(&dev->intf_state_mutex);
895 if (test_bit(MLX5_INTERFACE_STATE_UP, &dev->intf_state)) {
896 dev_warn(&dev->pdev->dev, "%s: interface is up, NOP\n",
897 __func__);
898 goto out;
899 }
900
726 device_printf((&pdev->dev)->bsddev, "INFO: ""firmware version: %d.%d.%d\n", fw_rev_maj(dev), fw_rev_min(dev), fw_rev_sub(dev));
727
728 /*
729 * On load removing any previous indication of internal error,
730 * device is up
731 */
732 dev->state = MLX5_DEVICE_STATE_UP;
733
734 err = mlx5_cmd_init(dev);
735 if (err) {
736 device_printf((&pdev->dev)->bsddev, "ERR: ""Failed initializing command interface, aborting\n");
901 device_printf((&pdev->dev)->bsddev, "INFO: ""firmware version: %d.%d.%d\n", fw_rev_maj(dev), fw_rev_min(dev), fw_rev_sub(dev));
902
903 /*
904 * On load removing any previous indication of internal error,
905 * device is up
906 */
907 dev->state = MLX5_DEVICE_STATE_UP;
908
909 err = mlx5_cmd_init(dev);
910 if (err) {
911 device_printf((&pdev->dev)->bsddev, "ERR: ""Failed initializing command interface, aborting\n");
737 goto err_unmap;
912 goto out_err;
738 }
739
740 err = wait_fw_init(dev, FW_INIT_TIMEOUT_MILI);
741 if (err) {
742 device_printf((&dev->pdev->dev)->bsddev, "ERR: ""Firmware over %d MS in initializing state, aborting\n", FW_INIT_TIMEOUT_MILI);
743 goto err_cmd_cleanup;
744 }
745

--- 108 unchanged lines hidden (view full) ---

854 mlx5_init_mr_table(dev);
855
856 err = mlx5_init_fs(dev);
857 if (err) {
858 mlx5_core_err(dev, "flow steering init %d\n", err);
859 goto err_init_tables;
860 }
861
913 }
914
915 err = wait_fw_init(dev, FW_INIT_TIMEOUT_MILI);
916 if (err) {
917 device_printf((&dev->pdev->dev)->bsddev, "ERR: ""Firmware over %d MS in initializing state, aborting\n", FW_INIT_TIMEOUT_MILI);
918 goto err_cmd_cleanup;
919 }
920

--- 108 unchanged lines hidden (view full) ---

1029 mlx5_init_mr_table(dev);
1030
1031 err = mlx5_init_fs(dev);
1032 if (err) {
1033 mlx5_core_err(dev, "flow steering init %d\n", err);
1034 goto err_init_tables;
1035 }
1036
1037 err = mlx5_register_device(dev);
1038 if (err) {
1039 dev_err(&pdev->dev, "mlx5_register_device failed %d\n", err);
1040 goto err_reg_dev;
1041 }
1042
1043 clear_bit(MLX5_INTERFACE_STATE_DOWN, &dev->intf_state);
1044 set_bit(MLX5_INTERFACE_STATE_UP, &dev->intf_state);
1045
1046out:
1047 mutex_unlock(&dev->intf_state_mutex);
862 return 0;
863
1048 return 0;
1049
1050err_reg_dev:
1051 mlx5_cleanup_fs(dev);
864err_init_tables:
865 mlx5_cleanup_mr_table(dev);
866 mlx5_cleanup_srq_table(dev);
867 mlx5_cleanup_qp_table(dev);
868 mlx5_cleanup_cq_table(dev);
869 unmap_bf_area(dev);
870
871err_stop_eqs:

--- 7 unchanged lines hidden (view full) ---

879
880disable_msix:
881 mlx5_disable_msix(dev);
882
883err_stop_poll:
884 mlx5_stop_health_poll(dev);
885 if (mlx5_cmd_teardown_hca(dev)) {
886 device_printf((&dev->pdev->dev)->bsddev, "ERR: ""tear_down_hca failed, skip cleanup\n");
1052err_init_tables:
1053 mlx5_cleanup_mr_table(dev);
1054 mlx5_cleanup_srq_table(dev);
1055 mlx5_cleanup_qp_table(dev);
1056 mlx5_cleanup_cq_table(dev);
1057 unmap_bf_area(dev);
1058
1059err_stop_eqs:

--- 7 unchanged lines hidden (view full) ---

1067
1068disable_msix:
1069 mlx5_disable_msix(dev);
1070
1071err_stop_poll:
1072 mlx5_stop_health_poll(dev);
1073 if (mlx5_cmd_teardown_hca(dev)) {
1074 device_printf((&dev->pdev->dev)->bsddev, "ERR: ""tear_down_hca failed, skip cleanup\n");
887 return err;
1075 goto out_err;
888 }
889
890reclaim_boot_pages:
891 mlx5_reclaim_startup_pages(dev);
892
893err_pagealloc_stop:
894 mlx5_pagealloc_stop(dev);
895
896err_disable_hca:
897 mlx5_core_disable_hca(dev);
898
899err_pagealloc_cleanup:
900 mlx5_pagealloc_cleanup(dev);
1076 }
1077
1078reclaim_boot_pages:
1079 mlx5_reclaim_startup_pages(dev);
1080
1081err_pagealloc_stop:
1082 mlx5_pagealloc_stop(dev);
1083
1084err_disable_hca:
1085 mlx5_core_disable_hca(dev);
1086
1087err_pagealloc_cleanup:
1088 mlx5_pagealloc_cleanup(dev);
1089
901err_cmd_cleanup:
902 mlx5_cmd_cleanup(dev);
903
1090err_cmd_cleanup:
1091 mlx5_cmd_cleanup(dev);
1092
904err_unmap:
905 iounmap(dev->iseg);
906
907err_clr_master:
908 pci_clear_master(dev->pdev);
909 release_bar(dev->pdev);
910
911err_disable:
912 pci_disable_device(dev->pdev);
913
914err_dbg:
1093out_err:
915 dev->state = MLX5_DEVICE_STATE_INTERNAL_ERROR;
1094 dev->state = MLX5_DEVICE_STATE_INTERNAL_ERROR;
1095 mutex_unlock(&dev->intf_state_mutex);
1096
916 return err;
917}
918
1097 return err;
1098}
1099
919static void mlx5_dev_cleanup(struct mlx5_core_dev *dev)
1100static int mlx5_unload_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv)
920{
1101{
921 struct mlx5_priv *priv = &dev->priv;
1102 int err = 0;
922
1103
1104 mutex_lock(&dev->intf_state_mutex);
1105 if (test_bit(MLX5_INTERFACE_STATE_DOWN, &dev->intf_state)) {
1106 dev_warn(&dev->pdev->dev, "%s: interface is down, NOP\n", __func__);
1107 goto out;
1108 }
1109
1110 mlx5_unregister_device(dev);
1111
923 mlx5_cleanup_fs(dev);
924 mlx5_cleanup_mr_table(dev);
925 mlx5_cleanup_srq_table(dev);
926 mlx5_cleanup_qp_table(dev);
927 mlx5_cleanup_cq_table(dev);
928 unmap_bf_area(dev);
929 mlx5_wait_for_reclaim_vfs_pages(dev);
930 free_comp_eqs(dev);
931 mlx5_stop_eqs(dev);
932 mlx5_free_uuars(dev, &priv->uuari);
933 mlx5_eq_cleanup(dev);
934 mlx5_disable_msix(dev);
935 mlx5_stop_health_poll(dev);
1112 mlx5_cleanup_fs(dev);
1113 mlx5_cleanup_mr_table(dev);
1114 mlx5_cleanup_srq_table(dev);
1115 mlx5_cleanup_qp_table(dev);
1116 mlx5_cleanup_cq_table(dev);
1117 unmap_bf_area(dev);
1118 mlx5_wait_for_reclaim_vfs_pages(dev);
1119 free_comp_eqs(dev);
1120 mlx5_stop_eqs(dev);
1121 mlx5_free_uuars(dev, &priv->uuari);
1122 mlx5_eq_cleanup(dev);
1123 mlx5_disable_msix(dev);
1124 mlx5_stop_health_poll(dev);
936 if (mlx5_cmd_teardown_hca(dev)) {
1125 err = mlx5_cmd_teardown_hca(dev);
1126 if (err) {
937 device_printf((&dev->pdev->dev)->bsddev, "ERR: ""tear_down_hca failed, skip cleanup\n");
1127 device_printf((&dev->pdev->dev)->bsddev, "ERR: ""tear_down_hca failed, skip cleanup\n");
938 return;
1128 goto out;
939 }
940 mlx5_pagealloc_stop(dev);
941 mlx5_reclaim_startup_pages(dev);
942 mlx5_core_disable_hca(dev);
943 mlx5_pagealloc_cleanup(dev);
944 mlx5_cmd_cleanup(dev);
1129 }
1130 mlx5_pagealloc_stop(dev);
1131 mlx5_reclaim_startup_pages(dev);
1132 mlx5_core_disable_hca(dev);
1133 mlx5_pagealloc_cleanup(dev);
1134 mlx5_cmd_cleanup(dev);
945 iounmap(dev->iseg);
946 pci_clear_master(dev->pdev);
947 release_bar(dev->pdev);
948 pci_disable_device(dev->pdev);
949}
950
1135
951static void mlx5_add_device(struct mlx5_interface *intf, struct mlx5_priv *priv)
952{
953 struct mlx5_device_context *dev_ctx;
954 struct mlx5_core_dev *dev = container_of(priv, struct mlx5_core_dev, priv);
955
956 dev_ctx = kmalloc(sizeof(*dev_ctx), GFP_KERNEL);
957
958 dev_ctx->intf = intf;
959 CURVNET_SET_QUIET(vnet0);
960 dev_ctx->context = intf->add(dev);
961 CURVNET_RESTORE();
962
963 if (dev_ctx->context) {
964 spin_lock_irq(&priv->ctx_lock);
965 list_add_tail(&dev_ctx->list, &priv->ctx_list);
966 spin_unlock_irq(&priv->ctx_lock);
967 } else {
968 kfree(dev_ctx);
969 }
1136out:
1137 clear_bit(MLX5_INTERFACE_STATE_UP, &dev->intf_state);
1138 set_bit(MLX5_INTERFACE_STATE_DOWN, &dev->intf_state);
1139 mutex_unlock(&dev->intf_state_mutex);
1140 return err;
970}
971
1141}
1142
972static void mlx5_remove_device(struct mlx5_interface *intf, struct mlx5_priv *priv)
1143void mlx5_core_event(struct mlx5_core_dev *dev, enum mlx5_dev_event event,
1144 unsigned long param)
973{
1145{
974 struct mlx5_device_context *dev_ctx;
975 struct mlx5_core_dev *dev = container_of(priv, struct mlx5_core_dev, priv);
976
977 list_for_each_entry(dev_ctx, &priv->ctx_list, list)
978 if (dev_ctx->intf == intf) {
979 spin_lock_irq(&priv->ctx_lock);
980 list_del(&dev_ctx->list);
981 spin_unlock_irq(&priv->ctx_lock);
982
983 intf->remove(dev, dev_ctx->context);
984 kfree(dev_ctx);
985 return;
986 }
987}
988static int mlx5_register_device(struct mlx5_core_dev *dev)
989{
990 struct mlx5_priv *priv = &dev->priv;
1146 struct mlx5_priv *priv = &dev->priv;
991 struct mlx5_interface *intf;
992
993 mutex_lock(&intf_mutex);
994 list_add_tail(&priv->dev_list, &dev_list);
995 list_for_each_entry(intf, &intf_list, list)
996 mlx5_add_device(intf, priv);
997 mutex_unlock(&intf_mutex);
998
999 return 0;
1000}
1001static void mlx5_unregister_device(struct mlx5_core_dev *dev)
1002{
1003 struct mlx5_priv *priv = &dev->priv;
1004 struct mlx5_interface *intf;
1005
1006 mutex_lock(&intf_mutex);
1007 list_for_each_entry(intf, &intf_list, list)
1008 mlx5_remove_device(intf, priv);
1009 list_del(&priv->dev_list);
1010 mutex_unlock(&intf_mutex);
1011}
1012
1013int mlx5_register_interface(struct mlx5_interface *intf)
1014{
1015 struct mlx5_priv *priv;
1016
1017 if (!intf->add || !intf->remove)
1018 return -EINVAL;
1019
1020 mutex_lock(&intf_mutex);
1021 list_add_tail(&intf->list, &intf_list);
1022 list_for_each_entry(priv, &dev_list, dev_list)
1023 mlx5_add_device(intf, priv);
1024 mutex_unlock(&intf_mutex);
1025
1026 return 0;
1027}
1028EXPORT_SYMBOL(mlx5_register_interface);
1029
1030void mlx5_unregister_interface(struct mlx5_interface *intf)
1031{
1032 struct mlx5_priv *priv;
1033
1034 mutex_lock(&intf_mutex);
1035 list_for_each_entry(priv, &dev_list, dev_list)
1036 mlx5_remove_device(intf, priv);
1037 list_del(&intf->list);
1038 mutex_unlock(&intf_mutex);
1039}
1040EXPORT_SYMBOL(mlx5_unregister_interface);
1041
1042void *mlx5_get_protocol_dev(struct mlx5_core_dev *mdev, int protocol)
1043{
1044 struct mlx5_priv *priv = &mdev->priv;
1045 struct mlx5_device_context *dev_ctx;
1046 unsigned long flags;
1147 struct mlx5_device_context *dev_ctx;
1148 unsigned long flags;
1047 void *result = NULL;
1048
1049 spin_lock_irqsave(&priv->ctx_lock, flags);
1050
1149
1150 spin_lock_irqsave(&priv->ctx_lock, flags);
1151
1051 list_for_each_entry(dev_ctx, &mdev->priv.ctx_list, list)
1052 if ((dev_ctx->intf->protocol == protocol) &&
1053 dev_ctx->intf->get_dev) {
1054 result = dev_ctx->intf->get_dev(dev_ctx->context);
1055 break;
1056 }
1057
1058 spin_unlock_irqrestore(&priv->ctx_lock, flags);
1059
1060 return result;
1061}
1062EXPORT_SYMBOL(mlx5_get_protocol_dev);
1063
1064static void mlx5_core_event(struct mlx5_core_dev *dev, enum mlx5_dev_event event,
1065 unsigned long param)
1066{
1067 struct mlx5_priv *priv = &dev->priv;
1068 struct mlx5_device_context *dev_ctx;
1069 unsigned long flags;
1070
1071 spin_lock_irqsave(&priv->ctx_lock, flags);
1072
1073 list_for_each_entry(dev_ctx, &priv->ctx_list, list)
1074 if (dev_ctx->intf->event)
1075 dev_ctx->intf->event(dev, dev_ctx->context, event, param);
1076
1077 spin_unlock_irqrestore(&priv->ctx_lock, flags);
1078}
1079
1080struct mlx5_core_event_handler {

--- 15 unchanged lines hidden (view full) ---

1096 if (id)
1097 priv->pci_dev_data = id->driver_data;
1098
1099 if (prof_sel < 0 || prof_sel >= ARRAY_SIZE(profiles)) {
1100 printf("mlx5_core: WARN: ""selected profile out of range, selecting default (%d)\n", MLX5_DEFAULT_PROF);
1101 prof_sel = MLX5_DEFAULT_PROF;
1102 }
1103 dev->profile = &profiles[prof_sel];
1152 list_for_each_entry(dev_ctx, &priv->ctx_list, list)
1153 if (dev_ctx->intf->event)
1154 dev_ctx->intf->event(dev, dev_ctx->context, event, param);
1155
1156 spin_unlock_irqrestore(&priv->ctx_lock, flags);
1157}
1158
1159struct mlx5_core_event_handler {

--- 15 unchanged lines hidden (view full) ---

1175 if (id)
1176 priv->pci_dev_data = id->driver_data;
1177
1178 if (prof_sel < 0 || prof_sel >= ARRAY_SIZE(profiles)) {
1179 printf("mlx5_core: WARN: ""selected profile out of range, selecting default (%d)\n", MLX5_DEFAULT_PROF);
1180 prof_sel = MLX5_DEFAULT_PROF;
1181 }
1182 dev->profile = &profiles[prof_sel];
1183 dev->pdev = pdev;
1104 dev->event = mlx5_core_event;
1105
1106 INIT_LIST_HEAD(&priv->ctx_list);
1107 spin_lock_init(&priv->ctx_lock);
1184 dev->event = mlx5_core_event;
1185
1186 INIT_LIST_HEAD(&priv->ctx_list);
1187 spin_lock_init(&priv->ctx_lock);
1108 err = mlx5_dev_init(dev, pdev);
1188 mutex_init(&dev->pci_status_mutex);
1189 mutex_init(&dev->intf_state_mutex);
1190 err = mlx5_pci_init(dev, priv);
1109 if (err) {
1191 if (err) {
1110 device_printf((&pdev->dev)->bsddev, "ERR: ""mlx5_dev_init failed %d\n", err);
1111 goto out;
1192 device_printf((&pdev->dev)->bsddev, "ERR: ""mlx5_pci_init failed %d\n", err);
1193 goto clean_dev;
1112 }
1113
1194 }
1195
1114 err = mlx5_register_device(dev);
1196 err = mlx5_health_init(dev);
1197 if (err) {
1198 device_printf((&pdev->dev)->bsddev, "ERR: ""mlx5_health_init failed %d\n", err);
1199 goto close_pci;
1200 }
1201
1202 err = mlx5_load_one(dev, priv);
1115 if (err) {
1116 device_printf((&pdev->dev)->bsddev, "ERR: ""mlx5_register_device failed %d\n", err);
1203 if (err) {
1204 device_printf((&pdev->dev)->bsddev, "ERR: ""mlx5_register_device failed %d\n", err);
1117 goto out_init;
1205 goto clean_health;
1118 }
1119
1120
1121 return 0;
1122
1206 }
1207
1208
1209 return 0;
1210
1123out_init:
1124 mlx5_dev_cleanup(dev);
1125out:
1211clean_health:
1212 mlx5_health_cleanup(dev);
1213close_pci:
1214 mlx5_pci_close(dev, priv);
1215clean_dev:
1126 kfree(dev);
1127 return err;
1128}
1129
1130static void remove_one(struct pci_dev *pdev)
1131{
1132 struct mlx5_core_dev *dev = pci_get_drvdata(pdev);
1216 kfree(dev);
1217 return err;
1218}
1219
1220static void remove_one(struct pci_dev *pdev)
1221{
1222 struct mlx5_core_dev *dev = pci_get_drvdata(pdev);
1223 struct mlx5_priv *priv = &dev->priv;
1133
1224
1134 mlx5_unregister_device(dev);
1135 mlx5_dev_cleanup(dev);
1225 if (mlx5_unload_one(dev, priv)) {
1226 dev_err(&dev->pdev->dev, "mlx5_unload_one failed\n");
1227 mlx5_health_cleanup(dev);
1228 return;
1229 }
1230
1231 mlx5_health_cleanup(dev);
1232 mlx5_pci_close(dev, priv);
1233 pci_set_drvdata(pdev, NULL);
1136 kfree(dev);
1137}
1138
1234 kfree(dev);
1235}
1236
1237static pci_ers_result_t mlx5_pci_err_detected(struct pci_dev *pdev,
1238 pci_channel_state_t state)
1239{
1240 struct mlx5_core_dev *dev = pci_get_drvdata(pdev);
1241 struct mlx5_priv *priv = &dev->priv;
1242
1243 dev_info(&pdev->dev, "%s was called\n", __func__);
1244 mlx5_enter_error_state(dev);
1245 mlx5_unload_one(dev, priv);
1246 mlx5_pci_disable_device(dev);
1247 return state == pci_channel_io_perm_failure ?
1248 PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_NEED_RESET;
1249}
1250
1251static pci_ers_result_t mlx5_pci_slot_reset(struct pci_dev *pdev)
1252{
1253 struct mlx5_core_dev *dev = pci_get_drvdata(pdev);
1254 int err = 0;
1255
1256 dev_info(&pdev->dev, "%s was called\n", __func__);
1257
1258 err = mlx5_pci_enable_device(dev);
1259 if (err) {
1260 dev_err(&pdev->dev, "%s: mlx5_pci_enable_device failed with error code: %d\n"
1261 , __func__, err);
1262 return PCI_ERS_RESULT_DISCONNECT;
1263 }
1264 pci_set_master(pdev);
1265 pci_set_powerstate(pdev->dev.bsddev, PCI_POWERSTATE_D0);
1266 pci_restore_state(pdev->dev.bsddev);
1267
1268 return err ? PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_RECOVERED;
1269}
1270
1271void mlx5_disable_device(struct mlx5_core_dev *dev)
1272{
1273 mlx5_pci_err_detected(dev->pdev, 0);
1274}
1275
1276/* wait for the device to show vital signs. For now we check
1277 * that we can read the device ID and that the health buffer
1278 * shows a non zero value which is different than 0xffffffff
1279 */
1280static void wait_vital(struct pci_dev *pdev)
1281{
1282 struct mlx5_core_dev *dev = pci_get_drvdata(pdev);
1283 struct mlx5_core_health *health = &dev->priv.health;
1284 const int niter = 100;
1285 u32 count;
1286 u16 did;
1287 int i;
1288
1289 /* Wait for firmware to be ready after reset */
1290 msleep(1000);
1291 for (i = 0; i < niter; i++) {
1292 if (pci_read_config_word(pdev, 2, &did)) {
1293 dev_warn(&pdev->dev, "failed reading config word\n");
1294 break;
1295 }
1296 if (did == pdev->device) {
1297 dev_info(&pdev->dev, "device ID correctly read after %d iterations\n", i);
1298 break;
1299 }
1300 msleep(50);
1301 }
1302 if (i == niter)
1303 dev_warn(&pdev->dev, "%s-%d: could not read device ID\n", __func__, __LINE__);
1304
1305 for (i = 0; i < niter; i++) {
1306 count = ioread32be(health->health_counter);
1307 if (count && count != 0xffffffff) {
1308 dev_info(&pdev->dev, "Counter value 0x%x after %d iterations\n", count, i);
1309 break;
1310 }
1311 msleep(50);
1312 }
1313
1314 if (i == niter)
1315 dev_warn(&pdev->dev, "%s-%d: could not read device ID\n", __func__, __LINE__);
1316}
1317
1318static void mlx5_pci_resume(struct pci_dev *pdev)
1319{
1320 struct mlx5_core_dev *dev = pci_get_drvdata(pdev);
1321 struct mlx5_priv *priv = &dev->priv;
1322 int err;
1323
1324 dev_info(&pdev->dev, "%s was called\n", __func__);
1325
1326 pci_save_state(pdev->dev.bsddev);
1327 wait_vital(pdev);
1328
1329 err = mlx5_load_one(dev, priv);
1330 if (err)
1331 dev_err(&pdev->dev, "%s: mlx5_load_one failed with error code: %d\n"
1332 , __func__, err);
1333 else
1334 dev_info(&pdev->dev, "%s: device recovered\n", __func__);
1335}
1336
1337static const struct pci_error_handlers mlx5_err_handler = {
1338 .error_detected = mlx5_pci_err_detected,
1339 .slot_reset = mlx5_pci_slot_reset,
1340 .resume = mlx5_pci_resume
1341};
1342
1139static void shutdown_one(struct pci_dev *pdev)
1140{
1343static void shutdown_one(struct pci_dev *pdev)
1344{
1141 /* prevent device from accessing host memory after shutdown */
1142 pci_clear_master(pdev);
1345 struct mlx5_core_dev *dev = pci_get_drvdata(pdev);
1346 struct mlx5_priv *priv = &dev->priv;
1347
1348 set_bit(MLX5_INTERFACE_STATE_SHUTDOWN, &dev->intf_state);
1349 mlx5_unload_one(dev, priv);
1350 mlx5_pci_disable_device(dev);
1143}
1144
1145static const struct pci_device_id mlx5_core_pci_table[] = {
1146 { PCI_VDEVICE(MELLANOX, 4113) }, /* Connect-IB */
1147 { PCI_VDEVICE(MELLANOX, 4114) }, /* Connect-IB VF */
1148 { PCI_VDEVICE(MELLANOX, 4115) }, /* ConnectX-4 */
1149 { PCI_VDEVICE(MELLANOX, 4116) }, /* ConnectX-4 VF */
1150 { PCI_VDEVICE(MELLANOX, 4117) }, /* ConnectX-4LX */

--- 29 unchanged lines hidden (view full) ---

1180
1181MODULE_DEVICE_TABLE(pci, mlx5_core_pci_table);
1182
1183static struct pci_driver mlx5_core_driver = {
1184 .name = DRIVER_NAME,
1185 .id_table = mlx5_core_pci_table,
1186 .shutdown = shutdown_one,
1187 .probe = init_one,
1351}
1352
1353static const struct pci_device_id mlx5_core_pci_table[] = {
1354 { PCI_VDEVICE(MELLANOX, 4113) }, /* Connect-IB */
1355 { PCI_VDEVICE(MELLANOX, 4114) }, /* Connect-IB VF */
1356 { PCI_VDEVICE(MELLANOX, 4115) }, /* ConnectX-4 */
1357 { PCI_VDEVICE(MELLANOX, 4116) }, /* ConnectX-4 VF */
1358 { PCI_VDEVICE(MELLANOX, 4117) }, /* ConnectX-4LX */

--- 29 unchanged lines hidden (view full) ---

1388
1389MODULE_DEVICE_TABLE(pci, mlx5_core_pci_table);
1390
1391static struct pci_driver mlx5_core_driver = {
1392 .name = DRIVER_NAME,
1393 .id_table = mlx5_core_pci_table,
1394 .shutdown = shutdown_one,
1395 .probe = init_one,
1188 .remove = remove_one
1396 .remove = remove_one,
1397 .err_handler = &mlx5_err_handler
1189};
1190
1191static int __init init(void)
1192{
1193 int err;
1194
1398};
1399
1400static int __init init(void)
1401{
1402 int err;
1403
1195 mlx5_core_wq = create_singlethread_workqueue("mlx5_core_wq");
1196 if (!mlx5_core_wq) {
1197 err = -ENOMEM;
1198 goto err_debug;
1199 }
1200 mlx5_health_init();
1201
1202 err = pci_register_driver(&mlx5_core_driver);
1203 if (err)
1404 err = pci_register_driver(&mlx5_core_driver);
1405 if (err)
1204 goto err_health;
1406 goto err_debug;
1205
1206
1207 return 0;
1208
1407
1408
1409 return 0;
1410
1209err_health:
1210 mlx5_health_cleanup();
1211 destroy_workqueue(mlx5_core_wq);
1212err_debug:
1213 return err;
1214}
1215
1216static void __exit cleanup(void)
1217{
1218 pci_unregister_driver(&mlx5_core_driver);
1411err_debug:
1412 return err;
1413}
1414
1415static void __exit cleanup(void)
1416{
1417 pci_unregister_driver(&mlx5_core_driver);
1219 mlx5_health_cleanup();
1220 destroy_workqueue(mlx5_core_wq);
1221}
1222
1223module_init(init);
1224module_exit(cleanup);
1418}
1419
1420module_init(init);
1421module_exit(cleanup);
1225
1226void mlx5_enter_error_state(struct mlx5_core_dev *dev)
1227{
1228 if (dev->state != MLX5_DEVICE_STATE_UP)
1229 return;
1230
1231 dev->state = MLX5_DEVICE_STATE_INTERNAL_ERROR;
1232 mlx5_trigger_cmd_completions(dev);
1233}
1234EXPORT_SYMBOL(mlx5_enter_error_state);