drivers/net/wireless/ath/ath6kl/debug.c

Source file repositories/reference/linux-study-clean/drivers/net/wireless/ath/ath6kl/debug.c

File Facts

System
Linux kernel
Corpus path
drivers/net/wireless/ath/ath6kl/debug.c
Extension
.c
Size
46460 bytes
Lines
1873
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern 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

static const struct file_operations fops_war_stats = {
	.read = read_file_war_stats,
	.open = simple_open,
	.owner = THIS_MODULE,
	.llseek = default_llseek,
};

void ath6kl_debug_fwlog_event(struct ath6kl *ar, const void *buf, size_t len)
{
	struct ath6kl_fwlog_slot *slot;
	struct sk_buff *skb;
	size_t slot_len;

	if (WARN_ON(len > ATH6KL_FWLOG_PAYLOAD_SIZE))
		return;

	slot_len = sizeof(*slot) + ATH6KL_FWLOG_PAYLOAD_SIZE;

	skb = alloc_skb(slot_len, GFP_KERNEL);
	if (!skb)
		return;

	slot = skb_put(skb, slot_len);
	slot->timestamp = cpu_to_le32(jiffies);
	slot->length = cpu_to_le32(len);
	memcpy(slot->payload, buf, len);

	/* Need to pad each record to fixed length ATH6KL_FWLOG_PAYLOAD_SIZE */
	memset(slot->payload + len, 0, ATH6KL_FWLOG_PAYLOAD_SIZE - len);

	spin_lock(&ar->debug.fwlog_queue.lock);

	__skb_queue_tail(&ar->debug.fwlog_queue, skb);
	complete(&ar->debug.fwlog_completion);

	/* drop oldest entries */
	while (skb_queue_len(&ar->debug.fwlog_queue) >
	       ATH6KL_FWLOG_MAX_ENTRIES) {
		skb = __skb_dequeue(&ar->debug.fwlog_queue);
		kfree_skb(skb);
	}

	spin_unlock(&ar->debug.fwlog_queue.lock);

	return;
}

static int ath6kl_fwlog_open(struct inode *inode, struct file *file)
{
	struct ath6kl *ar = inode->i_private;

	if (ar->debug.fwlog_open)
		return -EBUSY;

	ar->debug.fwlog_open = true;

	file->private_data = inode->i_private;
	return 0;
}

static int ath6kl_fwlog_release(struct inode *inode, struct file *file)
{
	struct ath6kl *ar = inode->i_private;

	ar->debug.fwlog_open = false;

	return 0;
}

static ssize_t ath6kl_fwlog_read(struct file *file, char __user *user_buf,
				 size_t count, loff_t *ppos)
{
	struct ath6kl *ar = file->private_data;
	struct sk_buff *skb;
	ssize_t ret_cnt;
	size_t len = 0;
	char *buf;

	buf = vmalloc(count);
	if (!buf)
		return -ENOMEM;

	/* read undelivered logs from firmware */
	ath6kl_read_fwlogs(ar);

	spin_lock(&ar->debug.fwlog_queue.lock);

	while ((skb = __skb_dequeue(&ar->debug.fwlog_queue))) {
		if (skb->len > count - len) {
			/* not enough space, put skb back and leave */

Annotation

Implementation Notes