From 9b394a3293bfa4397c24c6649034b411994dbb72 Mon Sep 17 00:00:00 2001 From: jhb Date: Mon, 4 Aug 2008 20:46:15 +0000 Subject: [PATCH] Add locking to the various iicbus(4) bridge drivers: - Just grab Giant in the ixp425_iic(4) driver since this driver uses a shared address/data register window pair to access the actual I2C registers. None of the other ixp425 drivers lock access to these shared address/data registers yet and that would need to be done before this could use any meaningful locking. - Add locking to the interrupt handler and 'iicbus_reset' methods of the at91_twi(4) driver. - Add locking to the pcf(4) driver. Other pcf(4) fixes include: - Don't needlessly zero the softc. - Use bus_foo rather than bus_space_foo and remove bus space tag and handle from softc. - The lpbb(4) driver just grabs Giant for now. This will be refined later when ppbus(4) is locked. - As was done with smbus earlier, move the DRIVER_MODULE() lines to match the bus driver (either iicbus or iicbb) to the bridge driver into the bridge drivers. Tested by: sam (arm/ixp425) --- sys/arm/at91/at91_twi.c | 7 ++++ sys/arm/xscale/ixp425/ixp425_iic.c | 9 +++++ sys/dev/bktr/bktr_i2c.c | 1 + sys/dev/iicbus/iicbb.c | 11 +----- sys/dev/pcf/envctrl.c | 13 +++--- sys/dev/pcf/pcf.c | 63 +++++++++++++++++++++++------- sys/dev/pcf/pcf_ebus.c | 10 +++-- sys/dev/pcf/pcf_isa.c | 10 +++-- sys/dev/pcf/pcfvar.h | 20 +++++++--- sys/dev/ppbus/lpbb.c | 56 +++++++++++++++++++------- sys/pci/viapm.c | 1 + 11 files changed, 143 insertions(+), 58 deletions(-) diff --git a/sys/arm/at91/at91_twi.c b/sys/arm/at91/at91_twi.c index 0d8a2d4efa50..ec05d146bf7e 100644 --- a/sys/arm/at91/at91_twi.c +++ b/sys/arm/at91/at91_twi.c @@ -155,6 +155,8 @@ at91_twi_detach(device_t dev) if (sc->iicbus && (rv = device_delete_child(dev, sc->iicbus)) != 0) return (rv); + AT91_TWI_LOCK_DESTROY(sc); + return (0); } @@ -211,6 +213,7 @@ at91_twi_intr(void *xsc) status = RD4(sc, TWI_SR); if (status == 0) return; + AT91_TWI_LOCK(sc); sc->flags |= status & (TWI_SR_OVRE | TWI_SR_UNRE | TWI_SR_NACK); if (status & TWI_SR_RXRDY) sc->flags |= TWI_SR_RXRDY; @@ -220,6 +223,7 @@ at91_twi_intr(void *xsc) sc->flags |= TWI_SR_TXCOMP; WR4(sc, TWI_IDR, status); wakeup(sc); + AT91_TWI_UNLOCK(sc); return; } @@ -230,6 +234,7 @@ at91_twi_wait(struct at91_twi_softc *sc, uint32_t bit) int counter = 100000; uint32_t sr; + AT91_TWI_ASSERT_LOCKED(sc); while (!((sr = RD4(sc, TWI_SR)) & bit) && counter-- > 0 && !(sr & TWI_SR_NACK)) continue; @@ -247,6 +252,7 @@ at91_twi_rst_card(device_t dev, u_char speed, u_char addr, u_char *oldaddr) int clk; sc = device_get_softc(dev); + AT91_TWI_LOCK(sc); if (oldaddr) *oldaddr = sc->twi_addr; sc->twi_addr = addr; @@ -275,6 +281,7 @@ at91_twi_rst_card(device_t dev, u_char speed, u_char addr, u_char *oldaddr) WR4(sc, TWI_CR, TWI_CR_MSEN | TWI_CR_SVDIS); WR4(sc, TWI_CWGR, sc->cwgr); printf("setting cwgr to %#x\n", sc->cwgr); + AT91_TWI_UNLOCK(sc); return 0; } diff --git a/sys/arm/xscale/ixp425/ixp425_iic.c b/sys/arm/xscale/ixp425/ixp425_iic.c index ecc889f9ec89..38a86a6ad5ee 100644 --- a/sys/arm/xscale/ixp425/ixp425_iic.c +++ b/sys/arm/xscale/ixp425/ixp425_iic.c @@ -106,9 +106,11 @@ ixpiic_getscl(device_t dev) struct ixpiic_softc *sc = ixpiic_sc; uint32_t reg; + mtx_lock(&Giant); GPIO_CONF_SET(sc, IXP425_GPIO_GPOER, GPIO_I2C_SCL_BIT); reg = GPIO_CONF_READ_4(sc, IXP425_GPIO_GPINR); + mtx_unlock(&Giant); return (reg & GPIO_I2C_SCL_BIT); } @@ -118,9 +120,11 @@ ixpiic_getsda(device_t dev) struct ixpiic_softc *sc = ixpiic_sc; uint32_t reg; + mtx_lock(&Giant); GPIO_CONF_SET(sc, IXP425_GPIO_GPOER, GPIO_I2C_SDA_BIT); reg = GPIO_CONF_READ_4(sc, IXP425_GPIO_GPINR); + mtx_unlock(&Giant); return (reg & GPIO_I2C_SDA_BIT); } @@ -129,11 +133,13 @@ ixpiic_setsda(device_t dev, char val) { struct ixpiic_softc *sc = ixpiic_sc; + mtx_lock(&Giant); GPIO_CONF_CLR(sc, IXP425_GPIO_GPOUTR, GPIO_I2C_SDA_BIT); if (val) GPIO_CONF_SET(sc, IXP425_GPIO_GPOER, GPIO_I2C_SDA_BIT); else GPIO_CONF_CLR(sc, IXP425_GPIO_GPOER, GPIO_I2C_SDA_BIT); + mtx_unlock(&Giant); DELAY(I2C_DELAY); } @@ -142,11 +148,13 @@ ixpiic_setscl(device_t dev, char val) { struct ixpiic_softc *sc = ixpiic_sc; + mtx_lock(&Giant); GPIO_CONF_CLR(sc, IXP425_GPIO_GPOUTR, GPIO_I2C_SCL_BIT); if (val) GPIO_CONF_SET(sc, IXP425_GPIO_GPOER, GPIO_I2C_SCL_BIT); else GPIO_CONF_CLR(sc, IXP425_GPIO_GPOER, GPIO_I2C_SCL_BIT); + mtx_unlock(&Giant); DELAY(I2C_DELAY); } @@ -184,3 +192,4 @@ static driver_t ixpiic_driver = { static devclass_t ixpiic_devclass; DRIVER_MODULE(ixpiic, ixp, ixpiic_driver, ixpiic_devclass, 0, 0); +DRIVER_MODULE(iicbb, ixpiic, iicbb_driver, iicbb_devclass, 0, 0); diff --git a/sys/dev/bktr/bktr_i2c.c b/sys/dev/bktr/bktr_i2c.c index 0d733c007492..403225818eae 100644 --- a/sys/dev/bktr/bktr_i2c.c +++ b/sys/dev/bktr/bktr_i2c.c @@ -356,6 +356,7 @@ bti2c_smb_readb(device_t dev, u_char slave, char cmd, char *byte) return (0); } +DRIVER_MODULE(iicbb, bktr, iicbb_driver, iicbb_devclass, 0, 0); DRIVER_MODULE(smbus, bktr, smbus_driver, smbus_devclass, 0, 0); #endif /* defined(BKTR_USE_FREEBSD_SMBUS) */ diff --git a/sys/dev/iicbus/iicbb.c b/sys/dev/iicbus/iicbb.c index ac10ceed2865..f0d4c2faef71 100644 --- a/sys/dev/iicbus/iicbb.c +++ b/sys/dev/iicbus/iicbb.c @@ -413,16 +413,7 @@ iicbb_read(device_t dev, char * buf, int len, int *read, int last, int delay) return (0); } -/* - * XXX This is lame. We need to have a base iicbb_bridge class that all these - * XXX derive from. - */ -DRIVER_MODULE(iicbb, bktr, iicbb_driver, iicbb_devclass, 0, 0); -DRIVER_MODULE(iicbb, ixpiic, iicbb_driver, iicbb_devclass, 0, 0); -DRIVER_MODULE(iicbb, lpbb, iicbb_driver, iicbb_devclass, 0, 0); -DRIVER_MODULE(iicbb, viapm, iicbb_driver, iicbb_devclass, 0, 0); -DRIVER_MODULE(iicbb, cxm_iic, iicbb_driver, iicbb_devclass, 0, 0); -DRIVER_MODULE(iicbb, at91_bbiic, iicbb_driver, iicbb_devclass, 0, 0); +DRIVER_MODULE(iicbus, iicbb, iicbus_driver, iicbus_devclass, 0, 0); MODULE_DEPEND(iicbb, iicbus, IICBUS_MINVER, IICBUS_PREFVER, IICBUS_MAXVER); MODULE_VERSION(iicbb, IICBB_MODVER); diff --git a/sys/dev/pcf/envctrl.c b/sys/dev/pcf/envctrl.c index 8c4795867881..7c1cb1b153f8 100644 --- a/sys/dev/pcf/envctrl.c +++ b/sys/dev/pcf/envctrl.c @@ -37,13 +37,15 @@ __FBSDID("$FreeBSD$"); */ #include -#include #include #include #include +#include #include #include +#include #include +#include #include #include @@ -107,7 +109,7 @@ envctrl_attach(device_t dev) int rv = ENXIO; sc = DEVTOSOFTC(dev); - bzero(sc, sizeof(struct pcf_softc)); + mtx_init(&sc->pcf_lock, device_get_nameunit(dev), "pcf", MTX_DEF); /* IO port is mandatory */ sc->res_ioport = bus_alloc_resource_any(dev, SYS_RES_MEMORY, @@ -116,8 +118,6 @@ envctrl_attach(device_t dev) device_printf(dev, "cannot reserve I/O port range\n"); goto error; } - sc->bt_ioport = rman_get_bustag(sc->res_ioport); - sc->bh_ioport = rman_get_bushandle(sc->res_ioport); sc->pcf_flags = device_get_flags(dev); @@ -134,7 +134,7 @@ envctrl_attach(device_t dev) pcf_rst_card(dev, IIC_FASTEST, PCF_DEFAULT_ADDR, NULL); rv = bus_setup_intr(dev, sc->res_irq, - INTR_TYPE_NET /* | INTR_ENTROPY */, + INTR_TYPE_NET | INTR_MPSAFE /* | INTR_ENTROPY */, NULL, pcf_intr, sc, &sc->intr_cookie); if (rv) { device_printf(dev, "could not setup IRQ\n"); @@ -158,6 +158,7 @@ envctrl_attach(device_t dev) bus_release_resource(dev, SYS_RES_MEMORY, sc->rid_ioport, sc->res_ioport); } + mtx_destroy(&sc->pcf_lock); return (rv); } @@ -181,10 +182,12 @@ envctrl_detach(device_t dev) } bus_release_resource(dev, SYS_RES_MEMORY, sc->rid_ioport, sc->res_ioport); + mtx_destroy(&sc->pcf_lock); return (0); } DRIVER_MODULE(envctrl, ebus, envctrl_driver, envctrl_devclass, 0, 0); +DRIVER_MODULE(iicbus, envctrl, iicbus_driver, iicbus_devclass, 0, 0); MODULE_DEPEND(envctrl, iicbus, PCF_MINVER, PCF_PREFVER, PCF_MAXVER); MODULE_VERSION(envctrl, PCF_MODVER); diff --git a/sys/dev/pcf/pcf.c b/sys/dev/pcf/pcf.c index 032095855f59..e6c9967e5e8a 100644 --- a/sys/dev/pcf/pcf.c +++ b/sys/dev/pcf/pcf.c @@ -29,10 +29,12 @@ __FBSDID("$FreeBSD$"); #include -#include +#include +#include #include #include -#include +#include +#include #include #include @@ -48,16 +50,18 @@ __FBSDID("$FreeBSD$"); static int pcf_wait_byte(struct pcf_softc *pcf); static int pcf_noack(struct pcf_softc *pcf, int timeout); +static void pcf_stop_locked(struct pcf_softc *pcf); /* * Polling mode for master operations wait for a new - * byte incomming or outgoing + * byte incoming or outgoing */ -int +static int pcf_wait_byte(struct pcf_softc *sc) { int counter = TIMEOUT; + PCF_ASSERT_LOCKED(sc); while (counter--) { if ((pcf_get_S1(sc) & PIN) == 0) @@ -71,11 +75,11 @@ pcf_wait_byte(struct pcf_softc *sc) return (IIC_ETIMEOUT); } -int -pcf_stop(device_t dev) +static void +pcf_stop_locked(struct pcf_softc *sc) { - struct pcf_softc *sc = DEVTOSOFTC(dev); + PCF_ASSERT_LOCKED(sc); #ifdef PCFDEBUG device_printf(dev, " >> stop\n"); #endif @@ -91,17 +95,15 @@ pcf_stop(device_t dev) sc->pcf_started = 0; } - - return (0); } - -int +static int pcf_noack(struct pcf_softc *sc, int timeout) { int noack; int k = timeout/10; + PCF_ASSERT_LOCKED(sc); do { noack = pcf_get_S1(sc) & LRB; if (!noack) @@ -118,6 +120,7 @@ pcf_repeated_start(device_t dev, u_char slave, int timeout) struct pcf_softc *sc = DEVTOSOFTC(dev); int error = 0; + PCF_LOCK(sc); #ifdef PCFDEBUG device_printf(dev, " >> repeated start for slave %#x\n", (unsigned)slave); @@ -142,10 +145,12 @@ pcf_repeated_start(device_t dev, u_char slave, int timeout) goto error; } + PCF_UNLOCK(sc); return (0); error: - pcf_stop(dev); + pcf_stop_locked(sc); + PCF_UNLOCK(sc); return (error); } @@ -155,6 +160,7 @@ pcf_start(device_t dev, u_char slave, int timeout) struct pcf_softc *sc = DEVTOSOFTC(dev); int error = 0; + PCF_LOCK(sc); #ifdef PCFDEBUG device_printf(dev, " >> start for slave %#x\n", (unsigned)slave); #endif @@ -162,6 +168,7 @@ pcf_start(device_t dev, u_char slave, int timeout) #ifdef PCFDEBUG printf("pcf: busy!\n"); #endif + PCF_UNLOCK(sc); return (IIC_EBUSBSY); } @@ -187,13 +194,30 @@ pcf_start(device_t dev, u_char slave, int timeout) goto error; } + PCF_UNLOCK(sc); return (0); error: - pcf_stop(dev); + pcf_stop_locked(sc); + PCF_UNLOCK(sc); return (error); } +int +pcf_stop(device_t dev) +{ + struct pcf_softc *sc = DEVTOSOFTC(dev); + +#ifdef PCFDEBUG + device_printf(dev, " >> stop\n"); +#endif + PCF_LOCK(sc); + pcf_stop_locked(sc); + PCF_UNLOCK(sc); + + return (0); +} + void pcf_intr(void *arg) { @@ -201,6 +225,7 @@ pcf_intr(void *arg) char data, status, addr; char error = 0; + PCF_LOCK(sc); status = pcf_get_S1(sc); if (status & PIN) { @@ -288,6 +313,7 @@ pcf_intr(void *arg) } } while ((pcf_get_S1(sc) & PIN) == 0); + PCF_UNLOCK(sc); return; @@ -296,6 +322,7 @@ pcf_intr(void *arg) pcf_set_S1(sc, PIN|ESO|ENI|ACK); sc->pcf_slave_mode = SLAVE_RECEIVER; + PCF_UNLOCK(sc); return; } @@ -305,6 +332,7 @@ pcf_rst_card(device_t dev, u_char speed, u_char addr, u_char *oldaddr) { struct pcf_softc *sc = DEVTOSOFTC(dev); + PCF_LOCK(sc); if (oldaddr) *oldaddr = sc->pcf_addr; @@ -343,6 +371,7 @@ pcf_rst_card(device_t dev, u_char speed, u_char addr, u_char *oldaddr) pcf_set_S1(sc, PIN|ESO|ENI|ACK); sc->pcf_slave_mode = SLAVE_RECEIVER; + PCF_UNLOCK(sc); return (0); } @@ -359,6 +388,7 @@ pcf_write(device_t dev, char *buf, int len, int *sent, int timeout /* us */) #endif bytes = 0; + PCF_LOCK(sc); while (len) { pcf_set_S0(sc, *buf++); @@ -379,6 +409,7 @@ pcf_write(device_t dev, char *buf, int len, int *sent, int timeout /* us */) error: *sent = bytes; + PCF_UNLOCK(sc); #ifdef PCFDEBUG device_printf(dev, " >> %d bytes written (%d)\n", bytes, error); @@ -399,6 +430,7 @@ pcf_read(device_t dev, char *buf, int len, int *read, int last, device_printf(dev, " << reading %d bytes\n", len); #endif + PCF_LOCK(sc); /* trig the bus to get the first data byte in S0 */ if (len) { if (len == 1 && last) @@ -415,14 +447,14 @@ pcf_read(device_t dev, char *buf, int len, int *read, int last, /* wait for trigged byte */ if ((error = pcf_wait_byte(sc))) { - pcf_stop(dev); + pcf_stop_locked(sc); goto error; } if (len == 1 && last) /* ok, last data byte already in S0, no I2C activity * on next pcf_get_S0() */ - pcf_stop(dev); + pcf_stop_locked(sc); else if (len == 2 && last) /* next trigged byte with no ack */ @@ -437,6 +469,7 @@ pcf_read(device_t dev, char *buf, int len, int *read, int last, error: *read = bytes; + PCF_UNLOCK(sc); #ifdef PCFDEBUG device_printf(dev, " << %d bytes read (%d): %#x%s\n", bytes, error, diff --git a/sys/dev/pcf/pcf_ebus.c b/sys/dev/pcf/pcf_ebus.c index e53e6d47fe0d..ad0e36e027ea 100644 --- a/sys/dev/pcf/pcf_ebus.c +++ b/sys/dev/pcf/pcf_ebus.c @@ -64,11 +64,13 @@ __FBSDID("$FreeBSD$"); */ #include -#include #include +#include #include #include +#include #include +#include #include #include @@ -142,7 +144,7 @@ pcf_ebus_attach(device_t dev) uint64_t own_addr; sc = DEVTOSOFTC(dev); - bzero(sc, sizeof(struct pcf_softc)); + mtx_init(&sc->pcf_lock, device_get_nameunit(dev), "pcf", MTX_DEF); /* get OFW node of the pcf */ if ((node = ofw_bus_get_node(dev)) <= 0) { @@ -157,8 +159,6 @@ pcf_ebus_attach(device_t dev) device_printf(dev, "cannot reserve I/O port range\n"); goto error; } - sc->bt_ioport = rman_get_bustag(sc->res_ioport); - sc->bh_ioport = rman_get_bushandle(sc->res_ioport); sc->pcf_flags = device_get_flags(dev); @@ -219,6 +219,7 @@ pcf_ebus_attach(device_t dev) bus_release_resource(dev, SYS_RES_MEMORY, sc->rid_ioport, sc->res_ioport); } + mtx_destroy(&sc->pcf_lock); return (rv); } @@ -245,6 +246,7 @@ pcf_ebus_detach(device_t dev) bus_release_resource(dev, SYS_RES_MEMORY, sc->rid_ioport, sc->res_ioport); + mtx_destroy(&sc->pcf_lock); return (0); } diff --git a/sys/dev/pcf/pcf_isa.c b/sys/dev/pcf/pcf_isa.c index 40064cc74bc3..3bb1ec6484d8 100644 --- a/sys/dev/pcf/pcf_isa.c +++ b/sys/dev/pcf/pcf_isa.c @@ -36,11 +36,13 @@ __FBSDID("$FreeBSD$"); */ #include -#include #include +#include #include #include +#include #include +#include #include #include @@ -126,7 +128,7 @@ pcf_isa_attach(device_t dev) int rv = ENXIO; sc = DEVTOSOFTC(dev); - bzero(sc, sizeof(struct pcf_softc)); + mtx_init(&sc->pcf_lock, device_get_nameunit(dev), "pcf", MTX_DEF); /* IO port is mandatory */ sc->res_ioport = bus_alloc_resource_any(dev, SYS_RES_IOPORT, @@ -135,8 +137,6 @@ pcf_isa_attach(device_t dev) device_printf(dev, "cannot reserve I/O port range\n"); goto error; } - sc->bt_ioport = rman_get_bustag(sc->res_ioport); - sc->bh_ioport = rman_get_bushandle(sc->res_ioport); sc->pcf_flags = device_get_flags(dev); @@ -179,6 +179,7 @@ pcf_isa_attach(device_t dev) bus_release_resource(dev, SYS_RES_IOPORT, sc->rid_ioport, sc->res_ioport); } + mtx_destroy(&sc->pcf_lock); return (rv); } @@ -202,6 +203,7 @@ pcf_isa_detach(device_t dev) } bus_release_resource(dev, SYS_RES_IOPORT, sc->rid_ioport, sc->res_ioport); + mtx_destroy(&sc->pcf_lock); return (0); } diff --git a/sys/dev/pcf/pcfvar.h b/sys/dev/pcf/pcfvar.h index ed4d9d8cb9a9..8e4d5d82ea2c 100644 --- a/sys/dev/pcf/pcfvar.h +++ b/sys/dev/pcf/pcfvar.h @@ -27,6 +27,9 @@ * $FreeBSD$ */ +#ifndef __PCFVAR_H__ +#define __PCFVAR_H__ + #define IO_PCFSIZE 2 #define TIMEOUT 9999 /* XXX */ @@ -63,19 +66,22 @@ struct pcf_softc { int pcf_slave_mode; /* receiver or transmitter */ int pcf_started; /* 1 if start condition sent */ + struct mtx pcf_lock; device_t iicbus; /* the corresponding iicbus */ /* Resource handling stuff. */ struct resource *res_ioport; int rid_ioport; - bus_space_tag_t bt_ioport; - bus_space_handle_t bh_ioport; struct resource *res_irq; int rid_irq; void *intr_cookie; }; #define DEVTOSOFTC(dev) ((struct pcf_softc *)device_get_softc(dev)) +#define PCF_LOCK(sc) mtx_lock(&(sc)->pcf_lock) +#define PCF_UNLOCK(sc) mtx_unlock(&(sc)->pcf_lock) +#define PCF_ASSERT_LOCKED(sc) mtx_assert(&(sc)->pcf_lock, MA_OWNED) + /* * PCF8584 datasheet : when operate at 8 MHz or more, a minimun time of * 6 clocks cycles must be left between two consecutives access @@ -92,7 +98,7 @@ static __inline void pcf_set_S0(struct pcf_softc *sc, int data) { - bus_space_write_1(sc->bt_ioport, sc->bh_ioport, 0, data); + bus_write_1(sc->res_ioport, 0, data); pcf_nops(); } @@ -100,7 +106,7 @@ static __inline void pcf_set_S1(struct pcf_softc *sc, int data) { - bus_space_write_1(sc->bt_ioport, sc->bh_ioport, 1, data); + bus_write_1(sc->res_ioport, 1, data); pcf_nops(); } @@ -109,7 +115,7 @@ pcf_get_S0(struct pcf_softc *sc) { char data; - data = bus_space_read_1(sc->bt_ioport, sc->bh_ioport, 0); + data = bus_read_1(sc->res_ioport, 0); pcf_nops(); return (data); @@ -120,7 +126,7 @@ pcf_get_S1(struct pcf_softc *sc) { char data; - data = bus_space_read_1(sc->bt_ioport, sc->bh_ioport, 1); + data = bus_read_1(sc->res_ioport, 1); pcf_nops(); return (data); @@ -138,3 +144,5 @@ extern driver_intr_t pcf_intr; #define PCF_MINVER 1 #define PCF_MAXVER 1 #define PCF_PREFVER PCF_MODVER + +#endif /* !__PCFVAR_H__ */ diff --git a/sys/dev/ppbus/lpbb.c b/sys/dev/ppbus/lpbb.c index 07a2f213a9fb..51d339897d42 100644 --- a/sys/dev/ppbus/lpbb.c +++ b/sys/dev/ppbus/lpbb.c @@ -36,10 +36,12 @@ __FBSDID("$FreeBSD$"); */ #include -#include -#include -#include #include +#include +#include +#include +#include +#include #include @@ -101,12 +103,16 @@ lpbb_callback(device_t dev, int index, caddr_t *data) case IIC_REQUEST_BUS: /* request the ppbus */ how = *(int *)data; + mtx_lock(&Giant); error = ppb_request_bus(ppbus, dev, how); + mtx_unlock(&Giant); break; case IIC_RELEASE_BUS: /* release the ppbus */ + mtx_lock(&Giant); error = ppb_release_bus(ppbus, dev); + mtx_unlock(&Giant); break; default: @@ -123,37 +129,56 @@ lpbb_callback(device_t dev, int index, caddr_t *data) #define ALIM 0x20 #define I2CKEY 0x50 -static int lpbb_getscl(device_t dev) +static int +lpbb_getscl(device_t dev) { - return ((ppb_rstr(device_get_parent(dev)) & SCL_in) == SCL_in); + int rval; + + mtx_lock(&Giant); + rval = ((ppb_rstr(device_get_parent(dev)) & SCL_in) == SCL_in); + mtx_unlock(&Giant); + return (rval); } -static int lpbb_getsda(device_t dev) +static int +lpbb_getsda(device_t dev) { - return ((ppb_rstr(device_get_parent(dev)) & SDA_in) == SDA_in); + int rval; + + mtx_lock(&Giant); + rval = ((ppb_rstr(device_get_parent(dev)) & SDA_in) == SDA_in); + mtx_unlock(&Giant); + return (rval); } -static void lpbb_setsda(device_t dev, char val) +static void +lpbb_setsda(device_t dev, char val) { device_t ppbus = device_get_parent(dev); - if(val==0) + mtx_lock(&Giant); + if (val == 0) ppb_wdtr(ppbus, (u_char)SDA_out); else ppb_wdtr(ppbus, (u_char)~SDA_out); + mtx_unlock(&Giant); } -static void lpbb_setscl(device_t dev, unsigned char val) +static void +lpbb_setscl(device_t dev, unsigned char val) { device_t ppbus = device_get_parent(dev); - if(val==0) - ppb_wctr(ppbus, (u_char)(ppb_rctr(ppbus)&~SCL_out)); + mtx_lock(&Giant); + if (val == 0) + ppb_wctr(ppbus, (u_char)(ppb_rctr(ppbus) & ~SCL_out)); else - ppb_wctr(ppbus, (u_char)(ppb_rctr(ppbus)|SCL_out)); + ppb_wctr(ppbus, (u_char)(ppb_rctr(ppbus) | SCL_out)); + mtx_unlock(&Giant); } -static int lpbb_detect(device_t dev) +static int +lpbb_detect(device_t dev) { device_t ppbus = device_get_parent(dev); @@ -183,6 +208,7 @@ lpbb_reset(device_t dev, u_char speed, u_char addr, u_char * oldaddr) { device_t ppbus = device_get_parent(dev); + mtx_lock(&Giant); if (ppb_request_bus(ppbus, dev, PPB_DONTWAIT)) { device_printf(dev, "can't allocate ppbus\n"); return (0); @@ -193,6 +219,7 @@ lpbb_reset(device_t dev, u_char speed, u_char addr, u_char * oldaddr) lpbb_setscl(dev, 1); ppb_release_bus(ppbus, dev); + mtx_unlock(&Giant); return (IIC_ENOADDR); } @@ -226,6 +253,7 @@ static driver_t lpbb_driver = { }; DRIVER_MODULE(lpbb, ppbus, lpbb_driver, lpbb_devclass, 0, 0); +DRIVER_MODULE(iicbb, lpbb, iicbb_driver, iicbb_devclass, 0, 0); MODULE_DEPEND(lpbb, ppbus, 1, 1, 1); MODULE_DEPEND(lpbb, iicbb, IICBB_MINVER, IICBB_PREFVER, IICBB_MAXVER); MODULE_VERSION(lpbb, 1); diff --git a/sys/pci/viapm.c b/sys/pci/viapm.c index 3448fbbe212f..e698b7727760 100644 --- a/sys/pci/viapm.c +++ b/sys/pci/viapm.c @@ -1009,6 +1009,7 @@ static driver_t viapropm_driver = { DRIVER_MODULE(viapm, pci, viapm_driver, viapm_devclass, 0, 0); DRIVER_MODULE(viapropm, pci, viapropm_driver, viapropm_devclass, 0, 0); +DRIVER_MODULE(iicbb, viapm, iicbb_driver, iicbb_devclass, 0, 0); DRIVER_MODULE(smbus, viapropm, smbus_driver, smbus_devclass, 0, 0); MODULE_DEPEND(viapm, pci, 1, 1, 1);