intel_th: Disallow multi mode on devices where it's broken
authorAlexander Shishkin <alexander.shishkin@linux.intel.com>
Tue, 17 Mar 2020 06:22:10 +0000 (08:22 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 18 Mar 2020 10:28:22 +0000 (11:28 +0100)
Some versions of Intel TH have an issue that prevents the multi mode of
MSU from working correctly, resulting in no trace data and potentially
stuck MSU pipeline.

Disable multi mode on such devices.

Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Link: https://lore.kernel.org/r/20200317062215.15598-2-alexander.shishkin@linux.intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/hwtracing/intel_th/intel_th.h
drivers/hwtracing/intel_th/msu.c
drivers/hwtracing/intel_th/pci.c

index 6f4f5486fe6dcccb3f9570cf3c0eb7da24b22b0c..5fe694708b7a3117991900ea89028b366ae18810 100644 (file)
@@ -47,11 +47,13 @@ struct intel_th_output {
 /**
  * struct intel_th_drvdata - describes hardware capabilities and quirks
  * @tscu_enable:       device needs SW to enable time stamping unit
+ * @multi_is_broken:   device has multiblock mode is broken
  * @has_mintctl:       device has interrupt control (MINTCTL) register
  * @host_mode_only:    device can only operate in 'host debugger' mode
  */
 struct intel_th_drvdata {
        unsigned int    tscu_enable        : 1,
+                       multi_is_broken    : 1,
                        has_mintctl        : 1,
                        host_mode_only     : 1;
 };
index 8e48c7458aa35cbbf3963462d969d2b22614ce49..6e118b790d83d9a64b1a84015b9bb96fe2557a0c 100644 (file)
@@ -157,7 +157,8 @@ struct msc {
        /* config */
        unsigned int            enabled : 1,
                                wrap    : 1,
-                               do_irq  : 1;
+                               do_irq  : 1,
+                               multi_is_broken : 1;
        unsigned int            mode;
        unsigned int            burst_len;
        unsigned int            index;
@@ -1664,7 +1665,7 @@ static int intel_th_msc_init(struct msc *msc)
 {
        atomic_set(&msc->user_count, -1);
 
-       msc->mode = MSC_MODE_MULTI;
+       msc->mode = msc->multi_is_broken ? MSC_MODE_SINGLE : MSC_MODE_MULTI;
        mutex_init(&msc->buf_mutex);
        INIT_LIST_HEAD(&msc->win_list);
        INIT_LIST_HEAD(&msc->iter_list);
@@ -1876,6 +1877,9 @@ mode_store(struct device *dev, struct device_attribute *attr, const char *buf,
        return -EINVAL;
 
 found:
+       if (i == MSC_MODE_MULTI && msc->multi_is_broken)
+               return -EOPNOTSUPP;
+
        mutex_lock(&msc->buf_mutex);
        ret = 0;
 
@@ -2082,6 +2086,9 @@ static int intel_th_msc_probe(struct intel_th_device *thdev)
        if (!res)
                msc->do_irq = 1;
 
+       if (INTEL_TH_CAP(to_intel_th(thdev), multi_is_broken))
+               msc->multi_is_broken = 1;
+
        msc->index = thdev->id;
 
        msc->thdev = thdev;
index e9d90b53bbc46325f199a9d684cdf9f5e12430cc..ad7e51ebe49ee626d79c765cdfe7f7e8c639d4a2 100644 (file)
@@ -120,6 +120,10 @@ static void intel_th_pci_remove(struct pci_dev *pdev)
        pci_free_irq_vectors(pdev);
 }
 
+static const struct intel_th_drvdata intel_th_1x_multi_is_broken = {
+       .multi_is_broken        = 1,
+};
+
 static const struct intel_th_drvdata intel_th_2x = {
        .tscu_enable    = 1,
        .has_mintctl    = 1,
@@ -152,7 +156,7 @@ static const struct pci_device_id intel_th_pci_id_table[] = {
        {
                /* Kaby Lake PCH-H */
                PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa2a6),
-               .driver_data = (kernel_ulong_t)0,
+               .driver_data = (kernel_ulong_t)&intel_th_1x_multi_is_broken,
        },
        {
                /* Denverton */
@@ -207,7 +211,7 @@ static const struct pci_device_id intel_th_pci_id_table[] = {
        {
                /* Comet Lake PCH-V */
                PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa3a6),
-               .driver_data = (kernel_ulong_t)&intel_th_2x,
+               .driver_data = (kernel_ulong_t)&intel_th_1x_multi_is_broken,
        },
        {
                /* Ice Lake NNPI */