/* Decrement sent descriptors counter */ static void mvneta_txq_sent_desc_dec(struct mvneta_port *pp, struct mvneta_tx_queue *txq, int sent_desc) { u32 val; /* Only 255 TX descriptors can be updated at once */ while (sent_desc > 0xff) { val = 0xff << MVNETA_TXQ_DEC_SENT_SHIFT; mvreg_write(pp, MVNETA_TXQ_UPDATE_REG(txq->id), val); sent_desc = sent_desc - 0xff; } val = sent_desc << MVNETA_TXQ_DEC_SENT_SHIFT; mvreg_write(pp, MVNETA_TXQ_UPDATE_REG(txq->id), val); }
/* Update HW with number of TX descriptors to be sent */ static void mvneta_txq_pend_desc_add(struct mvneta_port *pp, struct mvneta_tx_queue *txq, int pend_desc) { u32 val; /* Only 255 descriptors can be added at once ; Assume caller * process TX desriptors in quanta less than 256 */ val = pend_desc; mvreg_write(pp, MVNETA_TXQ_UPDATE_REG(txq->id), val); }
static int mvneta_send(struct eth_device *edev, void *data, int len) { struct mvneta_port *priv = edev->priv; struct txdesc *txdesc = priv->txdesc; int ret, error, last_desc; /* Flush transmit data */ dma_sync_single_for_device((unsigned long)data, len, DMA_TO_DEVICE); memset(txdesc, 0, sizeof(*txdesc)); /* Fill the Tx descriptor */ txdesc->cmd_sts = MVNETA_TX_L4_CSUM_NOT | MVNETA_TXD_FLZ_DESC; txdesc->buf_ptr = (u32)data; txdesc->byte_cnt = len; /* Increase the number of prepared descriptors (one), by writing * to the 'NoOfWrittenDescriptors' field in the PTXSU register. */ writel(1, priv->reg + MVNETA_TXQ_UPDATE_REG(0)); /* The controller updates the number of transmitted descriptors in * the Tx port status register (PTXS). */ ret = wait_on_timeout(TRANSFER_TIMEOUT, !mvneta_pending_tx(priv)); dma_sync_single_for_cpu((unsigned long)data, len, DMA_TO_DEVICE); if (ret) { dev_err(&edev->dev, "transmit timeout\n"); return ret; } last_desc = readl(&txdesc->cmd_sts) & MVNETA_TXD_L_DESC; error = readl(&txdesc->error); if (last_desc && error & MVNETA_TXD_ERROR) { dev_err(&edev->dev, "transmit error %d\n", (error & TXD_ERROR_MASK) >> TXD_ERROR_SHIFT); return -EIO; }
return ret; } last_desc = readl(&txdesc->cmd_sts) & MVNETA_TXD_L_DESC; error = readl(&txdesc->error); if (last_desc && error & MVNETA_TXD_ERROR) { dev_err(&edev->dev, "transmit error %d\n", (error & TXD_ERROR_MASK) >> TXD_ERROR_SHIFT); return -EIO; } /* Release the transmitted descriptor by writing to the * 'NoOfReleasedBuffers' field in the PTXSU register. */ writel(1 << MVNETA_TXQ_DEC_SENT_SHIFT, priv->reg + MVNETA_TXQ_UPDATE_REG(0)); return 0; } static int mvneta_recv(struct eth_device *edev) { struct mvneta_port *priv = edev->priv; struct rxdesc *rxdesc = &priv->rxdesc[priv->curr_rxdesc]; int ret, pending; u32 cmd_sts; /* wait for received packet */ pending = mvneta_pending_rx(priv); if (!pending) return 0;