ctrl = qmc_read16(&bd->cbd_sc);
if (ctrl & (QMC_BD_TX_R | QMC_BD_TX_UB)) {
- /* We are full ... */
- ret = -EBUSY;
- goto end;
+ if (!(ctrl & (QMC_BD_TX_R | QMC_BD_TX_I)) && bd == chan->txbd_done) {
+ if (ctrl & QMC_BD_TX_W)
+ chan->txbd_done = chan->txbds;
+ else
+ chan->txbd_done++;
+ } else {
+ /* We are full ... */
+ ret = -EBUSY;
+ goto end;
+ }
}
qmc_write16(&bd->cbd_datlen, length);
/* Activate the descriptor */
ctrl |= (QMC_BD_TX_R | QMC_BD_TX_UB);
+ if (complete)
+ ctrl |= QMC_BD_TX_I;
+ else
+ ctrl &= ~QMC_BD_TX_I;
wmb(); /* Be sure to flush the descriptor before control update */
qmc_write16(&bd->cbd_sc, ctrl);
ctrl = qmc_read16(&bd->cbd_sc);
if (ctrl & (QMC_BD_RX_E | QMC_BD_RX_UB)) {
- /* We are full ... */
- ret = -EBUSY;
- goto end;
+ if (!(ctrl & (QMC_BD_RX_E | QMC_BD_RX_I)) && bd == chan->rxbd_done) {
+ if (ctrl & QMC_BD_RX_W)
+ chan->rxbd_done = chan->rxbds;
+ else
+ chan->rxbd_done++;
+ } else {
+ /* We are full ... */
+ ret = -EBUSY;
+ goto end;
+ }
}
qmc_write16(&bd->cbd_datlen, 0); /* data length is updated by the QMC */
/* Activate the descriptor */
ctrl |= (QMC_BD_RX_E | QMC_BD_RX_UB);
+ if (complete)
+ ctrl |= QMC_BD_RX_I;
+ else
+ ctrl &= ~QMC_BD_RX_I;
wmb(); /* Be sure to flush data before descriptor activation */
qmc_write16(&bd->cbd_sc, ctrl);
/* Init Rx BDs and set Wrap bit on last descriptor */
BUILD_BUG_ON(QMC_NB_RXBDS == 0);
- val = QMC_BD_RX_I;
for (i = 0; i < QMC_NB_RXBDS; i++) {
bd = chan->rxbds + i;
- qmc_write16(&bd->cbd_sc, val);
+ qmc_write16(&bd->cbd_sc, 0);
}
bd = chan->rxbds + QMC_NB_RXBDS - 1;
- qmc_write16(&bd->cbd_sc, val | QMC_BD_RX_W);
+ qmc_write16(&bd->cbd_sc, QMC_BD_RX_W);
/* Init Tx BDs and set Wrap bit on last descriptor */
BUILD_BUG_ON(QMC_NB_TXBDS == 0);
- val = QMC_BD_TX_I;
if (chan->mode == QMC_HDLC)
- val |= QMC_BD_TX_L | QMC_BD_TX_TC;
+ val = QMC_BD_TX_L | QMC_BD_TX_TC;
+ else
+ val = 0;
for (i = 0; i < QMC_NB_TXBDS; i++) {
bd = chan->txbds + i;
qmc_write16(&bd->cbd_sc, val);