[Linux1394-cvslog] rev 662 - trunk
Brought to you by:
aeb,
bencollins
From: SVN U. <dm...@li...> - 2002-11-07 01:51:46
|
Author: dmaas Date: 2002-11-06 20:51:34 -0500 (Wed, 06 Nov 2002) New Revision: 662 Modified: trunk/iso.c trunk/iso.h trunk/ohci1394.c trunk/raw1394.c trunk/raw1394.h Log: rawiso update - use a callback in struct hpsb_iso instead of a wait_queue - notify raw1394 users of isochronous activity via a queued read() event, instead of poll() (This is less of a hack than the poll() method and restores the old poll() behavior) Modified: trunk/iso.h ============================================================================== --- trunk/iso.h (original) +++ trunk/iso.h 2002-11-06 20:51:35.000000000 -0500 @@ -46,8 +46,8 @@ struct hpsb_host *host; void *hostdata; - /* pointer to a wait queue that will receive wakeups */ - wait_queue_head_t *waitq; + /* function to be called (from interrupt context) when the iso status changes */ + void (*callback)(struct hpsb_iso*); int speed; /* SPEED_100, 200, or 400 */ int channel; @@ -108,19 +108,19 @@ /* allocate the buffer and DMA context */ struct hpsb_iso* hpsb_iso_xmit_init(struct hpsb_host *host, - unsigned int buf_packets, - unsigned int max_packet_size, - int channel, - int speed, - int irq_interval, - wait_queue_head_t *waitq); + unsigned int buf_packets, + unsigned int max_packet_size, + int channel, + int speed, + int irq_interval, + void (*callback)(struct hpsb_iso*)); struct hpsb_iso* hpsb_iso_recv_init(struct hpsb_host *host, - unsigned int buf_packets, - unsigned int max_packet_size, - int channel, - int irq_interval, - wait_queue_head_t *waitq); + unsigned int buf_packets, + unsigned int max_packet_size, + int channel, + int irq_interval, + void (*callback)(struct hpsb_iso*)); /* start/stop DMA */ int hpsb_iso_xmit_start(struct hpsb_iso *iso, int start_on_cycle, int prebuffer); Modified: trunk/ohci1394.c ============================================================================== --- trunk/ohci1394.c (original) +++ trunk/ohci1394.c 2002-11-06 20:51:35.000000000 -0500 @@ -1311,8 +1311,8 @@ } out: - if(wake && iso->waitq) { - wake_up_interruptible(iso->waitq); + if(wake && iso->callback) { + iso->callback(iso); } } @@ -1479,8 +1479,8 @@ } out: - if(wake && iso->waitq) { - wake_up_interruptible(iso->waitq); + if(wake && iso->callback) { + iso->callback(iso); } } Modified: trunk/raw1394.c ============================================================================== --- trunk/raw1394.c (original) +++ trunk/raw1394.c 2002-11-06 20:51:35.000000000 -0500 @@ -133,18 +133,25 @@ kfree(req); } +/* fi->reqlists_lock must be taken */ +static void __queue_complete_req(struct pending_request *req) +{ + struct file_info *fi = req->file_info; + list_del(&req->list); + list_add_tail(&req->list, &fi->req_complete); + + up(&fi->complete_sem); + wake_up_interruptible(&fi->poll_wait_complete); +} + static void queue_complete_req(struct pending_request *req) { unsigned long flags; struct file_info *fi = req->file_info; spin_lock_irqsave(&fi->reqlists_lock, flags); - list_del(&req->list); - list_add_tail(&req->list, &fi->req_complete); + __queue_complete_req(req); spin_unlock_irqrestore(&fi->reqlists_lock, flags); - - up(&fi->complete_sem); - wake_up_interruptible(&fi->poll_wait_complete); } static void queue_complete_cb(struct pending_request *req) @@ -1995,6 +2002,62 @@ /* rawiso operations */ +/* check if any RAW1394_REQ_RAWISO_ACTIVITY event is already in the + * completion queue (reqlists_lock must be taken) */ +static inline int __rawiso_event_in_queue(struct file_info *fi) +{ + struct list_head *lh; + struct pending_request *req; + + list_for_each(lh, &fi->req_complete) { + req = list_entry(lh, struct pending_request, list); + if(req->req.type == RAW1394_REQ_RAWISO_ACTIVITY) { + return 1; + } + } + + return 0; +} + +static void rawiso_activity_cb(struct hpsb_iso *iso) +{ + unsigned long host_flags; + struct list_head *lh; + struct host_info *hi; + + spin_lock_irqsave(&host_info_lock, host_flags); + hi = find_host_info(iso->host); + + if (hi != NULL) { + list_for_each(lh, &hi->file_info_list) { + unsigned long reqlist_flags; + struct file_info *fi = list_entry(lh, struct file_info, list); + + spin_lock_irqsave(&fi->reqlists_lock, reqlist_flags); + + /* only one ISO activity event may be in the queue */ + if(!__rawiso_event_in_queue(fi)) { + struct pending_request *req = __alloc_pending_request(SLAB_ATOMIC); + + if(req) { + req->file_info = fi; + req->req.type = RAW1394_REQ_RAWISO_ACTIVITY; + req->req.generation = get_hpsb_generation(iso->host); + __queue_complete_req(req); + } else { + /* on allocation failure, signal an overflow */ + if(fi->iso_handle) { + atomic_inc(&fi->iso_handle->overflows); + } + } + } + spin_unlock_irqrestore(&fi->reqlists_lock, reqlist_flags); + } + } + + spin_unlock_irqrestore(&host_info_lock, host_flags); +} + /* helper function - gather all the kernel iso status bits for returning to user-space */ static void raw1394_iso_fill_status(struct hpsb_iso *iso, struct raw1394_iso_status *stat) { @@ -2024,7 +2087,7 @@ stat.config.channel, stat.config.speed, stat.config.irq_interval, - &fi->poll_wait_complete); + rawiso_activity_cb); if(!fi->iso_handle) return -ENOMEM; @@ -2033,6 +2096,10 @@ raw1394_iso_fill_status(fi->iso_handle, &stat); if(copy_to_user(uaddr, &stat, sizeof(stat))) return -EFAULT; + + /* queue an event to get things started */ + rawiso_activity_cb(fi->iso_handle); + return 0; } @@ -2048,7 +2115,7 @@ stat.config.max_packet_size, stat.config.channel, stat.config.irq_interval, - &fi->poll_wait_complete); + rawiso_activity_cb); if(!fi->iso_handle) return -ENOMEM; @@ -2161,15 +2228,6 @@ return -EINVAL; } -/* Queued read() events and isochronous readiness are two completely - * independent sources of input. We must provide unique POLL values - * for each, so that libraw can distinguish between them. Older versions - * of libraw expect POLLIN to mean only that a read() event is pending. - * So, we have to use something other than POLLIN. The best choice seems - * to be POLLPRI ("urgent out-of-band input") - which also allows us - * to support select(), since POLLPRI signals "exception" activity - */ - static unsigned int raw1394_poll(struct file *file, poll_table *pt) { struct file_info *fi = file->private_data; @@ -2177,18 +2235,11 @@ poll_wait(file, &fi->poll_wait_complete, pt); - /* check for pending read() events */ spin_lock_irq(&fi->reqlists_lock); if (!list_empty(&fi->req_complete)) { mask |= POLLIN | POLLRDNORM; } spin_unlock_irq(&fi->reqlists_lock); - - /* check for isochronous activity */ - if(fi->iso_state != RAW1394_ISO_INACTIVE) { - if(hpsb_iso_n_ready(fi->iso_handle) > 0) - mask |= POLLPRI; - } return mask; } Modified: trunk/raw1394.h ============================================================================== --- trunk/raw1394.h (original) +++ trunk/raw1394.h 2002-11-06 20:51:35.000000000 -0500 @@ -36,10 +36,11 @@ #define RAW1394_REQ_PHYPACKET 500 /* kernel to user */ -#define RAW1394_REQ_BUS_RESET 10000 -#define RAW1394_REQ_ISO_RECEIVE 10001 -#define RAW1394_REQ_FCP_REQUEST 10002 -#define RAW1394_REQ_ARM 10003 +#define RAW1394_REQ_BUS_RESET 10000 +#define RAW1394_REQ_ISO_RECEIVE 10001 +#define RAW1394_REQ_FCP_REQUEST 10002 +#define RAW1394_REQ_ARM 10003 +#define RAW1394_REQ_RAWISO_ACTIVITY 10004 /* error codes */ #define RAW1394_ERROR_NONE 0 Modified: trunk/iso.c ============================================================================== --- trunk/iso.c (original) +++ trunk/iso.c 2002-11-06 20:51:35.000000000 -0500 @@ -33,11 +33,11 @@ } static struct hpsb_iso* hpsb_iso_common_init(struct hpsb_host *host, enum hpsb_iso_type type, - unsigned int buf_packets, - unsigned int max_packet_size, - int channel, - int irq_interval, - wait_queue_head_t *waitq) + unsigned int buf_packets, + unsigned int max_packet_size, + int channel, + int irq_interval, + void (*callback)(struct hpsb_iso*)) { struct hpsb_iso *iso; unsigned int packet_plus_info; @@ -86,7 +86,7 @@ iso->type = type; iso->host = host; iso->hostdata = NULL; - iso->waitq = waitq; + iso->callback = callback; iso->channel = channel; iso->irq_interval = irq_interval; dma_region_init(&iso->buf); @@ -133,11 +133,11 @@ int channel, int speed, int irq_interval, - wait_queue_head_t *waitq) + void (*callback)(struct hpsb_iso*)) { struct hpsb_iso *iso = hpsb_iso_common_init(host, HPSB_ISO_XMIT, buf_packets, max_packet_size, - channel, irq_interval, waitq); + channel, irq_interval, callback); if(!iso) return NULL; @@ -160,11 +160,11 @@ unsigned int max_packet_size, int channel, int irq_interval, - wait_queue_head_t *waitq) + void (*callback)(struct hpsb_iso*)) { struct hpsb_iso *iso = hpsb_iso_common_init(host, HPSB_ISO_RECV, buf_packets, max_packet_size, - channel, irq_interval, waitq); + channel, irq_interval, callback); if(!iso) return NULL; |