X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=drivers%2Fieee1394%2Fiso.c;h=1cf6487b65ba8ce9c2b042d0dc5bcbcf03369f50;hb=fce4877a6792ad72b88f6fd7556d19da5f20364d;hp=615541b8b90f5fa00c312e571a5fb6ac8d3aaa3f;hpb=1d492eb41371d9a5145651e8eb64bea1042a4057;p=linux-2.6-omap-h63xx.git diff --git a/drivers/ieee1394/iso.c b/drivers/ieee1394/iso.c index 615541b8b90..1cf6487b65b 100644 --- a/drivers/ieee1394/iso.c +++ b/drivers/ieee1394/iso.c @@ -9,10 +9,17 @@ * directory of the kernel sources for details. */ -#include +#include #include +#include +#include + +#include "hosts.h" #include "iso.h" +/** + * hpsb_iso_stop - stop DMA + */ void hpsb_iso_stop(struct hpsb_iso *iso) { if (!(iso->flags & HPSB_ISO_DRIVER_STARTED)) @@ -23,6 +30,9 @@ void hpsb_iso_stop(struct hpsb_iso *iso) iso->flags &= ~HPSB_ISO_DRIVER_STARTED; } +/** + * hpsb_iso_shutdown - deallocate buffer and DMA context + */ void hpsb_iso_shutdown(struct hpsb_iso *iso) { if (iso->flags & HPSB_ISO_DRIVER_INIT) { @@ -36,20 +46,22 @@ void hpsb_iso_shutdown(struct hpsb_iso *iso) kfree(iso); } -static struct hpsb_iso* hpsb_iso_common_init(struct hpsb_host *host, enum hpsb_iso_type type, +static struct hpsb_iso *hpsb_iso_common_init(struct hpsb_host *host, + enum hpsb_iso_type type, unsigned int data_buf_size, unsigned int buf_packets, - int channel, - int dma_mode, + int channel, int dma_mode, int irq_interval, - void (*callback)(struct hpsb_iso*)) + void (*callback) (struct hpsb_iso + *)) { struct hpsb_iso *iso; int dma_direction; /* make sure driver supports the ISO API */ if (!host->driver->isoctl) { - printk(KERN_INFO "ieee1394: host driver '%s' does not support the rawiso API\n", + printk(KERN_INFO + "ieee1394: host driver '%s' does not support the rawiso API\n", host->driver->name); return NULL; } @@ -59,12 +71,13 @@ static struct hpsb_iso* hpsb_iso_common_init(struct hpsb_host *host, enum hpsb_i if (buf_packets < 2) buf_packets = 2; - if ((dma_mode < HPSB_ISO_DMA_DEFAULT) || (dma_mode > HPSB_ISO_DMA_PACKET_PER_BUFFER)) - dma_mode=HPSB_ISO_DMA_DEFAULT; + if ((dma_mode < HPSB_ISO_DMA_DEFAULT) + || (dma_mode > HPSB_ISO_DMA_PACKET_PER_BUFFER)) + dma_mode = HPSB_ISO_DMA_DEFAULT; if ((irq_interval < 0) || (irq_interval > buf_packets / 4)) - irq_interval = buf_packets / 4; - if (irq_interval == 0) /* really interrupt for each packet*/ + irq_interval = buf_packets / 4; + if (irq_interval == 0) /* really interrupt for each packet */ irq_interval = 1; if (channel < -1 || channel >= 64) @@ -76,7 +89,10 @@ static struct hpsb_iso* hpsb_iso_common_init(struct hpsb_host *host, enum hpsb_i /* allocate and write the struct hpsb_iso */ - iso = kmalloc(sizeof(*iso) + buf_packets * sizeof(struct hpsb_iso_packet_info), GFP_KERNEL); + iso = + kmalloc(sizeof(*iso) + + buf_packets * sizeof(struct hpsb_iso_packet_info), + GFP_KERNEL); if (!iso) return NULL; @@ -111,17 +127,21 @@ static struct hpsb_iso* hpsb_iso_common_init(struct hpsb_host *host, enum hpsb_i iso->prebuffer = 0; /* allocate the packet buffer */ - if (dma_region_alloc(&iso->data_buf, iso->buf_size, host->pdev, dma_direction)) + if (dma_region_alloc + (&iso->data_buf, iso->buf_size, host->pdev, dma_direction)) goto err; return iso; -err: + err: hpsb_iso_shutdown(iso); return NULL; } -int hpsb_iso_n_ready(struct hpsb_iso* iso) +/** + * hpsb_iso_n_ready - returns number of packets ready to send or receive + */ +int hpsb_iso_n_ready(struct hpsb_iso *iso) { unsigned long flags; int val; @@ -133,18 +153,22 @@ int hpsb_iso_n_ready(struct hpsb_iso* iso) return val; } - -struct hpsb_iso* hpsb_iso_xmit_init(struct hpsb_host *host, +/** + * hpsb_iso_xmit_init - allocate the buffer and DMA context + */ +struct hpsb_iso *hpsb_iso_xmit_init(struct hpsb_host *host, unsigned int data_buf_size, unsigned int buf_packets, int channel, int speed, int irq_interval, - void (*callback)(struct hpsb_iso*)) + void (*callback) (struct hpsb_iso *)) { struct hpsb_iso *iso = hpsb_iso_common_init(host, HPSB_ISO_XMIT, data_buf_size, buf_packets, - channel, HPSB_ISO_DMA_DEFAULT, irq_interval, callback); + channel, + HPSB_ISO_DMA_DEFAULT, + irq_interval, callback); if (!iso) return NULL; @@ -157,22 +181,28 @@ struct hpsb_iso* hpsb_iso_xmit_init(struct hpsb_host *host, iso->flags |= HPSB_ISO_DRIVER_INIT; return iso; -err: + err: hpsb_iso_shutdown(iso); return NULL; } -struct hpsb_iso* hpsb_iso_recv_init(struct hpsb_host *host, +/** + * hpsb_iso_recv_init - allocate the buffer and DMA context + * + * Note, if channel = -1, multi-channel receive is enabled. + */ +struct hpsb_iso *hpsb_iso_recv_init(struct hpsb_host *host, unsigned int data_buf_size, unsigned int buf_packets, int channel, int dma_mode, int irq_interval, - void (*callback)(struct hpsb_iso*)) + void (*callback) (struct hpsb_iso *)) { struct hpsb_iso *iso = hpsb_iso_common_init(host, HPSB_ISO_RECV, data_buf_size, buf_packets, - channel, dma_mode, irq_interval, callback); + channel, dma_mode, + irq_interval, callback); if (!iso) return NULL; @@ -183,11 +213,16 @@ struct hpsb_iso* hpsb_iso_recv_init(struct hpsb_host *host, iso->flags |= HPSB_ISO_DRIVER_INIT; return iso; -err: + err: hpsb_iso_shutdown(iso); return NULL; } +/** + * hpsb_iso_recv_listen_channel + * + * multi-channel only + */ int hpsb_iso_recv_listen_channel(struct hpsb_iso *iso, unsigned char channel) { if (iso->type != HPSB_ISO_RECV || iso->channel != -1 || channel >= 64) @@ -195,20 +230,37 @@ int hpsb_iso_recv_listen_channel(struct hpsb_iso *iso, unsigned char channel) return iso->host->driver->isoctl(iso, RECV_LISTEN_CHANNEL, channel); } +/** + * hpsb_iso_recv_unlisten_channel + * + * multi-channel only + */ int hpsb_iso_recv_unlisten_channel(struct hpsb_iso *iso, unsigned char channel) { - if (iso->type != HPSB_ISO_RECV || iso->channel != -1 || channel >= 64) - return -EINVAL; - return iso->host->driver->isoctl(iso, RECV_UNLISTEN_CHANNEL, channel); + if (iso->type != HPSB_ISO_RECV || iso->channel != -1 || channel >= 64) + return -EINVAL; + return iso->host->driver->isoctl(iso, RECV_UNLISTEN_CHANNEL, channel); } +/** + * hpsb_iso_recv_set_channel_mask + * + * multi-channel only + */ int hpsb_iso_recv_set_channel_mask(struct hpsb_iso *iso, u64 mask) { if (iso->type != HPSB_ISO_RECV || iso->channel != -1) return -EINVAL; - return iso->host->driver->isoctl(iso, RECV_SET_CHANNEL_MASK, (unsigned long) &mask); + return iso->host->driver->isoctl(iso, RECV_SET_CHANNEL_MASK, + (unsigned long)&mask); } +/** + * hpsb_iso_recv_flush - check for arrival of new packets + * + * check for arrival of new packets immediately (even if irq_interval + * has not yet been reached) + */ int hpsb_iso_recv_flush(struct hpsb_iso *iso) { if (iso->type != HPSB_ISO_RECV) @@ -226,6 +278,9 @@ static int do_iso_xmit_start(struct hpsb_iso *iso, int cycle) return retval; } +/** + * hpsb_iso_xmit_start - start DMA + */ int hpsb_iso_xmit_start(struct hpsb_iso *iso, int cycle, int prebuffer) { if (iso->type != HPSB_ISO_XMIT) @@ -258,6 +313,9 @@ int hpsb_iso_xmit_start(struct hpsb_iso *iso, int cycle, int prebuffer) return 0; } +/** + * hpsb_iso_recv_start - start DMA + */ int hpsb_iso_recv_start(struct hpsb_iso *iso, int cycle, int tag_mask, int sync) { int retval = 0; @@ -283,7 +341,9 @@ int hpsb_iso_recv_start(struct hpsb_iso *iso, int cycle, int tag_mask, int sync) isoctl_args[2] = sync; - retval = iso->host->driver->isoctl(iso, RECV_START, (unsigned long) &isoctl_args[0]); + retval = + iso->host->driver->isoctl(iso, RECV_START, + (unsigned long)&isoctl_args[0]); if (retval) return retval; @@ -292,11 +352,11 @@ int hpsb_iso_recv_start(struct hpsb_iso *iso, int cycle, int tag_mask, int sync) } /* check to make sure the user has not supplied bogus values of offset/len - that would cause the kernel to access memory outside the buffer */ - + * that would cause the kernel to access memory outside the buffer */ static int hpsb_iso_check_offset_len(struct hpsb_iso *iso, unsigned int offset, unsigned short len, - unsigned int *out_offset, unsigned short *out_len) + unsigned int *out_offset, + unsigned short *out_len) { if (offset >= iso->buf_size) return -EFAULT; @@ -316,8 +376,14 @@ static int hpsb_iso_check_offset_len(struct hpsb_iso *iso, return 0; } - -int hpsb_iso_xmit_queue_packet(struct hpsb_iso *iso, u32 offset, u16 len, u8 tag, u8 sy) +/** + * hpsb_iso_xmit_queue_packet - queue a packet for transmission. + * + * @offset is relative to the beginning of the DMA buffer, where the packet's + * data payload should already have been placed. + */ +int hpsb_iso_xmit_queue_packet(struct hpsb_iso *iso, u32 offset, u16 len, + u8 tag, u8 sy) { struct hpsb_iso_packet_info *info; unsigned long flags; @@ -334,7 +400,8 @@ int hpsb_iso_xmit_queue_packet(struct hpsb_iso *iso, u32 offset, u16 len, u8 tag info = &iso->infos[iso->first_packet]; /* check for bogus offset/length */ - if (hpsb_iso_check_offset_len(iso, offset, len, &info->offset, &info->len)) + if (hpsb_iso_check_offset_len + (iso, offset, len, &info->offset, &info->len)) return -EFAULT; info->tag = tag; @@ -342,13 +409,13 @@ int hpsb_iso_xmit_queue_packet(struct hpsb_iso *iso, u32 offset, u16 len, u8 tag spin_lock_irqsave(&iso->lock, flags); - rv = iso->host->driver->isoctl(iso, XMIT_QUEUE, (unsigned long) info); + rv = iso->host->driver->isoctl(iso, XMIT_QUEUE, (unsigned long)info); if (rv) goto out; /* increment cursors */ - iso->first_packet = (iso->first_packet+1) % iso->buf_packets; - iso->xmit_cycle = (iso->xmit_cycle+1) % 8000; + iso->first_packet = (iso->first_packet + 1) % iso->buf_packets; + iso->xmit_cycle = (iso->xmit_cycle + 1) % 8000; iso->n_ready_packets--; if (iso->prebuffer != 0) { @@ -359,19 +426,33 @@ int hpsb_iso_xmit_queue_packet(struct hpsb_iso *iso, u32 offset, u16 len, u8 tag } } -out: + out: spin_unlock_irqrestore(&iso->lock, flags); return rv; } +/** + * hpsb_iso_xmit_sync - wait until all queued packets have been transmitted + */ int hpsb_iso_xmit_sync(struct hpsb_iso *iso) { if (iso->type != HPSB_ISO_XMIT) return -EINVAL; - return wait_event_interruptible(iso->waitq, hpsb_iso_n_ready(iso) == iso->buf_packets); + return wait_event_interruptible(iso->waitq, + hpsb_iso_n_ready(iso) == + iso->buf_packets); } +/** + * hpsb_iso_packet_sent + * + * Available to low-level drivers. + * + * Call after a packet has been transmitted to the bus (interrupt context is + * OK). @cycle is the _exact_ cycle the packet was sent on. @error should be + * non-zero if some sort of error occurred when sending the packet. + */ void hpsb_iso_packet_sent(struct hpsb_iso *iso, int cycle, int error) { unsigned long flags; @@ -395,8 +476,16 @@ void hpsb_iso_packet_sent(struct hpsb_iso *iso, int cycle, int error) spin_unlock_irqrestore(&iso->lock, flags); } +/** + * hpsb_iso_packet_received + * + * Available to low-level drivers. + * + * Call after a packet has been received (interrupt context is OK). + */ void hpsb_iso_packet_received(struct hpsb_iso *iso, u32 offset, u16 len, - u16 total_len, u16 cycle, u8 channel, u8 tag, u8 sy) + u16 total_len, u16 cycle, u8 channel, u8 tag, + u8 sy) { unsigned long flags; spin_lock_irqsave(&iso->lock, flags); @@ -416,13 +505,18 @@ void hpsb_iso_packet_received(struct hpsb_iso *iso, u32 offset, u16 len, info->tag = tag; info->sy = sy; - iso->pkt_dma = (iso->pkt_dma+1) % iso->buf_packets; + iso->pkt_dma = (iso->pkt_dma + 1) % iso->buf_packets; iso->n_ready_packets++; } spin_unlock_irqrestore(&iso->lock, flags); } +/** + * hpsb_iso_recv_release_packets - release packets, reuse buffer + * + * @n_packets have been read out of the buffer, re-use the buffer space + */ int hpsb_iso_recv_release_packets(struct hpsb_iso *iso, unsigned int n_packets) { unsigned long flags; @@ -435,20 +529,21 @@ int hpsb_iso_recv_release_packets(struct hpsb_iso *iso, unsigned int n_packets) spin_lock_irqsave(&iso->lock, flags); for (i = 0; i < n_packets; i++) { rv = iso->host->driver->isoctl(iso, RECV_RELEASE, - (unsigned long) &iso->infos[iso->first_packet]); + (unsigned long)&iso->infos[iso-> + first_packet]); if (rv) break; - iso->first_packet = (iso->first_packet+1) % iso->buf_packets; + iso->first_packet = (iso->first_packet + 1) % iso->buf_packets; iso->n_ready_packets--; /* release memory from packets discarded when queue was full */ - if (iso->n_ready_packets == 0) { /* Release only after all prior packets handled */ + if (iso->n_ready_packets == 0) { /* Release only after all prior packets handled */ if (iso->bytes_discarded != 0) { struct hpsb_iso_packet_info inf; inf.total_len = iso->bytes_discarded; iso->host->driver->isoctl(iso, RECV_RELEASE, - (unsigned long) &inf); + (unsigned long)&inf); iso->bytes_discarded = 0; } } @@ -457,6 +552,13 @@ int hpsb_iso_recv_release_packets(struct hpsb_iso *iso, unsigned int n_packets) return rv; } +/** + * hpsb_iso_wake + * + * Available to low-level drivers. + * + * Call to wake waiting processes after buffer space has opened up. + */ void hpsb_iso_wake(struct hpsb_iso *iso) { wake_up_interruptible(&iso->waitq);