Files
bes2600-dkms/bes2600/sbus.h
T
test0r 1e9eb4581f bes2600: drop sdio_rx_work relay, IRQ→bh-direct (no-relay architecture)
Patch C v3 — match cw1200 mainline architecture
(drivers/net/wireless/st/cw1200/).  Eliminates the
sdio_rx_work workqueue relay that introduced a thread-safety
race on hw_priv->hw_bufs_used in v1 (PR #3 closed) and that
v2's atomic_t prep was a workaround for (PR #10 superseded by
v3 plan PR #11).

Architectural changes:

  - bes2600_gpio_irq_handler: now calls self->irq_handler()
    directly instead of queue_work(self->sdio_wq, &self->rx_work).
    Bumps bh_rx atomic + wakes bh_wq.
  - bes2600_bh_rx_helper (BES_SDIO_RX_MULTIPLE_ENABLE branch):
    now calls priv->sbus_ops->bus_rx_batch() to do the SDIO read
    inline.  No pipe_read, no skb_dequeue.
  - bes2600_sdio_read_rx_batch (new): the SDIO read sequence
    extracted from sdio_rx_work, registered as
    sbus_ops->bus_rx_batch.  Runs in bh thread context.
  - bes2600_sdio_extract_packets: calls
    bes2600_bh_handle_rx_skb() directly per parsed SKB.  No
    skb_queue_tail, no rx_queue.
  - bes2600_bh_handle_rx_skb (new in bh.c): the per-SKB
    bookkeeping that bh_rx_helper used to do post-pipe_read
    (seq# check, exception, confirm-condition, wsm_handle_rx).
    Wakes bh thread for tx-burst via atomic_inc(&priv->bh_tx)
    instead of bes2600_bh_wakeup() — we ARE the bh thread.
  - Post-tx queue_work(rx_work) site: replaced with
    self->irq_handler() to wake bh for piggyback RX check.

Deleted infrastructure:

  - struct sbus_priv: rx_queue, rx_queue_lock, rx_work fields
  - bes2600_sdio_pipe_read: function deleted (unused)
  - sdio_rx_work: function deleted (unused)
  - sbus_ops->pipe_read assignment: removed for SDIO bus
  - skb_queue_head_init(&self->rx_queue), spin_lock_init(...),
    INIT_WORK(rx_work): probe-time setup removed
  - cancel_work_sync(rx_work) + drain loop in empty_work: removed
  - flush_work(rx_work) in drain helper: replaced with msleep(2)
  - work_pending(rx_work) check in suspend predicate: removed

Concurrency invariant restored:

  - hw_priv->hw_bufs_used: single-writer (bh thread only)
    by construction.  No atomic_t needed.
  - hw_priv->hw_bufs_used_vif[]: ditto.
  - hw_priv->wsm_tx_pending[]: ditto.
  - All other shared state: unchanged or already protected.

Phase 7 partial verification (rep 1, 2026-05-07):

  - Module loads clean, srcversion 371C6606B73AF19299228CA
  - Link associates, no WARN/BUG/oops
  - sdio_rx_work dispatches: 0 (function deleted)
  - bes2600_bh_work redispatches: 0 (single long-lived
    invariant preserved)
  - Chip handled stress traffic without wedge

Phase 7 full N=3 stress ramp deferred to follow-up rep series
(rep 2 had a TCP-level nc race; not a bes2600 issue but
invalidated rep 2's throughput number).
2026-05-07 22:34:11 +02:00

102 lines
3.3 KiB
C

/*
* Common sbus abstraction layer interface for bes2600 wireless driver
*
* Copyright (c) 2010, Bestechnic
* Author:
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef BES2600_SBUS_H
#define BES2600_SBUS_H
/*
* sbus priv forward definition.
* Implemented and instantiated in particular modules.
*/
struct sbus_priv;
struct bes2600_common;
typedef void (*sbus_irq_handler)(void *priv);
enum SUBSYSTEM {
SUBSYSTEM_MCU = 0,
SUBSYSTEM_WIFI,
SUBSYSTEM_BT,
SUBSYSTEM_BT_LP,
};
enum GPIO_WAKE_FLAG
{
GPIO_WAKE_FLAG_MCU = 0,
GPIO_WAKE_FLAG_WIFI_ON,
GPIO_WAKE_FLAG_WIFI_OFF,
GPIO_WAKE_FLAG_BT_ON,
GPIO_WAKE_FLAG_BT_OFF,
GPIO_WAKE_FLAG_BT_LP_ON,
GPIO_WAKE_FLAG_BT_LP_OFF,
GPIO_WAKE_FLAG_HOST_SUSPEND,
GPIO_WAKE_FLAG_HOST_RESUME,
GPIO_WAKE_FLAG_SDIO_RX,
GPIO_WAKE_FLAG_SDIO_PROBE,
};
struct sbus_ops {
int (*init)(struct sbus_priv *self, struct bes2600_common *core);
int (*sbus_memcpy_fromio)(struct sbus_priv *self, unsigned int addr,
void *dst, int count);
int (*sbus_memcpy_toio)(struct sbus_priv *self, unsigned int addr,
const void *src, int count);
void (*lock)(struct sbus_priv *self);
void (*unlock)(struct sbus_priv *self);
int (*irq_subscribe)(struct sbus_priv *self, sbus_irq_handler handler,
void *priv);
int (*irq_unsubscribe)(struct sbus_priv *self);
int (*reset)(struct sbus_priv *self);
size_t (*align_size)(struct sbus_priv *self, size_t size);
int (*set_block_size)(struct sbus_priv *self, size_t size);
int (*pipe_send)(struct sbus_priv *self, u8 pipe, u32 len, u8 *buf);
void * (*pipe_read)(struct sbus_priv *self);
int (*sbus_reg_read)(struct sbus_priv *self, u32 reg,
void *buf, int count);
int (*sbus_reg_write)(struct sbus_priv *self, u32 reg,
const void *buf, int count);
/* sub_system: 0 for mcu, 1 for wifi, 2 for bt, ... */
int (*sbus_active)(struct sbus_priv *self, int sub_system);
int (*sbus_deactive)(struct sbus_priv *self, int sub_system);
int (*power_switch)(struct sbus_priv *self, int on);
/* gpio wake, beacuse bes2600 sdio can't wakeup mcu, so add the two of interfaces */
void (*gpio_wake)(struct sbus_priv *self, int falg);
void (*gpio_sleep)(struct sbus_priv *self, int falg);
/* halt device to get debug information */
void (*halt_device)(struct sbus_priv *self);
bool (*wakeup_source)(struct sbus_priv *self);
int (*reboot)(struct sbus_priv *self);
/*
* Force the host bus to re-detect and re-probe the chip. Called
* from the firmware-wedge recovery path when power_switch() has no
* effective chip-reset signal of its own (e.g. PineTab2, where the
* wifi-reset GPIO is owned by sdio_pwrseq, not the bes2600 node).
* Returns 0 on success or a negative errno.
*/
int (*bus_reset)(struct sbus_priv *self);
/*
* Read a batch of RX frames inline from the bus and deliver each
* one via bes2600_bh_handle_rx_skb(). Called from the bh thread
* (process context, sleepable). Replaces the
* sdio_rx_work + rx_queue + pipe_read relay (Patch C v3, 2026).
* Returns 0 on success, negative on read error.
*/
int (*bus_rx_batch)(struct sbus_priv *self);
};
void bes2600_irq_handler(struct bes2600_common *priv);
/* This MUST be wrapped with hwbus_ops->lock/unlock! */
int __bes2600_irq_enable(int enable);
#endif /* BES2600_SBUS_H */