aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/cxl/pci.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc/cxl/pci.c')
-rw-r--r--drivers/misc/cxl/pci.c236
1 files changed, 18 insertions, 218 deletions
diff --git a/drivers/misc/cxl/pci.c b/drivers/misc/cxl/pci.c
index 429d6de1dde7..9c5a21fee835 100644
--- a/drivers/misc/cxl/pci.c
+++ b/drivers/misc/cxl/pci.c
@@ -55,8 +55,6 @@
55 pci_read_config_byte(dev, vsec + 0xa, dest) 55 pci_read_config_byte(dev, vsec + 0xa, dest)
56#define CXL_WRITE_VSEC_MODE_CONTROL(dev, vsec, val) \ 56#define CXL_WRITE_VSEC_MODE_CONTROL(dev, vsec, val) \
57 pci_write_config_byte(dev, vsec + 0xa, val) 57 pci_write_config_byte(dev, vsec + 0xa, val)
58#define CXL_WRITE_VSEC_MODE_CONTROL_BUS(bus, devfn, vsec, val) \
59 pci_bus_write_config_byte(bus, devfn, vsec + 0xa, val)
60#define CXL_VSEC_PROTOCOL_MASK 0xe0 58#define CXL_VSEC_PROTOCOL_MASK 0xe0
61#define CXL_VSEC_PROTOCOL_1024TB 0x80 59#define CXL_VSEC_PROTOCOL_1024TB 0x80
62#define CXL_VSEC_PROTOCOL_512TB 0x40 60#define CXL_VSEC_PROTOCOL_512TB 0x40
@@ -800,234 +798,36 @@ static int setup_cxl_bars(struct pci_dev *dev)
800 return 0; 798 return 0;
801} 799}
802 800
803#ifdef CONFIG_CXL_BIMODAL 801/* pciex node: ibm,opal-m64-window = <0x3d058 0x0 0x3d058 0x0 0x8 0x0>; */
804 802static int switch_card_to_cxl(struct pci_dev *dev)
805struct cxl_switch_work {
806 struct pci_dev *dev;
807 struct work_struct work;
808 int vsec;
809 int mode;
810};
811
812static void switch_card_to_cxl(struct work_struct *work)
813{ 803{
814 struct cxl_switch_work *switch_work = 804 int vsec;
815 container_of(work, struct cxl_switch_work, work);
816 struct pci_dev *dev = switch_work->dev;
817 struct pci_bus *bus = dev->bus;
818 struct pci_controller *hose = pci_bus_to_host(bus);
819 struct pci_dev *bridge;
820 struct pnv_php_slot *php_slot;
821 unsigned int devfn;
822 u8 val; 805 u8 val;
823 int rc; 806 int rc;
824 807
825 dev_info(&bus->dev, "cxl: Preparing for mode switch...\n"); 808 dev_info(&dev->dev, "switch card to CXL\n");
826 bridge = list_first_entry_or_null(&hose->bus->devices, struct pci_dev,
827 bus_list);
828 if (!bridge) {
829 dev_WARN(&bus->dev, "cxl: Couldn't find root port!\n");
830 goto err_dev_put;
831 }
832 809
833 php_slot = pnv_php_find_slot(pci_device_to_OF_node(bridge)); 810 if (!(vsec = find_cxl_vsec(dev))) {
834 if (!php_slot) { 811 dev_err(&dev->dev, "ABORTING: CXL VSEC not found!\n");
835 dev_err(&bus->dev, "cxl: Failed to find slot hotplug "
836 "information. You may need to upgrade "
837 "skiboot. Aborting.\n");
838 goto err_dev_put;
839 }
840
841 rc = CXL_READ_VSEC_MODE_CONTROL(dev, switch_work->vsec, &val);
842 if (rc) {
843 dev_err(&bus->dev, "cxl: Failed to read CAPI mode control: %i\n", rc);
844 goto err_dev_put;
845 }
846 devfn = dev->devfn;
847
848 /* Release the reference obtained in cxl_check_and_switch_mode() */
849 pci_dev_put(dev);
850
851 dev_dbg(&bus->dev, "cxl: Removing PCI devices from kernel\n");
852 pci_lock_rescan_remove();
853 pci_hp_remove_devices(bridge->subordinate);
854 pci_unlock_rescan_remove();
855
856 /* Switch the CXL protocol on the card */
857 if (switch_work->mode == CXL_BIMODE_CXL) {
858 dev_info(&bus->dev, "cxl: Switching card to CXL mode\n");
859 val &= ~CXL_VSEC_PROTOCOL_MASK;
860 val |= CXL_VSEC_PROTOCOL_256TB | CXL_VSEC_PROTOCOL_ENABLE;
861 rc = pnv_cxl_enable_phb_kernel_api(hose, true);
862 if (rc) {
863 dev_err(&bus->dev, "cxl: Failed to enable kernel API"
864 " on real PHB, aborting\n");
865 goto err_free_work;
866 }
867 } else {
868 dev_WARN(&bus->dev, "cxl: Switching card to PCI mode not supported!\n");
869 goto err_free_work;
870 }
871
872 rc = CXL_WRITE_VSEC_MODE_CONTROL_BUS(bus, devfn, switch_work->vsec, val);
873 if (rc) {
874 dev_err(&bus->dev, "cxl: Failed to configure CXL protocol: %i\n", rc);
875 goto err_free_work;
876 }
877
878 /*
879 * The CAIA spec (v1.1, Section 10.6 Bi-modal Device Support) states
880 * we must wait 100ms after this mode switch before touching PCIe config
881 * space.
882 */
883 msleep(100);
884
885 /*
886 * Hot reset to cause the card to come back in cxl mode. A
887 * OPAL_RESET_PCI_LINK would be sufficient, but currently lacks support
888 * in skiboot, so we use a hot reset instead.
889 *
890 * We call pci_set_pcie_reset_state() on the bridge, as a CAPI card is
891 * guaranteed to sit directly under the root port, and setting the reset
892 * state on a device directly under the root port is equivalent to doing
893 * it on the root port iself.
894 */
895 dev_info(&bus->dev, "cxl: Configuration write complete, resetting card\n");
896 pci_set_pcie_reset_state(bridge, pcie_hot_reset);
897 pci_set_pcie_reset_state(bridge, pcie_deassert_reset);
898
899 dev_dbg(&bus->dev, "cxl: Offlining slot\n");
900 rc = pnv_php_set_slot_power_state(&php_slot->slot, OPAL_PCI_SLOT_OFFLINE);
901 if (rc) {
902 dev_err(&bus->dev, "cxl: OPAL offlining call failed: %i\n", rc);
903 goto err_free_work;
904 }
905
906 dev_dbg(&bus->dev, "cxl: Onlining and probing slot\n");
907 rc = pnv_php_set_slot_power_state(&php_slot->slot, OPAL_PCI_SLOT_ONLINE);
908 if (rc) {
909 dev_err(&bus->dev, "cxl: OPAL onlining call failed: %i\n", rc);
910 goto err_free_work;
911 }
912
913 pci_lock_rescan_remove();
914 pci_hp_add_devices(bridge->subordinate);
915 pci_unlock_rescan_remove();
916
917 dev_info(&bus->dev, "cxl: CAPI mode switch completed\n");
918 kfree(switch_work);
919 return;
920
921err_dev_put:
922 /* Release the reference obtained in cxl_check_and_switch_mode() */
923 pci_dev_put(dev);
924err_free_work:
925 kfree(switch_work);
926}
927
928int cxl_check_and_switch_mode(struct pci_dev *dev, int mode, int vsec)
929{
930 struct cxl_switch_work *work;
931 u8 val;
932 int rc;
933
934 if (!cpu_has_feature(CPU_FTR_HVMODE))
935 return -ENODEV; 812 return -ENODEV;
936
937 if (!vsec) {
938 vsec = find_cxl_vsec(dev);
939 if (!vsec) {
940 dev_info(&dev->dev, "CXL VSEC not found\n");
941 return -ENODEV;
942 }
943 } 813 }
944 814
945 rc = CXL_READ_VSEC_MODE_CONTROL(dev, vsec, &val); 815 if ((rc = CXL_READ_VSEC_MODE_CONTROL(dev, vsec, &val))) {
946 if (rc) { 816 dev_err(&dev->dev, "failed to read current mode control: %i", rc);
947 dev_err(&dev->dev, "Failed to read current mode control: %i", rc);
948 return rc; 817 return rc;
949 } 818 }
950 819 val &= ~CXL_VSEC_PROTOCOL_MASK;
951 if (mode == CXL_BIMODE_PCI) { 820 val |= CXL_VSEC_PROTOCOL_256TB | CXL_VSEC_PROTOCOL_ENABLE;
952 if (!(val & CXL_VSEC_PROTOCOL_ENABLE)) { 821 if ((rc = CXL_WRITE_VSEC_MODE_CONTROL(dev, vsec, val))) {
953 dev_info(&dev->dev, "Card is already in PCI mode\n"); 822 dev_err(&dev->dev, "failed to enable CXL protocol: %i", rc);
954 return 0; 823 return rc;
955 }
956 /*
957 * TODO: Before it's safe to switch the card back to PCI mode
958 * we need to disable the CAPP and make sure any cachelines the
959 * card holds have been flushed out. Needs skiboot support.
960 */
961 dev_WARN(&dev->dev, "CXL mode switch to PCI unsupported!\n");
962 return -EIO;
963 }
964
965 if (val & CXL_VSEC_PROTOCOL_ENABLE) {
966 dev_info(&dev->dev, "Card is already in CXL mode\n");
967 return 0;
968 } 824 }
969
970 dev_info(&dev->dev, "Card is in PCI mode, scheduling kernel thread "
971 "to switch to CXL mode\n");
972
973 work = kmalloc(sizeof(struct cxl_switch_work), GFP_KERNEL);
974 if (!work)
975 return -ENOMEM;
976
977 pci_dev_get(dev);
978 work->dev = dev;
979 work->vsec = vsec;
980 work->mode = mode;
981 INIT_WORK(&work->work, switch_card_to_cxl);
982
983 schedule_work(&work->work);
984
985 /* 825 /*
986 * We return a failure now to abort the driver init. Once the 826 * The CAIA spec (v0.12 11.6 Bi-modal Device Support) states
987 * link has been cycled and the card is in cxl mode we will 827 * we must wait 100ms after this mode switch before touching
988 * come back (possibly using the generic cxl driver), but 828 * PCIe config space.
989 * return success as the card should then be in cxl mode.
990 *
991 * TODO: What if the card comes back in PCI mode even after
992 * the switch? Don't want to spin endlessly.
993 */ 829 */
994 return -EBUSY; 830 msleep(100);
995}
996EXPORT_SYMBOL_GPL(cxl_check_and_switch_mode);
997
998#endif /* CONFIG_CXL_BIMODAL */
999
1000static int setup_cxl_protocol_area(struct pci_dev *dev)
1001{
1002 u8 val;
1003 int rc;
1004 int vsec = find_cxl_vsec(dev);
1005
1006 if (!vsec) {
1007 dev_info(&dev->dev, "CXL VSEC not found\n");
1008 return -ENODEV;
1009 }
1010
1011 rc = CXL_READ_VSEC_MODE_CONTROL(dev, vsec, &val);
1012 if (rc) {
1013 dev_err(&dev->dev, "Failed to read current mode control: %i\n", rc);
1014 return rc;
1015 }
1016
1017 if (!(val & CXL_VSEC_PROTOCOL_ENABLE)) {
1018 dev_err(&dev->dev, "Card not in CAPI mode!\n");
1019 return -EIO;
1020 }
1021
1022 if ((val & CXL_VSEC_PROTOCOL_MASK) != CXL_VSEC_PROTOCOL_256TB) {
1023 val &= ~CXL_VSEC_PROTOCOL_MASK;
1024 val |= CXL_VSEC_PROTOCOL_256TB;
1025 rc = CXL_WRITE_VSEC_MODE_CONTROL(dev, vsec, val);
1026 if (rc) {
1027 dev_err(&dev->dev, "Failed to set CXL protocol area: %i\n", rc);
1028 return rc;
1029 }
1030 }
1031 831
1032 return 0; 832 return 0;
1033} 833}
@@ -1724,7 +1524,7 @@ static int cxl_configure_adapter(struct cxl *adapter, struct pci_dev *dev)
1724 if ((rc = setup_cxl_bars(dev))) 1524 if ((rc = setup_cxl_bars(dev)))
1725 return rc; 1525 return rc;
1726 1526
1727 if ((rc = setup_cxl_protocol_area(dev))) 1527 if ((rc = switch_card_to_cxl(dev)))
1728 return rc; 1528 return rc;
1729 1529
1730 if ((rc = cxl_update_image_control(adapter))) 1530 if ((rc = cxl_update_image_control(adapter)))