Skip to content

Commit

Permalink
net/ps3: Fix gelic RX DMA restart
Browse files Browse the repository at this point in the history
Fix the condition where PS3 network RX hangs when no network
TX is occurring by calling gelic_card_enable_rxdmac() during
RX_DMA_CHAIN_END event processing.

The gelic hardware automatically clears its RX_DMA_EN flag when
it detects an RX_DMA_CHAIN_END event.  In its processing of
RX_DMA_CHAIN_END the gelic driver is required to set RX_DMA_EN
(with a call to gelic_card_enable_rxdmac()) to restart RX DMA
transfers.  The existing gelic driver code does not set
RX_DMA_EN directly in its processing of the RX_DMA_CHAIN_END
event, but uses a flag variable card->rx_dma_restart_required
to schedule the setting of RX_DMA_EN until next inside the
interrupt handler.

It seems this delayed setting of RX_DMA_EN causes the hang since
the next RX interrupt after the RX_DMA_CHAIN_END event where
RX_DMA_EN is scheduled to be set will not occur since RX_DMA_EN
was not set.  In the case were network TX is occuring, RX_DMA_EN
is set in the next TX interrupt and RX processing continues.

Signed-off-by: Geoff Levand <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
glevand authored and davem330 committed Jul 14, 2011
1 parent 6383c0b commit ecae42d
Show file tree
Hide file tree
Showing 2 changed files with 8 additions and 14 deletions.
21 changes: 8 additions & 13 deletions drivers/net/ps3_gelic_net.c
Original file line number Diff line number Diff line change
Expand Up @@ -993,10 +993,6 @@ static int gelic_card_decode_one_descr(struct gelic_card *card)
int dmac_chain_ended;

status = gelic_descr_get_status(descr);
/* is this descriptor terminated with next_descr == NULL? */
dmac_chain_ended =
be32_to_cpu(descr->dmac_cmd_status) &
GELIC_DESCR_RX_DMA_CHAIN_END;

if (status == GELIC_DESCR_DMA_CARDOWNED)
return 0;
Expand Down Expand Up @@ -1059,6 +1055,11 @@ static int gelic_card_decode_one_descr(struct gelic_card *card)
/* ok, we've got a packet in descr */
gelic_net_pass_skb_up(descr, card, netdev);
refill:

/* is the current descriptor terminated with next_descr == NULL? */
dmac_chain_ended =
be32_to_cpu(descr->dmac_cmd_status) &
GELIC_DESCR_RX_DMA_CHAIN_END;
/*
* So that always DMAC can see the end
* of the descriptor chain to avoid
Expand Down Expand Up @@ -1087,10 +1088,9 @@ static int gelic_card_decode_one_descr(struct gelic_card *card)
* 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");
}

if (dmac_chain_ended)
gelic_card_enable_rxdmac(card);

return 1;
}
Expand Down Expand Up @@ -1156,11 +1156,6 @@ static irqreturn_t gelic_card_interrupt(int irq, void *ptr)

status &= card->irq_mask;

if (card->rx_dma_restart_required) {
card->rx_dma_restart_required = 0;
gelic_card_enable_rxdmac(card);
}

if (status & GELIC_CARD_RXINT) {
gelic_card_rx_irq_off(card);
napi_schedule(&card->napi);
Expand Down
1 change: 0 additions & 1 deletion drivers/net/ps3_gelic_net.h
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,6 @@ struct gelic_card {

struct gelic_descr_chain tx_chain;
struct gelic_descr_chain rx_chain;
int rx_dma_restart_required;
/*
* tx_lock guards tx descriptor list and
* tx_dma_progress.
Expand Down

0 comments on commit ecae42d

Please sign in to comment.