SHA256
1
0
forked from pool/dynamips
dynamips/dynamips-0.2.11_fix_mcast_queue.patch

121 lines
3.8 KiB
Diff

--- dynamips-0.2.11-source.orig/common/dev_gt.c 2014-03-02 15:22:17.881753020 +0100
+++ dynamips-0.2.11-source.patched/common/dev_gt.c 2014-03-02 15:15:55.467367795 +0100
@@ -2093,8 +2093,8 @@
int queue)
{
u_char pkt[GT_MAX_PKT_SIZE],*pkt_ptr;
- struct sdma_desc txd0,ctxd,*ptxd;
- m_uint32_t tx_start,tx_current;
+ struct sdma_desc ctxd;
+ m_uint32_t tx_current;
m_uint32_t len,tot_len;
int abort = FALSE;
@@ -2106,17 +2106,29 @@
return(FALSE);
/* Copy the current txring descriptor */
- tx_start = tx_current = port->tx_current[queue];
+ tx_current = port->tx_current[queue];
- if (!tx_start)
+ if (!tx_current)
return(FALSE);
- ptxd = &txd0;
- gt_sdma_desc_read(d,tx_start,ptxd);
+ gt_sdma_desc_read(d,tx_current,&ctxd);
/* If we don't own the first descriptor, we cannot transmit */
- if (!(txd0.cmd_stat & GT_TXDESC_OWN))
+ if (!(ctxd.cmd_stat & GT_TXDESC_OWN)) {
+ if (queue == 0) {
+ port->icr |= GT_ICR_TXENDL;
+ port->sdcmr |= GT_SDCMR_STDL;
+ port->sdcmr &= ~GT_SDCMR_TXDL;
+
+ } else {
+ port->icr |= GT_ICR_TXENDH;
+ port->sdcmr |= GT_SDCMR_STDH;
+ port->sdcmr &= ~GT_SDCMR_TXDH;
+ }
+
+ gt_eth_update_int_status(d,port);
return(FALSE);
+ }
/* Empty packet for now */
pkt_ptr = pkt;
@@ -2125,43 +2137,41 @@
for(;;) {
#if DEBUG_ETH_TX
GT_LOG(d,"gt_eth_handle_txqueue: loop: "
- "cmd_stat=0x%x, buf_size=0x%x, next_ptr=0x%x, buf_ptr=0x%x\n",
- ptxd->cmd_stat,ptxd->buf_size,ptxd->next_ptr,ptxd->buf_ptr);
+ "tx_current=0x%08x, cmd_stat=0x%08x, buf_size=0x%08x, next_ptr=0x%08x, buf_ptr=0x%08x\n",
+ tx_current, ctxd.cmd_stat, ctxd.buf_size, ctxd.next_ptr, ctxd.buf_ptr);
#endif
- if (!(ptxd->cmd_stat & GT_TXDESC_OWN)) {
+ if (!(ctxd.cmd_stat & GT_TXDESC_OWN)) {
GT_LOG(d,"gt_eth_handle_txqueue: descriptor not owned!\n");
abort = TRUE;
break;
}
/* Copy packet data to the buffer */
- len = (ptxd->buf_size & GT_TXDESC_BC_MASK) >> GT_TXDESC_BC_SHIFT;
+ len = (ctxd.buf_size & GT_TXDESC_BC_MASK) >> GT_TXDESC_BC_SHIFT;
- physmem_copy_from_vm(d->vm,pkt_ptr,ptxd->buf_ptr,len);
+ physmem_copy_from_vm(d->vm,pkt_ptr,ctxd.buf_ptr,len);
pkt_ptr += len;
tot_len += len;
- /* Clear the OWN bit if this is not the first descriptor */
- if (!(ptxd->cmd_stat & GT_TXDESC_F)) {
- ptxd->cmd_stat &= ~GT_TXDESC_OWN;
- physmem_copy_u32_to_vm(d->vm,tx_current,ptxd->cmd_stat);
+ /* Clear the OWN bit if this is not the last descriptor */
+ if (!(ctxd.cmd_stat & GT_TXDESC_L)) {
+ ctxd.cmd_stat &= ~GT_TXDESC_OWN;
+ physmem_copy_u32_to_vm(d->vm,tx_current+4,ctxd.cmd_stat);
}
- tx_current = ptxd->next_ptr;
-
/* Last descriptor or no more desc available ? */
- if (ptxd->cmd_stat & GT_TXDESC_L)
+ if (ctxd.cmd_stat & GT_TXDESC_L)
break;
- if (!tx_current) {
+ if (!(ctxd.next_ptr)) {
abort = TRUE;
break;
}
/* Fetch the next descriptor */
+ tx_current = ctxd.next_ptr;
gt_sdma_desc_read(d,tx_current,&ctxd);
- ptxd = &ctxd;
}
if ((tot_len != 0) && !abort) {
@@ -2180,11 +2190,11 @@
port->tx_frames++;
}
- /* Clear the OWN flag of the first descriptor */
- txd0.cmd_stat &= ~GT_TXDESC_OWN;
- physmem_copy_u32_to_vm(d->vm,tx_start+4,txd0.cmd_stat);
+ /* Clear the OWN flag of the last descriptor */
+ ctxd.cmd_stat &= ~GT_TXDESC_OWN;
+ physmem_copy_u32_to_vm(d->vm,tx_current+4,ctxd.cmd_stat);
- port->tx_current[queue] = tx_current;
+ port->tx_current[queue] = tx_current = ctxd.next_ptr;
/* Notify host about transmitted packet */
if (queue == 0)