8139too (2)
先頭を 32-byte 境界にアワせる根拠は未だナゾのまま。
kernel の ML なのかどうか分かりませんが、cache line (64 byte) にアワせるべきかそうでないか、というスレッドは見つけたんですが、32 byte な根拠は微妙。以下が根拠なんですか??
The reason it's 32 is that old drivers depended on the
struct being at least 32-byte aligned because they would
embed structures DMA'd to/from the card in their private
area and just assumed that would be aligned enough for
the card's restrictions.
http://www.mail-archive.com/netdev@vger.kernel.org/msg12380.html より引用
ま、いいや。とりあえず 32 byte な境界整列させてマス、というのは分かったので、もう少し alloc_netdev() を観察。基本的には
- 確保が必要な領域サイズを計算
- 領域確保
- 0 で初期化
- 先頭を確定して、先頭のパディングな領域サイズを退避
- priv な領域の確定 (ここも 32-byte で境界整列)
- setup 呼び出し
最後の strcpy が意味分からんがとりあえずスルー。setup で何してるのか、というと。領域確保した struct net_device な領域を初期化してるんですが具体的にどうか、というと、まず関数ポインタなメンバについて
dev->change_mtu = eth_change_mtu; dev->hard_header = eth_header; dev->rebuild_header = eth_rebuild_header; dev->set_mac_address = eth_mac_addr; dev->hard_header_cache = eth_header_cache; dev->header_cache_update= eth_header_cache_update; dev->hard_header_parse = eth_header_parse;
上記のおそらく同一ソース (net/ethernet/eth.c) な関数を登録している模様。以降の処理は以下。
dev->type = ARPHRD_ETHER; dev->hard_header_len = ETH_HLEN; dev->mtu = 1500; /* eth_mtu */ dev->addr_len = ETH_ALEN; dev->tx_queue_len = 1000; /* Ethernet wants good queues */ dev->flags = IFF_BROADCAST|IFF_MULTICAST; memset(dev->broadcast,0xFF, ETH_ALEN);
なんとなく耳に入るコトが多いソレが列挙されているような気が。とりあえず ethernet な NIC だったら alloc_etherdev() 使えば net_device やドライバ固有の構造体のスペースを確保して ethernet なデフォが設定される訳ですな。
で、alloc_etherdev() を呼び出して戻りをチェックした後に、マクロが二つ。
SET_MODULE_OWNER(dev); SET_NETDEV_DEV(dev, &pdev->dev);
定義元は include/linux/netdevice.h の netdev_priv() 関数が定義されている直下。
#define SET_MODULE_OWNER(dev) do { } while (0) /* Set the sysfs physical device reference for the network logical device * if set prior to registration will cause a symlink during initialization. */ #define SET_NETDEV_DEV(net, pdev) ((net)->class_dev.dev = (pdev))
dev->class_dev.dev に pdev->dev のアドレスが設定される模様。
で、多分更新が放置されているんだと思いますが、再度 netdev_priv() が呼び出され、件のドライバ固有の構造体 (ここでは rtl8139_private 型) の pci_dev メンバに引数で受け取った struct pci_dev 型のソレが設定されている。
「PCI デバイス」の有効化
テキスト p.258 な部分に突入。コメントによると
/* enable device (incl. PCI PM wakeup and hotplug setup) */
との事。テキスト p.259 によれば
「PCI デバイス」の「電源ステータス」を「D0」(フル・パワー) にして、「PCI コンフィグレーション空間」の「コマンド」レジスタに「メモリ空間イネーブル・ビット」および「I/O 空間イネーブル・ビット」を立ます。
となっている。現在、関数が定義されている箇所をサーチ中 (ETAGS は NG)。発見された模様。drivers/pci/pci.c か。
/** * pci_enable_device - Initialize device before it's used by a driver. * @dev: PCI device to be initialized * * Initialize device before it's used by a driver. Ask low-level code * to enable I/O and memory. Wake up the device if it was suspended. * Beware, this function can fail. */ int pci_enable_device(struct pci_dev *dev) { int err; if ((err = pci_enable_device_bars(dev, (1 << PCI_NUM_RESOURCES) - 1))) return err; pci_fixup_device(pci_fixup_enable, dev); dev->is_enabled = 1; return 0; }
失敗する事もあるから注意せえ、との事。テキストにも戻り値のチェックはしなさい、と書いてあります。で、エラーが戻ってくるかもしれない pci_enable_device_bars() の先を見ていく内に PCI コンフィグレーション空間読み書きな関数が pci_set_power_state() の中で出てきた。
ちょっと一旦停止して pci_*_config_*() な関数色々チェキ予定。