summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDominik Sliwa <dominik.sliwa@toradex.com>2019-01-30 12:49:38 +0100
committerDominik Sliwa <dominik.sliwa@toradex.com>2019-01-30 12:49:38 +0100
commit5de4c57d803e4d0f5334f4e04de51dc9872c1d2c (patch)
tree48983697f3bb3a8605ac45a549e1eddd1e1ad8c7
parentbd9327bb04f6612b32fed346589ff113118c7a0d (diff)
apalis-tk1: can: mfd: k20: use level interrupts and prioritize tx
Prioritize CAN TX trafic, and move from edge to level triggered interrupts. Signed-off-by: Dominik Sliwa <dominik.sliwa@toradex.com>
-rw-r--r--drivers/mfd/apalis-tk1-k20.c3
-rw-r--r--drivers/net/can/apalis-tk1-k20-can.c35
2 files changed, 20 insertions, 18 deletions
diff --git a/drivers/mfd/apalis-tk1-k20.c b/drivers/mfd/apalis-tk1-k20.c
index a6d1c1cdc0b6..dfdd3683d527 100644
--- a/drivers/mfd/apalis-tk1-k20.c
+++ b/drivers/mfd/apalis-tk1-k20.c
@@ -351,8 +351,7 @@ int apalis_tk1_k20_irq_request(struct apalis_tk1_k20_regmap *apalis_tk1_k20,
} else {
virq = (irq == APALIS_TK1_K20_CAN0_IRQ) ?
apalis_tk1_k20->can0_irq:apalis_tk1_k20->can1_irq;
- irq_flags = IRQF_ONESHOT | IRQF_TRIGGER_FALLING |
- IRQF_TRIGGER_RISING;
+ irq_flags = IRQF_ONESHOT | IRQF_TRIGGER_HIGH;
}
return devm_request_threaded_irq(apalis_tk1_k20->dev, virq,
NULL, handler, irq_flags, name, dev);
diff --git a/drivers/net/can/apalis-tk1-k20-can.c b/drivers/net/can/apalis-tk1-k20-can.c
index c42df958f5aa..2a61036a858b 100644
--- a/drivers/net/can/apalis-tk1-k20-can.c
+++ b/drivers/net/can/apalis-tk1-k20-can.c
@@ -125,8 +125,6 @@ static void apalis_tk1_k20_can_hw_tx_frame(struct net_device *net, u8 *buf,
+ APALIS_TK1_K20_CAN_DEV_OFFSET(
priv->pdata->id), buf, len);
apalis_tk1_k20_unlock(priv->apalis_tk1_k20);
-
- priv->tx_frame = 1;
}
static void apalis_tk1_k20_can_hw_tx(struct net_device *net,
@@ -142,7 +140,7 @@ static void apalis_tk1_k20_can_hw_tx(struct net_device *net,
+ CAN_HEADER_MAX_LEN, tx_buf_idx);
}
-static void apalis_tk1_k20_can_hw_rx(struct net_device *net, int buf_idx)
+static int apalis_tk1_k20_can_hw_rx(struct net_device *net, int buf_idx)
{
struct apalis_tk1_k20_priv *priv = netdev_priv(net);
struct sk_buff *skb;
@@ -168,7 +166,7 @@ static void apalis_tk1_k20_can_hw_rx(struct net_device *net, int buf_idx)
if (!skb) {
dev_err(&net->dev, "cannot allocate RX skb\n");
priv->net->stats.rx_dropped++;
- return;
+ return -ENOMEM;
}
memcpy(&frame->can_id, &buf[i * CAN_TRANSFER_BUF_LEN]
+ MB_EID_OFF, MB_EID_LEN);
@@ -186,6 +184,7 @@ static void apalis_tk1_k20_can_hw_rx(struct net_device *net, int buf_idx)
netif_rx_ni(skb);
}
+ return frame_available;
}
@@ -435,6 +434,7 @@ static void apalis_tk1_k20_can_tx_work_handler(struct work_struct *ws)
priv->tx_len = 1 + frame->can_dlc;
can_put_echo_skb(priv->tx_skb, net, 0);
priv->tx_skb = NULL;
+ priv->tx_frame = 1;
}
}
mutex_unlock(&priv->apalis_tk1_k20_can_lock);
@@ -545,7 +545,7 @@ static irqreturn_t apalis_tk1_k20_can_ist(int irq, void *dev_id)
mutex_lock(&priv->apalis_tk1_k20_can_lock);
while (!priv->force_quit) {
enum can_state new_state;
- int ret;
+ int ret, rx_cnt = 0;
u32 intf, eflag;
u8 clear_intf = 0;
int can_id = 0, data1 = 0;
@@ -565,31 +565,31 @@ static irqreturn_t apalis_tk1_k20_can_ist(int irq, void *dev_id)
intf &= CANCTRL_INTMASK;
- if (!(intf & CANINTF_TX) &&
+ if (intf == 0)
+ break;
+
+ /* TX complete */
+ if ((intf & CANINTF_TX) &&
(priv->tx_frame == 1)) {
priv->tx_frame = 0;
net->stats.tx_packets++;
- net->stats.tx_bytes += priv->tx_len - 1;
- can_led_event(net, CAN_LED_EVENT_TX);
if (priv->tx_len) {
+ net->stats.tx_bytes += priv->tx_len - 1;
+ can_led_event(net, CAN_LED_EVENT_TX);
can_get_echo_skb(net, 0);
priv->tx_len = 0;
}
netif_wake_queue(net);
- if (!(intf & (CANINTF_RX | CANINTF_ERR)))
- break;
+ clear_intf |= CANINTF_TX;
}
-
- if (intf == 0)
- break;
-
/* receive */
if (intf & CANINTF_RX)
- apalis_tk1_k20_can_hw_rx(net, 0);
+ rx_cnt = apalis_tk1_k20_can_hw_rx(net, 0);
/* any error interrupt we need to clear? */
if (intf & CANINTF_ERR)
- clear_intf |= intf & CANINTF_ERR;
+ clear_intf |= CANINTF_ERR;
+
apalis_tk1_k20_lock(priv->apalis_tk1_k20);
if (clear_intf)
ret = apalis_tk1_k20_reg_write(priv->apalis_tk1_k20,
@@ -676,6 +676,9 @@ static irqreturn_t apalis_tk1_k20_can_ist(int irq, void *dev_id)
break;
}
+ if (priv->tx_skb != NULL) {
+ break;
+ }
}
mutex_unlock(&priv->apalis_tk1_k20_can_lock);