mirror of
https://github.com/AsahiLinux/m1n1
synced 2024-11-10 01:34:12 +00:00
iodev: Protect iodevs with spinlocks
This makes SMP IRQ reports less flaky Signed-off-by: Hector Martin <marcan@marcan.st>
This commit is contained in:
parent
85ca5b94cb
commit
a383ef0b5a
7 changed files with 61 additions and 11 deletions
1
src/fb.c
1
src/fb.c
|
@ -301,6 +301,7 @@ const struct iodev_ops iodev_fb_ops = {
|
|||
struct iodev iodev_fb = {
|
||||
.ops = &iodev_fb_ops,
|
||||
.usage = USAGE_CONSOLE,
|
||||
.lock = SPINLOCK_INIT,
|
||||
};
|
||||
|
||||
static void fb_clear_console(void)
|
||||
|
|
52
src/iodev.c
52
src/iodev.c
|
@ -36,7 +36,10 @@ ssize_t iodev_can_read(iodev_id_t id)
|
|||
if (!iodevs[id]->ops->can_read)
|
||||
return 0;
|
||||
|
||||
return iodevs[id]->ops->can_read(iodevs[id]->opaque);
|
||||
spin_lock(&iodevs[id]->lock);
|
||||
ssize_t ret = iodevs[id]->ops->can_read(iodevs[id]->opaque);
|
||||
spin_unlock(&iodevs[id]->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool iodev_can_write(iodev_id_t id)
|
||||
|
@ -44,7 +47,12 @@ bool iodev_can_write(iodev_id_t id)
|
|||
if (!iodevs[id]->ops->can_write)
|
||||
return false;
|
||||
|
||||
return iodevs[id]->ops->can_write(iodevs[id]->opaque);
|
||||
if (mmu_active())
|
||||
spin_lock(&iodevs[id]->lock);
|
||||
bool ret = iodevs[id]->ops->can_write(iodevs[id]->opaque);
|
||||
if (mmu_active())
|
||||
spin_unlock(&iodevs[id]->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssize_t iodev_read(iodev_id_t id, void *buf, size_t length)
|
||||
|
@ -52,7 +60,10 @@ ssize_t iodev_read(iodev_id_t id, void *buf, size_t length)
|
|||
if (!iodevs[id]->ops->read)
|
||||
return -1;
|
||||
|
||||
return iodevs[id]->ops->read(iodevs[id]->opaque, buf, length);
|
||||
spin_lock(&iodevs[id]->lock);
|
||||
ssize_t ret = iodevs[id]->ops->read(iodevs[id]->opaque, buf, length);
|
||||
spin_unlock(&iodevs[id]->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssize_t iodev_write(iodev_id_t id, const void *buf, size_t length)
|
||||
|
@ -60,7 +71,12 @@ ssize_t iodev_write(iodev_id_t id, const void *buf, size_t length)
|
|||
if (!iodevs[id]->ops->write)
|
||||
return -1;
|
||||
|
||||
return iodevs[id]->ops->write(iodevs[id]->opaque, buf, length);
|
||||
if (mmu_active())
|
||||
spin_lock(&iodevs[id]->lock);
|
||||
ssize_t ret = iodevs[id]->ops->write(iodevs[id]->opaque, buf, length);
|
||||
if (mmu_active())
|
||||
spin_unlock(&iodevs[id]->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssize_t iodev_queue(iodev_id_t id, const void *buf, size_t length)
|
||||
|
@ -68,7 +84,10 @@ ssize_t iodev_queue(iodev_id_t id, const void *buf, size_t length)
|
|||
if (!iodevs[id]->ops->queue)
|
||||
return iodev_write(id, buf, length);
|
||||
|
||||
return iodevs[id]->ops->queue(iodevs[id]->opaque, buf, length);
|
||||
spin_lock(&iodevs[id]->lock);
|
||||
ssize_t ret = iodevs[id]->ops->queue(iodevs[id]->opaque, buf, length);
|
||||
spin_unlock(&iodevs[id]->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void iodev_flush(iodev_id_t id)
|
||||
|
@ -76,7 +95,9 @@ void iodev_flush(iodev_id_t id)
|
|||
if (!iodevs[id]->ops->flush)
|
||||
return;
|
||||
|
||||
spin_lock(&iodevs[id]->lock);
|
||||
iodevs[id]->ops->flush(iodevs[id]->opaque);
|
||||
spin_unlock(&iodevs[id]->lock);
|
||||
}
|
||||
|
||||
int in_iodev = 0;
|
||||
|
@ -89,8 +110,8 @@ void iodev_console_write(const void *buf, size_t length)
|
|||
|
||||
if (!do_lock && !is_primary_core()) {
|
||||
if (length && iodevs[IODEV_UART]->usage & USAGE_CONSOLE) {
|
||||
iodev_write(IODEV_UART, "*", 1);
|
||||
iodev_write(IODEV_UART, buf, length);
|
||||
iodevs[IODEV_UART]->ops->write(iodevs[IODEV_UART]->opaque, "*", 1);
|
||||
iodevs[IODEV_UART]->ops->write(iodevs[IODEV_UART]->opaque, buf, length);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -100,8 +121,8 @@ void iodev_console_write(const void *buf, size_t length)
|
|||
|
||||
if (in_iodev) {
|
||||
if (length && iodevs[IODEV_UART]->usage & USAGE_CONSOLE) {
|
||||
iodev_write(IODEV_UART, "*", 1);
|
||||
iodev_write(IODEV_UART, buf, length);
|
||||
iodevs[IODEV_UART]->ops->write(iodevs[IODEV_UART]->opaque, "+", 1);
|
||||
iodevs[IODEV_UART]->ops->write(iodevs[IODEV_UART]->opaque, buf, length);
|
||||
}
|
||||
if (do_lock)
|
||||
spin_unlock(&console_lock);
|
||||
|
@ -183,8 +204,16 @@ void iodev_console_write(const void *buf, size_t length)
|
|||
|
||||
void iodev_handle_events(iodev_id_t id)
|
||||
{
|
||||
if (in_iodev)
|
||||
bool do_lock = mmu_active();
|
||||
|
||||
if (do_lock)
|
||||
spin_lock(&console_lock);
|
||||
|
||||
if (in_iodev) {
|
||||
if (do_lock)
|
||||
spin_unlock(&console_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
in_iodev++;
|
||||
|
||||
|
@ -195,6 +224,9 @@ void iodev_handle_events(iodev_id_t id)
|
|||
|
||||
if (iodev_can_write(id))
|
||||
iodev_console_write(NULL, 0);
|
||||
|
||||
if (do_lock)
|
||||
spin_unlock(&console_lock);
|
||||
}
|
||||
|
||||
void iodev_console_kick(void)
|
||||
|
|
|
@ -34,6 +34,7 @@ struct iodev_ops {
|
|||
struct iodev {
|
||||
const struct iodev_ops *ops;
|
||||
|
||||
spinlock_t lock;
|
||||
iodev_usage_t usage;
|
||||
void *opaque;
|
||||
};
|
||||
|
|
|
@ -176,4 +176,5 @@ static struct iodev_ops iodev_uart_ops = {
|
|||
struct iodev iodev_uart = {
|
||||
.ops = &iodev_uart_ops,
|
||||
.usage = USAGE_CONSOLE | USAGE_UARTPROXY,
|
||||
.lock = SPINLOCK_INIT,
|
||||
};
|
||||
|
|
|
@ -210,10 +210,12 @@ struct iodev iodev_usb[USB_INSTANCES] = {
|
|||
{
|
||||
.ops = &iodev_usb_ops,
|
||||
.usage = USAGE_CONSOLE | USAGE_UARTPROXY,
|
||||
.lock = SPINLOCK_INIT,
|
||||
},
|
||||
{
|
||||
.ops = &iodev_usb_ops,
|
||||
.usage = USAGE_CONSOLE | USAGE_UARTPROXY,
|
||||
.lock = SPINLOCK_INIT,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -221,10 +223,12 @@ struct iodev iodev_usb_sec[USB_INSTANCES] = {
|
|||
{
|
||||
.ops = &iodev_usb_sec_ops,
|
||||
.usage = 0,
|
||||
.lock = SPINLOCK_INIT,
|
||||
},
|
||||
{
|
||||
.ops = &iodev_usb_sec_ops,
|
||||
.usage = 0,
|
||||
.lock = SPINLOCK_INIT,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -102,6 +102,12 @@ void flush_and_reboot(void)
|
|||
reboot();
|
||||
}
|
||||
|
||||
void spin_init(spinlock_t *lock)
|
||||
{
|
||||
lock->lock = -1;
|
||||
lock->count = 0;
|
||||
}
|
||||
|
||||
void spin_lock(spinlock_t *lock)
|
||||
{
|
||||
s64 me = smp_id();
|
||||
|
|
|
@ -371,8 +371,13 @@ typedef struct {
|
|||
int count;
|
||||
} spinlock_t ALIGNED(64);
|
||||
|
||||
#define DECLARE_SPINLOCK(n) spinlock_t n = {-1, 0}
|
||||
#define SPINLOCK_INIT \
|
||||
{ \
|
||||
-1, 0 \
|
||||
}
|
||||
#define DECLARE_SPINLOCK(n) spinlock_t n = SPINLOCK_INIT;
|
||||
|
||||
void spin_init(spinlock_t *lock);
|
||||
void spin_lock(spinlock_t *lock);
|
||||
void spin_unlock(spinlock_t *lock);
|
||||
|
||||
|
|
Loading…
Reference in a new issue