GCT GDM72xx WiMAX chip (2)

specification 探してみたけど無いですね。とりあえず掘削。

netlink_k.c

公開されてる手続きとしては

  • netlink_init
  • netlink_exit
  • netlink_send

の三つのみ。これらはいずれも gdm_wimax.c で呼び出されてますね。
とりあえず netlink_init 手続きから。これを呼び出しているのは gdm_wimax_event_init 手続きとなっております。

static int gdm_wimax_event_init(void)
{
	if (!wm_event.ref_cnt) {
		wm_event.sock = netlink_init(NETLINK_WIMAX,
						gdm_wimax_event_rcv);

む、netlink_init 手続きのプロトタイプは以下なのか。

struct sock *netlink_init(int unit, void (*cb)(struct net_device *dev, u16 type,
						void *msg, int len))

ええと、gdm_wimax_event_rcv 手続きの定義を見てみます。全部引用。

static void gdm_wimax_event_rcv(struct net_device *dev, u16 type, void *msg,
				int len)
{
	struct nic *nic = netdev_priv(dev);

	#if defined(DEBUG_HCI)
	u8 *buf = (u8 *) msg;
	u16 hci_cmd =  (buf[0]<<8) | buf[1];
	u16 hci_len = (buf[2]<<8) | buf[3];
	printk(KERN_DEBUG "H=>D: 0x%04x(%d)\n", hci_cmd, hci_len);
	#endif

	gdm_wimax_send(nic, msg, len);
}

く、debugging なナニが多いな。してるのは struct net_device なオブジェクトを struct nic なオブジェクトに変換して gdm_wimax_send にパスしてる模様。
この手続きは netlink_rcv 手続きから (関数ポインタ経由で) 呼び出されるんですが、この手続きは netlink_init 手続きで以下な構造体オブジェクトにセットされてて

	struct netlink_kernel_cfg cfg = {
		.input  = netlink_rcv,
	};

netlink_kernel_create 手続きで云々されてますね。

	sock = netlink_kernel_create(&init_net, unit, &cfg);

	if (sock)
		rcv_cb = cb;

一応、netlink_kernel_create 手続きが 0 以外を戻すのであれば関数ポインタを設定してますね。

netlink_exit 手続き

呼び出し元を確認。gdm_wimax.c で定義されている gdm_wimax_event_exit 手続きですね。この手続きは netlink_init が戻す struct sock 型のオブジェクトを netlink_kernel_release 手続きで解放している模様。
netlink_kernel_release 手続きは net/netlink/af_netlink.c で定義されている模様。

void
netlink_kernel_release(struct sock *sk)
{
	sk_release_kernel(sk);
}
EXPORT_SYMBOL(netlink_kernel_release);

netlink_kernel_create 手続きもワンクッション置いて同じファイルで定義されているようですが、掘削は別途で。

netlink_send 手続き

呼び出し元は gdm_wimax.c の __gdm_wimax_event_send 手続き。この手続きの呼び出し元は確認できておらんのですが、スデに確認した gdm_wimax_event_init 手続きで以下なカンジで参照されてますね。

			INIT_WORK(&wm_event.ws, __gdm_wimax_event_send);

このマクロは一体何かというと workqueue が云々らしい。定義が include/linux/workqueue.h で以下。

#define INIT_WORK(_work, _func)						\
	do {								\
		__INIT_WORK((_work), (_func), 0);			\
	} while (0)

ええと、em_event ですが定義が gdm_wimax.c で以下か。

static struct {
	int ref_cnt;
	struct sock *sock;
	struct list_head evtq;
	spinlock_t evt_lock;

	struct list_head freeq;
	struct work_struct ws;
} wm_event;

いっちゃん下の struct work_struct 型は workqueue 関連のデータ構造らしい。INIT_WORK マクロに渡される _work はこれ前提なのかな。ふむ、INIT_WORK は _work の初期設定してる風に見えますな。
おそらくは、なんですが gdm_wimax_event_send 手続きが送信手続きなのだろうと思われますが、workqueue を使って非同期な送信を行なっているのかな。

備忘など

以下が公開 i/f かな。

static struct net_device_ops gdm_netdev_ops = {
	.ndo_open				= gdm_wimax_open,
	.ndo_stop				= gdm_wimax_close,
	.ndo_set_config			= gdm_wimax_set_config,
	.ndo_start_xmit			= gdm_wimax_tx,
	.ndo_get_stats			= gdm_wimax_stats,
	.ndo_set_mac_address	= gdm_wimax_set_mac_addr,
	.ndo_do_ioctl			= gdm_wimax_ioctl,
};

あと、*register_wimax_device は sdio および usb なナニから呼び出されてますね。逆に物理レイヤ寄りの sdio および usb なナニからこちらの手続き呼び出しはどうやってハンドルしてるのか、なあたりは *register_wimax_device 手続きを云々なのか。

限界気味

まだ本調子ではないですね。ここ、非常に面白いので明日日中も継続して掘削の方向 (を