Pull USB fixes from Greg KH: "Here are a bunch of small USB fixes for reported problems and regressions for 6.9-rc2. Included in here are: - deadlock fixes for long-suffering issues - USB phy driver revert for reported problem - typec fixes for reported problems - duplicate id in dwc3 dropped - dwc2 driver fixes - udc driver warning fix - cdc-wdm race bugfix - other tiny USB bugfixes All of these have been in linux-next this past week with no reported issues" * tag 'usb-6.9-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (26 commits) USB: core: Fix deadlock in port "disable" sysfs attribute USB: core: Add hub_get() and hub_put() routines usb: typec: ucsi: Check capabilities before cable and identity discovery usb: typec: ucsi: Clear UCSI_CCI_RESET_COMPLETE before reset usb: typec: ucsi_acpi: Refactor and fix DELL quirk usb: typec: ucsi: Ack unsupported commands usb: typec: ucsi: Check for notifications after init usb: typec: ucsi: Clear EVENT_PENDING under PPM lock usb: typec: Return size of buffer if pd_set operation succeeds usb: udc: remove warning when queue disabled ep usb: dwc3: pci: Drop duplicate ID usb: dwc3: Properly set system wakeup Revert "usb: phy: generic: Get the vbus supply" usb: cdc-wdm: close race between read and workqueue usb: dwc2: gadget: LPM flow fix usb: dwc2: gadget: Fix exiting from clock gating usb: dwc2: host: Fix ISOC flow in DDMA mode usb: dwc2: host: Fix remote wakeup from hibernation usb: dwc2: host: Fix hibernation flow USB: core: Fix deadlock in usb_deauthorize_interface() ...
Unified · Split
| @@ -485,6 +485,7 @@ out_free_mem: · 484 unmodified lines | |||
| 485 | static int service_outstanding_interrupt(struct wdm_device *desc) | 485 | static int service_outstanding_interrupt(struct wdm_device *desc) |
| 486 | { | 486 | { |
| 487 | int rv = 0; | 487 | int rv = 0; |
| 488 | int used; | ||
| 488 | 489 | ||
| 489 | /* submit read urb only if the device is waiting for it */ | 490 | /* submit read urb only if the device is waiting for it */ |
| 490 | if (!desc->resp_count || !--desc->resp_count) | 491 | if (!desc->resp_count || !--desc->resp_count) |
| @@ -499,7 +500,10 @@ static int service_outstanding_interrupt(struct wdm_device *desc) · 8 unmodified lines | |||
| 499 | goto out; | 500 | goto out; |
| 500 | } | 501 | } |
| 501 | 502 | ||
| 502 | set_bit(WDM_RESPONDING, &desc->flags); | 503 | used = test_and_set_bit(WDM_RESPONDING, &desc->flags); |
| 504 | if (used) | ||
| 505 | goto out; | ||
| 506 | |||
| 503 | spin_unlock_irq(&desc->iuspin); | 507 | spin_unlock_irq(&desc->iuspin); |
| 504 | rv = usb_submit_urb(desc->response, GFP_KERNEL); | 508 | rv = usb_submit_urb(desc->response, GFP_KERNEL); |
| 505 | spin_lock_irq(&desc->iuspin); | 509 | spin_lock_irq(&desc->iuspin); |
| @@ -130,7 +130,6 @@ EXPORT_SYMBOL_GPL(ehci_cf_port_reset_rwsem); · 129 unmodified lines | |||
| 130 | #define HUB_DEBOUNCE_STEP 25 | 130 | #define HUB_DEBOUNCE_STEP 25 |
| 131 | #define HUB_DEBOUNCE_STABLE 100 | 131 | #define HUB_DEBOUNCE_STABLE 100 |
| 132 | 132 | ||
| 133 | static void hub_release(struct kref *kref); | ||
| 134 | static int usb_reset_and_verify_device(struct usb_device *udev); | 133 | static int usb_reset_and_verify_device(struct usb_device *udev); |
| 135 | static int hub_port_disable(struct usb_hub *hub, int port1, int set_state); | 134 | static int hub_port_disable(struct usb_hub *hub, int port1, int set_state); |
| 136 | static bool hub_port_warm_reset_required(struct usb_hub *hub, int port1, | 135 | static bool hub_port_warm_reset_required(struct usb_hub *hub, int port1, |
| @@ -720,14 +719,14 @@ static void kick_hub_wq(struct usb_hub *hub) · 583 unmodified lines | |||
| 720 | */ | 719 | */ |
| 721 | intf = to_usb_interface(hub->intfdev); | 720 | intf = to_usb_interface(hub->intfdev); |
| 722 | usb_autopm_get_interface_no_resume(intf); | 721 | usb_autopm_get_interface_no_resume(intf); |
| 723 | kref_get(&hub->kref); | 722 | hub_get(hub); |
| 724 | 723 | ||
| 725 | if (queue_work(hub_wq, &hub->events)) | 724 | if (queue_work(hub_wq, &hub->events)) |
| 726 | return; | 725 | return; |
| 727 | 726 | ||
| 728 | /* the work has already been scheduled */ | 727 | /* the work has already been scheduled */ |
| 729 | usb_autopm_put_interface_async(intf); | 728 | usb_autopm_put_interface_async(intf); |
| 730 | kref_put(&hub->kref, hub_release); | 729 | hub_put(hub); |
| 731 | } | 730 | } |
| 732 | 731 | ||
| 733 | void usb_kick_hub_wq(struct usb_device *hdev) | 732 | void usb_kick_hub_wq(struct usb_device *hdev) |
| @@ -1095,7 +1094,7 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) · 361 unmodified lines | |||
| 1095 | goto init2; | 1094 | goto init2; |
| 1096 | goto init3; | 1095 | goto init3; |
| 1097 | } | 1096 | } |
| 1098 | kref_get(&hub->kref); | 1097 | hub_get(hub); |
| 1099 | 1098 | ||
| 1100 | /* The superspeed hub except for root hub has to use Hub Depth | 1099 | /* The superspeed hub except for root hub has to use Hub Depth |
| 1101 | * value as an offset into the route string to locate the bits | 1100 | * value as an offset into the route string to locate the bits |
| @@ -1343,7 +1342,7 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) · 241 unmodified lines | |||
| 1343 | device_unlock(&hdev->dev); | 1342 | device_unlock(&hdev->dev); |
| 1344 | } | 1343 | } |
| 1345 | 1344 | ||
| 1346 | kref_put(&hub->kref, hub_release); | 1345 | hub_put(hub); |
| 1347 | } | 1346 | } |
| 1348 | 1347 | ||
| 1349 | /* Implement the continuations for the delays above */ | 1348 | /* Implement the continuations for the delays above */ |
| @@ -1759,6 +1758,16 @@ static void hub_release(struct kref *kref) · 409 unmodified lines | |||
| 1759 | kfree(hub); | 1758 | kfree(hub); |
| 1760 | } | 1759 | } |
| 1761 | 1760 | ||
| 1761 | void hub_get(struct usb_hub *hub) | ||
| 1762 | { | ||
| 1763 | kref_get(&hub->kref); | ||
| 1764 | } | ||
| 1765 | |||
| 1766 | void hub_put(struct usb_hub *hub) | ||
| 1767 | { | ||
| 1768 | kref_put(&hub->kref, hub_release); | ||
| 1769 | } | ||
| 1770 | |||
| 1762 | static unsigned highspeed_hubs; | 1771 | static unsigned highspeed_hubs; |
| 1763 | 1772 | ||
| 1764 | static void hub_disconnect(struct usb_interface *intf) | 1773 | static void hub_disconnect(struct usb_interface *intf) |
| @@ -1807,7 +1816,7 @@ static void hub_disconnect(struct usb_interface *intf) · 42 unmodified lines | |||
| 1807 | 1816 | ||
| 1808 | onboard_hub_destroy_pdevs(&hub->onboard_hub_devs); | 1817 | onboard_hub_destroy_pdevs(&hub->onboard_hub_devs); |
| 1809 | 1818 | ||
| 1810 | kref_put(&hub->kref, hub_release); | 1819 | hub_put(hub); |
| 1811 | } | 1820 | } |
| 1812 | 1821 | ||
| 1813 | static bool hub_descriptor_is_sane(struct usb_host_interface *desc) | 1822 | static bool hub_descriptor_is_sane(struct usb_host_interface *desc) |
| @@ -5934,7 +5943,7 @@ out_hdev_lock: · 4120 unmodified lines | |||
| 5934 | 5943 | ||
| 5935 | /* Balance the stuff in kick_hub_wq() and allow autosuspend */ | 5944 | /* Balance the stuff in kick_hub_wq() and allow autosuspend */ |
| 5936 | usb_autopm_put_interface(intf); | 5945 | usb_autopm_put_interface(intf); |
| 5937 | kref_put(&hub->kref, hub_release); | 5946 | hub_put(hub); |
| 5938 | 5947 | ||
| 5939 | kcov_remote_stop(); | 5948 | kcov_remote_stop(); |
| 5940 | } | 5949 | } |
| @@ -129,6 +129,8 @@ extern void usb_hub_remove_port_device(struct usb_hub *hub, · 128 unmodified lines | |||
| 129 | extern int usb_hub_set_port_power(struct usb_device *hdev, struct usb_hub *hub, | 129 | extern int usb_hub_set_port_power(struct usb_device *hdev, struct usb_hub *hub, |
| 130 | int port1, bool set); | 130 | int port1, bool set); |
| 131 | extern struct usb_hub *usb_hub_to_struct_hub(struct usb_device *hdev); | 131 | extern struct usb_hub *usb_hub_to_struct_hub(struct usb_device *hdev); |
| 132 | extern void hub_get(struct usb_hub *hub); | ||
| 133 | extern void hub_put(struct usb_hub *hub); | ||
| 132 | extern int hub_port_debounce(struct usb_hub *hub, int port1, | 134 | extern int hub_port_debounce(struct usb_hub *hub, int port1, |
| 133 | bool must_be_connected); | 135 | bool must_be_connected); |
| 134 | extern int usb_clear_port_feature(struct usb_device *hdev, | 136 | extern int usb_clear_port_feature(struct usb_device *hdev, |
| @@ -56,11 +56,22 @@ static ssize_t disable_show(struct device *dev, · 55 unmodified lines | |||
| 56 | u16 portstatus, unused; | 56 | u16 portstatus, unused; |
| 57 | bool disabled; | 57 | bool disabled; |
| 58 | int rc; | 58 | int rc; |
| 59 | struct kernfs_node *kn; | ||
| 59 | 60 | ||
| 61 | hub_get(hub); | ||
| 60 | rc = usb_autopm_get_interface(intf); | 62 | rc = usb_autopm_get_interface(intf); |
| 61 | if (rc < 0) | 63 | if (rc < 0) |
| 62 | return rc; | 64 | goto out_hub_get; |
| 63 | 65 | ||
| 66 | /* | ||
| 67 | * Prevent deadlock if another process is concurrently | ||
| 68 | * trying to unregister hdev. | ||
| 69 | */ | ||
| 70 | kn = sysfs_break_active_protection(&dev->kobj, &attr->attr); | ||
| 71 | if (!kn) { | ||
| 72 | rc = -ENODEV; | ||
| 73 | goto out_autopm; | ||
| 74 | } | ||
| 64 | usb_lock_device(hdev); | 75 | usb_lock_device(hdev); |
| 65 | if (hub->disconnected) { | 76 | if (hub->disconnected) { |
| 66 | rc = -ENODEV; | 77 | rc = -ENODEV; |
| @@ -70,9 +81,13 @@ static ssize_t disable_show(struct device *dev, · 3 unmodified lines | |||
| 70 | usb_hub_port_status(hub, port1, &portstatus, &unused); | 81 | usb_hub_port_status(hub, port1, &portstatus, &unused); |
| 71 | disabled = !usb_port_is_power_on(hub, portstatus); | 82 | disabled = !usb_port_is_power_on(hub, portstatus); |
| 72 | 83 | ||
| 73 | out_hdev_lock: | 84 | out_hdev_lock: |
| 74 | usb_unlock_device(hdev); | 85 | usb_unlock_device(hdev); |
| 86 | sysfs_unbreak_active_protection(kn); | ||
| 87 | out_autopm: | ||
| 75 | usb_autopm_put_interface(intf); | 88 | usb_autopm_put_interface(intf); |
| 89 | out_hub_get: | ||
| 90 | hub_put(hub); | ||
| 76 | 91 | ||
| 77 | if (rc) | 92 | if (rc) |
| 78 | return rc; | 93 | return rc; |
| @@ -90,15 +105,26 @@ static ssize_t disable_store(struct device *dev, struct device_attribute *attr, · 11 unmodified lines | |||
| 90 | int port1 = port_dev->portnum; | 105 | int port1 = port_dev->portnum; |
| 91 | bool disabled; | 106 | bool disabled; |
| 92 | int rc; | 107 | int rc; |
| 108 | struct kernfs_node *kn; | ||
| 93 | 109 | ||
| 94 | rc = kstrtobool(buf, &disabled); | 110 | rc = kstrtobool(buf, &disabled); |
| 95 | if (rc) | 111 | if (rc) |
| 96 | return rc; | 112 | return rc; |
| 97 | 113 | ||
| 114 | hub_get(hub); | ||
| 98 | rc = usb_autopm_get_interface(intf); | 115 | rc = usb_autopm_get_interface(intf); |
| 99 | if (rc < 0) | 116 | if (rc < 0) |
| 100 | return rc; | 117 | goto out_hub_get; |
| 101 | 118 | ||
| 119 | /* | ||
| 120 | * Prevent deadlock if another process is concurrently | ||
| 121 | * trying to unregister hdev. | ||
| 122 | */ | ||
| 123 | kn = sysfs_break_active_protection(&dev->kobj, &attr->attr); | ||
| 124 | if (!kn) { | ||
| 125 | rc = -ENODEV; | ||
| 126 | goto out_autopm; | ||
| 127 | } | ||
| 102 | usb_lock_device(hdev); | 128 | usb_lock_device(hdev); |
| 103 | if (hub->disconnected) { | 129 | if (hub->disconnected) { |
| 104 | rc = -ENODEV; | 130 | rc = -ENODEV; |
| @@ -119,9 +145,13 @@ static ssize_t disable_store(struct device *dev, struct device_attribute *attr, · 14 unmodified lines | |||
| 119 | if (!rc) | 145 | if (!rc) |
| 120 | rc = count; | 146 | rc = count; |
| 121 | 147 | ||
| 122 | out_hdev_lock: | 148 | out_hdev_lock: |
| 123 | usb_unlock_device(hdev); | 149 | usb_unlock_device(hdev); |
| 150 | sysfs_unbreak_active_protection(kn); | ||
| 151 | out_autopm: | ||
| 124 | usb_autopm_put_interface(intf); | 152 | usb_autopm_put_interface(intf); |
| 153 | out_hub_get: | ||
| 154 | hub_put(hub); | ||
| 125 | 155 | ||
| 126 | return rc; | 156 | return rc; |
| 127 | } | 157 | } |
| @@ -1217,14 +1217,24 @@ static ssize_t interface_authorized_store(struct device *dev, · 1216 unmodified lines | |||
| 1217 | { | 1217 | { |
| 1218 | struct usb_interface *intf = to_usb_interface(dev); | 1218 | struct usb_interface *intf = to_usb_interface(dev); |
| 1219 | bool val; | 1219 | bool val; |
| 1220 | struct kernfs_node *kn; | ||
| 1220 | 1221 | ||
| 1221 | if (kstrtobool(buf, &val) != 0) | 1222 | if (kstrtobool(buf, &val) != 0) |
| 1222 | return -EINVAL; | 1223 | return -EINVAL; |
| 1223 | 1224 | ||
| 1224 | if (val) | 1225 | if (val) { |
| 1225 | usb_authorize_interface(intf); | 1226 | usb_authorize_interface(intf); |
| 1226 | else | 1227 | } else { |
| 1227 | usb_deauthorize_interface(intf); | 1228 | /* |
| 1229 | * Prevent deadlock if another process is concurrently | ||
| 1230 | * trying to unregister intf. | ||
| 1231 | */ | ||
| 1232 | kn = sysfs_break_active_protection(&dev->kobj, &attr->attr); | ||
| 1233 | if (kn) { | ||
| 1234 | usb_deauthorize_interface(intf); | ||
| 1235 | sysfs_unbreak_active_protection(kn); | ||
| 1236 | } | ||
| 1237 | } | ||
| 1228 | 1238 | ||
| 1229 | return count; | 1239 | return count; |
| 1230 | } | 1240 | } |
| @@ -729,8 +729,14 @@ struct dwc2_dregs_backup { · 728 unmodified lines | |||
| 729 | * struct dwc2_hregs_backup - Holds host registers state before | 729 | * struct dwc2_hregs_backup - Holds host registers state before |
| 730 | * entering partial power down | 730 | * entering partial power down |
| 731 | * @hcfg: Backup of HCFG register | 731 | * @hcfg: Backup of HCFG register |
| 732 | * @hflbaddr: Backup of HFLBADDR register | ||
| 732 | * @haintmsk: Backup of HAINTMSK register | 733 | * @haintmsk: Backup of HAINTMSK register |
| 734 | * @hcchar: Backup of HCCHAR register | ||
| 735 | * @hcsplt: Backup of HCSPLT register | ||
| 733 | * @hcintmsk: Backup of HCINTMSK register | 736 | * @hcintmsk: Backup of HCINTMSK register |
| 737 | * @hctsiz: Backup of HCTSIZ register | ||
| 738 | * @hdma: Backup of HCDMA register | ||
| 739 | * @hcdmab: Backup of HCDMAB register | ||
| 734 | * @hprt0: Backup of HPTR0 register | 740 | * @hprt0: Backup of HPTR0 register |
| 735 | * @hfir: Backup of HFIR register | 741 | * @hfir: Backup of HFIR register |
| 736 | * @hptxfsiz: Backup of HPTXFSIZ register | 742 | * @hptxfsiz: Backup of HPTXFSIZ register |
| @@ -738,8 +744,14 @@ struct dwc2_dregs_backup { · 1 unmodified line | |||
| 738 | */ | 744 | */ |
| 739 | struct dwc2_hregs_backup { | 745 | struct dwc2_hregs_backup { |
| 740 | u32 hcfg; | 746 | u32 hcfg; |
| 747 | u32 hflbaddr; | ||
| 741 | u32 haintmsk; | 748 | u32 haintmsk; |
| 749 | u32 hcchar[MAX_EPS_CHANNELS]; | ||
| 750 | u32 hcsplt[MAX_EPS_CHANNELS]; | ||
| 742 | u32 hcintmsk[MAX_EPS_CHANNELS]; | 751 | u32 hcintmsk[MAX_EPS_CHANNELS]; |
| 752 | u32 hctsiz[MAX_EPS_CHANNELS]; | ||
| 753 | u32 hcidma[MAX_EPS_CHANNELS]; | ||
| 754 | u32 hcidmab[MAX_EPS_CHANNELS]; | ||
| 743 | u32 hprt0; | 755 | u32 hprt0; |
| 744 | u32 hfir; | 756 | u32 hfir; |
| 745 | u32 hptxfsiz; | 757 | u32 hptxfsiz; |
| @@ -1086,6 +1098,7 @@ struct dwc2_hsotg { · 340 unmodified lines | |||
| 1086 | bool needs_byte_swap; | 1098 | bool needs_byte_swap; |
| 1087 | 1099 | ||
| 1088 | /* DWC OTG HW Release versions */ | 1100 | /* DWC OTG HW Release versions */ |
| 1101 | #define DWC2_CORE_REV_4_30a 0x4f54430a | ||
| 1089 | #define DWC2_CORE_REV_2_71a 0x4f54271a | 1102 | #define DWC2_CORE_REV_2_71a 0x4f54271a |
| 1090 | #define DWC2_CORE_REV_2_72a 0x4f54272a | 1103 | #define DWC2_CORE_REV_2_72a 0x4f54272a |
| 1091 | #define DWC2_CORE_REV_2_80a 0x4f54280a | 1104 | #define DWC2_CORE_REV_2_80a 0x4f54280a |
| @@ -1323,6 +1336,7 @@ int dwc2_backup_global_registers(struct dwc2_hsotg *hsotg); · 231 unmodified lines | |||
| 1323 | int dwc2_restore_global_registers(struct dwc2_hsotg *hsotg); | 1336 | int dwc2_restore_global_registers(struct dwc2_hsotg *hsotg); |
| 1324 | 1337 | ||
| 1325 | void dwc2_enable_acg(struct dwc2_hsotg *hsotg); | 1338 | void dwc2_enable_acg(struct dwc2_hsotg *hsotg); |
| 1339 | void dwc2_wakeup_from_lpm_l1(struct dwc2_hsotg *hsotg, bool remotewakeup); | ||
| 1326 | 1340 | ||
| 1327 | /* This function should be called on every hardware interrupt. */ | 1341 | /* This function should be called on every hardware interrupt. */ |
| 1328 | irqreturn_t dwc2_handle_common_intr(int irq, void *dev); | 1342 | irqreturn_t dwc2_handle_common_intr(int irq, void *dev); |
| @@ -297,7 +297,8 @@ static void dwc2_handle_session_req_intr(struct dwc2_hsotg *hsotg) · 296 unmodified lines | |||
| 297 | 297 | ||
| 298 | /* Exit gadget mode clock gating. */ | 298 | /* Exit gadget mode clock gating. */ |
| 299 | if (hsotg->params.power_down == | 299 | if (hsotg->params.power_down == |
| 300 | DWC2_POWER_DOWN_PARAM_NONE && hsotg->bus_suspended) | 300 | DWC2_POWER_DOWN_PARAM_NONE && hsotg->bus_suspended && |
| 301 | !hsotg->params.no_clock_gating) | ||
| 301 | dwc2_gadget_exit_clock_gating(hsotg, 0); | 302 | dwc2_gadget_exit_clock_gating(hsotg, 0); |
| 302 | } | 303 | } |
| 303 | 304 | ||
| @@ -322,10 +323,11 @@ static void dwc2_handle_session_req_intr(struct dwc2_hsotg *hsotg) · 18 unmodified lines | |||
| 322 | * @hsotg: Programming view of DWC_otg controller | 323 | * @hsotg: Programming view of DWC_otg controller |
| 323 | * | 324 | * |
| 324 | */ | 325 | */ |
| 325 | static void dwc2_wakeup_from_lpm_l1(struct dwc2_hsotg *hsotg) | 326 | void dwc2_wakeup_from_lpm_l1(struct dwc2_hsotg *hsotg, bool remotewakeup) |
| 326 | { | 327 | { |
| 327 | u32 glpmcfg; | 328 | u32 glpmcfg; |
| 328 | u32 i = 0; | 329 | u32 pcgctl; |
| 330 | u32 dctl; | ||
| 329 | 331 | ||
| 330 | if (hsotg->lx_state != DWC2_L1) { | 332 | if (hsotg->lx_state != DWC2_L1) { |
| 331 | dev_err(hsotg->dev, "Core isn't in DWC2_L1 state\n"); | 333 | dev_err(hsotg->dev, "Core isn't in DWC2_L1 state\n"); |
| @@ -334,37 +336,57 @@ static void dwc2_wakeup_from_lpm_l1(struct dwc2_hsotg *hsotg) · 2 unmodified lines | |||
| 334 | 336 | ||
| 335 | glpmcfg = dwc2_readl(hsotg, GLPMCFG); | 337 | glpmcfg = dwc2_readl(hsotg, GLPMCFG); |
| 336 | if (dwc2_is_device_mode(hsotg)) { | 338 | if (dwc2_is_device_mode(hsotg)) { |
| 337 | dev_dbg(hsotg->dev, "Exit from L1 state\n"); | 339 | dev_dbg(hsotg->dev, "Exit from L1 state, remotewakeup=%d\n", remotewakeup); |
| 338 | glpmcfg &= ~GLPMCFG_ENBLSLPM; | 340 | glpmcfg &= ~GLPMCFG_ENBLSLPM; |
| 339 | glpmcfg &= ~GLPMCFG_HIRD_THRES_EN; | 341 | glpmcfg &= ~GLPMCFG_HIRD_THRES_MASK; |
| 340 | dwc2_writel(hsotg, glpmcfg, GLPMCFG); | 342 | dwc2_writel(hsotg, glpmcfg, GLPMCFG); |
| 341 | 343 | ||
| 342 | do { | 344 | pcgctl = dwc2_readl(hsotg, PCGCTL); |
| 343 | glpmcfg = dwc2_readl(hsotg, GLPMCFG); | 345 | pcgctl &= ~PCGCTL_ENBL_SLEEP_GATING; |
| 346 | dwc2_writel(hsotg, pcgctl, PCGCTL); | ||
| 344 | 347 | ||
| 345 | if (!(glpmcfg & (GLPMCFG_COREL1RES_MASK | | 348 | glpmcfg = dwc2_readl(hsotg, GLPMCFG); |
| 346 | GLPMCFG_L1RESUMEOK | GLPMCFG_SLPSTS))) | 349 | if (glpmcfg & GLPMCFG_ENBESL) { |
| 347 | break; | 350 | glpmcfg |= GLPMCFG_RSTRSLPSTS; |
| 351 | dwc2_writel(hsotg, glpmcfg, GLPMCFG); | ||
| 352 | } | ||
| 353 | |||
| 354 | if (remotewakeup) { | ||
| 355 | if (dwc2_hsotg_wait_bit_set(hsotg, GLPMCFG, GLPMCFG_L1RESUMEOK, 1000)) { | ||
| 356 | dev_warn(hsotg->dev, "%s: timeout GLPMCFG_L1RESUMEOK\n", __func__); | ||
| 357 | goto fail; | ||
| 358 | return; | ||
| 359 | } | ||
| 360 | |||
| 361 | dctl = dwc2_readl(hsotg, DCTL); | ||
| 362 | dctl |= DCTL_RMTWKUPSIG; | ||
| 363 | dwc2_writel(hsotg, dctl, DCTL); | ||
| 348 | 364 | ||
| 349 | udelay(1); | 365 | if (dwc2_hsotg_wait_bit_set(hsotg, GINTSTS, GINTSTS_WKUPINT, 1000)) { |
| 350 | } while (++i < 200); | 366 | dev_warn(hsotg->dev, "%s: timeout GINTSTS_WKUPINT\n", __func__); |
| 367 | goto fail; | ||
| 368 | return; | ||
| 369 | } | ||
| 370 | } | ||
| 351 | 371 | ||
| 352 | if (i == 200) { | 372 | glpmcfg = dwc2_readl(hsotg, GLPMCFG); |
| 353 | dev_err(hsotg->dev, "Failed to exit L1 sleep state in 200us.\n"); | 373 | if (glpmcfg & GLPMCFG_COREL1RES_MASK || glpmcfg & GLPMCFG_SLPSTS || |
| 374 | glpmcfg & GLPMCFG_L1RESUMEOK) { | ||
| 375 | goto fail; | ||
| 354 | return; | 376 | return; |
| 355 | } | 377 | } |
| 356 | dwc2_gadget_init_lpm(hsotg); | 378 | |
| 379 | /* Inform gadget to exit from L1 */ | ||
| 380 | call_gadget(hsotg, resume); | ||
| 381 | /* Change to L0 state */ | ||
| 382 | hsotg->lx_state = DWC2_L0; | ||
| 383 | hsotg->bus_suspended = false; | ||
| 384 | fail: dwc2_gadget_init_lpm(hsotg); | ||
| 357 | } else { | 385 | } else { |
| 358 | /* TODO */ | 386 | /* TODO */ |
| 359 | dev_err(hsotg->dev, "Host side LPM is not supported.\n"); | 387 | dev_err(hsotg->dev, "Host side LPM is not supported.\n"); |
| 360 | return; | 388 | return; |
| 361 | } | 389 | } |
| 362 | |||
| 363 | /* Change to L0 state */ | ||
| 364 | hsotg->lx_state = DWC2_L0; | ||
| 365 | |||
| 366 | /* Inform gadget to exit from L1 */ | ||
| 367 | call_gadget(hsotg, resume); | ||
| 368 | } | 390 | } |
| 369 | 391 | ||
| 370 | /* | 392 | /* |
| @@ -385,7 +407,7 @@ static void dwc2_handle_wakeup_detected_intr(struct dwc2_hsotg *hsotg) · 14 unmodified lines | |||
| 385 | dev_dbg(hsotg->dev, "%s lxstate = %d\n", __func__, hsotg->lx_state); | 407 | dev_dbg(hsotg->dev, "%s lxstate = %d\n", __func__, hsotg->lx_state); |
| 386 | 408 | ||
| 387 | if (hsotg->lx_state == DWC2_L1) { | 409 | if (hsotg->lx_state == DWC2_L1) { |
| 388 | dwc2_wakeup_from_lpm_l1(hsotg); | 410 | dwc2_wakeup_from_lpm_l1(hsotg, false); |
| 389 | return; | 411 | return; |
| 390 | } | 412 | } |
| 391 | 413 | ||
| @@ -408,7 +430,8 @@ static void dwc2_handle_wakeup_detected_intr(struct dwc2_hsotg *hsotg) · 16 unmodified lines | |||
| 408 | 430 | ||
| 409 | /* Exit gadget mode clock gating. */ | 431 | /* Exit gadget mode clock gating. */ |
| 410 | if (hsotg->params.power_down == | 432 | if (hsotg->params.power_down == |
| 411 | DWC2_POWER_DOWN_PARAM_NONE && hsotg->bus_suspended) | 433 | DWC2_POWER_DOWN_PARAM_NONE && hsotg->bus_suspended && |
| 434 | !hsotg->params.no_clock_gating) | ||
| 412 | dwc2_gadget_exit_clock_gating(hsotg, 0); | 435 | dwc2_gadget_exit_clock_gating(hsotg, 0); |
| 413 | } else { | 436 | } else { |
| 414 | /* Change to L0 state */ | 437 | /* Change to L0 state */ |
| @@ -425,7 +448,8 @@ static void dwc2_handle_wakeup_detected_intr(struct dwc2_hsotg *hsotg) · 10 unmodified lines | |||
| 425 | } | 448 | } |
| 426 | 449 | ||
| 427 | if (hsotg->params.power_down == | 450 | if (hsotg->params.power_down == |
| 428 | DWC2_POWER_DOWN_PARAM_NONE && hsotg->bus_suspended) | 451 | DWC2_POWER_DOWN_PARAM_NONE && hsotg->bus_suspended && |
| 452 | !hsotg->params.no_clock_gating) | ||
| 429 | dwc2_host_exit_clock_gating(hsotg, 1); | 453 | dwc2_host_exit_clock_gating(hsotg, 1); |
| 430 | 454 | ||
| 431 | /* | 455 | /* |
| @@ -1415,6 +1415,10 @@ static int dwc2_hsotg_ep_queue(struct usb_ep *ep, struct usb_request *req, · 1414 unmodified lines | |||
| 1415 | ep->name, req, req->length, req->buf, req->no_interrupt, | 1415 | ep->name, req, req->length, req->buf, req->no_interrupt, |
| 1416 | req->zero, req->short_not_ok); | 1416 | req->zero, req->short_not_ok); |
| 1417 | 1417 | ||
| 1418 | if (hs->lx_state == DWC2_L1) { | ||
| 1419 | dwc2_wakeup_from_lpm_l1(hs, true); | ||
| 1420 | } | ||
| 1421 | |||
| 1418 | /* Prevent new request submission when controller is suspended */ | 1422 | /* Prevent new request submission when controller is suspended */ |
| 1419 | if (hs->lx_state != DWC2_L0) { | 1423 | if (hs->lx_state != DWC2_L0) { |
| 1420 | dev_dbg(hs->dev, "%s: submit request only in active state\n", | 1424 | dev_dbg(hs->dev, "%s: submit request only in active state\n", |
| @@ -3727,6 +3731,12 @@ irq_retry: · 2306 unmodified lines | |||
| 3727 | if (hsotg->in_ppd && hsotg->lx_state == DWC2_L2) | 3731 | if (hsotg->in_ppd && hsotg->lx_state == DWC2_L2) |
| 3728 | dwc2_exit_partial_power_down(hsotg, 0, true); | 3732 | dwc2_exit_partial_power_down(hsotg, 0, true); |
| 3729 | 3733 | ||
| 3734 | /* Exit gadget mode clock gating. */ | ||
| 3735 | if (hsotg->params.power_down == | ||
| 3736 | DWC2_POWER_DOWN_PARAM_NONE && hsotg->bus_suspended && | ||
| 3737 | !hsotg->params.no_clock_gating) | ||
| 3738 | dwc2_gadget_exit_clock_gating(hsotg, 0); | ||
| 3739 | |||
| 3730 | hsotg->lx_state = DWC2_L0; | 3740 | hsotg->lx_state = DWC2_L0; |
| 3731 | } | 3741 | } |
| 3732 | 3742 | ||
| @@ -2701,8 +2701,11 @@ enum dwc2_transaction_type dwc2_hcd_select_transactions( · 2700 unmodified lines | |||
| 2701 | hsotg->available_host_channels--; | 2701 | hsotg->available_host_channels--; |
| 2702 | } | 2702 | } |
| 2703 | qh = list_entry(qh_ptr, struct dwc2_qh, qh_list_entry); | 2703 | qh = list_entry(qh_ptr, struct dwc2_qh, qh_list_entry); |
| 2704 | if (dwc2_assign_and_init_hc(hsotg, qh)) | 2704 | if (dwc2_assign_and_init_hc(hsotg, qh)) { |
| 2705 | if (hsotg->params.uframe_sched) | ||
| 2706 | hsotg->available_host_channels++; | ||
| 2705 | break; | 2707 | break; |
| 2708 | } | ||
| 2706 | 2709 | ||
| 2707 | /* | 2710 | /* |
| 2708 | * Move the QH from the periodic ready schedule to the | 2711 | * Move the QH from the periodic ready schedule to the |
| @@ -2735,8 +2738,11 @@ enum dwc2_transaction_type dwc2_hcd_select_transactions( · 26 unmodified lines | |||
| 2735 | hsotg->available_host_channels--; | 2738 | hsotg->available_host_channels--; |
| 2736 | } | 2739 | } |
| 2737 | 2740 | ||
| 2738 | if (dwc2_assign_and_init_hc(hsotg, qh)) | 2741 | if (dwc2_assign_and_init_hc(hsotg, qh)) { |
| 2742 | if (hsotg->params.uframe_sched) | ||
| 2743 | hsotg->available_host_channels++; | ||
| 2739 | break; | 2744 | break; |
| 2745 | } | ||
| 2740 | 2746 | ||
| 2741 | /* | 2747 | /* |
| 2742 | * Move the QH from the non-periodic inactive schedule to the | 2748 | * Move the QH from the non-periodic inactive schedule to the |
| @@ -4143,6 +4149,8 @@ void dwc2_host_complete(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd, · 1400 unmodified lines | |||
| 4143 | urb->actual_length); | 4149 | urb->actual_length); |
| 4144 | 4150 | ||
| 4145 | if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { | 4151 | if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { |
| 4152 | if (!hsotg->params.dma_desc_enable) | ||
| 4153 | urb->start_frame = qtd->qh->start_active_frame; | ||
| 4146 | urb->error_count = dwc2_hcd_urb_get_error_count(qtd->urb); | 4154 | urb->error_count = dwc2_hcd_urb_get_error_count(qtd->urb); |
| 4147 | for (i = 0; i < urb->number_of_packets; ++i) { | 4155 | for (i = 0; i < urb->number_of_packets; ++i) { |
| 4148 | urb->iso_frame_desc[i].actual_length = | 4156 | urb->iso_frame_desc[i].actual_length = |
| @@ -4649,7 +4657,7 @@ static int _dwc2_hcd_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, · 500 unmodified lines | |||
| 4649 | } | 4657 | } |
| 4650 | 4658 | ||
| 4651 | if (hsotg->params.power_down == DWC2_POWER_DOWN_PARAM_NONE && | 4659 | if (hsotg->params.power_down == DWC2_POWER_DOWN_PARAM_NONE && |
| 4652 | hsotg->bus_suspended) { | 4660 | hsotg->bus_suspended && !hsotg->params.no_clock_gating) { |
| 4653 | if (dwc2_is_device_mode(hsotg)) | 4661 | if (dwc2_is_device_mode(hsotg)) |
| 4654 | dwc2_gadget_exit_clock_gating(hsotg, 0); | 4662 | dwc2_gadget_exit_clock_gating(hsotg, 0); |
| 4655 | else | 4663 | else |
| @@ -5406,9 +5414,16 @@ int dwc2_backup_host_registers(struct dwc2_hsotg *hsotg) · 750 unmodified lines | |||
| 5406 | /* Backup Host regs */ | 5414 | /* Backup Host regs */ |
| 5407 | hr = &hsotg->hr_backup; | 5415 | hr = &hsotg->hr_backup; |
| 5408 | hr->hcfg = dwc2_readl(hsotg, HCFG); | 5416 | hr->hcfg = dwc2_readl(hsotg, HCFG); |
| 5417 | hr->hflbaddr = dwc2_readl(hsotg, HFLBADDR); | ||
| 5409 | hr->haintmsk = dwc2_readl(hsotg, HAINTMSK); | 5418 | hr->haintmsk = dwc2_readl(hsotg, HAINTMSK); |
| 5410 | for (i = 0; i < hsotg->params.host_channels; ++i) | 5419 | for (i = 0; i < hsotg->params.host_channels; ++i) { |
| 5420 | hr->hcchar[i] = dwc2_readl(hsotg, HCCHAR(i)); | ||
| 5421 | hr->hcsplt[i] = dwc2_readl(hsotg, HCSPLT(i)); | ||
| 5411 | hr->hcintmsk[i] = dwc2_readl(hsotg, HCINTMSK(i)); | 5422 | hr->hcintmsk[i] = dwc2_readl(hsotg, HCINTMSK(i)); |
| 5423 | hr->hctsiz[i] = dwc2_readl(hsotg, HCTSIZ(i)); | ||
| 5424 | hr->hcidma[i] = dwc2_readl(hsotg, HCDMA(i)); | ||
| 5425 | hr->hcidmab[i] = dwc2_readl(hsotg, HCDMAB(i)); | ||
| 5426 | } | ||
| 5412 | 5427 | ||
| 5413 | hr->hprt0 = dwc2_read_hprt0(hsotg); | 5428 | hr->hprt0 = dwc2_read_hprt0(hsotg); |
| 5414 | hr->hfir = dwc2_readl(hsotg, HFIR); | 5429 | hr->hfir = dwc2_readl(hsotg, HFIR); |
| @@ -5442,10 +5457,17 @@ int dwc2_restore_host_registers(struct dwc2_hsotg *hsotg) · 27 unmodified lines | |||
| 5442 | hr->valid = false; | 5457 | hr->valid = false; |
| 5443 | 5458 | ||
| 5444 | dwc2_writel(hsotg, hr->hcfg, HCFG); | 5459 | dwc2_writel(hsotg, hr->hcfg, HCFG); |
| 5460 | dwc2_writel(hsotg, hr->hflbaddr, HFLBADDR); | ||
| 5445 | dwc2_writel(hsotg, hr->haintmsk, HAINTMSK); | 5461 | dwc2_writel(hsotg, hr->haintmsk, HAINTMSK); |
| 5446 | 5462 | ||
| 5447 | for (i = 0; i < hsotg->params.host_channels; ++i) | 5463 | for (i = 0; i < hsotg->params.host_channels; ++i) { |
| 5464 | dwc2_writel(hsotg, hr->hcchar[i], HCCHAR(i)); | ||
| 5465 | dwc2_writel(hsotg, hr->hcsplt[i], HCSPLT(i)); | ||
| 5448 | dwc2_writel(hsotg, hr->hcintmsk[i], HCINTMSK(i)); | 5466 | dwc2_writel(hsotg, hr->hcintmsk[i], HCINTMSK(i)); |
| 5467 | dwc2_writel(hsotg, hr->hctsiz[i], HCTSIZ(i)); | ||
| 5468 | dwc2_writel(hsotg, hr->hcidma[i], HCDMA(i)); | ||
| 5469 | dwc2_writel(hsotg, hr->hcidmab[i], HCDMAB(i)); | ||
| 5470 | } | ||
| 5449 | 5471 | ||
| 5450 | dwc2_writel(hsotg, hr->hprt0, HPRT0); | 5472 | dwc2_writel(hsotg, hr->hprt0, HPRT0); |
| 5451 | dwc2_writel(hsotg, hr->hfir, HFIR); | 5473 | dwc2_writel(hsotg, hr->hfir, HFIR); |
| @@ -5610,10 +5632,12 @@ int dwc2_host_exit_hibernation(struct dwc2_hsotg *hsotg, int rem_wakeup, · 158 unmodified lines | |||
| 5610 | dwc2_writel(hsotg, hr->hcfg, HCFG); | 5632 | dwc2_writel(hsotg, hr->hcfg, HCFG); |
| 5611 | 5633 | ||
| 5612 | /* De-assert Wakeup Logic */ | 5634 | /* De-assert Wakeup Logic */ |
| 5613 | gpwrdn = dwc2_readl(hsotg, GPWRDN); | 5635 | if (!(rem_wakeup && hsotg->hw_params.snpsid >= DWC2_CORE_REV_4_30a)) { |
| 5614 | gpwrdn &= ~GPWRDN_PMUACTV; | 5636 | gpwrdn = dwc2_readl(hsotg, GPWRDN); |
| 5615 | dwc2_writel(hsotg, gpwrdn, GPWRDN); | 5637 | gpwrdn &= ~GPWRDN_PMUACTV; |
| 5616 | udelay(10); | 5638 | dwc2_writel(hsotg, gpwrdn, GPWRDN); |
| 5639 | udelay(10); | ||
| 5640 | } | ||
| 5617 | 5641 | ||
| 5618 | hprt0 = hr->hprt0; | 5642 | hprt0 = hr->hprt0; |
| 5619 | hprt0 |= HPRT0_PWR; | 5643 | hprt0 |= HPRT0_PWR; |
| @@ -5638,6 +5662,13 @@ int dwc2_host_exit_hibernation(struct dwc2_hsotg *hsotg, int rem_wakeup, · 18 unmodified lines | |||
| 5638 | hprt0 |= HPRT0_RES; | 5662 | hprt0 |= HPRT0_RES; |
| 5639 | dwc2_writel(hsotg, hprt0, HPRT0); | 5663 | dwc2_writel(hsotg, hprt0, HPRT0); |
| 5640 | 5664 | ||
| 5665 | /* De-assert Wakeup Logic */ | ||
| 5666 | if ((rem_wakeup && hsotg->hw_params.snpsid >= DWC2_CORE_REV_4_30a)) { | ||
| 5667 | gpwrdn = dwc2_readl(hsotg, GPWRDN); | ||
| 5668 | gpwrdn &= ~GPWRDN_PMUACTV; | ||
| 5669 | dwc2_writel(hsotg, gpwrdn, GPWRDN); | ||
| 5670 | udelay(10); | ||
| 5671 | } | ||
| 5641 | /* Wait for Resume time and then program HPRT again */ | 5672 | /* Wait for Resume time and then program HPRT again */ |
| 5642 | mdelay(100); | 5673 | mdelay(100); |
| 5643 | hprt0 &= ~HPRT0_RES; | 5674 | hprt0 &= ~HPRT0_RES; |
| @@ -559,7 +559,7 @@ static void dwc2_init_isoc_dma_desc(struct dwc2_hsotg *hsotg, · 558 unmodified lines | |||
| 559 | idx = qh->td_last; | 559 | idx = qh->td_last; |
| 560 | inc = qh->host_interval; | 560 | inc = qh->host_interval; |
| 561 | hsotg->frame_number = dwc2_hcd_get_frame_number(hsotg); | 561 | hsotg->frame_number = dwc2_hcd_get_frame_number(hsotg); |
| 562 | cur_idx = dwc2_frame_list_idx(hsotg->frame_number); | 562 | cur_idx = idx; |
| 563 | next_idx = dwc2_desclist_idx_inc(qh->td_last, inc, qh->dev_speed); | 563 | next_idx = dwc2_desclist_idx_inc(qh->td_last, inc, qh->dev_speed); |
| 564 | 564 | ||
| 565 | /* | 565 | /* |
| @@ -866,6 +866,8 @@ static int dwc2_cmpl_host_isoc_dma_desc(struct dwc2_hsotg *hsotg, · 300 unmodified lines | |||
| 866 | { | 866 | { |
| 867 | struct dwc2_dma_desc *dma_desc; | 867 | struct dwc2_dma_desc *dma_desc; |
| 868 | struct dwc2_hcd_iso_packet_desc *frame_desc; | 868 | struct dwc2_hcd_iso_packet_desc *frame_desc; |
| 869 | u16 frame_desc_idx; | ||
| 870 | struct urb *usb_urb = qtd->urb->priv; | ||
| 869 | u16 remain = 0; | 871 | u16 remain = 0; |
| 870 | int rc = 0; | 872 | int rc = 0; |
| 871 | 873 | ||
| @@ -878,8 +880,11 @@ static int dwc2_cmpl_host_isoc_dma_desc(struct dwc2_hsotg *hsotg, · 6 unmodified lines | |||
| 878 | DMA_FROM_DEVICE); | 880 | DMA_FROM_DEVICE); |
| 879 | 881 | ||
| 880 | dma_desc = &qh->desc_list[idx]; | 882 | dma_desc = &qh->desc_list[idx]; |
| 883 | frame_desc_idx = (idx - qtd->isoc_td_first) & (usb_urb->number_of_packets - 1); | ||
| 881 | 884 | ||
| 882 | frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index_last]; | 885 | frame_desc = &qtd->urb->iso_descs[frame_desc_idx]; |
| 886 | if (idx == qtd->isoc_td_first) | ||
| 887 | usb_urb->start_frame = dwc2_hcd_get_frame_number(hsotg); | ||
| 883 | dma_desc->buf = (u32)(qtd->urb->dma + frame_desc->offset); | 888 | dma_desc->buf = (u32)(qtd->urb->dma + frame_desc->offset); |
| 884 | if (chan->ep_is_in) | 889 | if (chan->ep_is_in) |
| 885 | remain = (dma_desc->status & HOST_DMA_ISOC_NBYTES_MASK) >> | 890 | remain = (dma_desc->status & HOST_DMA_ISOC_NBYTES_MASK) >> |
| @@ -900,7 +905,7 @@ static int dwc2_cmpl_host_isoc_dma_desc(struct dwc2_hsotg *hsotg, · 14 unmodified lines | |||
| 900 | frame_desc->status = 0; | 905 | frame_desc->status = 0; |
| 901 | } | 906 | } |
| 902 | 907 | ||
| 903 | if (++qtd->isoc_frame_index == qtd->urb->packet_count) { | 908 | if (++qtd->isoc_frame_index == usb_urb->number_of_packets) { |
| 904 | /* | 909 | /* |
| 905 | * urb->status is not used for isoc transfers here. The | 910 | * urb->status is not used for isoc transfers here. The |
| 906 | * individual frame_desc status are used instead. | 911 | * individual frame_desc status are used instead. |
| @@ -1005,11 +1010,11 @@ static void dwc2_complete_isoc_xfer_ddma(struct dwc2_hsotg *hsotg, · 98 unmodified lines | |||
| 1005 | return; | 1010 | return; |
| 1006 | idx = dwc2_desclist_idx_inc(idx, qh->host_interval, | 1011 | idx = dwc2_desclist_idx_inc(idx, qh->host_interval, |
| 1007 | chan->speed); | 1012 | chan->speed); |
| 1008 | if (!rc) | 1013 | if (rc == 0) |
| 1009 | continue; | 1014 | continue; |
| 1010 | 1015 | ||
| 1011 | if (rc == DWC2_CMPL_DONE) | 1016 | if (rc == DWC2_CMPL_DONE || rc == DWC2_CMPL_STOP) |
| 1012 | break; | 1017 | goto stop_scan; |
| 1013 | 1018 | ||
| 1014 | /* rc == DWC2_CMPL_STOP */ | 1019 | /* rc == DWC2_CMPL_STOP */ |
| 1015 | 1020 | ||
| @@ -698,7 +698,7 @@ · 697 unmodified lines | |||
| 698 | #define TXSTS_QTOP_TOKEN_MASK (0x3 << 25) | 698 | #define TXSTS_QTOP_TOKEN_MASK (0x3 << 25) |
| 699 | #define TXSTS_QTOP_TOKEN_SHIFT 25 | 699 | #define TXSTS_QTOP_TOKEN_SHIFT 25 |
| 700 | #define TXSTS_QTOP_TERMINATE BIT(24) | 700 | #define TXSTS_QTOP_TERMINATE BIT(24) |
| 701 | #define TXSTS_QSPCAVAIL_MASK (0xff << 16) | 701 | #define TXSTS_QSPCAVAIL_MASK (0x7f << 16) |
| 702 | #define TXSTS_QSPCAVAIL_SHIFT 16 | 702 | #define TXSTS_QSPCAVAIL_SHIFT 16 |
| 703 | #define TXSTS_FSPCAVAIL_MASK (0xffff << 0) | 703 | #define TXSTS_FSPCAVAIL_MASK (0xffff << 0) |
| 704 | #define TXSTS_FSPCAVAIL_SHIFT 0 | 704 | #define TXSTS_FSPCAVAIL_SHIFT 0 |
| @@ -331,7 +331,7 @@ static void dwc2_driver_remove(struct platform_device *dev) · 330 unmodified lines | |||
| 331 | 331 | ||
| 332 | /* Exit clock gating when driver is removed. */ | 332 | /* Exit clock gating when driver is removed. */ |
| 333 | if (hsotg->params.power_down == DWC2_POWER_DOWN_PARAM_NONE && | 333 | if (hsotg->params.power_down == DWC2_POWER_DOWN_PARAM_NONE && |
| 334 | hsotg->bus_suspended) { | 334 | hsotg->bus_suspended && !hsotg->params.no_clock_gating) { |
| 335 | if (dwc2_is_device_mode(hsotg)) | 335 | if (dwc2_is_device_mode(hsotg)) |
| 336 | dwc2_gadget_exit_clock_gating(hsotg, 0); | 336 | dwc2_gadget_exit_clock_gating(hsotg, 0); |
| 337 | else | 337 | else |
| @@ -1519,6 +1519,8 @@ static void dwc3_get_properties(struct dwc3 *dwc) · 1518 unmodified lines | |||
| 1519 | else | 1519 | else |
| 1520 | dwc->sysdev = dwc->dev; | 1520 | dwc->sysdev = dwc->dev; |
| 1521 | 1521 | ||
| 1522 | dwc->sys_wakeup = device_may_wakeup(dwc->sysdev); | ||
| 1523 | |||
| 1522 | ret = device_property_read_string(dev, "usb-psy-name", &usb_psy_name); | 1524 | ret = device_property_read_string(dev, "usb-psy-name", &usb_psy_name); |
| 1523 | if (ret >= 0) { | 1525 | if (ret >= 0) { |
| 1524 | dwc->usb_psy = power_supply_get_by_name(usb_psy_name); | 1526 | dwc->usb_psy = power_supply_get_by_name(usb_psy_name); |
| @@ -1133,6 +1133,7 @@ struct dwc3_scratchpad_array { · 1132 unmodified lines | |||
| 1133 | * 3 - Reserved | 1133 | * 3 - Reserved |
| 1134 | * @dis_metastability_quirk: set to disable metastability quirk. | 1134 | * @dis_metastability_quirk: set to disable metastability quirk. |
| 1135 | * @dis_split_quirk: set to disable split boundary. | 1135 | * @dis_split_quirk: set to disable split boundary. |
| 1136 | * @sys_wakeup: set if the device may do system wakeup. | ||
| 1136 | * @wakeup_configured: set if the device is configured for remote wakeup. | 1137 | * @wakeup_configured: set if the device is configured for remote wakeup. |
| 1137 | * @suspended: set to track suspend event due to U3/L2. | 1138 | * @suspended: set to track suspend event due to U3/L2. |
| 1138 | * @imod_interval: set the interrupt moderation interval in 250ns | 1139 | * @imod_interval: set the interrupt moderation interval in 250ns |
| @@ -1357,6 +1358,7 @@ struct dwc3 { · 218 unmodified lines | |||
| 1357 | 1358 | ||
| 1358 | unsigned dis_split_quirk:1; | 1359 | unsigned dis_split_quirk:1; |
| 1359 | unsigned async_callbacks:1; | 1360 | unsigned async_callbacks:1; |
| 1361 | unsigned sys_wakeup:1; | ||
| 1360 | unsigned wakeup_configured:1; | 1362 | unsigned wakeup_configured:1; |
| 1361 | unsigned suspended:1; | 1363 | unsigned suspended:1; |
| 1362 | 1364 | ||
| @@ -51,7 +51,6 @@ · 50 unmodified lines | |||
| 51 | #define PCI_DEVICE_ID_INTEL_MTLP 0x7ec1 | 51 | #define PCI_DEVICE_ID_INTEL_MTLP 0x7ec1 |
| 52 | #define PCI_DEVICE_ID_INTEL_MTLS 0x7f6f | 52 | #define PCI_DEVICE_ID_INTEL_MTLS 0x7f6f |
| 53 | #define PCI_DEVICE_ID_INTEL_MTL 0x7e7e | 53 | #define PCI_DEVICE_ID_INTEL_MTL 0x7e7e |
| 54 | #define PCI_DEVICE_ID_INTEL_ARLH 0x7ec1 | ||
| 55 | #define PCI_DEVICE_ID_INTEL_ARLH_PCH 0x777e | 54 | #define PCI_DEVICE_ID_INTEL_ARLH_PCH 0x777e |
| 56 | #define PCI_DEVICE_ID_INTEL_TGL 0x9a15 | 55 | #define PCI_DEVICE_ID_INTEL_TGL 0x9a15 |
| 57 | #define PCI_DEVICE_ID_AMD_MR 0x163a | 56 | #define PCI_DEVICE_ID_AMD_MR 0x163a |
| @@ -423,7 +422,6 @@ static const struct pci_device_id dwc3_pci_id_table[] = { · 365 unmodified lines | |||
| 423 | { PCI_DEVICE_DATA(INTEL, MTLP, &dwc3_pci_intel_swnode) }, | 422 | { PCI_DEVICE_DATA(INTEL, MTLP, &dwc3_pci_intel_swnode) }, |
| 424 | { PCI_DEVICE_DATA(INTEL, MTL, &dwc3_pci_intel_swnode) }, | 423 | { PCI_DEVICE_DATA(INTEL, MTL, &dwc3_pci_intel_swnode) }, |
| 425 | { PCI_DEVICE_DATA(INTEL, MTLS, &dwc3_pci_intel_swnode) }, | 424 | { PCI_DEVICE_DATA(INTEL, MTLS, &dwc3_pci_intel_swnode) }, |
| 426 | { PCI_DEVICE_DATA(INTEL, ARLH, &dwc3_pci_intel_swnode) }, | ||
| 427 | { PCI_DEVICE_DATA(INTEL, ARLH_PCH, &dwc3_pci_intel_swnode) }, | 425 | { PCI_DEVICE_DATA(INTEL, ARLH_PCH, &dwc3_pci_intel_swnode) }, |
| 428 | { PCI_DEVICE_DATA(INTEL, TGL, &dwc3_pci_intel_swnode) }, | 426 | { PCI_DEVICE_DATA(INTEL, TGL, &dwc3_pci_intel_swnode) }, |
| 429 | 427 | ||
| @@ -2955,6 +2955,9 @@ static int dwc3_gadget_start(struct usb_gadget *g, · 2954 unmodified lines | |||
| 2955 | dwc->gadget_driver = driver; | 2955 | dwc->gadget_driver = driver; |
| 2956 | spin_unlock_irqrestore(&dwc->lock, flags); | 2956 | spin_unlock_irqrestore(&dwc->lock, flags); |
| 2957 | 2957 | ||
| 2958 | if (dwc->sys_wakeup) | ||
| 2959 | device_wakeup_enable(dwc->sysdev); | ||
| 2960 | |||
| 2958 | return 0; | 2961 | return 0; |
| 2959 | } | 2962 | } |
| 2960 | 2963 | ||
| @@ -2970,6 +2973,9 @@ static int dwc3_gadget_stop(struct usb_gadget *g) · 9 unmodified lines | |||
| 2970 | struct dwc3 *dwc = gadget_to_dwc(g); | 2973 | struct dwc3 *dwc = gadget_to_dwc(g); |
| 2971 | unsigned long flags; | 2974 | unsigned long flags; |
| 2972 | 2975 | ||
| 2976 | if (dwc->sys_wakeup) | ||
| 2977 | device_wakeup_disable(dwc->sysdev); | ||
| 2978 | |||
| 2973 | spin_lock_irqsave(&dwc->lock, flags); | 2979 | spin_lock_irqsave(&dwc->lock, flags); |
| 2974 | dwc->gadget_driver = NULL; | 2980 | dwc->gadget_driver = NULL; |
| 2975 | dwc->max_cfg_eps = 0; | 2981 | dwc->max_cfg_eps = 0; |
| @@ -4651,6 +4657,10 @@ int dwc3_gadget_init(struct dwc3 *dwc) · 1675 unmodified lines | |||
| 4651 | else | 4657 | else |
| 4652 | dwc3_gadget_set_speed(dwc->gadget, dwc->maximum_speed); | 4658 | dwc3_gadget_set_speed(dwc->gadget, dwc->maximum_speed); |
| 4653 | 4659 | ||
| 4660 | /* No system wakeup if no gadget driver bound */ | ||
| 4661 | if (dwc->sys_wakeup) | ||
| 4662 | device_wakeup_disable(dwc->sysdev); | ||
| 4663 | |||
| 4654 | return 0; | 4664 | return 0; |
| 4655 | 4665 | ||
| 4656 | err5: | 4666 | err5: |
| @@ -173,6 +173,14 @@ int dwc3_host_init(struct dwc3 *dwc) · 172 unmodified lines | |||
| 173 | goto err; | 173 | goto err; |
| 174 | } | 174 | } |
| 175 | 175 | ||
| 176 | if (dwc->sys_wakeup) { | ||
| 177 | /* Restore wakeup setting if switched from device */ | ||
| 178 | device_wakeup_enable(dwc->sysdev); | ||
| 179 | |||
| 180 | /* Pass on wakeup setting to the new xhci platform device */ | ||
| 181 | device_init_wakeup(&xhci->dev, true); | ||
| 182 | } | ||
| 183 | |||
| 176 | return 0; | 184 | return 0; |
| 177 | err: | 185 | err: |
| 178 | platform_device_put(xhci); | 186 | platform_device_put(xhci); |
| @@ -181,6 +189,9 @@ err: · 2 unmodified lines | |||
| 181 | 189 | ||
| 182 | void dwc3_host_exit(struct dwc3 *dwc) | 190 | void dwc3_host_exit(struct dwc3 *dwc) |
| 183 | { | 191 | { |
| 192 | if (dwc->sys_wakeup) | ||
| 193 | device_init_wakeup(&dwc->xhci->dev, false); | ||
| 194 | |||
| 184 | platform_device_unregister(dwc->xhci); | 195 | platform_device_unregister(dwc->xhci); |
| 185 | dwc->xhci = NULL; | 196 | dwc->xhci = NULL; |
| 186 | } | 197 | } |
| @@ -292,7 +292,9 @@ int usb_ep_queue(struct usb_ep *ep, · 291 unmodified lines | |||
| 292 | { | 292 | { |
| 293 | int ret = 0; | 293 | int ret = 0; |
| 294 | 294 | ||
| 295 | if (WARN_ON_ONCE(!ep->enabled && ep->address)) { | 295 | if (!ep->enabled && ep->address) { |
| 296 | pr_debug("USB gadget: queue request to disabled ep 0x%x (%s)\n", | ||
| 297 | ep->address, ep->name); | ||
| 296 | ret = -ESHUTDOWN; | 298 | ret = -ESHUTDOWN; |
| 297 | goto out; | 299 | goto out; |
| 298 | } | 300 | } |
| @@ -518,8 +518,10 @@ static int ljca_new_client_device(struct ljca_adapter *adap, u8 type, u8 id, · 517 unmodified lines | |||
| 518 | int ret; | 518 | int ret; |
| 519 | 519 | ||
| 520 | client = kzalloc(sizeof *client, GFP_KERNEL); | 520 | client = kzalloc(sizeof *client, GFP_KERNEL); |
| 521 | if (!client) | 521 | if (!client) { |
| 522 | kfree(data); | ||
| 522 | return -ENOMEM; | 523 | return -ENOMEM; |
| 524 | } | ||
| 523 | 525 | ||
| 524 | client->type = type; | 526 | client->type = type; |
| 525 | client->id = id; | 527 | client->id = id; |
| @@ -535,8 +537,10 @@ static int ljca_new_client_device(struct ljca_adapter *adap, u8 type, u8 id, · 9 unmodified lines | |||
| 535 | auxdev->dev.release = ljca_auxdev_release; | 537 | auxdev->dev.release = ljca_auxdev_release; |
| 536 | 538 | ||
| 537 | ret = auxiliary_device_init(auxdev); | 539 | ret = auxiliary_device_init(auxdev); |
| 538 | if (ret) | 540 | if (ret) { |
| 541 | kfree(data); | ||
| 539 | goto err_free; | 542 | goto err_free; |
| 543 | } | ||
| 540 | 544 | ||
| 541 | ljca_auxdev_acpi_bind(adap, auxdev, adr, id); | 545 | ljca_auxdev_acpi_bind(adap, auxdev, adr, id); |
| 542 | 546 | ||
| @@ -590,12 +594,8 @@ static int ljca_enumerate_gpio(struct ljca_adapter *adap) · 47 unmodified lines | |||
| 590 | valid_pin[i] = get_unaligned_le32(&desc->bank_desc[i].valid_pins); | 594 | valid_pin[i] = get_unaligned_le32(&desc->bank_desc[i].valid_pins); |
| 591 | bitmap_from_arr32(gpio_info->valid_pin_map, valid_pin, gpio_num); | 595 | bitmap_from_arr32(gpio_info->valid_pin_map, valid_pin, gpio_num); |
| 592 | 596 | ||
| 593 | ret = ljca_new_client_device(adap, LJCA_CLIENT_GPIO, 0, "ljca-gpio", | 597 | return ljca_new_client_device(adap, LJCA_CLIENT_GPIO, 0, "ljca-gpio", |
| 594 | gpio_info, LJCA_GPIO_ACPI_ADR); | 598 | gpio_info, LJCA_GPIO_ACPI_ADR); |
| 595 | if (ret) | ||
| 596 | kfree(gpio_info); | ||
| 597 | |||
| 598 | return ret; | ||
| 599 | } | 599 | } |
| 600 | 600 | ||
| 601 | static int ljca_enumerate_i2c(struct ljca_adapter *adap) | 601 | static int ljca_enumerate_i2c(struct ljca_adapter *adap) |
| @@ -629,10 +629,8 @@ static int ljca_enumerate_i2c(struct ljca_adapter *adap) · 27 unmodified lines | |||
| 629 | ret = ljca_new_client_device(adap, LJCA_CLIENT_I2C, i, | 629 | ret = ljca_new_client_device(adap, LJCA_CLIENT_I2C, i, |
| 630 | "ljca-i2c", i2c_info, | 630 | "ljca-i2c", i2c_info, |
| 631 | LJCA_I2C1_ACPI_ADR + i); | 631 | LJCA_I2C1_ACPI_ADR + i); |
| 632 | if (ret) { | 632 | if (ret) |
| 633 | kfree(i2c_info); | ||
| 634 | return ret; | 633 | return ret; |
| 635 | } | ||
| 636 | } | 634 | } |
| 637 | 635 | ||
| 638 | return 0; | 636 | return 0; |
| @@ -669,10 +667,8 @@ static int ljca_enumerate_spi(struct ljca_adapter *adap) · 30 unmodified lines | |||
| 669 | ret = ljca_new_client_device(adap, LJCA_CLIENT_SPI, i, | 667 | ret = ljca_new_client_device(adap, LJCA_CLIENT_SPI, i, |
| 670 | "ljca-spi", spi_info, | 668 | "ljca-spi", spi_info, |
| 671 | LJCA_SPI1_ACPI_ADR + i); | 669 | LJCA_SPI1_ACPI_ADR + i); |
| 672 | if (ret) { | 670 | if (ret) |
| 673 | kfree(spi_info); | ||
| 674 | return ret; | 671 | return ret; |
| 675 | } | ||
| 676 | } | 672 | } |
| 677 | 673 | ||
| 678 | return 0; | 674 | return 0; |
| @@ -262,13 +262,6 @@ int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_generic *nop) · 261 unmodified lines | |||
| 262 | return dev_err_probe(dev, PTR_ERR(nop->vbus_draw), | 262 | return dev_err_probe(dev, PTR_ERR(nop->vbus_draw), |
| 263 | "could not get vbus regulator\n"); | 263 | "could not get vbus regulator\n"); |
| 264 | 264 | ||
| 265 | nop->vbus_draw = devm_regulator_get_exclusive(dev, "vbus"); | ||
| 266 | if (PTR_ERR(nop->vbus_draw) == -ENODEV) | ||
| 267 | nop->vbus_draw = NULL; | ||
| 268 | if (IS_ERR(nop->vbus_draw)) | ||
| 269 | return dev_err_probe(dev, PTR_ERR(nop->vbus_draw), | ||
| 270 | "could not get vbus regulator\n"); | ||
| 271 | |||
| 272 | nop->dev = dev; | 265 | nop->dev = dev; |
| 273 | nop->phy.dev = nop->dev; | 266 | nop->phy.dev = nop->dev; |
| 274 | nop->phy.label = "nop-xceiv"; | 267 | nop->phy.label = "nop-xceiv"; |
| @@ -533,7 +533,7 @@ static struct urb *uas_alloc_cmd_urb(struct uas_dev_info *devinfo, gfp_t gfp, · 532 unmodified lines | |||
| 533 | * daft to me. | 533 | * daft to me. |
| 534 | */ | 534 | */ |
| 535 | 535 | ||
| 536 | static struct urb *uas_submit_sense_urb(struct scsi_cmnd *cmnd, gfp_t gfp) | 536 | static int uas_submit_sense_urb(struct scsi_cmnd *cmnd, gfp_t gfp) |
| 537 | { | 537 | { |
| 538 | struct uas_dev_info *devinfo = cmnd->device->hostdata; | 538 | struct uas_dev_info *devinfo = cmnd->device->hostdata; |
| 539 | struct urb *urb; | 539 | struct urb *urb; |
| @@ -541,30 +541,28 @@ static struct urb *uas_submit_sense_urb(struct scsi_cmnd *cmnd, gfp_t gfp) · 1 unmodified line | |||
| 541 | 541 | ||
| 542 | urb = uas_alloc_sense_urb(devinfo, gfp, cmnd); | 542 | urb = uas_alloc_sense_urb(devinfo, gfp, cmnd); |
| 543 | if (!urb) | 543 | if (!urb) |
| 544 | return NULL; | 544 | return -ENOMEM; |
| 545 | usb_anchor_urb(urb, &devinfo->sense_urbs); | 545 | usb_anchor_urb(urb, &devinfo->sense_urbs); |
| 546 | err = usb_submit_urb(urb, gfp); | 546 | err = usb_submit_urb(urb, gfp); |
| 547 | if (err) { | 547 | if (err) { |
| 548 | usb_unanchor_urb(urb); | 548 | usb_unanchor_urb(urb); |
| 549 | uas_log_cmd_state(cmnd, "sense submit err", err); | 549 | uas_log_cmd_state(cmnd, "sense submit err", err); |
| 550 | usb_free_urb(urb); | 550 | usb_free_urb(urb); |
| 551 | return NULL; | ||
| 552 | } | 551 | } |
| 553 | return urb; | 552 | return err; |
| 554 | } | 553 | } |
| 555 | 554 | ||
| 556 | static int uas_submit_urbs(struct scsi_cmnd *cmnd, | 555 | static int uas_submit_urbs(struct scsi_cmnd *cmnd, |
| 557 | struct uas_dev_info *devinfo) | 556 | struct uas_dev_info *devinfo) |
| 558 | { | 557 | { |
| 559 | struct uas_cmd_info *cmdinfo = scsi_cmd_priv(cmnd); | 558 | struct uas_cmd_info *cmdinfo = scsi_cmd_priv(cmnd); |
| 560 | struct urb *urb; | ||
| 561 | int err; | 559 | int err; |
| 562 | 560 | ||
| 563 | lockdep_assert_held(&devinfo->lock); | 561 | lockdep_assert_held(&devinfo->lock); |
| 564 | if (cmdinfo->state & SUBMIT_STATUS_URB) { | 562 | if (cmdinfo->state & SUBMIT_STATUS_URB) { |
| 565 | urb = uas_submit_sense_urb(cmnd, GFP_ATOMIC); | 563 | err = uas_submit_sense_urb(cmnd, GFP_ATOMIC); |
| 566 | if (!urb) | 564 | if (err) |
| 567 | return SCSI_MLQUEUE_DEVICE_BUSY; | 565 | return err; |
| 568 | cmdinfo->state &= ~SUBMIT_STATUS_URB; | 566 | cmdinfo->state &= ~SUBMIT_STATUS_URB; |
| 569 | } | 567 | } |
| 570 | 568 | ||
| @@ -572,7 +570,7 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd, · 1 unmodified line | |||
| 572 | cmdinfo->data_in_urb = uas_alloc_data_urb(devinfo, GFP_ATOMIC, | 570 | cmdinfo->data_in_urb = uas_alloc_data_urb(devinfo, GFP_ATOMIC, |
| 573 | cmnd, DMA_FROM_DEVICE); | 571 | cmnd, DMA_FROM_DEVICE); |
| 574 | if (!cmdinfo->data_in_urb) | 572 | if (!cmdinfo->data_in_urb) |
| 575 | return SCSI_MLQUEUE_DEVICE_BUSY; | 573 | return -ENOMEM; |
| 576 | cmdinfo->state &= ~ALLOC_DATA_IN_URB; | 574 | cmdinfo->state &= ~ALLOC_DATA_IN_URB; |
| 577 | } | 575 | } |
| 578 | 576 | ||
| @@ -582,7 +580,7 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd, · 3 unmodified lines | |||
| 582 | if (err) { | 580 | if (err) { |
| 583 | usb_unanchor_urb(cmdinfo->data_in_urb); | 581 | usb_unanchor_urb(cmdinfo->data_in_urb); |
| 584 | uas_log_cmd_state(cmnd, "data in submit err", err); | 582 | uas_log_cmd_state(cmnd, "data in submit err", err); |
| 585 | return SCSI_MLQUEUE_DEVICE_BUSY; | 583 | return err; |
| 586 | } | 584 | } |
| 587 | cmdinfo->state &= ~SUBMIT_DATA_IN_URB; | 585 | cmdinfo->state &= ~SUBMIT_DATA_IN_URB; |
| 588 | cmdinfo->state |= DATA_IN_URB_INFLIGHT; | 586 | cmdinfo->state |= DATA_IN_URB_INFLIGHT; |
| @@ -592,7 +590,7 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd, · 3 unmodified lines | |||
| 592 | cmdinfo->data_out_urb = uas_alloc_data_urb(devinfo, GFP_ATOMIC, | 590 | cmdinfo->data_out_urb = uas_alloc_data_urb(devinfo, GFP_ATOMIC, |
| 593 | cmnd, DMA_TO_DEVICE); | 591 | cmnd, DMA_TO_DEVICE); |
| 594 | if (!cmdinfo->data_out_urb) | 592 | if (!cmdinfo->data_out_urb) |
| 595 | return SCSI_MLQUEUE_DEVICE_BUSY; | 593 | return -ENOMEM; |
| 596 | cmdinfo->state &= ~ALLOC_DATA_OUT_URB; | 594 | cmdinfo->state &= ~ALLOC_DATA_OUT_URB; |
| 597 | } | 595 | } |
| 598 | 596 | ||
| @@ -602,7 +600,7 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd, · 3 unmodified lines | |||
| 602 | if (err) { | 600 | if (err) { |
| 603 | usb_unanchor_urb(cmdinfo->data_out_urb); | 601 | usb_unanchor_urb(cmdinfo->data_out_urb); |
| 604 | uas_log_cmd_state(cmnd, "data out submit err", err); | 602 | uas_log_cmd_state(cmnd, "data out submit err", err); |
| 605 | return SCSI_MLQUEUE_DEVICE_BUSY; | 603 | return err; |
| 606 | } | 604 | } |
| 607 | cmdinfo->state &= ~SUBMIT_DATA_OUT_URB; | 605 | cmdinfo->state &= ~SUBMIT_DATA_OUT_URB; |
| 608 | cmdinfo->state |= DATA_OUT_URB_INFLIGHT; | 606 | cmdinfo->state |= DATA_OUT_URB_INFLIGHT; |
| @@ -611,7 +609,7 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd, · 2 unmodified lines | |||
| 611 | if (cmdinfo->state & ALLOC_CMD_URB) { | 609 | if (cmdinfo->state & ALLOC_CMD_URB) { |
| 612 | cmdinfo->cmd_urb = uas_alloc_cmd_urb(devinfo, GFP_ATOMIC, cmnd); | 610 | cmdinfo->cmd_urb = uas_alloc_cmd_urb(devinfo, GFP_ATOMIC, cmnd); |
| 613 | if (!cmdinfo->cmd_urb) | 611 | if (!cmdinfo->cmd_urb) |
| 614 | return SCSI_MLQUEUE_DEVICE_BUSY; | 612 | return -ENOMEM; |
| 615 | cmdinfo->state &= ~ALLOC_CMD_URB; | 613 | cmdinfo->state &= ~ALLOC_CMD_URB; |
| 616 | } | 614 | } |
| 617 | 615 | ||
| @@ -621,7 +619,7 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd, · 3 unmodified lines | |||
| 621 | if (err) { | 619 | if (err) { |
| 622 | usb_unanchor_urb(cmdinfo->cmd_urb); | 620 | usb_unanchor_urb(cmdinfo->cmd_urb); |
| 623 | uas_log_cmd_state(cmnd, "cmd submit err", err); | 621 | uas_log_cmd_state(cmnd, "cmd submit err", err); |
| 624 | return SCSI_MLQUEUE_DEVICE_BUSY; | 622 | return err; |
| 625 | } | 623 | } |
| 626 | cmdinfo->cmd_urb = NULL; | 624 | cmdinfo->cmd_urb = NULL; |
| 627 | cmdinfo->state &= ~SUBMIT_CMD_URB; | 625 | cmdinfo->state &= ~SUBMIT_CMD_URB; |
| @@ -698,7 +696,7 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd) · 70 unmodified lines | |||
| 698 | * of queueing, no matter how fatal the error | 696 | * of queueing, no matter how fatal the error |
| 699 | */ | 697 | */ |
| 700 | if (err == -ENODEV) { | 698 | if (err == -ENODEV) { |
| 701 | set_host_byte(cmnd, DID_ERROR); | 699 | set_host_byte(cmnd, DID_NO_CONNECT); |
| 702 | scsi_done(cmnd); | 700 | scsi_done(cmnd); |
| 703 | goto zombie; | 701 | goto zombie; |
| 704 | } | 702 | } |
| @@ -1310,6 +1310,7 @@ static ssize_t select_usb_power_delivery_store(struct device *dev, · 1309 unmodified lines | |||
| 1310 | { | 1310 | { |
| 1311 | struct typec_port *port = to_typec_port(dev); | 1311 | struct typec_port *port = to_typec_port(dev); |
| 1312 | struct usb_power_delivery *pd; | 1312 | struct usb_power_delivery *pd; |
| 1313 | int ret; | ||
| 1313 | 1314 | ||
| 1314 | if (!port->ops || !port->ops->pd_set) | 1315 | if (!port->ops || !port->ops->pd_set) |
| 1315 | return -EOPNOTSUPP; | 1316 | return -EOPNOTSUPP; |
| @@ -1318,7 +1319,11 @@ static ssize_t select_usb_power_delivery_store(struct device *dev, · 2 unmodified lines | |||
| 1318 | if (!pd) | 1319 | if (!pd) |
| 1319 | return -EINVAL; | 1320 | return -EINVAL; |
| 1320 | 1321 | ||
| 1321 | return port->ops->pd_set(port, pd); | 1322 | ret = port->ops->pd_set(port, pd); |
| 1323 | if (ret) | ||
| 1324 | return ret; | ||
| 1325 | |||
| 1326 | return size; | ||
| 1322 | } | 1327 | } |
| 1323 | 1328 | ||
| 1324 | static ssize_t select_usb_power_delivery_show(struct device *dev, | 1329 | static ssize_t select_usb_power_delivery_show(struct device *dev, |
| @@ -6861,7 +6861,7 @@ static int tcpm_pd_set(struct typec_port *p, struct usb_power_delivery *pd) · 6860 unmodified lines | |||
| 6861 | 6861 | ||
| 6862 | if (data->source_desc.pdo[0]) { | 6862 | if (data->source_desc.pdo[0]) { |
| 6863 | for (i = 0; i < PDO_MAX_OBJECTS && data->source_desc.pdo[i]; i++) | 6863 | for (i = 0; i < PDO_MAX_OBJECTS && data->source_desc.pdo[i]; i++) |
| 6864 | port->snk_pdo[i] = data->source_desc.pdo[i]; | 6864 | port->src_pdo[i] = data->source_desc.pdo[i]; |
| 6865 | port->nr_src_pdo = i + 1; | 6865 | port->nr_src_pdo = i + 1; |
| 6866 | } | 6866 | } |
| 6867 | 6867 | ||
| @@ -6910,7 +6910,9 @@ static int tcpm_pd_set(struct typec_port *p, struct usb_power_delivery *pd) · 42 unmodified lines | |||
| 6910 | 6910 | ||
| 6911 | port->port_source_caps = data->source_cap; | 6911 | port->port_source_caps = data->source_cap; |
| 6912 | port->port_sink_caps = data->sink_cap; | 6912 | port->port_sink_caps = data->sink_cap; |
| 6913 | typec_port_set_usb_power_delivery(p, NULL); | ||
| 6913 | port->selected_pd = pd; | 6914 | port->selected_pd = pd; |
| 6915 | typec_port_set_usb_power_delivery(p, port->selected_pd); | ||
| 6914 | unlock: | 6916 | unlock: |
| 6915 | mutex_unlock(&port->lock); | 6917 | mutex_unlock(&port->lock); |
| 6916 | return ret; | 6918 | return ret; |
| @@ -6943,9 +6945,7 @@ static void tcpm_port_unregister_pd(struct tcpm_port *port) · 26 unmodified lines | |||
| 6943 | port->port_source_caps = NULL; | 6945 | port->port_source_caps = NULL; |
| 6944 | for (i = 0; i < port->pd_count; i++) { | 6946 | for (i = 0; i < port->pd_count; i++) { |
| 6945 | usb_power_delivery_unregister_capabilities(port->pd_list[i]->sink_cap); | 6947 | usb_power_delivery_unregister_capabilities(port->pd_list[i]->sink_cap); |
| 6946 | kfree(port->pd_list[i]->sink_cap); | ||
| 6947 | usb_power_delivery_unregister_capabilities(port->pd_list[i]->source_cap); | 6948 | usb_power_delivery_unregister_capabilities(port->pd_list[i]->source_cap); |
| 6948 | kfree(port->pd_list[i]->source_cap); | ||
| 6949 | devm_kfree(port->dev, port->pd_list[i]); | 6949 | devm_kfree(port->dev, port->pd_list[i]); |
| 6950 | port->pd_list[i] = NULL; | 6950 | port->pd_list[i] = NULL; |
| 6951 | usb_power_delivery_unregister(port->pds[i]); | 6951 | usb_power_delivery_unregister(port->pds[i]); |
| @@ -151,8 +151,12 @@ static int ucsi_exec_command(struct ucsi *ucsi, u64 cmd) · 150 unmodified lines | |||
| 151 | if (!(cci & UCSI_CCI_COMMAND_COMPLETE)) | 151 | if (!(cci & UCSI_CCI_COMMAND_COMPLETE)) |
| 152 | return -EIO; | 152 | return -EIO; |
| 153 | 153 | ||
| 154 | if (cci & UCSI_CCI_NOT_SUPPORTED) | 154 | if (cci & UCSI_CCI_NOT_SUPPORTED) { |
| 155 | if (ucsi_acknowledge_command(ucsi) < 0) | ||
| 156 | dev_err(ucsi->dev, | ||
| 157 | "ACK of unsupported command failed\n"); | ||
| 155 | return -EOPNOTSUPP; | 158 | return -EOPNOTSUPP; |
| 159 | } | ||
| 156 | 160 | ||
| 157 | if (cci & UCSI_CCI_ERROR) { | 161 | if (cci & UCSI_CCI_ERROR) { |
| 158 | if (cmd == UCSI_GET_ERROR_STATUS) | 162 | if (cmd == UCSI_GET_ERROR_STATUS) |
| @@ -1133,17 +1137,21 @@ static int ucsi_check_cable(struct ucsi_connector *con) · 974 unmodified lines | |||
| 1133 | if (ret < 0) | 1137 | if (ret < 0) |
| 1134 | return ret; | 1138 | return ret; |
| 1135 | 1139 | ||
| 1136 | ret = ucsi_get_cable_identity(con); | 1140 | if (con->ucsi->cap.features & UCSI_CAP_GET_PD_MESSAGE) { |
| 1137 | if (ret < 0) | 1141 | ret = ucsi_get_cable_identity(con); |
| 1138 | return ret; | 1142 | if (ret < 0) |
| 1143 | return ret; | ||
| 1144 | } | ||
| 1139 | 1145 | ||
| 1140 | ret = ucsi_register_plug(con); | 1146 | if (con->ucsi->cap.features & UCSI_CAP_ALT_MODE_DETAILS) { |
| 1141 | if (ret < 0) | 1147 | ret = ucsi_register_plug(con); |
| 1142 | return ret; | 1148 | if (ret < 0) |
| 1149 | return ret; | ||
| 1143 | 1150 | ||
| 1144 | ret = ucsi_register_altmodes(con, UCSI_RECIPIENT_SOP_P); | 1151 | ret = ucsi_register_altmodes(con, UCSI_RECIPIENT_SOP_P); |
| 1145 | if (ret < 0) | 1152 | if (ret < 0) |
| 1146 | return ret; | 1153 | return ret; |
| 1154 | } | ||
| 1147 | 1155 | ||
| 1148 | return 0; | 1156 | return 0; |
| 1149 | } | 1157 | } |
| @@ -1189,8 +1197,10 @@ static void ucsi_handle_connector_change(struct work_struct *work) · 39 unmodified lines | |||
| 1189 | ucsi_register_partner(con); | 1197 | ucsi_register_partner(con); |
| 1190 | ucsi_partner_task(con, ucsi_check_connection, 1, HZ); | 1198 | ucsi_partner_task(con, ucsi_check_connection, 1, HZ); |
| 1191 | ucsi_partner_task(con, ucsi_check_connector_capability, 1, HZ); | 1199 | ucsi_partner_task(con, ucsi_check_connector_capability, 1, HZ); |
| 1192 | ucsi_partner_task(con, ucsi_get_partner_identity, 1, HZ); | 1200 | if (con->ucsi->cap.features & UCSI_CAP_GET_PD_MESSAGE) |
| 1193 | ucsi_partner_task(con, ucsi_check_cable, 1, HZ); | 1201 | ucsi_partner_task(con, ucsi_get_partner_identity, 1, HZ); |
| 1202 | if (con->ucsi->cap.features & UCSI_CAP_CABLE_DETAILS) | ||
| 1203 | ucsi_partner_task(con, ucsi_check_cable, 1, HZ); | ||
| 1194 | 1204 | ||
| 1195 | if (UCSI_CONSTAT_PWR_OPMODE(con->status.flags) == | 1205 | if (UCSI_CONSTAT_PWR_OPMODE(con->status.flags) == |
| 1196 | UCSI_CONSTAT_PWR_OPMODE_PD) | 1206 | UCSI_CONSTAT_PWR_OPMODE_PD) |
| @@ -1215,11 +1225,11 @@ static void ucsi_handle_connector_change(struct work_struct *work) · 18 unmodified lines | |||
| 1215 | if (con->status.change & UCSI_CONSTAT_CAM_CHANGE) | 1225 | if (con->status.change & UCSI_CONSTAT_CAM_CHANGE) |
| 1216 | ucsi_partner_task(con, ucsi_check_altmodes, 1, 0); | 1226 | ucsi_partner_task(con, ucsi_check_altmodes, 1, 0); |
| 1217 | 1227 | ||
| 1218 | clear_bit(EVENT_PENDING, &con->ucsi->flags); | ||
| 1219 | |||
| 1220 | mutex_lock(&ucsi->ppm_lock); | 1228 | mutex_lock(&ucsi->ppm_lock); |
| 1229 | clear_bit(EVENT_PENDING, &con->ucsi->flags); | ||
| 1221 | ret = ucsi_acknowledge_connector_change(ucsi); | 1230 | ret = ucsi_acknowledge_connector_change(ucsi); |
| 1222 | mutex_unlock(&ucsi->ppm_lock); | 1231 | mutex_unlock(&ucsi->ppm_lock); |
| 1232 | |||
| 1223 | if (ret) | 1233 | if (ret) |
| 1224 | dev_err(ucsi->dev, "%s: ACK failed (%d)", __func__, ret); | 1234 | dev_err(ucsi->dev, "%s: ACK failed (%d)", __func__, ret); |
| 1225 | 1235 | ||
| @@ -1237,7 +1247,7 @@ void ucsi_connector_change(struct ucsi *ucsi, u8 num) · 11 unmodified lines | |||
| 1237 | struct ucsi_connector *con = &ucsi->connector[num - 1]; | 1247 | struct ucsi_connector *con = &ucsi->connector[num - 1]; |
| 1238 | 1248 | ||
| 1239 | if (!(ucsi->ntfy & UCSI_ENABLE_NTFY_CONNECTOR_CHANGE)) { | 1249 | if (!(ucsi->ntfy & UCSI_ENABLE_NTFY_CONNECTOR_CHANGE)) { |
| 1240 | dev_dbg(ucsi->dev, "Bogus connector change event\n"); | 1250 | dev_dbg(ucsi->dev, "Early connector change event\n"); |
| 1241 | return; | 1251 | return; |
| 1242 | } | 1252 | } |
| 1243 | 1253 | ||
| @@ -1260,13 +1270,47 @@ static int ucsi_reset_connector(struct ucsi_connector *con, bool hard) · 16 unmodified lines | |||
| 1260 | 1270 | ||
| 1261 | static int ucsi_reset_ppm(struct ucsi *ucsi) | 1271 | static int ucsi_reset_ppm(struct ucsi *ucsi) |
| 1262 | { | 1272 | { |
| 1263 | u64 command = UCSI_PPM_RESET; | 1273 | u64 command; |
| 1264 | unsigned long tmo; | 1274 | unsigned long tmo; |
| 1265 | u32 cci; | 1275 | u32 cci; |
| 1266 | int ret; | 1276 | int ret; |
| 1267 | 1277 | ||
| 1268 | mutex_lock(&ucsi->ppm_lock); | 1278 | mutex_lock(&ucsi->ppm_lock); |
| 1269 | 1279 | ||
| 1280 | ret = ucsi->ops->read(ucsi, UCSI_CCI, &cci, sizeof(cci)); | ||
| 1281 | if (ret < 0) | ||
| 1282 | goto out; | ||
| 1283 | |||
| 1284 | /* | ||
| 1285 | * If UCSI_CCI_RESET_COMPLETE is already set we must clear | ||
| 1286 | * the flag before we start another reset. Send a | ||
| 1287 | * UCSI_SET_NOTIFICATION_ENABLE command to achieve this. | ||
| 1288 | * Ignore a timeout and try the reset anyway if this fails. | ||
| 1289 | */ | ||
| 1290 | if (cci & UCSI_CCI_RESET_COMPLETE) { | ||
| 1291 | command = UCSI_SET_NOTIFICATION_ENABLE; | ||
| 1292 | ret = ucsi->ops->async_write(ucsi, UCSI_CONTROL, &command, | ||
| 1293 | sizeof(command)); | ||
| 1294 | if (ret < 0) | ||
| 1295 | goto out; | ||
| 1296 | |||
| 1297 | tmo = jiffies + msecs_to_jiffies(UCSI_TIMEOUT_MS); | ||
| 1298 | do { | ||
| 1299 | ret = ucsi->ops->read(ucsi, UCSI_CCI, | ||
| 1300 | &cci, sizeof(cci)); | ||
| 1301 | if (ret < 0) | ||
| 1302 | goto out; | ||
| 1303 | if (cci & UCSI_CCI_COMMAND_COMPLETE) | ||
| 1304 | break; | ||
| 1305 | if (time_is_before_jiffies(tmo)) | ||
| 1306 | break; | ||
| 1307 | msleep(20); | ||
| 1308 | } while (1); | ||
| 1309 | |||
| 1310 | WARN_ON(cci & UCSI_CCI_RESET_COMPLETE); | ||
| 1311 | } | ||
| 1312 | |||
| 1313 | command = UCSI_PPM_RESET; | ||
| 1270 | ret = ucsi->ops->async_write(ucsi, UCSI_CONTROL, &command, | 1314 | ret = ucsi->ops->async_write(ucsi, UCSI_CONTROL, &command, |
| 1271 | sizeof(command)); | 1315 | sizeof(command)); |
| 1272 | if (ret < 0) | 1316 | if (ret < 0) |
| @@ -1589,8 +1633,10 @@ static int ucsi_register_port(struct ucsi *ucsi, struct ucsi_connector *con) · 316 unmodified lines | |||
| 1589 | ucsi_register_partner(con); | 1633 | ucsi_register_partner(con); |
| 1590 | ucsi_pwr_opmode_change(con); | 1634 | ucsi_pwr_opmode_change(con); |
| 1591 | ucsi_port_psy_changed(con); | 1635 | ucsi_port_psy_changed(con); |
| 1592 | ucsi_get_partner_identity(con); | 1636 | if (con->ucsi->cap.features & UCSI_CAP_GET_PD_MESSAGE) |
| 1593 | ucsi_check_cable(con); | 1637 | ucsi_get_partner_identity(con); |
| 1638 | if (con->ucsi->cap.features & UCSI_CAP_CABLE_DETAILS) | ||
| 1639 | ucsi_check_cable(con); | ||
| 1594 | } | 1640 | } |
| 1595 | 1641 | ||
| 1596 | /* Only notify USB controller if partner supports USB data */ | 1642 | /* Only notify USB controller if partner supports USB data */ |
| @@ -1636,6 +1682,7 @@ static int ucsi_init(struct ucsi *ucsi) · 39 unmodified lines | |||
| 1636 | { | 1682 | { |
| 1637 | struct ucsi_connector *con, *connector; | 1683 | struct ucsi_connector *con, *connector; |
| 1638 | u64 command, ntfy; | 1684 | u64 command, ntfy; |
| 1685 | u32 cci; | ||
| 1639 | int ret; | 1686 | int ret; |
| 1640 | int i; | 1687 | int i; |
| 1641 | 1688 | ||
| @@ -1688,6 +1735,13 @@ static int ucsi_init(struct ucsi *ucsi) · 46 unmodified lines | |||
| 1688 | 1735 | ||
| 1689 | ucsi->connector = connector; | 1736 | ucsi->connector = connector; |
| 1690 | ucsi->ntfy = ntfy; | 1737 | ucsi->ntfy = ntfy; |
| 1738 | |||
| 1739 | ret = ucsi->ops->read(ucsi, UCSI_CCI, &cci, sizeof(cci)); | ||
| 1740 | if (ret) | ||
| 1741 | return ret; | ||
| 1742 | if (UCSI_CCI_CONNECTOR(READ_ONCE(cci))) | ||
| 1743 | ucsi_connector_change(ucsi, cci); | ||
| 1744 | |||
| 1691 | return 0; | 1745 | return 0; |
| 1692 | 1746 | ||
| 1693 | err_unregister: | 1747 | err_unregister: |
| @@ -206,7 +206,7 @@ struct ucsi_capability { · 205 unmodified lines | |||
| 206 | #define UCSI_CAP_ATTR_POWER_OTHER BIT(10) | 206 | #define UCSI_CAP_ATTR_POWER_OTHER BIT(10) |
| 207 | #define UCSI_CAP_ATTR_POWER_VBUS BIT(14) | 207 | #define UCSI_CAP_ATTR_POWER_VBUS BIT(14) |
| 208 | u8 num_connectors; | 208 | u8 num_connectors; |
| 209 | u8 features; | 209 | u16 features; |
| 210 | #define UCSI_CAP_SET_UOM BIT(0) | 210 | #define UCSI_CAP_SET_UOM BIT(0) |
| 211 | #define UCSI_CAP_SET_PDM BIT(1) | 211 | #define UCSI_CAP_SET_PDM BIT(1) |
| 212 | #define UCSI_CAP_ALT_MODE_DETAILS BIT(2) | 212 | #define UCSI_CAP_ALT_MODE_DETAILS BIT(2) |
| @@ -215,7 +215,8 @@ struct ucsi_capability { · 2 unmodified lines | |||
| 215 | #define UCSI_CAP_CABLE_DETAILS BIT(5) | 215 | #define UCSI_CAP_CABLE_DETAILS BIT(5) |
| 216 | #define UCSI_CAP_EXT_SUPPLY_NOTIFICATIONS BIT(6) | 216 | #define UCSI_CAP_EXT_SUPPLY_NOTIFICATIONS BIT(6) |
| 217 | #define UCSI_CAP_PD_RESET BIT(7) | 217 | #define UCSI_CAP_PD_RESET BIT(7) |
| 218 | u16 reserved_1; | 218 | #define UCSI_CAP_GET_PD_MESSAGE BIT(8) |
| 219 | u8 reserved_1; | ||
| 219 | u8 num_alt_modes; | 220 | u8 num_alt_modes; |
| 220 | u8 reserved_2; | 221 | u8 reserved_2; |
| 221 | u16 bc_version; | 222 | u16 bc_version; |
| @@ -23,10 +23,11 @@ struct ucsi_acpi { · 22 unmodified lines | |||
| 23 | void *base; | 23 | void *base; |
| 24 | struct completion complete; | 24 | struct completion complete; |
| 25 | unsigned long flags; | 25 | unsigned long flags; |
| 26 | #define UCSI_ACPI_SUPPRESS_EVENT 0 | ||
| 27 | #define UCSI_ACPI_COMMAND_PENDING 1 | ||
| 28 | #define UCSI_ACPI_ACK_PENDING 2 | ||
| 26 | guid_t guid; | 29 | guid_t guid; |
| 27 | u64 cmd; | 30 | u64 cmd; |
| 28 | bool dell_quirk_probed; | ||
| 29 | bool dell_quirk_active; | ||
| 30 | }; | 31 | }; |
| 31 | 32 | ||
| 32 | static int ucsi_acpi_dsm(struct ucsi_acpi *ua, int func) | 33 | static int ucsi_acpi_dsm(struct ucsi_acpi *ua, int func) |
| @@ -79,9 +80,9 @@ static int ucsi_acpi_sync_write(struct ucsi *ucsi, unsigned int offset, · 46 unmodified lines | |||
| 79 | int ret; | 80 | int ret; |
| 80 | 81 | ||
| 81 | if (ack) | 82 | if (ack) |
| 82 | set_bit(ACK_PENDING, &ua->flags); | 83 | set_bit(UCSI_ACPI_ACK_PENDING, &ua->flags); |
| 83 | else | 84 | else |
| 84 | set_bit(COMMAND_PENDING, &ua->flags); | 85 | set_bit(UCSI_ACPI_COMMAND_PENDING, &ua->flags); |
| 85 | 86 | ||
| 86 | ret = ucsi_acpi_async_write(ucsi, offset, val, val_len); | 87 | ret = ucsi_acpi_async_write(ucsi, offset, val, val_len); |
| 87 | if (ret) | 88 | if (ret) |
| @@ -92,9 +93,9 @@ static int ucsi_acpi_sync_write(struct ucsi *ucsi, unsigned int offset, · 4 unmodified lines | |||
| 92 | 93 | ||
| 93 | out_clear_bit: | 94 | out_clear_bit: |
| 94 | if (ack) | 95 | if (ack) |
| 95 | clear_bit(ACK_PENDING, &ua->flags); | 96 | clear_bit(UCSI_ACPI_ACK_PENDING, &ua->flags); |
| 96 | else | 97 | else |
| 97 | clear_bit(COMMAND_PENDING, &ua->flags); | 98 | clear_bit(UCSI_ACPI_COMMAND_PENDING, &ua->flags); |
| 98 | 99 | ||
| 99 | return ret; | 100 | return ret; |
| 100 | } | 101 | } |
| @@ -129,51 +130,40 @@ static const struct ucsi_operations ucsi_zenbook_ops = { · 28 unmodified lines | |||
| 129 | }; | 130 | }; |
| 130 | 131 | ||
| 131 | /* | 132 | /* |
| 132 | * Some Dell laptops expect that an ACK command with the | 133 | * Some Dell laptops don't like ACK commands with the |
| 133 | * UCSI_ACK_CONNECTOR_CHANGE bit set is followed by a (separate) | 134 | * UCSI_ACK_CONNECTOR_CHANGE but not the UCSI_ACK_COMMAND_COMPLETE |
| 134 | * ACK command that only has the UCSI_ACK_COMMAND_COMPLETE bit set. | 135 | * bit set. To work around this send a dummy command and bundle the |
| 135 | * If this is not done events are not delivered to OSPM and | 136 | * UCSI_ACK_CONNECTOR_CHANGE with the UCSI_ACK_COMMAND_COMPLETE |
| 136 | * subsequent commands will timeout. | 137 | * for the dummy command. |
| 137 | */ | 138 | */ |
| 138 | static int | 139 | static int |
| 139 | ucsi_dell_sync_write(struct ucsi *ucsi, unsigned int offset, | 140 | ucsi_dell_sync_write(struct ucsi *ucsi, unsigned int offset, |
| 140 | const void *val, size_t val_len) | 141 | const void *val, size_t val_len) |
| 141 | { | 142 | { |
| 142 | struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi); | 143 | struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi); |
| 143 | u64 cmd = *(u64 *)val, ack = 0; | 144 | u64 cmd = *(u64 *)val; |
| 145 | u64 dummycmd = UCSI_GET_CAPABILITY; | ||
| 144 | int ret; | 146 | int ret; |
| 145 | 147 | ||
| 146 | if (UCSI_COMMAND(cmd) == UCSI_ACK_CC_CI && | 148 | if (cmd == (UCSI_ACK_CC_CI | UCSI_ACK_CONNECTOR_CHANGE)) { |
| 147 | cmd & UCSI_ACK_CONNECTOR_CHANGE) | 149 | cmd |= UCSI_ACK_COMMAND_COMPLETE; |
| 148 | ack = UCSI_ACK_CC_CI | UCSI_ACK_COMMAND_COMPLETE; | 150 | |
| 149 | 151 | /* | |
| 150 | ret = ucsi_acpi_sync_write(ucsi, offset, val, val_len); | 152 | * The UCSI core thinks it is sending a connector change ack |
| 151 | if (ret != 0) | 153 | * and will accept new connector change events. We don't want |
| 152 | return ret; | 154 | * this to happen for the dummy command as its response will |
| 153 | if (ack == 0) | 155 | * still report the very event that the core is trying to clear. |
| 154 | return ret; | 156 | */ |
| 155 | 157 | set_bit(UCSI_ACPI_SUPPRESS_EVENT, &ua->flags); | |
| 156 | if (!ua->dell_quirk_probed) { | 158 | ret = ucsi_acpi_sync_write(ucsi, UCSI_CONTROL, &dummycmd, |
| 157 | ua->dell_quirk_probed = true; | 159 | sizeof(dummycmd)); |
| 158 | 160 | clear_bit(UCSI_ACPI_SUPPRESS_EVENT, &ua->flags); | |
| 159 | cmd = UCSI_GET_CAPABILITY; | 161 | |
| 160 | ret = ucsi_acpi_sync_write(ucsi, UCSI_CONTROL, &cmd, | 162 | if (ret < 0) |
| 161 | sizeof(cmd)); | ||
| 162 | if (ret == 0) | ||
| 163 | return ucsi_acpi_sync_write(ucsi, UCSI_CONTROL, | ||
| 164 | &ack, sizeof(ack)); | ||
| 165 | if (ret != -ETIMEDOUT) | ||
| 166 | return ret; | 163 | return ret; |
| 167 | |||
| 168 | ua->dell_quirk_active = true; | ||
| 169 | dev_err(ua->dev, "Firmware bug: Additional ACK required after ACKing a connector change.\n"); | ||
| 170 | dev_err(ua->dev, "Firmware bug: Enabling workaround\n"); | ||
| 171 | } | 164 | } |
| 172 | 165 | ||
| 173 | if (!ua->dell_quirk_active) | 166 | return ucsi_acpi_sync_write(ucsi, UCSI_CONTROL, &cmd, sizeof(cmd)); |
| 174 | return ret; | ||
| 175 | |||
| 176 | return ucsi_acpi_sync_write(ucsi, UCSI_CONTROL, &ack, sizeof(ack)); | ||
| 177 | } | 167 | } |
| 178 | 168 | ||
| 179 | static const struct ucsi_operations ucsi_dell_ops = { | 169 | static const struct ucsi_operations ucsi_dell_ops = { |
| @@ -209,13 +199,14 @@ static void ucsi_acpi_notify(acpi_handle handle, u32 event, void *data) · 29 unmodified lines | |||
| 209 | if (ret) | 199 | if (ret) |
| 210 | return; | 200 | return; |
| 211 | 201 | ||
| 212 | if (UCSI_CCI_CONNECTOR(cci)) | 202 | if (UCSI_CCI_CONNECTOR(cci) && |
| 203 | !test_bit(UCSI_ACPI_SUPPRESS_EVENT, &ua->flags)) | ||
| 213 | ucsi_connector_change(ua->ucsi, UCSI_CCI_CONNECTOR(cci)); | 204 | ucsi_connector_change(ua->ucsi, UCSI_CCI_CONNECTOR(cci)); |
| 214 | 205 | ||
| 215 | if (cci & UCSI_CCI_ACK_COMPLETE && test_bit(ACK_PENDING, &ua->flags)) | 206 | if (cci & UCSI_CCI_ACK_COMPLETE && test_bit(ACK_PENDING, &ua->flags)) |
| 216 | complete(&ua->complete); | 207 | complete(&ua->complete); |
| 217 | if (cci & UCSI_CCI_COMMAND_COMPLETE && | 208 | if (cci & UCSI_CCI_COMMAND_COMPLETE && |
| 218 | test_bit(COMMAND_PENDING, &ua->flags)) | 209 | test_bit(UCSI_ACPI_COMMAND_PENDING, &ua->flags)) |
| 219 | complete(&ua->complete); | 210 | complete(&ua->complete); |
| 220 | } | 211 | } |
| 221 | 212 | ||
| @@ -255,6 +255,20 @@ static void pmic_glink_ucsi_notify(struct work_struct *work) · 254 unmodified lines | |||
| 255 | static void pmic_glink_ucsi_register(struct work_struct *work) | 255 | static void pmic_glink_ucsi_register(struct work_struct *work) |
| 256 | { | 256 | { |
| 257 | struct pmic_glink_ucsi *ucsi = container_of(work, struct pmic_glink_ucsi, register_work); | 257 | struct pmic_glink_ucsi *ucsi = container_of(work, struct pmic_glink_ucsi, register_work); |
| 258 | int orientation; | ||
| 259 | int i; | ||
| 260 | |||
| 261 | for (i = 0; i < PMIC_GLINK_MAX_PORTS; i++) { | ||
| 262 | if (!ucsi->port_orientation[i]) | ||
| 263 | continue; | ||
| 264 | orientation = gpiod_get_value(ucsi->port_orientation[i]); | ||
| 265 | |||
| 266 | if (orientation >= 0) { | ||
| 267 | typec_switch_set(ucsi->port_switch[i], | ||
| 268 | orientation ? TYPEC_ORIENTATION_REVERSE | ||
| 269 | : TYPEC_ORIENTATION_NORMAL); | ||
| 270 | } | ||
| 271 | } | ||
| 258 | 272 | ||
| 259 | ucsi_register(ucsi->ucsi); | 273 | ucsi_register(ucsi->ucsi); |
| 260 | } | 274 | } |