aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/can
diff options
context:
space:
mode:
authorTomoya <tomoya-linux@dsn.okisemi.com>2010-12-12 15:24:07 -0500
committerDavid S. Miller <davem@davemloft.net>2010-12-13 15:24:18 -0500
commit76d94b232940ca91e9b26c590cb7312ab88ff722 (patch)
tree05b7db8706741aea22da359ec64e64429142b5a3 /drivers/net/can
parent249fab773dd5f689318c969ed649c4db077cdfc3 (diff)
pch_can: Add flow control processing
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>
Diffstat (limited to 'drivers/net/can')
-rw-r--r--drivers/net/can/pch_can.c31
1 files changed, 12 insertions, 19 deletions
diff --git a/drivers/net/can/pch_can.c b/drivers/net/can/pch_can.c
index a9b6a6525a65..f0f140492c07 100644
--- a/drivers/net/can/pch_can.c
+++ b/drivers/net/can/pch_can.c
@@ -102,6 +102,10 @@
102 102
103#define PCH_FIFO_THRESH 16 103#define PCH_FIFO_THRESH 16
104 104
105/* TxRqst2 show status of MsgObjNo.17~32 */
106#define PCH_TREQ2_TX_MASK (((1 << PCH_TX_OBJ_NUM) - 1) <<\
107 (PCH_RX_OBJ_END - 16))
108
105enum pch_ifreg { 109enum pch_ifreg {
106 PCH_RX_IFREG, 110 PCH_RX_IFREG,
107 PCH_TX_IFREG, 111 PCH_TX_IFREG,
@@ -871,6 +875,8 @@ MSG_OBJ:
871 dlc = 8; 875 dlc = 8;
872 stats->tx_bytes += dlc; 876 stats->tx_bytes += dlc;
873 stats->tx_packets++; 877 stats->tx_packets++;
878 if (int_stat == PCH_TX_OBJ_END)
879 netif_wake_queue(ndev);
874 } 880 }
875 881
876 int_stat = pch_can_int_pending(priv); 882 int_stat = pch_can_int_pending(priv);
@@ -1009,18 +1015,6 @@ static int pch_close(struct net_device *ndev)
1009 return 0; 1015 return 0;
1010} 1016}
1011 1017
1012static int pch_get_msg_obj_sts(struct net_device *ndev, u32 obj_id)
1013{
1014 u32 buffer_status = 0;
1015 struct pch_can_priv *priv = netdev_priv(ndev);
1016
1017 /* Getting the message object status. */
1018 buffer_status = (u32) pch_can_get_buffer_status(priv);
1019
1020 return buffer_status & obj_id;
1021}
1022
1023
1024static netdev_tx_t pch_xmit(struct sk_buff *skb, struct net_device *ndev) 1018static netdev_tx_t pch_xmit(struct sk_buff *skb, struct net_device *ndev)
1025{ 1019{
1026 int i, j; 1020 int i, j;
@@ -1031,17 +1025,16 @@ static netdev_tx_t pch_xmit(struct sk_buff *skb, struct net_device *ndev)
1031 if (can_dropped_invalid_skb(ndev, skb)) 1025 if (can_dropped_invalid_skb(ndev, skb))
1032 return NETDEV_TX_OK; 1026 return NETDEV_TX_OK;
1033 1027
1034 if (priv->tx_obj == PCH_TX_OBJ_END) { /* Point tail Obj */ 1028 if (priv->tx_obj == PCH_TX_OBJ_END) {
1035 while (pch_get_msg_obj_sts(ndev, (((1 << PCH_TX_OBJ_NUM)-1) << 1029 if (ioread32(&priv->regs->treq2) & PCH_TREQ2_TX_MASK)
1036 PCH_RX_OBJ_NUM))) 1030 netif_stop_queue(ndev);
1037 udelay(500);
1038 1031
1039 priv->tx_obj = PCH_TX_OBJ_START; /* Point head of Tx Obj ID */ 1032 tx_buffer_avail = priv->tx_obj;
1040 tx_buffer_avail = priv->tx_obj; /* Point Tail of Tx Obj */ 1033 priv->tx_obj = PCH_TX_OBJ_START;
1041 } else { 1034 } else {
1042 tx_buffer_avail = priv->tx_obj; 1035 tx_buffer_avail = priv->tx_obj;
1036 priv->tx_obj++;
1043 } 1037 }
1044 priv->tx_obj++;
1045 1038
1046 /* Reading the Msg Obj from the Msg RAM to the Interface register. */ 1039 /* Reading the Msg Obj from the Msg RAM to the Interface register. */
1047 iowrite32(PCH_CMASK_RX_TX_GET, &priv->regs->ifregs[1].cmask); 1040 iowrite32(PCH_CMASK_RX_TX_GET, &priv->regs->ifregs[1].cmask);