Marvell Wi-Fi driverのSDIO card割り込みの処理 についてLinuxカーネルに含まれているソースコードを調べてみました。
まとめ
- 割り込みが入るとレジスタをまとめてmp_regsに読み出す。
- 各レジスタの使い方についてまとめた。
- host_int_status_regが正なら、割り込みをハンドリングする必要がある
- mwifiex_process_int_status()が割り込みを処理する関数
- コマンド受信割り込み、データ送信割り込み、データ受信割り込みの順で処理する。
- mpaでaggregateの受信が可能なら、まとめて読みむ
対象
- Linux kernel 4.6.2
- drivers/net/wireless/marvell/mwiflex
レジスタ
- 割り込み処理で使うレジスタです。
mp_regs
- 割り込みでまとめて読み出すレジスタ
- チップごとに読み出すサイズが異なる。max_mp_regsで定義。 87xxは64 88xxは184 89xxは196
- アドレス REG_PORT | MWIFIEX_SDIO_BYTE_MODE_MASK から長さ max_mp_regs だけ読む
if (mwifiex_read_data_sync(adapter, card->mp_regs,
card->reg->max_mp_regs,
REG_PORT | MWIFIEX_SDIO_BYTE_MODE_MASK, 0)) {
mwifiex_dbg(adapter, ERROR, "read mp_regs failed\n");
status_reg0 status_reg1
- firmware stautus 16bit
- mwifiex_sdio_read_fw_status() で読み出す
- ファームウェアダウンロード後の起動確認で使う
- 正常な場合の期待値は 0xfedc
101:#define FIRMWARE_READY_SDIO 0xfedc
host_int_status_reg
- int status reg
- 割り込みステータス
- DN_LD_CMD_PORT_HOST_INT_STATUS コマンド送信完了
- UP_LD_CMD_PORT_HOST_INT_STATUS コマンド受信
- DN_LD_HOST_INT_STATUS データ送信完了
- UP_LD_HOST_INT_STATUS データ受信
io_port_0_reg io_port_1_reg io_port_2_reg
- multiport aggregation で使うio_portを示す
rd_bitmap_l rd_bitmap_u
- 受信バッファのビットマップ
- ビットが1なら受信データあり、0ならデータ無し
- 0ビット目が、mpaでない受信ポート状態
- 1ビット目以降が、mpaの各ポートの状態
wr_bitmap_l wr_bitmap_u
- 送信バッファのビットマップ
- 1なら送信待ちのデータあり、0ならデータ無し
- 0ビット目以降が、mpaの各ポートの状態
rd_len_p0_l rd_len_p0_u
- port 0の受信データ長
- port nの受信データ長は、rd_len_p0_l +(n<<1), rd_len_p0_u + (n<<1) のアドレスにある
card_misc_cfg_reg
- その他の設定
- 割り込みの自動再有効の設定で使う
/* Dnld/Upld ready set to auto reset */
if (!mwifiex_read_reg(adapter, card->reg->card_misc_cfg_reg, ®))
mwifiex_write_reg(adapter, card->reg->card_misc_cfg_reg,
reg | AUTO_RE_ENABLE_INT);
else
return -1;
return 0;
SDIO カード割り込みハンドラの登録
- カード割り込みはsdio_claim_irq()でハンドラを登録します。
static int mwifiex_sdio_enable_host_int(struct mwifiex_adapter *adapter)
{
struct sdio_mmc_card *card = adapter->card;
struct sdio_func *func = card->func;
int ret;
sdio_claim_host(func);
/* Request the SDIO IRQ */
ret = sdio_claim_irq(func, mwifiex_sdio_interrupt);
- 解除は、sdio_release_irq()です。
SDIO card割り込みハンドラ 1
- SIO deviceからカード割り込みが入ると、sdio_claim_irq()で登録したハンドラが呼ばれます。
- card構造体とadapter構造体のポインタを取得
- adapter->ps_stateはカードのPS状態を表します。割り込みが入ったということは起き上がったと等価なので、PS_SATE_AWAKEを設定
- mwifiex_interrupt_status()
- mwifiex_main_process()
/*
* SDIO interrupt handler.
*
* This function reads the interrupt status from firmware and handles
* the interrupt in current thread (ksdioirqd) right away.
*/
static void
mwifiex_sdio_interrupt(struct sdio_func *func)
{
struct mwifiex_adapter *adapter;
struct sdio_mmc_card *card;
card = sdio_get_drvdata(func);
if (!card || !card->adapter) {
pr_err("int: func=%p card=%p adapter=%p\n",
func, card, card ? card->adapter : NULL);
return;
}
adapter = card->adapter;
if (!adapter->pps_uapsd_mode && adapter->ps_state == PS_STATE_SLEEP)
adapter->ps_state = PS_STATE_AWAKE;
mwifiex_interrupt_status(adapter);
mwifiex_main_process(adapter);
}
SDIO card割り込みハンドラ 2
- mwifiex_interrupt_status()
- 割り込みステータスをアップデート
- card->reg->max_mp_regs
- adapter->int_status
- sdio_iregが正なら、なんらなかの処理すべき割り込みがある。
/*
* This function reads the interrupt status from card.
*/
static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter)
{
struct sdio_mmc_card *card = adapter->card;
u8 sdio_ireg;
unsigned long flags;
if (mwifiex_read_data_sync(adapter, card->mp_regs,
card->reg->max_mp_regs,
REG_PORT | MWIFIEX_SDIO_BYTE_MODE_MASK, 0)) {
mwifiex_dbg(adapter, ERROR, "read mp_regs failed\n");
return;
}
sdio_ireg = card->mp_regs[card->reg->host_int_status_reg];
if (sdio_ireg) {
/*
* DN_LD_HOST_INT_STATUS and/or UP_LD_HOST_INT_STATUS
* For SDIO new mode CMD port interrupts
* DN_LD_CMD_PORT_HOST_INT_STATUS and/or
* UP_LD_CMD_PORT_HOST_INT_STATUS
* Clear the interrupt status register
*/
mwifiex_dbg(adapter, INTR,
"int: sdio_ireg = %#x\n", sdio_ireg);
spin_lock_irqsave(&adapter->int_lock, flags);
adapter->int_status |= sdio_ireg;
spin_unlock_irqrestore(&adapter->int_lock, flags);
}
}
SDIO card割り込みハンドラ 2
- mwifiex_main_process()
- これはドライバのメインプロセスです。
- データ送受信に関わらないところは省略する
- 割り込みが入ったら、adapter->if_ops.process_int_status(adapter);を呼ぶ
- この実体はsdio.cのmwifiex_process_int_status()
/*
* The main process.
*
* This function is the main procedure of the driver and handles various driver
* operations. It runs in a loop and provides the core functionalities.
*
* The main responsibilities of this function are -
* - Ensure concurrency control
* - Handle pending interrupts and call interrupt handlers
* - Wake up the card if required
* - Handle command responses and call response handlers
* - Handle events and call event handlers
* - Execute pending commands
* - Transmit pending data packets
*/
int mwifiex_main_process(struct mwifiex_adapter *adapter)
{
int ret = 0;
unsigned long flags;
spin_lock_irqsave(&adapter->main_proc_lock, flags);
/* Check if already processing */
if (adapter->mwifiex_processing || adapter->main_locked) {
adapter->more_task_flag = true;
spin_unlock_irqrestore(&adapter->main_proc_lock, flags);
goto exit_main_proc;
} else {
adapter->mwifiex_processing = true;
spin_unlock_irqrestore(&adapter->main_proc_lock, flags);
}
process_start:
do {
...
/* Handle pending interrupt if any */
if (adapter->int_status) {
if (adapter->hs_activated)
mwifiex_process_hs_config(adapter);
if (adapter->if_ops.process_int_status)
adapter->if_ops.process_int_status(adapter);
}
...
} while (true);
...
exit_main_proc:
if (adapter->hw_status == MWIFIEX_HW_STATUS_CLOSING)
mwifiex_shutdown_drv(adapter);
return ret;
}
EXPORT_SYMBOL_GPL(mwifiex_main_process);
# SDIO card割り込みハンドラ 3
- mwifiex_process_int_status()の概要
- UP_LD_CMD_PORT_HOST_INT_STATUS コマンド受信割り込み
- cmd_rd_len_1とcmd_rd_len_0を読み、受信長を知る
- 受信長分のskbを確保
- CMD53でコマンドを読み出し
- mwifiex_decode_rx_packet()でコマンドを解析
- DN_LD_HOST_INT_STATUS データ送信完了割り込み
- wr_bitmap_l と wr_bitmap_u を読み card->mp_wr_bitmapに上書き
- not generate download ready interrupt の対応
- UP_LD_HOST_INT_STATUS データ受信割り込み
- rd_bitmap_l と rd_bitmap_u を読む
- mwifiex_get_rd_port(adapter, &port)で読みだすportを知る。
- mwifiex_sdio_card_to_host_mp_aggr()データを読み出す。 mpa可能ならmpaで読み出す。
- 終了処理
参考
- Marvell Wi-Fi driverのmulti port aggregation を読む http://qiita.com/eggman/items/7c1db4c13551e44433dc