Pull USB fixes from Greg KH: "Here are some small fixes for reported issues with some USB drivers. They include: - xhci fixes for xhci-mtk platform driver - typec driver fixes for reported problems. - cdc-wdm read-stuck fix - gadget driver fix for reported race condition - new usb-serial driver ids All of these have been in linux-next with no reported problems" * tag 'usb-5.18-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: usb: xhci-mtk: remove bandwidth budget table usb: xhci-mtk: fix fs isoc's transfer error usb: gadget: fix race when gadget driver register via ioctl usb: typec: tcpci_mt6360: Update for BMC PHY setting usb: gadget: uvc: allow for application to cleanly shutdown usb: typec: tcpci: Don't skip cleanup in .remove() on error usb: cdc-wdm: fix reading stuck on device close USB: serial: qcserial: add support for Sierra Wireless EM7590 USB: serial: option: add Fibocom MA510 modem USB: serial: option: add Fibocom L610 modem USB: serial: pl2303: add device id for HP LM930 Display
Unified · Split
| @@ -774,6 +774,7 @@ static int wdm_release(struct inode *inode, struct file *file) · 773 unmodified lines | ||
| 774 | 774 | poison_urbs(desc); |
| 775 | 775 | spin_lock_irq(&desc->iuspin); |
| 776 | 776 | desc->resp_count = 0; |
| 777 | + clear_bit(WDM_RESPONDING, &desc->flags); | |
| 777 | 778 | spin_unlock_irq(&desc->iuspin); |
| 778 | 779 | desc->manage_power(desc->intf, 0); |
| 779 | 780 | unpoison_urbs(desc); |
| @@ -890,13 +890,37 @@ static void uvc_function_unbind(struct usb_configuration *c, · 889 unmodified lines | ||
| 890 | 890 | { |
| 891 | 891 | struct usb_composite_dev *cdev = c->cdev; |
| 892 | 892 | struct uvc_device *uvc = to_uvc(f); |
| 893 | + long wait_ret = 1; | |
| 893 | 894 | |
| 894 | 895 | uvcg_info(f, "%s()\n", __func__); |
| 895 | 896 | |
| 897 | + /* If we know we're connected via v4l2, then there should be a cleanup | |
| 898 | + * of the device from userspace either via UVC_EVENT_DISCONNECT or | |
| 899 | + * though the video device removal uevent. Allow some time for the | |
| 900 | + * application to close out before things get deleted. | |
| 901 | + */ | |
| 902 | + if (uvc->func_connected) { | |
| 903 | + uvcg_dbg(f, "waiting for clean disconnect\n"); | |
| 904 | + wait_ret = wait_event_interruptible_timeout(uvc->func_connected_queue, | |
| 905 | + uvc->func_connected == false, msecs_to_jiffies(500)); | |
| 906 | + uvcg_dbg(f, "done waiting with ret: %ld\n", wait_ret); | |
| 907 | + } | |
| 908 | + | |
| 896 | 909 | device_remove_file(&uvc->vdev.dev, &dev_attr_function_name); |
| 897 | 910 | video_unregister_device(&uvc->vdev); |
| 898 | 911 | v4l2_device_unregister(&uvc->v4l2_dev); |
| 899 | 912 | |
| 913 | + if (uvc->func_connected) { | |
| 914 | + /* Wait for the release to occur to ensure there are no longer any | |
| 915 | + * pending operations that may cause panics when resources are cleaned | |
| 916 | + * up. | |
| 917 | + */ | |
| 918 | + uvcg_warn(f, "%s no clean disconnect, wait for release\n", __func__); | |
| 919 | + wait_ret = wait_event_interruptible_timeout(uvc->func_connected_queue, | |
| 920 | + uvc->func_connected == false, msecs_to_jiffies(1000)); | |
| 921 | + uvcg_dbg(f, "done waiting for release with ret: %ld\n", wait_ret); | |
| 922 | + } | |
| 923 | + | |
| 900 | 924 | usb_ep_free_request(cdev->gadget->ep0, uvc->control_req); |
| 901 | 925 | kfree(uvc->control_buf); |
| 902 | 926 | |
| @@ -915,6 +939,7 @@ static struct usb_function *uvc_alloc(struct usb_function_instance *fi) · 12 unmodified lines | ||
| 915 | 939 | |
| 916 | 940 | mutex_init(&uvc->video.mutex); |
| 917 | 941 | uvc->state = UVC_STATE_DISCONNECTED; |
| 942 | + init_waitqueue_head(&uvc->func_connected_queue); | |
| 918 | 943 | opts = fi_to_f_uvc_opts(fi); |
| 919 | 944 | |
| 920 | 945 | mutex_lock(&opts->lock); |
| @@ -14,6 +14,7 @@ · 13 unmodified lines | ||
| 14 | 14 | #include <linux/spinlock.h> |
| 15 | 15 | #include <linux/usb/composite.h> |
| 16 | 16 | #include <linux/videodev2.h> |
| 17 | +#include <linux/wait.h> | |
| 17 | 18 | |
| 18 | 19 | #include <media/v4l2-device.h> |
| 19 | 20 | #include <media/v4l2-dev.h> |
| @@ -129,6 +130,7 @@ struct uvc_device { · 109 unmodified lines | ||
| 129 | 130 | struct usb_function func; |
| 130 | 131 | struct uvc_video video; |
| 131 | 132 | bool func_connected; |
| 133 | + wait_queue_head_t func_connected_queue; | |
| 132 | 134 | |
| 133 | 135 | /* Descriptors */ |
| 134 | 136 | struct { |
| @@ -253,10 +253,11 @@ uvc_v4l2_subscribe_event(struct v4l2_fh *fh, · 252 unmodified lines | ||
| 253 | 253 | |
| 254 | 254 | static void uvc_v4l2_disable(struct uvc_device *uvc) |
| 255 | 255 | { |
| 256 | − uvc->func_connected = false; | |
| 257 | 256 | uvc_function_disconnect(uvc); |
| 258 | 257 | uvcg_video_enable(&uvc->video, 0); |
| 259 | 258 | uvcg_free_buffers(&uvc->video.queue); |
| 259 | + uvc->func_connected = false; | |
| 260 | + wake_up_interruptible(&uvc->func_connected_queue); | |
| 260 | 261 | } |
| 261 | 262 | |
| 262 | 263 | static int |
| @@ -145,6 +145,7 @@ enum dev_state { · 144 unmodified lines | ||
| 145 | 145 | STATE_DEV_INVALID = 0, |
| 146 | 146 | STATE_DEV_OPENED, |
| 147 | 147 | STATE_DEV_INITIALIZED, |
| 148 | + STATE_DEV_REGISTERING, | |
| 148 | 149 | STATE_DEV_RUNNING, |
| 149 | 150 | STATE_DEV_CLOSED, |
| 150 | 151 | STATE_DEV_FAILED |
| @@ -508,6 +509,7 @@ static int raw_ioctl_run(struct raw_dev *dev, unsigned long value) · 357 unmodified lines | ||
| 508 | 509 | ret = -EINVAL; |
| 509 | 510 | goto out_unlock; |
| 510 | 511 | } |
| 512 | + dev->state = STATE_DEV_REGISTERING; | |
| 511 | 513 | spin_unlock_irqrestore(&dev->lock, flags); |
| 512 | 514 | |
| 513 | 515 | ret = usb_gadget_probe_driver(&dev->driver); |
| @@ -19,11 +19,6 @@ · 18 unmodified lines | ||
| 19 | 19 | #define HS_BW_BOUNDARY 6144 |
| 20 | 20 | /* usb2 spec section11.18.1: at most 188 FS bytes per microframe */ |
| 21 | 21 | #define FS_PAYLOAD_MAX 188 |
| 22 | −/* | |
| 23 | − * max number of microframes for split transfer, | |
| 24 | − * for fs isoc in : 1 ss + 1 idle + 7 cs | |
| 25 | − */ | |
| 26 | −#define TT_MICROFRAMES_MAX 9 | |
| 27 | 22 | |
| 28 | 23 | #define DBG_BUF_EN 64 |
| 29 | 24 | |
| @@ -242,28 +237,17 @@ static void drop_tt(struct usb_device *udev) · 212 unmodified lines | ||
| 242 | 237 | |
| 243 | 238 | static struct mu3h_sch_ep_info * |
| 244 | 239 | create_sch_ep(struct xhci_hcd_mtk *mtk, struct usb_device *udev, |
| 245 | − struct usb_host_endpoint *ep, struct xhci_ep_ctx *ep_ctx) | |
| 240 | + struct usb_host_endpoint *ep) | |
| 246 | 241 | { |
| 247 | 242 | struct mu3h_sch_ep_info *sch_ep; |
| 248 | 243 | struct mu3h_sch_bw_info *bw_info; |
| 249 | 244 | struct mu3h_sch_tt *tt = NULL; |
| 250 | − u32 len_bw_budget_table; | |
| 251 | 245 | |
| 252 | 246 | bw_info = get_bw_info(mtk, udev, ep); |
| 253 | 247 | if (!bw_info) |
| 254 | 248 | return ERR_PTR(-ENODEV); |
| 255 | 249 | |
| 256 | − if (is_fs_or_ls(udev->speed)) | |
| 257 | − len_bw_budget_table = TT_MICROFRAMES_MAX; | |
| 258 | − else if ((udev->speed >= USB_SPEED_SUPER) | |
| 259 | − && usb_endpoint_xfer_isoc(&ep->desc)) | |
| 260 | − len_bw_budget_table = get_esit(ep_ctx); | |
| 261 | − else | |
| 262 | − len_bw_budget_table = 1; | |
| 263 | − | |
| 264 | − sch_ep = kzalloc(struct_size(sch_ep, bw_budget_table, | |
| 265 | − len_bw_budget_table), | |
| 266 | − GFP_KERNEL); | |
| 250 | + sch_ep = kzalloc(sizeof(*sch_ep), GFP_KERNEL); | |
| 267 | 251 | if (!sch_ep) |
| 268 | 252 | return ERR_PTR(-ENOMEM); |
| 269 | 253 | |
| @@ -295,8 +279,6 @@ static void setup_sch_info(struct xhci_ep_ctx *ep_ctx, · 25 unmodified lines | ||
| 295 | 279 | u32 mult; |
| 296 | 280 | u32 esit_pkts; |
| 297 | 281 | u32 max_esit_payload; |
| 298 | − u32 *bwb_table = sch_ep->bw_budget_table; | |
| 299 | − int i; | |
| 300 | 282 | |
| 301 | 283 | ep_type = CTX_TO_EP_TYPE(le32_to_cpu(ep_ctx->ep_info2)); |
| 302 | 284 | maxpkt = MAX_PACKET_DECODED(le32_to_cpu(ep_ctx->ep_info2)); |
| @@ -332,7 +314,6 @@ static void setup_sch_info(struct xhci_ep_ctx *ep_ctx, · 29 unmodified lines | ||
| 332 | 314 | */ |
| 333 | 315 | sch_ep->pkts = max_burst + 1; |
| 334 | 316 | sch_ep->bw_cost_per_microframe = maxpkt * sch_ep->pkts; |
| 335 | − bwb_table[0] = sch_ep->bw_cost_per_microframe; | |
| 336 | 317 | } else if (sch_ep->speed >= USB_SPEED_SUPER) { |
| 337 | 318 | /* usb3_r1 spec section4.4.7 & 4.4.8 */ |
| 338 | 319 | sch_ep->cs_count = 0; |
| @@ -349,7 +330,6 @@ static void setup_sch_info(struct xhci_ep_ctx *ep_ctx, · 10 unmodified lines | ||
| 349 | 330 | if (ep_type == INT_IN_EP || ep_type == INT_OUT_EP) { |
| 350 | 331 | sch_ep->pkts = esit_pkts; |
| 351 | 332 | sch_ep->num_budget_microframes = 1; |
| 352 | − bwb_table[0] = maxpkt * sch_ep->pkts; | |
| 353 | 333 | } |
| 354 | 334 | |
| 355 | 335 | if (ep_type == ISOC_IN_EP || ep_type == ISOC_OUT_EP) { |
| @@ -366,15 +346,8 @@ static void setup_sch_info(struct xhci_ep_ctx *ep_ctx, · 10 unmodified lines | ||
| 366 | 346 | DIV_ROUND_UP(esit_pkts, sch_ep->pkts); |
| 367 | 347 | |
| 368 | 348 | sch_ep->repeat = !!(sch_ep->num_budget_microframes > 1); |
| 369 | − sch_ep->bw_cost_per_microframe = maxpkt * sch_ep->pkts; | |
| 370 | − | |
| 371 | − for (i = 0; i < sch_ep->num_budget_microframes - 1; i++) | |
| 372 | − bwb_table[i] = sch_ep->bw_cost_per_microframe; | |
| 373 | − | |
| 374 | − /* last one <= bw_cost_per_microframe */ | |
| 375 | − bwb_table[i] = maxpkt * esit_pkts | |
| 376 | − - i * sch_ep->bw_cost_per_microframe; | |
| 377 | 349 | } |
| 350 | + sch_ep->bw_cost_per_microframe = maxpkt * sch_ep->pkts; | |
| 378 | 351 | } else if (is_fs_or_ls(sch_ep->speed)) { |
| 379 | 352 | sch_ep->pkts = 1; /* at most one packet for each microframe */ |
| 380 | 353 | |
| @@ -384,28 +357,7 @@ static void setup_sch_info(struct xhci_ep_ctx *ep_ctx, · 3 unmodified lines | ||
| 384 | 357 | */ |
| 385 | 358 | sch_ep->cs_count = DIV_ROUND_UP(maxpkt, FS_PAYLOAD_MAX); |
| 386 | 359 | sch_ep->num_budget_microframes = sch_ep->cs_count; |
| 387 | − sch_ep->bw_cost_per_microframe = | |
| 388 | − (maxpkt < FS_PAYLOAD_MAX) ? maxpkt : FS_PAYLOAD_MAX; | |
| 389 | − | |
| 390 | − /* init budget table */ | |
| 391 | − if (ep_type == ISOC_OUT_EP) { | |
| 392 | − for (i = 0; i < sch_ep->num_budget_microframes; i++) | |
| 393 | − bwb_table[i] = sch_ep->bw_cost_per_microframe; | |
| 394 | − } else if (ep_type == INT_OUT_EP) { | |
| 395 | − /* only first one consumes bandwidth, others as zero */ | |
| 396 | − bwb_table[0] = sch_ep->bw_cost_per_microframe; | |
| 397 | − } else { /* INT_IN_EP or ISOC_IN_EP */ | |
| 398 | − bwb_table[0] = 0; /* start split */ | |
| 399 | − bwb_table[1] = 0; /* idle */ | |
| 400 | − /* | |
| 401 | − * due to cs_count will be updated according to cs | |
| 402 | − * position, assign all remainder budget array | |
| 403 | − * elements as @bw_cost_per_microframe, but only first | |
| 404 | − * @num_budget_microframes elements will be used later | |
| 405 | − */ | |
| 406 | − for (i = 2; i < TT_MICROFRAMES_MAX; i++) | |
| 407 | − bwb_table[i] = sch_ep->bw_cost_per_microframe; | |
| 408 | − } | |
| 360 | + sch_ep->bw_cost_per_microframe = min_t(u32, maxpkt, FS_PAYLOAD_MAX); | |
| 409 | 361 | } |
| 410 | 362 | } |
| 411 | 363 | |
| @@ -422,7 +374,7 @@ static u32 get_max_bw(struct mu3h_sch_bw_info *sch_bw, · 10 unmodified lines | ||
| 422 | 374 | |
| 423 | 375 | for (j = 0; j < sch_ep->num_budget_microframes; j++) { |
| 424 | 376 | k = XHCI_MTK_BW_INDEX(base + j); |
| 425 | − bw = sch_bw->bus_bw[k] + sch_ep->bw_budget_table[j]; | |
| 377 | + bw = sch_bw->bus_bw[k] + sch_ep->bw_cost_per_microframe; | |
| 426 | 378 | if (bw > max_bw) |
| 427 | 379 | max_bw = bw; |
| 428 | 380 | } |
| @@ -433,18 +385,16 @@ static u32 get_max_bw(struct mu3h_sch_bw_info *sch_bw, · 4 unmodified lines | ||
| 433 | 385 | static void update_bus_bw(struct mu3h_sch_bw_info *sch_bw, |
| 434 | 386 | struct mu3h_sch_ep_info *sch_ep, bool used) |
| 435 | 387 | { |
| 388 | + int bw_updated; | |
| 436 | 389 | u32 base; |
| 437 | − int i, j, k; | |
| 390 | + int i, j; | |
| 391 | + | |
| 392 | + bw_updated = sch_ep->bw_cost_per_microframe * (used ? 1 : -1); | |
| 438 | 393 | |
| 439 | 394 | for (i = 0; i < sch_ep->num_esit; i++) { |
| 440 | 395 | base = sch_ep->offset + i * sch_ep->esit; |
| 441 | − for (j = 0; j < sch_ep->num_budget_microframes; j++) { | |
| 442 | − k = XHCI_MTK_BW_INDEX(base + j); | |
| 443 | − if (used) | |
| 444 | − sch_bw->bus_bw[k] += sch_ep->bw_budget_table[j]; | |
| 445 | − else | |
| 446 | − sch_bw->bus_bw[k] -= sch_ep->bw_budget_table[j]; | |
| 447 | − } | |
| 396 | + for (j = 0; j < sch_ep->num_budget_microframes; j++) | |
| 397 | + sch_bw->bus_bw[XHCI_MTK_BW_INDEX(base + j)] += bw_updated; | |
| 448 | 398 | } |
| 449 | 399 | } |
| 450 | 400 | |
| @@ -464,7 +414,7 @@ static int check_fs_bus_bw(struct mu3h_sch_ep_info *sch_ep, int offset) · 13 unmodified lines | ||
| 464 | 414 | */ |
| 465 | 415 | for (j = 0; j < sch_ep->num_budget_microframes; j++) { |
| 466 | 416 | k = XHCI_MTK_BW_INDEX(base + j); |
| 467 | − tmp = tt->fs_bus_bw[k] + sch_ep->bw_budget_table[j]; | |
| 417 | + tmp = tt->fs_bus_bw[k] + sch_ep->bw_cost_per_microframe; | |
| 468 | 418 | if (tmp > FS_PAYLOAD_MAX) |
| 469 | 419 | return -ESCH_BW_OVERFLOW; |
| 470 | 420 | } |
| @@ -538,19 +488,17 @@ static int check_sch_tt(struct mu3h_sch_ep_info *sch_ep, u32 offset) · 67 unmodified lines | ||
| 538 | 488 | static void update_sch_tt(struct mu3h_sch_ep_info *sch_ep, bool used) |
| 539 | 489 | { |
| 540 | 490 | struct mu3h_sch_tt *tt = sch_ep->sch_tt; |
| 491 | + int bw_updated; | |
| 541 | 492 | u32 base; |
| 542 | − int i, j, k; | |
| 493 | + int i, j; | |
| 494 | + | |
| 495 | + bw_updated = sch_ep->bw_cost_per_microframe * (used ? 1 : -1); | |
| 543 | 496 | |
| 544 | 497 | for (i = 0; i < sch_ep->num_esit; i++) { |
| 545 | 498 | base = sch_ep->offset + i * sch_ep->esit; |
| 546 | 499 | |
| 547 | − for (j = 0; j < sch_ep->num_budget_microframes; j++) { | |
| 548 | − k = XHCI_MTK_BW_INDEX(base + j); | |
| 549 | − if (used) | |
| 550 | − tt->fs_bus_bw[k] += sch_ep->bw_budget_table[j]; | |
| 551 | − else | |
| 552 | − tt->fs_bus_bw[k] -= sch_ep->bw_budget_table[j]; | |
| 553 | − } | |
| 500 | + for (j = 0; j < sch_ep->num_budget_microframes; j++) | |
| 501 | + tt->fs_bus_bw[XHCI_MTK_BW_INDEX(base + j)] += bw_updated; | |
| 554 | 502 | } |
| 555 | 503 | |
| 556 | 504 | if (used) |
| @@ -710,7 +658,7 @@ static int add_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev, · 153 unmodified lines | ||
| 710 | 658 | |
| 711 | 659 | xhci_dbg(xhci, "%s %s\n", __func__, decode_ep(ep, udev->speed)); |
| 712 | 660 | |
| 713 | − sch_ep = create_sch_ep(mtk, udev, ep, ep_ctx); | |
| 661 | + sch_ep = create_sch_ep(mtk, udev, ep); | |
| 714 | 662 | if (IS_ERR_OR_NULL(sch_ep)) |
| 715 | 663 | return -ENOMEM; |
| 716 | 664 | |
| @@ -83,7 +83,6 @@ struct mu3h_sch_bw_info { · 82 unmodified lines | ||
| 83 | 83 | * times; 1: distribute the (bMaxBurst+1)*(Mult+1) packets |
| 84 | 84 | * according to @pkts and @repeat. normal mode is used by |
| 85 | 85 | * default |
| 86 | − * @bw_budget_table: table to record bandwidth budget per microframe | |
| 87 | 86 | */ |
| 88 | 87 | struct mu3h_sch_ep_info { |
| 89 | 88 | u32 esit; |
| @@ -109,7 +108,6 @@ struct mu3h_sch_ep_info { · 19 unmodified lines | ||
| 109 | 108 | u32 pkts; |
| 110 | 109 | u32 cs_count; |
| 111 | 110 | u32 burst_mode; |
| 112 | − u32 bw_budget_table[]; | |
| 113 | 111 | }; |
| 114 | 112 | |
| 115 | 113 | #define MU3C_U3_PORT_MAX 4 |
| @@ -2123,10 +2123,14 @@ static const struct usb_device_id option_ids[] = { · 2122 unmodified lines | ||
| 2123 | 2123 | .driver_info = RSVD(3) }, |
| 2124 | 2124 | { USB_DEVICE(0x1508, 0x1001), /* Fibocom NL668 (IOT version) */ |
| 2125 | 2125 | .driver_info = RSVD(4) | RSVD(5) | RSVD(6) }, |
| 2126 | + { USB_DEVICE(0x1782, 0x4d10) }, /* Fibocom L610 (AT mode) */ | |
| 2127 | + { USB_DEVICE_INTERFACE_CLASS(0x1782, 0x4d11, 0xff) }, /* Fibocom L610 (ECM/RNDIS mode) */ | |
| 2126 | 2128 | { USB_DEVICE(0x2cb7, 0x0104), /* Fibocom NL678 series */ |
| 2127 | 2129 | .driver_info = RSVD(4) | RSVD(5) }, |
| 2128 | 2130 | { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0105, 0xff), /* Fibocom NL678 series */ |
| 2129 | 2131 | .driver_info = RSVD(6) }, |
| 2132 | + { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0106, 0xff) }, /* Fibocom MA510 (ECM mode w/ diag intf.) */ | |
| 2133 | + { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x010a, 0xff) }, /* Fibocom MA510 (ECM mode) */ | |
| 2130 | 2134 | { USB_DEVICE_AND_INTERFACE_INFO(0x2cb7, 0x010b, 0xff, 0xff, 0x30) }, /* Fibocom FG150 Diag */ |
| 2131 | 2135 | { USB_DEVICE_AND_INTERFACE_INFO(0x2cb7, 0x010b, 0xff, 0, 0) }, /* Fibocom FG150 AT */ |
| 2132 | 2136 | { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x01a0, 0xff) }, /* Fibocom NL668-AM/NL652-EU (laptop MBIM) */ |
| @@ -106,6 +106,7 @@ static const struct usb_device_id id_table[] = { · 105 unmodified lines | ||
| 106 | 106 | { USB_DEVICE(HP_VENDOR_ID, HP_LCM220_PRODUCT_ID) }, |
| 107 | 107 | { USB_DEVICE(HP_VENDOR_ID, HP_LCM960_PRODUCT_ID) }, |
| 108 | 108 | { USB_DEVICE(HP_VENDOR_ID, HP_LM920_PRODUCT_ID) }, |
| 109 | + { USB_DEVICE(HP_VENDOR_ID, HP_LM930_PRODUCT_ID) }, | |
| 109 | 110 | { USB_DEVICE(HP_VENDOR_ID, HP_LM940_PRODUCT_ID) }, |
| 110 | 111 | { USB_DEVICE(HP_VENDOR_ID, HP_TD620_PRODUCT_ID) }, |
| 111 | 112 | { USB_DEVICE(CRESSI_VENDOR_ID, CRESSI_EDY_PRODUCT_ID) }, |
| @@ -135,6 +135,7 @@ · 134 unmodified lines | ||
| 135 | 135 | #define HP_TD620_PRODUCT_ID 0x0956 |
| 136 | 136 | #define HP_LD960_PRODUCT_ID 0x0b39 |
| 137 | 137 | #define HP_LD381_PRODUCT_ID 0x0f7f |
| 138 | +#define HP_LM930_PRODUCT_ID 0x0f9b | |
| 138 | 139 | #define HP_LCM220_PRODUCT_ID 0x3139 |
| 139 | 140 | #define HP_LCM960_PRODUCT_ID 0x3239 |
| 140 | 141 | #define HP_LD220_PRODUCT_ID 0x3524 |
| @@ -166,6 +166,8 @@ static const struct usb_device_id id_table[] = { · 165 unmodified lines | ||
| 166 | 166 | {DEVICE_SWI(0x1199, 0x9090)}, /* Sierra Wireless EM7565 QDL */ |
| 167 | 167 | {DEVICE_SWI(0x1199, 0x9091)}, /* Sierra Wireless EM7565 */ |
| 168 | 168 | {DEVICE_SWI(0x1199, 0x90d2)}, /* Sierra Wireless EM9191 QDL */ |
| 169 | + {DEVICE_SWI(0x1199, 0xc080)}, /* Sierra Wireless EM7590 QDL */ | |
| 170 | + {DEVICE_SWI(0x1199, 0xc081)}, /* Sierra Wireless EM7590 */ | |
| 169 | 171 | {DEVICE_SWI(0x413c, 0x81a2)}, /* Dell Wireless 5806 Gobi(TM) 4G LTE Mobile Broadband Card */ |
| 170 | 172 | {DEVICE_SWI(0x413c, 0x81a3)}, /* Dell Wireless 5570 HSPA+ (42Mbps) Mobile Broadband Card */ |
| 171 | 173 | {DEVICE_SWI(0x413c, 0x81a4)}, /* Dell Wireless 5570e HSPA+ (42Mbps) Mobile Broadband Card */ |
| @@ -877,7 +877,7 @@ static int tcpci_remove(struct i2c_client *client) · 876 unmodified lines | ||
| 877 | 877 | /* Disable chip interrupts before unregistering port */ |
| 878 | 878 | err = tcpci_write16(chip->tcpci, TCPC_ALERT_MASK, 0); |
| 879 | 879 | if (err < 0) |
| 880 | − return err; | |
| 880 | + dev_warn(&client->dev, "Failed to disable irqs (%pe)\n", ERR_PTR(err)); | |
| 881 | 881 | |
| 882 | 882 | tcpci_unregister_port(chip->tcpci); |
| 883 | 883 | |
| @@ -15,6 +15,9 @@ · 14 unmodified lines | ||
| 15 | 15 | |
| 16 | 16 | #include "tcpci.h" |
| 17 | 17 | |
| 18 | +#define MT6360_REG_PHYCTRL1 0x80 | |
| 19 | +#define MT6360_REG_PHYCTRL3 0x82 | |
| 20 | +#define MT6360_REG_PHYCTRL7 0x86 | |
| 18 | 21 | #define MT6360_REG_VCONNCTRL1 0x8C |
| 19 | 22 | #define MT6360_REG_MODECTRL2 0x8F |
| 20 | 23 | #define MT6360_REG_SWRESET 0xA0 |
| @@ -22,6 +25,8 @@ · 1 unmodified line | ||
| 22 | 25 | #define MT6360_REG_DRPCTRL1 0xA2 |
| 23 | 26 | #define MT6360_REG_DRPCTRL2 0xA3 |
| 24 | 27 | #define MT6360_REG_I2CTORST 0xBF |
| 28 | +#define MT6360_REG_PHYCTRL11 0xCA | |
| 29 | +#define MT6360_REG_RXCTRL1 0xCE | |
| 25 | 30 | #define MT6360_REG_RXCTRL2 0xCF |
| 26 | 31 | #define MT6360_REG_CTDCTRL2 0xEC |
| 27 | 32 | |
| @@ -106,6 +111,27 @@ static int mt6360_tcpc_init(struct tcpci *tcpci, struct tcpci_data *tdata) · 78 unmodified lines | ||
| 106 | 111 | if (ret) |
| 107 | 112 | return ret; |
| 108 | 113 | |
| 114 | + /* BMC PHY */ | |
| 115 | + ret = mt6360_tcpc_write16(regmap, MT6360_REG_PHYCTRL1, 0x3A70); | |
| 116 | + if (ret) | |
| 117 | + return ret; | |
| 118 | + | |
| 119 | + ret = regmap_write(regmap, MT6360_REG_PHYCTRL3, 0x82); | |
| 120 | + if (ret) | |
| 121 | + return ret; | |
| 122 | + | |
| 123 | + ret = regmap_write(regmap, MT6360_REG_PHYCTRL7, 0x36); | |
| 124 | + if (ret) | |
| 125 | + return ret; | |
| 126 | + | |
| 127 | + ret = mt6360_tcpc_write16(regmap, MT6360_REG_PHYCTRL11, 0x3C60); | |
| 128 | + if (ret) | |
| 129 | + return ret; | |
| 130 | + | |
| 131 | + ret = regmap_write(regmap, MT6360_REG_RXCTRL1, 0xE8); | |
| 132 | + if (ret) | |
| 133 | + return ret; | |
| 134 | + | |
| 109 | 135 | /* Set shipping mode off, AUTOIDLE on */ |
| 110 | 136 | return regmap_write(regmap, MT6360_REG_MODECTRL2, 0x7A); |
| 111 | 137 | } |