From f21c179e1206e88d187d517d97d270c6492d4673 Mon Sep 17 00:00:00 2001 From: "David E. Box" Date: Wed, 29 Jun 2022 15:13:31 -0700 Subject: platform/x86/intel/vsec: Rework early hardware code In the Intel VSEC PCI driver, use a new VSEC_QUIRK_EARLY_HW flag in driver_data to indicate the need for early hardware quirks in auxiliary devices. Remove the separate PCI ID list maintained by the Intel PMT auxiliary driver. Cc: Srinivas Pandruvada Signed-off-by: David E. Box Signed-off-by: Gayatri Kammela Link: https://lore.kernel.org/r/20220629221334.434307-2-gayatri.kammela@linux.intel.com Reviewed-by: Hans de Goede Signed-off-by: Hans de Goede --- drivers/platform/x86/intel/vsec.c | 46 +++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 24 deletions(-) (limited to 'drivers/platform/x86/intel/vsec.c') diff --git a/drivers/platform/x86/intel/vsec.c b/drivers/platform/x86/intel/vsec.c index bed436bf181f..d48df46e2e27 100644 --- a/drivers/platform/x86/intel/vsec.c +++ b/drivers/platform/x86/intel/vsec.c @@ -54,12 +54,6 @@ struct intel_vsec_header { u32 offset; }; -/* Platform specific data */ -struct intel_vsec_platform_info { - struct intel_vsec_header **capabilities; - unsigned long quirks; -}; - enum intel_vsec_id { VSEC_ID_TELEMETRY = 2, VSEC_ID_WATCHER = 3, @@ -169,10 +163,11 @@ static int intel_vsec_add_aux(struct pci_dev *pdev, struct intel_vsec_device *in } static int intel_vsec_add_dev(struct pci_dev *pdev, struct intel_vsec_header *header, - unsigned long quirks) + struct intel_vsec_platform_info *info) { struct intel_vsec_device *intel_vsec_dev; struct resource *res, *tmp; + unsigned long quirks = info->quirks; int i; if (!intel_vsec_allowed(header->id) || intel_vsec_disabled(header->id, quirks)) @@ -216,7 +211,7 @@ static int intel_vsec_add_dev(struct pci_dev *pdev, struct intel_vsec_header *he intel_vsec_dev->pcidev = pdev; intel_vsec_dev->resource = res; intel_vsec_dev->num_resources = header->num_entries; - intel_vsec_dev->quirks = quirks; + intel_vsec_dev->info = info; if (header->id == VSEC_ID_SDSI) intel_vsec_dev->ida = &intel_vsec_sdsi_ida; @@ -226,14 +221,15 @@ static int intel_vsec_add_dev(struct pci_dev *pdev, struct intel_vsec_header *he return intel_vsec_add_aux(pdev, intel_vsec_dev, intel_vsec_name(header->id)); } -static bool intel_vsec_walk_header(struct pci_dev *pdev, unsigned long quirks, - struct intel_vsec_header **header) +static bool intel_vsec_walk_header(struct pci_dev *pdev, + struct intel_vsec_platform_info *info) { + struct intel_vsec_header **header = info->capabilities; bool have_devices = false; int ret; for ( ; *header; header++) { - ret = intel_vsec_add_dev(pdev, *header, quirks); + ret = intel_vsec_add_dev(pdev, *header, info); if (ret) dev_info(&pdev->dev, "Could not add device for DVSEC id %d\n", (*header)->id); @@ -244,7 +240,8 @@ static bool intel_vsec_walk_header(struct pci_dev *pdev, unsigned long quirks, return have_devices; } -static bool intel_vsec_walk_dvsec(struct pci_dev *pdev, unsigned long quirks) +static bool intel_vsec_walk_dvsec(struct pci_dev *pdev, + struct intel_vsec_platform_info *info) { bool have_devices = false; int pos = 0; @@ -283,7 +280,7 @@ static bool intel_vsec_walk_dvsec(struct pci_dev *pdev, unsigned long quirks) pci_read_config_dword(pdev, pos + PCI_DVSEC_HEADER2, &hdr); header.id = PCI_DVSEC_HEADER2_ID(hdr); - ret = intel_vsec_add_dev(pdev, &header, quirks); + ret = intel_vsec_add_dev(pdev, &header, info); if (ret) continue; @@ -293,7 +290,8 @@ static bool intel_vsec_walk_dvsec(struct pci_dev *pdev, unsigned long quirks) return have_devices; } -static bool intel_vsec_walk_vsec(struct pci_dev *pdev, unsigned long quirks) +static bool intel_vsec_walk_vsec(struct pci_dev *pdev, + struct intel_vsec_platform_info *info) { bool have_devices = false; int pos = 0; @@ -327,7 +325,7 @@ static bool intel_vsec_walk_vsec(struct pci_dev *pdev, unsigned long quirks) header.tbir = INTEL_DVSEC_TABLE_BAR(table); header.offset = INTEL_DVSEC_TABLE_OFFSET(table); - ret = intel_vsec_add_dev(pdev, &header, quirks); + ret = intel_vsec_add_dev(pdev, &header, info); if (ret) continue; @@ -341,7 +339,6 @@ static int intel_vsec_pci_probe(struct pci_dev *pdev, const struct pci_device_id { struct intel_vsec_platform_info *info; bool have_devices = false; - unsigned long quirks = 0; int ret; ret = pcim_enable_device(pdev); @@ -349,17 +346,17 @@ static int intel_vsec_pci_probe(struct pci_dev *pdev, const struct pci_device_id return ret; info = (struct intel_vsec_platform_info *)id->driver_data; - if (info) - quirks = info->quirks; + if (!info) + return -EINVAL; - if (intel_vsec_walk_dvsec(pdev, quirks)) + if (intel_vsec_walk_dvsec(pdev, info)) have_devices = true; - if (intel_vsec_walk_vsec(pdev, quirks)) + if (intel_vsec_walk_vsec(pdev, info)) have_devices = true; if (info && (info->quirks & VSEC_QUIRK_NO_DVSEC) && - intel_vsec_walk_header(pdev, quirks, info->capabilities)) + intel_vsec_walk_header(pdev, info)) have_devices = true; if (!have_devices) @@ -370,7 +367,8 @@ static int intel_vsec_pci_probe(struct pci_dev *pdev, const struct pci_device_id /* TGL info */ static const struct intel_vsec_platform_info tgl_info = { - .quirks = VSEC_QUIRK_NO_WATCHER | VSEC_QUIRK_NO_CRASHLOG | VSEC_QUIRK_TABLE_SHIFT, + .quirks = VSEC_QUIRK_NO_WATCHER | VSEC_QUIRK_NO_CRASHLOG | + VSEC_QUIRK_TABLE_SHIFT | VSEC_QUIRK_EARLY_HW, }; /* DG1 info */ @@ -390,7 +388,7 @@ static struct intel_vsec_header *dg1_capabilities[] = { static const struct intel_vsec_platform_info dg1_info = { .capabilities = dg1_capabilities, - .quirks = VSEC_QUIRK_NO_DVSEC, + .quirks = VSEC_QUIRK_NO_DVSEC | VSEC_QUIRK_EARLY_HW, }; #define PCI_DEVICE_ID_INTEL_VSEC_ADL 0x467d @@ -400,7 +398,7 @@ static const struct intel_vsec_platform_info dg1_info = { static const struct pci_device_id intel_vsec_pci_ids[] = { { PCI_DEVICE_DATA(INTEL, VSEC_ADL, &tgl_info) }, { PCI_DEVICE_DATA(INTEL, VSEC_DG1, &dg1_info) }, - { PCI_DEVICE_DATA(INTEL, VSEC_OOBMSM, NULL) }, + { PCI_DEVICE_DATA(INTEL, VSEC_OOBMSM, &(struct intel_vsec_platform_info) {}) }, { PCI_DEVICE_DATA(INTEL, VSEC_TGL, &tgl_info) }, { } }; -- cgit v1.2.3 From 99de05043e77cdecc34c09e4fabffdc6d9147c80 Mon Sep 17 00:00:00 2001 From: "David E. Box" Date: Wed, 29 Jun 2022 15:13:32 -0700 Subject: platform/x86/intel/vsec: Add support for Raptor Lake Add Raptor Lake support to Intel's PMT driver. Cc: Srinivas Pandruvada Signed-off-by: David E. Box Signed-off-by: Gayatri Kammela Link: https://lore.kernel.org/r/20220629221334.434307-3-gayatri.kammela@linux.intel.com Reviewed-by: Hans de Goede Signed-off-by: Hans de Goede --- drivers/platform/x86/intel/vsec.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/platform/x86/intel/vsec.c') diff --git a/drivers/platform/x86/intel/vsec.c b/drivers/platform/x86/intel/vsec.c index d48df46e2e27..9368a3d587ab 100644 --- a/drivers/platform/x86/intel/vsec.c +++ b/drivers/platform/x86/intel/vsec.c @@ -394,11 +394,13 @@ static const struct intel_vsec_platform_info dg1_info = { #define PCI_DEVICE_ID_INTEL_VSEC_ADL 0x467d #define PCI_DEVICE_ID_INTEL_VSEC_DG1 0x490e #define PCI_DEVICE_ID_INTEL_VSEC_OOBMSM 0x09a7 +#define PCI_DEVICE_ID_INTEL_VSEC_RPL 0xa77d #define PCI_DEVICE_ID_INTEL_VSEC_TGL 0x9a0d static const struct pci_device_id intel_vsec_pci_ids[] = { { PCI_DEVICE_DATA(INTEL, VSEC_ADL, &tgl_info) }, { PCI_DEVICE_DATA(INTEL, VSEC_DG1, &dg1_info) }, { PCI_DEVICE_DATA(INTEL, VSEC_OOBMSM, &(struct intel_vsec_platform_info) {}) }, + { PCI_DEVICE_DATA(INTEL, VSEC_RPL, &tgl_info) }, { PCI_DEVICE_DATA(INTEL, VSEC_TGL, &tgl_info) }, { } }; -- cgit v1.2.3 From 936874b77dd0a86aafc1f03c11cb97ec938c16f1 Mon Sep 17 00:00:00 2001 From: Gayatri Kammela Date: Wed, 29 Jun 2022 15:13:34 -0700 Subject: platform/x86/intel/vsec: Add PCI error recovery support to Intel PMT Add PCI error recovery support for Intel PMT driver to recover from PCI fatal errors Cc: Srinivas Pandruvada Cc: David E Box Signed-off-by: Gayatri Kammela Link: https://lore.kernel.org/r/20220629221334.434307-5-gayatri.kammela@linux.intel.com Reviewed-by: Hans de Goede Signed-off-by: Hans de Goede --- drivers/platform/x86/intel/vsec.c | 82 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 80 insertions(+), 2 deletions(-) (limited to 'drivers/platform/x86/intel/vsec.c') diff --git a/drivers/platform/x86/intel/vsec.c b/drivers/platform/x86/intel/vsec.c index 9368a3d587ab..70c76f54f544 100644 --- a/drivers/platform/x86/intel/vsec.c +++ b/drivers/platform/x86/intel/vsec.c @@ -15,6 +15,7 @@ #include #include +#include #include #include #include @@ -30,9 +31,13 @@ #define INTEL_DVSEC_TABLE_BAR(x) ((x) & GENMASK(2, 0)) #define INTEL_DVSEC_TABLE_OFFSET(x) ((x) & GENMASK(31, 3)) #define TABLE_OFFSET_SHIFT 3 +#define PMT_XA_START 0 +#define PMT_XA_MAX INT_MAX +#define PMT_XA_LIMIT XA_LIMIT(PMT_XA_START, PMT_XA_MAX) static DEFINE_IDA(intel_vsec_ida); static DEFINE_IDA(intel_vsec_sdsi_ida); +static DEFINE_XARRAY_ALLOC(auxdev_array); /** * struct intel_vsec_header - Common fields of Intel VSEC and DVSEC registers. @@ -132,7 +137,7 @@ static int intel_vsec_add_aux(struct pci_dev *pdev, struct intel_vsec_device *in const char *name) { struct auxiliary_device *auxdev = &intel_vsec_dev->auxdev; - int ret; + int ret, id; ret = ida_alloc(intel_vsec_dev->ida, GFP_KERNEL); if (ret < 0) { @@ -159,7 +164,18 @@ static int intel_vsec_add_aux(struct pci_dev *pdev, struct intel_vsec_device *in return ret; } - return devm_add_action_or_reset(&pdev->dev, intel_vsec_remove_aux, auxdev); + ret = devm_add_action_or_reset(&pdev->dev, intel_vsec_remove_aux, + auxdev); + if (ret < 0) + return ret; + + /* Add auxdev to list */ + ret = xa_alloc(&auxdev_array, &id, intel_vsec_dev, PMT_XA_LIMIT, + GFP_KERNEL); + if (ret) + return ret; + + return 0; } static int intel_vsec_add_dev(struct pci_dev *pdev, struct intel_vsec_header *header, @@ -345,6 +361,7 @@ static int intel_vsec_pci_probe(struct pci_dev *pdev, const struct pci_device_id if (ret) return ret; + pci_save_state(pdev); info = (struct intel_vsec_platform_info *)id->driver_data; if (!info) return -EINVAL; @@ -406,10 +423,71 @@ static const struct pci_device_id intel_vsec_pci_ids[] = { }; MODULE_DEVICE_TABLE(pci, intel_vsec_pci_ids); +static pci_ers_result_t intel_vsec_pci_error_detected(struct pci_dev *pdev, + pci_channel_state_t state) +{ + pci_channel_state_t status = PCI_ERS_RESULT_NEED_RESET; + + dev_info(&pdev->dev, "PCI error detected, state %d", state); + + if (state == pci_channel_io_perm_failure) + status = PCI_ERS_RESULT_DISCONNECT; + else + pci_disable_device(pdev); + + return status; +} + +static pci_ers_result_t intel_vsec_pci_slot_reset(struct pci_dev *pdev) +{ + struct intel_vsec_device *intel_vsec_dev; + pci_channel_state_t status = PCI_ERS_RESULT_DISCONNECT; + const struct pci_device_id *pci_dev_id; + unsigned long index; + + dev_info(&pdev->dev, "Resetting PCI slot\n"); + + msleep(2000); + if (pci_enable_device(pdev)) { + dev_info(&pdev->dev, + "Failed to re-enable PCI device after reset.\n"); + goto out; + } + + status = PCI_ERS_RESULT_RECOVERED; + + xa_for_each(&auxdev_array, index, intel_vsec_dev) { + /* check if pdev doesn't match */ + if (pdev != intel_vsec_dev->pcidev) + continue; + devm_release_action(&pdev->dev, intel_vsec_remove_aux, + &intel_vsec_dev->auxdev); + } + pci_disable_device(pdev); + pci_restore_state(pdev); + pci_dev_id = pci_match_id(intel_vsec_pci_ids, pdev); + intel_vsec_pci_probe(pdev, pci_dev_id); + +out: + return status; +} + +static void intel_vsec_pci_resume(struct pci_dev *pdev) +{ + dev_info(&pdev->dev, "Done resuming PCI device\n"); +} + +const struct pci_error_handlers intel_vsec_pci_err_handlers = { + .error_detected = intel_vsec_pci_error_detected, + .slot_reset = intel_vsec_pci_slot_reset, + .resume = intel_vsec_pci_resume, +}; + static struct pci_driver intel_vsec_pci_driver = { .name = "intel_vsec", .id_table = intel_vsec_pci_ids, .probe = intel_vsec_pci_probe, + .err_handler = &intel_vsec_pci_err_handlers, }; module_pci_driver(intel_vsec_pci_driver); -- cgit v1.2.3 From 3d46d78480757e6d403c3bc2b32d2b05ecbed543 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 1 Aug 2022 16:55:36 +0200 Subject: platform/x86/intel/vsec: Fix wrong type for local status variables The local status variables in intel_vsec_pci_error_detected() and intel_vsec_pci_slot_reset() should have pci_ers_result_t as type (and not pci_channel_state_t). Also fix a whitespace error as well as intel_vsec_pci_err_handlers not being marked static. This fixes the following sparse errors: drivers/platform/x86/intel/vsec.c:429:38: sparse: sparse: incorrect type in initializer (different base types) @@ expected restricted pci_channel_state_t [usertype] status @@ got restricted pci_ers_result_t @@ drivers/platform/x86/intel/vsec.c:429:38: sparse: expected restricted pci_channel_state_t [usertype] status drivers/platform/x86/intel/vsec.c:429:38: sparse: got restricted pci_ers_result_t drivers/platform/x86/intel/vsec.c:434:24: sparse: sparse: incorrect type in assignment (different base types) @@ expected restricted pci_channel_state_t [usertype] status @@ got restricted pci_ers_result_t @@ drivers/platform/x86/intel/vsec.c:434:24: sparse: expected restricted pci_channel_state_t [usertype] status drivers/platform/x86/intel/vsec.c:434:24: sparse: got restricted pci_ers_result_t drivers/platform/x86/intel/vsec.c:438:16: sparse: sparse: incorrect type in return expression (different base types) @@ expected restricted pci_ers_result_t @@ got restricted pci_channel_state_t [usertype] status @@ drivers/platform/x86/intel/vsec.c:438:16: sparse: expected restricted pci_ers_result_t drivers/platform/x86/intel/vsec.c:438:16: sparse: got restricted pci_channel_state_t [usertype] status drivers/platform/x86/intel/vsec.c:444:38: sparse: sparse: incorrect type in initializer (different base types) @@ expected restricted pci_channel_state_t [usertype] status @@ got restricted pci_ers_result_t @@ drivers/platform/x86/intel/vsec.c:444:38: sparse: expected restricted pci_channel_state_t [usertype] status drivers/platform/x86/intel/vsec.c:444:38: sparse: got restricted pci_ers_result_t drivers/platform/x86/intel/vsec.c:457:16: sparse: sparse: incorrect type in assignment (different base types) @@ expected restricted pci_channel_state_t [usertype] status @@ got restricted pci_ers_result_t @@ drivers/platform/x86/intel/vsec.c:457:16: sparse: expected restricted pci_channel_state_t [usertype] status drivers/platform/x86/intel/vsec.c:457:16: sparse: got restricted pci_ers_result_t drivers/platform/x86/intel/vsec.c:472:16: sparse: sparse: incorrect type in return expression (different base types) @@ expected restricted pci_ers_result_t @@ got restricted pci_channel_state_t [usertype] status @@ drivers/platform/x86/intel/vsec.c:472:16: sparse: expected restricted pci_ers_result_t drivers/platform/x86/intel/vsec.c:472:16: sparse: got restricted pci_channel_state_t [usertype] status drivers/platform/x86/intel/vsec.c:480:33: sparse: sparse: symbol 'intel_vsec_pci_err_handlers' was not declared. Should it be static? Reported-by: kernel test robot Cc: Srinivas Pandruvada Cc: David E Box Cc: Gayatri Kammela Signed-off-by: Hans de Goede Link: https://lore.kernel.org/r/20220801145536.172410-1-hdegoede@redhat.com --- drivers/platform/x86/intel/vsec.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/platform/x86/intel/vsec.c') diff --git a/drivers/platform/x86/intel/vsec.c b/drivers/platform/x86/intel/vsec.c index 70c76f54f544..bb81b8b1f7e9 100644 --- a/drivers/platform/x86/intel/vsec.c +++ b/drivers/platform/x86/intel/vsec.c @@ -426,7 +426,7 @@ MODULE_DEVICE_TABLE(pci, intel_vsec_pci_ids); static pci_ers_result_t intel_vsec_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state) { - pci_channel_state_t status = PCI_ERS_RESULT_NEED_RESET; + pci_ers_result_t status = PCI_ERS_RESULT_NEED_RESET; dev_info(&pdev->dev, "PCI error detected, state %d", state); @@ -441,7 +441,7 @@ static pci_ers_result_t intel_vsec_pci_error_detected(struct pci_dev *pdev, static pci_ers_result_t intel_vsec_pci_slot_reset(struct pci_dev *pdev) { struct intel_vsec_device *intel_vsec_dev; - pci_channel_state_t status = PCI_ERS_RESULT_DISCONNECT; + pci_ers_result_t status = PCI_ERS_RESULT_DISCONNECT; const struct pci_device_id *pci_dev_id; unsigned long index; @@ -454,7 +454,7 @@ static pci_ers_result_t intel_vsec_pci_slot_reset(struct pci_dev *pdev) goto out; } - status = PCI_ERS_RESULT_RECOVERED; + status = PCI_ERS_RESULT_RECOVERED; xa_for_each(&auxdev_array, index, intel_vsec_dev) { /* check if pdev doesn't match */ @@ -477,7 +477,7 @@ static void intel_vsec_pci_resume(struct pci_dev *pdev) dev_info(&pdev->dev, "Done resuming PCI device\n"); } -const struct pci_error_handlers intel_vsec_pci_err_handlers = { +static const struct pci_error_handlers intel_vsec_pci_err_handlers = { .error_detected = intel_vsec_pci_error_detected, .slot_reset = intel_vsec_pci_slot_reset, .resume = intel_vsec_pci_resume, -- cgit v1.2.3