/*
* Clear TX fifo. Needed to avoid BABBLE errors.
*/
-static inline void musb_h_tx_flush_fifo(struct musb_hw_ep *ep)
+static void musb_h_tx_flush_fifo(struct musb_hw_ep *ep)
{
void __iomem *epio = ep->regs;
u16 csr;
urb->actual_length, urb->transfer_buffer_length
);
+ usb_hcd_unlink_urb_from_ep(musb_to_hcd(musb), urb);
spin_unlock(&musb->lock);
usb_hcd_giveback_urb(musb_to_hcd(musb), urb, status);
spin_lock(&musb->lock);
break;
}
- usb_hcd_unlink_urb_from_ep(musb_to_hcd(musb), urb);
-
qh->is_ready = 0;
__musb_giveback(musb, urb, status);
qh->is_ready = ready;
}
}
-static inline u16 musb_h_flush_rxfifo(struct musb_hw_ep *hw_ep, u16 csr)
+static u16 musb_h_flush_rxfifo(struct musb_hw_ep *hw_ep, u16 csr)
{
/* we don't want fifo to fill itself again;
* ignore dma (various models),
/*
* Handle default endpoint interrupt as host. Only called in IRQ time
- * from the LinuxIsr() interrupt service routine.
+ * from musb_interrupt().
*
* called with controller irqlocked
*/
musb_writew(hw_ep->regs, MUSB_RXCSR, val);
#ifdef CONFIG_USB_INVENTRA_DMA
+ if (usb_pipeisoc(pipe)) {
+ struct usb_iso_packet_descriptor *d;
+
+ d = urb->iso_frame_desc + qh->iso_idx;
+ d->actual_length = xfer_len;
+
+ /* even if there was an error, we did the dma
+ * for iso_frame_desc->length
+ */
+ if (d->status != EILSEQ && d->status != -EOVERFLOW)
+ d->status = 0;
+
+ if (++qh->iso_idx >= urb->number_of_packets)
+ done = true;
+ else
+ done = false;
+
+ } else {
/* done if urb buffer is full or short packet is recd */
done = (urb->actual_length + xfer_len >=
urb->transfer_buffer_length
|| dma->actual_len < qh->maxpacket);
+ }
/* send IN token for next packet, without AUTOREQ */
if (!done) {
if (dma) {
struct dma_controller *c;
u16 rx_count;
- int ret;
+ int ret, length;
+ dma_addr_t buf;
rx_count = musb_readw(epio, MUSB_RXCOUNT);
c = musb->dma_controller;
+ if (usb_pipeisoc(pipe)) {
+ int status = 0;
+ struct usb_iso_packet_descriptor *d;
+
+ d = urb->iso_frame_desc + qh->iso_idx;
+
+ if (iso_err) {
+ status = -EILSEQ;
+ urb->error_count++;
+ }
+ if (rx_count > d->length) {
+ if (status == 0) {
+ status = -EOVERFLOW;
+ urb->error_count++;
+ }
+ DBG(2, "** OVERFLOW %d into %d\n",\
+ rx_count, d->length);
+
+ length = d->length;
+ } else
+ length = rx_count;
+ d->status = status;
+ buf = urb->transfer_dma + d->offset;
+ } else {
+ length = rx_count;
+ buf = urb->transfer_dma +
+ urb->actual_length;
+ }
+
dma->desired_mode = 0;
#ifdef USE_MODE1
/* because of the issue below, mode 1 will
urb->actual_length)
> qh->maxpacket)
dma->desired_mode = 1;
+ if (rx_count < hw_ep->max_packet_sz_rx) {
+ length = rx_count;
+ dma->bDesiredMode = 0;
+ } else {
+ length = urb->transfer_buffer_length;
+ }
#endif
/* Disadvantage of using mode 1:
*/
ret = c->channel_program(
dma, qh->maxpacket,
- dma->desired_mode,
- urb->transfer_dma
- + urb->actual_length,
- (dma->desired_mode == 0)
- ? rx_count
- : urb->transfer_buffer_length);
+ dma->desired_mode, buf, length);
if (!ret) {
c->channel_release(dma);
}
}
- if (dma && usb_pipeisoc(pipe)) {
- struct usb_iso_packet_descriptor *d;
- int iso_stat = status;
-
- d = urb->iso_frame_desc + qh->iso_idx;
- d->actual_length += xfer_len;
- if (iso_err) {
- iso_stat = -EILSEQ;
- urb->error_count++;
- }
- d->status = iso_stat;
- }
-
finish:
urb->actual_length += xfer_len;
qh->offset += xfer_len;
*/
qh = kzalloc(sizeof *qh, mem_flags);
if (!qh) {
+ spin_lock_irqsave(&musb->lock, flags);
usb_hcd_unlink_urb_from_ep(hcd, urb);
+ spin_unlock_irqrestore(&musb->lock, flags);
return -ENOMEM;
}
/* set up tt info if needed */
if (urb->dev->tt) {
qh->h_port_reg = (u8) urb->dev->ttport;
- qh->h_addr_reg |= 0x80;
+ if (urb->dev->tt->hub)
+ qh->h_addr_reg =
+ (u8) urb->dev->tt->hub->devnum;
+ if (urb->dev->tt->multi)
+ qh->h_addr_reg |= 0x80;
}
}
}
done:
if (ret != 0) {
+ spin_lock_irqsave(&musb->lock, flags);
usb_hcd_unlink_urb_from_ep(hcd, urb);
+ spin_unlock_irqrestore(&musb->lock, flags);
kfree(qh);
}
return ret;