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:
parent
574ec20bbb
commit
18b07e09e0
@ -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) {
|
||||
|
||||
@ -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;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user