pch_can: Add flow control processing
authorTomoya <tomoya-linux@dsn.okisemi.com>
Sun, 12 Dec 2010 20:24:07 +0000 (20:24 +0000)
committerDavid S. Miller <davem@davemloft.net>
Mon, 13 Dec 2010 20:24:18 +0000 (12:24 -0800)
Currently, there is no flow control processing.
Thus, Add flow control processing as
when there is no empty of tx buffer,
netif_stop_queue is called.
When there is empty buffer, netif_wake_queue is called.

Signed-off-by: Tomoya MORINAGA <tomoya-linux@dsn.okisemi.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/can/pch_can.c

index a9b6a6525a65512f1705e297f64448adea6490f9..f0f140492c07a7cd94dc89a173e7d90bcfbfed3a 100644 (file)
 
 #define PCH_FIFO_THRESH                16
 
+/* TxRqst2 show status of MsgObjNo.17~32 */
+#define PCH_TREQ2_TX_MASK      (((1 << PCH_TX_OBJ_NUM) - 1) <<\
+                                                       (PCH_RX_OBJ_END - 16))
+
 enum pch_ifreg {
        PCH_RX_IFREG,
        PCH_TX_IFREG,
@@ -871,6 +875,8 @@ MSG_OBJ:
                        dlc = 8;
                stats->tx_bytes += dlc;
                stats->tx_packets++;
+               if (int_stat == PCH_TX_OBJ_END)
+                       netif_wake_queue(ndev);
        }
 
        int_stat = pch_can_int_pending(priv);
@@ -1009,18 +1015,6 @@ static int pch_close(struct net_device *ndev)
        return 0;
 }
 
-static int pch_get_msg_obj_sts(struct net_device *ndev, u32 obj_id)
-{
-       u32 buffer_status = 0;
-       struct pch_can_priv *priv = netdev_priv(ndev);
-
-       /* Getting the message object status. */
-       buffer_status = (u32) pch_can_get_buffer_status(priv);
-
-       return buffer_status & obj_id;
-}
-
-
 static netdev_tx_t pch_xmit(struct sk_buff *skb, struct net_device *ndev)
 {
        int i, j;
@@ -1031,17 +1025,16 @@ static netdev_tx_t pch_xmit(struct sk_buff *skb, struct net_device *ndev)
        if (can_dropped_invalid_skb(ndev, skb))
                return NETDEV_TX_OK;
 
-       if (priv->tx_obj == PCH_TX_OBJ_END) { /* Point tail Obj */
-               while (pch_get_msg_obj_sts(ndev, (((1 << PCH_TX_OBJ_NUM)-1) <<
-                                          PCH_RX_OBJ_NUM)))
-                       udelay(500);
+       if (priv->tx_obj == PCH_TX_OBJ_END) {
+               if (ioread32(&priv->regs->treq2) & PCH_TREQ2_TX_MASK)
+                       netif_stop_queue(ndev);
 
-               priv->tx_obj = PCH_TX_OBJ_START; /* Point head of Tx Obj ID */
-               tx_buffer_avail = priv->tx_obj; /* Point Tail of Tx Obj */
+               tx_buffer_avail = priv->tx_obj;
+               priv->tx_obj = PCH_TX_OBJ_START;
        } else {
                tx_buffer_avail = priv->tx_obj;
+               priv->tx_obj++;
        }
-       priv->tx_obj++;
 
        /* Reading the Msg Obj from the Msg RAM to the Interface register. */
        iowrite32(PCH_CMASK_RX_TX_GET, &priv->regs->ifregs[1].cmask);