Commit ec607da7c2f2199a486f8df243f23f509f6ab5c0
1 parent
1dce7c3c
avoid recursive tx
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2050 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
14 additions
and
1 deletions
hw/pcnet.c
| @@ -57,6 +57,7 @@ struct PCNetState_st { | @@ -57,6 +57,7 @@ struct PCNetState_st { | ||
| 57 | uint64_t timer; | 57 | uint64_t timer; |
| 58 | int xmit_pos, recv_pos; | 58 | int xmit_pos, recv_pos; |
| 59 | uint8_t buffer[4096]; | 59 | uint8_t buffer[4096]; |
| 60 | + int tx_busy; | ||
| 60 | }; | 61 | }; |
| 61 | 62 | ||
| 62 | #ifdef __GNUC__ | 63 | #ifdef __GNUC__ |
| @@ -659,6 +660,8 @@ static void pcnet_s_reset(PCNetState *s) | @@ -659,6 +660,8 @@ static void pcnet_s_reset(PCNetState *s) | ||
| 659 | s->csr[114] = 0x0000; | 660 | s->csr[114] = 0x0000; |
| 660 | s->csr[122] = 0x0000; | 661 | s->csr[122] = 0x0000; |
| 661 | s->csr[124] = 0x0000; | 662 | s->csr[124] = 0x0000; |
| 663 | + | ||
| 664 | + s->tx_busy = 0; | ||
| 662 | } | 665 | } |
| 663 | 666 | ||
| 664 | static void pcnet_update_irq(PCNetState *s) | 667 | static void pcnet_update_irq(PCNetState *s) |
| @@ -1104,7 +1107,9 @@ static void pcnet_transmit(PCNetState *s) | @@ -1104,7 +1107,9 @@ static void pcnet_transmit(PCNetState *s) | ||
| 1104 | s->csr[0] &= ~0x0008; | 1107 | s->csr[0] &= ~0x0008; |
| 1105 | return; | 1108 | return; |
| 1106 | } | 1109 | } |
| 1107 | - | 1110 | + |
| 1111 | + s->tx_busy = 1; | ||
| 1112 | + | ||
| 1108 | txagain: | 1113 | txagain: |
| 1109 | if (pcnet_tdte_poll(s)) { | 1114 | if (pcnet_tdte_poll(s)) { |
| 1110 | struct pcnet_TMD tmd; | 1115 | struct pcnet_TMD tmd; |
| @@ -1167,6 +1172,8 @@ static void pcnet_transmit(PCNetState *s) | @@ -1167,6 +1172,8 @@ static void pcnet_transmit(PCNetState *s) | ||
| 1167 | if (count--) | 1172 | if (count--) |
| 1168 | goto txagain; | 1173 | goto txagain; |
| 1169 | } | 1174 | } |
| 1175 | + | ||
| 1176 | + s->tx_busy = 0; | ||
| 1170 | } | 1177 | } |
| 1171 | 1178 | ||
| 1172 | static void pcnet_poll(PCNetState *s) | 1179 | static void pcnet_poll(PCNetState *s) |
| @@ -1177,7 +1184,13 @@ static void pcnet_poll(PCNetState *s) | @@ -1177,7 +1184,13 @@ static void pcnet_poll(PCNetState *s) | ||
| 1177 | 1184 | ||
| 1178 | if (CSR_TDMD(s) || | 1185 | if (CSR_TDMD(s) || |
| 1179 | (CSR_TXON(s) && !CSR_DPOLL(s) && pcnet_tdte_poll(s))) | 1186 | (CSR_TXON(s) && !CSR_DPOLL(s) && pcnet_tdte_poll(s))) |
| 1187 | + { | ||
| 1188 | + /* prevent recursion */ | ||
| 1189 | + if (s->tx_busy) | ||
| 1190 | + return; | ||
| 1191 | + | ||
| 1180 | pcnet_transmit(s); | 1192 | pcnet_transmit(s); |
| 1193 | + } | ||
| 1181 | } | 1194 | } |
| 1182 | 1195 | ||
| 1183 | static void pcnet_poll_timer(void *opaque) | 1196 | static void pcnet_poll_timer(void *opaque) |