Commit b5beaa44 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull USB / Thunderbolt fixes from Greg KH:
 "Here are some small USB and Thunderbolt driver fixes for 6.10-rc4.
  Included in here are:

   - thunderbolt debugfs bugfix

   - USB typec bugfixes

   - kcov usb bugfix

   - xhci bugfixes

   - usb-storage bugfix

   - dt-bindings bugfix

   - cdc-wdm log message spam bugfix

  All of these, except for the last cdc-wdm log level change, have been
  in linux-next for a while with no reported problems. The cdc-wdm
  bugfix has been tested by syzbot and proved to fix the reported cpu
  lockup issues when the log is constantly spammed by a broken device"

* tag 'usb-6.10-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb:
  USB: class: cdc-wdm: Fix CPU lockup caused by excessive log messages
  xhci: Handle TD clearing for multiple streams case
  xhci: Apply broken streams quirk to Etron EJ188 xHCI host
  xhci: Apply reset resume quirk to Etron EJ188 xHCI host
  xhci: Set correct transferred length for cancelled bulk transfers
  usb-storage: alauda: Check whether the media is initialized
  usb: typec: ucsi: Ack also failed Get Error commands
  kcov, usb: disable interrupts in kcov_remote_start_usb_softirq
  dt-bindings: usb: realtek,rts5411: Add missing "additionalProperties" on child nodes
  usb: typec: tcpm: Ignore received Hard Reset in TOGGLING state
  usb: typec: tcpm: fix use-after-free case in tcpm_register_source_caps
  USB: xen-hcd: Traverse host/ when CONFIG_USB_XEN_HCD is selected
  usb: typec: ucsi: glink: increase max ports for x1e80100
  Revert "usb: chipidea: move ci_ulpi_init after the phy initialization"
  thunderbolt: debugfs: Fix margin debugfs node creation condition
parents 6efc63a8 22f00812
...@@ -65,6 +65,7 @@ patternProperties: ...@@ -65,6 +65,7 @@ patternProperties:
description: The hard wired USB devices description: The hard wired USB devices
type: object type: object
$ref: /schemas/usb/usb-device.yaml $ref: /schemas/usb/usb-device.yaml
additionalProperties: true
required: required:
- peer-hub - peer-hub
......
...@@ -943,8 +943,9 @@ static void margining_port_init(struct tb_port *port) ...@@ -943,8 +943,9 @@ static void margining_port_init(struct tb_port *port)
debugfs_create_file("run", 0600, dir, port, &margining_run_fops); debugfs_create_file("run", 0600, dir, port, &margining_run_fops);
debugfs_create_file("results", 0600, dir, port, &margining_results_fops); debugfs_create_file("results", 0600, dir, port, &margining_results_fops);
debugfs_create_file("test", 0600, dir, port, &margining_test_fops); debugfs_create_file("test", 0600, dir, port, &margining_test_fops);
if (independent_voltage_margins(usb4) || if (independent_voltage_margins(usb4) == USB4_MARGIN_CAP_0_VOLTAGE_HL ||
(supports_time(usb4) && independent_time_margins(usb4))) (supports_time(usb4) &&
independent_time_margins(usb4) == USB4_MARGIN_CAP_1_TIME_LR))
debugfs_create_file("margin", 0600, dir, port, &margining_margin_fops); debugfs_create_file("margin", 0600, dir, port, &margining_margin_fops);
} }
......
...@@ -35,6 +35,7 @@ obj-$(CONFIG_USB_R8A66597_HCD) += host/ ...@@ -35,6 +35,7 @@ obj-$(CONFIG_USB_R8A66597_HCD) += host/
obj-$(CONFIG_USB_FSL_USB2) += host/ obj-$(CONFIG_USB_FSL_USB2) += host/
obj-$(CONFIG_USB_FOTG210_HCD) += host/ obj-$(CONFIG_USB_FOTG210_HCD) += host/
obj-$(CONFIG_USB_MAX3421_HCD) += host/ obj-$(CONFIG_USB_MAX3421_HCD) += host/
obj-$(CONFIG_USB_XEN_HCD) += host/
obj-$(CONFIG_USB_C67X00_HCD) += c67x00/ obj-$(CONFIG_USB_C67X00_HCD) += c67x00/
......
...@@ -1084,6 +1084,10 @@ static int ci_hdrc_probe(struct platform_device *pdev) ...@@ -1084,6 +1084,10 @@ static int ci_hdrc_probe(struct platform_device *pdev)
return -ENODEV; return -ENODEV;
} }
ret = ci_ulpi_init(ci);
if (ret)
return ret;
if (ci->platdata->phy) { if (ci->platdata->phy) {
ci->phy = ci->platdata->phy; ci->phy = ci->platdata->phy;
} else if (ci->platdata->usb_phy) { } else if (ci->platdata->usb_phy) {
...@@ -1138,10 +1142,6 @@ static int ci_hdrc_probe(struct platform_device *pdev) ...@@ -1138,10 +1142,6 @@ static int ci_hdrc_probe(struct platform_device *pdev)
goto ulpi_exit; goto ulpi_exit;
} }
ret = ci_ulpi_init(ci);
if (ret)
return ret;
ci->hw_bank.phys = res->start; ci->hw_bank.phys = res->start;
ci->irq = platform_get_irq(pdev, 0); ci->irq = platform_get_irq(pdev, 0);
......
...@@ -68,6 +68,11 @@ int ci_ulpi_init(struct ci_hdrc *ci) ...@@ -68,6 +68,11 @@ int ci_ulpi_init(struct ci_hdrc *ci)
if (ci->platdata->phy_mode != USBPHY_INTERFACE_MODE_ULPI) if (ci->platdata->phy_mode != USBPHY_INTERFACE_MODE_ULPI)
return 0; return 0;
/*
* Set PORTSC correctly so we can read/write ULPI registers for
* identification purposes
*/
hw_phymode_configure(ci);
ci->ulpi_ops.read = ci_ulpi_read; ci->ulpi_ops.read = ci_ulpi_read;
ci->ulpi_ops.write = ci_ulpi_write; ci->ulpi_ops.write = ci_ulpi_write;
......
...@@ -266,14 +266,14 @@ static void wdm_int_callback(struct urb *urb) ...@@ -266,14 +266,14 @@ static void wdm_int_callback(struct urb *urb)
dev_err(&desc->intf->dev, "Stall on int endpoint\n"); dev_err(&desc->intf->dev, "Stall on int endpoint\n");
goto sw; /* halt is cleared in work */ goto sw; /* halt is cleared in work */
default: default:
dev_err(&desc->intf->dev, dev_err_ratelimited(&desc->intf->dev,
"nonzero urb status received: %d\n", status); "nonzero urb status received: %d\n", status);
break; break;
} }
} }
if (urb->actual_length < sizeof(struct usb_cdc_notification)) { if (urb->actual_length < sizeof(struct usb_cdc_notification)) {
dev_err(&desc->intf->dev, "wdm_int_callback - %d bytes\n", dev_err_ratelimited(&desc->intf->dev, "wdm_int_callback - %d bytes\n",
urb->actual_length); urb->actual_length);
goto exit; goto exit;
} }
......
...@@ -1623,6 +1623,7 @@ static void __usb_hcd_giveback_urb(struct urb *urb) ...@@ -1623,6 +1623,7 @@ static void __usb_hcd_giveback_urb(struct urb *urb)
struct usb_hcd *hcd = bus_to_hcd(urb->dev->bus); struct usb_hcd *hcd = bus_to_hcd(urb->dev->bus);
struct usb_anchor *anchor = urb->anchor; struct usb_anchor *anchor = urb->anchor;
int status = urb->unlinked; int status = urb->unlinked;
unsigned long flags;
urb->hcpriv = NULL; urb->hcpriv = NULL;
if (unlikely((urb->transfer_flags & URB_SHORT_NOT_OK) && if (unlikely((urb->transfer_flags & URB_SHORT_NOT_OK) &&
...@@ -1640,13 +1641,14 @@ static void __usb_hcd_giveback_urb(struct urb *urb) ...@@ -1640,13 +1641,14 @@ static void __usb_hcd_giveback_urb(struct urb *urb)
/* pass ownership to the completion handler */ /* pass ownership to the completion handler */
urb->status = status; urb->status = status;
/* /*
* This function can be called in task context inside another remote * Only collect coverage in the softirq context and disable interrupts
* coverage collection section, but kcov doesn't support that kind of * to avoid scenarios with nested remote coverage collection sections
* recursion yet. Only collect coverage in softirq context for now. * that KCOV does not support.
* See the comment next to kcov_remote_start_usb_softirq() for details.
*/ */
kcov_remote_start_usb_softirq((u64)urb->dev->bus->busnum); flags = kcov_remote_start_usb_softirq((u64)urb->dev->bus->busnum);
urb->complete(urb); urb->complete(urb);
kcov_remote_stop_softirq(); kcov_remote_stop_softirq(flags);
usb_anchor_resume_wakeups(anchor); usb_anchor_resume_wakeups(anchor);
atomic_dec(&urb->use_count); atomic_dec(&urb->use_count);
......
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#define PCI_VENDOR_ID_ETRON 0x1b6f #define PCI_VENDOR_ID_ETRON 0x1b6f
#define PCI_DEVICE_ID_EJ168 0x7023 #define PCI_DEVICE_ID_EJ168 0x7023
#define PCI_DEVICE_ID_EJ188 0x7052
#define PCI_DEVICE_ID_INTEL_LYNXPOINT_XHCI 0x8c31 #define PCI_DEVICE_ID_INTEL_LYNXPOINT_XHCI 0x8c31
#define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI 0x9c31 #define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI 0x9c31
...@@ -395,6 +396,12 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) ...@@ -395,6 +396,12 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
xhci->quirks |= XHCI_RESET_ON_RESUME; xhci->quirks |= XHCI_RESET_ON_RESUME;
xhci->quirks |= XHCI_BROKEN_STREAMS; xhci->quirks |= XHCI_BROKEN_STREAMS;
} }
if (pdev->vendor == PCI_VENDOR_ID_ETRON &&
pdev->device == PCI_DEVICE_ID_EJ188) {
xhci->quirks |= XHCI_RESET_ON_RESUME;
xhci->quirks |= XHCI_BROKEN_STREAMS;
}
if (pdev->vendor == PCI_VENDOR_ID_RENESAS && if (pdev->vendor == PCI_VENDOR_ID_RENESAS &&
pdev->device == 0x0014) { pdev->device == 0x0014) {
xhci->quirks |= XHCI_ZERO_64B_REGS; xhci->quirks |= XHCI_ZERO_64B_REGS;
......
...@@ -1031,13 +1031,27 @@ static int xhci_invalidate_cancelled_tds(struct xhci_virt_ep *ep) ...@@ -1031,13 +1031,27 @@ static int xhci_invalidate_cancelled_tds(struct xhci_virt_ep *ep)
break; break;
case TD_DIRTY: /* TD is cached, clear it */ case TD_DIRTY: /* TD is cached, clear it */
case TD_HALTED: case TD_HALTED:
td->cancel_status = TD_CLEARING_CACHE; case TD_CLEARING_CACHE_DEFERRED:
if (cached_td) if (cached_td) {
/* FIXME stream case, several stopped rings */ if (cached_td->urb->stream_id != td->urb->stream_id) {
/* Multiple streams case, defer move dq */
xhci_dbg(xhci, xhci_dbg(xhci,
"Move dq past stream %u URB %p instead of stream %u URB %p\n", "Move dq deferred: stream %u URB %p\n",
td->urb->stream_id, td->urb, td->urb->stream_id, td->urb);
cached_td->urb->stream_id, cached_td->urb); td->cancel_status = TD_CLEARING_CACHE_DEFERRED;
break;
}
/* Should never happen, but clear the TD if it does */
xhci_warn(xhci,
"Found multiple active URBs %p and %p in stream %u?\n",
td->urb, cached_td->urb,
td->urb->stream_id);
td_to_noop(xhci, ring, cached_td, false);
cached_td->cancel_status = TD_CLEARED;
}
td->cancel_status = TD_CLEARING_CACHE;
cached_td = td; cached_td = td;
break; break;
} }
...@@ -1057,9 +1071,15 @@ static int xhci_invalidate_cancelled_tds(struct xhci_virt_ep *ep) ...@@ -1057,9 +1071,15 @@ static int xhci_invalidate_cancelled_tds(struct xhci_virt_ep *ep)
if (err) { if (err) {
/* Failed to move past cached td, just set cached TDs to no-op */ /* Failed to move past cached td, just set cached TDs to no-op */
list_for_each_entry_safe(td, tmp_td, &ep->cancelled_td_list, cancelled_td_list) { list_for_each_entry_safe(td, tmp_td, &ep->cancelled_td_list, cancelled_td_list) {
if (td->cancel_status != TD_CLEARING_CACHE) /*
* Deferred TDs need to have the deq pointer set after the above command
* completes, so if that failed we just give up on all of them (and
* complain loudly since this could cause issues due to caching).
*/
if (td->cancel_status != TD_CLEARING_CACHE &&
td->cancel_status != TD_CLEARING_CACHE_DEFERRED)
continue; continue;
xhci_dbg(xhci, "Failed to clear cancelled cached URB %p, mark clear anyway\n", xhci_warn(xhci, "Failed to clear cancelled cached URB %p, mark clear anyway\n",
td->urb); td->urb);
td_to_noop(xhci, ring, td, false); td_to_noop(xhci, ring, td, false);
td->cancel_status = TD_CLEARED; td->cancel_status = TD_CLEARED;
...@@ -1346,6 +1366,7 @@ static void xhci_handle_cmd_set_deq(struct xhci_hcd *xhci, int slot_id, ...@@ -1346,6 +1366,7 @@ static void xhci_handle_cmd_set_deq(struct xhci_hcd *xhci, int slot_id,
struct xhci_ep_ctx *ep_ctx; struct xhci_ep_ctx *ep_ctx;
struct xhci_slot_ctx *slot_ctx; struct xhci_slot_ctx *slot_ctx;
struct xhci_td *td, *tmp_td; struct xhci_td *td, *tmp_td;
bool deferred = false;
ep_index = TRB_TO_EP_INDEX(le32_to_cpu(trb->generic.field[3])); ep_index = TRB_TO_EP_INDEX(le32_to_cpu(trb->generic.field[3]));
stream_id = TRB_TO_STREAM_ID(le32_to_cpu(trb->generic.field[2])); stream_id = TRB_TO_STREAM_ID(le32_to_cpu(trb->generic.field[2]));
...@@ -1432,6 +1453,8 @@ static void xhci_handle_cmd_set_deq(struct xhci_hcd *xhci, int slot_id, ...@@ -1432,6 +1453,8 @@ static void xhci_handle_cmd_set_deq(struct xhci_hcd *xhci, int slot_id,
xhci_dbg(ep->xhci, "%s: Giveback cancelled URB %p TD\n", xhci_dbg(ep->xhci, "%s: Giveback cancelled URB %p TD\n",
__func__, td->urb); __func__, td->urb);
xhci_td_cleanup(ep->xhci, td, ep_ring, td->status); xhci_td_cleanup(ep->xhci, td, ep_ring, td->status);
} else if (td->cancel_status == TD_CLEARING_CACHE_DEFERRED) {
deferred = true;
} else { } else {
xhci_dbg(ep->xhci, "%s: Keep cancelled URB %p TD as cancel_status is %d\n", xhci_dbg(ep->xhci, "%s: Keep cancelled URB %p TD as cancel_status is %d\n",
__func__, td->urb, td->cancel_status); __func__, td->urb, td->cancel_status);
...@@ -1441,8 +1464,17 @@ static void xhci_handle_cmd_set_deq(struct xhci_hcd *xhci, int slot_id, ...@@ -1441,8 +1464,17 @@ static void xhci_handle_cmd_set_deq(struct xhci_hcd *xhci, int slot_id,
ep->ep_state &= ~SET_DEQ_PENDING; ep->ep_state &= ~SET_DEQ_PENDING;
ep->queued_deq_seg = NULL; ep->queued_deq_seg = NULL;
ep->queued_deq_ptr = NULL; ep->queued_deq_ptr = NULL;
if (deferred) {
/* We have more streams to clear */
xhci_dbg(ep->xhci, "%s: Pending TDs to clear, continuing with invalidation\n",
__func__);
xhci_invalidate_cancelled_tds(ep);
} else {
/* Restart any rings with pending URBs */ /* Restart any rings with pending URBs */
xhci_dbg(ep->xhci, "%s: All TDs cleared, ring doorbell\n", __func__);
ring_doorbell_for_active_rings(xhci, slot_id, ep_index); ring_doorbell_for_active_rings(xhci, slot_id, ep_index);
}
} }
static void xhci_handle_cmd_reset_ep(struct xhci_hcd *xhci, int slot_id, static void xhci_handle_cmd_reset_ep(struct xhci_hcd *xhci, int slot_id,
...@@ -2524,9 +2556,8 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep, ...@@ -2524,9 +2556,8 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
goto finish_td; goto finish_td;
case COMP_STOPPED_LENGTH_INVALID: case COMP_STOPPED_LENGTH_INVALID:
/* stopped on ep trb with invalid length, exclude it */ /* stopped on ep trb with invalid length, exclude it */
ep_trb_len = 0; td->urb->actual_length = sum_trb_lengths(xhci, ep_ring, ep_trb);
remaining = 0; goto finish_td;
break;
case COMP_USB_TRANSACTION_ERROR: case COMP_USB_TRANSACTION_ERROR:
if (xhci->quirks & XHCI_NO_SOFT_RETRY || if (xhci->quirks & XHCI_NO_SOFT_RETRY ||
(ep->err_count++ > MAX_SOFT_RETRY) || (ep->err_count++ > MAX_SOFT_RETRY) ||
......
...@@ -1276,6 +1276,7 @@ enum xhci_cancelled_td_status { ...@@ -1276,6 +1276,7 @@ enum xhci_cancelled_td_status {
TD_DIRTY = 0, TD_DIRTY = 0,
TD_HALTED, TD_HALTED,
TD_CLEARING_CACHE, TD_CLEARING_CACHE,
TD_CLEARING_CACHE_DEFERRED,
TD_CLEARED, TD_CLEARED,
}; };
......
...@@ -105,6 +105,8 @@ struct alauda_info { ...@@ -105,6 +105,8 @@ struct alauda_info {
unsigned char sense_key; unsigned char sense_key;
unsigned long sense_asc; /* additional sense code */ unsigned long sense_asc; /* additional sense code */
unsigned long sense_ascq; /* additional sense code qualifier */ unsigned long sense_ascq; /* additional sense code qualifier */
bool media_initialized;
}; };
#define short_pack(lsb,msb) ( ((u16)(lsb)) | ( ((u16)(msb))<<8 ) ) #define short_pack(lsb,msb) ( ((u16)(lsb)) | ( ((u16)(msb))<<8 ) )
...@@ -476,11 +478,12 @@ static int alauda_check_media(struct us_data *us) ...@@ -476,11 +478,12 @@ static int alauda_check_media(struct us_data *us)
} }
/* Check for media change */ /* Check for media change */
if (status[0] & 0x08) { if (status[0] & 0x08 || !info->media_initialized) {
usb_stor_dbg(us, "Media change detected\n"); usb_stor_dbg(us, "Media change detected\n");
alauda_free_maps(&MEDIA_INFO(us)); alauda_free_maps(&MEDIA_INFO(us));
alauda_init_media(us); rc = alauda_init_media(us);
if (rc == USB_STOR_TRANSPORT_GOOD)
info->media_initialized = true;
info->sense_key = UNIT_ATTENTION; info->sense_key = UNIT_ATTENTION;
info->sense_asc = 0x28; info->sense_asc = 0x28;
info->sense_ascq = 0x00; info->sense_ascq = 0x00;
......
...@@ -3014,8 +3014,10 @@ static int tcpm_register_source_caps(struct tcpm_port *port) ...@@ -3014,8 +3014,10 @@ static int tcpm_register_source_caps(struct tcpm_port *port)
memcpy(caps.pdo, port->source_caps, sizeof(u32) * port->nr_source_caps); memcpy(caps.pdo, port->source_caps, sizeof(u32) * port->nr_source_caps);
caps.role = TYPEC_SOURCE; caps.role = TYPEC_SOURCE;
if (cap) if (cap) {
usb_power_delivery_unregister_capabilities(cap); usb_power_delivery_unregister_capabilities(cap);
port->partner_source_caps = NULL;
}
cap = usb_power_delivery_register_capabilities(port->partner_pd, &caps); cap = usb_power_delivery_register_capabilities(port->partner_pd, &caps);
if (IS_ERR(cap)) if (IS_ERR(cap))
...@@ -6172,6 +6174,7 @@ static void _tcpm_pd_hard_reset(struct tcpm_port *port) ...@@ -6172,6 +6174,7 @@ static void _tcpm_pd_hard_reset(struct tcpm_port *port)
port->tcpc->set_bist_data(port->tcpc, false); port->tcpc->set_bist_data(port->tcpc, false);
switch (port->state) { switch (port->state) {
case TOGGLING:
case ERROR_RECOVERY: case ERROR_RECOVERY:
case PORT_RESET: case PORT_RESET:
case PORT_RESET_WAIT_OFF: case PORT_RESET_WAIT_OFF:
......
...@@ -153,8 +153,13 @@ static int ucsi_exec_command(struct ucsi *ucsi, u64 cmd) ...@@ -153,8 +153,13 @@ static int ucsi_exec_command(struct ucsi *ucsi, u64 cmd)
} }
if (cci & UCSI_CCI_ERROR) { if (cci & UCSI_CCI_ERROR) {
if (cmd == UCSI_GET_ERROR_STATUS) if (cmd == UCSI_GET_ERROR_STATUS) {
ret = ucsi_acknowledge(ucsi, false);
if (ret)
return ret;
return -EIO; return -EIO;
}
return ucsi_read_error(ucsi); return ucsi_read_error(ucsi);
} }
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
#include <linux/soc/qcom/pmic_glink.h> #include <linux/soc/qcom/pmic_glink.h>
#include "ucsi.h" #include "ucsi.h"
#define PMIC_GLINK_MAX_PORTS 2 #define PMIC_GLINK_MAX_PORTS 3
#define UCSI_BUF_SIZE 48 #define UCSI_BUF_SIZE 48
......
...@@ -55,21 +55,47 @@ static inline void kcov_remote_start_usb(u64 id) ...@@ -55,21 +55,47 @@ static inline void kcov_remote_start_usb(u64 id)
/* /*
* The softirq flavor of kcov_remote_*() functions is introduced as a temporary * The softirq flavor of kcov_remote_*() functions is introduced as a temporary
* work around for kcov's lack of nested remote coverage sections support in * workaround for KCOV's lack of nested remote coverage sections support.
* task context. Adding support for nested sections is tracked in: *
* https://bugzilla.kernel.org/show_bug.cgi?id=210337 * Adding support is tracked in https://bugzilla.kernel.org/show_bug.cgi?id=210337.
*
* kcov_remote_start_usb_softirq():
*
* 1. Only collects coverage when called in the softirq context. This allows
* avoiding nested remote coverage collection sections in the task context.
* For example, USB/IP calls usb_hcd_giveback_urb() in the task context
* within an existing remote coverage collection section. Thus, KCOV should
* not attempt to start collecting coverage within the coverage collection
* section in __usb_hcd_giveback_urb() in this case.
*
* 2. Disables interrupts for the duration of the coverage collection section.
* This allows avoiding nested remote coverage collection sections in the
* softirq context (a softirq might occur during the execution of a work in
* the BH workqueue, which runs with in_serving_softirq() > 0).
* For example, usb_giveback_urb_bh() runs in the BH workqueue with
* interrupts enabled, so __usb_hcd_giveback_urb() might be interrupted in
* the middle of its remote coverage collection section, and the interrupt
* handler might invoke __usb_hcd_giveback_urb() again.
*/ */
static inline void kcov_remote_start_usb_softirq(u64 id) static inline unsigned long kcov_remote_start_usb_softirq(u64 id)
{ {
if (in_serving_softirq()) unsigned long flags = 0;
if (in_serving_softirq()) {
local_irq_save(flags);
kcov_remote_start_usb(id); kcov_remote_start_usb(id);
}
return flags;
} }
static inline void kcov_remote_stop_softirq(void) static inline void kcov_remote_stop_softirq(unsigned long flags)
{ {
if (in_serving_softirq()) if (in_serving_softirq()) {
kcov_remote_stop(); kcov_remote_stop();
local_irq_restore(flags);
}
} }
#ifdef CONFIG_64BIT #ifdef CONFIG_64BIT
...@@ -103,8 +129,11 @@ static inline u64 kcov_common_handle(void) ...@@ -103,8 +129,11 @@ static inline u64 kcov_common_handle(void)
} }
static inline void kcov_remote_start_common(u64 id) {} static inline void kcov_remote_start_common(u64 id) {}
static inline void kcov_remote_start_usb(u64 id) {} static inline void kcov_remote_start_usb(u64 id) {}
static inline void kcov_remote_start_usb_softirq(u64 id) {} static inline unsigned long kcov_remote_start_usb_softirq(u64 id)
static inline void kcov_remote_stop_softirq(void) {} {
return 0;
}
static inline void kcov_remote_stop_softirq(unsigned long flags) {}
#endif /* CONFIG_KCOV */ #endif /* CONFIG_KCOV */
#endif /* _LINUX_KCOV_H */ #endif /* _LINUX_KCOV_H */
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