diff options
author | Tomoya <tomoya-linux@dsn.okisemi.com> | 2010-12-12 15:24:07 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-12-13 15:24:18 -0500 |
commit | 76d94b232940ca91e9b26c590cb7312ab88ff722 (patch) | |
tree | 05b7db8706741aea22da359ec64e64429142b5a3 /drivers/net/can | |
parent | 249fab773dd5f689318c969ed649c4db077cdfc3 (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.c | 31 |
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 | |||
105 | enum pch_ifreg { | 109 | enum 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 | ||
1012 | static 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 | |||
1024 | static netdev_tx_t pch_xmit(struct sk_buff *skb, struct net_device *ndev) | 1018 | static 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); |