aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2012-05-29 19:33:20 -0700
committerH. Peter Anvin <hpa@zytor.com>2012-05-29 19:33:20 -0700
commit7699e996c613e51049e0bad6ade32215ac263289 (patch)
treedd30bd90519c6eb731440580898fbbd8910c98b9
parent4645f42100d2d11fa0281dbdc5431882e4cac69b (diff)
downloadsyslinux-7699e996c613e51049e0bad6ade32215ac263289.tar.gz
syslinux-7699e996c613e51049e0bad6ade32215ac263289.tar.xz
syslinux-7699e996c613e51049e0bad6ade32215ac263289.zip
pxe: always start the idle thread, in case we need itsyslinux-4.10-pre21
Always start the idle thread, but leave it blocked unless we have an indication that interrupts are not working. Signed-off-by: H. Peter Anvin <hpa@zytor.com>
-rw-r--r--core/fs/pxe/isr.c36
-rw-r--r--core/pxeisr.inc7
-rw-r--r--core/thread/idle_thread.c7
3 files changed, 39 insertions, 11 deletions
diff --git a/core/fs/pxe/isr.c b/core/fs/pxe/isr.c
index e2bf2f67..69cfe9f1 100644
--- a/core/fs/pxe/isr.c
+++ b/core/fs/pxe/isr.c
@@ -13,8 +13,9 @@
#include <sys/io.h>
extern uint8_t pxe_irq_pending;
-extern volatile uint8_t pxe_irq_timeout;
+extern volatile uint8_t pxe_need_poll;
static DECLARE_INIT_SEMAPHORE(pxe_receive_thread_sem, 0);
+static DECLARE_INIT_SEMAPHORE(pxe_poll_thread_sem, 0);
static struct thread *pxe_thread, *poll_thread;
/*
@@ -26,6 +27,7 @@ static bool install_irq_vector(uint8_t irq, void (*isr)(void), far_ptr_t *old)
unsigned int vec;
uint8_t mask, mymask;
uint32_t now;
+ bool ok;
if (irq < 8)
vec = irq + 0x08;
@@ -36,6 +38,11 @@ static bool install_irq_vector(uint8_t irq, void (*isr)(void), far_ptr_t *old)
cli();
+ if (pxe_need_poll) {
+ sti();
+ return false;
+ }
+
entry = (far_ptr_t *)(vec << 2);
*old = *entry;
entry->ptr = (uint32_t)isr;
@@ -60,16 +67,16 @@ static bool install_irq_vector(uint8_t irq, void (*isr)(void), far_ptr_t *old)
now = jiffies();
/* Some time to watch for stuck interrupts */
- while (jiffies() - now < 4 && !pxe_irq_timeout)
+ while (jiffies() - now < 4 && (ok = !pxe_need_poll))
hlt();
- if (pxe_irq_timeout)
+ if (!ok)
*entry = *old; /* Restore the old vector */
printf("UNDI: IRQ %d(0x%02x): %04x:%04x -> %04x:%04x\n", irq, vec,
old->seg, old->offs, entry->seg, entry->offs);
- return !pxe_irq_timeout;
+ return ok;
}
static bool uninstall_irq_vector(uint8_t irq, void (*isr), far_ptr_t *old)
@@ -108,6 +115,12 @@ static void pxe_poll_wakeups(void)
static jiffies_t last_jiffies = 0;
jiffies_t now = jiffies();
+ if (pxe_need_poll == 1) {
+ /* If we need polling now, activate polling */
+ pxe_need_poll = 3;
+ sem_up(&pxe_poll_thread_sem);
+ }
+
if (now != last_jiffies) {
last_jiffies = now;
__thread_process_timeouts();
@@ -183,11 +196,15 @@ static void pxe_poll_thread(void *dummy)
{
(void)dummy;
+ /* Block indefinitely unless activated */
+ sem_down(&pxe_poll_thread_sem, 0);
+
for (;;) {
cli();
if (pxe_receive_thread_sem.count < 0 && pxe_isr_poll())
sem_up(&pxe_receive_thread_sem);
- __schedule();
+ else
+ __schedule();
sti();
cpu_relax();
}
@@ -206,9 +223,10 @@ void pxe_init_isr(void)
* avoid packet loss we need to move it into memory that we ourselves
* manage, as soon as possible.
*/
+ core_pm_hook = __schedule;
+
pxe_thread = start_thread("pxe receive", 16384, -20,
pxe_receive_thread, NULL);
- core_pm_hook = __schedule;
}
/*
@@ -230,9 +248,11 @@ void pxe_start_isr(void)
irq = 0; /* Install failed or stuck interrupt */
}
+ poll_thread = start_thread("pxe poll", 4096, POLL_THREAD_PRIORITY,
+ pxe_poll_thread, NULL);
+
if (!irq || !(pxe_undi_iface.ServiceFlags & PXE_UNDI_IFACE_FLAG_IRQ))
- poll_thread = start_thread("pxe poll", 4096, POLL_THREAD_PRIORITY,
- pxe_poll_thread, NULL);
+ pxe_need_poll |= 1;
}
int reset_pxe(void)
diff --git a/core/pxeisr.inc b/core/pxeisr.inc
index 6f9844e0..5bcb9244 100644
--- a/core/pxeisr.inc
+++ b/core/pxeisr.inc
@@ -95,7 +95,7 @@ pxe_irq_chain equ $-4
in al,dx
or al,ch
out dx,al
- mov byte [pxe_irq_timeout],1
+ or byte [pxe_need_poll],1
jmp .exit
@@ -162,7 +162,8 @@ pxeirq_count resw 1
pxe_irq_vector resb 1 ; PXE IRQ vector
global pxe_irq_pending
pxe_irq_pending resb 1 ; IRQ pending flag
- global pxe_irq_timeout
-pxe_irq_timeout resb 1 ; Stuck IRQs, disabled timeout
+ global pxe_need_poll
+pxe_need_poll resb 1 ; Bit 0 = need polling
+ ; Bit 1 = polling active
section .text16
diff --git a/core/thread/idle_thread.c b/core/thread/idle_thread.c
index 4555333a..8faa0719 100644
--- a/core/thread/idle_thread.c
+++ b/core/thread/idle_thread.c
@@ -2,12 +2,19 @@
#include <limits.h>
#include <sys/cpu.h>
+static void default_idle_thread_hook(void)
+{
+}
+
+void (*idle_thread_hook)(void) = default_idle_thread_hook;
+
static void idle_thread_func(void *dummy)
{
(void)dummy;
for (;;) {
cli();
+ idle_thread_hook();
__schedule();
asm volatile("sti ; hlt" : : : "memory");
}