123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304 |
- #include "xframe_queue.h"
- #include "xbus-core.h"
- #include "dahdi_debug.h"
- extern int debug;
- static xframe_t *transport_alloc_xframe(xbus_t *xbus, gfp_t gfp_flags);
- static void transport_free_xframe(xbus_t *xbus, xframe_t *xframe);
- void xframe_queue_init(struct xframe_queue *q, unsigned int steady_state_count, unsigned int max_count, const char *name, void *priv)
- {
- memset(q, 0, sizeof(*q));
- spin_lock_init(&q->lock);
- INIT_LIST_HEAD(&q->head);
- q->max_count = XFRAME_QUEUE_MARGIN + max_count;
- q->steady_state_count = XFRAME_QUEUE_MARGIN + steady_state_count;
- q->name = name;
- q->priv = priv;
- }
- void xframe_queue_clearstats(struct xframe_queue *q)
- {
- q->worst_count = 0;
- //q->overflows = 0; /* Never clear overflows */
- q->worst_lag_usec = 0L;
- }
- static void __xframe_dump_queue(struct xframe_queue *q)
- {
- xframe_t *xframe;
- int i = 0;
- char prefix[30];
- struct timeval now;
- do_gettimeofday(&now);
- printk(KERN_DEBUG "%s: dump queue '%s' (first packet in each frame)\n",
- THIS_MODULE->name,
- q->name);
- list_for_each_entry_reverse(xframe, &q->head, frame_list) {
- xpacket_t *pack = (xpacket_t *)&xframe->packets[0];
- long usec = usec_diff(&now, &xframe->tv_queued);
- snprintf(prefix, ARRAY_SIZE(prefix), " %3d> %5ld.%03ld msec",
- i++, usec / 1000, usec % 1000);
- dump_packet(prefix, pack, 1);
- }
- }
- static bool __xframe_enqueue(struct xframe_queue *q, xframe_t *xframe)
- {
- int ret = 1;
- if(unlikely(q->disabled)) {
- ret = 0;
- goto out;
- }
- if(q->count >= q->max_count) {
- q->overflows++;
- NOTICE("Overflow of %-15s: counts %3d, %3d, %3d worst %3d, overflows %3d worst_lag %02ld.%ld ms\n",
- q->name,
- q->steady_state_count,
- q->count,
- q->max_count,
- q->worst_count,
- q->overflows,
- q->worst_lag_usec / 1000,
- q->worst_lag_usec % 1000);
- __xframe_dump_queue(q);
- ret = 0;
- goto out;
- }
- if(++q->count > q->worst_count)
- q->worst_count = q->count;
- list_add_tail(&xframe->frame_list, &q->head);
- do_gettimeofday(&xframe->tv_queued);
- out:
- return ret;
- }
- bool xframe_enqueue(struct xframe_queue *q, xframe_t *xframe)
- {
- unsigned long flags;
- int ret;
- spin_lock_irqsave(&q->lock, flags);
- ret = __xframe_enqueue(q, xframe);
- spin_unlock_irqrestore(&q->lock, flags);
- return ret;
- }
- static xframe_t *__xframe_dequeue(struct xframe_queue *q)
- {
- xframe_t *frm = NULL;
- struct list_head *h;
- struct timeval now;
- unsigned long usec_lag;
- if(list_empty(&q->head))
- goto out;
- h = q->head.next;
- list_del_init(h);
- --q->count;
- frm = list_entry(h, xframe_t, frame_list);
- do_gettimeofday(&now);
- usec_lag =
- (now.tv_sec - frm->tv_queued.tv_sec)*1000*1000 +
- (now.tv_usec - frm->tv_queued.tv_usec);
- if(q->worst_lag_usec < usec_lag)
- q->worst_lag_usec = usec_lag;
- out:
- return frm;
- }
- xframe_t *xframe_dequeue(struct xframe_queue *q)
- {
- unsigned long flags;
- xframe_t *frm;
- spin_lock_irqsave(&q->lock, flags);
- frm = __xframe_dequeue(q);
- spin_unlock_irqrestore(&q->lock, flags);
- return frm;
- }
- void xframe_queue_disable(struct xframe_queue *q, bool disabled)
- {
- q->disabled = disabled;
- }
- void xframe_queue_clear(struct xframe_queue *q)
- {
- xframe_t *xframe;
- xbus_t *xbus = q->priv;
- int i = 0;
- xframe_queue_disable(q, 1);
- while((xframe = xframe_dequeue(q)) != NULL) {
- transport_free_xframe(xbus, xframe);
- i++;
- }
- XBUS_DBG(DEVICES, xbus, "%s: finished queue clear (%d items)\n", q->name, i);
- }
- uint xframe_queue_count(struct xframe_queue *q)
- {
- return q->count;
- }
- /*------------------------- Frame Alloc/Dealloc --------------------*/
- static xframe_t *transport_alloc_xframe(xbus_t *xbus, gfp_t gfp_flags)
- {
- struct xbus_ops *ops;
- xframe_t *xframe;
- unsigned long flags;
- BUG_ON(!xbus);
- ops = transportops_get(xbus);
- if(unlikely(!ops)) {
- XBUS_ERR(xbus, "Missing transport\n");
- return NULL;
- }
- spin_lock_irqsave(&xbus->transport.lock, flags);
- //XBUS_INFO(xbus, "%s (transport_refcount=%d)\n", __FUNCTION__, atomic_read(&xbus->transport.transport_refcount));
- xframe = ops->alloc_xframe(xbus, gfp_flags);
- if(!xframe) {
- static int rate_limit;
- if((rate_limit++ % 3001) == 0)
- XBUS_ERR(xbus,
- "Failed xframe allocation from transport (%d)\n",
- rate_limit);
- transportops_put(xbus);
- /* fall through */
- }
- spin_unlock_irqrestore(&xbus->transport.lock, flags);
- return xframe;
- }
- static void transport_free_xframe(xbus_t *xbus, xframe_t *xframe)
- {
- struct xbus_ops *ops;
- unsigned long flags;
- BUG_ON(!xbus);
- ops = xbus->transport.ops;
- BUG_ON(!ops);
- spin_lock_irqsave(&xbus->transport.lock, flags);
- //XBUS_INFO(xbus, "%s (transport_refcount=%d)\n", __FUNCTION__, atomic_read(&xbus->transport.transport_refcount));
- ops->free_xframe(xbus, xframe);
- transportops_put(xbus);
- spin_unlock_irqrestore(&xbus->transport.lock, flags);
- }
- static bool xframe_queue_adjust(struct xframe_queue *q)
- {
- xbus_t *xbus;
- xframe_t *xframe;
- int delta;
- unsigned long flags;
- int ret = 0;
- BUG_ON(!q);
- xbus = q->priv;
- BUG_ON(!xbus);
- spin_lock_irqsave(&q->lock, flags);
- delta = q->count - q->steady_state_count;
- if(delta < -XFRAME_QUEUE_MARGIN) {
- /* Increase pool by one frame */
- //XBUS_INFO(xbus, "%s(%d): Allocate one\n", q->name, delta);
- xframe = transport_alloc_xframe(xbus, GFP_ATOMIC);
- if(!xframe) {
- static int rate_limit;
- if((rate_limit++ % 3001) == 0)
- XBUS_ERR(xbus, "%s: failed frame allocation\n", q->name);
- goto out;
- }
- if(!__xframe_enqueue(q, xframe)) {
- static int rate_limit;
- if((rate_limit++ % 3001) == 0)
- XBUS_ERR(xbus, "%s: failed enqueueing frame\n", q->name);
- transport_free_xframe(xbus, xframe);
- goto out;
- }
- } else if(delta > XFRAME_QUEUE_MARGIN) {
- /* Decrease pool by one frame */
- //XBUS_INFO(xbus, "%s(%d): Free one\n", q->name, delta);
- xframe = __xframe_dequeue(q);
- if(!xframe) {
- static int rate_limit;
- if((rate_limit++ % 3001) == 0)
- XBUS_ERR(xbus, "%s: failed dequeueing frame\n", q->name);
- goto out;
- }
- transport_free_xframe(xbus, xframe);
- }
- ret = 1;
- out:
- spin_unlock_irqrestore(&q->lock, flags);
- return ret;
- }
- xframe_t *get_xframe(struct xframe_queue *q)
- {
- xframe_t *xframe;
- xbus_t *xbus;
- BUG_ON(!q);
- xbus = (xbus_t *)q->priv;
- BUG_ON(!xbus);
- xframe_queue_adjust(q);
- xframe = xframe_dequeue(q);
- if(!xframe) {
- static int rate_limit;
- if((rate_limit++ % 3001) == 0)
- XBUS_ERR(xbus, "%s STILL EMPTY (%d)\n", q->name, rate_limit);
- return NULL;
- }
- BUG_ON(xframe->xframe_magic != XFRAME_MAGIC);
- atomic_set(&xframe->frame_len, 0);
- xframe->first_free = xframe->packets;
- do_gettimeofday(&xframe->tv_created);
- /*
- * If later parts bother to correctly initialize their
- * headers, there is no need to memset() the whole data.
- *
- * ticket:403
- *
- * memset(xframe->packets, 0, xframe->frame_maxlen);
- */
- //XBUS_INFO(xbus, "%s\n", __FUNCTION__);
- return xframe;
- }
- void put_xframe(struct xframe_queue *q, xframe_t *xframe)
- {
- xbus_t *xbus;
- BUG_ON(!q);
- xbus = (xbus_t *)q->priv;
- BUG_ON(!xbus);
- //XBUS_INFO(xbus, "%s\n", __FUNCTION__);
- BUG_ON(!TRANSPORT_EXIST(xbus));
- if(unlikely(!xframe_enqueue(q, xframe))) {
- XBUS_ERR(xbus, "Failed returning xframe to %s\n", q->name);
- transport_free_xframe(xbus, xframe);
- return;
- }
- xframe_queue_adjust(q);
- }
- EXPORT_SYMBOL(xframe_queue_init);
- EXPORT_SYMBOL(xframe_queue_clearstats);
- EXPORT_SYMBOL(xframe_enqueue);
- EXPORT_SYMBOL(xframe_dequeue);
- EXPORT_SYMBOL(xframe_queue_disable);
- EXPORT_SYMBOL(xframe_queue_clear);
- EXPORT_SYMBOL(xframe_queue_count);
- EXPORT_SYMBOL(get_xframe);
- EXPORT_SYMBOL(put_xframe);
|