diff options
Diffstat (limited to 'drivers/net/ps3_gelic_net.c')
-rw-r--r-- | drivers/net/ps3_gelic_net.c | 45 |
1 files changed, 37 insertions, 8 deletions
diff --git a/drivers/net/ps3_gelic_net.c b/drivers/net/ps3_gelic_net.c index d596df987585..13d1c0a2a25f 100644 --- a/drivers/net/ps3_gelic_net.c +++ b/drivers/net/ps3_gelic_net.c @@ -917,31 +917,60 @@ static int gelic_net_decode_one_descr(struct gelic_net_card *card) goto refill; } - if ((status != GELIC_NET_DESCR_COMPLETE) && - (status != GELIC_NET_DESCR_FRAME_END)) { + if (status == GELIC_NET_DESCR_BUFFER_FULL) { + /* + * Buffer full would occur if and only if + * the frame length was longer than the size of this + * descriptor's buffer. If the frame length was equal + * to or shorter than buffer'size, FRAME_END condition + * would occur. + * Anyway this frame was longer than the MTU, + * just drop it. + */ + dev_info(ctodev(card), "overlength frame\n"); + goto refill; + } + /* + * descriptoers any other than FRAME_END here should + * be treated as error. + */ + if (status != GELIC_NET_DESCR_FRAME_END) { dev_dbg(ctodev(card), "RX descriptor with state %x\n", status); goto refill; } /* ok, we've got a packet in descr */ - gelic_net_pass_skb_up(descr, card); /* 1: skb_up sccess */ - + gelic_net_pass_skb_up(descr, card); refill: - descr->next_descr_addr = 0; /* unlink the descr */ + /* + * So that always DMAC can see the end + * of the descriptor chain to avoid + * from unwanted DMAC overrun. + */ + descr->next_descr_addr = 0; /* change the descriptor state: */ gelic_net_set_descr_status(descr, GELIC_NET_DESCR_NOT_IN_USE); - /* refill one desc - * FIXME: this can fail, but for now, just leave this - * descriptor without skb + /* + * this call can fail, but for now, just leave this + * decriptor without skb */ gelic_net_prepare_rx_descr(card, descr); + chain->head = descr; chain->tail = descr->next; + + /* + * Set this descriptor the end of the chain. + */ descr->prev->next_descr_addr = descr->bus_addr; + /* + * If dmac chain was met, DMAC stopped. + * thus re-enable it + */ if (dmac_chain_ended) { card->rx_dma_restart_required = 1; dev_dbg(ctodev(card), "reenable rx dma scheduled\n"); |