mailweb.openeuler.org
Manage this list

Keyboard Shortcuts

Thread View

  • j: Next unread message
  • k: Previous unread message
  • j a: Jump to all threads
  • j l: Jump to MailingList overview

Kernel

Threads by month
  • ----- 2025 -----
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2024 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2023 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2022 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2021 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2020 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2019 -----
  • December
kernel@openeuler.org

  • 58 participants
  • 19300 discussions
[PATCH OLK-5.10] iommu/vt-d:Add support for detecting ACPI device in RMRR
by LeoLiuoc 09 Jul '21

09 Jul '21
Some ACPI devices need to issue dma requests to access the reserved memory area.BIOS uses the device scope type ACPI_NAMESPACE_DEVICE in RMRR to report these ACPI devices. This patch add support for detecting ACPI devices in RMRR and in order to distinguish it from PCI device, some interface functions are modified. Signed-off-by: LeoLiu-oc <LeoLiu-oc(a)zhaoxin.com> ---  drivers/iommu/intel/dmar.c  | 77 +++++++++++++++++++--------------  drivers/iommu/intel/iommu.c | 86 ++++++++++++++++++++++++++++++++++---  drivers/iommu/iommu.c       |  6 +++  include/linux/dmar.h        | 11 ++++-  include/linux/iommu.h       |  3 ++  5 files changed, 142 insertions(+), 41 deletions(-) diff --git a/drivers/iommu/intel/dmar.c b/drivers/iommu/intel/dmar.c index b8d0b56a7575..1d705589fe21 100644 --- a/drivers/iommu/intel/dmar.c +++ b/drivers/iommu/intel/dmar.c @@ -215,7 +215,7 @@ static bool dmar_match_pci_path(struct dmar_pci_notify_info *info, int bus,  }  /* Return: > 0 if match found, 0 if no match found, < 0 if error happens */ -int dmar_insert_dev_scope(struct dmar_pci_notify_info *info, +int dmar_pci_insert_dev_scope(struct dmar_pci_notify_info *info,                void *start, void*end, u16 segment,                struct dmar_dev_scope *devices,                int devices_cnt) @@ -304,7 +304,7 @@ static int dmar_pci_bus_add_dev(struct dmar_pci_notify_info *info)          drhd = container_of(dmaru->hdr,                      struct acpi_dmar_hardware_unit, header); -        ret = dmar_insert_dev_scope(info, (void *)(drhd + 1), +        ret = dmar_pci_insert_dev_scope(info, (void *)(drhd + 1),                  ((void *)drhd) + drhd->header.length,                  dmaru->segment,                  dmaru->devices, dmaru->devices_cnt); @@ -719,47 +719,58 @@ dmar_find_matched_drhd_unit(struct pci_dev *dev)      return dmaru;  } -static void __init dmar_acpi_insert_dev_scope(u8 device_number, -                          struct acpi_device *adev) +/* Return: > 0 if match found, 0 if no match found */ +bool dmar_acpi_insert_dev_scope(u8 device_number, +                struct acpi_device *adev, +                void *start, void *end, +                struct dmar_dev_scope *devices, +                int devices_cnt)  { -    struct dmar_drhd_unit *dmaru; -    struct acpi_dmar_hardware_unit *drhd;      struct acpi_dmar_device_scope *scope;      struct device *tmp;      int i;      struct acpi_dmar_pci_path *path; +    for (; start < end; start += scope->length) { +        scope = start; +        if (scope->entry_type != ACPI_DMAR_SCOPE_TYPE_NAMESPACE) +            continue; +        if (scope->enumeration_id != device_number) +            continue; +        path = (void *)(scope + 1); +        for_each_dev_scope(devices, devices_cnt, i, tmp) +            if (tmp == NULL) { +                devices[i].bus = scope->bus; +                devices[i].devfn = PCI_DEVFN(path->device, path->function); +                rcu_assign_pointer(devices[i].dev, +                            get_device(&adev->dev)); +                return true; +            } +        WARN_ON(i >= devices_cnt); +    } +    return false; +} + +static int dmar_acpi_bus_add_dev(u8 device_number, struct acpi_device *adev) +{ +    struct dmar_drhd_unit *dmaru; +    struct acpi_dmar_hardware_unit *drhd; +    int ret; +      for_each_drhd_unit(dmaru) {          drhd = container_of(dmaru->hdr,                      struct acpi_dmar_hardware_unit,                      header); - -        for (scope = (void *)(drhd + 1); -             (unsigned long)scope < ((unsigned long)drhd) + drhd->header.length; -             scope = ((void *)scope) + scope->length) { -            if (scope->entry_type != ACPI_DMAR_SCOPE_TYPE_NAMESPACE) -                continue; -            if (scope->enumeration_id != device_number) -                continue; - -            path = (void *)(scope + 1); -            pr_info("ACPI device \"%s\" under DMAR at %llx as %02x:%02x.%d\n", -                dev_name(&adev->dev), dmaru->reg_base_addr, -                scope->bus, path->device, path->function); -            for_each_dev_scope(dmaru->devices, dmaru->devices_cnt, i, tmp) -                if (tmp == NULL) { -                    dmaru->devices[i].bus = scope->bus; -                    dmaru->devices[i].devfn = PCI_DEVFN(path->device, -                                        path->function); -                    rcu_assign_pointer(dmaru->devices[i].dev, -                               get_device(&adev->dev)); -                    return; -                } -            BUG_ON(i >= dmaru->devices_cnt); -        } +        ret = dmar_acpi_insert_dev_scope(device_number, adev, (void *)(drhd+1), +                        ((void *)drhd)+drhd->header.length, +                        dmaru->devices, dmaru->devices_cnt); +        if (ret) +            break;      } -    pr_warn("No IOMMU scope found for ANDD enumeration ID %d (%s)\n", -        device_number, dev_name(&adev->dev)); +    if (ret > 0) +        ret = dmar_rmrr_add_acpi_dev(device_number, adev); + +    return ret;  }  static int __init dmar_acpi_dev_scope_init(void) @@ -788,7 +799,7 @@ static int __init dmar_acpi_dev_scope_init(void)                         andd->device_name);                  continue;              } -            dmar_acpi_insert_dev_scope(andd->device_number, adev); +            dmar_acpi_bus_add_dev(andd->device_number, adev);          }      }      return 0; diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c index 6cc6ef585aa4..5f2b7a64d2c7 100644 --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -4600,6 +4600,25 @@ int dmar_find_matched_atsr_unit(struct pci_dev *dev)      return ret;  } +int dmar_rmrr_add_acpi_dev(u8 device_number, struct acpi_device *adev) +{ +    int ret; +    struct dmar_rmrr_unit *rmrru; +    struct acpi_dmar_reserved_memory *rmrr; + +    list_for_each_entry(rmrru, &dmar_rmrr_units, list) { +        rmrr = container_of(rmrru->hdr, +                struct acpi_dmar_reserved_memory, +                header); +        ret = dmar_acpi_insert_dev_scope(device_number, adev, (void *)(rmrr + 1), +                        ((void *)rmrr) + rmrr->header.length, +                        rmrru->devices, rmrru->devices_cnt); +        if (ret) +            break; +    } +    return 0; +} +  int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)  {      int ret; @@ -4615,7 +4634,7 @@ int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)          rmrr = container_of(rmrru->hdr,                      struct acpi_dmar_reserved_memory, header);          if (info->event == BUS_NOTIFY_ADD_DEVICE) { -            ret = dmar_insert_dev_scope(info, (void *)(rmrr + 1), +            ret = dmar_pci_insert_dev_scope(info, (void *)(rmrr + 1),                  ((void *)rmrr) + rmrr->header.length,                  rmrr->segment, rmrru->devices,                  rmrru->devices_cnt); @@ -4633,7 +4652,7 @@ int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)          atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);          if (info->event == BUS_NOTIFY_ADD_DEVICE) { -            ret = dmar_insert_dev_scope(info, (void *)(atsr + 1), +            ret = dmar_pci_insert_dev_scope(info, (void *)(atsr + 1),                      (void *)atsr + atsr->header.length,                      atsr->segment, atsru->devices,                      atsru->devices_cnt); @@ -4872,6 +4891,22 @@ static int __init platform_optin_force_iommu(void)      return 1;  } +static int acpi_device_create_direct_mappings(struct device *pn_dev, struct device *acpi_device) +{ +    struct iommu_group *group; + +    acpi_device->bus->iommu_ops = &intel_iommu_ops; +    group = iommu_group_get(pn_dev); +    if (!group) { +        pr_warn("ACPI name space devices create direct mappings wrong!\n"); +        return -EINVAL; +    } +    printk(KERN_INFO "pn_dev:%s enter to %s\n", dev_name(pn_dev), __func__); +    __acpi_device_create_direct_mappings(group, acpi_device); + +    return 0; +} +  static int __init probe_acpi_namespace_devices(void)  {      struct dmar_drhd_unit *drhd; @@ -4879,6 +4914,7 @@ static int __init probe_acpi_namespace_devices(void)      struct intel_iommu *iommu __maybe_unused;      struct device *dev;      int i, ret = 0; +    u8 bus, devfn;      for_each_active_iommu(iommu, drhd) {          for_each_active_dev_scope(drhd->devices, @@ -4887,6 +4923,8 @@ static int __init probe_acpi_namespace_devices(void)              struct iommu_group *group;              struct acpi_device *adev; +            struct device *pn_dev = NULL; +            struct device_domain_info *info = NULL;              if (dev->bus != &acpi_bus_type)                  continue; @@ -4896,19 +4934,53 @@ static int __init probe_acpi_namespace_devices(void)                          &adev->physical_node_list, node) {                  group = iommu_group_get(pn->dev);                  if (group) { +                    pn_dev = pn->dev;                      iommu_group_put(group);                      continue;                  } -                pn->dev->bus->iommu_ops = &intel_iommu_ops; -                ret = iommu_probe_device(pn->dev); -                if (ret) -                    break; +                iommu = device_to_iommu(dev, &bus, &devfn); +                if (!iommu) +                    return -ENODEV; +                info = dmar_search_domain_by_dev_info(iommu->segment, bus, devfn); +                if (!info) { +                    pn->dev->bus->iommu_ops = &intel_iommu_ops; +                    ret = iommu_probe_device(pn->dev); +                    if (ret) { +                        pr_err("pn->dev:%s probe fail! ret:%d\n", +                            dev_name(pn->dev), ret); +                        goto unlock; +                    } +                } +                pn_dev = pn->dev; +            } +            if (!pn_dev) { +                iommu = device_to_iommu(dev, &bus, &devfn); +                if (!iommu) +                    return -ENODEV; +                info = dmar_search_domain_by_dev_info(iommu->segment, bus, devfn); +                if (!info) { +                    dev->bus->iommu_ops = &intel_iommu_ops; +                    ret = iommu_probe_device(dev); +                    if (ret) { +                        pr_err("dev:%s probe fail! ret:%d\n", +                            dev_name(dev), ret); +                        goto unlock; +                    } +                    goto unlock; +                }              } +            if (!info) +                ret = acpi_device_create_direct_mappings(pn_dev, dev); +            else +                ret = acpi_device_create_direct_mappings(info->dev, dev); +unlock:              mutex_unlock(&adev->physical_node_lock); -            if (ret) +            if (ret) { +                pr_err("%s fail! ret:%d\n", __func__, ret);                  return ret; +            }          }      } diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 86e3dbdfb7bd..6212eb1856f5 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -814,6 +814,12 @@ static bool iommu_is_attach_deferred(struct iommu_domain *domain,      return false;  } +void  __acpi_device_create_direct_mappings(struct iommu_group *group, struct device *acpi_device) +{ +    iommu_create_device_direct_mappings(group, acpi_device); +} +EXPORT_SYMBOL_GPL(__acpi_device_create_direct_mappings); +  /**   * iommu_group_add_device - add a device to an iommu group   * @group: the group into which to add the device (reference should be held) diff --git a/include/linux/dmar.h b/include/linux/dmar.h index 65565820328a..248e3c2feeae 100644 --- a/include/linux/dmar.h +++ b/include/linux/dmar.h @@ -113,10 +113,13 @@ extern int dmar_parse_dev_scope(void *start, void *end, int *cnt,                  struct dmar_dev_scope **devices, u16 segment);  extern void *dmar_alloc_dev_scope(void *start, void *end, int *cnt);  extern void dmar_free_dev_scope(struct dmar_dev_scope **devices, int *cnt); -extern int dmar_insert_dev_scope(struct dmar_pci_notify_info *info, +extern int dmar_pci_insert_dev_scope(struct dmar_pci_notify_info *info,                   void *start, void*end, u16 segment,                   struct dmar_dev_scope *devices,                   int devices_cnt); +extern bool dmar_acpi_insert_dev_scope(u8 device_number, +                struct acpi_device *adev, void *start, void *end, +                struct dmar_dev_scope *devices, int devices_cnt);  extern int dmar_remove_dev_scope(struct dmar_pci_notify_info *info,                   u16 segment, struct dmar_dev_scope *devices,                   int count); @@ -140,6 +143,7 @@ extern int dmar_parse_one_atsr(struct acpi_dmar_header *header, void *arg);  extern int dmar_check_one_atsr(struct acpi_dmar_header *hdr, void *arg);  extern int dmar_release_one_atsr(struct acpi_dmar_header *hdr, void *arg);  extern int dmar_iommu_hotplug(struct dmar_drhd_unit *dmaru, bool insert); +extern int dmar_rmrr_add_acpi_dev(u8 device_number, struct acpi_device *adev);  extern int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info);  #else /* !CONFIG_INTEL_IOMMU: */  static inline int intel_iommu_init(void) { return -ENODEV; } @@ -150,6 +154,11 @@ static inline void intel_iommu_shutdown(void) { }  #define    dmar_check_one_atsr        dmar_res_noop  #define    dmar_release_one_atsr        dmar_res_noop +static inline int dmar_rmrr_add_acpi_dev(u8 device_number, struct acpi_device *adev) +{ +    return 0; +} +  static inline int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)  {      return 0; diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 3ff424d4f481..66ae2b7d65de 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -546,6 +546,9 @@ extern void iommu_domain_window_disable(struct iommu_domain *domain, u32 wnd_nr)  extern int report_iommu_fault(struct iommu_domain *domain, struct device *dev,                    unsigned long iova, int flags); +extern void __acpi_device_create_direct_mappings(struct iommu_group *group, +                        struct device *acpi_device); +  static inline void iommu_flush_iotlb_all(struct iommu_domain *domain)  {      if (domain->ops->flush_iotlb_all) -- 2.20.1
1 0
0 0
[PATCH OLK-5.10] USB:Fix kernel NULL pointer when unbind UHCI form vfio-pci
by LeoLiuoc 09 Jul '21

09 Jul '21
This bug is found in Zhaoxin platform, but it's a commom code bug. Fail sequence: step1: Unbind UHCI controller from native driver; step2: Bind UHCI controller to vfio-pci, which will put UHCI controller in one vfio        group's device list and set UHCI's dev->driver_data to struct vfio-pci(for UHCI) step3: Unbind EHCI controller from native driver, will try to tell UHCI native driver        that "I'm removed by set companion_hcd->self.hs_companion to NULL. However,        companion_hcd get from UHCI's dev->driver_data that has modified by vfio-pci        already.So, the vfio-pci structure will be damaged! step4: Bind EHCI controller to vfio-pci driver, which will put EHCI controller in the        same vfio group as UHCI controller;      ... ... step5: Unbind UHCI controller from vfio-pci, which will delete UHCI from vfio group'        device list that has been damaged in step 3. So,delete operation can random        result into a NULL pointer dereference with the below stack dump. step6: Bind UHCI controller to native driver; step7: Unbind EHCI controller from vfio-pci, which will try to remove EHCI controller        from the vfio group; step8: Bind EHCI controller to native driver; [  929.114641] uhci_hcd 0000:00:10.0: remove, state 1 [ 929.114652] usb usb1: USB disconnect, device number 1 [ 929.114655] usb 1-1: USB disconnect, device number 2 [ 929.270313] usb 1-2: USB disconnect, device number 3 [ 929.318404] uhci_hcd 0000:00:10.0: USB bus 1 deregistered [ 929.343029] uhci_hcd 0000:00:10.1: remove, state 4 [  929.343045] usb usb3: USB disconnect, device number 1 [  929.343685] uhci_hcd 0000:00:10.1: USB bus 3 deregistered [  929.369087] ehci-pci 0000:00:10.7: remove, state 4 [  929.369102] usb usb4: USB disconnect, device number 1 [  929.370325] ehci-pci 0000:00:10.7: USB bus 4 deregistered [  932.398494] BUG: unable to handle kernel NULL pointer dereference at 0000000000000000 [  932.398496] PGD 42a67d067 P4D 42a67d067 PUD 42a65f067 PMD 0 [  932.398502] Oops: 0002 [#2] SMP NOPTI [  932.398505] CPU: 2 PID: 7824 Comm: vfio_unbind.sh Tainted: P D  4.19.65-2020051917-rainos #1 [  932.398506] Hardware name: Shanghai Zhaoxin Semiconductor Co., Ltd. HX002EH/HX002EH,            BIOS HX002EH0_01_R480_R_200408 04/08/2020 [ 932.398513] RIP: 0010:vfio_device_put+0x31/0xa0 [vfio] [ 932.398515] Code: 89 e5 41 54 53 4c 8b 67 18 48 89 fb 49 8d 74 24 30 e8 e3 0e f3 de         84 c0 74 67 48 8b 53 20 48 8b 43 28 48 8b 7b 18 48 89 42 08 <48> 89 10         48 b8 00 01 00 00 00 00 ad de 48 89 43 20 48 b8 00 02 00 [  932.398516] RSP: 0018:ffffbbfd04cffc18 EFLAGS: 00010202 [ 932.398518] RAX: 0000000000000000 RBX: ffff92c7ea717880 RCX: 0000000000000000 [  932.398519] RDX: ffff92c7ea713620 RSI: ffff92c7ea713630 RDI: ffff92c7ea713600 [  932.398521] RBP: ffffbbfd04cffc28 R08: ffff92c7f02a8080 R09: ffff92c7efc03980 [ 932.398522] R10: ffffbbfd04cff9a8 R11: 0000000000000000 R12: ffff92c7ea713600 [  932.398523] R13: ffff92c7ed8bb0a8 R14: ffff92c7ea717880 R15: 0000000000000000 [  932.398525] FS: 00007f3031500740(0000) GS:ffff92c7f0280000(0000) knlGS:0000000000000000 [  932.398526] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [  932.398527] CR2: 0000000000000000 CR3: 0000000428626004 CR4: 0000000000160ee0 [  932.398528] Call Trace: [  932.398534]  vfio_del_group_dev+0xe8/0x2a0 [vfio] [ 932.398539]  ? __blocking_notifier_call_chain+0x52/0x60 [  932.398542]  ? do_wait_intr_irq+0x90/0x90 [  932.398546]  ? iommu_bus_notifier+0x75/0x100 [  932.398551] vfio_pci_remove+0x20/0xa0 [vfio_pci] [  932.398554] pci_device_remove+0x3e/0xc0 [  932.398557] device_release_driver_internal+0x17a/0x240 [  932.398560]  device_release_driver+0x12/0x20 [  932.398561] unbind_store+0xee/0x180 [  932.398564]  drv_attr_store+0x27/0x40 [  932.398567]  sysfs_kf_write+0x3c/0x50 [  932.398568] kernfs_fop_write+0x125/0x1a0 [  932.398572] __vfs_write+0x3a/0x190 [  932.398575]  ? apparmor_file_permission+0x1a/0x20 [  932.398577]  ? security_file_permission+0x3b/0xc0 [  932.398581]  ? _cond_resched+0x1a/0x50 [  932.398582] vfs_write+0xb8/0x1b0 [  932.398584]  ksys_write+0x5c/0xe0 [ 932.398586]  __x64_sys_write+0x1a/0x20 [  932.398589] do_syscall_64+0x5a/0x110 [  932.398592] entry_SYSCALL_64_after_hwframe+0x44/0xa9 Using virt-manager/qemu to boot guest os, we can see the same fail sequence! Fix this by determine whether the PCI Driver of the USB controller is a kernel native driver. If not, do not let it modify UHCI's dev->driver_data. Signed-off-by: LeoLiu-oc <LeoLiu-oc(a)zhaoxin.com> ---  drivers/usb/core/hcd-pci.c | 10 ++++++++++  1 file changed, 10 insertions(+) diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index ec0d6c50610c..000ee7a6731f 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c @@ -49,6 +49,7 @@ static void for_each_companion(struct pci_dev *pdev, struct usb_hcd *hcd,      struct pci_dev        *companion;      struct usb_hcd        *companion_hcd;      unsigned int        slot = PCI_SLOT(pdev->devfn); +    struct pci_driver    *drv;      /*       * Iterate through other PCI functions in the same slot. @@ -61,6 +62,15 @@ static void for_each_companion(struct pci_dev *pdev, struct usb_hcd *hcd,                  PCI_SLOT(companion->devfn) != slot)              continue; +        drv = companion->driver; +        if (!drv) +            continue; + +        if (strncmp(drv->name, "uhci_hcd", sizeof("uhci_hcd") - 1) && +            strncmp(drv->name, "ooci_hcd", sizeof("uhci_hcd") - 1) && +            strncmp(drv->name, "ehci_hcd", sizeof("uhci_hcd") - 1)) +            continue; +          /*           * Companion device should be either UHCI,OHCI or EHCI host           * controller, otherwise skip. -- 2.20.1
1 0
0 0
[PATCH OLK-5.10] xhci: fix issue with resume from system Sx state
by LeoLiuoc 09 Jul '21

09 Jul '21
On Zhaoxin ZX-100 project, xHCI can't work normally after resume from system Sx state. To fix this issue, when resume from system sx state, reinitialize xHCI instead of restore. Signed-off-by: LeoLiu-oc <LeoLiu-oc(a)zhaoxin.com> ---  drivers/usb/host/xhci-pci.c | 3 +++  1 file changed, 3 insertions(+) diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 471cf3e96032..44dd77343cc1 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -307,6 +307,9 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)      if (pdev->vendor == PCI_VENDOR_ID_TI && pdev->device == 0x8241)          xhci->quirks |= XHCI_LIMIT_ENDPOINT_INTERVAL_7; +    if (pdev->vendor == PCI_VENDOR_ID_ZHAOXIN && pdev->device == 0x9202) +        xhci->quirks |= XHCI_RESET_ON_RESUME; +      if ((pdev->vendor == PCI_VENDOR_ID_BROADCOM ||           pdev->vendor == PCI_VENDOR_ID_CAVIUM) &&           pdev->device == 0x9026) -- 2.20.1
1 0
0 0
[PATCH OLK-5.10] xhci: Adjust the UHCI Controllers bit value
by LeoLiuoc 09 Jul '21

09 Jul '21
Over Current condition is not standardized in the UHCI spec. Zhaoxin UHCI controllers report Over Current active off. Intel controllers report it active on, so we'll adjust the bit value. Signed-off-by: LeoLiu-oc <LeoLiu-oc(a)zhaoxin.com> ---  drivers/usb/host/uhci-pci.c | 3 +++  1 file changed, 3 insertions(+) diff --git a/drivers/usb/host/uhci-pci.c b/drivers/usb/host/uhci-pci.c index 9b88745d247f..d90c391d4899 100644 --- a/drivers/usb/host/uhci-pci.c +++ b/drivers/usb/host/uhci-pci.c @@ -134,6 +134,9 @@ static int uhci_pci_init(struct usb_hcd *hcd)      if (to_pci_dev(uhci_dev(uhci))->vendor == PCI_VENDOR_ID_INTEL)          device_set_wakeup_capable(uhci_dev(uhci), true); +    if (to_pci_dev(uhci_dev(uhci))->vendor == PCI_VENDOR_ID_ZHAOXIN) +        uhci->oc_low = 1; +      /* Set up pointers to PCI-specific functions */      uhci->reset_hc = uhci_pci_reset_hc;      uhci->check_and_reset_hc = uhci_pci_check_and_reset_hc; -- 2.20.1
1 0
0 0
[PATCH OLK-5.10 3/3] ALSA: hda: Add support of Zhaoxin NB HDAC codec
by LeoLiuoc 09 Jul '21

09 Jul '21
Add Zhaoxin NB HDAC codec support. Signed-off-by: LeoLiu-oc <LeoLiu-oc(a)zhaoxin.com> ---  sound/pci/hda/patch_hdmi.c | 26 ++++++++++++++++++++++++++  1 file changed, 26 insertions(+) diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 6d2a4dfcfe43..f541aeb4ecca 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -4249,6 +4249,20 @@ static int patch_via_hdmi(struct hda_codec *codec)      return patch_simple_hdmi(codec, VIAHDMI_CVT_NID, VIAHDMI_PIN_NID);  } +/* ZHAOXIN HDMI Implementation */ +static int patch_zx_hdmi(struct hda_codec *codec) +{ +    int err; + +    err = patch_generic_hdmi(codec); +    codec->no_sticky_stream = 1; + +    if (err) +        return err; + +    return 0; +} +  /*   * patch entries   */ @@ -4342,6 +4356,12 @@ HDA_CODEC_ENTRY(0x11069f80, "VX900 HDMI/DP",    patch_via_hdmi),  HDA_CODEC_ENTRY(0x11069f81, "VX900 HDMI/DP",    patch_via_hdmi),  HDA_CODEC_ENTRY(0x11069f84, "VX11 HDMI/DP", patch_generic_hdmi),  HDA_CODEC_ENTRY(0x11069f85, "VX11 HDMI/DP", patch_generic_hdmi), +HDA_CODEC_ENTRY(0x11069f86, "CND001 HDMI/DP", patch_generic_hdmi), +HDA_CODEC_ENTRY(0x11069f87, "CND001 HDMI/DP", patch_generic_hdmi), +HDA_CODEC_ENTRY(0x11069f88, "CHX001 HDMI/DP",    patch_zx_hdmi), +HDA_CODEC_ENTRY(0x11069f89, "CHX001 HDMI/DP",    patch_zx_hdmi), +HDA_CODEC_ENTRY(0x11069f8a, "CHX002 HDMI/DP",    patch_zx_hdmi), +HDA_CODEC_ENTRY(0x11069f8b, "CHX002 HDMI/DP",    patch_zx_hdmi),  HDA_CODEC_ENTRY(0x80860054, "IbexPeak HDMI", patch_i915_cpt_hdmi),  HDA_CODEC_ENTRY(0x80862800, "Geminilake HDMI", patch_i915_glk_hdmi),  HDA_CODEC_ENTRY(0x80862801, "Bearlake HDMI", patch_generic_hdmi), @@ -4369,6 +4389,12 @@ HDA_CODEC_ENTRY(0x80862880, "CedarTrail HDMI",    patch_generic_hdmi),  HDA_CODEC_ENTRY(0x80862882, "Valleyview2 HDMI", patch_i915_byt_hdmi),  HDA_CODEC_ENTRY(0x80862883, "Braswell HDMI", patch_i915_byt_hdmi),  HDA_CODEC_ENTRY(0x808629fb, "Crestline HDMI", patch_generic_hdmi), +HDA_CODEC_ENTRY(0x1d179f86, "CND001 HDMI/DP", patch_generic_hdmi), +HDA_CODEC_ENTRY(0x1d179f87, "CND001 HDMI/DP", patch_generic_hdmi), +HDA_CODEC_ENTRY(0x1d179f88, "CHX001 HDMI/DP",    patch_zx_hdmi), +HDA_CODEC_ENTRY(0x1d179f89, "CHX001 HDMI/DP",    patch_zx_hdmi), +HDA_CODEC_ENTRY(0x1d179f8a, "CHX002 HDMI/DP",    patch_zx_hdmi), +HDA_CODEC_ENTRY(0x1d179f8b, "CHX002 HDMI/DP",    patch_zx_hdmi),  /* special ID for generic HDMI */  HDA_CODEC_ENTRY(HDA_CODEC_ID_GENERIC_HDMI, "Generic HDMI", patch_generic_hdmi),  {} /* terminator */ -- 2.20.1
1 0
0 0
[PATCH OLK-5.10 2/3] ALSA: hda: Add support of Zhaoxin NB HDAC
by LeoLiuoc 09 Jul '21

09 Jul '21
Add the new PCI ID 0x1d17 0x9141/0x9142/0x9144 Zhaoxin NB HDAC support. And add some special initialization for Zhaoxin NB HDAC. Signed-off-by: LeoLiu-oc <LeoLiu-oc(a)zhaoxin.com> ---  sound/pci/hda/hda_controller.c | 17 ++++++++++-  sound/pci/hda/hda_controller.h |  2 ++  sound/pci/hda/hda_intel.c      | 53 +++++++++++++++++++++++++++++++++-  3 files changed, 70 insertions(+), 2 deletions(-) diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c index b972d59eb1ec..d6de0b1fcb66 100644 --- a/sound/pci/hda/hda_controller.c +++ b/sound/pci/hda/hda_controller.c @@ -1057,6 +1057,16 @@ void azx_stop_chip(struct azx *chip)  }  EXPORT_SYMBOL_GPL(azx_stop_chip); +static void azx_rirb_zxdelay(struct azx *chip, int enable) +{ +    if (chip->remap_diu_addr) { +        if (!enable) +            writel(0x0, (char *)chip->remap_diu_addr + 0x490a8); +        else +            writel(0x1000000, (char *)chip->remap_diu_addr + 0x490a8); +    } +} +  /*   * interrupt handler   */ @@ -1116,9 +1126,14 @@ irqreturn_t azx_interrupt(int irq, void *dev_id)              azx_writeb(chip, RIRBSTS, RIRB_INT_MASK);              active = true;              if (status & RIRB_INT_RESPONSE) { -                if (chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND) +                if ((chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND) || +                    (chip->driver_caps & AZX_DCAPS_RIRB_PRE_DELAY)) { +                    azx_rirb_zxdelay(chip, 1);                      udelay(80); +                }                  snd_hdac_bus_update_rirb(bus); +                if (chip->driver_caps & AZX_DCAPS_RIRB_PRE_DELAY) +                    azx_rirb_zxdelay(chip, 0);              }          }      } while (active && ++repeat < 10); diff --git a/sound/pci/hda/hda_controller.h b/sound/pci/hda/hda_controller.h index 68f9668788ea..543b9f75cf42 100644 --- a/sound/pci/hda/hda_controller.h +++ b/sound/pci/hda/hda_controller.h @@ -45,6 +45,7 @@  #define AZX_DCAPS_CORBRP_SELF_CLEAR (1 << 28)    /* CORBRP clears itself after reset */  #define AZX_DCAPS_NO_MSI64      (1 << 29)    /* Stick to 32-bit MSIs */  #define AZX_DCAPS_SEPARATE_STREAM_TAG    (1 << 30) /* capture and playback use separate stream tag */ +#define AZX_DCAPS_RIRB_PRE_DELAY  (1 << 31)  enum {      AZX_SNOOP_TYPE_NONE, @@ -147,6 +148,7 @@ struct azx {      /* GTS present */      unsigned int gts_present:1; +    void __iomem *remap_diu_addr;  #ifdef CONFIG_SND_HDA_DSP_LOADER      struct azx_dev saved_azx_dev; diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 8ff7902ec6e6..5ac2e95fd5fa 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -241,7 +241,8 @@ MODULE_SUPPORTED_DEVICE("{{Intel, ICH6},"               "{VIA, VT8251},"               "{VIA, VT8237A},"               "{ULI, M5461}," -             "{ZX, ZhaoxinHDA}}"); +             "{ZX, ZhaoxinHDA}," +             "{ZX, ZhaoxinHDMI}}");  MODULE_DESCRIPTION("Intel HDA driver");  #if defined(CONFIG_PM) && defined(CONFIG_VGA_SWITCHEROO) @@ -273,6 +274,7 @@ enum {      AZX_DRIVER_CTHDA,      AZX_DRIVER_CMEDIA,      AZX_DRIVER_ZHAOXIN, +    AZX_DRIVER_ZXHDMI,      AZX_DRIVER_GENERIC,      AZX_NUM_DRIVERS, /* keep this as last entry */  }; @@ -390,6 +392,7 @@ static const char * const driver_short_names[] = {      [AZX_DRIVER_CTHDA] = "HDA Creative",      [AZX_DRIVER_CMEDIA] = "HDA C-Media",      [AZX_DRIVER_ZHAOXIN] = "HDA Zhaoxin", +    [AZX_DRIVER_ZXHDMI] = "HDA Zhaoxin GFX",      [AZX_DRIVER_GENERIC] = "HD-Audio Generic",  }; @@ -411,6 +414,29 @@ static void update_pci_byte(struct pci_dev *pci, unsigned int reg,      pci_write_config_byte(pci, reg, data);  } +static int azx_init_chip_zx(struct azx *chip) +{ +    struct snd_card *card = chip->card; +    unsigned int diu_reg; +    struct pci_dev *diu_pci = NULL; + +    diu_pci = pci_get_device(0x1d17, 0x3a03, NULL); +    if (!diu_pci) { +        dev_err(card->dev, "hda no chx001 device.\n"); +        return -ENXIO; +    } +    pci_read_config_dword(diu_pci, PCI_BASE_ADDRESS_0, &diu_reg); +    chip->remap_diu_addr = ioremap(diu_reg, 0x50000); +    dev_info(card->dev, "hda %x %p\n", diu_reg, chip->remap_diu_addr); +    return 0; +} + +static void azx_free_chip_zx(struct azx *chip) +{ +    if (chip->remap_diu_addr) +        iounmap(chip->remap_diu_addr); +} +  static void azx_init_pci(struct azx *chip)  {      int snoop_type = azx_get_snoop_type(chip); @@ -1386,6 +1412,9 @@ static void azx_free(struct azx *chip)      hda->init_failed = 1; /* to be sure */      complete_all(&hda->probe_wait); +    if (chip->driver_type == AZX_DRIVER_ZXHDMI) +        azx_free_chip_zx(chip); +      if (use_vga_switcheroo(hda)) {          if (chip->disabled && hda->probe_continued)              snd_hda_unlock_devices(&chip->bus); @@ -1786,6 +1815,8 @@ static int default_bdl_pos_adj(struct azx *chip)      case AZX_DRIVER_ICH:      case AZX_DRIVER_PCH:          return 1; +    case AZX_DRIVER_ZXHDMI: +        return 128;      default:          return 32;      } @@ -1903,6 +1934,11 @@ static int azx_first_init(struct azx *chip)      }  #endif +    chip->remap_diu_addr = NULL; + +    if (chip->driver_type == AZX_DRIVER_ZXHDMI) +        azx_init_chip_zx(chip); +      err = pci_request_regions(pci, "ICH HD audio");      if (err < 0)          return err; @@ -2011,6 +2047,7 @@ static int azx_first_init(struct azx *chip)              chip->playback_streams = ATIHDMI_NUM_PLAYBACK;              chip->capture_streams = ATIHDMI_NUM_CAPTURE;              break; +        case AZX_DRIVER_ZXHDMI:          case AZX_DRIVER_GENERIC:          default:              chip->playback_streams = ICH6_NUM_PLAYBACK; @@ -2732,6 +2769,13 @@ static const struct pci_device_id azx_ids[] = {      { PCI_DEVICE(0x1106, 0x9170), .driver_data = AZX_DRIVER_GENERIC },      /* VIA GFX VT6122/VX11 */      { PCI_DEVICE(0x1106, 0x9140), .driver_data = AZX_DRIVER_GENERIC }, +    { PCI_DEVICE(0x1106, 0x9141), .driver_data = AZX_DRIVER_GENERIC  }, +    { PCI_DEVICE(0x1106, 0x9142), +      .driver_data = AZX_DRIVER_ZXHDMI | AZX_DCAPS_POSFIX_LPIB | +      AZX_DCAPS_NO_MSI | AZX_DCAPS_RIRB_PRE_DELAY }, +    { PCI_DEVICE(0x1106, 0x9144), +      .driver_data = AZX_DRIVER_ZXHDMI | AZX_DCAPS_POSFIX_LPIB | +      AZX_DCAPS_NO_MSI | AZX_DCAPS_RIRB_PRE_DELAY },      /* SIS966 */      { PCI_DEVICE(0x1039, 0x7502), .driver_data = AZX_DRIVER_SIS },      /* ULI M5461 */ @@ -2787,6 +2831,13 @@ static const struct pci_device_id azx_ids[] = {        .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_HDMI },      /* Zhaoxin */      { PCI_DEVICE(0x1d17, 0x3288), .driver_data = AZX_DRIVER_ZHAOXIN }, +    { PCI_DEVICE(0x1d17, 0x9141), .driver_data = AZX_DRIVER_GENERIC  }, +    { PCI_DEVICE(0x1d17, 0x9142), +      .driver_data = AZX_DRIVER_ZXHDMI | AZX_DCAPS_POSFIX_LPIB | +      AZX_DCAPS_NO_MSI | AZX_DCAPS_RIRB_PRE_DELAY }, +    { PCI_DEVICE(0x1d17, 0x9144), +      .driver_data = AZX_DRIVER_ZXHDMI | AZX_DCAPS_POSFIX_LPIB | +      AZX_DCAPS_NO_MSI | AZX_DCAPS_RIRB_PRE_DELAY },      { 0, }  };  MODULE_DEVICE_TABLE(pci, azx_ids); -- 2.20.1
1 0
0 0
[PATCH OLK-5.10 1/3] ALSA: hda: Add Zhaoxin SB HDAC non snoop path support
by LeoLiuoc 09 Jul '21

09 Jul '21
Add Zhaoxin SB HDAC non snoop path support. Signed-off-by: LeoLiu-oc <LeoLiu-oc(a)zhaoxin.com> ---  sound/pci/hda/hda_intel.c | 13 +++++++++++--  1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 4c8b281c3992..8ff7902ec6e6 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -240,8 +240,8 @@ MODULE_SUPPORTED_DEVICE("{{Intel, ICH6},"               "{ATI, RV770},"               "{VIA, VT8251},"               "{VIA, VT8237A}," -             "{SiS, SIS966}," -             "{ULI, M5461}}"); +             "{ULI, M5461}," +             "{ZX, ZhaoxinHDA}}");  MODULE_DESCRIPTION("Intel HDA driver");  #if defined(CONFIG_PM) && defined(CONFIG_VGA_SWITCHEROO) @@ -1744,6 +1744,15 @@ static void azx_check_snoop_available(struct azx *chip)              snoop = false;      } +    if (azx_get_snoop_type(chip) == AZX_SNOOP_TYPE_NONE && +        chip->driver_type == AZX_DRIVER_ZHAOXIN) { +        u8 val1; + +        pci_read_config_byte(chip->pci, 0x42, &val1); +        if (!(val1 & 0x80) && chip->pci->revision == 0x20) +            snoop = false; +    } +      if (chip->driver_caps & AZX_DCAPS_SNOOP_OFF)          snoop = false; -- 2.20.1
1 0
0 0
[PATCH OLK-5.10 0/3] Add support of Zhaoxin HDAC and codec
by LeoLiuoc 09 Jul '21

09 Jul '21
Zhaoxin have new SB & NB HDAC controller. And have new NB HDAC codec. This patch set add support for them. LeoLiu-oc (3):   ALSA: hda: Add Zhaoxin SB HDAC non snoop path support   ALSA: hda: Add support of Zhaoxin NB HDAC   ALSA: hda: Add support of Zhaoxin NB HDAC codec  sound/pci/hda/hda_controller.c | 17 ++++++++-  sound/pci/hda/hda_controller.h |  2 ++  sound/pci/hda/hda_intel.c      | 64 ++++++++++++++++++++++++++++++++--  sound/pci/hda/patch_hdmi.c     | 26 ++++++++++++++  4 files changed, 106 insertions(+), 3 deletions(-) -- 2.20.1
1 0
0 0
[PATCH OLK-5.10] xhci: Show Zhaoxin XHCI root hub speed correctly
by LeoLiuoc 09 Jul '21

09 Jul '21
Some Zhaoxin xHCI controllers follow usb3.1 spec, but only support gen1 speed 5G. While in Linux kernel, if xHCI suspport usb3.1,root hub speed will show on 10G. To fix this issue, read usb speed ID supported by xHCI to determine root hub speed. Signed-off-by: LeoLiu-oc <LeoLiu-oc(a)zhaoxin.com> ---  drivers/usb/host/xhci.c | 19 +++++++++++++++++++  1 file changed, 19 insertions(+) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index a834f3927bee..e9d67ee299d9 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -5186,6 +5186,7 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)       */      struct device        *dev = hcd->self.sysdev;      unsigned int        minor_rev; +    u8            i, j;      int            retval;      /* Accept arbitrarily long scatter-gather lists */ @@ -5240,6 +5241,24 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)              hcd->self.root_hub->speed = USB_SPEED_SUPER_PLUS;              break;          } + +        /* usb3.1 has gen1 and gen2, Some zx's xHCI controller that follow usb3.1 spec +         * but only support gen1 +         */ +        if (xhci->quirks & XHCI_ZHAOXIN_HOST) { +            minor_rev = 0; +            for (j = 0; j < xhci->num_port_caps; j++) { +                for (i = 0; i < xhci->port_caps[j].psi_count; i++) { +                    if (XHCI_EXT_PORT_PSIV(xhci->port_caps[j].psi[i]) >= 5) +                        minor_rev = 1; +                } +                if (minor_rev != 1) { +                    hcd->speed = HCD_USB3; +                    hcd->self.root_hub->speed = USB_SPEED_SUPER; +                } +            } +        } +          xhci_info(xhci, "Host supports USB 3.%x %sSuperSpeed\n",                minor_rev,                minor_rev ? "Enhanced " : ""); -- 2.20.1
1 0
0 0
[PATCH OLK-5.10] xhci: fix issue of cross page boundary in TRB prefetch
by LeoLiuoc 09 Jul '21

09 Jul '21
On some Zhaoxin platforms, xHCI will prefetch TRB for performance improvement. However this TRB prefetch mechanism may cross page boundary, which may access memory not belong to xHCI. In order to fix this issue, using two pages for TRB allocate and only the first page will be used. Signed-off-by: LeoLiu-oc <LeoLiu-oc(a)zhaoxin.com> ---  drivers/usb/host/xhci-mem.c | 10 +++++++++-  drivers/usb/host/xhci-pci.c |  5 +++++  drivers/usb/host/xhci.h     |  1 +  3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 8ce043e6ed87..67329b4188cf 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -2458,8 +2458,16 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)       * and our use of dma addresses in the trb_address_map radix tree needs       * TRB_SEGMENT_SIZE alignment, so we pick the greater alignment need.       */ -    xhci->segment_pool = dma_pool_create("xHCI ring segments", dev, +    /* With xHCI TRB prefetch patch:To fix cross page boundary access issue +     * in IOV environment +     */ +    if (xhci->quirks & XHCI_ZHAOXIN_TRB_FETCH) { +        xhci->segment_pool = dma_pool_create("xHCI ring segments", dev, +            TRB_SEGMENT_SIZE*2, TRB_SEGMENT_SIZE*2, xhci->page_size*2); +    } else { +        xhci->segment_pool = dma_pool_create("xHCI ring segments", dev,              TRB_SEGMENT_SIZE, TRB_SEGMENT_SIZE, xhci->page_size); +    }      /* See Table 46 and Note on Figure 55 */      xhci->device_pool = dma_pool_create("xHCI input/output contexts", dev, diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index e78316ed99d4..471cf3e96032 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -281,6 +281,11 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)      if (pdev->vendor == PCI_VENDOR_ID_VIA && pdev->device == 0x3483)          xhci->quirks |= XHCI_LPM_SUPPORT; +    if (pdev->vendor == PCI_VENDOR_ID_ZHAOXIN && +        (pdev->device == 0x9202 || +         pdev->device == 0x9203)) +        xhci->quirks |= XHCI_ZHAOXIN_TRB_FETCH; +      if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA &&          pdev->device == PCI_DEVICE_ID_ASMEDIA_1042_XHCI)          xhci->quirks |= XHCI_BROKEN_STREAMS; diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 576cafb5d873..e215431f927a 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1881,6 +1881,7 @@ struct xhci_hcd {  #define XHCI_SG_TRB_CACHE_SIZE_QUIRK    BIT_ULL(39)  #define XHCI_NO_SOFT_RETRY    BIT_ULL(40)  #define XHCI_ZHAOXIN_HOST    BIT_ULL(41) +#define XHCI_ZHAOXIN_TRB_FETCH    BIT_ULL(42)      unsigned int        num_active_eps;      unsigned int        limit_active_eps; -- 2.20.1
1 0
0 0
  • ← Newer
  • 1
  • ...
  • 1827
  • 1828
  • 1829
  • 1830
  • 1831
  • 1832
  • 1833
  • ...
  • 1930
  • Older →

HyperKitty Powered by HyperKitty