mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-19 05:37:54 +00:00
parent
cfab4e74a9
commit
17a140db3d
@ -1,34 +0,0 @@
|
||||
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
|
||||
index 74664a6..38cc18a 100644
|
||||
--- a/drivers/net/phy/phy_device.c
|
||||
+++ b/drivers/net/phy/phy_device.c
|
||||
@@ -944,7 +944,10 @@ EXPORT_SYMBOL(phy_attached_print);
|
||||
int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
|
||||
u32 flags, phy_interface_t interface)
|
||||
{
|
||||
+#if 0
|
||||
+ /* 'driver' has not been set yet on Genode */
|
||||
struct module *ndev_owner = dev->dev.parent->driver->owner;
|
||||
+#endif
|
||||
struct mii_bus *bus = phydev->mdio.bus;
|
||||
struct device *d = &phydev->mdio.dev;
|
||||
bool using_genphy = false;
|
||||
@@ -955,7 +958,7 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
|
||||
* our own module->refcnt here, otherwise we would not be able to
|
||||
* unload later on.
|
||||
*/
|
||||
- if (ndev_owner != bus->owner && !try_module_get(bus->owner)) {
|
||||
+ if (/*ndev_owner != bus->owner &&*/ !try_module_get(bus->owner)) {
|
||||
dev_err(&dev->dev, "failed to get the bus module\n");
|
||||
return -EIO;
|
||||
}
|
||||
@@ -1060,7 +1063,9 @@ error_module_put:
|
||||
module_put(d->driver->owner);
|
||||
error_put_device:
|
||||
put_device(d);
|
||||
+#if 0
|
||||
if (ndev_owner != bus->owner)
|
||||
+#endif
|
||||
module_put(bus->owner);
|
||||
return err;
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
|
||||
index 9147f9f..c63ee5c 100644
|
||||
--- a/include/linux/skbuff.h
|
||||
+++ b/include/linux/skbuff.h
|
||||
@@ -3281,7 +3281,7 @@ static inline void skb_remcsum_process(struct sk_buff *skb, void *ptr,
|
||||
|
||||
if (unlikely(skb->ip_summed != CHECKSUM_COMPLETE)) {
|
||||
__skb_checksum_complete(skb);
|
||||
- skb_postpull_rcsum(skb, skb->data, ptr - (void *)skb->data);
|
||||
+ skb_postpull_rcsum(skb, skb->data, (unsigned char*)ptr - skb->data);
|
||||
}
|
||||
|
||||
delta = remcsum_adjust(ptr, skb->csum, start, offset);
|
@ -1,13 +0,0 @@
|
||||
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
|
||||
index d4604bc..3f72629 100644
|
||||
--- a/drivers/net/ethernet/freescale/fec_main.c
|
||||
+++ b/drivers/net/ethernet/freescale/fec_main.c
|
||||
@@ -2798,7 +2798,7 @@ fec_enet_alloc_txq_buffers(struct net_device *ndev, unsigned int queue)
|
||||
txq = fep->tx_queue[queue];
|
||||
bdp = txq->bd.base;
|
||||
for (i = 0; i < txq->bd.ring_size; i++) {
|
||||
- txq->tx_bounce[i] = kmalloc(FEC_ENET_TX_FRSIZE, GFP_KERNEL);
|
||||
+ txq->tx_bounce[i] = kmalloc(FEC_ENET_TX_FRSIZE, GFP_KERNEL | GFP_LX_DMA);
|
||||
if (!txq->tx_bounce[i])
|
||||
goto err_alloc;
|
||||
|
@ -1,43 +0,0 @@
|
||||
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
|
||||
index 3f72629..2b54f2b 100644
|
||||
--- a/drivers/net/ethernet/freescale/fec_main.c
|
||||
+++ b/drivers/net/ethernet/freescale/fec_main.c
|
||||
@@ -428,7 +428,7 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
|
||||
{
|
||||
struct fec_enet_private *fep = netdev_priv(ndev);
|
||||
int nr_frags = skb_shinfo(skb)->nr_frags;
|
||||
- struct bufdesc *bdp, *last_bdp;
|
||||
+ struct bufdesc *bdp, *last_bdp, *dummy_bdp;
|
||||
void *bufaddr;
|
||||
dma_addr_t addr;
|
||||
unsigned short status;
|
||||
@@ -532,6 +532,7 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
|
||||
*/
|
||||
status |= (BD_ENET_TX_READY | BD_ENET_TX_TC);
|
||||
bdp->cbd_sc = cpu_to_fec16(status);
|
||||
+ dummy_bdp = bdp;
|
||||
|
||||
/* If this was the last BD in the ring, start at the beginning again. */
|
||||
bdp = fec_enet_get_nextdesc(last_bdp, &txq->bd);
|
||||
@@ -542,6 +543,21 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
|
||||
* txq->bd.cur.
|
||||
*/
|
||||
wmb();
|
||||
+
|
||||
+ /*
|
||||
+ * Unfortunately, our current implementation of 'wmb()' doesn't seem
|
||||
+ * to do what we want it to do. On base-hw + imx6q_sabrelite, the
|
||||
+ * write of bdp->cbd_sc seems to get re-ordered after the write to
|
||||
+ * txq->bd.reg_desc_active and, therefore, the transmission of the packet
|
||||
+ * would only be triggered the next time we reach this point,
|
||||
+ * i.e. when the next packet is sent. However, we only quick-fix it by
|
||||
+ * enforcing the write with this volatile global read as we will
|
||||
+ * soon update the FEC NIC port with a new DDE approach anyway
|
||||
+ * (See Genode Github issue #4010).
|
||||
+ */
|
||||
+ static unsigned long volatile dummy_cbd_sc;
|
||||
+ dummy_cbd_sc = *(unsigned long volatile *)&dummy_bdp->cbd_sc;
|
||||
+
|
||||
txq->bd.cur = bdp;
|
||||
|
||||
/* Trigger transmission start */
|
@ -1,10 +0,0 @@
|
||||
+++ src/linux/drivers/gpu/drm/i915/i915_pci.c
|
||||
@@ -954,7 +954,7 @@
|
||||
XE_LPD_FEATURES,
|
||||
PLATFORM(INTEL_ALDERLAKE_P),
|
||||
.has_cdclk_crawl = 1,
|
||||
- .require_force_probe = 1,
|
||||
+ .require_force_probe = 0,
|
||||
.display.has_modular_fia = 1,
|
||||
.platform_engine_mask =
|
||||
BIT(RCS0) | BIT(BCS0) | BIT(VECS0) | BIT(VCS0) | BIT(VCS2),
|
@ -1,66 +0,0 @@
|
||||
From 52a9dab6d892763b2a8334a568bd4e2c1a6fde66 Mon Sep 17 00:00:00 2001
|
||||
From: Kees Cook <keescook@chromium.org>
|
||||
Date: Sun, 13 Feb 2022 10:24:43 -0800
|
||||
Subject: [PATCH] libsubcmd: Fix use-after-free for realloc(..., 0)
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
GCC 12 correctly reports a potential use-after-free condition in the
|
||||
xrealloc helper. Fix the warning by avoiding an implicit "free(ptr)"
|
||||
when size == 0:
|
||||
|
||||
In file included from help.c:12:
|
||||
In function 'xrealloc',
|
||||
inlined from 'add_cmdname' at help.c:24:2: subcmd-util.h:56:23: error: pointer may be used after 'realloc' [-Werror=use-after-free]
|
||||
56 | ret = realloc(ptr, size);
|
||||
| ^~~~~~~~~~~~~~~~~~
|
||||
subcmd-util.h:52:21: note: call to 'realloc' here
|
||||
52 | void *ret = realloc(ptr, size);
|
||||
| ^~~~~~~~~~~~~~~~~~
|
||||
subcmd-util.h:58:31: error: pointer may be used after 'realloc' [-Werror=use-after-free]
|
||||
58 | ret = realloc(ptr, 1);
|
||||
| ^~~~~~~~~~~~~~~
|
||||
subcmd-util.h:52:21: note: call to 'realloc' here
|
||||
52 | void *ret = realloc(ptr, size);
|
||||
| ^~~~~~~~~~~~~~~~~~
|
||||
|
||||
Fixes: 2f4ce5ec1d447beb ("perf tools: Finalize subcmd independence")
|
||||
Reported-by: Valdis Klētnieks <valdis.kletnieks@vt.edu>
|
||||
Signed-off-by: Kees Kook <keescook@chromium.org>
|
||||
Tested-by: Valdis Klētnieks <valdis.kletnieks@vt.edu>
|
||||
Tested-by: Justin M. Forbes <jforbes@fedoraproject.org>
|
||||
Acked-by: Josh Poimboeuf <jpoimboe@redhat.com>
|
||||
Cc: linux-hardening@vger.kernel.org
|
||||
Cc: Valdis Klētnieks <valdis.kletnieks@vt.edu>
|
||||
Link: http://lore.kernel.org/lkml/20220213182443.4037039-1-keescook@chromium.org
|
||||
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
|
||||
---
|
||||
tools/lib/subcmd/subcmd-util.h | 11 ++---------
|
||||
1 file changed, 2 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/tools/lib/subcmd/subcmd-util.h b/tools/lib/subcmd/subcmd-util.h
|
||||
index 794a375dad36..b2aec04fce8f 100644
|
||||
--- src/linux/tools/lib/subcmd/subcmd-util.h
|
||||
+++ src/linux/tools/lib/subcmd/subcmd-util.h
|
||||
@@ -50,15 +50,8 @@ static NORETURN inline void die(const char *err, ...)
|
||||
static inline void *xrealloc(void *ptr, size_t size)
|
||||
{
|
||||
void *ret = realloc(ptr, size);
|
||||
- if (!ret && !size)
|
||||
- ret = realloc(ptr, 1);
|
||||
- if (!ret) {
|
||||
- ret = realloc(ptr, size);
|
||||
- if (!ret && !size)
|
||||
- ret = realloc(ptr, 1);
|
||||
- if (!ret)
|
||||
- die("Out of memory, realloc failed");
|
||||
- }
|
||||
+ if (!ret)
|
||||
+ die("Out of memory, realloc failed");
|
||||
return ret;
|
||||
}
|
||||
|
||||
--
|
||||
2.39.0
|
||||
|
@ -1,14 +0,0 @@
|
||||
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
|
||||
index 5bd400f..044c17c 100644
|
||||
--- a/drivers/usb/core/hub.c
|
||||
+++ b/drivers/usb/core/hub.c
|
||||
@@ -841,7 +841,8 @@ int usb_hub_clear_tt_buffer(struct urb *urb)
|
||||
clear->tt = tt->multi ? udev->ttport : 1;
|
||||
clear->devinfo = usb_pipeendpoint (pipe);
|
||||
clear->devinfo |= udev->devnum << 4;
|
||||
- clear->devinfo |= usb_pipecontrol(pipe)
|
||||
+ /* usb_pipeint(pipe) is only relevant for the 'dwc_otg' driver */
|
||||
+ clear->devinfo |= (usb_pipecontrol(pipe) || usb_pipeint(pipe))
|
||||
? (USB_ENDPOINT_XFER_CONTROL << 11)
|
||||
: (USB_ENDPOINT_XFER_BULK << 11);
|
||||
if (usb_pipein(pipe))
|
@ -1,107 +0,0 @@
|
||||
For Intel host controllers an interrupt is raised for every isochronous packet,
|
||||
because of the "AVOID_BEI" quirk. The reasoning for this is found in the
|
||||
following commit:
|
||||
|
||||
commit 227a4fd801c8a9fa2c4700ab98ec1aec06e3b44d
|
||||
Author: Lu Baolu <baolu.lu@linux.intel.com>
|
||||
Date: Mon Mar 23 18:27:42 2015 +0200
|
||||
|
||||
usb: xhci: apply XHCI_AVOID_BEI quirk to all Intel xHCI controllers
|
||||
|
||||
When a device with an isochronous endpoint is plugged into the Intel
|
||||
xHCI host controller, and the driver submits multiple frames per URB,
|
||||
the xHCI driver will set the Block Event Interrupt (BEI) flag on all
|
||||
but the last TD for the URB. This causes the host controller to place
|
||||
an event on the event ring, but not send an interrupt. When the last
|
||||
TD for the URB completes, BEI is cleared, and we get an interrupt for
|
||||
the whole URB.
|
||||
|
||||
However, under Intel xHCI host controllers, if the event ring is full
|
||||
of events from transfers with BEI set, an "Event Ring is Full" event
|
||||
will be posted to the last entry of the event ring, but no interrupt
|
||||
is generated. Host will cease all transfer and command executions and
|
||||
wait until software completes handling the pending events in the event
|
||||
ring. That means xHC stops, but event of "event ring is full" is not
|
||||
notified. As the result, the xHC looks like dead to user.
|
||||
|
||||
This patch is to apply XHCI_AVOID_BEI quirk to Intel xHC devices. And
|
||||
it should be backported to kernels as old as 3.0, that contains the
|
||||
commit 69e848c2090a ("Intel xhci: Support EHCI/xHCI port switching.").
|
||||
|
||||
Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
|
||||
Tested-by: Alistair Grant <akgrant0710@gmail.com>
|
||||
Cc: stable@vger.kernel.org
|
||||
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
|
||||
Because this behavior up to 8000 interrupts/s can be raised by the host
|
||||
controller during isochronous transfer. Since 2020 there exists a patch that
|
||||
relaxes this burden and which we will apply.
|
||||
|
||||
Author: Mathias Nyman <mathias.nyman@linux.intel.com>
|
||||
Date: Fr Sep 18 2020 13:17:24 2020 +0200
|
||||
|
||||
xhci: Tune interrupt blocking for isochronous transfers
|
||||
|
||||
controllers with XHCI_AVOID_BEI quirk cause too frequent interrupts
|
||||
and affect power management.
|
||||
|
||||
To avoid interrupting on every isochronous interval the BEI (Block
|
||||
Event Interrupt) flag is set for all except the last Isoch TRB in a URB.
|
||||
This lead to event ring filling up in case several isoc URB were
|
||||
queued and cancelled rapidly, which some controllers didn't
|
||||
handle well, and thus the XHCI_AVOID_BEI quirk was introduced.
|
||||
see commit 227a4fd801c8 ("usb: xhci: apply XHCI_AVOID_BEI quirk to all
|
||||
Intel xHCI controllers")
|
||||
|
||||
With the XHCI_AVOID_BEI quirk each Isoch TRB will trigger an interrupt.
|
||||
This can cause up to 8000 interrupts per second for isochronous transfers
|
||||
with HD USB3 cameras, affecting power saving.
|
||||
|
||||
The event ring fits 256 events, instead of interrupting on every
|
||||
isochronous TRB if XHCI_AVOID_BEI is set we make sure at least every
|
||||
8th Isochronous TRB asserts an interrupt, clearing the event ring.
|
||||
|
||||
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
|
||||
|
||||
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
|
||||
index 028891a..31f6bd3 100644
|
||||
--- a/drivers/usb/host/xhci-ring.c
|
||||
+++ b/drivers/usb/host/xhci-ring.c
|
||||
@@ -3608,6 +3608,24 @@ static int xhci_get_isoc_frame_id(struct xhci_hcd *xhci,
|
||||
return start_frame;
|
||||
}
|
||||
|
||||
+/* Check if we should generate event interrupt for a TD in an isoc URB */
|
||||
+static bool trb_block_event_intr(struct xhci_hcd *xhci, int num_tds, int i)
|
||||
+{
|
||||
+ if (xhci->hci_version < 0x100)
|
||||
+ return false;
|
||||
+ /* always generate an event interrupt for the last TD */
|
||||
+ if (i == num_tds - 1)
|
||||
+ return false;
|
||||
+ /*
|
||||
+ * If AVOID_BEI is set the host handles full event rings poorly,
|
||||
+ * generate an event at least every 8th TD to clear the event ring
|
||||
+ */
|
||||
+ if (i && xhci->quirks & XHCI_AVOID_BEI)
|
||||
+ return !!(i % 8);
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
/* This is for isoc transfer */
|
||||
static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
|
||||
struct urb *urb, int slot_id, unsigned int ep_index)
|
||||
@@ -3715,10 +3733,7 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
|
||||
more_trbs_coming = false;
|
||||
td->last_trb = ep_ring->enqueue;
|
||||
field |= TRB_IOC;
|
||||
- /* set BEI, except for the last TD */
|
||||
- if (xhci->hci_version >= 0x100 &&
|
||||
- !(xhci->quirks & XHCI_AVOID_BEI) &&
|
||||
- i < num_tds - 1)
|
||||
+ if (trb_block_event_intr(xhci, num_tds, i))
|
||||
field |= TRB_BEI;
|
||||
}
|
||||
/* Calculate TRB length */
|
@ -1,548 +0,0 @@
|
||||
diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
|
||||
index c821b4b..5accd4d 100644
|
||||
--- a/drivers/usb/core/config.c
|
||||
+++ b/drivers/usb/core/config.c
|
||||
@@ -706,7 +706,7 @@ static int usb_parse_configuration(struct usb_device *dev, int cfgidx,
|
||||
}
|
||||
|
||||
len = sizeof(*intfc) + sizeof(struct usb_host_interface) * j;
|
||||
- config->intf_cache[i] = intfc = kzalloc(len, GFP_KERNEL);
|
||||
+ config->intf_cache[i] = intfc = kzalloc(len, GFP_LX_DMA);
|
||||
if (!intfc)
|
||||
return -ENOMEM;
|
||||
kref_init(&intfc->ref);
|
||||
@@ -817,16 +817,16 @@ int usb_get_configuration(struct usb_device *dev)
|
||||
}
|
||||
|
||||
length = ncfg * sizeof(struct usb_host_config);
|
||||
- dev->config = kzalloc(length, GFP_KERNEL);
|
||||
+ dev->config = kzalloc(length, GFP_LX_DMA);
|
||||
if (!dev->config)
|
||||
goto err2;
|
||||
|
||||
length = ncfg * sizeof(char *);
|
||||
- dev->rawdescriptors = kzalloc(length, GFP_KERNEL);
|
||||
+ dev->rawdescriptors = kzalloc(length, GFP_LX_DMA);
|
||||
if (!dev->rawdescriptors)
|
||||
goto err2;
|
||||
|
||||
- desc = kmalloc(USB_DT_CONFIG_SIZE, GFP_KERNEL);
|
||||
+ desc = kmalloc(USB_DT_CONFIG_SIZE, GFP_LX_DMA);
|
||||
if (!desc)
|
||||
goto err2;
|
||||
|
||||
@@ -855,7 +855,7 @@ int usb_get_configuration(struct usb_device *dev)
|
||||
USB_DT_CONFIG_SIZE);
|
||||
|
||||
/* Now that we know the length, get the whole thing */
|
||||
- bigbuffer = kmalloc(length, GFP_KERNEL);
|
||||
+ bigbuffer = kmalloc(length, GFP_LX_DMA);
|
||||
if (!bigbuffer) {
|
||||
result = -ENOMEM;
|
||||
goto err;
|
||||
@@ -928,7 +928,7 @@ int usb_get_bos_descriptor(struct usb_device *dev)
|
||||
__u8 cap_type;
|
||||
int ret;
|
||||
|
||||
- bos = kzalloc(sizeof(struct usb_bos_descriptor), GFP_KERNEL);
|
||||
+ bos = kzalloc(sizeof(struct usb_bos_descriptor), GFP_LX_DMA);
|
||||
if (!bos)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -949,12 +949,12 @@ int usb_get_bos_descriptor(struct usb_device *dev)
|
||||
if (total_len < length)
|
||||
return -EINVAL;
|
||||
|
||||
- dev->bos = kzalloc(sizeof(struct usb_host_bos), GFP_KERNEL);
|
||||
+ dev->bos = kzalloc(sizeof(struct usb_host_bos), GFP_LX_DMA);
|
||||
if (!dev->bos)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Now let's get the whole BOS descriptor set */
|
||||
- buffer = kzalloc(total_len, GFP_KERNEL);
|
||||
+ buffer = kzalloc(total_len, GFP_LX_DMA);
|
||||
if (!buffer) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
|
||||
index fc32391..919c9e9 100644
|
||||
--- a/drivers/usb/core/hcd.c
|
||||
+++ b/drivers/usb/core/hcd.c
|
||||
@@ -507,7 +507,7 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
|
||||
* USB hub descriptor.
|
||||
*/
|
||||
tbuf_size = max_t(u16, sizeof(struct usb_hub_descriptor), wLength);
|
||||
- tbuf = kzalloc(tbuf_size, GFP_KERNEL);
|
||||
+ tbuf = kzalloc(tbuf_size, GFP_LX_DMA);
|
||||
if (!tbuf) {
|
||||
status = -ENOMEM;
|
||||
goto err_alloc;
|
||||
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
|
||||
index c5c1f6c..5bd400f 100644
|
||||
--- a/drivers/usb/core/hub.c
|
||||
+++ b/drivers/usb/core/hub.c
|
||||
@@ -706,7 +706,7 @@ resubmit:
|
||||
if (hub->quiescing)
|
||||
return;
|
||||
|
||||
- status = usb_submit_urb(hub->urb, GFP_ATOMIC);
|
||||
+ status = usb_submit_urb(hub->urb, GFP_LX_DMA);
|
||||
if (status != 0 && status != -ENODEV && status != -EPERM)
|
||||
dev_err(hub->intfdev, "resubmit --> %d\n", status);
|
||||
}
|
||||
@@ -1310,20 +1310,20 @@ static int hub_configure(struct usb_hub *hub,
|
||||
unsigned full_load;
|
||||
unsigned maxchild;
|
||||
|
||||
- hub->buffer = kmalloc(sizeof(*hub->buffer), GFP_KERNEL);
|
||||
+ hub->buffer = kmalloc(sizeof(*hub->buffer), GFP_LX_DMA);
|
||||
if (!hub->buffer) {
|
||||
ret = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
- hub->status = kmalloc(sizeof(*hub->status), GFP_KERNEL);
|
||||
+ hub->status = kmalloc(sizeof(*hub->status), GFP_LX_DMA);
|
||||
if (!hub->status) {
|
||||
ret = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
mutex_init(&hub->status_mutex);
|
||||
|
||||
- hub->descriptor = kzalloc(sizeof(*hub->descriptor), GFP_KERNEL);
|
||||
+ hub->descriptor = kzalloc(sizeof(*hub->descriptor), GFP_LX_DMA);
|
||||
if (!hub->descriptor) {
|
||||
ret = -ENOMEM;
|
||||
goto fail;
|
||||
@@ -1565,7 +1565,7 @@ static int hub_configure(struct usb_hub *hub,
|
||||
if (maxp > sizeof(*hub->buffer))
|
||||
maxp = sizeof(*hub->buffer);
|
||||
|
||||
- hub->urb = usb_alloc_urb(0, GFP_KERNEL);
|
||||
+ hub->urb = usb_alloc_urb(0, GFP_LX_DMA);
|
||||
if (!hub->urb) {
|
||||
ret = -ENOMEM;
|
||||
goto fail;
|
||||
@@ -4713,7 +4713,7 @@ check_highspeed(struct usb_hub *hub, struct usb_device *udev, int port1)
|
||||
if (udev->quirks & USB_QUIRK_DEVICE_QUALIFIER)
|
||||
return;
|
||||
|
||||
- qual = kmalloc(sizeof *qual, GFP_KERNEL);
|
||||
+ qual = kmalloc(sizeof *qual, GFP_LX_DMA);
|
||||
if (qual == NULL)
|
||||
return;
|
||||
|
||||
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
|
||||
index b3f98e0..3442858 100644
|
||||
--- a/drivers/usb/core/message.c
|
||||
+++ b/drivers/usb/core/message.c
|
||||
@@ -237,7 +237,7 @@ int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe,
|
||||
if (!ep || len < 0)
|
||||
return -EINVAL;
|
||||
|
||||
- urb = usb_alloc_urb(0, GFP_KERNEL);
|
||||
+ urb = usb_alloc_urb(0, GFP_LX_DMA);
|
||||
if (!urb)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -990,7 +989,7 @@ int usb_get_status(struct usb_device *dev, int recip, int type, int target,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
- status = kmalloc(length, GFP_KERNEL);
|
||||
+ status = kmalloc(length, GFP_LX_DMA);
|
||||
if (!status)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -2084,7 +2083,7 @@ int usb_driver_set_configuration(struct usb_device *udev, int config)
|
||||
{
|
||||
struct set_config_request *req;
|
||||
|
||||
- req = kmalloc(sizeof(*req), GFP_KERNEL);
|
||||
+ req = kmalloc(sizeof(*req), GFP_LX_DMA);
|
||||
if (!req)
|
||||
return -ENOMEM;
|
||||
req->udev = udev;
|
||||
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
|
||||
index 0a84661..f427b75 100644
|
||||
--- a/drivers/usb/host/ehci-hub.c
|
||||
+++ b/drivers/usb/host/ehci-hub.c
|
||||
@@ -749,7 +749,7 @@ static struct urb *request_single_step_set_feature_urb(
|
||||
struct usb_hcd *hcd = bus_to_hcd(udev->bus);
|
||||
struct usb_host_endpoint *ep;
|
||||
|
||||
- urb = usb_alloc_urb(0, GFP_KERNEL);
|
||||
+ urb = usb_alloc_urb(0, GFP_LX_DMA);
|
||||
if (!urb)
|
||||
return NULL;
|
||||
|
||||
@@ -804,11 +803,11 @@ static int ehset_single_step_set_feature(struct usb_hcd *hcd, int port)
|
||||
ehci_err(ehci, "No device attached to the RootHub\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
- buf = kmalloc(USB_DT_DEVICE_SIZE, GFP_KERNEL);
|
||||
+ buf = kmalloc(USB_DT_DEVICE_SIZE, GFP_LX_DMA);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
- dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
|
||||
+ dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_LX_DMA);
|
||||
if (!dr) {
|
||||
kfree(buf);
|
||||
return -ENOMEM;
|
||||
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
|
||||
index 3276304..8b9e337 100644
|
||||
--- a/drivers/usb/host/ehci-q.c
|
||||
+++ b/drivers/usb/host/ehci-q.c
|
||||
@@ -1020,7 +1020,7 @@ static struct ehci_qh *qh_append_tds (
|
||||
qh = (struct ehci_qh *) *ptr;
|
||||
if (unlikely (qh == NULL)) {
|
||||
/* can't sleep here, we have ehci->lock... */
|
||||
- qh = qh_make (ehci, urb, GFP_ATOMIC);
|
||||
+ qh = qh_make (ehci, urb, GFP_LX_DMA);
|
||||
*ptr = qh;
|
||||
}
|
||||
if (likely (qh != NULL)) {
|
||||
@@ -1172,7 +1172,7 @@ static int submit_single_step_set_feature(
|
||||
head = &qtd_list;
|
||||
|
||||
/* URBs map to sequences of QTDs: one logical transaction */
|
||||
- qtd = ehci_qtd_alloc(ehci, GFP_KERNEL);
|
||||
+ qtd = ehci_qtd_alloc(ehci, GFP_LX_DMA);
|
||||
if (unlikely(!qtd))
|
||||
return -1;
|
||||
list_add_tail(&qtd->qtd_list, head);
|
||||
@@ -1193,7 +1193,7 @@ static int submit_single_step_set_feature(
|
||||
sizeof(struct usb_ctrlrequest),
|
||||
QTD_IOC | token | (2 /* "setup" */ << 8), 8);
|
||||
|
||||
- submit_async(ehci, urb, &qtd_list, GFP_ATOMIC);
|
||||
+ submit_async(ehci, urb, &qtd_list, GFP_LX_DMA);
|
||||
return 0; /*Return now; we shall come back after 15 seconds*/
|
||||
}
|
||||
|
||||
@@ -1221,7 +1221,7 @@ static int submit_single_step_set_feature(
|
||||
token |= QTD_TOGGLE; /* force DATA1 */
|
||||
|
||||
qtd_prev = qtd;
|
||||
- qtd = ehci_qtd_alloc(ehci, GFP_ATOMIC);
|
||||
+ qtd = ehci_qtd_alloc(ehci, GFP_LX_DMA);
|
||||
if (unlikely(!qtd))
|
||||
goto cleanup;
|
||||
qtd->urb = urb;
|
||||
@@ -1231,7 +1231,7 @@ static int submit_single_step_set_feature(
|
||||
/* Interrupt after STATUS completion */
|
||||
qtd_fill(ehci, qtd, 0, 0, token | QTD_IOC, 0);
|
||||
|
||||
- submit_async(ehci, urb, &qtd_list, GFP_KERNEL);
|
||||
+ submit_async(ehci, urb, &qtd_list, GFP_LX_DMA);
|
||||
|
||||
return 0;
|
||||
|
||||
diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c
|
||||
index ac7d4ac..1eb1fc7 100644
|
||||
--- a/drivers/usb/host/ohci-dbg.c
|
||||
+++ b/drivers/usb/host/ohci-dbg.c
|
||||
@@ -683,7 +683,7 @@ static int fill_buffer(struct debug_buffer *buf)
|
||||
int ret = 0;
|
||||
|
||||
if (!buf->page)
|
||||
- buf->page = (char *)get_zeroed_page(GFP_KERNEL);
|
||||
+ buf->page = (char *)get_zeroed_page(GFP_LX_DMA);
|
||||
|
||||
if (!buf->page) {
|
||||
ret = -ENOMEM;
|
||||
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
|
||||
index d088c34..2211b20 100644
|
||||
--- a/drivers/usb/host/ohci-hcd.c
|
||||
+++ b/drivers/usb/host/ohci-hcd.c
|
||||
@@ -506,7 +506,7 @@ static int ohci_init (struct ohci_hcd *ohci)
|
||||
ohci->prev_frame_no = IO_WATCHDOG_OFF;
|
||||
|
||||
ohci->hcca = dma_alloc_coherent (hcd->self.controller,
|
||||
- sizeof(*ohci->hcca), &ohci->hcca_dma, GFP_KERNEL);
|
||||
+ sizeof(*ohci->hcca), &ohci->hcca_dma, GFP_LX_DMA);
|
||||
if (!ohci->hcca)
|
||||
return -ENOMEM;
|
||||
|
||||
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
|
||||
index f9c3947..99a1696 100644
|
||||
--- a/drivers/usb/host/uhci-hcd.c
|
||||
+++ b/drivers/usb/host/uhci-hcd.c
|
||||
@@ -602,7 +602,7 @@ static int uhci_start(struct usb_hcd *hcd)
|
||||
|
||||
uhci->frame = dma_zalloc_coherent(uhci_dev(uhci),
|
||||
UHCI_NUMFRAMES * sizeof(*uhci->frame),
|
||||
- &uhci->frame_dma_handle, GFP_KERNEL);
|
||||
+ &uhci->frame_dma_handle, GFP_LX_DMA);
|
||||
if (!uhci->frame) {
|
||||
dev_err(uhci_dev(uhci),
|
||||
"unable to allocate consistent memory for frame list\n");
|
||||
@@ -610,7 +610,7 @@ static int uhci_start(struct usb_hcd *hcd)
|
||||
}
|
||||
|
||||
uhci->frame_cpu = kcalloc(UHCI_NUMFRAMES, sizeof(*uhci->frame_cpu),
|
||||
- GFP_KERNEL);
|
||||
+ GFP_LX_DMA);
|
||||
if (!uhci->frame_cpu)
|
||||
goto err_alloc_frame_cpu;
|
||||
|
||||
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
|
||||
index 35fcb82..3a0cff5 100644
|
||||
--- a/drivers/usb/host/uhci-q.c
|
||||
+++ b/drivers/usb/host/uhci-q.c
|
||||
@@ -108,7 +108,7 @@ static struct uhci_td *uhci_alloc_td(struct uhci_hcd *uhci)
|
||||
dma_addr_t dma_handle;
|
||||
struct uhci_td *td;
|
||||
|
||||
- td = dma_pool_alloc(uhci->td_pool, GFP_ATOMIC, &dma_handle);
|
||||
+ td = dma_pool_alloc(uhci->td_pool, GFP_LX_DMA, &dma_handle);
|
||||
if (!td)
|
||||
return NULL;
|
||||
|
||||
@@ -248,7 +248,7 @@ static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci,
|
||||
dma_addr_t dma_handle;
|
||||
struct uhci_qh *qh;
|
||||
|
||||
- qh = dma_pool_zalloc(uhci->qh_pool, GFP_ATOMIC, &dma_handle);
|
||||
+ qh = dma_pool_zalloc(uhci->qh_pool, GFP_LX_DMA, &dma_handle);
|
||||
if (!qh)
|
||||
return NULL;
|
||||
|
||||
@@ -724,7 +724,7 @@ static inline struct urb_priv *uhci_alloc_urb_priv(struct uhci_hcd *uhci,
|
||||
{
|
||||
struct urb_priv *urbp;
|
||||
|
||||
- urbp = kmem_cache_zalloc(uhci_up_cachep, GFP_ATOMIC);
|
||||
+ urbp = kmem_cache_zalloc(uhci_up_cachep, GFP_LX_DMA);
|
||||
if (!urbp)
|
||||
return NULL;
|
||||
|
||||
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
|
||||
index 72ebbc9..0e815a8 100644
|
||||
--- a/drivers/usb/host/xhci-hub.c
|
||||
+++ b/drivers/usb/host/xhci-hub.c
|
||||
@@ -404,7 +404,7 @@ static int xhci_stop_device(struct xhci_hcd *xhci, int slot_id, int suspend)
|
||||
if (GET_EP_CTX_STATE(ep_ctx) != EP_STATE_RUNNING)
|
||||
continue;
|
||||
|
||||
- command = xhci_alloc_command(xhci, false, GFP_NOWAIT);
|
||||
+ command = xhci_alloc_command(xhci, false, GFP_LX_DMA);
|
||||
if (!command) {
|
||||
spin_unlock_irqrestore(&xhci->lock, flags);
|
||||
ret = -ENOMEM;
|
||||
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
|
||||
index 332420d..e037aaf 100644
|
||||
--- a/drivers/usb/host/xhci-mem.c
|
||||
+++ b/drivers/usb/host/xhci-mem.c
|
||||
@@ -2135,7 +2135,7 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports,
|
||||
rhub->psi_count = XHCI_EXT_PORT_PSIC(temp);
|
||||
if (rhub->psi_count) {
|
||||
rhub->psi = kcalloc(rhub->psi_count, sizeof(*rhub->psi),
|
||||
- GFP_KERNEL);
|
||||
+ GFP_LX_DMA);
|
||||
if (!rhub->psi)
|
||||
rhub->psi_count = 0;
|
||||
|
||||
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
|
||||
index daa94c3..028891a 100644
|
||||
--- a/drivers/usb/host/xhci-ring.c
|
||||
+++ b/drivers/usb/host/xhci-ring.c
|
||||
@@ -656,6 +656,7 @@
|
||||
struct device *dev = xhci_to_hcd(xhci)->self.controller;
|
||||
struct xhci_segment *seg = td->bounce_seg;
|
||||
struct urb *urb = td->urb;
|
||||
+ size_t len;
|
||||
|
||||
if (!ring || !seg || !urb)
|
||||
return;
|
||||
@@ -667,8 +668,16 @@
|
||||
}
|
||||
|
||||
/* for in tranfers we need to copy the data from bounce to sg */
|
||||
- sg_pcopy_from_buffer(urb->sg, urb->num_mapped_sgs, seg->bounce_buf,
|
||||
- seg->bounce_len, seg->bounce_offs);
|
||||
+ if (urb->num_sgs) {
|
||||
+ len = sg_pcopy_from_buffer(urb->sg, urb->num_mapped_sgs, seg->bounce_buf,
|
||||
+ seg->bounce_len, seg->bounce_offs);
|
||||
+ if (len != seg->bounce_len)
|
||||
+ xhci_warn(xhci, "WARN Wrong bounce buffer read length: %zu != %d\n",
|
||||
+ len, seg->bounce_len);
|
||||
+ } else {
|
||||
+ memcpy(urb->transfer_buffer + seg->bounce_offs, seg->bounce_buf,
|
||||
+ seg->bounce_len);
|
||||
+ }
|
||||
dma_unmap_single(dev, seg->bounce_dma, ring->bounce_buf_len,
|
||||
DMA_FROM_DEVICE);
|
||||
seg->bounce_len = 0;
|
||||
@@ -1141,7 +1150,7 @@
|
||||
if (xhci->quirks & XHCI_RESET_EP_QUIRK) {
|
||||
struct xhci_command *command;
|
||||
|
||||
- command = xhci_alloc_command(xhci, false, GFP_ATOMIC);
|
||||
+ command = xhci_alloc_command(xhci, false, GFP_LX_DMA);
|
||||
if (!command)
|
||||
return;
|
||||
|
||||
@@ -1821,7 +1830,7 @@
|
||||
{
|
||||
struct xhci_virt_ep *ep = &xhci->devs[slot_id]->eps[ep_index];
|
||||
struct xhci_command *command;
|
||||
- command = xhci_alloc_command(xhci, false, GFP_ATOMIC);
|
||||
+ command = xhci_alloc_command(xhci, false, GFP_LX_DMA);
|
||||
if (!command)
|
||||
return;
|
||||
|
||||
@@ -3136,6 +3145,7 @@
|
||||
unsigned int unalign;
|
||||
unsigned int max_pkt;
|
||||
u32 new_buff_len;
|
||||
+ size_t len;
|
||||
|
||||
max_pkt = usb_endpoint_maxp(&urb->ep->desc);
|
||||
unalign = (enqd_len + *trb_buff_len) % max_pkt;
|
||||
@@ -3166,8 +3176,17 @@
|
||||
|
||||
/* create a max max_pkt sized bounce buffer pointed to by last trb */
|
||||
if (usb_urb_dir_out(urb)) {
|
||||
- sg_pcopy_to_buffer(urb->sg, urb->num_mapped_sgs,
|
||||
- seg->bounce_buf, new_buff_len, enqd_len);
|
||||
+ if (urb->num_sgs) {
|
||||
+ len = sg_pcopy_to_buffer(urb->sg, urb->num_mapped_sgs,
|
||||
+ seg->bounce_buf, new_buff_len, enqd_len);
|
||||
+ if (len != new_buff_len) {
|
||||
+ xhci_warn(xhci, "WARN Wrong bounce buffer write length: %zu != %d\n",
|
||||
+ len, new_buff_len);
|
||||
+ }
|
||||
+ } else {
|
||||
+ memcpy(seg->bounce_buf, urb->transfer_buffer + enqd_len,
|
||||
+ new_buff_len);
|
||||
+ }
|
||||
seg->bounce_dma = dma_map_single(dev, seg->bounce_buf,
|
||||
max_pkt, DMA_TO_DEVICE);
|
||||
} else {
|
||||
@@ -3906,7 +3925,7 @@
|
||||
reserved_trbs++;
|
||||
|
||||
ret = prepare_ring(xhci, xhci->cmd_ring, EP_STATE_RUNNING,
|
||||
- reserved_trbs, GFP_ATOMIC);
|
||||
+ reserved_trbs, GFP_LX_DMA);
|
||||
if (ret < 0) {
|
||||
xhci_err(xhci, "ERR: No room for command on command ring\n");
|
||||
if (command_must_succeed)
|
||||
@@ -4040,7 +4059,7 @@
|
||||
}
|
||||
|
||||
/* This function gets called from contexts where it cannot sleep */
|
||||
- cmd = xhci_alloc_command(xhci, false, GFP_ATOMIC);
|
||||
+ cmd = xhci_alloc_command(xhci, false, GFP_LX_DMA);
|
||||
if (!cmd)
|
||||
return;
|
||||
|
||||
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
|
||||
index 5d37700..1945abb 100644
|
||||
--- a/drivers/usb/host/xhci.c
|
||||
+++ b/drivers/usb/host/xhci.c
|
||||
@@ -602,7 +604,7 @@ int xhci_run(struct usb_hcd *hcd)
|
||||
if (xhci->quirks & XHCI_NEC_HOST) {
|
||||
struct xhci_command *command;
|
||||
|
||||
- command = xhci_alloc_command(xhci, false, GFP_KERNEL);
|
||||
+ command = xhci_alloc_command(xhci, false, GFP_LX_DMA);
|
||||
if (!command)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -1244,7 +1246,7 @@ static int xhci_check_maxpacket(struct xhci_hcd *xhci, unsigned int slot_id,
|
||||
* changes max packet sizes.
|
||||
*/
|
||||
|
||||
- command = xhci_alloc_command(xhci, true, GFP_KERNEL);
|
||||
+ command = xhci_alloc_command(xhci, true, GFP_LX_DMA);
|
||||
if (!command)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -1355,7 +1357,7 @@ static int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flag
|
||||
switch (usb_endpoint_type(&urb->ep->desc)) {
|
||||
|
||||
case USB_ENDPOINT_XFER_CONTROL:
|
||||
- ret = xhci_queue_ctrl_tx(xhci, GFP_ATOMIC, urb,
|
||||
+ ret = xhci_queue_ctrl_tx(xhci, GFP_LX_DMA, urb,
|
||||
slot_id, ep_index);
|
||||
break;
|
||||
case USB_ENDPOINT_XFER_BULK:
|
||||
@@ -1366,18 +1368,18 @@ static int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flag
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
- ret = xhci_queue_bulk_tx(xhci, GFP_ATOMIC, urb,
|
||||
+ ret = xhci_queue_bulk_tx(xhci, GFP_LX_DMA, urb,
|
||||
slot_id, ep_index);
|
||||
break;
|
||||
|
||||
|
||||
case USB_ENDPOINT_XFER_INT:
|
||||
- ret = xhci_queue_intr_tx(xhci, GFP_ATOMIC, urb,
|
||||
+ ret = xhci_queue_intr_tx(xhci, GFP_LX_DMA, urb,
|
||||
slot_id, ep_index);
|
||||
break;
|
||||
|
||||
case USB_ENDPOINT_XFER_ISOC:
|
||||
- ret = xhci_queue_isoc_tx_prepare(xhci, GFP_ATOMIC, urb,
|
||||
+ ret = xhci_queue_isoc_tx_prepare(xhci, GFP_LX_DMA, urb,
|
||||
slot_id, ep_index);
|
||||
}
|
||||
|
||||
@@ -1499,7 +1501,7 @@ static int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
|
||||
* the first cancellation to be handled.
|
||||
*/
|
||||
if (!(ep->ep_state & EP_STOP_CMD_PENDING)) {
|
||||
- command = xhci_alloc_command(xhci, false, GFP_ATOMIC);
|
||||
+ command = xhci_alloc_command(xhci, false, GFP_LX_DMA);
|
||||
if (!command) {
|
||||
ret = -ENOMEM;
|
||||
goto done;
|
||||
@@ -2684,7 +2686,7 @@ static int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
|
||||
xhci_dbg(xhci, "%s called for udev %p\n", __func__, udev);
|
||||
virt_dev = xhci->devs[udev->slot_id];
|
||||
|
||||
- command = xhci_alloc_command(xhci, true, GFP_KERNEL);
|
||||
+ command = xhci_alloc_command(xhci, true, GFP_LX_DMA);
|
||||
if (!command)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -3560,7 +3562,7 @@ int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id)
|
||||
u32 state;
|
||||
int ret = 0;
|
||||
|
||||
- command = xhci_alloc_command(xhci, false, GFP_KERNEL);
|
||||
+ command = xhci_alloc_command(xhci, false, GFP_LX_DMA);
|
||||
if (!command)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -3622,7 +3624,7 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev)
|
||||
int ret, slot_id;
|
||||
struct xhci_command *command;
|
||||
|
||||
- command = xhci_alloc_command(xhci, true, GFP_KERNEL);
|
||||
+ command = xhci_alloc_command(xhci, true, GFP_LX_DMA);
|
||||
if (!command)
|
||||
return 0;
|
||||
|
||||
@@ -3755,7 +3757,7 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev,
|
||||
}
|
||||
}
|
||||
|
||||
- command = xhci_alloc_command(xhci, true, GFP_KERNEL);
|
||||
+ command = xhci_alloc_command(xhci, true, GFP_LX_DMA);
|
||||
if (!command) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
@@ -4688,7 +4690,7 @@ static int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev,
|
||||
|
||||
spin_lock_irqsave(&xhci->lock, flags);
|
||||
if (hdev->speed == USB_SPEED_HIGH &&
|
||||
- xhci_alloc_tt_info(xhci, vdev, hdev, tt, GFP_ATOMIC)) {
|
||||
+ xhci_alloc_tt_info(xhci, vdev, hdev, tt, GFP_LX_DMA)) {
|
||||
xhci_dbg(xhci, "Could not allocate xHCI TT structure.\n");
|
||||
xhci_free_command(xhci, config_cmd);
|
||||
spin_unlock_irqrestore(&xhci->lock, flags);
|
@ -1,12 +0,0 @@
|
||||
diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
|
||||
index 8d8bafc..3c3f71c 100644
|
||||
--- a/drivers/usb/host/ehci-omap.c
|
||||
+++ b/drivers/usb/host/ehci-omap.c
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <linux/clk.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/usb/hcd.h>
|
||||
+#include <linux/usb/phy.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
|
@ -1,105 +0,0 @@
|
||||
This is a backport of commit dc0ffbea5729a3abafa577ebfce87f18b79e294b:
|
||||
|
||||
Subject: [PATCH] usb: host: xhci: update event ring dequeue pointer on purpose
|
||||
|
||||
On some situations, the software handles TRB events slower
|
||||
than adding TRBs, then xhci_handle_event can't return zero
|
||||
long time, the xHC will consider the event ring is full,
|
||||
and trigger "Event Ring Full" error, but in fact, the software
|
||||
has already finished lots of events, just no chance to
|
||||
update ERDP (event ring dequeue pointer).
|
||||
|
||||
In this commit, we force update ERDP if half of TRBS_PER_SEGMENT
|
||||
events have handled to avoid "Event Ring Full" error.
|
||||
|
||||
Signed-off-by: Peter Chen <peter.chen@nxp.com>
|
||||
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
|
||||
Link: https://lore.kernel.org/r/1573836603-10871-2-git-send-email-mathias.nyman@linux.intel.com
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
--- a/drivers/usb/host/xhci-ring.c
|
||||
+++ b/drivers/usb/host/xhci-ring.c
|
||||
@@ -2717,6 +2717,42 @@
|
||||
}
|
||||
|
||||
/*
|
||||
+ * Update Event Ring Dequeue Pointer:
|
||||
+ * - When all events have finished
|
||||
+ * - To avoid "Event Ring Full Error" condition
|
||||
+ */
|
||||
+static void xhci_update_erst_dequeue(struct xhci_hcd *xhci,
|
||||
+ union xhci_trb *event_ring_deq)
|
||||
+{
|
||||
+ u64 temp_64;
|
||||
+ dma_addr_t deq;
|
||||
+
|
||||
+ temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
|
||||
+ /* If necessary, update the HW's version of the event ring deq ptr. */
|
||||
+ if (event_ring_deq != xhci->event_ring->dequeue) {
|
||||
+ deq = xhci_trb_virt_to_dma(xhci->event_ring->deq_seg,
|
||||
+ xhci->event_ring->dequeue);
|
||||
+ if (deq == 0)
|
||||
+ xhci_warn(xhci, "WARN something wrong with SW event ring dequeue ptr\n");
|
||||
+ /*
|
||||
+ * Per 4.9.4, Software writes to the ERDP register shall
|
||||
+ * always advance the Event Ring Dequeue Pointer value.
|
||||
+ */
|
||||
+ if ((temp_64 & (u64) ~ERST_PTR_MASK) ==
|
||||
+ ((u64) deq & (u64) ~ERST_PTR_MASK))
|
||||
+ return;
|
||||
+
|
||||
+ /* Update HC event ring dequeue pointer */
|
||||
+ temp_64 &= ERST_PTR_MASK;
|
||||
+ temp_64 |= ((u64) deq & (u64) ~ERST_PTR_MASK);
|
||||
+ }
|
||||
+
|
||||
+ /* Clear the event handler busy flag (RW1C) */
|
||||
+ temp_64 |= ERST_EHB;
|
||||
+ xhci_write_64(xhci, temp_64, &xhci->ir_set->erst_dequeue);
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
* xHCI spec says we can get an interrupt, and if the HC has an error condition,
|
||||
* we might get bad data out of the event ring. Section 4.10.2.7 has a list of
|
||||
* indicators of an event TRB error, but we check the status *first* to be safe.
|
||||
@@ -2727,9 +2763,9 @@
|
||||
union xhci_trb *event_ring_deq;
|
||||
irqreturn_t ret = IRQ_NONE;
|
||||
unsigned long flags;
|
||||
- dma_addr_t deq;
|
||||
u64 temp_64;
|
||||
u32 status;
|
||||
+ int event_loop = 0;
|
||||
|
||||
spin_lock_irqsave(&xhci->lock, flags);
|
||||
/* Check if the xHC generated the interrupt, or the irq is shared */
|
||||
@@ -2783,24 +2819,14 @@
|
||||
/* FIXME this should be a delayed service routine
|
||||
* that clears the EHB.
|
||||
*/
|
||||
- while (xhci_handle_event(xhci) > 0) {}
|
||||
-
|
||||
- temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
|
||||
- /* If necessary, update the HW's version of the event ring deq ptr. */
|
||||
- if (event_ring_deq != xhci->event_ring->dequeue) {
|
||||
- deq = xhci_trb_virt_to_dma(xhci->event_ring->deq_seg,
|
||||
- xhci->event_ring->dequeue);
|
||||
- if (deq == 0)
|
||||
- xhci_warn(xhci, "WARN something wrong with SW event "
|
||||
- "ring dequeue ptr.\n");
|
||||
- /* Update HC event ring dequeue pointer */
|
||||
- temp_64 &= ERST_PTR_MASK;
|
||||
- temp_64 |= ((u64) deq & (u64) ~ERST_PTR_MASK);
|
||||
+ while (xhci_handle_event(xhci) > 0) {
|
||||
+ if (event_loop++ < TRBS_PER_SEGMENT / 2)
|
||||
+ continue;
|
||||
+ xhci_update_erst_dequeue(xhci, event_ring_deq);
|
||||
+ event_loop = 0;
|
||||
}
|
||||
|
||||
- /* Clear the event handler busy flag (RW1C); event ring is empty. */
|
||||
- temp_64 |= ERST_EHB;
|
||||
- xhci_write_64(xhci, temp_64, &xhci->ir_set->erst_dequeue);
|
||||
+ xhci_update_erst_dequeue(xhci, event_ring_deq);
|
||||
ret = IRQ_HANDLED;
|
||||
|
||||
out:
|
@ -1,71 +0,0 @@
|
||||
From 09f736aa95476631227d2dc0e6b9aeee1ad7ed58 Mon Sep 17 00:00:00 2001
|
||||
From: Mathias Nyman <mathias.nyman@linux.intel.com>
|
||||
Date: Fri, 26 Nov 2021 14:23:40 +0200
|
||||
Subject: xhci: Fix commad ring abort, write all 64 bits to CRCR register.
|
||||
|
||||
Turns out some xHC controllers require all 64 bits in the CRCR register
|
||||
to be written to execute a command abort.
|
||||
|
||||
The lower 32 bits containing the command abort bit is written first.
|
||||
In case the command ring stops before we write the upper 32 bits then
|
||||
hardware may use these upper bits to set the commnd ring dequeue pointer.
|
||||
|
||||
Solve this by making sure the upper 32 bits contain a valid command
|
||||
ring dequeue pointer.
|
||||
|
||||
The original patch that only wrote the first 32 to stop the ring went
|
||||
to stable, so this fix should go there as well.
|
||||
|
||||
Fixes: ff0e50d3564f ("xhci: Fix command ring pointer corruption while aborting a command")
|
||||
Cc: stable@vger.kernel.org
|
||||
Tested-by: Pavankumar Kondeti <quic_pkondeti@quicinc.com>
|
||||
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
|
||||
Link: https://lore.kernel.org/r/20211126122340.1193239-2-mathias.nyman@linux.intel.com
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/usb/host/xhci-ring.c | 21 ++++++++++++++-------
|
||||
1 file changed, 14 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
|
||||
index 311597bba80e2..eaa49aef29352 100644
|
||||
--- a/drivers/usb/host/xhci-ring.c
|
||||
+++ b/drivers/usb/host/xhci-ring.c
|
||||
@@ -366,7 +366,9 @@ static void xhci_handle_stopped_cmd_ring(struct xhci_hcd *xhci,
|
||||
/* Must be called with xhci->lock held, releases and aquires lock back */
|
||||
static int xhci_abort_cmd_ring(struct xhci_hcd *xhci, unsigned long flags)
|
||||
{
|
||||
- u32 temp_32;
|
||||
+ struct xhci_segment *new_seg = xhci->cmd_ring->deq_seg;
|
||||
+ union xhci_trb *new_deq = xhci->cmd_ring->dequeue;
|
||||
+ u64 crcr;
|
||||
int ret;
|
||||
|
||||
xhci_dbg(xhci, "Abort command ring\n");
|
||||
@@ -375,13 +377,18 @@ static int xhci_abort_cmd_ring(struct xhci_hcd *xhci, unsigned long flags)
|
||||
|
||||
/*
|
||||
* The control bits like command stop, abort are located in lower
|
||||
- * dword of the command ring control register. Limit the write
|
||||
- * to the lower dword to avoid corrupting the command ring pointer
|
||||
- * in case if the command ring is stopped by the time upper dword
|
||||
- * is written.
|
||||
+ * dword of the command ring control register.
|
||||
+ * Some controllers require all 64 bits to be written to abort the ring.
|
||||
+ * Make sure the upper dword is valid, pointing to the next command,
|
||||
+ * avoiding corrupting the command ring pointer in case the command ring
|
||||
+ * is stopped by the time the upper dword is written.
|
||||
*/
|
||||
- temp_32 = readl(&xhci->op_regs->cmd_ring);
|
||||
- writel(temp_32 | CMD_RING_ABORT, &xhci->op_regs->cmd_ring);
|
||||
+ next_trb(xhci, NULL, &new_seg, &new_deq);
|
||||
+ if (trb_is_link(new_deq))
|
||||
+ next_trb(xhci, NULL, &new_seg, &new_deq);
|
||||
+
|
||||
+ crcr = xhci_trb_virt_to_dma(new_seg, new_deq);
|
||||
+ xhci_write_64(xhci, crcr | CMD_RING_ABORT, &xhci->op_regs->cmd_ring);
|
||||
|
||||
/* Section 4.6.1.2 of xHCI 1.0 spec says software should also time the
|
||||
* completion of the Command Abort operation. If CRR is not negated in 5
|
||||
--
|
||||
cgit
|
||||
|
@ -1,59 +0,0 @@
|
||||
From e91ac20889d1a26d077cc511365cd7ff4346a6f3 Mon Sep 17 00:00:00 2001
|
||||
From: Weitao Wang <WeitaoWang-oc@zhaoxin.com>
|
||||
Date: Fri, 8 Apr 2022 16:48:21 +0300
|
||||
Subject: [PATCH] USB: Fix xhci event ring dequeue pointer ERDP update issue
|
||||
|
||||
In some situations software handles TRB events slower than adding TRBs.
|
||||
If the number of TRB events to be processed in a given interrupt is exactly
|
||||
the same as the event ring size 256, then the local variable
|
||||
"event_ring_deq" that holds the initial dequeue position is equal to
|
||||
software_dequeue after handling all 256 interrupts.
|
||||
|
||||
It will cause driver to not update ERDP to hardware,
|
||||
|
||||
Software dequeue pointer is out of sync with ERDP on interrupt exit.
|
||||
On the next interrupt, the event ring may full but driver will not
|
||||
update ERDP as software_dequeue is equal to ERDP.
|
||||
|
||||
[ 536.377115] xhci_hcd 0000:00:12.0: ERROR unknown event type 37
|
||||
[ 566.933173] sd 8:0:0:0: [sdb] tag#27 uas_eh_abort_handler 0 uas-tag 7 inflight: CMD OUT
|
||||
[ 566.933181] sd 8:0:0:0: [sdb] tag#27 CDB: Write(10) 2a 00 17 71 e6 78 00 00 08 00
|
||||
[ 572.041186] xhci_hcd On some situataions,the0000:00:12.0: xHCI host not responding to stop endpoint command.
|
||||
[ 572.057193] xhci_hcd 0000:00:12.0: Host halt failed, -110
|
||||
[ 572.057196] xhci_hcd 0000:00:12.0: xHCI host controller not responding, assume dead
|
||||
[ 572.057236] sd 8:0:0:0: [sdb] tag#26 uas_eh_abort_handler 0 uas-tag 6 inflight: CMD
|
||||
[ 572.057240] sd 8:0:0:0: [sdb] tag#26 CDB: Write(10) 2a 00 38 eb cc d8 00 00 08 00
|
||||
[ 572.057244] sd 8:0:0:0: [sdb] tag#25 uas_eh_abort_handler 0 uas-tag 5 inflight: CMD
|
||||
|
||||
Hardware ERDP is updated mid event handling if there are more than 128
|
||||
events in an interrupt (half of ring size).
|
||||
Fix this by updating the software local variable at the same time as
|
||||
hardware ERDP.
|
||||
|
||||
[commit message rewording -Mathias]
|
||||
|
||||
Fixes: dc0ffbea5729 ("usb: host: xhci: update event ring dequeue pointer on purpose")
|
||||
Reviewed-by: Peter Chen <peter.chen@kernel.org>
|
||||
Signed-off-by: Weitao Wang <WeitaoWang-oc@zhaoxin.com>
|
||||
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
|
||||
Link: https://lore.kernel.org/r/20220408134823.2527272-2-mathias.nyman@linux.intel.com
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/usb/host/xhci-ring.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
|
||||
index d0b6806275e0..f9707997969d 100644
|
||||
--- a/drivers/usb/host/xhci-ring.c
|
||||
+++ b/drivers/usb/host/xhci-ring.c
|
||||
@@ -3141,6 +3141,7 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd)
|
||||
if (event_loop++ < TRBS_PER_SEGMENT / 2)
|
||||
continue;
|
||||
xhci_update_erst_dequeue(xhci, event_ring_deq);
|
||||
+ event_ring_deq = xhci->event_ring->dequeue;
|
||||
|
||||
/* ring is half-full, force isoc trbs to interrupt more often */
|
||||
if (xhci->isoc_bei_interval > AVOID_BEI_INTERVAL_MIN)
|
||||
--
|
||||
2.25.1
|
||||
|
@ -1,28 +0,0 @@
|
||||
LIB_MK := lib/mk/usb_host_include.mk lib/import/import-usb_arch_include.mk \
|
||||
$(foreach SPEC,arm arm_64 x86_32 x86_64,lib/mk/spec/$(SPEC)/lx_kit_setjmp.mk)
|
||||
|
||||
PORT_DIR := $(call port_dir,$(REP_DIR)/ports/dde_linux)
|
||||
|
||||
MIRROR_FROM_REP_DIR := $(LIB_MK) \
|
||||
lib/import/import-usb_host_include.mk \
|
||||
src/include/legacy src/lib/legacy/lx_kit \
|
||||
src/lib/lx_kit/spec \
|
||||
$(foreach SPEC,arm arm_64 arm_v6 arm_v7 x86 x86_32 x86_64,src/include/spec/$(SPEC)) \
|
||||
$(shell cd $(REP_DIR); find src/drivers/usb_host -type f)
|
||||
|
||||
MIRROR_FROM_PORT_DIR := $(shell cd $(PORT_DIR); find src/drivers/usb_host -type f | grep -v ".git")
|
||||
MIRROR_FROM_PORT_DIR := $(filter-out $(MIRROR_FROM_REP_DIR),$(MIRROR_FROM_PORT_DIR))
|
||||
|
||||
content: $(MIRROR_FROM_REP_DIR) $(MIRROR_FROM_PORT_DIR)
|
||||
|
||||
$(MIRROR_FROM_REP_DIR):
|
||||
$(mirror_from_rep_dir)
|
||||
|
||||
$(MIRROR_FROM_PORT_DIR):
|
||||
mkdir -p $(dir $@)
|
||||
cp $(PORT_DIR)/$@ $@
|
||||
|
||||
content: LICENSE
|
||||
LICENSE:
|
||||
( echo "GNU General Public License version 2, see:"; \
|
||||
echo "https://www.kernel.org/pub/linux/kernel/COPYING" ) > $@
|
@ -1 +0,0 @@
|
||||
2023-08-21 0db2afb6d236762f066a30556c1c765800d6ed85
|
@ -1,8 +0,0 @@
|
||||
base
|
||||
os
|
||||
format
|
||||
usb_session
|
||||
gpio_session
|
||||
platform_session
|
||||
timer_session
|
||||
report_session
|
@ -1,89 +0,0 @@
|
||||
/*
|
||||
* \brief Generic base of a network session using a DDE Linux back end
|
||||
* \author Martin Stein
|
||||
* \date 2020-12-13
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2020 Genode Labs GmbH
|
||||
*
|
||||
* This file is distributed under the terms of the GNU General Public License
|
||||
* version 2.
|
||||
*/
|
||||
|
||||
#include <linux_network_session_base.h>
|
||||
#include <legacy/lx_kit/scheduler.h>
|
||||
#include <lx_emul.h>
|
||||
|
||||
|
||||
void Linux_network_session_base::_run_tx_task(void * args)
|
||||
{
|
||||
Tx_data *data = static_cast<Tx_data*>(args);
|
||||
|
||||
while (1) {
|
||||
Lx::scheduler().current()->block_and_schedule();
|
||||
|
||||
net_device * ndev = data->ndev;
|
||||
struct sk_buff * skb = data->skb;
|
||||
|
||||
ndev->netdev_ops->ndo_start_xmit(skb, ndev);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Linux_network_session_base::_run_rx_task(void * args)
|
||||
{
|
||||
Rx_data *data = static_cast<Rx_data*>(args);
|
||||
|
||||
while (1) {
|
||||
Lx::scheduler().current()->block_and_schedule();
|
||||
|
||||
int ret = 0;
|
||||
struct napi_struct * n = data->napi;
|
||||
|
||||
for (;;) {
|
||||
|
||||
/* This NAPI_STATE_SCHED test is for avoiding a race
|
||||
* with netpoll's poll_napi(). Only the entity which
|
||||
* obtains the lock and sees NAPI_STATE_SCHED set will
|
||||
* actually make the ->poll() call. Therefore we avoid
|
||||
* accidentally calling ->poll() when NAPI is not scheduled.
|
||||
*/
|
||||
if (!test_bit(NAPI_STATE_SCHED, &n->state)) break;
|
||||
|
||||
int weight = n->weight;
|
||||
int work = n->poll(n, weight);
|
||||
ret += work;
|
||||
|
||||
if (work < weight) break;
|
||||
|
||||
Genode::warning("Too much incoming traffic, we should "
|
||||
"schedule RX more intelligent");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Linux_network_session_base::
|
||||
Linux_network_session_base(Genode::Session_label const &label)
|
||||
:
|
||||
_ndev { _register_session(*this, label) }
|
||||
{
|
||||
if (!_ndev) {
|
||||
error("failed to register session with label \"", label, "\"");
|
||||
throw Genode::Service_denied();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Linux_network_session_base::_read_link_state_from_ndev() const
|
||||
{
|
||||
return !(_ndev->state & (1UL << __LINK_STATE_NOCARRIER));
|
||||
}
|
||||
|
||||
|
||||
void Linux_network_session_base::unblock_rx_task(napi_struct * n)
|
||||
{
|
||||
_rx_data.napi = n;
|
||||
_rx_task.unblock();
|
||||
}
|
@ -1,78 +0,0 @@
|
||||
/*
|
||||
* \brief Virtual interface of a network session connected to the driver
|
||||
* \author Martin Stein
|
||||
* \date 2020-12-13
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2020 Genode Labs GmbH
|
||||
*
|
||||
* This file is distributed under the terms of the GNU General Public License
|
||||
* version 2.
|
||||
*/
|
||||
|
||||
#ifndef _SRC__DRIVERS__NIC__LINUX_NETWORK_SESSION_BASE_H_
|
||||
#define _SRC__DRIVERS__NIC__LINUX_NETWORK_SESSION_BASE_H_
|
||||
|
||||
#include <legacy/lx_kit/scheduler.h>
|
||||
|
||||
/* forward declarations */
|
||||
extern "C" {
|
||||
struct net_device;
|
||||
struct napi_struct;
|
||||
struct sk_buff;
|
||||
}
|
||||
|
||||
|
||||
class Linux_network_session_base
|
||||
{
|
||||
protected:
|
||||
|
||||
enum { HEAD_ROOM = 8 };
|
||||
|
||||
struct Tx_data
|
||||
{
|
||||
net_device * ndev;
|
||||
sk_buff * skb;
|
||||
};
|
||||
|
||||
struct Rx_data
|
||||
{
|
||||
struct napi_struct * napi;
|
||||
};
|
||||
|
||||
net_device * _ndev = nullptr;
|
||||
Tx_data _tx_data;
|
||||
Rx_data _rx_data;
|
||||
Lx::Task _tx_task { _run_tx_task, &_tx_data, "tx_task",
|
||||
Lx::Task::PRIORITY_1, Lx::scheduler() };
|
||||
Lx::Task _rx_task { _run_rx_task, &_rx_data, "rx_task",
|
||||
Lx::Task::PRIORITY_1, Lx::scheduler() };
|
||||
|
||||
static void _run_tx_task(void * args);
|
||||
|
||||
static void _run_rx_task(void * args);
|
||||
|
||||
static net_device *
|
||||
_register_session(Linux_network_session_base &session,
|
||||
Genode::Session_label label);
|
||||
|
||||
bool _read_link_state_from_ndev() const;
|
||||
|
||||
public:
|
||||
|
||||
Linux_network_session_base(Genode::Session_label const &label);
|
||||
|
||||
void unblock_rx_task(napi_struct * n);
|
||||
|
||||
|
||||
/***********************
|
||||
** Virtual interface **
|
||||
***********************/
|
||||
|
||||
virtual void receive(struct sk_buff *skb) = 0;
|
||||
|
||||
virtual void link_state(bool state) = 0;
|
||||
};
|
||||
|
||||
#endif /* _SRC__DRIVERS__NIC__LINUX_NETWORK_SESSION_BASE_H_ */
|
Loading…
Reference in New Issue
Block a user