RE: [PATCH 36/37] xhci: simplify how we store TDs in urb private data

2017-01-23 Thread David Laight
From: David Laight
> Sent: 23 January 2017 11:58
> From: Mathias Nyman
> > Sent: 20 January 2017 14:47
> 
> > Instead of storing a zero length array of td pointers, and then
> > allocate memory both for the td pointer array and the td's, just
> > use a zero length array of actual td's in urb private data.
> 
> This reminds me of an old patch that got reverted because things
> broke because the lifetimes/accesses of the data wasn't the obvious one.

Mathias checked (off list) and the handling of stalled endpoints has
apparently changed - which is what caused the problem with the old patch.

David

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 36/37] xhci: simplify how we store TDs in urb private data

2017-01-23 Thread Mathias Nyman

On 23.01.2017 14:15, Mathias Nyman wrote:

On 23.01.2017 13:57, David Laight wrote:

From: Mathias Nyman

Sent: 20 January 2017 14:47



Instead of storing a zero length array of td pointers, and then
allocate memory both for the td pointer array and the td's, just
use a zero length array of actual td's in urb private data.


This reminds me of an old patch that got reverted because things
broke because the lifetimes/accesses of the data wasn't the obvious one.



Can you recall more details about that case? I'd hate to revert this
later.



Thanks for the (off list) info.

You submitted a similar patch in 2013, but it caused a regression and was not 
applied:

https://www.spinics.net/lists/linux-usb/msg99748.html

Reason it regressed back then was because we handled stalled endpoints a bit 
differently.
We saved a pointer to the current TD of a stalled endpoint, then gave back the
URB, and freed urb_priv, but _not_ the TD that urb_priv->td[x] pointed to.

This TD was later used in the endpoint reset callback to figure out where we 
should
set the dequeue pointer of that ring.

Handling stalled endpoints has changed since then. We don't store the TD 
pointer in
STALL cases, and we free the urb_priv completely when giving back the URB

see:

commit 8e71a322fdb127814bcba423a512914ca5bc6cf5
USB: xhci: Reset a halted endpoint immediately when we encounter a stall.

So now it should work

-Mathias


--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


RE: [PATCH 36/37] xhci: simplify how we store TDs in urb private data

2017-01-23 Thread David Laight
From: Mathias Nyman
> Sent: 20 January 2017 14:47

> Instead of storing a zero length array of td pointers, and then
> allocate memory both for the td pointer array and the td's, just
> use a zero length array of actual td's in urb private data.

This reminds me of an old patch that got reverted because things
broke because the lifetimes/accesses of the data wasn't the obvious one.

That might have been a different structure.

FWIW it is a shame that things like USB3 ethernet can't transmit and
receive without all these intermediate and dynamically allocated
structures.

David

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 36/37] xhci: simplify how we store TDs in urb private data

2017-01-23 Thread Mathias Nyman

On 23.01.2017 13:57, David Laight wrote:

From: Mathias Nyman

Sent: 20 January 2017 14:47



Instead of storing a zero length array of td pointers, and then
allocate memory both for the td pointer array and the td's, just
use a zero length array of actual td's in urb private data.


This reminds me of an old patch that got reverted because things
broke because the lifetimes/accesses of the data wasn't the obvious one.



Can you recall more details about that case? I'd hate to revert this
later.

I looked at the history how we ended up with this type of allocation for
urb priv. I couldn't find any reverts or reasons why it's the way it is.
  


That might have been a different structure.

FWIW it is a shame that things like USB3 ethernet can't transmit and
receive without all these intermediate and dynamically allocated
structures.


Well, there's one less allocation after this patch :)

-Mathias
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 36/37] xhci: simplify how we store TDs in urb private data

2017-01-20 Thread Mathias Nyman
Instead of storing a zero length array of td pointers, and then
allocate memory both for the td pointer array and the td's, just
use a zero length array of actual td's in urb private data.

old:

struct urb_priv {
   struct xhci_td *td[0]
}

new:

struct urb_priv {
struct xhci_td td[0]
}

Signed-off-by: Mathias Nyman 
---
 drivers/usb/host/xhci-mem.c  |  5 +
 drivers/usb/host/xhci-ring.c | 20 ++--
 drivers/usb/host/xhci.c  | 24 ++--
 drivers/usb/host/xhci.h  |  2 +-
 4 files changed, 18 insertions(+), 33 deletions(-)

diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index e452492..ba1853f4 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -1817,10 +1817,7 @@ struct xhci_command *xhci_alloc_command(struct xhci_hcd 
*xhci,
 
 void xhci_urb_free_priv(struct urb_priv *urb_priv)
 {
-   if (urb_priv) {
-   kfree(urb_priv->td[0]);
-   kfree(urb_priv);
-   }
+   kfree(urb_priv);
 }
 
 void xhci_free_command(struct xhci_hcd *xhci,
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index dbbf8c2..5e51109 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -2841,7 +2841,7 @@ static int prepare_transfer(struct xhci_hcd *xhci,
return ret;
 
urb_priv = urb->hcpriv;
-   td = urb_priv->td[td_index];
+   td = _priv->td[td_index];
 
INIT_LIST_HEAD(>td_list);
INIT_LIST_HEAD(>cancelled_td_list);
@@ -3137,7 +3137,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t 
mem_flags,
if (urb->transfer_flags & URB_ZERO_PACKET && urb_priv->num_tds > 1)
need_zero_pkt = true;
 
-   td = urb_priv->td[0];
+   td = _priv->td[0];
 
/*
 * Don't give the first TRB to the hardware (by toggling the cycle bit)
@@ -3230,7 +3230,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t 
mem_flags,
ret = prepare_transfer(xhci, xhci->devs[slot_id],
   ep_index, urb->stream_id,
   1, urb, 1, mem_flags);
-   urb_priv->td[1]->last_trb = ring->enqueue;
+   urb_priv->td[1].last_trb = ring->enqueue;
field = TRB_TYPE(TRB_NORMAL) | ring->cycle_state | TRB_IOC;
queue_trb(xhci, ring, 0, 0, 0, TRB_INTR_TARGET(0), field);
}
@@ -3282,7 +3282,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t 
mem_flags,
return ret;
 
urb_priv = urb->hcpriv;
-   td = urb_priv->td[0];
+   td = _priv->td[0];
 
/*
 * Don't give the first TRB to the hardware (by toggling the cycle bit)
@@ -3570,7 +3570,7 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, 
gfp_t mem_flags,
return ret;
goto cleanup;
}
-   td = urb_priv->td[i];
+   td = _priv->td[i];
 
/* use SIA as default, if frame id is used overwrite it */
sia_frame_id = TRB_SIA;
@@ -3677,20 +3677,20 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, 
gfp_t mem_flags,
/* Clean up a partially enqueued isoc transfer. */
 
for (i--; i >= 0; i--)
-   list_del_init(_priv->td[i]->td_list);
+   list_del_init(_priv->td[i].td_list);
 
/* Use the first TD as a temporary variable to turn the TDs we've queued
 * into No-ops with a software-owned cycle bit. That way the hardware
 * won't accidentally start executing bogus TDs when we partially
 * overwrite them.  td->first_trb and td->start_seg are already set.
 */
-   urb_priv->td[0]->last_trb = ep_ring->enqueue;
+   urb_priv->td[0].last_trb = ep_ring->enqueue;
/* Every TRB except the first & last will have its cycle bit flipped. */
-   td_to_noop(xhci, ep_ring, urb_priv->td[0], true);
+   td_to_noop(xhci, ep_ring, _priv->td[0], true);
 
/* Reset the ring enqueue back to the first TRB and its cycle bit. */
-   ep_ring->enqueue = urb_priv->td[0]->first_trb;
-   ep_ring->enq_seg = urb_priv->td[0]->start_seg;
+   ep_ring->enqueue = urb_priv->td[0].first_trb;
+   ep_ring->enq_seg = urb_priv->td[0].start_seg;
ep_ring->cycle_state = start_cycle;
ep_ring->num_trbs_free = ep_ring->num_trbs_free_temp;
usb_hcd_unlink_urb_from_ep(bus_to_hcd(urb->dev->bus), urb);
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index bee6272..dde5c2d 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -1332,12 +1332,11 @@ static int xhci_check_maxpacket(struct xhci_hcd *xhci, 
unsigned int slot_id,
 int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags)
 {
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
-   struct xhci_td *buffer;
unsigned long flags;