Commit 9057a646 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'usb-5.19-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb

Pull USB driver fixes from Greg KH:
 "Here are some small USB driver fixes and new device ids for 5.19-rc3

  They include:

   - new usb-serial driver device ids

   - usb gadget driver fixes for reported problems

   - cdnsp driver fix

   - dwc3 driver fixes for reported problems

   - dwc3 driver fix for merge problem that I caused in 5.18

   - xhci driver fixes

   - dwc2 memory leak fix

  All of these have been in linux-next for a while with no reported
  issues"

* tag 'usb-5.19-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb:
  usb: gadget: f_fs: change ep->ep safe in ffs_epfile_io()
  usb: gadget: f_fs: change ep->status safe in ffs_epfile_io()
  xhci: Fix null pointer dereference in resume if xhci has only one roothub
  USB: fixup for merge issue with "usb: dwc3: Don't switch OTG -> peripheral if extcon is present"
  usb: cdnsp: Fixed setting last_trb incorrectly
  usb: gadget: u_ether: fix regression in setting fixed MAC address
  usb: gadget: lpc32xx_udc: Fix refcount leak in lpc32xx_udc_probe
  usb: dwc2: Fix memory leak in dwc2_hcd_init
  usb: dwc3: pci: Restore line lost in merge conflict resolution
  usb: dwc3: gadget: Fix IN endpoint max packet size allocation
  USB: serial: option: add support for Cinterion MV31 with new baseline
  USB: serial: io_ti: add Agilent E5805A support
parents 47700948 0698f020
...@@ -1941,14 +1941,17 @@ int cdnsp_queue_bulk_tx(struct cdnsp_device *pdev, struct cdnsp_request *preq) ...@@ -1941,14 +1941,17 @@ int cdnsp_queue_bulk_tx(struct cdnsp_device *pdev, struct cdnsp_request *preq)
} }
if (enqd_len + trb_buff_len >= full_len) { if (enqd_len + trb_buff_len >= full_len) {
if (need_zero_pkt) if (need_zero_pkt && !zero_len_trb) {
zero_len_trb = !zero_len_trb; zero_len_trb = true;
} else {
zero_len_trb = false;
field &= ~TRB_CHAIN; field &= ~TRB_CHAIN;
field |= TRB_IOC; field |= TRB_IOC;
more_trbs_coming = false; more_trbs_coming = false;
need_zero_pkt = false;
preq->td.last_trb = ring->enqueue; preq->td.last_trb = ring->enqueue;
} }
}
/* Only set interrupt on short packet for OUT endpoints. */ /* Only set interrupt on short packet for OUT endpoints. */
if (!preq->direction) if (!preq->direction)
...@@ -1962,7 +1965,7 @@ int cdnsp_queue_bulk_tx(struct cdnsp_device *pdev, struct cdnsp_request *preq) ...@@ -1962,7 +1965,7 @@ int cdnsp_queue_bulk_tx(struct cdnsp_device *pdev, struct cdnsp_request *preq)
length_field = TRB_LEN(trb_buff_len) | TRB_TD_SIZE(remainder) | length_field = TRB_LEN(trb_buff_len) | TRB_TD_SIZE(remainder) |
TRB_INTR_TARGET(0); TRB_INTR_TARGET(0);
cdnsp_queue_trb(pdev, ring, more_trbs_coming | zero_len_trb, cdnsp_queue_trb(pdev, ring, more_trbs_coming,
lower_32_bits(send_addr), lower_32_bits(send_addr),
upper_32_bits(send_addr), upper_32_bits(send_addr),
length_field, length_field,
......
...@@ -5190,7 +5190,7 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg) ...@@ -5190,7 +5190,7 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg)
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) { if (!res) {
retval = -EINVAL; retval = -EINVAL;
goto error1; goto error2;
} }
hcd->rsrc_start = res->start; hcd->rsrc_start = res->start;
hcd->rsrc_len = resource_size(res); hcd->rsrc_len = resource_size(res);
......
...@@ -1644,13 +1644,8 @@ static struct extcon_dev *dwc3_get_extcon(struct dwc3 *dwc) ...@@ -1644,13 +1644,8 @@ static struct extcon_dev *dwc3_get_extcon(struct dwc3 *dwc)
* This device property is for kernel internal use only and * This device property is for kernel internal use only and
* is expected to be set by the glue code. * is expected to be set by the glue code.
*/ */
if (device_property_read_string(dev, "linux,extcon-name", &name) == 0) { if (device_property_read_string(dev, "linux,extcon-name", &name) == 0)
edev = extcon_get_extcon_dev(name); return extcon_get_extcon_dev(name);
if (!edev)
return ERR_PTR(-EPROBE_DEFER);
return edev;
}
/* /*
* Try to get an extcon device from the USB PHY controller's "port" * Try to get an extcon device from the USB PHY controller's "port"
......
...@@ -127,6 +127,7 @@ static const struct property_entry dwc3_pci_intel_phy_charger_detect_properties[ ...@@ -127,6 +127,7 @@ static const struct property_entry dwc3_pci_intel_phy_charger_detect_properties[
PROPERTY_ENTRY_STRING("dr_mode", "peripheral"), PROPERTY_ENTRY_STRING("dr_mode", "peripheral"),
PROPERTY_ENTRY_BOOL("snps,dis_u2_susphy_quirk"), PROPERTY_ENTRY_BOOL("snps,dis_u2_susphy_quirk"),
PROPERTY_ENTRY_BOOL("linux,phy_charger_detect"), PROPERTY_ENTRY_BOOL("linux,phy_charger_detect"),
PROPERTY_ENTRY_BOOL("linux,sysdev_is_parent"),
{} {}
}; };
......
...@@ -2976,6 +2976,7 @@ static int dwc3_gadget_init_in_endpoint(struct dwc3_ep *dep) ...@@ -2976,6 +2976,7 @@ static int dwc3_gadget_init_in_endpoint(struct dwc3_ep *dep)
struct dwc3 *dwc = dep->dwc; struct dwc3 *dwc = dep->dwc;
u32 mdwidth; u32 mdwidth;
int size; int size;
int maxpacket;
mdwidth = dwc3_mdwidth(dwc); mdwidth = dwc3_mdwidth(dwc);
...@@ -2988,21 +2989,24 @@ static int dwc3_gadget_init_in_endpoint(struct dwc3_ep *dep) ...@@ -2988,21 +2989,24 @@ static int dwc3_gadget_init_in_endpoint(struct dwc3_ep *dep)
else else
size = DWC31_GTXFIFOSIZ_TXFDEP(size); size = DWC31_GTXFIFOSIZ_TXFDEP(size);
/* FIFO Depth is in MDWDITH bytes. Multiply */
size *= mdwidth;
/* /*
* To meet performance requirement, a minimum TxFIFO size of 3x * maxpacket size is determined as part of the following, after assuming
* MaxPacketSize is recommended for endpoints that support burst and a * a mult value of one maxpacket:
* minimum TxFIFO size of 2x MaxPacketSize for endpoints that don't * DWC3 revision 280A and prior:
* support burst. Use those numbers and we can calculate the max packet * fifo_size = mult * (max_packet / mdwidth) + 1;
* limit as below. * maxpacket = mdwidth * (fifo_size - 1);
*
* DWC3 revision 290A and onwards:
* fifo_size = mult * ((max_packet + mdwidth)/mdwidth + 1) + 1
* maxpacket = mdwidth * ((fifo_size - 1) - 1) - mdwidth;
*/ */
if (dwc->maximum_speed >= USB_SPEED_SUPER) if (DWC3_VER_IS_PRIOR(DWC3, 290A))
size /= 3; maxpacket = mdwidth * (size - 1);
else else
size /= 2; maxpacket = mdwidth * ((size - 1) - 1) - mdwidth;
/* Functionally, space for one max packet is sufficient */
size = min_t(int, maxpacket, 1024);
usb_ep_set_maxpacket_limit(&dep->endpoint, size); usb_ep_set_maxpacket_limit(&dep->endpoint, size);
dep->endpoint.max_streams = 16; dep->endpoint.max_streams = 16;
......
...@@ -122,8 +122,6 @@ struct ffs_ep { ...@@ -122,8 +122,6 @@ struct ffs_ep {
struct usb_endpoint_descriptor *descs[3]; struct usb_endpoint_descriptor *descs[3];
u8 num; u8 num;
int status; /* P: epfile->mutex */
}; };
struct ffs_epfile { struct ffs_epfile {
...@@ -227,6 +225,9 @@ struct ffs_io_data { ...@@ -227,6 +225,9 @@ struct ffs_io_data {
bool use_sg; bool use_sg;
struct ffs_data *ffs; struct ffs_data *ffs;
int status;
struct completion done;
}; };
struct ffs_desc_helper { struct ffs_desc_helper {
...@@ -707,12 +708,15 @@ static const struct file_operations ffs_ep0_operations = { ...@@ -707,12 +708,15 @@ static const struct file_operations ffs_ep0_operations = {
static void ffs_epfile_io_complete(struct usb_ep *_ep, struct usb_request *req) static void ffs_epfile_io_complete(struct usb_ep *_ep, struct usb_request *req)
{ {
struct ffs_io_data *io_data = req->context;
ENTER(); ENTER();
if (req->context) { if (req->status)
struct ffs_ep *ep = _ep->driver_data; io_data->status = req->status;
ep->status = req->status ? req->status : req->actual; else
complete(req->context); io_data->status = req->actual;
}
complete(&io_data->done);
} }
static ssize_t ffs_copy_to_iter(void *data, int data_len, struct iov_iter *iter) static ssize_t ffs_copy_to_iter(void *data, int data_len, struct iov_iter *iter)
...@@ -1050,7 +1054,6 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) ...@@ -1050,7 +1054,6 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
WARN(1, "%s: data_len == -EINVAL\n", __func__); WARN(1, "%s: data_len == -EINVAL\n", __func__);
ret = -EINVAL; ret = -EINVAL;
} else if (!io_data->aio) { } else if (!io_data->aio) {
DECLARE_COMPLETION_ONSTACK(done);
bool interrupted = false; bool interrupted = false;
req = ep->req; req = ep->req;
...@@ -1066,7 +1069,8 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) ...@@ -1066,7 +1069,8 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
io_data->buf = data; io_data->buf = data;
req->context = &done; init_completion(&io_data->done);
req->context = io_data;
req->complete = ffs_epfile_io_complete; req->complete = ffs_epfile_io_complete;
ret = usb_ep_queue(ep->ep, req, GFP_ATOMIC); ret = usb_ep_queue(ep->ep, req, GFP_ATOMIC);
...@@ -1075,7 +1079,12 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) ...@@ -1075,7 +1079,12 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
spin_unlock_irq(&epfile->ffs->eps_lock); spin_unlock_irq(&epfile->ffs->eps_lock);
if (wait_for_completion_interruptible(&done)) { if (wait_for_completion_interruptible(&io_data->done)) {
spin_lock_irq(&epfile->ffs->eps_lock);
if (epfile->ep != ep) {
ret = -ESHUTDOWN;
goto error_lock;
}
/* /*
* To avoid race condition with ffs_epfile_io_complete, * To avoid race condition with ffs_epfile_io_complete,
* dequeue the request first then check * dequeue the request first then check
...@@ -1083,17 +1092,18 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) ...@@ -1083,17 +1092,18 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
* condition with req->complete callback. * condition with req->complete callback.
*/ */
usb_ep_dequeue(ep->ep, req); usb_ep_dequeue(ep->ep, req);
wait_for_completion(&done); spin_unlock_irq(&epfile->ffs->eps_lock);
interrupted = ep->status < 0; wait_for_completion(&io_data->done);
interrupted = io_data->status < 0;
} }
if (interrupted) if (interrupted)
ret = -EINTR; ret = -EINTR;
else if (io_data->read && ep->status > 0) else if (io_data->read && io_data->status > 0)
ret = __ffs_epfile_read_data(epfile, data, ep->status, ret = __ffs_epfile_read_data(epfile, data, io_data->status,
&io_data->data); &io_data->data);
else else
ret = ep->status; ret = io_data->status;
goto error_mutex; goto error_mutex;
} else if (!(req = usb_ep_alloc_request(ep->ep, GFP_ATOMIC))) { } else if (!(req = usb_ep_alloc_request(ep->ep, GFP_ATOMIC))) {
ret = -ENOMEM; ret = -ENOMEM;
......
...@@ -775,9 +775,13 @@ struct eth_dev *gether_setup_name(struct usb_gadget *g, ...@@ -775,9 +775,13 @@ struct eth_dev *gether_setup_name(struct usb_gadget *g,
dev->qmult = qmult; dev->qmult = qmult;
snprintf(net->name, sizeof(net->name), "%s%%d", netname); snprintf(net->name, sizeof(net->name), "%s%%d", netname);
if (get_ether_addr(dev_addr, addr)) if (get_ether_addr(dev_addr, addr)) {
net->addr_assign_type = NET_ADDR_RANDOM;
dev_warn(&g->dev, dev_warn(&g->dev,
"using random %s ethernet address\n", "self"); "using random %s ethernet address\n", "self");
} else {
net->addr_assign_type = NET_ADDR_SET;
}
eth_hw_addr_set(net, addr); eth_hw_addr_set(net, addr);
if (get_ether_addr(host_addr, dev->host_mac)) if (get_ether_addr(host_addr, dev->host_mac))
dev_warn(&g->dev, dev_warn(&g->dev,
...@@ -844,6 +848,10 @@ struct net_device *gether_setup_name_default(const char *netname) ...@@ -844,6 +848,10 @@ struct net_device *gether_setup_name_default(const char *netname)
eth_random_addr(dev->dev_mac); eth_random_addr(dev->dev_mac);
pr_warn("using random %s ethernet address\n", "self"); pr_warn("using random %s ethernet address\n", "self");
/* by default we always have a random MAC address */
net->addr_assign_type = NET_ADDR_RANDOM;
eth_random_addr(dev->host_mac); eth_random_addr(dev->host_mac);
pr_warn("using random %s ethernet address\n", "host"); pr_warn("using random %s ethernet address\n", "host");
...@@ -871,7 +879,6 @@ int gether_register_netdev(struct net_device *net) ...@@ -871,7 +879,6 @@ int gether_register_netdev(struct net_device *net)
dev = netdev_priv(net); dev = netdev_priv(net);
g = dev->gadget; g = dev->gadget;
net->addr_assign_type = NET_ADDR_RANDOM;
eth_hw_addr_set(net, dev->dev_mac); eth_hw_addr_set(net, dev->dev_mac);
status = register_netdev(net); status = register_netdev(net);
...@@ -912,6 +919,7 @@ int gether_set_dev_addr(struct net_device *net, const char *dev_addr) ...@@ -912,6 +919,7 @@ int gether_set_dev_addr(struct net_device *net, const char *dev_addr)
if (get_ether_addr(dev_addr, new_addr)) if (get_ether_addr(dev_addr, new_addr))
return -EINVAL; return -EINVAL;
memcpy(dev->dev_mac, new_addr, ETH_ALEN); memcpy(dev->dev_mac, new_addr, ETH_ALEN);
net->addr_assign_type = NET_ADDR_SET;
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(gether_set_dev_addr); EXPORT_SYMBOL_GPL(gether_set_dev_addr);
......
...@@ -3016,6 +3016,7 @@ static int lpc32xx_udc_probe(struct platform_device *pdev) ...@@ -3016,6 +3016,7 @@ static int lpc32xx_udc_probe(struct platform_device *pdev)
} }
udc->isp1301_i2c_client = isp1301_get_client(isp1301_node); udc->isp1301_i2c_client = isp1301_get_client(isp1301_node);
of_node_put(isp1301_node);
if (!udc->isp1301_i2c_client) { if (!udc->isp1301_i2c_client) {
return -EPROBE_DEFER; return -EPROBE_DEFER;
} }
......
...@@ -1107,7 +1107,6 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) ...@@ -1107,7 +1107,6 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
{ {
u32 command, temp = 0; u32 command, temp = 0;
struct usb_hcd *hcd = xhci_to_hcd(xhci); struct usb_hcd *hcd = xhci_to_hcd(xhci);
struct usb_hcd *secondary_hcd;
int retval = 0; int retval = 0;
bool comp_timer_running = false; bool comp_timer_running = false;
bool pending_portevent = false; bool pending_portevent = false;
...@@ -1214,23 +1213,19 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) ...@@ -1214,23 +1213,19 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
* first with the primary HCD, and then with the secondary HCD. * first with the primary HCD, and then with the secondary HCD.
* If we don't do the same, the host will never be started. * If we don't do the same, the host will never be started.
*/ */
if (!usb_hcd_is_primary_hcd(hcd))
secondary_hcd = hcd;
else
secondary_hcd = xhci->shared_hcd;
xhci_dbg(xhci, "Initialize the xhci_hcd\n"); xhci_dbg(xhci, "Initialize the xhci_hcd\n");
retval = xhci_init(hcd->primary_hcd); retval = xhci_init(hcd);
if (retval) if (retval)
return retval; return retval;
comp_timer_running = true; comp_timer_running = true;
xhci_dbg(xhci, "Start the primary HCD\n"); xhci_dbg(xhci, "Start the primary HCD\n");
retval = xhci_run(hcd->primary_hcd); retval = xhci_run(hcd);
if (!retval && secondary_hcd) { if (!retval && xhci->shared_hcd) {
xhci_dbg(xhci, "Start the secondary HCD\n"); xhci_dbg(xhci, "Start the secondary HCD\n");
retval = xhci_run(secondary_hcd); retval = xhci_run(xhci->shared_hcd);
} }
hcd->state = HC_STATE_SUSPENDED; hcd->state = HC_STATE_SUSPENDED;
if (xhci->shared_hcd) if (xhci->shared_hcd)
xhci->shared_hcd->state = HC_STATE_SUSPENDED; xhci->shared_hcd->state = HC_STATE_SUSPENDED;
......
...@@ -166,6 +166,7 @@ static const struct usb_device_id edgeport_2port_id_table[] = { ...@@ -166,6 +166,7 @@ static const struct usb_device_id edgeport_2port_id_table[] = {
{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_8S) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_8S) },
{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_416) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_416) },
{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_416B) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_416B) },
{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_E5805A) },
{ } { }
}; };
...@@ -204,6 +205,7 @@ static const struct usb_device_id id_table_combined[] = { ...@@ -204,6 +205,7 @@ static const struct usb_device_id id_table_combined[] = {
{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_8S) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_8S) },
{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_416) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_416) },
{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_416B) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_416B) },
{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_E5805A) },
{ } { }
}; };
......
...@@ -212,6 +212,7 @@ ...@@ -212,6 +212,7 @@
// //
// Definitions for other product IDs // Definitions for other product IDs
#define ION_DEVICE_ID_MT4X56USB 0x1403 // OEM device #define ION_DEVICE_ID_MT4X56USB 0x1403 // OEM device
#define ION_DEVICE_ID_E5805A 0x1A01 // OEM device (rebranded Edgeport/4)
#define GENERATION_ID_FROM_USB_PRODUCT_ID(ProductId) \ #define GENERATION_ID_FROM_USB_PRODUCT_ID(ProductId) \
......
...@@ -432,6 +432,8 @@ static void option_instat_callback(struct urb *urb); ...@@ -432,6 +432,8 @@ static void option_instat_callback(struct urb *urb);
#define CINTERION_PRODUCT_CLS8 0x00b0 #define CINTERION_PRODUCT_CLS8 0x00b0
#define CINTERION_PRODUCT_MV31_MBIM 0x00b3 #define CINTERION_PRODUCT_MV31_MBIM 0x00b3
#define CINTERION_PRODUCT_MV31_RMNET 0x00b7 #define CINTERION_PRODUCT_MV31_RMNET 0x00b7
#define CINTERION_PRODUCT_MV31_2_MBIM 0x00b8
#define CINTERION_PRODUCT_MV31_2_RMNET 0x00b9
#define CINTERION_PRODUCT_MV32_WA 0x00f1 #define CINTERION_PRODUCT_MV32_WA 0x00f1
#define CINTERION_PRODUCT_MV32_WB 0x00f2 #define CINTERION_PRODUCT_MV32_WB 0x00f2
...@@ -1979,6 +1981,10 @@ static const struct usb_device_id option_ids[] = { ...@@ -1979,6 +1981,10 @@ static const struct usb_device_id option_ids[] = {
.driver_info = RSVD(3)}, .driver_info = RSVD(3)},
{ USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_MV31_RMNET, 0xff), { USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_MV31_RMNET, 0xff),
.driver_info = RSVD(0)}, .driver_info = RSVD(0)},
{ USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_MV31_2_MBIM, 0xff),
.driver_info = RSVD(3)},
{ USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_MV31_2_RMNET, 0xff),
.driver_info = RSVD(0)},
{ USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_MV32_WA, 0xff), { USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_MV32_WA, 0xff),
.driver_info = RSVD(3)}, .driver_info = RSVD(3)},
{ USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_MV32_WB, 0xff), { USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_MV32_WB, 0xff),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment