[ patch .24-rc0 1/5 ] SuperIO locks coordinator - add the module
01 - adds superio_locks module User-drivers specify the sio-port characteristics they can support device-ids, sio-port-addrs, enter & exit sequences, etc in a struct superio_search (in __devinit, preferably). superio_find() then searches existing slots/shared-reservations for a matching sio-port, and returns it if found. Otherwize it probes port-addrs, specified by find() user, and makes and returns a new reservation. superio_find() finds and reserves the slot, returned as ptr or null superio_release()relinguishes the slot (ref-counted) Once theyve got the reservation in struct superio * gate (as named in patches 2-5) they *may* use superio_lock(gate) superio_enter/exit(gate) superio_inb/w(gate, regaddr), superio_outb/w(gate, regaddr, val) or they can do it themselves with inb/outb, by using gate->sioaddr, etc. The API names (superio_find etc) were chosen to fit the idiom used in hwmon/*.c, patches 2-5 remove the per-user-driver copies of the superio_*() fns. I added the module to /drivers/hwmon, mostly cuz thats where Ive used it - perhaps drivers/isa is better ? Signed-off-by: Jim Cromie <[EMAIL PROTECTED]> --- hwmon-superio-module drivers/hwmon/Kconfig |9 + drivers/hwmon/Makefile|1 drivers/hwmon/superio_locks.c | 235 ++ include/linux/superio-locks.h | 112 4 files changed, 357 insertions(+) diff -ruNp -X dontdiff -X exclude-diffs hwmon-fan-push-offset/drivers/hwmon/Kconfig hwmon-superio.old/drivers/hwmon/Kconfig --- hwmon-fan-push-offset/drivers/hwmon/Kconfig 2007-10-14 13:00:24.0 -0600 +++ hwmon-superio.old/drivers/hwmon/Kconfig 2007-10-14 17:22:23.0 -0600 @@ -750,4 +765,13 @@ config HWMON_DEBUG_CHIP a problem with I2C support and want to see more of what is going on. +config SUPERIO_LOCKS + tristate "Super-IO port sharing" + default n + help + This module provides a shared reservation for use by drivers + which need to share access to a multi-function device via + its superio port, and which register that port. + endif # HWMON + diff -ruNp -X dontdiff -X exclude-diffs hwmon-fan-push-offset/drivers/hwmon/Makefile hwmon-superio.old/drivers/hwmon/Makefile --- hwmon-fan-push-offset/drivers/hwmon/Makefile2007-10-14 13:00:24.0 -0600 +++ hwmon-superio.old/drivers/hwmon/Makefile2007-10-14 17:22:23.0 -0600 @@ -72,3 +72,4 @@ ifeq ($(CONFIG_HWMON_DEBUG_CHIP),y) EXTRA_CFLAGS += -DDEBUG endif +obj-$(CONFIG_SUPERIO_LOCKS)+= superio_locks.o diff -ruNp -X dontdiff -X exclude-diffs hwmon-fan-push-offset/drivers/hwmon/superio_locks.c hwmon-superio.old/drivers/hwmon/superio_locks.c --- hwmon-fan-push-offset/drivers/hwmon/superio_locks.c 1969-12-31 17:00:00.0 -0700 +++ hwmon-superio.old/drivers/hwmon/superio_locks.c 2007-10-14 20:27:49.0 -0600 @@ -0,0 +1,235 @@ + +#define DRVNAME "superio_locks" +#define DEBUG 1 + +#include +#include +#include +#include +#include +#include +#include + +MODULE_AUTHOR("Jim Cromie <[EMAIL PROTECTED]"); +MODULE_LICENSE("GPL"); + +/* + * This module allows multiple driver modules to coordinate their use + * of a Super-IO port to control the multiple logical devices behind + * it. Drivers will superio_find() their port, and 2 such modules + * will share a slot containing the lock. + */ +static int max_locks = 3; /* 3 is enough for 90% uses */ +module_param(max_locks, int, 0); +MODULE_PARM_DESC(max_locks, +" Number of sio-lock clients to serve (default=3)"); + +static int paranoid; +module_param(paranoid, int, 0); +MODULE_PARM_DESC(paranoid, +" when true, fails if superio-port region is claimed"); + +static struct superio *sio_locks; +static struct mutex reservation_lock; + +#define SIO_DEVID_ADDR_STD 0x20 +#define SIO_LDN_ADDR_STD 0x07 + +struct superio* superio_probe_reserve(const struct superio_search * const where, + int cmd_addr, int want_devid) +{ + struct superio *gate; + u16 devid_addr = where->devid_addr; + u16 mydevid; + int slot, rc, i; + + if (!devid_addr) + devid_addr = SIO_DEVID_ADDR_STD; + + + /* send superio-enter sequence for devices which need them */ + for (i = 0; i < SEQ_SZ && where->enter_seq[i]; i++) + outb(where->enter_seq[i], cmd_addr); + + outb(devid_addr, cmd_addr); + + /* sanity check that cmd-reg remembers the val just written + rc = inb(cmd_addr); + if (rc != (devid_addr & 0xFF)) { + pr_debug("cmd-reg absent at %x, got %x\n", cmd_addr, rc); + return NULL; + } + */ + /* Read the device-id register(s), using cmd written above */ + if (!where->devid_word) { + mydevid = inb(cmd_addr+1); + } else { + /* want 16 bit devid, so get it
[ patch .24-rc0 1/5 ] SuperIO locks coordinator - add the module
01 - adds superio_locks module User-drivers specify the sio-port characteristics they can support device-ids, sio-port-addrs, enter exit sequences, etc in a struct superio_search (in __devinit, preferably). superio_find() then searches existing slots/shared-reservations for a matching sio-port, and returns it if found. Otherwize it probes port-addrs, specified by find() user, and makes and returns a new reservation. superio_find() finds and reserves the slot, returned as ptr or null superio_release()relinguishes the slot (ref-counted) Once theyve got the reservation in struct superio * gate (as named in patches 2-5) they *may* use superio_lock(gate) superio_enter/exit(gate) superio_inb/w(gate, regaddr), superio_outb/w(gate, regaddr, val) or they can do it themselves with inb/outb, by using gate-sioaddr, etc. The API names (superio_find etc) were chosen to fit the idiom used in hwmon/*.c, patches 2-5 remove the per-user-driver copies of the superio_*() fns. I added the module to /drivers/hwmon, mostly cuz thats where Ive used it - perhaps drivers/isa is better ? Signed-off-by: Jim Cromie [EMAIL PROTECTED] --- hwmon-superio-module drivers/hwmon/Kconfig |9 + drivers/hwmon/Makefile|1 drivers/hwmon/superio_locks.c | 235 ++ include/linux/superio-locks.h | 112 4 files changed, 357 insertions(+) diff -ruNp -X dontdiff -X exclude-diffs hwmon-fan-push-offset/drivers/hwmon/Kconfig hwmon-superio.old/drivers/hwmon/Kconfig --- hwmon-fan-push-offset/drivers/hwmon/Kconfig 2007-10-14 13:00:24.0 -0600 +++ hwmon-superio.old/drivers/hwmon/Kconfig 2007-10-14 17:22:23.0 -0600 @@ -750,4 +765,13 @@ config HWMON_DEBUG_CHIP a problem with I2C support and want to see more of what is going on. +config SUPERIO_LOCKS + tristate Super-IO port sharing + default n + help + This module provides a shared reservation for use by drivers + which need to share access to a multi-function device via + its superio port, and which register that port. + endif # HWMON + diff -ruNp -X dontdiff -X exclude-diffs hwmon-fan-push-offset/drivers/hwmon/Makefile hwmon-superio.old/drivers/hwmon/Makefile --- hwmon-fan-push-offset/drivers/hwmon/Makefile2007-10-14 13:00:24.0 -0600 +++ hwmon-superio.old/drivers/hwmon/Makefile2007-10-14 17:22:23.0 -0600 @@ -72,3 +72,4 @@ ifeq ($(CONFIG_HWMON_DEBUG_CHIP),y) EXTRA_CFLAGS += -DDEBUG endif +obj-$(CONFIG_SUPERIO_LOCKS)+= superio_locks.o diff -ruNp -X dontdiff -X exclude-diffs hwmon-fan-push-offset/drivers/hwmon/superio_locks.c hwmon-superio.old/drivers/hwmon/superio_locks.c --- hwmon-fan-push-offset/drivers/hwmon/superio_locks.c 1969-12-31 17:00:00.0 -0700 +++ hwmon-superio.old/drivers/hwmon/superio_locks.c 2007-10-14 20:27:49.0 -0600 @@ -0,0 +1,235 @@ + +#define DRVNAME superio_locks +#define DEBUG 1 + +#include linux/kernel.h +#include linux/init.h +#include linux/module.h +#include linux/moduleparam.h +#include linux/mutex.h +#include linux/ioport.h +#include linux/superio-locks.h + +MODULE_AUTHOR(Jim Cromie [EMAIL PROTECTED]); +MODULE_LICENSE(GPL); + +/* + * This module allows multiple driver modules to coordinate their use + * of a Super-IO port to control the multiple logical devices behind + * it. Drivers will superio_find() their port, and 2 such modules + * will share a slot containing the lock. + */ +static int max_locks = 3; /* 3 is enough for 90% uses */ +module_param(max_locks, int, 0); +MODULE_PARM_DESC(max_locks, + Number of sio-lock clients to serve (default=3)); + +static int paranoid; +module_param(paranoid, int, 0); +MODULE_PARM_DESC(paranoid, + when true, fails if superio-port region is claimed); + +static struct superio *sio_locks; +static struct mutex reservation_lock; + +#define SIO_DEVID_ADDR_STD 0x20 +#define SIO_LDN_ADDR_STD 0x07 + +struct superio* superio_probe_reserve(const struct superio_search * const where, + int cmd_addr, int want_devid) +{ + struct superio *gate; + u16 devid_addr = where-devid_addr; + u16 mydevid; + int slot, rc, i; + + if (!devid_addr) + devid_addr = SIO_DEVID_ADDR_STD; + + + /* send superio-enter sequence for devices which need them */ + for (i = 0; i SEQ_SZ where-enter_seq[i]; i++) + outb(where-enter_seq[i], cmd_addr); + + outb(devid_addr, cmd_addr); + + /* sanity check that cmd-reg remembers the val just written + rc = inb(cmd_addr); + if (rc != (devid_addr 0xFF)) { + pr_debug(cmd-reg absent at %x, got %x\n, cmd_addr, rc); + return NULL; + } + */ + /* Read the device-id register(s), using cmd written above */ + if (!where-devid_word) { + mydevid =