From: Benedikt Spranger <b.spranger@linutronix.de>
To: netdev@vger.kernel.org
Cc: Alexander Frank <Alexander.Frank@eberspaecher.com>,
Sebastian Andrzej Siewior <bigeasy@linutronix.de>,
Holger Dengler <dengler@linutronix.de>,
Benedikt Spranger <b.spranger@linutronix.de>
Subject: [PATCH 11/16] c_can: stop netqueue if hardware is busy
Date: Mon, 9 Sep 2013 09:25:08 +0200 [thread overview]
Message-ID: <1378711513-2548-12-git-send-email-b.spranger@linutronix.de> (raw)
In-Reply-To: <1378711513-2548-1-git-send-email-b.spranger@linutronix.de>
Unlike other network devices the FlexCard do not support interrupts on TX.
Emulate the TX interrupt by polling the MOTRX registers and restart the
netqueue if one or more message object is available for transtition of CAN
frames.
Signed-off-by: Benedikt Spranger <b.spranger@linutronix.de>
---
drivers/net/can/c_can/c_can.c | 61 ++++++++++++++++++++++++++++++++++++++++---
drivers/net/can/c_can/c_can.h | 4 +++
2 files changed, 62 insertions(+), 3 deletions(-)
diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c
index 46d741d..02f7c89 100644
--- a/drivers/net/can/c_can/c_can.c
+++ b/drivers/net/can/c_can/c_can.c
@@ -550,18 +550,66 @@ static void c_can_inval_msg_object(struct net_device *dev, int iface, int objno)
static inline int c_can_is_next_tx_obj_busy(struct c_can_priv *priv, int objno)
{
- int val = c_can_read_reg32(priv, C_CAN_TXRQST1_REG);
+ int val = c_can_read_reg32(priv, C_CAN_TXRQST1_REG + (objno / 32) * 4);
/*
* as transmission request register's bit n-1 corresponds to
* message object n, we need to handle the same properly.
*/
- if (val & (1 << (objno - 1)))
+ if (val & (1 << ((objno % 32) - 1)))
return 1;
return 0;
}
+static void c_can_motrx_add_timer(struct net_device *dev)
+{
+ struct c_can_priv *priv = netdev_priv(dev);
+
+ priv->timer.expires = round_jiffies_relative(1);
+ add_timer(&priv->timer);
+}
+
+static void c_can_motrx_poll(unsigned long data)
+{
+ struct net_device *dev = (struct net_device *)data;
+ struct c_can_priv *priv = netdev_priv(dev);
+ u32 val, empty = 0;
+ int i;
+
+ for (i = 0; i < C_CAN_MOTRX_NR; i++) {
+ val = c_can_read_reg32(priv, C_CAN_TXRQST1_REG + i * 4);
+
+ if (val < priv->motrx[i]) {
+ netif_wake_queue(dev);
+ return;
+ }
+
+ empty |= val;
+ }
+
+ if (!empty) {
+ netif_wake_queue(dev);
+ return;
+ }
+
+ c_can_motrx_add_timer(dev);
+}
+
+static void c_can_motrx_monitor(struct net_device *dev)
+{
+ struct c_can_priv *priv = netdev_priv(dev);
+ int i;
+
+ if (priv->type != BOSCH_D_CAN_FLEXCARD)
+ return;
+
+ for (i = 0; i < C_CAN_MOTRX_NR; i++)
+ priv->motrx[i] = c_can_read_reg32(priv,
+ C_CAN_TXRQST1_REG + i * 4);
+ c_can_motrx_add_timer(dev);
+}
+
static netdev_tx_t c_can_start_xmit(struct sk_buff *skb,
struct net_device *dev)
{
@@ -582,6 +630,7 @@ static netdev_tx_t c_can_start_xmit(struct sk_buff *skb,
if (readl(priv->base + FC_TXFIFO_STAT) &
FC_TXFIFO_STAT_FULL) {
netif_stop_queue(dev);
+ c_can_motrx_monitor(dev);
return NETDEV_TX_BUSY;
}
@@ -619,8 +668,10 @@ static netdev_tx_t c_can_start_xmit(struct sk_buff *skb,
* if the next TX message object is still in use
*/
if (c_can_is_next_tx_obj_busy(priv, get_tx_next_msg_obj(priv))
- || ((priv->tx_next & C_CAN_NEXT_MSG_OBJ_MASK) == 0))
+ || ((priv->tx_next & C_CAN_NEXT_MSG_OBJ_MASK) == 0)) {
netif_stop_queue(dev);
+ c_can_motrx_monitor(dev);
+ }
}
return NETDEV_TX_OK;
@@ -1272,6 +1323,7 @@ static int c_can_close(struct net_device *dev)
{
struct c_can_priv *priv = netdev_priv(dev);
+ del_timer_sync(&priv->timer);
netif_stop_queue(dev);
napi_disable(&priv->napi);
c_can_stop(dev);
@@ -1306,6 +1358,9 @@ struct net_device *alloc_c_can_dev(void)
CAN_CTRLMODE_LISTENONLY |
CAN_CTRLMODE_BERR_REPORTING;
spin_lock_init(&priv->lock);
+ priv->timer.function = c_can_motrx_poll;
+ priv->timer.data = (unsigned long) dev;
+ init_timer_deferrable(&priv->timer);
return dev;
}
diff --git a/drivers/net/can/c_can/c_can.h b/drivers/net/can/c_can/c_can.h
index beea437..6d0f805 100644
--- a/drivers/net/can/c_can/c_can.h
+++ b/drivers/net/can/c_can/c_can.h
@@ -153,6 +153,8 @@ enum c_can_dev_id {
BOSCH_D_CAN_FLEXCARD,
};
+#define C_CAN_MOTRX_NR 1
+
/* c_can private data structure */
struct c_can_priv {
struct can_priv can; /* must be the first member */
@@ -176,6 +178,8 @@ struct c_can_priv {
unsigned int instance;
void (*raminit) (const struct c_can_priv *priv, bool enable);
spinlock_t lock;
+ struct timer_list timer;
+ u32 motrx[C_CAN_MOTRX_NR];
};
struct net_device *alloc_c_can_dev(void);
--
1.8.4.rc3
next prev parent reply other threads:[~2013-09-09 7:43 UTC|newest]
Thread overview: 34+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-09-09 7:24 [PATCH 00/16] Support for Eberspächer Flexcard DCAN function Benedikt Spranger
2013-09-09 7:24 ` [PATCH 01/16] c_can_platform: add FlexCard D-CAN support Benedikt Spranger
2013-09-09 8:22 ` Marc Kleine-Budde
2013-09-09 7:24 ` [PATCH 02/16] c_can: add generic D-CAN RAM initialization support Benedikt Spranger
2013-09-09 8:34 ` Marc Kleine-Budde
2013-09-09 7:25 ` [PATCH 03/16] c_can: simplify arbitration register handling Benedikt Spranger
2013-09-09 9:16 ` Marc Kleine-Budde
2013-09-09 7:25 ` [PATCH 04/16] c_can: fix receive buffer configuration Benedikt Spranger
2013-09-09 10:51 ` Marc Kleine-Budde
2013-09-09 7:25 ` [PATCH 05/16] c_can: use 32 bit access for D_CAN Benedikt Spranger
2013-09-09 9:37 ` Marc Kleine-Budde
2013-09-09 7:25 ` [PATCH 06/16] c_can: consider set bittiming may fail Benedikt Spranger
2013-09-09 9:39 ` Marc Kleine-Budde
2013-09-09 7:25 ` [PATCH 07/16] c_can: reconfigre message objects after leaving init state Benedikt Spranger
2013-09-09 7:25 ` [PATCH 08/16] c_can: Add FlexCard CAN TX fifo support Benedikt Spranger
2013-09-09 9:47 ` Marc Kleine-Budde
2013-09-09 7:25 ` [PATCH 09/16] c_can: expicit 32bit access on D_CAN to message buffer data register Benedikt Spranger
2013-09-09 11:20 ` Marc Kleine-Budde
2013-09-09 7:25 ` [PATCH 10/16] c_can: add 16bit align 32bit access functions Benedikt Spranger
2013-09-09 9:57 ` Marc Kleine-Budde
2013-09-09 7:25 ` Benedikt Spranger [this message]
2013-09-09 10:05 ` [PATCH 11/16] c_can: stop netqueue if hardware is busy Marc Kleine-Budde
2013-09-09 10:21 ` Marc Kleine-Budde
2013-09-09 7:25 ` [PATCH 12/16] c_can: Add flag to disable automatic retransmission of CAN frames Benedikt Spranger
2013-09-09 10:21 ` Marc Kleine-Budde
2013-09-09 10:34 ` Marc Kleine-Budde
2013-09-09 7:25 ` [PATCH 13/16] c_can: flexcard: add ioctl to reset FIFO message object Benedikt Spranger
2013-09-09 10:24 ` Marc Kleine-Budde
2013-09-09 7:25 ` [PATCH 14/16] flexcard: can: CAN local loopback using SKB pflags Benedikt Spranger
2013-09-09 7:25 ` [PATCH 15/16] flexcard: can: Configure CAN loopback packages (TXACK) Benedikt Spranger
2013-09-09 10:29 ` Marc Kleine-Budde
2013-09-09 7:25 ` [PATCH 16/16] c_can: fix TX packet accounting Benedikt Spranger
2013-09-09 10:31 ` Marc Kleine-Budde
2013-09-09 7:54 ` [PATCH 00/16] Support for Eberspächer Flexcard DCAN function Marc Kleine-Budde
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1378711513-2548-12-git-send-email-b.spranger@linutronix.de \
--to=b.spranger@linutronix.de \
--cc=Alexander.Frank@eberspaecher.com \
--cc=bigeasy@linutronix.de \
--cc=dengler@linutronix.de \
--cc=netdev@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).