diff options
Diffstat (limited to 'drivers/ieee1394/iso.c')
-rw-r--r-- | drivers/ieee1394/iso.c | 27 |
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 | ||
397 | void hpsb_iso_packet_received(struct hpsb_iso *iso, u32 offset, u16 len, | 398 | void 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; |