[PARPORT] [PATCH 2.5.63 2/9] Update parport class driver to new module loader API.

From: Bob Miller (rem@osdl.org)
Date: Thu Feb 27 2003 - 16:58:11 EST

  • Next message: Bob Miller: "[PARPORT] [PATCH 2.5.63 5/9] Update the Archimedes parport driver for new module API."

    Changes to the parport class driver to allow removal of depricated
    check_region() and MOD_INC_USE_COUNT/MOD_DEC_USE_COUNT methods.

    Changed to use C99 initializers.

    Also fixed an allocate race in parport_register_port(). The old code would
    lock the portlist to find the next parallel port device number to use.
    After figuring this out, the list would be unlocked to do all the memory
    allocations for the new device. After the new parallel port device
    data structures were all setup, parport_register_port() would re-lock
    the portlist to insert the new device. But, it would not check to make
    sure that some other code didn't already install a device with the
    same number. I changed the code to, after all device setup, lock
    the list, find the number, update the members that need the number
    and then insert the device into the list all on same list lock round-trip.

    -- 
    Bob Miller					Email: rem@osdl.org
    Open Source Development Lab			Phone: 503.626.2455 Ext. 17
    

    diff -Nru a/include/linux/parport.h b/include/linux/parport.h --- a/include/linux/parport.h Thu Feb 27 09:46:20 2003 +++ b/include/linux/parport.h Thu Feb 27 09:46:20 2003 @@ -166,9 +166,6 @@ void (*save_state)(struct parport *, struct parport_state *); void (*restore_state)(struct parport *, struct parport_state *); - void (*inc_use_count)(void); - void (*dec_use_count)(void); - /* Block read/write */ size_t (*epp_write_data) (struct parport *port, const void *buf, size_t len, int flags); @@ -192,6 +189,7 @@ size_t len, int flags); size_t (*byte_read_data) (struct parport *port, void *buf, size_t len, int flags); + struct module *owner; }; struct parport_device_info { @@ -540,9 +538,6 @@ extern int parport_device_proc_unregister(struct pardevice *device); extern int parport_default_proc_register(void); extern int parport_default_proc_unregister(void); - -extern void dec_parport_count(void); -extern void inc_parport_count(void); /* If PC hardware is the only type supported, we can optimise a bit. */ #if (defined(CONFIG_PARPORT_PC) || defined(CONFIG_PARPORT_PC_MODULE)) && !(defined(CONFIG_PARPORT_ARC) || defined(CONFIG_PARPORT_ARC_MODULE)) && !(defined(CONFIG_PARPORT_AMIGA) || defined(CONFIG_PARPORT_AMIGA_MODULE)) && !(defined(CONFIG_PARPORT_MFC3) || defined(CONFIG_PARPORT_MFC3_MODULE)) && !(defined(CONFIG_PARPORT_ATARI) || defined(CONFIG_PARPORT_ATARI_MODULE)) && !(defined(CONFIG_USB_USS720) || defined(CONFIG_USB_USS720_MODULE)) && !(defined(CONFIG_PARPORT_SUNBPP) || defined(CONFIG_PARPORT_SUNBPP_MODULE)) && !defined(CONFIG_PARPORT_OTHER)

    diff -Nru a/drivers/parport/init.c b/drivers/parport/init.c --- a/drivers/parport/init.c Thu Feb 27 09:46:20 2003 +++ b/drivers/parport/init.c Thu Feb 27 09:46:20 2003 @@ -227,17 +227,3 @@ EXPORT_SYMBOL(parport_find_device); EXPORT_SYMBOL(parport_find_class); #endif - -void inc_parport_count(void) -{ -#ifdef MODULE - MOD_INC_USE_COUNT; -#endif -} - -void dec_parport_count(void) -{ -#ifdef MODULE - MOD_DEC_USE_COUNT; -#endif -}

    diff -Nru a/drivers/parport/share.c b/drivers/parport/share.c --- a/drivers/parport/share.c Thu Feb 27 09:46:20 2003 +++ b/drivers/parport/share.c Thu Feb 27 09:46:20 2003 @@ -55,37 +55,44 @@ static void dead_onearg (struct parport *p){} static void dead_initstate (struct pardevice *d, struct parport_state *s) { } static void dead_state (struct parport *p, struct parport_state *s) { } -static void dead_noargs (void) { } static size_t dead_write (struct parport *p, const void *b, size_t l, int f) { return 0; } static size_t dead_read (struct parport *p, void *b, size_t l, int f) { return 0; } static struct parport_operations dead_ops = { - dead_write_lines, /* data */ - dead_read_lines, - dead_write_lines, /* control */ - dead_read_lines, - dead_frob_lines, - dead_read_lines, /* status */ - dead_onearg, /* enable_irq */ - dead_onearg, /* disable_irq */ - dead_onearg, /* data_forward */ - dead_onearg, /* data_reverse */ - dead_initstate, /* init_state */ - dead_state, - dead_state, - dead_noargs, /* xxx_use_count */ - dead_noargs, - dead_write, /* epp */ - dead_read, - dead_write, - dead_read, - dead_write, /* ecp */ - dead_read, - dead_write, - dead_write, /* compat */ - dead_read, /* nibble */ - dead_read /* byte */ + .write_data = dead_write_lines, /* data */ + .read_data = dead_read_lines, + + .write_control = dead_write_lines, /* control */ + .read_control = dead_read_lines, + .frob_control = dead_frob_lines, + + .read_status = dead_read_lines, /* status */ + + .enable_irq = dead_onearg, /* enable_irq */ + .disable_irq = dead_onearg, /* disable_irq */ + + .data_forward = dead_onearg, /* data_forward */ + .data_reverse = dead_onearg, /* data_reverse */ + + .init_state = dead_initstate, /* init_state */ + .save_state = dead_state, + .restore_state = dead_state, + + .epp_write_data = dead_write, /* epp */ + .epp_read_data = dead_read, + .epp_write_addr = dead_write, + .epp_read_addr = dead_read, + + .ecp_write_data = dead_write, /* ecp */ + .ecp_read_data = dead_read, + .ecp_write_addr = dead_write, + + .compat_write_data = dead_write, /* compat */ + .nibble_read_data = dead_read, /* nibble */ + .byte_read_data = dead_read, /* byte */ + + .owner = NULL, }; /* Call attach(port) for each registered driver. */ @@ -390,25 +397,6 @@ return NULL; } - /* Search for the lowest free parport number. */ - - spin_lock_irq (&parportlist_lock); - for (portnum = 0; ; portnum++) { - struct parport *itr = portlist; - while (itr) { - if (itr->number == portnum) - /* No good, already used. */ - break; - else - itr = itr->next; - } - - if (itr == NULL) - /* Got to the end of the list. */ - break; - } - spin_unlock_irq (&parportlist_lock); - /* Init our structure */ memset(tmp, 0, sizeof(struct parport)); tmp->base = base; @@ -420,7 +408,6 @@ tmp->devices = tmp->cad = NULL; tmp->flags = 0; tmp->ops = ops; - tmp->portnum = tmp->number = portnum; tmp->physport = tmp; memset (tmp->probe_info, 0, 5 * sizeof (struct parport_device_info)); tmp->cad_lock = RW_LOCK_UNLOCKED; @@ -438,9 +425,32 @@ kfree(tmp); return NULL; } + /* Search for the lowest free parport number. */ + + spin_lock_irq (&parportlist_lock); + for (portnum = 0; ; portnum++) { + struct parport *itr = portlist; + while (itr) { + if (itr->number == portnum) + /* No good, already used. */ + break; + else + itr = itr->next; + } + + if (itr == NULL) + /* Got to the end of the list. */ + break; + } + + /* + * Now that the portnum is known finish doing the Init. + */ + tmp->portnum = tmp->number = portnum; sprintf(name, "parport%d", portnum); tmp->name = name; + /* * Chain the entry to our list. * @@ -448,8 +458,6 @@ * to clear irq on the local CPU. -arca */ - spin_lock(&parportlist_lock); - /* We are locked against anyone else performing alterations, but * because of parport_enumerate people can still _read_ the list * while we are changing it; so be careful.. @@ -664,8 +672,10 @@ kmalloc. To be absolutely safe, we have to require that our caller doesn't sleep in between parport_enumerate and parport_register_device.. */ - inc_parport_count(); - port->ops->inc_use_count(); + if (!try_module_get(port->ops->owner)) { + return NULL; + } + parport_get_port (port); tmp = kmalloc(sizeof(struct pardevice), GFP_KERNEL); @@ -736,9 +746,9 @@ out_free_pardevice: kfree (tmp); out: - dec_parport_count(); - port->ops->dec_use_count(); parport_put_port (port); + module_put(port->ops->owner); + return NULL; } @@ -801,8 +811,7 @@ kfree(dev->state); kfree(dev); - dec_parport_count(); - port->ops->dec_use_count(); + module_put(port->ops->owner); parport_put_port (port); /* Yes, that's right, someone _could_ still have a pointer to

    -- To unsubscribe, send mail to: linux-parport-request@torque.net -- -- with the single word "unsubscribe" in the body of the message. --



    This archive was generated by hypermail 2b29 : Thu Feb 27 2003 - 17:13:54 EST