aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ieee1394/iso.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ieee1394/iso.c')
-rw-r--r--drivers/ieee1394/iso.c27
1 files changed, 21 insertions, 6 deletions
diff --git a/drivers/ieee1394/iso.c b/drivers/ieee1394/iso.c
index f05759107f7e..615541b8b90f 100644
--- a/drivers/ieee1394/iso.c
+++ b/drivers/ieee1394/iso.c
@@ -62,10 +62,10 @@ static struct hpsb_iso* hpsb_iso_common_init(struct hpsb_host *host, enum hpsb_i
62 if ((dma_mode < HPSB_ISO_DMA_DEFAULT) || (dma_mode > HPSB_ISO_DMA_PACKET_PER_BUFFER)) 62 if ((dma_mode < HPSB_ISO_DMA_DEFAULT) || (dma_mode > HPSB_ISO_DMA_PACKET_PER_BUFFER))
63 dma_mode=HPSB_ISO_DMA_DEFAULT; 63 dma_mode=HPSB_ISO_DMA_DEFAULT;
64 64
65 if ((irq_interval < 0) || (irq_interval > buf_packets / 4))
66 irq_interval = buf_packets / 4;
65 if (irq_interval == 0) /* really interrupt for each packet*/ 67 if (irq_interval == 0) /* really interrupt for each packet*/
66 irq_interval = 1; 68 irq_interval = 1;
67 else if ((irq_interval < 0) || (irq_interval > buf_packets / 4))
68 irq_interval = buf_packets / 4;
69 69
70 if (channel < -1 || channel >= 64) 70 if (channel < -1 || channel >= 64)
71 return NULL; 71 return NULL;
@@ -106,6 +106,7 @@ static struct hpsb_iso* hpsb_iso_common_init(struct hpsb_host *host, enum hpsb_i
106 } 106 }
107 107
108 atomic_set(&iso->overflows, 0); 108 atomic_set(&iso->overflows, 0);
109 iso->bytes_discarded = 0;
109 iso->flags = 0; 110 iso->flags = 0;
110 iso->prebuffer = 0; 111 iso->prebuffer = 0;
111 112
@@ -241,12 +242,12 @@ int hpsb_iso_xmit_start(struct hpsb_iso *iso, int cycle, int prebuffer)
241 iso->xmit_cycle = cycle; 242 iso->xmit_cycle = cycle;
242 243
243 if (prebuffer < 0) 244 if (prebuffer < 0)
244 prebuffer = iso->buf_packets; 245 prebuffer = iso->buf_packets - 1;
245 else if (prebuffer == 0) 246 else if (prebuffer == 0)
246 prebuffer = 1; 247 prebuffer = 1;
247 248
248 if (prebuffer > iso->buf_packets) 249 if (prebuffer >= iso->buf_packets)
249 prebuffer = iso->buf_packets; 250 prebuffer = iso->buf_packets - 1;
250 251
251 iso->prebuffer = prebuffer; 252 iso->prebuffer = prebuffer;
252 253
@@ -395,7 +396,7 @@ void hpsb_iso_packet_sent(struct hpsb_iso *iso, int cycle, int error)
395} 396}
396 397
397void hpsb_iso_packet_received(struct hpsb_iso *iso, u32 offset, u16 len, 398void hpsb_iso_packet_received(struct hpsb_iso *iso, u32 offset, u16 len,
398 u16 cycle, u8 channel, u8 tag, u8 sy) 399 u16 total_len, u16 cycle, u8 channel, u8 tag, u8 sy)
399{ 400{
400 unsigned long flags; 401 unsigned long flags;
401 spin_lock_irqsave(&iso->lock, flags); 402 spin_lock_irqsave(&iso->lock, flags);
@@ -403,10 +404,13 @@ void hpsb_iso_packet_received(struct hpsb_iso *iso, u32 offset, u16 len,
403 if (iso->n_ready_packets == iso->buf_packets) { 404 if (iso->n_ready_packets == iso->buf_packets) {
404 /* overflow! */ 405 /* overflow! */
405 atomic_inc(&iso->overflows); 406 atomic_inc(&iso->overflows);
407 /* Record size of this discarded packet */
408 iso->bytes_discarded += total_len;
406 } else { 409 } else {
407 struct hpsb_iso_packet_info *info = &iso->infos[iso->pkt_dma]; 410 struct hpsb_iso_packet_info *info = &iso->infos[iso->pkt_dma];
408 info->offset = offset; 411 info->offset = offset;
409 info->len = len; 412 info->len = len;
413 info->total_len = total_len;
410 info->cycle = cycle; 414 info->cycle = cycle;
411 info->channel = channel; 415 info->channel = channel;
412 info->tag = tag; 416 info->tag = tag;
@@ -437,6 +441,17 @@ int hpsb_iso_recv_release_packets(struct hpsb_iso *iso, unsigned int n_packets)
437 441
438 iso->first_packet = (iso->first_packet+1) % iso->buf_packets; 442 iso->first_packet = (iso->first_packet+1) % iso->buf_packets;
439 iso->n_ready_packets--; 443 iso->n_ready_packets--;
444
445 /* release memory from packets discarded when queue was full */
446 if (iso->n_ready_packets == 0) { /* Release only after all prior packets handled */
447 if (iso->bytes_discarded != 0) {
448 struct hpsb_iso_packet_info inf;
449 inf.total_len = iso->bytes_discarded;
450 iso->host->driver->isoctl(iso, RECV_RELEASE,
451 (unsigned long) &inf);
452 iso->bytes_discarded = 0;
453 }
454 }
440 } 455 }
441 spin_unlock_irqrestore(&iso->lock, flags); 456 spin_unlock_irqrestore(&iso->lock, flags);
442 return rv; 457 return rv;