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

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

File Facts

System
Linux kernel
Corpus path
drivers/net/wireless/st/cw1200/bh.c
Extension
.c
Size
14510 bytes
Lines
609
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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 (WARN_ON(rc < 0)) {
			dev_kfree_skb(skb_rx);
			return rc;
		} else if (rc > 0) {
			*tx = 1;
		}
	}

	/* cw1200_wsm_rx takes care on SKB livetime */
	if (WARN_ON(wsm_handle_rx(priv, wsm_id, wsm, &skb_rx)))
		goto err;

	dev_kfree_skb(skb_rx);

	return 0;

err:
	dev_kfree_skb(skb_rx);
	return -1;
}

static int cw1200_bh_tx_helper(struct cw1200_common *priv,
			       int *pending_tx,
			       int *tx_burst)
{
	size_t tx_len;
	u8 *data;
	int ret;
	struct wsm_hdr *wsm;

	if (priv->device_can_sleep) {
		ret = cw1200_device_wakeup(priv);
		if (WARN_ON(ret < 0)) { /* Error in wakeup */
			*pending_tx = 1;
			return 0;
		} else if (ret) { /* Woke up */
			priv->device_can_sleep = false;
		} else { /* Did not awake */
			*pending_tx = 1;
			return 0;
		}
	}

	wsm_alloc_tx_buffer(priv);
	ret = wsm_get_tx(priv, &data, &tx_len, tx_burst);
	if (ret <= 0) {
		wsm_release_tx_buffer(priv, 1);
		if (WARN_ON(ret < 0))
			return ret; /* Error */
		return 0; /* No work */
	}

	wsm = (struct wsm_hdr *)data;
	BUG_ON(tx_len < sizeof(*wsm));
	BUG_ON(__le16_to_cpu(wsm->len) != tx_len);

	atomic_inc(&priv->bh_tx);

	tx_len = priv->hwbus_ops->align_size(
		priv->hwbus_priv, tx_len);

	/* Check if not exceeding CW1200 capabilities */
	if (WARN_ON_ONCE(tx_len > EFFECTIVE_BUF_SIZE))
		pr_debug("Write aligned len: %zu\n", tx_len);

	wsm->id &= __cpu_to_le16(0xffff ^ WSM_TX_SEQ(WSM_TX_SEQ_MAX));
	wsm->id |= __cpu_to_le16(WSM_TX_SEQ(priv->wsm_tx_seq));

	if (WARN_ON(cw1200_data_write(priv, data, tx_len))) {
		pr_err("tx blew up, len %zu\n", tx_len);
		wsm_release_tx_buffer(priv, 1);
		return -1; /* Error */
	}

	if (priv->wsm_enable_wsm_dumps)
		print_hex_dump_bytes("--> ",
				     DUMP_PREFIX_NONE,
				     data,
				     __le16_to_cpu(wsm->len));

	wsm_txed(priv, data);
	priv->wsm_tx_seq = (priv->wsm_tx_seq + 1) & WSM_TX_SEQ_MAX;

	if (*tx_burst > 1) {
		cw1200_debug_tx_burst(priv);
		return 1; /* Work remains */
	}

	return 0;
}

Annotation

Implementation Notes