aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2012-05-29 21:02:09 -0700
committerH. Peter Anvin <hpa@zytor.com>2012-05-29 21:02:09 -0700
commit6d8a787f6795a40cd4b285ee5fda78306d51b55d (patch)
tree28c043613cd476a67fda92e2de722e3b191edfa1
parent7699e996c613e51049e0bad6ade32215ac263289 (diff)
downloadsyslinux-6d8a787f6795a40cd4b285ee5fda78306d51b55d.tar.gz
syslinux-6d8a787f6795a40cd4b285ee5fda78306d51b55d.tar.xz
syslinux-6d8a787f6795a40cd4b285ee5fda78306d51b55d.zip
pxe: force polling on if we receive no interrupts
Some PXE stacks will claim to support interrupts and don't. If 3 seconds after the first packet transmission we still have not received any interrupt at all, activate the polling thread. Signed-off-by: H. Peter Anvin <hpa@zytor.com>
-rw-r--r--core/lwip/src/netif/undiif.c16
-rw-r--r--core/pxeisr.inc13
2 files changed, 24 insertions, 5 deletions
diff --git a/core/lwip/src/netif/undiif.c b/core/lwip/src/netif/undiif.c
index fbb0a853..b82b6f32 100644
--- a/core/lwip/src/netif/undiif.c
+++ b/core/lwip/src/netif/undiif.c
@@ -286,6 +286,9 @@ low_level_init(struct netif *netif)
* to become availale since the stack doesn't retry to send a packet
* dropped because of memory failure (except for the TCP timers).
*/
+extern volatile uint32_t pxe_irq_count;
+extern volatile uint8_t pxe_need_poll;
+
static err_t
undi_transmit(struct netif *netif, struct pbuf *pbuf,
hwaddr_t *dest, uint16_t undi_protocol)
@@ -297,11 +300,24 @@ undi_transmit(struct netif *netif, struct pbuf *pbuf,
static __lowmem struct pxe_xmit pxe;
static __lowmem hwaddr_t low_dest;
static __lowmem char pkt_buf[PKTBUF_SIZE];
+ uint32_t now;
+ static uint32_t first_xmit;
/* Drop jumbo frames */
if ((pbuf->tot_len > sizeof(pkt_buf)) || (pbuf->tot_len > netif->mtu))
return ERR_ARG;
+ if (__unlikely(!pxe_irq_count)) {
+ now = ms_timer();
+ if (!first_xmit) {
+ first_xmit = now;
+ } else if (now - first_xmit > 3000) {
+ /* 3 seconds after first transmit, and no interrupts */
+ pxe_need_poll |= 1;
+ pxe_irq_count++; /* We don't need to do this again... */
+ }
+ }
+
pbuf_copy_partial( pbuf, pkt_buf, pbuf->tot_len, 0);
if (dest)
memcpy(low_dest, dest, netif->hwaddr_len);
diff --git a/core/pxeisr.inc b/core/pxeisr.inc
index 5bcb9244..93c73ed5 100644
--- a/core/pxeisr.inc
+++ b/core/pxeisr.inc
@@ -39,6 +39,7 @@ pxe_isr:
; We need to EOI this ourselves, so that the
; leftover BC doesn't get control.
mov byte [pxe_irq_pending],1
+ inc dword [pxe_irq_count]
cmp byte [pxe_irq_vector], 8
mov al,0x20 ; Non-specific EOI
@@ -49,7 +50,7 @@ pxe_isr:
out 0x20,al ; Primary PIC
mov [pxeirq_last],ax
- mov word [pxeirq_count],PXEIRQ_MAX
+ mov word [pxeirq_deadman],PXEIRQ_MAX
.exit:
pop gs
@@ -62,7 +63,7 @@ pxe_isr:
.notus:
cmp ax,[pxeirq_last]
jne .reset_timeout
- dec word [pxeirq_count]
+ dec word [pxeirq_deadman]
jz .timeout
.chain:
@@ -77,7 +78,7 @@ pxe_irq_chain equ $-4
.reset_timeout:
mov [pxeirq_last],ax
- mov word [pxeirq_count],PXEIRQ_MAX
+ mov word [pxeirq_deadman],PXEIRQ_MAX
jmp .chain
; Too many spurious interrupts, shut off the interrupts
@@ -154,10 +155,12 @@ pxenv_undi_isr_buf:
.pkttype: resb 1
.size equ $-pxenv_undi_isr_buf
- alignb 2
+ alignb 4
pxeirq_last resw 1
-pxeirq_count resw 1
+pxeirq_deadman resw 1
+ global pxe_irq_count
+pxe_irq_count resd 1 ; PXE IRQ counter
global pxe_irq_vector
pxe_irq_vector resb 1 ; PXE IRQ vector
global pxe_irq_pending