掘削ログ

昨晩、class_create な手続き呼び出し箇所を特定するために rt2870sta の中身を掘ってて力尽きた模様です。何故か日報に残されたソレをこちらに纏めてみます。
とりあえず rt2870 の中身からスタートという事で初期化な手続きが rtusb_init な模様。os/linux/us_main_dev.c にて定義。

INT __init rtusb_init(void)
{
        printk("rtusb init --->\n");   
        return usb_register(&rtusb_driver);
}

usb_register 手続きの定義は rt2870 なツリーの中には無い。カーネルツリーの include/linux/usb.h にて以下。

static inline int usb_register(struct usb_driver *driver)
{
        return usb_register_driver(driver, THIS_MODULE, KBUILD_MODNAME);
}

日報なログにはパスが書いてない。相当へろへろだった事が伺えます。で、usb_register_driver 手続きですが、drivers/usb/core/driver.c な模様。

int usb_register_driver(struct usb_driver *new_driver, struct module *owner,
                        const char *mod_name)
{
        int retval = 0;

        if (usb_disabled())
                return -ENODEV;

        new_driver->drvwrap.for_devices = 0;
        new_driver->drvwrap.driver.name = (char *) new_driver->name;
        new_driver->drvwrap.driver.bus = &usb_bus_type;
        new_driver->drvwrap.driver.probe = usb_probe_interface;
        new_driver->drvwrap.driver.remove = usb_unbind_interface;
        new_driver->drvwrap.driver.owner = owner;
        new_driver->drvwrap.driver.mod_name = mod_name;
        spin_lock_init(&new_driver->dynids.lock);
        INIT_LIST_HEAD(&new_driver->dynids.list);

        retval = driver_register(&new_driver->drvwrap.driver);

        if (!retval) {
                pr_info("%s: registered new interface driver %s\n",
                        usbcore_name, new_driver->name);
                usbfs_update_special();
                usb_create_newid_file(new_driver);
        } else {
                printk(KERN_ERR "%s: error %d registering interface "
                        "       driver %s\n",
                        usbcore_name, retval, new_driver->name);
        }

        return retval;
}

で、driver_register は何処、というあたりで倒れた模様です。ちなみに driver_register 手続きですが、driver/base/driver.c にて定義されておりますな。そこから呼び出されている手続きの内、クサそうなのは

  • driver_find 手続き (ではないかも
  • bus_add_driver 手続き
  • driver_add_groups 手続き

なんですが、端末で探すの疲れる。gtags するのは微妙だしなぁ。bus_add_driver にアタリを付けて掘削。定義が以下です。ちょっと長いので小刻みに引用します。

/**
 * bus_add_driver - Add a driver to the bus.
 * @drv: driver.
 */
int bus_add_driver(struct device_driver *drv)
{
        struct bus_type *bus;
        struct driver_private *priv;
        int error = 0;

        bus = bus_get(drv->bus);
        if (!bus)
                return -EINVAL;

        pr_debug("bus: '%s': add driver %s\n", bus->name, drv->name);

        priv = kzalloc(sizeof(*priv), GFP_KERNEL);
        if (!priv) {
                error = -ENOMEM;
                goto out_put_bus;
        }
        klist_init(&priv->klist_devices, NULL, NULL);
        priv->driver = drv;
        drv->p = priv;
        priv->kobj.kset = bus->p->drivers_kset;
        error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL,
                                     "%s", drv->name);
        if (error)
                goto out_unregister;

kobject_init_and_add とか怪しげ。driver 配下で find|grep したら定義が無い。定義自体は lib/kobject.c で以下。

/**
 * kobject_init_and_add - initialize a kobject structure and add it to the kobject hierarchy
 * @kobj: pointer to the kobject to initialize
 * @ktype: pointer to the ktype for this kobject.
 * @parent: pointer to the parent of this kobject.
 * @fmt: the name of the kobject.
 *
 * This function combines the call to kobject_init() and
 * kobject_add().  The same type of error handling after a call to
 * kobject_add() and kobject lifetime rules are the same here.
 */
int kobject_init_and_add(struct kobject *kobj, struct kobj_type *ktype,
                         struct kobject *parent, const char *fmt, ...)
{
        va_list args;
        int retval;

        kobject_init(kobj, ktype);

        va_start(args, fmt);
        retval = kobject_add_varg(kobj, parent, fmt, args);
        va_end(args);

        return retval;
}
EXPORT_SYMBOL_GPL(kobject_init_and_add);

そっから先を見てみたんですが、class 云々は無いのかどうなのか。gdgd のまま勉強会が始まってしまうので、ここでエントリ投入。