drivers: eth: gmac: drop TX timeout handling

The current SAM E70 Ethernet driver sometimes get stuck if the stack
has to send 2 packets in a row, for example an ack for the just received
data + answer data.

The problem is the following one:
1) The first packet goes through eth_tx, one tx_desc_sem semaphore is
   taken, and the tx_timeout_work delayed work is submitted.
2) The second packet also goes through eth_tx, another tx_desc_sem
   semaphore is taken, and the tx_timeout_work delayed work is not
   started because there is already one already submitted.
3) The first packet has been sent, one tx_desc_sem semaphore is given
   and the tx_timeout_work delayed work is cancelled.
4) The second packet has been sent but given the delayed work has
   already been cancelled, tx_completed is not called: the tx_desc_sem
   semaphore is not given back and the network packet is not
   unreferenced.

The whole timeout concept probably has to be reworked. In the meantime
it is probably better to just drop the timeout code instead of keeping
the driver broken. We can only get stuck on the TX path if there is a
bug in the driver or a hardware malfunction. It might happen, but with
the less probability then the current hangs. In addition it just hides
the real issues and prevent them to be fixed.

This commit therefore just remove the timeout code in the TX path.

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
This commit is contained in:
Aurelien Jarno 2019-01-18 21:33:03 +01:00 committed by Jukka Rissanen
parent 574ec20bbb
commit 18b07e09e0
2 changed files with 2 additions and 37 deletions

View File

@ -929,22 +929,6 @@ static void link_configure(Gmac *gmac, u32_t flags)
gmac->GMAC_NCR |= (GMAC_NCR_RXEN | GMAC_NCR_TXEN);
}
static void eth_tx_timeout_work(struct k_work *item)
{
struct gmac_queue *queue =
CONTAINER_OF(item, struct gmac_queue, tx_timeout_work);
struct eth_sam_dev_data *dev_data =
CONTAINER_OF(queue, struct eth_sam_dev_data,
queue_list[queue->que_idx]);
struct device *const dev = net_if_get_device(dev_data->iface);
const struct eth_sam_dev_cfg *const cfg = DEV_CFG(dev);
Gmac *gmac = cfg->regs;
/* Just treat it as an error and discard all packets in the queue */
tx_error_handler(gmac, queue);
}
static int nonpriority_queue_init(Gmac *gmac, struct gmac_queue *queue)
{
int result;
@ -971,9 +955,6 @@ static int nonpriority_queue_init(Gmac *gmac, struct gmac_queue *queue)
k_sem_init(&queue->tx_desc_sem, queue->tx_desc_list.len - 1,
queue->tx_desc_list.len - 1);
k_delayed_work_init(&queue->tx_timeout_work,
eth_tx_timeout_work);
/* Set Receive Buffer Queue Pointer Register */
gmac->GMAC_RBQB = (u32_t)queue->rx_desc_list.buf;
/* Set Transmit Buffer Queue Pointer Register */
@ -1030,9 +1011,6 @@ static int priority_queue_init(Gmac *gmac, struct gmac_queue *queue)
k_sem_init(&queue->tx_desc_sem, queue->tx_desc_list.len - 1,
queue->tx_desc_list.len - 1);
k_delayed_work_init(&queue->tx_timeout_work,
eth_tx_timeout_work);
/* Setup RX buffer size for DMA */
gmac->GMAC_RBSRPQ[queue_index] =
GMAC_RBSRPQ_RBS(CONFIG_NET_BUF_DATA_SIZE >> 6);
@ -1411,12 +1389,6 @@ static int eth_tx(struct device *dev, struct net_pkt *pkt)
/* Start transmission */
gmac->GMAC_NCR |= GMAC_NCR_TSTART;
/* Set timeout for queue */
if (k_delayed_work_remaining_get(&queue->tx_timeout_work) == 0) {
k_delayed_work_submit(&queue->tx_timeout_work,
CONFIG_ETH_SAM_GMAC_TX_TIMEOUT_MSEC);
}
return 0;
}
@ -1460,10 +1432,7 @@ static void queue0_isr(void *arg)
gmac_desc_get_w1(tail_desc),
tx_desc_list->tail);
/* Check if it is not too late */
if (k_delayed_work_cancel(&queue->tx_timeout_work) == 0) {
tx_completed(gmac, queue);
}
tx_completed(gmac, queue);
}
if (isr & GMAC_IER_HRESP) {
@ -1511,10 +1480,7 @@ static inline void priority_queue_isr(void *arg, unsigned int queue_idx)
gmac_desc_get_w1(tail_desc),
tx_desc_list->tail);
/* Check if it is not too late */
if (k_delayed_work_cancel(&queue->tx_timeout_work) == 0) {
tx_completed(gmac, queue);
}
tx_completed(gmac, queue);
}
if (isrpq & GMAC_IERPQ_HRESP) {

View File

@ -169,7 +169,6 @@ struct gmac_queue {
struct gmac_desc_list rx_desc_list;
struct gmac_desc_list tx_desc_list;
struct k_sem tx_desc_sem;
struct k_delayed_work tx_timeout_work;
struct ring_buf rx_frag_list;
struct ring_buf tx_frames;