Skip to content

Commit

Permalink
rtc: cmos: avoid taking rtc_lock for extended period of time
Browse files Browse the repository at this point in the history
On my device reading entirety of /sys/devices/pnp0/00:03/cmos_nvram0/nvmem
takes about 9 msec during which time interrupts are off on the CPU that
does the read and the thread that performs the read can not be migrated
or preempted by another higher priority thread (RT or not).

Allow readers and writers be preempted by taking and releasing rtc_lock
spinlock for each individual byte read or written rather than once per
read/write request.

Signed-off-by: Dmitry Torokhov <[email protected]>
Reviewed-by: Mateusz Jończyk <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Alexandre Belloni <[email protected]>
  • Loading branch information
dtor authored and alexandrebelloni committed Oct 31, 2024
1 parent d448837 commit 0a6efab
Showing 1 changed file with 15 additions and 16 deletions.
31 changes: 15 additions & 16 deletions drivers/rtc/rtc-cmos.c
Original file line number Diff line number Diff line change
Expand Up @@ -645,18 +645,17 @@ static int cmos_nvram_read(void *priv, unsigned int off, void *val,
unsigned char *buf = val;

off += NVRAM_OFFSET;
spin_lock_irq(&rtc_lock);
for (; count; count--, off++) {
for (; count; count--, off++, buf++) {
guard(spinlock_irq)(&rtc_lock);
if (off < 128)
*buf++ = CMOS_READ(off);
*buf = CMOS_READ(off);
else if (can_bank2)
*buf++ = cmos_read_bank2(off);
*buf = cmos_read_bank2(off);
else
break;
return -EIO;
}
spin_unlock_irq(&rtc_lock);

return count ? -EIO : 0;
return 0;
}

static int cmos_nvram_write(void *priv, unsigned int off, void *val,
Expand All @@ -671,23 +670,23 @@ static int cmos_nvram_write(void *priv, unsigned int off, void *val,
* NVRAM to update, updating checksums is also part of its job.
*/
off += NVRAM_OFFSET;
spin_lock_irq(&rtc_lock);
for (; count; count--, off++) {
for (; count; count--, off++, buf++) {
/* don't trash RTC registers */
if (off == cmos->day_alrm
|| off == cmos->mon_alrm
|| off == cmos->century)
buf++;
else if (off < 128)
CMOS_WRITE(*buf++, off);
continue;

guard(spinlock_irq)(&rtc_lock);
if (off < 128)
CMOS_WRITE(*buf, off);
else if (can_bank2)
cmos_write_bank2(*buf++, off);
cmos_write_bank2(*buf, off);
else
break;
return -EIO;
}
spin_unlock_irq(&rtc_lock);

return count ? -EIO : 0;
return 0;
}

/*----------------------------------------------------------------*/
Expand Down

0 comments on commit 0a6efab

Please sign in to comment.