summaryrefslogtreecommitdiff
path: root/nuttx
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2012-03-13 16:15:24 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2012-03-13 16:15:24 +0000
commite47e27f3e2eb9073b5c8e7a548a3626fbea8e0e5 (patch)
treead466fa4953fa74f35846b1045fd3ea54cf7a6a3 /nuttx
parent44845f6ba52562efd54a6e87492ae909d00d5d7e (diff)
downloadpx4-nuttx-e47e27f3e2eb9073b5c8e7a548a3626fbea8e0e5.tar.gz
px4-nuttx-e47e27f3e2eb9073b5c8e7a548a3626fbea8e0e5.tar.bz2
px4-nuttx-e47e27f3e2eb9073b5c8e7a548a3626fbea8e0e5.zip
Correct PIC32 Ethernet Tx ring handling
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@4484 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx')
-rw-r--r--nuttx/arch/mips/src/pic32mx/pic32mx-ethernet.c110
1 files changed, 80 insertions, 30 deletions
diff --git a/nuttx/arch/mips/src/pic32mx/pic32mx-ethernet.c b/nuttx/arch/mips/src/pic32mx/pic32mx-ethernet.c
index 8bbd62906..1638df468 100644
--- a/nuttx/arch/mips/src/pic32mx/pic32mx-ethernet.c
+++ b/nuttx/arch/mips/src/pic32mx/pic32mx-ethernet.c
@@ -116,6 +116,10 @@
# define CONFIG_NET_NTXDESC 2
#endif
+#if CONFIG_NET_NTXDESC > 255
+# error "The number of TX descriptors exceeds the range of a uint8_t index"
+#endif
+
#ifndef CONFIG_NET_NRXDESC
# define CONFIG_NET_NRXDESC 4
#endif
@@ -335,6 +339,7 @@ struct pic32mx_driver_s
#ifdef PIC32MX_HAVE_PHY
uint8_t pd_phyaddr; /* PHY device address */
#endif
+ uint8_t pd_txnext; /* Index to the next Tx descriptor */
uint32_t pd_inten; /* Shadow copy of INTEN register */
WDOG_ID pd_txpoll; /* TX poll timer */
WDOG_ID pd_txtimeout; /* TX timeout timer */
@@ -396,7 +401,8 @@ static void pic32mx_freebuffer(struct pic32mx_driver_s *priv, uint8_t *buffer);
static inline void pic32mx_txdescinit(struct pic32mx_driver_s *priv);
static inline void pic32mx_rxdescinit(struct pic32mx_driver_s *priv);
-static struct pic32mx_txdesc_s *pic32mx_txdesc(struct pic32mx_driver_s *priv);
+static inline struct pic32mx_txdesc_s *pic32mx_txdesc(struct pic32mx_driver_s *priv);
+static inline void pic32mx_txnext(struct pic32mx_driver_s *priv);
static inline void pic32mx_rxreturn(struct pic32mx_rxdesc_s *rxdesc);
static struct pic32mx_rxdesc_s *pic32mx_rxdesc(struct pic32mx_driver_s *priv);
@@ -765,6 +771,10 @@ static inline void pic32mx_txdescinit(struct pic32mx_driver_s *priv)
pic32mx_dumptxdesc(txdesc, "Initial");
}
+ /* Position the Tx index to the first descriptor in the ring */
+
+ priv->pd_txnext = 0;
+
/* Update the ETHTXST register with the physical address of the head of
* the TX descriptors list.
*/
@@ -843,50 +853,86 @@ static inline void pic32mx_rxdescinit(struct pic32mx_driver_s *priv)
* Function: pic32mx_txdesc
*
* Description:
- * Check if a free TX descriptor is available.
+ * Check if the next Tx descriptor is available.
*
* Parameters:
* priv - Reference to the driver state structure
*
* Returned Value:
- * A pointer to an available TX descriptor on success; NULL on failure
- *
- * Assumptions:
- * May or may not be called from an interrupt handler. In either case,
- * global interrupts are disabled, either explicitly or indirectly through
- * interrupt handling logic.
+ * A pointer to the next available Tx descriptor on success; NULL if the
+ * next Tx dscriptor is not available.
*
****************************************************************************/
-static struct pic32mx_txdesc_s *pic32mx_txdesc(struct pic32mx_driver_s *priv)
+static inline struct pic32mx_txdesc_s *pic32mx_txdesc(struct pic32mx_driver_s *priv)
{
struct pic32mx_txdesc_s *txdesc;
- int i;
- /* Inspect the list of TX descriptors to see if the EOWN bit is cleared. If it
- * is, this descriptor is now under software control and the message was
- * transmitted.
+ /* Get a reference to the next Tx descriptor in the ring */
+
+ txdesc = &priv->pd_txdesc[priv->pd_txnext];
+
+ /* Check if the EOWN bit is cleared. If it is, this descriptor is now under
+ * software control and the message has been transmitted.
+ *
+ * Also check that the buffer address is NULL. There is a race condition
+ * in that the hardware may have completed the transfer, but there may
+ * still be a valid buffer attached to the Tx descriptor because we have
+ * not yet processed the Tx done condition. We will know that the Tx
+ * done condition has been processed when the buffer has been freed and
+ * reset to zero.
*/
- for (i = 0; i < CONFIG_NET_NTXDESC; i++)
+ if ((txdesc->status & TXDESC_STATUS_EOWN) == 0 && txdesc->address == 0)
{
- /* Check if software owns this descriptor */
-
- txdesc = &priv->pd_txdesc[i];
- if ((txdesc->status & TXDESC_STATUS_EOWN) == 0)
- {
- /* Yes.. return a pointer to the desciptor */
+ /* Yes.. return a pointer to the descriptor */
- return txdesc;
- }
+ return txdesc;
}
- /* All descriptors are owned by the Ethernet controller.. return NULL */
+ /* The next Tx descriptor is still owned by the Ethernet controller.. the
+ * Tx ring if full and cannot be used now. Return NULL.
+ */
return NULL;
}
/****************************************************************************
+ * Function: pic32mx_txnext
+ *
+ * Description:
+ * After the next Tx descriptor has been given to the hardware, update the
+ * index to the next Tx descriptor in the ring.
+ *
+ * Parameters:
+ * priv - Reference to the driver state structure
+ *
+ * Returned Value:
+ * None.
+ *
+ ****************************************************************************/
+
+static inline void pic32mx_txnext(struct pic32mx_driver_s *priv)
+{
+ /* Increment the index to the next Tx descriptor in the ring */
+
+ int txnext = priv->pd_txnext + 1;
+
+ /* If the new index would go beyond the end of the allocated descriptors
+ * for the Tx ring, then reset to first descriptor.
+ */
+
+ if (txnext >= CONFIG_NET_NTXDESC)
+ {
+ txnext = 0;
+ }
+
+ /* Save the index to the next Tx descriptor */
+
+ priv->pd_txnext = txnext;
+}
+
+/****************************************************************************
* Function: pic32mx_rxreturn
*
* Description:
@@ -1005,7 +1051,7 @@ static int pic32mx_transmit(struct pic32mx_driver_s *priv)
* the message.
*/
- /* Find the first available TX descriptor. We are guaranteed that is will
+ /* Find the next available TX descriptor. We are guaranteed that is will
* not fail by upstream logic that assures that a TX packet is available
* before polling uIP.
*/
@@ -1038,6 +1084,10 @@ static int pic32mx_transmit(struct pic32mx_driver_s *priv)
txdesc->status = status;
pic32mx_dumptxdesc(txdesc, "After transmit setup");
+ /* Update the index to the next descriptor to use in the Tx ring */
+
+ pic32mx_txnext(priv);
+
/* Enable the transmission of the message by setting the TXRTS bit (ETHCON1:9). */
pic32mx_putreg(ETH_CON1_TXRTS | ETH_CON1_ON, PIC32MX_ETH_CON1SET);
@@ -1097,8 +1147,8 @@ static int pic32mx_uiptxpoll(struct uip_driver_s *dev)
uip_arp_out(&priv->pd_dev);
pic32mx_transmit(priv);
- /* Check if there is room in the device to hold another packet. If not,
- * return any non-zero value to terminate the poll.
+ /* Check if the next TX descriptor is avaialable. If not, return any
+ * non-zero value to terminate the poll.
*/
if (pic32mx_txdesc(priv) == NULL || sq_empty(&priv->pd_freebuffers))
@@ -1144,7 +1194,7 @@ static void pic32mx_response(struct pic32mx_driver_s *priv)
{
struct pic32mx_txdesc_s *txdesc;
- /* Check if there is room in the device to hold another packet. */
+ /* Check if the next TX descriptor is available. */
txdesc = pic32mx_txdesc(priv);
if (txdesc != NULL)
@@ -1696,8 +1746,8 @@ static void pic32mx_polltimer(int argc, uint32_t arg, ...)
{
struct pic32mx_driver_s *priv = (struct pic32mx_driver_s *)arg;
- /* Check if there is room in the send another TX packet. We cannot perform
- * the TX poll if he are unable to accept another packet for transmission.
+ /* Check if the next Tx descriptor is available. We cannot perform the Tx
+ * poll if we are unable to accept another packet for transmission.
*/
if (pic32mx_txdesc(priv) != NULL)
@@ -2107,7 +2157,7 @@ static int pic32mx_txavail(struct uip_driver_s *dev)
if (priv->pd_ifup)
{
- /* Check if there is room in the hardware to hold another outgoing packet. */
+ /* Check if the next Tx descriptor is available. */
if (pic32mx_txdesc(priv) != NULL)
{