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 | 485 | static int service_outstanding_interrupt(struct wdm_device *desc) |
| 486 | 486 | { |
| 487 | 487 | int rv = 0; |
| 488 | + int used; | |
| 488 | 489 | |
| 489 | 490 | /* submit read urb only if the device is waiting for it */ |
| 490 | 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 | 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 | 507 | spin_unlock_irq(&desc->iuspin); |
| 504 | 508 | rv = usb_submit_urb(desc->response, GFP_KERNEL); |
| 505 | 509 | spin_lock_irq(&desc->iuspin); |
| @@ -130,7 +130,6 @@ EXPORT_SYMBOL_GPL(ehci_cf_port_reset_rwsem); · 129 unmodified lines | ||
| 130 | 130 | #define HUB_DEBOUNCE_STEP 25 |
| 131 | 131 | #define HUB_DEBOUNCE_STABLE 100 |
| 132 | 132 | |
| 133 | −static void hub_release(struct kref *kref); | |
| 134 | 133 | static int usb_reset_and_verify_device(struct usb_device *udev); |
| 135 | 134 | static int hub_port_disable(struct usb_hub *hub, int port1, int set_state); |
| 136 | 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 | 720 | intf = to_usb_interface(hub->intfdev); |
| 722 | 721 | usb_autopm_get_interface_no_resume(intf); |
| 723 | − kref_get(&hub->kref); | |
| 722 | + hub_get(hub); | |
| 724 | 723 | |
| 725 | 724 | if (queue_work(hub_wq, &hub->events)) |
| 726 | 725 | return; |
| 727 | 726 | |
| 728 | 727 | /* the work has already been scheduled */ |
| 729 | 728 | usb_autopm_put_interface_async(intf); |
| 730 | − kref_put(&hub->kref, hub_release); | |
| 729 | + hub_put(hub); | |
| 731 | 730 | } |
| 732 | 731 | |
| 733 | 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 | 1094 | goto init2; |
| 1096 | 1095 | goto init3; |
| 1097 | 1096 | } |
| 1098 | − kref_get(&hub->kref); | |
| 1097 | + hub_get(hub); | |
| 1099 | 1098 | |
| 1100 | 1099 | /* The superspeed hub except for root hub has to use Hub Depth |
| 1101 | 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 | 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 | 1348 | /* Implement the continuations for the delays above */ |
| @@ -1759,6 +1758,16 @@ static void hub_release(struct kref *kref) · 409 unmodified lines | ||
| 1759 | 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 | 1771 | static unsigned highspeed_hubs; |
| 1763 | 1772 | |
| 1764 | 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 | 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 | 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 | 5944 | /* Balance the stuff in kick_hub_wq() and allow autosuspend */ |
| 5936 | 5945 | usb_autopm_put_interface(intf); |
| 5937 | − kref_put(&hub->kref, hub_release); | |
| 5946 | + hub_put(hub); | |
| 5938 | 5947 | |
| 5939 | 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 | 129 | extern int usb_hub_set_port_power(struct usb_device *hdev, struct usb_hub *hub, |
| 130 | 130 | int port1, bool set); |
| 131 | 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 | 134 | extern int hub_port_debounce(struct usb_hub *hub, int port1, |
| 133 | 135 | bool must_be_connected); |
| 134 | 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 | 56 | u16 portstatus, unused; |
| 57 | 57 | bool disabled; |
| 58 | 58 | int rc; |
| 59 | + struct kernfs_node *kn; | |
| 59 | 60 | |
| 61 | + hub_get(hub); | |
| 60 | 62 | rc = usb_autopm_get_interface(intf); |
| 61 | 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 | 75 | usb_lock_device(hdev); |
| 65 | 76 | if (hub->disconnected) { |
| 66 | 77 | rc = -ENODEV; |
| @@ -70,9 +81,13 @@ static ssize_t disable_show(struct device *dev, · 3 unmodified lines | ||
| 70 | 81 | usb_hub_port_status(hub, port1, &portstatus, &unused); |
| 71 | 82 | disabled = !usb_port_is_power_on(hub, portstatus); |
| 72 | 83 | |
| 73 | −out_hdev_lock: | |
| 84 | + out_hdev_lock: | |
| 74 | 85 | usb_unlock_device(hdev); |
| 86 | + sysfs_unbreak_active_protection(kn); | |
| 87 | + out_autopm: | |
| 75 | 88 | usb_autopm_put_interface(intf); |
| 89 | + out_hub_get: | |
| 90 | + hub_put(hub); | |
| 76 | 91 | |
| 77 | 92 | if (rc) |
| 78 | 93 | return rc; |
| @@ -90,15 +105,26 @@ static ssize_t disable_store(struct device *dev, struct device_attribute *attr, · 11 unmodified lines | ||
| 90 | 105 | int port1 = port_dev->portnum; |
| 91 | 106 | bool disabled; |
| 92 | 107 | int rc; |
| 108 | + struct kernfs_node *kn; | |
| 93 | 109 | |
| 94 | 110 | rc = kstrtobool(buf, &disabled); |
| 95 | 111 | if (rc) |
| 96 | 112 | return rc; |
| 97 | 113 | |
| 114 | + hub_get(hub); | |
| 98 | 115 | rc = usb_autopm_get_interface(intf); |
| 99 | 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 | 128 | usb_lock_device(hdev); |
| 103 | 129 | if (hub->disconnected) { |
| 104 | 130 | rc = -ENODEV; |
| @@ -119,9 +145,13 @@ static ssize_t disable_store(struct device *dev, struct device_attribute *attr, · 14 unmodified lines | ||
| 119 | 145 | if (!rc) |
| 120 | 146 | rc = count; |
| 121 | 147 | |
| 122 | −out_hdev_lock: | |
| 148 | + out_hdev_lock: | |
| 123 | 149 | usb_unlock_device(hdev); |
| 150 | + sysfs_unbreak_active_protection(kn); | |
| 151 | + out_autopm: | |
| 124 | 152 | usb_autopm_put_interface(intf); |
| 153 | + out_hub_get: | |
| 154 | + hub_put(hub); | |
| 125 | 155 | |
| 126 | 156 | return rc; |
| 127 | 157 | } |
| @@ -1217,14 +1217,24 @@ static ssize_t interface_authorized_store(struct device *dev, · 1216 unmodified lines | ||
| 1217 | 1217 | { |
| 1218 | 1218 | struct usb_interface *intf = to_usb_interface(dev); |
| 1219 | 1219 | bool val; |
| 1220 | + struct kernfs_node *kn; | |
| 1220 | 1221 | |
| 1221 | 1222 | if (kstrtobool(buf, &val) != 0) |
| 1222 | 1223 | return -EINVAL; |
| 1223 | 1224 | |
| 1224 | − if (val) | |
| 1225 | + if (val) { | |
| 1225 | 1226 | usb_authorize_interface(intf); |
| 1226 | − else | |
| 1227 | − usb_deauthorize_interface(intf); | |
| 1227 | + } else { | |
| 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 | 1239 | return count; |
| 1230 | 1240 | } |
| @@ -729,8 +729,14 @@ struct dwc2_dregs_backup { · 728 unmodified lines | ||
| 729 | 729 | * struct dwc2_hregs_backup - Holds host registers state before |
| 730 | 730 | * entering partial power down |
| 731 | 731 | * @hcfg: Backup of HCFG register |
| 732 | + * @hflbaddr: Backup of HFLBADDR register | |
| 732 | 733 | * @haintmsk: Backup of HAINTMSK register |
| 734 | + * @hcchar: Backup of HCCHAR register | |
| 735 | + * @hcsplt: Backup of HCSPLT register | |
| 733 | 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 | 740 | * @hprt0: Backup of HPTR0 register |
| 735 | 741 | * @hfir: Backup of HFIR register |
| 736 | 742 | * @hptxfsiz: Backup of HPTXFSIZ register |
| @@ -738,8 +744,14 @@ struct dwc2_dregs_backup { · 1 unmodified line | ||
| 738 | 744 | */ |
| 739 | 745 | struct dwc2_hregs_backup { |
| 740 | 746 | u32 hcfg; |
| 747 | + u32 hflbaddr; | |
| 741 | 748 | u32 haintmsk; |
| 749 | + u32 hcchar[MAX_EPS_CHANNELS]; | |
| 750 | + u32 hcsplt[MAX_EPS_CHANNELS]; | |
| 742 | 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 | 755 | u32 hprt0; |
| 744 | 756 | u32 hfir; |
| 745 | 757 | u32 hptxfsiz; |
| @@ -1086,6 +1098,7 @@ struct dwc2_hsotg { · 340 unmodified lines | ||
| 1086 | 1098 | bool needs_byte_swap; |
| 1087 | 1099 | |
| 1088 | 1100 | /* DWC OTG HW Release versions */ |
| 1101 | +#define DWC2_CORE_REV_4_30a 0x4f54430a | |
| 1089 | 1102 | #define DWC2_CORE_REV_2_71a 0x4f54271a |
| 1090 | 1103 | #define DWC2_CORE_REV_2_72a 0x4f54272a |
| 1091 | 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 | 1336 | int dwc2_restore_global_registers(struct dwc2_hsotg *hsotg); |
| 1324 | 1337 | |
| 1325 | 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 | 1341 | /* This function should be called on every hardware interrupt. */ |
| 1328 | 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 | 298 | /* Exit gadget mode clock gating. */ |
| 299 | 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 | 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 | 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 | 328 | u32 glpmcfg; |
| 328 | − u32 i = 0; | |
| 329 | + u32 pcgctl; | |
| 330 | + u32 dctl; | |
| 329 | 331 | |
| 330 | 332 | if (hsotg->lx_state != DWC2_L1) { |
| 331 | 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 | 337 | glpmcfg = dwc2_readl(hsotg, GLPMCFG); |
| 336 | 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 | 340 | glpmcfg &= ~GLPMCFG_ENBLSLPM; |
| 339 | − glpmcfg &= ~GLPMCFG_HIRD_THRES_EN; | |
| 341 | + glpmcfg &= ~GLPMCFG_HIRD_THRES_MASK; | |
| 340 | 342 | dwc2_writel(hsotg, glpmcfg, GLPMCFG); |
| 341 | 343 | |
| 342 | − do { | |
| 343 | − glpmcfg = dwc2_readl(hsotg, GLPMCFG); | |
| 344 | + pcgctl = dwc2_readl(hsotg, PCGCTL); | |
| 345 | + pcgctl &= ~PCGCTL_ENBL_SLEEP_GATING; | |
| 346 | + dwc2_writel(hsotg, pcgctl, PCGCTL); | |
| 344 | 347 | |
| 345 | − if (!(glpmcfg & (GLPMCFG_COREL1RES_MASK | | |
| 346 | − GLPMCFG_L1RESUMEOK | GLPMCFG_SLPSTS))) | |
| 347 | − break; | |
| 348 | + glpmcfg = dwc2_readl(hsotg, GLPMCFG); | |
| 349 | + if (glpmcfg & GLPMCFG_ENBESL) { | |
| 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); | |
| 350 | − } while (++i < 200); | |
| 365 | + if (dwc2_hsotg_wait_bit_set(hsotg, GINTSTS, GINTSTS_WKUPINT, 1000)) { | |
| 366 | + dev_warn(hsotg->dev, "%s: timeout GINTSTS_WKUPINT\n", __func__); | |
| 367 | + goto fail; | |
| 368 | + return; | |
| 369 | + } | |
| 370 | + } | |
| 351 | 371 | |
| 352 | − if (i == 200) { | |
| 353 | − dev_err(hsotg->dev, "Failed to exit L1 sleep state in 200us.\n"); | |
| 372 | + glpmcfg = dwc2_readl(hsotg, GLPMCFG); | |
| 373 | + if (glpmcfg & GLPMCFG_COREL1RES_MASK || glpmcfg & GLPMCFG_SLPSTS || | |
| 374 | + glpmcfg & GLPMCFG_L1RESUMEOK) { | |
| 375 | + goto fail; | |
| 354 | 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 | 385 | } else { |
| 358 | 386 | /* TODO */ |
| 359 | 387 | dev_err(hsotg->dev, "Host side LPM is not supported.\n"); |
| 360 | 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 | 407 | dev_dbg(hsotg->dev, "%s lxstate = %d\n", __func__, hsotg->lx_state); |
| 386 | 408 | |
| 387 | 409 | if (hsotg->lx_state == DWC2_L1) { |
| 388 | − dwc2_wakeup_from_lpm_l1(hsotg); | |
| 410 | + dwc2_wakeup_from_lpm_l1(hsotg, false); | |
| 389 | 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 | 431 | /* Exit gadget mode clock gating. */ |
| 410 | 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 | 435 | dwc2_gadget_exit_clock_gating(hsotg, 0); |
| 413 | 436 | } else { |
| 414 | 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 | 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 | 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 | 1415 | ep->name, req, req->length, req->buf, req->no_interrupt, |
| 1416 | 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 | 1422 | /* Prevent new request submission when controller is suspended */ |
| 1419 | 1423 | if (hs->lx_state != DWC2_L0) { |
| 1420 | 1424 | dev_dbg(hs->dev, "%s: submit request only in active state\n", |
| @@ -3727,6 +3731,12 @@ irq_retry: · 2306 unmodified lines | ||
| 3727 | 3731 | if (hsotg->in_ppd && hsotg->lx_state == DWC2_L2) |
| 3728 | 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 | 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 | 2701 | hsotg->available_host_channels--; |
| 2702 | 2702 | } |
| 2703 | 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 | 2707 | break; |
| 2708 | + } | |
| 2706 | 2709 | |
| 2707 | 2710 | /* |
| 2708 | 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 | 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 | 2744 | break; |
| 2745 | + } | |
| 2740 | 2746 | |
| 2741 | 2747 | /* |
| 2742 | 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 | 4149 | urb->actual_length); |
| 4144 | 4150 | |
| 4145 | 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 | 4154 | urb->error_count = dwc2_hcd_urb_get_error_count(qtd->urb); |
| 4147 | 4155 | for (i = 0; i < urb->number_of_packets; ++i) { |
| 4148 | 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 | 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 | 4661 | if (dwc2_is_device_mode(hsotg)) |
| 4654 | 4662 | dwc2_gadget_exit_clock_gating(hsotg, 0); |
| 4655 | 4663 | else |
| @@ -5406,9 +5414,16 @@ int dwc2_backup_host_registers(struct dwc2_hsotg *hsotg) · 750 unmodified lines | ||
| 5406 | 5414 | /* Backup Host regs */ |
| 5407 | 5415 | hr = &hsotg->hr_backup; |
| 5408 | 5416 | hr->hcfg = dwc2_readl(hsotg, HCFG); |
| 5417 | + hr->hflbaddr = dwc2_readl(hsotg, HFLBADDR); | |
| 5409 | 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 | 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 | 5428 | hr->hprt0 = dwc2_read_hprt0(hsotg); |
| 5414 | 5429 | hr->hfir = dwc2_readl(hsotg, HFIR); |
| @@ -5442,10 +5457,17 @@ int dwc2_restore_host_registers(struct dwc2_hsotg *hsotg) · 27 unmodified lines | ||
| 5442 | 5457 | hr->valid = false; |
| 5443 | 5458 | |
| 5444 | 5459 | dwc2_writel(hsotg, hr->hcfg, HCFG); |
| 5460 | + dwc2_writel(hsotg, hr->hflbaddr, HFLBADDR); | |
| 5445 | 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 | 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 | 5472 | dwc2_writel(hsotg, hr->hprt0, HPRT0); |
| 5451 | 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 | 5632 | dwc2_writel(hsotg, hr->hcfg, HCFG); |
| 5611 | 5633 | |
| 5612 | 5634 | /* De-assert Wakeup Logic */ |
| 5613 | − gpwrdn = dwc2_readl(hsotg, GPWRDN); | |
| 5614 | − gpwrdn &= ~GPWRDN_PMUACTV; | |
| 5615 | − dwc2_writel(hsotg, gpwrdn, GPWRDN); | |
| 5616 | − udelay(10); | |
| 5635 | + if (!(rem_wakeup && hsotg->hw_params.snpsid >= DWC2_CORE_REV_4_30a)) { | |
| 5636 | + gpwrdn = dwc2_readl(hsotg, GPWRDN); | |
| 5637 | + gpwrdn &= ~GPWRDN_PMUACTV; | |
| 5638 | + dwc2_writel(hsotg, gpwrdn, GPWRDN); | |
| 5639 | + udelay(10); | |
| 5640 | + } | |
| 5617 | 5641 | |
| 5618 | 5642 | hprt0 = hr->hprt0; |
| 5619 | 5643 | hprt0 |= HPRT0_PWR; |
| @@ -5638,6 +5662,13 @@ int dwc2_host_exit_hibernation(struct dwc2_hsotg *hsotg, int rem_wakeup, · 18 unmodified lines | ||
| 5638 | 5662 | hprt0 |= HPRT0_RES; |
| 5639 | 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 | 5672 | /* Wait for Resume time and then program HPRT again */ |
| 5642 | 5673 | mdelay(100); |
| 5643 | 5674 | hprt0 &= ~HPRT0_RES; |
| @@ -559,7 +559,7 @@ static void dwc2_init_isoc_dma_desc(struct dwc2_hsotg *hsotg, · 558 unmodified lines | ||
| 559 | 559 | idx = qh->td_last; |
| 560 | 560 | inc = qh->host_interval; |
| 561 | 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 | 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 | 867 | struct dwc2_dma_desc *dma_desc; |
| 868 | 868 | struct dwc2_hcd_iso_packet_desc *frame_desc; |
| 869 | + u16 frame_desc_idx; | |
| 870 | + struct urb *usb_urb = qtd->urb->priv; | |
| 869 | 871 | u16 remain = 0; |
| 870 | 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 | 880 | DMA_FROM_DEVICE); |
| 879 | 881 | |
| 880 | 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 | 888 | dma_desc->buf = (u32)(qtd->urb->dma + frame_desc->offset); |
| 884 | 889 | if (chan->ep_is_in) |
| 885 | 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 | 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 | 910 | * urb->status is not used for isoc transfers here. The |
| 906 | 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 | 1010 | return; |
| 1006 | 1011 | idx = dwc2_desclist_idx_inc(idx, qh->host_interval, |
| 1007 | 1012 | chan->speed); |
| 1008 | − if (!rc) | |
| 1013 | + if (rc == 0) | |
| 1009 | 1014 | continue; |
| 1010 | 1015 | |
| 1011 | − if (rc == DWC2_CMPL_DONE) | |
| 1012 | − break; | |
| 1016 | + if (rc == DWC2_CMPL_DONE || rc == DWC2_CMPL_STOP) | |
| 1017 | + goto stop_scan; | |
| 1013 | 1018 | |
| 1014 | 1019 | /* rc == DWC2_CMPL_STOP */ |
| 1015 | 1020 | |
| @@ -698,7 +698,7 @@ · 697 unmodified lines | ||
| 698 | 698 | #define TXSTS_QTOP_TOKEN_MASK (0x3 << 25) |
| 699 | 699 | #define TXSTS_QTOP_TOKEN_SHIFT 25 |
| 700 | 700 | #define TXSTS_QTOP_TERMINATE BIT(24) |
| 701 | −#define TXSTS_QSPCAVAIL_MASK (0xff << 16) | |
| 701 | +#define TXSTS_QSPCAVAIL_MASK (0x7f << 16) | |
| 702 | 702 | #define TXSTS_QSPCAVAIL_SHIFT 16 |
| 703 | 703 | #define TXSTS_FSPCAVAIL_MASK (0xffff << 0) |
| 704 | 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 | 332 | /* Exit clock gating when driver is removed. */ |
| 333 | 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 | 335 | if (dwc2_is_device_mode(hsotg)) |
| 336 | 336 | dwc2_gadget_exit_clock_gating(hsotg, 0); |
| 337 | 337 | else |
| @@ -1519,6 +1519,8 @@ static void dwc3_get_properties(struct dwc3 *dwc) · 1518 unmodified lines | ||
| 1519 | 1519 | else |
| 1520 | 1520 | dwc->sysdev = dwc->dev; |
| 1521 | 1521 | |
| 1522 | + dwc->sys_wakeup = device_may_wakeup(dwc->sysdev); | |
| 1523 | + | |
| 1522 | 1524 | ret = device_property_read_string(dev, "usb-psy-name", &usb_psy_name); |
| 1523 | 1525 | if (ret >= 0) { |
| 1524 | 1526 | dwc->usb_psy = power_supply_get_by_name(usb_psy_name); |
| @@ -1133,6 +1133,7 @@ struct dwc3_scratchpad_array { · 1132 unmodified lines | ||
| 1133 | 1133 | * 3 - Reserved |
| 1134 | 1134 | * @dis_metastability_quirk: set to disable metastability quirk. |
| 1135 | 1135 | * @dis_split_quirk: set to disable split boundary. |
| 1136 | + * @sys_wakeup: set if the device may do system wakeup. | |
| 1136 | 1137 | * @wakeup_configured: set if the device is configured for remote wakeup. |
| 1137 | 1138 | * @suspended: set to track suspend event due to U3/L2. |
| 1138 | 1139 | * @imod_interval: set the interrupt moderation interval in 250ns |
| @@ -1357,6 +1358,7 @@ struct dwc3 { · 218 unmodified lines | ||
| 1357 | 1358 | |
| 1358 | 1359 | unsigned dis_split_quirk:1; |
| 1359 | 1360 | unsigned async_callbacks:1; |
| 1361 | + unsigned sys_wakeup:1; | |
| 1360 | 1362 | unsigned wakeup_configured:1; |
| 1361 | 1363 | unsigned suspended:1; |
| 1362 | 1364 | |
| @@ -51,7 +51,6 @@ · 50 unmodified lines | ||
| 51 | 51 | #define PCI_DEVICE_ID_INTEL_MTLP 0x7ec1 |
| 52 | 52 | #define PCI_DEVICE_ID_INTEL_MTLS 0x7f6f |
| 53 | 53 | #define PCI_DEVICE_ID_INTEL_MTL 0x7e7e |
| 54 | −#define PCI_DEVICE_ID_INTEL_ARLH 0x7ec1 | |
| 55 | 54 | #define PCI_DEVICE_ID_INTEL_ARLH_PCH 0x777e |
| 56 | 55 | #define PCI_DEVICE_ID_INTEL_TGL 0x9a15 |
| 57 | 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 | 422 | { PCI_DEVICE_DATA(INTEL, MTLP, &dwc3_pci_intel_swnode) }, |
| 424 | 423 | { PCI_DEVICE_DATA(INTEL, MTL, &dwc3_pci_intel_swnode) }, |
| 425 | 424 | { PCI_DEVICE_DATA(INTEL, MTLS, &dwc3_pci_intel_swnode) }, |
| 426 | − { PCI_DEVICE_DATA(INTEL, ARLH, &dwc3_pci_intel_swnode) }, | |
| 427 | 425 | { PCI_DEVICE_DATA(INTEL, ARLH_PCH, &dwc3_pci_intel_swnode) }, |
| 428 | 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 | 2955 | dwc->gadget_driver = driver; |
| 2956 | 2956 | spin_unlock_irqrestore(&dwc->lock, flags); |
| 2957 | 2957 | |
| 2958 | + if (dwc->sys_wakeup) | |
| 2959 | + device_wakeup_enable(dwc->sysdev); | |
| 2960 | + | |
| 2958 | 2961 | return 0; |
| 2959 | 2962 | } |
| 2960 | 2963 | |
| @@ -2970,6 +2973,9 @@ static int dwc3_gadget_stop(struct usb_gadget *g) · 9 unmodified lines | ||
| 2970 | 2973 | struct dwc3 *dwc = gadget_to_dwc(g); |
| 2971 | 2974 | unsigned long flags; |
| 2972 | 2975 | |
| 2976 | + if (dwc->sys_wakeup) | |
| 2977 | + device_wakeup_disable(dwc->sysdev); | |
| 2978 | + | |
| 2973 | 2979 | spin_lock_irqsave(&dwc->lock, flags); |
| 2974 | 2980 | dwc->gadget_driver = NULL; |
| 2975 | 2981 | dwc->max_cfg_eps = 0; |
| @@ -4651,6 +4657,10 @@ int dwc3_gadget_init(struct dwc3 *dwc) · 1675 unmodified lines | ||
| 4651 | 4657 | else |
| 4652 | 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 | 4664 | return 0; |
| 4655 | 4665 | |
| 4656 | 4666 | err5: |
| @@ -173,6 +173,14 @@ int dwc3_host_init(struct dwc3 *dwc) · 172 unmodified lines | ||
| 173 | 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 | 184 | return 0; |
| 177 | 185 | err: |
| 178 | 186 | platform_device_put(xhci); |
| @@ -181,6 +189,9 @@ err: · 2 unmodified lines | ||
| 181 | 189 | |
| 182 | 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 | 195 | platform_device_unregister(dwc->xhci); |
| 185 | 196 | dwc->xhci = NULL; |
| 186 | 197 | } |
| @@ -292,7 +292,9 @@ int usb_ep_queue(struct usb_ep *ep, · 291 unmodified lines | ||
| 292 | 292 | { |
| 293 | 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 | 298 | ret = -ESHUTDOWN; |
| 297 | 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 | 518 | int ret; |
| 519 | 519 | |
| 520 | 520 | client = kzalloc(sizeof *client, GFP_KERNEL); |
| 521 | − if (!client) | |
| 521 | + if (!client) { | |
| 522 | + kfree(data); | |
| 522 | 523 | return -ENOMEM; |
| 524 | + } | |
| 523 | 525 | |
| 524 | 526 | client->type = type; |
| 525 | 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 | 537 | auxdev->dev.release = ljca_auxdev_release; |
| 536 | 538 | |
| 537 | 539 | ret = auxiliary_device_init(auxdev); |
| 538 | − if (ret) | |
| 540 | + if (ret) { | |
| 541 | + kfree(data); | |
| 539 | 542 | goto err_free; |
| 543 | + } | |
| 540 | 544 | |
| 541 | 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 | 594 | valid_pin[i] = get_unaligned_le32(&desc->bank_desc[i].valid_pins); |
| 591 | 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 | 598 | gpio_info, LJCA_GPIO_ACPI_ADR); |
| 595 | − if (ret) | |
| 596 | − kfree(gpio_info); | |
| 597 | − | |
| 598 | − return ret; | |
| 599 | 599 | } |
| 600 | 600 | |
| 601 | 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 | 629 | ret = ljca_new_client_device(adap, LJCA_CLIENT_I2C, i, |
| 630 | 630 | "ljca-i2c", i2c_info, |
| 631 | 631 | LJCA_I2C1_ACPI_ADR + i); |
| 632 | − if (ret) { | |
| 633 | − kfree(i2c_info); | |
| 632 | + if (ret) | |
| 634 | 633 | return ret; |
| 635 | − } | |
| 636 | 634 | } |
| 637 | 635 | |
| 638 | 636 | return 0; |
| @@ -669,10 +667,8 @@ static int ljca_enumerate_spi(struct ljca_adapter *adap) · 30 unmodified lines | ||
| 669 | 667 | ret = ljca_new_client_device(adap, LJCA_CLIENT_SPI, i, |
| 670 | 668 | "ljca-spi", spi_info, |
| 671 | 669 | LJCA_SPI1_ACPI_ADR + i); |
| 672 | − if (ret) { | |
| 673 | − kfree(spi_info); | |
| 670 | + if (ret) | |
| 674 | 671 | return ret; |
| 675 | − } | |
| 676 | 672 | } |
| 677 | 673 | |
| 678 | 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 | 262 | return dev_err_probe(dev, PTR_ERR(nop->vbus_draw), |
| 263 | 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 | 265 | nop->dev = dev; |
| 273 | 266 | nop->phy.dev = nop->dev; |
| 274 | 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 | 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 | 538 | struct uas_dev_info *devinfo = cmnd->device->hostdata; |
| 539 | 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 | 542 | urb = uas_alloc_sense_urb(devinfo, gfp, cmnd); |
| 543 | 543 | if (!urb) |
| 544 | − return NULL; | |
| 544 | + return -ENOMEM; | |
| 545 | 545 | usb_anchor_urb(urb, &devinfo->sense_urbs); |
| 546 | 546 | err = usb_submit_urb(urb, gfp); |
| 547 | 547 | if (err) { |
| 548 | 548 | usb_unanchor_urb(urb); |
| 549 | 549 | uas_log_cmd_state(cmnd, "sense submit err", err); |
| 550 | 550 | usb_free_urb(urb); |
| 551 | − return NULL; | |
| 552 | 551 | } |
| 553 | − return urb; | |
| 552 | + return err; | |
| 554 | 553 | } |
| 555 | 554 | |
| 556 | 555 | static int uas_submit_urbs(struct scsi_cmnd *cmnd, |
| 557 | 556 | struct uas_dev_info *devinfo) |
| 558 | 557 | { |
| 559 | 558 | struct uas_cmd_info *cmdinfo = scsi_cmd_priv(cmnd); |
| 560 | − struct urb *urb; | |
| 561 | 559 | int err; |
| 562 | 560 | |
| 563 | 561 | lockdep_assert_held(&devinfo->lock); |
| 564 | 562 | if (cmdinfo->state & SUBMIT_STATUS_URB) { |
| 565 | − urb = uas_submit_sense_urb(cmnd, GFP_ATOMIC); | |
| 566 | − if (!urb) | |
| 567 | − return SCSI_MLQUEUE_DEVICE_BUSY; | |
| 563 | + err = uas_submit_sense_urb(cmnd, GFP_ATOMIC); | |
| 564 | + if (err) | |
| 565 | + return err; | |
| 568 | 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 | 570 | cmdinfo->data_in_urb = uas_alloc_data_urb(devinfo, GFP_ATOMIC, |
| 573 | 571 | cmnd, DMA_FROM_DEVICE); |
| 574 | 572 | if (!cmdinfo->data_in_urb) |
| 575 | − return SCSI_MLQUEUE_DEVICE_BUSY; | |
| 573 | + return -ENOMEM; | |
| 576 | 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 | 580 | if (err) { |
| 583 | 581 | usb_unanchor_urb(cmdinfo->data_in_urb); |
| 584 | 582 | uas_log_cmd_state(cmnd, "data in submit err", err); |
| 585 | − return SCSI_MLQUEUE_DEVICE_BUSY; | |
| 583 | + return err; | |
| 586 | 584 | } |
| 587 | 585 | cmdinfo->state &= ~SUBMIT_DATA_IN_URB; |
| 588 | 586 | cmdinfo->state |= DATA_IN_URB_INFLIGHT; |
| @@ -592,7 +590,7 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd, · 3 unmodified lines | ||
| 592 | 590 | cmdinfo->data_out_urb = uas_alloc_data_urb(devinfo, GFP_ATOMIC, |
| 593 | 591 | cmnd, DMA_TO_DEVICE); |
| 594 | 592 | if (!cmdinfo->data_out_urb) |
| 595 | − return SCSI_MLQUEUE_DEVICE_BUSY; | |
| 593 | + return -ENOMEM; | |
| 596 | 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 | 600 | if (err) { |
| 603 | 601 | usb_unanchor_urb(cmdinfo->data_out_urb); |
| 604 | 602 | uas_log_cmd_state(cmnd, "data out submit err", err); |
| 605 | − return SCSI_MLQUEUE_DEVICE_BUSY; | |
| 603 | + return err; | |
| 606 | 604 | } |
| 607 | 605 | cmdinfo->state &= ~SUBMIT_DATA_OUT_URB; |
| 608 | 606 | cmdinfo->state |= DATA_OUT_URB_INFLIGHT; |
| @@ -611,7 +609,7 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd, · 2 unmodified lines | ||
| 611 | 609 | if (cmdinfo->state & ALLOC_CMD_URB) { |
| 612 | 610 | cmdinfo->cmd_urb = uas_alloc_cmd_urb(devinfo, GFP_ATOMIC, cmnd); |
| 613 | 611 | if (!cmdinfo->cmd_urb) |
| 614 | − return SCSI_MLQUEUE_DEVICE_BUSY; | |
| 612 | + return -ENOMEM; | |
| 615 | 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 | 619 | if (err) { |
| 622 | 620 | usb_unanchor_urb(cmdinfo->cmd_urb); |
| 623 | 621 | uas_log_cmd_state(cmnd, "cmd submit err", err); |
| 624 | − return SCSI_MLQUEUE_DEVICE_BUSY; | |
| 622 | + return err; | |
| 625 | 623 | } |
| 626 | 624 | cmdinfo->cmd_urb = NULL; |
| 627 | 625 | cmdinfo->state &= ~SUBMIT_CMD_URB; |
| @@ -698,7 +696,7 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd) · 70 unmodified lines | ||
| 698 | 696 | * of queueing, no matter how fatal the error |
| 699 | 697 | */ |
| 700 | 698 | if (err == -ENODEV) { |
| 701 | − set_host_byte(cmnd, DID_ERROR); | |
| 699 | + set_host_byte(cmnd, DID_NO_CONNECT); | |
| 702 | 700 | scsi_done(cmnd); |
| 703 | 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 | 1311 | struct typec_port *port = to_typec_port(dev); |
| 1312 | 1312 | struct usb_power_delivery *pd; |
| 1313 | + int ret; | |
| 1313 | 1314 | |
| 1314 | 1315 | if (!port->ops || !port->ops->pd_set) |
| 1315 | 1316 | return -EOPNOTSUPP; |
| @@ -1318,7 +1319,11 @@ static ssize_t select_usb_power_delivery_store(struct device *dev, · 2 unmodified lines | ||
| 1318 | 1319 | if (!pd) |
| 1319 | 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 | 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 | 6862 | if (data->source_desc.pdo[0]) { |
| 6863 | 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 | 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 | 6911 | port->port_source_caps = data->source_cap; |
| 6912 | 6912 | port->port_sink_caps = data->sink_cap; |
| 6913 | + typec_port_set_usb_power_delivery(p, NULL); | |
| 6913 | 6914 | port->selected_pd = pd; |
| 6915 | + typec_port_set_usb_power_delivery(p, port->selected_pd); | |
| 6914 | 6916 | unlock: |
| 6915 | 6917 | mutex_unlock(&port->lock); |
| 6916 | 6918 | return ret; |
| @@ -6943,9 +6945,7 @@ static void tcpm_port_unregister_pd(struct tcpm_port *port) · 26 unmodified lines | ||
| 6943 | 6945 | port->port_source_caps = NULL; |
| 6944 | 6946 | for (i = 0; i < port->pd_count; i++) { |
| 6945 | 6947 | usb_power_delivery_unregister_capabilities(port->pd_list[i]->sink_cap); |
| 6946 | − kfree(port->pd_list[i]->sink_cap); | |
| 6947 | 6948 | usb_power_delivery_unregister_capabilities(port->pd_list[i]->source_cap); |
| 6948 | − kfree(port->pd_list[i]->source_cap); | |
| 6949 | 6949 | devm_kfree(port->dev, port->pd_list[i]); |
| 6950 | 6950 | port->pd_list[i] = NULL; |
| 6951 | 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 | 151 | if (!(cci & UCSI_CCI_COMMAND_COMPLETE)) |
| 152 | 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 | 158 | return -EOPNOTSUPP; |
| 159 | + } | |
| 156 | 160 | |
| 157 | 161 | if (cci & UCSI_CCI_ERROR) { |
| 158 | 162 | if (cmd == UCSI_GET_ERROR_STATUS) |
| @@ -1133,17 +1137,21 @@ static int ucsi_check_cable(struct ucsi_connector *con) · 974 unmodified lines | ||
| 1133 | 1137 | if (ret < 0) |
| 1134 | 1138 | return ret; |
| 1135 | 1139 | |
| 1136 | − ret = ucsi_get_cable_identity(con); | |
| 1137 | − if (ret < 0) | |
| 1138 | − return ret; | |
| 1140 | + if (con->ucsi->cap.features & UCSI_CAP_GET_PD_MESSAGE) { | |
| 1141 | + ret = ucsi_get_cable_identity(con); | |
| 1142 | + if (ret < 0) | |
| 1143 | + return ret; | |
| 1144 | + } | |
| 1139 | 1145 | |
| 1140 | − ret = ucsi_register_plug(con); | |
| 1141 | − if (ret < 0) | |
| 1142 | − return ret; | |
| 1146 | + if (con->ucsi->cap.features & UCSI_CAP_ALT_MODE_DETAILS) { | |
| 1147 | + ret = ucsi_register_plug(con); | |
| 1148 | + if (ret < 0) | |
| 1149 | + return ret; | |
| 1143 | 1150 | |
| 1144 | − ret = ucsi_register_altmodes(con, UCSI_RECIPIENT_SOP_P); | |
| 1145 | − if (ret < 0) | |
| 1146 | − return ret; | |
| 1151 | + ret = ucsi_register_altmodes(con, UCSI_RECIPIENT_SOP_P); | |
| 1152 | + if (ret < 0) | |
| 1153 | + return ret; | |
| 1154 | + } | |
| 1147 | 1155 | |
| 1148 | 1156 | return 0; |
| 1149 | 1157 | } |
| @@ -1189,8 +1197,10 @@ static void ucsi_handle_connector_change(struct work_struct *work) · 39 unmodified lines | ||
| 1189 | 1197 | ucsi_register_partner(con); |
| 1190 | 1198 | ucsi_partner_task(con, ucsi_check_connection, 1, HZ); |
| 1191 | 1199 | ucsi_partner_task(con, ucsi_check_connector_capability, 1, HZ); |
| 1192 | − ucsi_partner_task(con, ucsi_get_partner_identity, 1, HZ); | |
| 1193 | − ucsi_partner_task(con, ucsi_check_cable, 1, HZ); | |
| 1200 | + if (con->ucsi->cap.features & UCSI_CAP_GET_PD_MESSAGE) | |
| 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 | 1205 | if (UCSI_CONSTAT_PWR_OPMODE(con->status.flags) == |
| 1196 | 1206 | UCSI_CONSTAT_PWR_OPMODE_PD) |
| @@ -1215,11 +1225,11 @@ static void ucsi_handle_connector_change(struct work_struct *work) · 18 unmodified lines | ||
| 1215 | 1225 | if (con->status.change & UCSI_CONSTAT_CAM_CHANGE) |
| 1216 | 1226 | ucsi_partner_task(con, ucsi_check_altmodes, 1, 0); |
| 1217 | 1227 | |
| 1218 | − clear_bit(EVENT_PENDING, &con->ucsi->flags); | |
| 1219 | − | |
| 1220 | 1228 | mutex_lock(&ucsi->ppm_lock); |
| 1229 | + clear_bit(EVENT_PENDING, &con->ucsi->flags); | |
| 1221 | 1230 | ret = ucsi_acknowledge_connector_change(ucsi); |
| 1222 | 1231 | mutex_unlock(&ucsi->ppm_lock); |
| 1232 | + | |
| 1223 | 1233 | if (ret) |
| 1224 | 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 | 1247 | struct ucsi_connector *con = &ucsi->connector[num - 1]; |
| 1238 | 1248 | |
| 1239 | 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 | 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 | 1271 | static int ucsi_reset_ppm(struct ucsi *ucsi) |
| 1262 | 1272 | { |
| 1263 | − u64 command = UCSI_PPM_RESET; | |
| 1273 | + u64 command; | |
| 1264 | 1274 | unsigned long tmo; |
| 1265 | 1275 | u32 cci; |
| 1266 | 1276 | int ret; |
| 1267 | 1277 | |
| 1268 | 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 | 1314 | ret = ucsi->ops->async_write(ucsi, UCSI_CONTROL, &command, |
| 1271 | 1315 | sizeof(command)); |
| 1272 | 1316 | if (ret < 0) |
| @@ -1589,8 +1633,10 @@ static int ucsi_register_port(struct ucsi *ucsi, struct ucsi_connector *con) · 316 unmodified lines | ||
| 1589 | 1633 | ucsi_register_partner(con); |
| 1590 | 1634 | ucsi_pwr_opmode_change(con); |
| 1591 | 1635 | ucsi_port_psy_changed(con); |
| 1592 | − ucsi_get_partner_identity(con); | |
| 1593 | − ucsi_check_cable(con); | |
| 1636 | + if (con->ucsi->cap.features & UCSI_CAP_GET_PD_MESSAGE) | |
| 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 | 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 | 1683 | struct ucsi_connector *con, *connector; |
| 1638 | 1684 | u64 command, ntfy; |
| 1685 | + u32 cci; | |
| 1639 | 1686 | int ret; |
| 1640 | 1687 | int i; |
| 1641 | 1688 | |
| @@ -1688,6 +1735,13 @@ static int ucsi_init(struct ucsi *ucsi) · 46 unmodified lines | ||
| 1688 | 1735 | |
| 1689 | 1736 | ucsi->connector = connector; |
| 1690 | 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 | 1745 | return 0; |
| 1692 | 1746 | |
| 1693 | 1747 | err_unregister: |
| @@ -206,7 +206,7 @@ struct ucsi_capability { · 205 unmodified lines | ||
| 206 | 206 | #define UCSI_CAP_ATTR_POWER_OTHER BIT(10) |
| 207 | 207 | #define UCSI_CAP_ATTR_POWER_VBUS BIT(14) |
| 208 | 208 | u8 num_connectors; |
| 209 | − u8 features; | |
| 209 | + u16 features; | |
| 210 | 210 | #define UCSI_CAP_SET_UOM BIT(0) |
| 211 | 211 | #define UCSI_CAP_SET_PDM BIT(1) |
| 212 | 212 | #define UCSI_CAP_ALT_MODE_DETAILS BIT(2) |
| @@ -215,7 +215,8 @@ struct ucsi_capability { · 2 unmodified lines | ||
| 215 | 215 | #define UCSI_CAP_CABLE_DETAILS BIT(5) |
| 216 | 216 | #define UCSI_CAP_EXT_SUPPLY_NOTIFICATIONS BIT(6) |
| 217 | 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 | 220 | u8 num_alt_modes; |
| 220 | 221 | u8 reserved_2; |
| 221 | 222 | u16 bc_version; |
| @@ -23,10 +23,11 @@ struct ucsi_acpi { · 22 unmodified lines | ||
| 23 | 23 | void *base; |
| 24 | 24 | struct completion complete; |
| 25 | 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 | 29 | guid_t guid; |
| 27 | 30 | u64 cmd; |
| 28 | − bool dell_quirk_probed; | |
| 29 | − bool dell_quirk_active; | |
| 30 | 31 | }; |
| 31 | 32 | |
| 32 | 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 | 80 | int ret; |
| 80 | 81 | |
| 81 | 82 | if (ack) |
| 82 | − set_bit(ACK_PENDING, &ua->flags); | |
| 83 | + set_bit(UCSI_ACPI_ACK_PENDING, &ua->flags); | |
| 83 | 84 | else |
| 84 | − set_bit(COMMAND_PENDING, &ua->flags); | |
| 85 | + set_bit(UCSI_ACPI_COMMAND_PENDING, &ua->flags); | |
| 85 | 86 | |
| 86 | 87 | ret = ucsi_acpi_async_write(ucsi, offset, val, val_len); |
| 87 | 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 | 94 | out_clear_bit: |
| 94 | 95 | if (ack) |
| 95 | − clear_bit(ACK_PENDING, &ua->flags); | |
| 96 | + clear_bit(UCSI_ACPI_ACK_PENDING, &ua->flags); | |
| 96 | 97 | else |
| 97 | − clear_bit(COMMAND_PENDING, &ua->flags); | |
| 98 | + clear_bit(UCSI_ACPI_COMMAND_PENDING, &ua->flags); | |
| 98 | 99 | |
| 99 | 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 | − * UCSI_ACK_CONNECTOR_CHANGE bit set is followed by a (separate) | |
| 134 | − * ACK command that only has the UCSI_ACK_COMMAND_COMPLETE bit set. | |
| 135 | − * If this is not done events are not delivered to OSPM and | |
| 136 | − * subsequent commands will timeout. | |
| 133 | + * Some Dell laptops don't like ACK commands with the | |
| 134 | + * UCSI_ACK_CONNECTOR_CHANGE but not the UCSI_ACK_COMMAND_COMPLETE | |
| 135 | + * bit set. To work around this send a dummy command and bundle the | |
| 136 | + * UCSI_ACK_CONNECTOR_CHANGE with the UCSI_ACK_COMMAND_COMPLETE | |
| 137 | + * for the dummy command. | |
| 137 | 138 | */ |
| 138 | 139 | static int |
| 139 | 140 | ucsi_dell_sync_write(struct ucsi *ucsi, unsigned int offset, |
| 140 | 141 | const void *val, size_t val_len) |
| 141 | 142 | { |
| 142 | 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 | 146 | int ret; |
| 145 | 147 | |
| 146 | − if (UCSI_COMMAND(cmd) == UCSI_ACK_CC_CI && | |
| 147 | − cmd & UCSI_ACK_CONNECTOR_CHANGE) | |
| 148 | − ack = UCSI_ACK_CC_CI | UCSI_ACK_COMMAND_COMPLETE; | |
| 149 | − | |
| 150 | − ret = ucsi_acpi_sync_write(ucsi, offset, val, val_len); | |
| 151 | − if (ret != 0) | |
| 152 | − return ret; | |
| 153 | − if (ack == 0) | |
| 154 | − return ret; | |
| 155 | − | |
| 156 | − if (!ua->dell_quirk_probed) { | |
| 157 | − ua->dell_quirk_probed = true; | |
| 158 | − | |
| 159 | − cmd = UCSI_GET_CAPABILITY; | |
| 160 | − ret = ucsi_acpi_sync_write(ucsi, UCSI_CONTROL, &cmd, | |
| 161 | − sizeof(cmd)); | |
| 162 | − if (ret == 0) | |
| 163 | − return ucsi_acpi_sync_write(ucsi, UCSI_CONTROL, | |
| 164 | − &ack, sizeof(ack)); | |
| 165 | − if (ret != -ETIMEDOUT) | |
| 148 | + if (cmd == (UCSI_ACK_CC_CI | UCSI_ACK_CONNECTOR_CHANGE)) { | |
| 149 | + cmd |= UCSI_ACK_COMMAND_COMPLETE; | |
| 150 | + | |
| 151 | + /* | |
| 152 | + * The UCSI core thinks it is sending a connector change ack | |
| 153 | + * and will accept new connector change events. We don't want | |
| 154 | + * this to happen for the dummy command as its response will | |
| 155 | + * still report the very event that the core is trying to clear. | |
| 156 | + */ | |
| 157 | + set_bit(UCSI_ACPI_SUPPRESS_EVENT, &ua->flags); | |
| 158 | + ret = ucsi_acpi_sync_write(ucsi, UCSI_CONTROL, &dummycmd, | |
| 159 | + sizeof(dummycmd)); | |
| 160 | + clear_bit(UCSI_ACPI_SUPPRESS_EVENT, &ua->flags); | |
| 161 | + | |
| 162 | + if (ret < 0) | |
| 166 | 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) | |
| 174 | − return ret; | |
| 175 | − | |
| 176 | − return ucsi_acpi_sync_write(ucsi, UCSI_CONTROL, &ack, sizeof(ack)); | |
| 166 | + return ucsi_acpi_sync_write(ucsi, UCSI_CONTROL, &cmd, sizeof(cmd)); | |
| 177 | 167 | } |
| 178 | 168 | |
| 179 | 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 | 199 | if (ret) |
| 210 | 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 | 204 | ucsi_connector_change(ua->ucsi, UCSI_CCI_CONNECTOR(cci)); |
| 214 | 205 | |
| 215 | 206 | if (cci & UCSI_CCI_ACK_COMPLETE && test_bit(ACK_PENDING, &ua->flags)) |
| 216 | 207 | complete(&ua->complete); |
| 217 | 208 | if (cci & UCSI_CCI_COMMAND_COMPLETE && |
| 218 | − test_bit(COMMAND_PENDING, &ua->flags)) | |
| 209 | + test_bit(UCSI_ACPI_COMMAND_PENDING, &ua->flags)) | |
| 219 | 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 | 255 | static void pmic_glink_ucsi_register(struct work_struct *work) |
| 256 | 256 | { |
| 257 | 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 | 273 | ucsi_register(ucsi->ucsi); |
| 260 | 274 | } |