drivers/net/wireless/ath/wil6210/fw_inc.c

Source file repositories/reference/linux-study-clean/drivers/net/wireless/ath/wil6210/fw_inc.c

File Facts

System
Linux kernel
Corpus path
drivers/net/wireless/ath/wil6210/fw_inc.c
Extension
.c
Size
21607 bytes
Lines
829
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 (delay++ > 100) {
			wil_err_fw(wil, "gw timeout\n");
			return -EINVAL;
		}
	} while (readl(gwa_ctl) & WIL_FW_GW_CTL_BUSY); /* gw done? */

	return 0;
}

static int fw_handle_gateway_data(struct wil6210_priv *wil, const void *data,
				  size_t size)
{
	const struct wil_fw_record_gateway_data *d = data;
	const struct wil_fw_data_gw *block = d->data;
	void __iomem *gwa_addr;
	void __iomem *gwa_val;
	void __iomem *gwa_cmd;
	void __iomem *gwa_ctl;
	u32 gw_cmd;
	int n, i;

	if (size < sizeof(*d) + sizeof(*block)) {
		wil_err_fw(wil, "gateway record too short: %zu\n", size);
		return -EINVAL;
	}

	if ((size - sizeof(*d)) % sizeof(*block)) {
		wil_err_fw(wil, "gateway record data size"
			   " not aligned on %zu: %zu\n",
			   sizeof(*block), size - sizeof(*d));
		return -EINVAL;
	}
	n = (size - sizeof(*d)) / sizeof(*block);

	gw_cmd = le32_to_cpu(d->command);

	wil_dbg_fw(wil, "gw write record [%3d] blocks, cmd 0x%08x\n",
		   n, gw_cmd);

	if (!wil_fw_addr_check(wil, &gwa_addr, d->gateway_addr_addr, 0,
			       "gateway_addr_addr") ||
	    !wil_fw_addr_check(wil, &gwa_val, d->gateway_value_addr, 0,
			       "gateway_value_addr") ||
	    !wil_fw_addr_check(wil, &gwa_cmd, d->gateway_cmd_addr, 0,
			       "gateway_cmd_addr") ||
	    !wil_fw_addr_check(wil, &gwa_ctl, d->gateway_ctrl_address, 0,
			       "gateway_ctrl_address"))
		return -EINVAL;

	wil_dbg_fw(wil, "gw addresses: addr 0x%08x val 0x%08x"
		   " cmd 0x%08x ctl 0x%08x\n",
		   le32_to_cpu(d->gateway_addr_addr),
		   le32_to_cpu(d->gateway_value_addr),
		   le32_to_cpu(d->gateway_cmd_addr),
		   le32_to_cpu(d->gateway_ctrl_address));

	for (i = 0; i < n; i++) {
		int rc;
		u32 a = le32_to_cpu(block[i].addr);
		u32 v = le32_to_cpu(block[i].value);

		wil_dbg_fw(wil, "  gw write[%3d] [0x%08x] <== 0x%08x\n",
			   i, a, v);

		writel(v, gwa_val);
		rc = gw_write(wil, gwa_addr, gwa_cmd, gwa_ctl, gw_cmd, a);
		if (rc)
			return rc;
	}

	return 0;
}

static int fw_handle_gateway_data4(struct wil6210_priv *wil, const void *data,
				   size_t size)
{
	const struct wil_fw_record_gateway_data4 *d = data;
	const struct wil_fw_data_gw4 *block = d->data;
	void __iomem *gwa_addr;
	void __iomem *gwa_val[ARRAY_SIZE(block->value)];
	void __iomem *gwa_cmd;
	void __iomem *gwa_ctl;
	u32 gw_cmd;
	int n, i, k;

	if (size < sizeof(*d) + sizeof(*block)) {
		wil_err_fw(wil, "gateway4 record too short: %zu\n", size);
		return -EINVAL;
	}

Annotation

Implementation Notes