drivers/soundwire/debugfs.c

Source file repositories/reference/linux-study-clean/drivers/soundwire/debugfs.c

File Facts

System
Linux kernel
Corpus path
drivers/soundwire/debugfs.c
Extension
.c
Size
9823 bytes
Lines
386
Domain
Driver Families
Bucket
drivers/soundwire
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 (ret < 0) {
			dev_err(&slave->dev, "firmware %s not found\n", firmware_file);
			goto out;
		}
		if (fw->size < num_bytes) {
			dev_err(&slave->dev,
				"firmware %s: firmware size %zd, desired %zd\n",
				firmware_file, fw->size, num_bytes);
			goto out;
		}
	}

	/* Userspace changed the hardware state behind the kernel's back */
	add_taint(TAINT_USER, LOCKDEP_STILL_OK);

	dev_dbg(&slave->dev, "starting command\n");
	start_t = ktime_get();

	if (cmd == 0) {
		if (cmd_type)
			ret = do_bpt_sequence(slave, true, (u8 *)fw->data);
		else
			ret = sdw_nwrite_no_pm(slave, start_addr, num_bytes, fw->data);
	} else {
		memset(read_buffer, 0, sizeof(read_buffer));

		if (cmd_type)
			ret = do_bpt_sequence(slave, false, read_buffer);
		else
			ret = sdw_nread_no_pm(slave, start_addr, num_bytes, read_buffer);
	}

	finish_t = ktime_get();

	dev_dbg(&slave->dev, "command completed, num_byte %zu status %d, time %lld ms\n",
		num_bytes, ret, div_u64(finish_t - start_t, NSEC_PER_MSEC));

out:
	if (fw)
		release_firmware(fw);

	pm_runtime_mark_last_busy(&slave->dev);
	pm_runtime_put(&slave->dev);

	return ret;
}
DEFINE_DEBUGFS_ATTRIBUTE(cmd_go_fops, NULL,
			 cmd_go, "%llu\n");

#define MAX_LINE_LEN 128

static int read_buffer_show(struct seq_file *s_file, void *data)
{
	char buf[MAX_LINE_LEN];
	int i;

	if (num_bytes == 0 || num_bytes > MAX_CMD_BYTES)
		return -EINVAL;

	for (i = 0; i < num_bytes; i++) {
		scnprintf(buf, MAX_LINE_LEN, "address %#x val 0x%02x\n",
			  start_addr + i, read_buffer[i]);
		seq_printf(s_file, "%s", buf);
	}

	return 0;
}
DEFINE_SHOW_ATTRIBUTE(read_buffer);

void sdw_slave_debugfs_init(struct sdw_slave *slave)
{
	struct dentry *master;
	struct dentry *d;
	char name[32];

	master = slave->bus->debugfs;

	/* create the debugfs slave-name */
	snprintf(name, sizeof(name), "%s", dev_name(&slave->dev));
	d = debugfs_create_dir(name, master);

	debugfs_create_file("registers", 0400, d, slave, &sdw_slave_reg_fops);

	/* interface to send arbitrary commands */
	debugfs_create_file("command", 0200, d, slave, &set_command_fops);
	debugfs_create_file("command_type", 0200, d, slave, &set_command_type_fops);
	debugfs_create_file("start_address", 0200, d, slave, &set_start_address_fops);
	debugfs_create_file("num_bytes", 0200, d, slave, &set_num_bytes_fops);
	debugfs_create_file("go", 0200, d, slave, &cmd_go_fops);

Annotation

Implementation Notes