drivers/net/wireless/silabs/wfx/bh.c
Source file repositories/reference/linux-study-clean/drivers/net/wireless/silabs/wfx/bh.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/net/wireless/silabs/wfx/bh.c- Extension
.c- Size
- 8840 bytes
- Lines
- 325
- 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.
- 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.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/gpio/consumer.hnet/mac80211.hbh.hwfx.hhwio.htraces.hhif_rx.hhif_api_cmd.h
Detected Declarations
function halffunction device_releasefunction rx_helperfunction bh_work_rxfunction tx_helperfunction bh_work_txfunction ack_sdio_datafunction bh_workfunction wfx_bh_request_rxfunction wfx_bh_request_txfunction wfx_bh_poll_irqfunction wfx_bh_registerfunction wfx_bh_unregister
Annotated Snippet
if (wait_for_completion_timeout(&wdev->hif.ctrl_ready, msecs_to_jiffies(2))) {
complete(&wdev->hif.ctrl_ready);
return;
} else if (max_retry-- > 0) {
/* Older firmwares have a race in sleep/wake-up process. Redo the process
* is sufficient to unfreeze the chip.
*/
dev_err(wdev->dev, "timeout while wake up chip\n");
gpiod_set_value_cansleep(wdev->pdata.gpio_wakeup, 0);
usleep_range(2000, 2500);
} else {
dev_err(wdev->dev, "max wake-up retries reached\n");
return;
}
}
}
static void device_release(struct wfx_dev *wdev)
{
if (!wdev->pdata.gpio_wakeup)
return;
gpiod_set_value_cansleep(wdev->pdata.gpio_wakeup, 0);
}
static int rx_helper(struct wfx_dev *wdev, size_t read_len, int *is_cnf)
{
struct sk_buff *skb;
struct wfx_hif_msg *hif;
size_t alloc_len;
size_t computed_len;
int release_count;
int piggyback = 0;
WARN(read_len > round_down(0xFFF, 2) * sizeof(u16), "request exceed the chip capability");
/* Add 2 to take into account piggyback size */
alloc_len = wdev->hwbus_ops->align_size(wdev->hwbus_priv, read_len + 2);
skb = dev_alloc_skb(alloc_len);
if (!skb)
return -ENOMEM;
if (wfx_data_read(wdev, skb->data, alloc_len))
goto err;
piggyback = le16_to_cpup((__le16 *)(skb->data + alloc_len - 2));
_trace_piggyback(piggyback, false);
hif = (struct wfx_hif_msg *)skb->data;
WARN(hif->encrypted & 0x3, "encryption is unsupported");
if (WARN(read_len < sizeof(struct wfx_hif_msg), "corrupted read"))
goto err;
computed_len = le16_to_cpu(hif->len);
computed_len = round_up(computed_len, 2);
if (computed_len != read_len) {
dev_err(wdev->dev, "inconsistent message length: %zu != %zu\n",
computed_len, read_len);
print_hex_dump(KERN_INFO, "hif: ", DUMP_PREFIX_OFFSET, 16, 1,
hif, read_len, true);
goto err;
}
if (!(hif->id & HIF_ID_IS_INDICATION)) {
(*is_cnf)++;
if (hif->id == HIF_CNF_ID_MULTI_TRANSMIT)
release_count =
((struct wfx_hif_cnf_multi_transmit *)hif->body)->num_tx_confs;
else
release_count = 1;
WARN(wdev->hif.tx_buffers_used < release_count, "corrupted buffer counter");
wdev->hif.tx_buffers_used -= release_count;
}
_trace_hif_recv(hif, wdev->hif.tx_buffers_used);
if (hif->id != HIF_IND_ID_EXCEPTION && hif->id != HIF_IND_ID_ERROR) {
if (hif->seqnum != wdev->hif.rx_seqnum)
dev_warn(wdev->dev, "wrong message sequence: %d != %d\n",
hif->seqnum, wdev->hif.rx_seqnum);
wdev->hif.rx_seqnum = (hif->seqnum + 1) % (HIF_COUNTER_MAX + 1);
}
skb_put(skb, le16_to_cpu(hif->len));
/* wfx_handle_rx takes care on SKB livetime */
wfx_handle_rx(wdev, skb);
if (!wdev->hif.tx_buffers_used)
wake_up(&wdev->hif.tx_buffers_empty);
return piggyback;
err:
Annotation
- Immediate include surface: `linux/gpio/consumer.h`, `net/mac80211.h`, `bh.h`, `wfx.h`, `hwio.h`, `traces.h`, `hif_rx.h`, `hif_api_cmd.h`.
- Detected declarations: `function half`, `function device_release`, `function rx_helper`, `function bh_work_rx`, `function tx_helper`, `function bh_work_tx`, `function ack_sdio_data`, `function bh_work`, `function wfx_bh_request_rx`, `function wfx_bh_request_tx`.
- Atlas domain: Driver Families / drivers/net.
- Implementation status: source implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.