drivers/net/ethernet/meta/fbnic/fbnic_fw_log.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/meta/fbnic/fbnic_fw_log.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/meta/fbnic/fbnic_fw_log.c
Extension
.c
Size
2759 bytes
Lines
121
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

// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) Meta Platforms, Inc. and affiliates. */

#include <linux/spinlock.h>
#include <linux/vmalloc.h>

#include "fbnic.h"
#include "fbnic_fw.h"
#include "fbnic_fw_log.h"

void fbnic_fw_log_enable(struct fbnic_dev *fbd, bool send_hist)
{
	int err;

	if (!fbnic_fw_log_ready(fbd))
		return;

	if (fbd->fw_cap.running.mgmt.version < MIN_FW_VER_CODE_HIST)
		send_hist = false;

	err = fbnic_fw_xmit_send_logs(fbd, true, send_hist);
	if (err && err != -EOPNOTSUPP)
		dev_warn(fbd->dev, "Unable to enable firmware logs: %d\n", err);
}

void fbnic_fw_log_disable(struct fbnic_dev *fbd)
{
	int err;

	err = fbnic_fw_xmit_send_logs(fbd, false, false);
	if (err && err != -EOPNOTSUPP)
		dev_warn(fbd->dev, "Unable to disable firmware logs: %d\n",
			 err);
}

int fbnic_fw_log_init(struct fbnic_dev *fbd)
{
	struct fbnic_fw_log *log = &fbd->fw_log;
	void *data;

	if (WARN_ON_ONCE(fbnic_fw_log_ready(fbd)))
		return -EEXIST;

	data = vmalloc(FBNIC_FW_LOG_SIZE);
	if (!data)
		return -ENOMEM;

	spin_lock_init(&fbd->fw_log.lock);
	INIT_LIST_HEAD(&log->entries);
	log->size = FBNIC_FW_LOG_SIZE;
	log->data_start = data;
	log->data_end = data + FBNIC_FW_LOG_SIZE;

	return 0;
}

void fbnic_fw_log_free(struct fbnic_dev *fbd)
{
	struct fbnic_fw_log *log = &fbd->fw_log;

	if (!fbnic_fw_log_ready(fbd))
		return;

	INIT_LIST_HEAD(&log->entries);
	log->size = 0;
	vfree(log->data_start);
	log->data_start = NULL;
	log->data_end = NULL;
}

int fbnic_fw_log_write(struct fbnic_dev *fbd, u64 index, u32 timestamp,
		       const char *msg)
{
	struct fbnic_fw_log_entry *entry, *head, *tail, *next;
	struct fbnic_fw_log *log = &fbd->fw_log;
	size_t msg_len = strlen(msg) + 1;
	unsigned long flags;
	void *entry_end;

	if (!fbnic_fw_log_ready(fbd)) {
		dev_err(fbd->dev, "Firmware sent log entry without being requested!\n");
		return -ENOSPC;
	}

	spin_lock_irqsave(&log->lock, flags);

	if (list_empty(&log->entries)) {
		entry = log->data_start;
	} else {
		head = list_first_entry(&log->entries, typeof(*head), list);

Annotation

Implementation Notes