RE: [PATCH v2] usb: cdns3: Optimize DMA request buffer allocation
Hi Peter, > On 21-03-17 20:13:59, Sanket Parmar wrote: > > dma_alloc_coherent() might fail on the platform with a small > > DMA region. > > > > To avoid such failure in cdns3_prepare_aligned_request_buf(), > > dma_alloc_coherent() is replaced with dma_alloc_noncoherent() > > to allocate aligned request buffer of dynamic length. > > > > Reported-by: Aswath Govindraju > > Signed-off-by: Sanket Parmar > > --- > > > > Changelog: > > v2: > > - used dma_*_noncoherent() APIs > > - changed the commit log > > > > drivers/usb/cdns3/cdns3-gadget.c | 30 - > - > > drivers/usb/cdns3/cdns3-gadget.h | 2 ++ > > 2 files changed, 26 insertions(+), 6 deletions(-) > > > > diff --git a/drivers/usb/cdns3/cdns3-gadget.c b/drivers/usb/cdns3/cdns3- > gadget.c > > index 0b892a2..126087b 100644 > > --- a/drivers/usb/cdns3/cdns3-gadget.c > > +++ b/drivers/usb/cdns3/cdns3-gadget.c > > @@ -819,9 +819,15 @@ void cdns3_gadget_giveback(struct > cdns3_endpoint *priv_ep, > > priv_ep->dir); > > > > if ((priv_req->flags & REQUEST_UNALIGNED) && > > - priv_ep->dir == USB_DIR_OUT && !request->status) > > + priv_ep->dir == USB_DIR_OUT && !request->status) { > > + /* Make DMA buffer CPU accessible */ > > + dma_sync_single_for_cpu(priv_dev->sysdev, > > + priv_req->aligned_buf->dma, > > + priv_req->aligned_buf->size, > > + priv_req->aligned_buf->dir); > > memcpy(request->buf, priv_req->aligned_buf->buf, > >request->length); > > + } > > > > priv_req->flags &= ~(REQUEST_PENDING | REQUEST_UNALIGNED); > > /* All TRBs have finished, clear the counter */ > > @@ -883,8 +889,8 @@ static void cdns3_free_aligned_request_buf(struct > work_struct *work) > > * interrupts. > > */ > > spin_unlock_irqrestore(_dev->lock, flags); > > - dma_free_coherent(priv_dev->sysdev, buf->size, > > - buf->buf, buf->dma); > > + dma_free_noncoherent(priv_dev->sysdev, buf- > >size, > > + buf->buf, buf->dma, buf->dir); > > kfree(buf); > > spin_lock_irqsave(_dev->lock, flags); > > } > > @@ -911,10 +917,13 @@ static int > cdns3_prepare_aligned_request_buf(struct cdns3_request *priv_req) > > return -ENOMEM; > > > > buf->size = priv_req->request.length; > > + buf->dir = usb_endpoint_dir_in(priv_ep->endpoint.desc) ? > > + DMA_TO_DEVICE : DMA_FROM_DEVICE; > > > > - buf->buf = dma_alloc_coherent(priv_dev->sysdev, > > + buf->buf = dma_alloc_noncoherent(priv_dev->sysdev, > > buf->size, > > >dma, > > + buf->dir, > > GFP_ATOMIC); > > if (!buf->buf) { > > kfree(buf); > > @@ -936,10 +945,18 @@ static int > cdns3_prepare_aligned_request_buf(struct cdns3_request *priv_req) > > } > > > > if (priv_ep->dir == USB_DIR_IN) { > > + /* Make DMA buffer CPU accessible */ > > + dma_sync_single_for_cpu(priv_dev->sysdev, > > + buf->dma, buf->size, buf->dir); > > memcpy(buf->buf, priv_req->request.buf, > >priv_req->request.length); > > } > > > > + /* Transfer DMA buffer ownership back to device */ > > + dma_sync_single_for_device(priv_dev->sysdev, > > + buf->dma, buf->size, buf->dir); > > + > > + > > One more blank line. > > Otherwise, it seems OK for me. I have remove this blank line. New patch has been posted already. > > > priv_req->flags |= REQUEST_UNALIGNED; > > trace_cdns3_prepare_aligned_request(priv_req); > > > > @@ -3088,9 +3105,10 @@ static void cdns3_gadget_exit(struct cdns *cdns) > > struct cdns3_aligned_buf *buf; > > > > buf = cdns3_next_align_buf(_dev->aligned_buf_list); > > - dm
[PATCH v3] usb: cdns3: Optimize DMA request buffer allocation
dma_alloc_coherent() might fail on the platform with a small DMA region. To avoid such failure in cdns3_prepare_aligned_request_buf(), dma_alloc_coherent() is replaced with dma_alloc_noncoherent() to allocate aligned request buffer of dynamic length. Reported-by: Aswath Govindraju Signed-off-by: Sanket Parmar --- Changelog: v3: - removed extra blank line v2: - used dma_*_noncoherent() APIs - changed the commit log drivers/usb/cdns3/cdns3-gadget.c | 29 +++-- drivers/usb/cdns3/cdns3-gadget.h | 2 ++ 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/drivers/usb/cdns3/cdns3-gadget.c b/drivers/usb/cdns3/cdns3-gadget.c index 0b892a2..9b1bd41 100644 --- a/drivers/usb/cdns3/cdns3-gadget.c +++ b/drivers/usb/cdns3/cdns3-gadget.c @@ -819,9 +819,15 @@ void cdns3_gadget_giveback(struct cdns3_endpoint *priv_ep, priv_ep->dir); if ((priv_req->flags & REQUEST_UNALIGNED) && - priv_ep->dir == USB_DIR_OUT && !request->status) + priv_ep->dir == USB_DIR_OUT && !request->status) { + /* Make DMA buffer CPU accessible */ + dma_sync_single_for_cpu(priv_dev->sysdev, + priv_req->aligned_buf->dma, + priv_req->aligned_buf->size, + priv_req->aligned_buf->dir); memcpy(request->buf, priv_req->aligned_buf->buf, request->length); + } priv_req->flags &= ~(REQUEST_PENDING | REQUEST_UNALIGNED); /* All TRBs have finished, clear the counter */ @@ -883,8 +889,8 @@ static void cdns3_free_aligned_request_buf(struct work_struct *work) * interrupts. */ spin_unlock_irqrestore(_dev->lock, flags); - dma_free_coherent(priv_dev->sysdev, buf->size, - buf->buf, buf->dma); + dma_free_noncoherent(priv_dev->sysdev, buf->size, + buf->buf, buf->dma, buf->dir); kfree(buf); spin_lock_irqsave(_dev->lock, flags); } @@ -911,10 +917,13 @@ static int cdns3_prepare_aligned_request_buf(struct cdns3_request *priv_req) return -ENOMEM; buf->size = priv_req->request.length; + buf->dir = usb_endpoint_dir_in(priv_ep->endpoint.desc) ? + DMA_TO_DEVICE : DMA_FROM_DEVICE; - buf->buf = dma_alloc_coherent(priv_dev->sysdev, + buf->buf = dma_alloc_noncoherent(priv_dev->sysdev, buf->size, >dma, + buf->dir, GFP_ATOMIC); if (!buf->buf) { kfree(buf); @@ -936,10 +945,17 @@ static int cdns3_prepare_aligned_request_buf(struct cdns3_request *priv_req) } if (priv_ep->dir == USB_DIR_IN) { + /* Make DMA buffer CPU accessible */ + dma_sync_single_for_cpu(priv_dev->sysdev, + buf->dma, buf->size, buf->dir); memcpy(buf->buf, priv_req->request.buf, priv_req->request.length); } + /* Transfer DMA buffer ownership back to device */ + dma_sync_single_for_device(priv_dev->sysdev, + buf->dma, buf->size, buf->dir); + priv_req->flags |= REQUEST_UNALIGNED; trace_cdns3_prepare_aligned_request(priv_req); @@ -3088,9 +3104,10 @@ static void cdns3_gadget_exit(struct cdns *cdns) struct cdns3_aligned_buf *buf; buf = cdns3_next_align_buf(_dev->aligned_buf_list); - dma_free_coherent(priv_dev->sysdev, buf->size, + dma_free_noncoherent(priv_dev->sysdev, buf->size, buf->buf, - buf->dma); + buf->dma, + buf->dir); list_del(>list); kfree(buf); diff --git a/drivers/usb/cdns3/cdns3-gadget.h b/drivers/usb/cdns3/cdns3-gadget.h index ecf9b91..c5660f2 100644 --- a/drivers/usb/cdns3/cdns3-gadget.h +++ b/drivers/usb/cdns3/cdns3-gadget.h @@ -12,6 +12,7 @@ #ifndef __LINUX_CDNS3_GADGET #define __LINUX_CDNS3_GADGET #include +#include /* * USBSS-DEV register interface. @@ -1205,6 +1206,7 @@ struct cdns3_aligned_buf { void*buf; dma_addr_t dma; u32 size; + enum dma_data_direction dir; unsignedin_use:1; struct list_headlist; }; -- 2.4.5
[PATCH v2] usb: cdns3: Optimize DMA request buffer allocation
dma_alloc_coherent() might fail on the platform with a small DMA region. To avoid such failure in cdns3_prepare_aligned_request_buf(), dma_alloc_coherent() is replaced with dma_alloc_noncoherent() to allocate aligned request buffer of dynamic length. Reported-by: Aswath Govindraju Signed-off-by: Sanket Parmar --- Changelog: v2: - used dma_*_noncoherent() APIs - changed the commit log drivers/usb/cdns3/cdns3-gadget.c | 30 -- drivers/usb/cdns3/cdns3-gadget.h | 2 ++ 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/drivers/usb/cdns3/cdns3-gadget.c b/drivers/usb/cdns3/cdns3-gadget.c index 0b892a2..126087b 100644 --- a/drivers/usb/cdns3/cdns3-gadget.c +++ b/drivers/usb/cdns3/cdns3-gadget.c @@ -819,9 +819,15 @@ void cdns3_gadget_giveback(struct cdns3_endpoint *priv_ep, priv_ep->dir); if ((priv_req->flags & REQUEST_UNALIGNED) && - priv_ep->dir == USB_DIR_OUT && !request->status) + priv_ep->dir == USB_DIR_OUT && !request->status) { + /* Make DMA buffer CPU accessible */ + dma_sync_single_for_cpu(priv_dev->sysdev, + priv_req->aligned_buf->dma, + priv_req->aligned_buf->size, + priv_req->aligned_buf->dir); memcpy(request->buf, priv_req->aligned_buf->buf, request->length); + } priv_req->flags &= ~(REQUEST_PENDING | REQUEST_UNALIGNED); /* All TRBs have finished, clear the counter */ @@ -883,8 +889,8 @@ static void cdns3_free_aligned_request_buf(struct work_struct *work) * interrupts. */ spin_unlock_irqrestore(_dev->lock, flags); - dma_free_coherent(priv_dev->sysdev, buf->size, - buf->buf, buf->dma); + dma_free_noncoherent(priv_dev->sysdev, buf->size, + buf->buf, buf->dma, buf->dir); kfree(buf); spin_lock_irqsave(_dev->lock, flags); } @@ -911,10 +917,13 @@ static int cdns3_prepare_aligned_request_buf(struct cdns3_request *priv_req) return -ENOMEM; buf->size = priv_req->request.length; + buf->dir = usb_endpoint_dir_in(priv_ep->endpoint.desc) ? + DMA_TO_DEVICE : DMA_FROM_DEVICE; - buf->buf = dma_alloc_coherent(priv_dev->sysdev, + buf->buf = dma_alloc_noncoherent(priv_dev->sysdev, buf->size, >dma, + buf->dir, GFP_ATOMIC); if (!buf->buf) { kfree(buf); @@ -936,10 +945,18 @@ static int cdns3_prepare_aligned_request_buf(struct cdns3_request *priv_req) } if (priv_ep->dir == USB_DIR_IN) { + /* Make DMA buffer CPU accessible */ + dma_sync_single_for_cpu(priv_dev->sysdev, + buf->dma, buf->size, buf->dir); memcpy(buf->buf, priv_req->request.buf, priv_req->request.length); } + /* Transfer DMA buffer ownership back to device */ + dma_sync_single_for_device(priv_dev->sysdev, + buf->dma, buf->size, buf->dir); + + priv_req->flags |= REQUEST_UNALIGNED; trace_cdns3_prepare_aligned_request(priv_req); @@ -3088,9 +3105,10 @@ static void cdns3_gadget_exit(struct cdns *cdns) struct cdns3_aligned_buf *buf; buf = cdns3_next_align_buf(_dev->aligned_buf_list); - dma_free_coherent(priv_dev->sysdev, buf->size, + dma_free_noncoherent(priv_dev->sysdev, buf->size, buf->buf, - buf->dma); + buf->dma, + buf->dir); list_del(>list); kfree(buf); diff --git a/drivers/usb/cdns3/cdns3-gadget.h b/drivers/usb/cdns3/cdns3-gadget.h index ecf9b91..c5660f2 100644 --- a/drivers/usb/cdns3/cdns3-gadget.h +++ b/drivers/usb/cdns3/cdns3-gadget.h @@ -12,6 +12,7 @@ #ifndef __LINUX_CDNS3_GADGET #define __LINUX_CDNS3_GADGET #include +#include /* * USBSS-DEV register interface. @@ -1205,6 +1206,7 @@ struct cdns3_aligned_buf { void*buf; dma_addr_t dma; u32 size; + enum dma_data_direction dir; unsignedin_use:1; struct list_headlist; }; -- 2.4.5
RE: [PATCH 2/2] usb: cdns3: Optimize DMA request buffer allocation
> > On 21-03-09 06:19:40, Sanket Parmar wrote: > > dma_alloc_coherent() might fail on the platform with a small DMA region. > > > > To avoid such failure in cdns3_prepare_aligned_request_buf(), > > dma_alloc_coherent() is replaced with kmalloc and dma_map API to > > allocate aligned request buffer of dynamic length. > > > > Fixes: 7733f6c32e36 ("usb: cdns3: Add Cadence USB3 DRD Driver") > > The comment with the 1st patch, it is not a bug-fix. I will remove this. > > > Reported-by: Aswath Govindraju > > Signed-off-by: Sanket Parmar > > --- > > drivers/usb/cdns3/cdns3-gadget.c | 73 +-- > -- > > drivers/usb/cdns3/cdns3-gadget.h |2 + > > 2 files changed, 51 insertions(+), 24 deletions(-) > > > > diff --git a/drivers/usb/cdns3/cdns3-gadget.c b/drivers/usb/cdns3/cdns3- > gadget.c > > index 5f51215..b4955ce 100644 > > --- a/drivers/usb/cdns3/cdns3-gadget.c > > +++ b/drivers/usb/cdns3/cdns3-gadget.c > > @@ -818,10 +818,26 @@ void cdns3_gadget_giveback(struct > cdns3_endpoint *priv_ep, > > usb_gadget_unmap_request_by_dev(priv_dev->sysdev, request, > > priv_ep->dir); > > > > - if ((priv_req->flags & REQUEST_UNALIGNED) && > > - priv_ep->dir == USB_DIR_OUT && !request->status) > > - memcpy(request->buf, priv_req->aligned_buf->buf, > > - request->length); > > + if ((priv_req->flags & REQUEST_UNALIGNED) && priv_req- > >aligned_buf) { > > + struct cdns3_aligned_buf *buf; > > + > > + buf = priv_req->aligned_buf; > > + dma_unmap_single(priv_dev->sysdev, buf->dma, buf->size, > > + buf->dir); > > + priv_req->flags &= ~REQUEST_UNALIGNED; > > + > > + if (priv_ep->dir == USB_DIR_OUT && !request->status) { > > + memcpy(request->buf, priv_req->aligned_buf->buf, > > + request->length); > > + } > > + > > + trace_cdns3_free_aligned_request(priv_req); > > + priv_req->aligned_buf->in_use = 0; > > + queue_work(system_freezable_wq, > > + _dev->aligned_buf_wq); > > + priv_req->aligned_buf = NULL; > > + > > + } > > > > priv_req->flags &= ~(REQUEST_PENDING | REQUEST_UNALIGNED); > > /* All TRBs have finished, clear the counter */ > > @@ -883,8 +899,7 @@ static void cdns3_free_aligned_request_buf(struct > work_struct *work) > > * interrupts. > > */ > > spin_unlock_irqrestore(_dev->lock, flags); > > - dma_free_coherent(priv_dev->sysdev, buf->size, > > - buf->buf, buf->dma); > > + kfree(buf->buf); > > kfree(buf); > > spin_lock_irqsave(_dev->lock, flags); > > } > > @@ -910,27 +925,16 @@ static int > cdns3_prepare_aligned_request_buf(struct cdns3_request *priv_req) > > if (!buf) > > return -ENOMEM; > > > > - buf->size = priv_req->request.length; > > + buf->size = usb_endpoint_dir_out(priv_ep->endpoint.desc) > ? > > + usb_ep_align(&(priv_ep->endpoint), > priv_req->request.length) > > + : priv_req->request.length; > > > > - buf->buf = dma_alloc_coherent(priv_dev->sysdev, > > - buf->size, > > - >dma, > > - GFP_ATOMIC); > > + buf->buf = kmalloc(buf->size, GFP_ATOMIC); > > if (!buf->buf) { > > kfree(buf); > > return -ENOMEM; > > } > > > > - if (priv_req->aligned_buf) { > > - trace_cdns3_free_aligned_request(priv_req); > > - priv_req->aligned_buf->in_use = 0; > > - queue_work(system_freezable_wq, > > - _dev->aligned_buf_wq); > > - } > > - > > - buf->in_use = 1; > > - priv_req->aligned_buf = buf; > > - > > list_add_tail(>list, >
RE: [PATCH 1/2] usb: cdns3: Use dma_pool_* api to alloc trb pool
Hi Peter, > > On 21-03-09 06:19:39, Sanket Parmar wrote: > > Allocation of DMA coherent memory in atomic context using > > dma_alloc_coherent() might fail on platforms with smaller > > DMA region. > > > > To fix it, dma_alloc_coherent() is replaced with dma_pool > > API to allocate a smaller chunk of DMA coherent memory for > > TRB rings. > > > > Fixes: 7733f6c32e36 ("usb: cdns3: Add Cadence USB3 DRD Driver") > > The patch is ok, but I don't think it is a bug-fix, it is an > improvement for smaller DMA region use case. > > I will apply it with deletion of above Fixes tag if you have no > more opinion. > Please go ahead. Thanks, Sanket > Peter > > Reported-by: Aswath Govindraju > > Signed-off-by: Sanket Parmar > > --- > > drivers/usb/cdns3/cdns3-gadget.c | 42 +--- > - > > drivers/usb/cdns3/cdns3-gadget.h |1 + > > 2 files changed, 20 insertions(+), 23 deletions(-) > > > > diff --git a/drivers/usb/cdns3/cdns3-gadget.c b/drivers/usb/cdns3/cdns3- > gadget.c > > index 582bfec..5f51215 100644 > > --- a/drivers/usb/cdns3/cdns3-gadget.c > > +++ b/drivers/usb/cdns3/cdns3-gadget.c > > @@ -59,6 +59,7 @@ > > #include > > #include > > #include > > +#include > > #include > > > > #include "core.h" > > @@ -190,29 +191,13 @@ dma_addr_t cdns3_trb_virt_to_dma(struct > cdns3_endpoint *priv_ep, > > return priv_ep->trb_pool_dma + offset; > > } > > > > -static int cdns3_ring_size(struct cdns3_endpoint *priv_ep) > > -{ > > - switch (priv_ep->type) { > > - case USB_ENDPOINT_XFER_ISOC: > > - return TRB_ISO_RING_SIZE; > > - case USB_ENDPOINT_XFER_CONTROL: > > - return TRB_CTRL_RING_SIZE; > > - default: > > - if (priv_ep->use_streams) > > - return TRB_STREAM_RING_SIZE; > > - else > > - return TRB_RING_SIZE; > > - } > > -} > > - > > static void cdns3_free_trb_pool(struct cdns3_endpoint *priv_ep) > > { > > struct cdns3_device *priv_dev = priv_ep->cdns3_dev; > > > > if (priv_ep->trb_pool) { > > - dma_free_coherent(priv_dev->sysdev, > > - cdns3_ring_size(priv_ep), > > - priv_ep->trb_pool, priv_ep- > >trb_pool_dma); > > + dma_pool_free(priv_dev->eps_dma_pool, > > + priv_ep->trb_pool, priv_ep->trb_pool_dma); > > priv_ep->trb_pool = NULL; > > } > > } > > @@ -226,7 +211,7 @@ static void cdns3_free_trb_pool(struct > cdns3_endpoint *priv_ep) > > int cdns3_allocate_trb_pool(struct cdns3_endpoint *priv_ep) > > { > > struct cdns3_device *priv_dev = priv_ep->cdns3_dev; > > - int ring_size = cdns3_ring_size(priv_ep); > > + int ring_size = TRB_RING_SIZE; > > int num_trbs = ring_size / TRB_SIZE; > > struct cdns3_trb *link_trb; > > > > @@ -234,10 +219,10 @@ int cdns3_allocate_trb_pool(struct > cdns3_endpoint *priv_ep) > > cdns3_free_trb_pool(priv_ep); > > > > if (!priv_ep->trb_pool) { > > - priv_ep->trb_pool = dma_alloc_coherent(priv_dev->sysdev, > > - ring_size, > > - _ep- > >trb_pool_dma, > > - GFP_DMA32 | > GFP_ATOMIC); > > + priv_ep->trb_pool = dma_pool_alloc(priv_dev- > >eps_dma_pool, > > + GFP_DMA32 | > GFP_ATOMIC, > > + _ep->trb_pool_dma); > > + > > if (!priv_ep->trb_pool) > > return -ENOMEM; > > > > @@ -3113,6 +3098,7 @@ static void cdns3_gadget_exit(struct cdns *cdns) > > > > dma_free_coherent(priv_dev->sysdev, 8, priv_dev->setup_buf, > > priv_dev->setup_dma); > > + dma_pool_destroy(priv_dev->eps_dma_pool); > > > > kfree(priv_dev->zlp_buf); > > usb_put_gadget(_dev->gadget); > > @@ -3185,6 +3171,14 @@ static int cdns3_gadget_start(struct cdns *cdns) > > /* initialize endpoint container */ > > INIT_LIST_HEAD(_dev->gadget.ep_list); > > INIT_LIST_HEAD(_dev->aligned_buf_list); > > + priv_dev->eps_dma_pool = > dma_pool_create("cdns3_eps_dma_pool", >
RE: [PATCH 2/2] usb: cdns3: Optimize DMA request buffer allocation
> On Tue, Mar 09, 2021 at 10:18:43AM +0000, Sanket Parmar wrote: > > > On Tue, Mar 09, 2021 at 06:19:40AM +0100, Sanket Parmar wrote: > > > > dma_alloc_coherent() might fail on the platform with a small DMA > region. > > > > > > > > To avoid such failure in cdns3_prepare_aligned_request_buf(), > > > > dma_alloc_coherent() is replaced with kmalloc and dma_map API to > > > > allocate aligned request buffer of dynamic length. > > > > > > dma_alloc_noncoherent is the proper API instead of using kmalloc, which > > > can lead to unaddressable memory that might require bounce buffering. > > > > cdns3 device required DMA coherent buffer to perform operations. So > > dma_alloc_noncoherent will not help here. > > > > Also all gadget classes(except g_ether) use kmalloc to allocated request > buffer, > > and device driver uses usb_gadget_map_request_by_dev to map the > request > > buffer. Similar approach is used to allocate aligned buffer. > > If you can use kmalloc and dma_map_single you can use > dma_alloc_noncoherent per definition. Okay. I was not aware of it. I will test it. Thank you for your feedback. -- Sanket
RE: [PATCH 2/2] usb: cdns3: Optimize DMA request buffer allocation
> On Tue, Mar 09, 2021 at 06:19:40AM +0100, Sanket Parmar wrote: > > dma_alloc_coherent() might fail on the platform with a small DMA region. > > > > To avoid such failure in cdns3_prepare_aligned_request_buf(), > > dma_alloc_coherent() is replaced with kmalloc and dma_map API to > > allocate aligned request buffer of dynamic length. > > dma_alloc_noncoherent is the proper API instead of using kmalloc, which > can lead to unaddressable memory that might require bounce buffering. cdns3 device required DMA coherent buffer to perform operations. So dma_alloc_noncoherent will not help here. Also all gadget classes(except g_ether) use kmalloc to allocated request buffer, and device driver uses usb_gadget_map_request_by_dev to map the request buffer. Similar approach is used to allocate aligned buffer. Thanks, Sanket
RE: [PATCH] usb: cdns3: Coherent memory allocation optimization
Hi Peter, > On 21-03-05 17:01:11, Sanket Parmar wrote: > > Allocation of DMA coherent memory in atomic context using > > dma_alloc_coherent() might fail on some platform. To fix it, > > Replaced dma_alloc_coherent() with dma_pool API to allocate a > > smaller chunk of DMA coherent memory for TRB rings. > > > > Also in cdns3_prepare_aligned_request_buf(), replaced > > dma_alloc_coherent() with kmalloc and dma_map API to allocate > > aligned request buffer of dynamic length. > > > > You do two changes in one commit, would you please split this one as > two patches? > > > Fixes: commit 7733f6c32e36 ("usb: cdns3: Add Cadence USB3 DRD Driver") > > "commit" is not needed > > > Reported by: Aswath Govindraju > > Reported-by: > I have split the change into two patches. New patch series has been posted already. > > Signed-off-by: Sanket Parmar > > --- > > drivers/usb/cdns3/cdns3-gadget.c | 115 ++ > --- > > drivers/usb/cdns3/cdns3-gadget.h |3 + > > 2 files changed, 71 insertions(+), 47 deletions(-) > > > > diff --git a/drivers/usb/cdns3/cdns3-gadget.c b/drivers/usb/cdns3/cdns3- > gadget.c > > index 582bfec..5fd6993 100644 > > --- a/drivers/usb/cdns3/cdns3-gadget.c > > +++ b/drivers/usb/cdns3/cdns3-gadget.c > > @@ -59,6 +59,7 @@ > > #include > > #include > > #include > > +#include > > #include > > > > #include "core.h" > > @@ -190,29 +191,13 @@ dma_addr_t cdns3_trb_virt_to_dma(struct > cdns3_endpoint *priv_ep, > > return priv_ep->trb_pool_dma + offset; > > } > > > > -static int cdns3_ring_size(struct cdns3_endpoint *priv_ep) > > -{ > > - switch (priv_ep->type) { > > - case USB_ENDPOINT_XFER_ISOC: > > - return TRB_ISO_RING_SIZE; > > - case USB_ENDPOINT_XFER_CONTROL: > > - return TRB_CTRL_RING_SIZE; > > - default: > > - if (priv_ep->use_streams) > > - return TRB_STREAM_RING_SIZE; > > - else > > - return TRB_RING_SIZE; > > - } > > -} > > - > > static void cdns3_free_trb_pool(struct cdns3_endpoint *priv_ep) > > { > > struct cdns3_device *priv_dev = priv_ep->cdns3_dev; > > > > if (priv_ep->trb_pool) { > > - dma_free_coherent(priv_dev->sysdev, > > - cdns3_ring_size(priv_ep), > > - priv_ep->trb_pool, priv_ep->trb_pool_dma); > > + dma_pool_free(priv_dev->eps_dma_pool, > > + priv_ep->trb_pool, priv_ep->trb_pool_dma); > > priv_ep->trb_pool = NULL; > > } > > } > > @@ -226,7 +211,7 @@ static void cdns3_free_trb_pool(struct > cdns3_endpoint *priv_ep) > > int cdns3_allocate_trb_pool(struct cdns3_endpoint *priv_ep) > > { > > struct cdns3_device *priv_dev = priv_ep->cdns3_dev; > > - int ring_size = cdns3_ring_size(priv_ep); > > + int ring_size = TRB_RING_SIZE; > > You will use the same size for TRB ring region for control/bulk/isoc > endpoint. > As single DMA pool is used to allocate the ring buffer, different TRB ring size is not possible for different EP. Hence, TRB_RING_SIZE(600 * 12 B) which fits for all type of EPs is used. > > int num_trbs = ring_size / TRB_SIZE; > > struct cdns3_trb *link_trb; > > > > @@ -234,10 +219,10 @@ int cdns3_allocate_trb_pool(struct > cdns3_endpoint *priv_ep) > > cdns3_free_trb_pool(priv_ep); > > > > if (!priv_ep->trb_pool) { > > - priv_ep->trb_pool = dma_alloc_coherent(priv_dev->sysdev, > > - ring_size, > > - _ep->trb_pool_dma, > > - GFP_DMA32 | > GFP_ATOMIC); > > + priv_ep->trb_pool = dma_pool_alloc(priv_dev- > >eps_dma_pool, > > + GFP_DMA32 | GFP_ATOMIC, > > + _ep->trb_pool_dma); > > dma_pool_alloc also allocates the whole thunk of TRB region. See the > kernel-doc for dma_pool_create. > > * Given one of these pools, dma_pool_alloc() > * may be used to allocate memory. Such memory will all have "consistent" Yes, dma_pool_alloc allocates the whole chunk of TRB region for enabled EPs from the pool. Currently the block size of the DMA pool is 7.2KB. So dma
[PATCH 2/2] usb: cdns3: Optimize DMA request buffer allocation
dma_alloc_coherent() might fail on the platform with a small DMA region. To avoid such failure in cdns3_prepare_aligned_request_buf(), dma_alloc_coherent() is replaced with kmalloc and dma_map API to allocate aligned request buffer of dynamic length. Fixes: 7733f6c32e36 ("usb: cdns3: Add Cadence USB3 DRD Driver") Reported-by: Aswath Govindraju Signed-off-by: Sanket Parmar --- drivers/usb/cdns3/cdns3-gadget.c | 73 + drivers/usb/cdns3/cdns3-gadget.h |2 + 2 files changed, 51 insertions(+), 24 deletions(-) diff --git a/drivers/usb/cdns3/cdns3-gadget.c b/drivers/usb/cdns3/cdns3-gadget.c index 5f51215..b4955ce 100644 --- a/drivers/usb/cdns3/cdns3-gadget.c +++ b/drivers/usb/cdns3/cdns3-gadget.c @@ -818,10 +818,26 @@ void cdns3_gadget_giveback(struct cdns3_endpoint *priv_ep, usb_gadget_unmap_request_by_dev(priv_dev->sysdev, request, priv_ep->dir); - if ((priv_req->flags & REQUEST_UNALIGNED) && - priv_ep->dir == USB_DIR_OUT && !request->status) - memcpy(request->buf, priv_req->aligned_buf->buf, - request->length); + if ((priv_req->flags & REQUEST_UNALIGNED) && priv_req->aligned_buf) { + struct cdns3_aligned_buf *buf; + + buf = priv_req->aligned_buf; + dma_unmap_single(priv_dev->sysdev, buf->dma, buf->size, + buf->dir); + priv_req->flags &= ~REQUEST_UNALIGNED; + + if (priv_ep->dir == USB_DIR_OUT && !request->status) { + memcpy(request->buf, priv_req->aligned_buf->buf, + request->length); + } + + trace_cdns3_free_aligned_request(priv_req); + priv_req->aligned_buf->in_use = 0; + queue_work(system_freezable_wq, + _dev->aligned_buf_wq); + priv_req->aligned_buf = NULL; + + } priv_req->flags &= ~(REQUEST_PENDING | REQUEST_UNALIGNED); /* All TRBs have finished, clear the counter */ @@ -883,8 +899,7 @@ static void cdns3_free_aligned_request_buf(struct work_struct *work) * interrupts. */ spin_unlock_irqrestore(_dev->lock, flags); - dma_free_coherent(priv_dev->sysdev, buf->size, - buf->buf, buf->dma); + kfree(buf->buf); kfree(buf); spin_lock_irqsave(_dev->lock, flags); } @@ -910,27 +925,16 @@ static int cdns3_prepare_aligned_request_buf(struct cdns3_request *priv_req) if (!buf) return -ENOMEM; - buf->size = priv_req->request.length; + buf->size = usb_endpoint_dir_out(priv_ep->endpoint.desc) ? + usb_ep_align(&(priv_ep->endpoint), priv_req->request.length) + : priv_req->request.length; - buf->buf = dma_alloc_coherent(priv_dev->sysdev, - buf->size, - >dma, - GFP_ATOMIC); + buf->buf = kmalloc(buf->size, GFP_ATOMIC); if (!buf->buf) { kfree(buf); return -ENOMEM; } - if (priv_req->aligned_buf) { - trace_cdns3_free_aligned_request(priv_req); - priv_req->aligned_buf->in_use = 0; - queue_work(system_freezable_wq, - _dev->aligned_buf_wq); - } - - buf->in_use = 1; - priv_req->aligned_buf = buf; - list_add_tail(>list, _dev->aligned_buf_list); } @@ -940,6 +944,27 @@ static int cdns3_prepare_aligned_request_buf(struct cdns3_request *priv_req) priv_req->request.length); } + if (priv_req->aligned_buf) { + trace_cdns3_free_aligned_request(priv_req); + priv_req->aligned_buf->in_use = 0; + queue_work(system_freezable_wq, + _dev->aligned_buf_wq); + } + + buf->dir = priv_ep->dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE; + buf->in_use = 1; + priv_req->aligned_buf = buf; + + buf->dma = dma_map_single(priv_dev->sysdev, buf->buf, buf->size, + buf->dir); + + if (dma_mapping_error(priv_dev->sysdev, buf-
[PATCH 1/2] usb: cdns3: Use dma_pool_* api to alloc trb pool
Allocation of DMA coherent memory in atomic context using dma_alloc_coherent() might fail on platforms with smaller DMA region. To fix it, dma_alloc_coherent() is replaced with dma_pool API to allocate a smaller chunk of DMA coherent memory for TRB rings. Fixes: 7733f6c32e36 ("usb: cdns3: Add Cadence USB3 DRD Driver") Reported-by: Aswath Govindraju Signed-off-by: Sanket Parmar --- drivers/usb/cdns3/cdns3-gadget.c | 42 + drivers/usb/cdns3/cdns3-gadget.h |1 + 2 files changed, 20 insertions(+), 23 deletions(-) diff --git a/drivers/usb/cdns3/cdns3-gadget.c b/drivers/usb/cdns3/cdns3-gadget.c index 582bfec..5f51215 100644 --- a/drivers/usb/cdns3/cdns3-gadget.c +++ b/drivers/usb/cdns3/cdns3-gadget.c @@ -59,6 +59,7 @@ #include #include #include +#include #include #include "core.h" @@ -190,29 +191,13 @@ dma_addr_t cdns3_trb_virt_to_dma(struct cdns3_endpoint *priv_ep, return priv_ep->trb_pool_dma + offset; } -static int cdns3_ring_size(struct cdns3_endpoint *priv_ep) -{ - switch (priv_ep->type) { - case USB_ENDPOINT_XFER_ISOC: - return TRB_ISO_RING_SIZE; - case USB_ENDPOINT_XFER_CONTROL: - return TRB_CTRL_RING_SIZE; - default: - if (priv_ep->use_streams) - return TRB_STREAM_RING_SIZE; - else - return TRB_RING_SIZE; - } -} - static void cdns3_free_trb_pool(struct cdns3_endpoint *priv_ep) { struct cdns3_device *priv_dev = priv_ep->cdns3_dev; if (priv_ep->trb_pool) { - dma_free_coherent(priv_dev->sysdev, - cdns3_ring_size(priv_ep), - priv_ep->trb_pool, priv_ep->trb_pool_dma); + dma_pool_free(priv_dev->eps_dma_pool, + priv_ep->trb_pool, priv_ep->trb_pool_dma); priv_ep->trb_pool = NULL; } } @@ -226,7 +211,7 @@ static void cdns3_free_trb_pool(struct cdns3_endpoint *priv_ep) int cdns3_allocate_trb_pool(struct cdns3_endpoint *priv_ep) { struct cdns3_device *priv_dev = priv_ep->cdns3_dev; - int ring_size = cdns3_ring_size(priv_ep); + int ring_size = TRB_RING_SIZE; int num_trbs = ring_size / TRB_SIZE; struct cdns3_trb *link_trb; @@ -234,10 +219,10 @@ int cdns3_allocate_trb_pool(struct cdns3_endpoint *priv_ep) cdns3_free_trb_pool(priv_ep); if (!priv_ep->trb_pool) { - priv_ep->trb_pool = dma_alloc_coherent(priv_dev->sysdev, - ring_size, - _ep->trb_pool_dma, - GFP_DMA32 | GFP_ATOMIC); + priv_ep->trb_pool = dma_pool_alloc(priv_dev->eps_dma_pool, + GFP_DMA32 | GFP_ATOMIC, + _ep->trb_pool_dma); + if (!priv_ep->trb_pool) return -ENOMEM; @@ -3113,6 +3098,7 @@ static void cdns3_gadget_exit(struct cdns *cdns) dma_free_coherent(priv_dev->sysdev, 8, priv_dev->setup_buf, priv_dev->setup_dma); + dma_pool_destroy(priv_dev->eps_dma_pool); kfree(priv_dev->zlp_buf); usb_put_gadget(_dev->gadget); @@ -3185,6 +3171,14 @@ static int cdns3_gadget_start(struct cdns *cdns) /* initialize endpoint container */ INIT_LIST_HEAD(_dev->gadget.ep_list); INIT_LIST_HEAD(_dev->aligned_buf_list); + priv_dev->eps_dma_pool = dma_pool_create("cdns3_eps_dma_pool", +priv_dev->sysdev, +TRB_RING_SIZE, 8, 0); + if (!priv_dev->eps_dma_pool) { + dev_err(priv_dev->dev, "Failed to create TRB dma pool\n"); + ret = -ENOMEM; + goto err1; + } ret = cdns3_init_eps(priv_dev); if (ret) { @@ -3235,6 +3229,8 @@ static int cdns3_gadget_start(struct cdns *cdns) err2: cdns3_free_all_eps(priv_dev); err1: + dma_pool_destroy(priv_dev->eps_dma_pool); + usb_put_gadget(_dev->gadget); cdns->gadget_dev = NULL; return ret; diff --git a/drivers/usb/cdns3/cdns3-gadget.h b/drivers/usb/cdns3/cdns3-gadget.h index 21fa461..ecf9b91 100644 --- a/drivers/usb/cdns3/cdns3-gadget.h +++ b/drivers/usb/cdns3/cdns3-gadget.h @@ -1298,6 +1298,7 @@ struct cdns3_device { struct cdns3_usb_regs __iomem *regs; + struct dma_pool *eps_dma_pool; struct usb_ctrlrequest *setup_buf; dma_addr_t setup_dma; void*zlp_buf; -- 1.7.1
[PATCH] usb: cdns3: Coherent memory allocation optimization
Allocation of DMA coherent memory in atomic context using dma_alloc_coherent() might fail on some platform. To fix it, Replaced dma_alloc_coherent() with dma_pool API to allocate a smaller chunk of DMA coherent memory for TRB rings. Also in cdns3_prepare_aligned_request_buf(), replaced dma_alloc_coherent() with kmalloc and dma_map API to allocate aligned request buffer of dynamic length. Fixes: commit 7733f6c32e36 ("usb: cdns3: Add Cadence USB3 DRD Driver") Reported by: Aswath Govindraju Signed-off-by: Sanket Parmar --- drivers/usb/cdns3/cdns3-gadget.c | 115 ++--- drivers/usb/cdns3/cdns3-gadget.h |3 + 2 files changed, 71 insertions(+), 47 deletions(-) diff --git a/drivers/usb/cdns3/cdns3-gadget.c b/drivers/usb/cdns3/cdns3-gadget.c index 582bfec..5fd6993 100644 --- a/drivers/usb/cdns3/cdns3-gadget.c +++ b/drivers/usb/cdns3/cdns3-gadget.c @@ -59,6 +59,7 @@ #include #include #include +#include #include #include "core.h" @@ -190,29 +191,13 @@ dma_addr_t cdns3_trb_virt_to_dma(struct cdns3_endpoint *priv_ep, return priv_ep->trb_pool_dma + offset; } -static int cdns3_ring_size(struct cdns3_endpoint *priv_ep) -{ - switch (priv_ep->type) { - case USB_ENDPOINT_XFER_ISOC: - return TRB_ISO_RING_SIZE; - case USB_ENDPOINT_XFER_CONTROL: - return TRB_CTRL_RING_SIZE; - default: - if (priv_ep->use_streams) - return TRB_STREAM_RING_SIZE; - else - return TRB_RING_SIZE; - } -} - static void cdns3_free_trb_pool(struct cdns3_endpoint *priv_ep) { struct cdns3_device *priv_dev = priv_ep->cdns3_dev; if (priv_ep->trb_pool) { - dma_free_coherent(priv_dev->sysdev, - cdns3_ring_size(priv_ep), - priv_ep->trb_pool, priv_ep->trb_pool_dma); + dma_pool_free(priv_dev->eps_dma_pool, + priv_ep->trb_pool, priv_ep->trb_pool_dma); priv_ep->trb_pool = NULL; } } @@ -226,7 +211,7 @@ static void cdns3_free_trb_pool(struct cdns3_endpoint *priv_ep) int cdns3_allocate_trb_pool(struct cdns3_endpoint *priv_ep) { struct cdns3_device *priv_dev = priv_ep->cdns3_dev; - int ring_size = cdns3_ring_size(priv_ep); + int ring_size = TRB_RING_SIZE; int num_trbs = ring_size / TRB_SIZE; struct cdns3_trb *link_trb; @@ -234,10 +219,10 @@ int cdns3_allocate_trb_pool(struct cdns3_endpoint *priv_ep) cdns3_free_trb_pool(priv_ep); if (!priv_ep->trb_pool) { - priv_ep->trb_pool = dma_alloc_coherent(priv_dev->sysdev, - ring_size, - _ep->trb_pool_dma, - GFP_DMA32 | GFP_ATOMIC); + priv_ep->trb_pool = dma_pool_alloc(priv_dev->eps_dma_pool, + GFP_DMA32 | GFP_ATOMIC, + _ep->trb_pool_dma); + if (!priv_ep->trb_pool) return -ENOMEM; @@ -833,10 +818,26 @@ void cdns3_gadget_giveback(struct cdns3_endpoint *priv_ep, usb_gadget_unmap_request_by_dev(priv_dev->sysdev, request, priv_ep->dir); - if ((priv_req->flags & REQUEST_UNALIGNED) && - priv_ep->dir == USB_DIR_OUT && !request->status) - memcpy(request->buf, priv_req->aligned_buf->buf, - request->length); + if ((priv_req->flags & REQUEST_UNALIGNED) && priv_req->aligned_buf) { + struct cdns3_aligned_buf *buf; + + buf = priv_req->aligned_buf; + dma_unmap_single(priv_dev->sysdev, buf->dma, buf->size, + buf->dir); + priv_req->flags &= ~REQUEST_UNALIGNED; + + if (priv_ep->dir == USB_DIR_OUT && !request->status) { + memcpy(request->buf, priv_req->aligned_buf->buf, + request->length); + } + + trace_cdns3_free_aligned_request(priv_req); + priv_req->aligned_buf->in_use = 0; + queue_work(system_freezable_wq, + _dev->aligned_buf_wq); + priv_req->aligned_buf = NULL; + + } priv_req->flags &= ~(REQUEST_PENDING | REQUEST_UNALIGNED); /* All TRBs have finished, clear the counter */ @@ -898,8 +899,7 @@ static void cdns3_free_aligned_request_buf(struct work_struct *work) * interrupts.
[PATCH] phy: cadence: sierra: Fix for USB3 U1/U2 state
Updated values of USB3 related Sierra PHY registers. This change fixes USB3 device disconnect issue observed while enternig U1/U2 state. Signed-off-by: Sanket Parmar --- drivers/phy/cadence/phy-cadence-sierra.c | 27 ++- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/drivers/phy/cadence/phy-cadence-sierra.c b/drivers/phy/cadence/phy-cadence-sierra.c index a5c08e5..faed652 100644 --- a/drivers/phy/cadence/phy-cadence-sierra.c +++ b/drivers/phy/cadence/phy-cadence-sierra.c @@ -685,10 +685,10 @@ static struct cdns_reg_pairs cdns_usb_cmn_regs_ext_ssc[] = { static struct cdns_reg_pairs cdns_usb_ln_regs_ext_ssc[] = { {0xFE0A, SIERRA_DET_STANDEC_A_PREG}, {0x000F, SIERRA_DET_STANDEC_B_PREG}, - {0x00A5, SIERRA_DET_STANDEC_C_PREG}, + {0x55A5, SIERRA_DET_STANDEC_C_PREG}, {0x69ad, SIERRA_DET_STANDEC_D_PREG}, {0x0241, SIERRA_DET_STANDEC_E_PREG}, - {0x0010, SIERRA_PSM_LANECAL_DLY_A1_RESETS_PREG}, + {0x0110, SIERRA_PSM_LANECAL_DLY_A1_RESETS_PREG}, {0x0014, SIERRA_PSM_A0IN_TMR_PREG}, {0xCF00, SIERRA_PSM_DIAG_PREG}, {0x001F, SIERRA_PSC_TX_A0_PREG}, @@ -696,7 +696,7 @@ static struct cdns_reg_pairs cdns_usb_ln_regs_ext_ssc[] = { {0x0003, SIERRA_PSC_TX_A2_PREG}, {0x0003, SIERRA_PSC_TX_A3_PREG}, {0x0FFF, SIERRA_PSC_RX_A0_PREG}, - {0x0619, SIERRA_PSC_RX_A1_PREG}, + {0x0003, SIERRA_PSC_RX_A1_PREG}, {0x0003, SIERRA_PSC_RX_A2_PREG}, {0x0001, SIERRA_PSC_RX_A3_PREG}, {0x0001, SIERRA_PLLCTRL_SUBRATE_PREG}, @@ -705,19 +705,19 @@ static struct cdns_reg_pairs cdns_usb_ln_regs_ext_ssc[] = { {0x00CA, SIERRA_CLKPATH_BIASTRIM_PREG}, {0x2512, SIERRA_DFE_BIASTRIM_PREG}, {0x, SIERRA_DRVCTRL_ATTEN_PREG}, - {0x873E, SIERRA_CLKPATHCTRL_TMR_PREG}, - {0x03CF, SIERRA_RX_CREQ_FLTR_A_MODE1_PREG}, - {0x01CE, SIERRA_RX_CREQ_FLTR_A_MODE0_PREG}, + {0x823E, SIERRA_CLKPATHCTRL_TMR_PREG}, + {0x078F, SIERRA_RX_CREQ_FLTR_A_MODE1_PREG}, + {0x078F, SIERRA_RX_CREQ_FLTR_A_MODE0_PREG}, {0x7B3C, SIERRA_CREQ_CCLKDET_MODE01_PREG}, - {0x033F, SIERRA_RX_CTLE_MAINTENANCE_PREG}, + {0x023C, SIERRA_RX_CTLE_MAINTENANCE_PREG}, {0x3232, SIERRA_CREQ_FSMCLK_SEL_PREG}, {0x, SIERRA_CREQ_EQ_CTRL_PREG}, - {0x8000, SIERRA_CREQ_SPARE_PREG}, + {0x, SIERRA_CREQ_SPARE_PREG}, {0xCC44, SIERRA_CREQ_EQ_OPEN_EYE_THRESH_PREG}, - {0x8453, SIERRA_CTLELUT_CTRL_PREG}, - {0x4110, SIERRA_DFE_ECMP_RATESEL_PREG}, - {0x4110, SIERRA_DFE_SMP_RATESEL_PREG}, - {0x0002, SIERRA_DEQ_PHALIGN_CTRL}, + {0x8452, SIERRA_CTLELUT_CTRL_PREG}, + {0x4121, SIERRA_DFE_ECMP_RATESEL_PREG}, + {0x4121, SIERRA_DFE_SMP_RATESEL_PREG}, + {0x0003, SIERRA_DEQ_PHALIGN_CTRL}, {0x3200, SIERRA_DEQ_CONCUR_CTRL1_PREG}, {0x5064, SIERRA_DEQ_CONCUR_CTRL2_PREG}, {0x0030, SIERRA_DEQ_EPIPWR_CTRL2_PREG}, @@ -725,7 +725,7 @@ static struct cdns_reg_pairs cdns_usb_ln_regs_ext_ssc[] = { {0x5A5A, SIERRA_DEQ_ERRCMP_CTRL_PREG}, {0x02F5, SIERRA_DEQ_OFFSET_CTRL_PREG}, {0x02F5, SIERRA_DEQ_GAIN_CTRL_PREG}, - {0x9A8A, SIERRA_DEQ_VGATUNE_CTRL_PREG}, + {0x, SIERRA_DEQ_VGATUNE_CTRL_PREG}, {0x0014, SIERRA_DEQ_GLUT0}, {0x0014, SIERRA_DEQ_GLUT1}, {0x0014, SIERRA_DEQ_GLUT2}, @@ -772,6 +772,7 @@ static struct cdns_reg_pairs cdns_usb_ln_regs_ext_ssc[] = { {0x000F, SIERRA_LFPSFILT_NS_PREG}, {0x0009, SIERRA_LFPSFILT_RD_PREG}, {0x0001, SIERRA_LFPSFILT_MP_PREG}, + {0x6013, SIERRA_SIGDET_SUPPORT_PREG}, {0x8013, SIERRA_SDFILT_H2L_A_PREG}, {0x8009, SIERRA_SDFILT_L2H_PREG}, {0x0024, SIERRA_RXBUFFER_CTLECTRL_PREG}, -- 2.4.5