drivers/net/wireless/st/cw1200/queue.c

Source file repositories/reference/linux-study-clean/drivers/net/wireless/st/cw1200/queue.c

File Facts

System
Linux kernel
Corpus path
drivers/net/wireless/st/cw1200/queue.c
Extension
.c
Size
13944 bytes
Lines
550
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (time_is_after_jiffies(iter->queue_timestamp + queue->ttl)) {
			item = iter;
			break;
		}
		--queue->num_queued;
		--queue->link_map_cache[iter->txpriv.link_id];
		spin_lock_bh(&stats->lock);
		--stats->num_queued;
		if (!--stats->link_map_cache[iter->txpriv.link_id])
			wakeup_stats = true;
		spin_unlock_bh(&stats->lock);
		cw1200_debug_tx_ttl(stats->priv);
		cw1200_queue_register_post_gc(head, iter);
		iter->skb = NULL;
		list_move_tail(&iter->head, &queue->free_pool);
	}

	if (wakeup_stats)
		wake_up(&stats->wait_link_id_empty);

	if (queue->overfull) {
		if (queue->num_queued <= (queue->capacity >> 1)) {
			queue->overfull = false;
			if (unlock)
				__cw1200_queue_unlock(queue);
		} else if (item) {
			unsigned long tmo = item->queue_timestamp + queue->ttl;
			mod_timer(&queue->gc, tmo);
			cw1200_pm_stay_awake(&stats->priv->pm_state,
					     tmo - jiffies);
		}
	}
}

static void cw1200_queue_gc(struct timer_list *t)
{
	LIST_HEAD(list);
	struct cw1200_queue *queue =
		timer_container_of(queue, t, gc);

	spin_lock_bh(&queue->lock);
	__cw1200_queue_gc(queue, &list, true);
	spin_unlock_bh(&queue->lock);
	cw1200_queue_post_gc(queue->stats, &list);
}

int cw1200_queue_stats_init(struct cw1200_queue_stats *stats,
			    size_t map_capacity,
			    cw1200_queue_skb_dtor_t skb_dtor,
			    struct cw1200_common *priv)
{
	memset(stats, 0, sizeof(*stats));
	stats->map_capacity = map_capacity;
	stats->skb_dtor = skb_dtor;
	stats->priv = priv;
	spin_lock_init(&stats->lock);
	init_waitqueue_head(&stats->wait_link_id_empty);

	stats->link_map_cache = kzalloc_objs(int, map_capacity);
	if (!stats->link_map_cache)
		return -ENOMEM;

	return 0;
}

int cw1200_queue_init(struct cw1200_queue *queue,
		      struct cw1200_queue_stats *stats,
		      u8 queue_id,
		      size_t capacity,
		      unsigned long ttl)
{
	size_t i;

	memset(queue, 0, sizeof(*queue));
	queue->stats = stats;
	queue->capacity = capacity;
	queue->queue_id = queue_id;
	queue->ttl = ttl;
	INIT_LIST_HEAD(&queue->queue);
	INIT_LIST_HEAD(&queue->pending);
	INIT_LIST_HEAD(&queue->free_pool);
	spin_lock_init(&queue->lock);
	timer_setup(&queue->gc, cw1200_queue_gc, 0);

	queue->pool = kzalloc_objs(struct cw1200_queue_item, capacity);
	if (!queue->pool)
		return -ENOMEM;

	queue->link_map_cache = kzalloc_objs(int, stats->map_capacity);
	if (!queue->link_map_cache) {

Annotation

Implementation Notes