USB: imx21-hcd: refactor hardware data memory management
We already have fields describing the hardware data memory (dmem_size and dmem_offset) in the HCD private data, use them rather than the rather obscure read from the hardware descriptor. Signed-off-by: Martin Fuzzey <mfuzzey@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
Родитель
e6da55cb0a
Коммит
b2a068d058
|
@ -323,16 +323,23 @@ static void activate_queued_etd(struct imx21 *imx21,
|
||||||
etd_writel(imx21, etd_num, 1,
|
etd_writel(imx21, etd_num, 1,
|
||||||
((dmem_offset + maxpacket) << DW1_YBUFSRTAD) | dmem_offset);
|
((dmem_offset + maxpacket) << DW1_YBUFSRTAD) | dmem_offset);
|
||||||
|
|
||||||
|
etd->dmem_offset = dmem_offset;
|
||||||
urb_priv->active = 1;
|
urb_priv->active = 1;
|
||||||
activate_etd(imx21, etd_num, etd->dma_handle, dir);
|
activate_etd(imx21, etd_num, etd->dma_handle, dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void free_dmem(struct imx21 *imx21, int offset)
|
static void free_dmem(struct imx21 *imx21, struct etd_priv *etd)
|
||||||
{
|
{
|
||||||
struct imx21_dmem_area *area;
|
struct imx21_dmem_area *area;
|
||||||
struct etd_priv *etd, *tmp;
|
struct etd_priv *tmp;
|
||||||
int found = 0;
|
int found = 0;
|
||||||
|
int offset;
|
||||||
|
|
||||||
|
if (!etd->dmem_size)
|
||||||
|
return;
|
||||||
|
etd->dmem_size = 0;
|
||||||
|
|
||||||
|
offset = etd->dmem_offset;
|
||||||
list_for_each_entry(area, &imx21->dmem_list, list) {
|
list_for_each_entry(area, &imx21->dmem_list, list) {
|
||||||
if (area->offset == offset) {
|
if (area->offset == offset) {
|
||||||
debug_dmem_freed(imx21, area->size);
|
debug_dmem_freed(imx21, area->size);
|
||||||
|
@ -734,9 +741,7 @@ static void dequeue_isoc_urb(struct imx21 *imx21,
|
||||||
struct etd_priv *etd = imx21->etd + etd_num;
|
struct etd_priv *etd = imx21->etd + etd_num;
|
||||||
|
|
||||||
reset_etd(imx21, etd_num);
|
reset_etd(imx21, etd_num);
|
||||||
if (etd->dmem_size)
|
free_dmem(imx21, etd);
|
||||||
free_dmem(imx21, etd->dmem_offset);
|
|
||||||
etd->dmem_size = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -761,7 +766,6 @@ static void schedule_nonisoc_etd(struct imx21 *imx21, struct urb *urb)
|
||||||
int state = urb_priv->state;
|
int state = urb_priv->state;
|
||||||
int etd_num = ep_priv->etd[0];
|
int etd_num = ep_priv->etd[0];
|
||||||
struct etd_priv *etd;
|
struct etd_priv *etd;
|
||||||
int dmem_offset;
|
|
||||||
u32 count;
|
u32 count;
|
||||||
u16 etd_buf_size;
|
u16 etd_buf_size;
|
||||||
u16 maxpacket;
|
u16 maxpacket;
|
||||||
|
@ -855,8 +859,8 @@ static void schedule_nonisoc_etd(struct imx21 *imx21, struct urb *urb)
|
||||||
|
|
||||||
/* allocate x and y buffer space at once */
|
/* allocate x and y buffer space at once */
|
||||||
etd->dmem_size = (count > maxpacket) ? maxpacket * 2 : maxpacket;
|
etd->dmem_size = (count > maxpacket) ? maxpacket * 2 : maxpacket;
|
||||||
dmem_offset = alloc_dmem(imx21, etd->dmem_size, urb_priv->ep);
|
etd->dmem_offset = alloc_dmem(imx21, etd->dmem_size, urb_priv->ep);
|
||||||
if (dmem_offset < 0) {
|
if (etd->dmem_offset < 0) {
|
||||||
/* Setup everything we can in HW and update when we get DMEM */
|
/* Setup everything we can in HW and update when we get DMEM */
|
||||||
etd_writel(imx21, etd_num, 1, (u32)maxpacket << 16);
|
etd_writel(imx21, etd_num, 1, (u32)maxpacket << 16);
|
||||||
|
|
||||||
|
@ -867,8 +871,8 @@ static void schedule_nonisoc_etd(struct imx21 *imx21, struct urb *urb)
|
||||||
}
|
}
|
||||||
|
|
||||||
etd_writel(imx21, etd_num, 1,
|
etd_writel(imx21, etd_num, 1,
|
||||||
(((u32) dmem_offset + (u32) maxpacket) << DW1_YBUFSRTAD) |
|
(((u32) etd->dmem_offset + (u32) maxpacket) << DW1_YBUFSRTAD) |
|
||||||
(u32) dmem_offset);
|
(u32) etd->dmem_offset);
|
||||||
|
|
||||||
urb_priv->active = 1;
|
urb_priv->active = 1;
|
||||||
|
|
||||||
|
@ -886,7 +890,6 @@ static void nonisoc_etd_done(struct usb_hcd *hcd, struct urb *urb, int etd_num)
|
||||||
u32 etd_mask = 1 << etd_num;
|
u32 etd_mask = 1 << etd_num;
|
||||||
struct urb_priv *urb_priv = urb->hcpriv;
|
struct urb_priv *urb_priv = urb->hcpriv;
|
||||||
int dir;
|
int dir;
|
||||||
u16 xbufaddr;
|
|
||||||
int cc;
|
int cc;
|
||||||
u32 bytes_xfrd;
|
u32 bytes_xfrd;
|
||||||
int etd_done;
|
int etd_done;
|
||||||
|
@ -894,7 +897,6 @@ static void nonisoc_etd_done(struct usb_hcd *hcd, struct urb *urb, int etd_num)
|
||||||
disactivate_etd(imx21, etd_num);
|
disactivate_etd(imx21, etd_num);
|
||||||
|
|
||||||
dir = (etd_readl(imx21, etd_num, 0) >> DW0_DIRECT) & 0x3;
|
dir = (etd_readl(imx21, etd_num, 0) >> DW0_DIRECT) & 0x3;
|
||||||
xbufaddr = etd_readl(imx21, etd_num, 1) & 0xffff;
|
|
||||||
cc = (etd_readl(imx21, etd_num, 2) >> DW2_COMPCODE) & 0xf;
|
cc = (etd_readl(imx21, etd_num, 2) >> DW2_COMPCODE) & 0xf;
|
||||||
bytes_xfrd = etd->len - (etd_readl(imx21, etd_num, 3) & 0x1fffff);
|
bytes_xfrd = etd->len - (etd_readl(imx21, etd_num, 3) & 0x1fffff);
|
||||||
|
|
||||||
|
@ -907,7 +909,7 @@ static void nonisoc_etd_done(struct usb_hcd *hcd, struct urb *urb, int etd_num)
|
||||||
clear_toggle_bit(imx21, USBH_XFILLSTAT, etd_mask);
|
clear_toggle_bit(imx21, USBH_XFILLSTAT, etd_mask);
|
||||||
clear_toggle_bit(imx21, USBH_YFILLSTAT, etd_mask);
|
clear_toggle_bit(imx21, USBH_YFILLSTAT, etd_mask);
|
||||||
}
|
}
|
||||||
free_dmem(imx21, xbufaddr);
|
free_dmem(imx21, etd);
|
||||||
|
|
||||||
urb->error_count = 0;
|
urb->error_count = 0;
|
||||||
if (!(urb->transfer_flags & URB_SHORT_NOT_OK)
|
if (!(urb->transfer_flags & URB_SHORT_NOT_OK)
|
||||||
|
@ -1123,7 +1125,7 @@ static int imx21_hc_urb_dequeue(struct usb_hcd *hcd, struct urb *urb,
|
||||||
int etd_num = ep_priv->etd[0];
|
int etd_num = ep_priv->etd[0];
|
||||||
if (etd_num != -1) {
|
if (etd_num != -1) {
|
||||||
disactivate_etd(imx21, etd_num);
|
disactivate_etd(imx21, etd_num);
|
||||||
free_dmem(imx21, etd_readl(imx21, etd_num, 1) & 0xffff);
|
free_dmem(imx21, &imx21->etd[etd_num]);
|
||||||
imx21->etd[etd_num].urb = NULL;
|
imx21->etd[etd_num].urb = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче