From 08649f593c19e3ee564fbff6582ac8d14d9b664b Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Fri, 1 Aug 2008 20:39:18 +0000 Subject: - Use an sx lock to serialize writes since they update the checksum. - Remove D_NEEDGIANT as the rtc drivers already have their own locks, so this doesn't need Giant. MFC after: 1 week --- sys/dev/nvram/nvram.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'sys/dev') diff --git a/sys/dev/nvram/nvram.c b/sys/dev/nvram/nvram.c index 12b6cd431e55..164287ef097a 100644 --- a/sys/dev/nvram/nvram.c +++ b/sys/dev/nvram/nvram.c @@ -31,7 +31,9 @@ #include #include #include +#include #include +#include #include #include @@ -63,10 +65,10 @@ static d_read_t nvram_read; static d_write_t nvram_write; static struct cdev *nvram_dev; +static struct sx nvram_lock; static struct cdevsw nvram_cdevsw = { .d_version = D_VERSION, - .d_flags = D_NEEDGIANT, .d_open = nvram_open, .d_read = nvram_read, .d_write = nvram_write, @@ -113,18 +115,24 @@ nvram_write(struct cdev *dev, struct uio *uio, int flags) int i; uint16_t sum; + sx_xlock(&nvram_lock); + /* Assert that we understand the existing checksum first! */ sum = rtcin(NVRAM_FIRST + CKSUM_MSB) << 8 | rtcin(NVRAM_FIRST + CKSUM_LSB); for (i = CKSUM_FIRST; i <= CKSUM_LAST; i++) sum -= rtcin(NVRAM_FIRST + i); - if (sum != 0) + if (sum != 0) { + sx_xunlock(&nvram_lock); return (EIO); + } /* Bring in user data and write */ while (uio->uio_resid > 0 && error == 0) { nv_off = uio->uio_offset + NVRAM_FIRST; - if (nv_off < NVRAM_FIRST || nv_off >= NVRAM_LAST) + if (nv_off < NVRAM_FIRST || nv_off >= NVRAM_LAST) { + sx_xunlock(&nvram_lock); return (0); /* Signal EOF */ + } /* Single byte at a time */ error = uiomove(&v, 1, uio); writertc(nv_off, v); @@ -135,6 +143,7 @@ nvram_write(struct cdev *dev, struct uio *uio, int flags) sum += rtcin(NVRAM_FIRST + i); writertc(NVRAM_FIRST + CKSUM_MSB, sum >> 8); writertc(NVRAM_FIRST + CKSUM_LSB, sum); + sx_xunlock(&nvram_lock); return (error); } @@ -143,12 +152,14 @@ nvram_modevent(module_t mod __unused, int type, void *data __unused) { switch (type) { case MOD_LOAD: + sx_init(&nvram_lock, "nvram"); nvram_dev = make_dev(&nvram_cdevsw, 0, UID_ROOT, GID_KMEM, 0640, "nvram"); break; case MOD_UNLOAD: case MOD_SHUTDOWN: destroy_dev(nvram_dev); + sx_destroy(&nvram_lock); break; default: return (EOPNOTSUPP); -- cgit v1.3