mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-18 22:36:58 +07:00
linux-can-fixes-for-4.16-20180314
-----BEGIN PGP SIGNATURE----- iQFHBAABCgAxFiEENrCndlB/VnAEWuH5k9IU1zQoZfEFAlqpD0ETHG1rbEBwZW5n dXRyb25peC5kZQAKCRCT0hTXNChl8RLvB/9Sb3oVKHNeSSDTN/oR3fOrlVd2rj58 Aajmtwkfc4uXuV/1l/Muu/zsP4DED7WrO0r777C3rX+0jsZtHALZbtS/0ksbUvJM mJQ//xC4cfQJ1djNtPz9QmNMbHH4zchKY3xTGTiQeEZddnFYGPgB3OCo0j9R4AGd a46n1svV8Zzao8NJ4Hc/2AQwyn1EafUKqoR5u9hH/pZ9oCZH/EDH9qaTaMuoRWMq BgoS14yDG9mOfdbUA2Ywd7nZ4KiHM6Or1b+S/1W8Unfnfl3bIfVPsJQi2Ypn1zpf hXKYz68AfP7B0uNZGxVjjTliF8M4CAdv/9pAW7Pwx68Pu2TvaknROFxe =o8zS -----END PGP SIGNATURE----- Merge tag 'linux-can-fixes-for-4.16-20180314' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can Marc Kleine-Budde says: ==================== pull-request: can 2018-03-14 this is a pull request of two patches for net/master. Both patches are by Andri Yngvason and fix problems in the cc770 driver, that show up quite fast on RT systems, but also on non RT setups. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
4ea41f829a
@ -390,37 +390,23 @@ static int cc770_get_berr_counter(const struct net_device *dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static netdev_tx_t cc770_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
static void cc770_tx(struct net_device *dev, int mo)
|
||||
{
|
||||
struct cc770_priv *priv = netdev_priv(dev);
|
||||
struct net_device_stats *stats = &dev->stats;
|
||||
struct can_frame *cf = (struct can_frame *)skb->data;
|
||||
unsigned int mo = obj2msgobj(CC770_OBJ_TX);
|
||||
struct can_frame *cf = (struct can_frame *)priv->tx_skb->data;
|
||||
u8 dlc, rtr;
|
||||
u32 id;
|
||||
int i;
|
||||
|
||||
if (can_dropped_invalid_skb(dev, skb))
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
if ((cc770_read_reg(priv,
|
||||
msgobj[mo].ctrl1) & TXRQST_UNC) == TXRQST_SET) {
|
||||
netdev_err(dev, "TX register is still occupied!\n");
|
||||
return NETDEV_TX_BUSY;
|
||||
}
|
||||
|
||||
netif_stop_queue(dev);
|
||||
|
||||
dlc = cf->can_dlc;
|
||||
id = cf->can_id;
|
||||
if (cf->can_id & CAN_RTR_FLAG)
|
||||
rtr = 0;
|
||||
else
|
||||
rtr = MSGCFG_DIR;
|
||||
rtr = cf->can_id & CAN_RTR_FLAG ? 0 : MSGCFG_DIR;
|
||||
|
||||
cc770_write_reg(priv, msgobj[mo].ctrl0,
|
||||
MSGVAL_RES | TXIE_RES | RXIE_RES | INTPND_RES);
|
||||
cc770_write_reg(priv, msgobj[mo].ctrl1,
|
||||
RMTPND_RES | TXRQST_RES | CPUUPD_SET | NEWDAT_RES);
|
||||
cc770_write_reg(priv, msgobj[mo].ctrl0,
|
||||
MSGVAL_SET | TXIE_SET | RXIE_RES | INTPND_RES);
|
||||
|
||||
if (id & CAN_EFF_FLAG) {
|
||||
id &= CAN_EFF_MASK;
|
||||
cc770_write_reg(priv, msgobj[mo].config,
|
||||
@ -439,22 +425,30 @@ static netdev_tx_t cc770_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
for (i = 0; i < dlc; i++)
|
||||
cc770_write_reg(priv, msgobj[mo].data[i], cf->data[i]);
|
||||
|
||||
/* Store echo skb before starting the transfer */
|
||||
can_put_echo_skb(skb, dev, 0);
|
||||
|
||||
cc770_write_reg(priv, msgobj[mo].ctrl1,
|
||||
RMTPND_RES | TXRQST_SET | CPUUPD_RES | NEWDAT_UNC);
|
||||
|
||||
stats->tx_bytes += dlc;
|
||||
|
||||
|
||||
/*
|
||||
* HM: We had some cases of repeated IRQs so make sure the
|
||||
* INT is acknowledged I know it's already further up, but
|
||||
* doing again fixed the issue
|
||||
*/
|
||||
RMTPND_UNC | TXRQST_SET | CPUUPD_RES | NEWDAT_UNC);
|
||||
cc770_write_reg(priv, msgobj[mo].ctrl0,
|
||||
MSGVAL_UNC | TXIE_UNC | RXIE_UNC | INTPND_RES);
|
||||
MSGVAL_SET | TXIE_SET | RXIE_SET | INTPND_UNC);
|
||||
}
|
||||
|
||||
static netdev_tx_t cc770_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
{
|
||||
struct cc770_priv *priv = netdev_priv(dev);
|
||||
unsigned int mo = obj2msgobj(CC770_OBJ_TX);
|
||||
|
||||
if (can_dropped_invalid_skb(dev, skb))
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
netif_stop_queue(dev);
|
||||
|
||||
if ((cc770_read_reg(priv,
|
||||
msgobj[mo].ctrl1) & TXRQST_UNC) == TXRQST_SET) {
|
||||
netdev_err(dev, "TX register is still occupied!\n");
|
||||
return NETDEV_TX_BUSY;
|
||||
}
|
||||
|
||||
priv->tx_skb = skb;
|
||||
cc770_tx(dev, mo);
|
||||
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
@ -680,19 +674,47 @@ static void cc770_tx_interrupt(struct net_device *dev, unsigned int o)
|
||||
struct cc770_priv *priv = netdev_priv(dev);
|
||||
struct net_device_stats *stats = &dev->stats;
|
||||
unsigned int mo = obj2msgobj(o);
|
||||
struct can_frame *cf;
|
||||
u8 ctrl1;
|
||||
|
||||
ctrl1 = cc770_read_reg(priv, msgobj[mo].ctrl1);
|
||||
|
||||
/* Nothing more to send, switch off interrupts */
|
||||
cc770_write_reg(priv, msgobj[mo].ctrl0,
|
||||
MSGVAL_RES | TXIE_RES | RXIE_RES | INTPND_RES);
|
||||
/*
|
||||
* We had some cases of repeated IRQ so make sure the
|
||||
* INT is acknowledged
|
||||
*/
|
||||
cc770_write_reg(priv, msgobj[mo].ctrl0,
|
||||
MSGVAL_UNC | TXIE_UNC | RXIE_UNC | INTPND_RES);
|
||||
cc770_write_reg(priv, msgobj[mo].ctrl1,
|
||||
RMTPND_RES | TXRQST_RES | MSGLST_RES | NEWDAT_RES);
|
||||
|
||||
stats->tx_packets++;
|
||||
if (unlikely(!priv->tx_skb)) {
|
||||
netdev_err(dev, "missing tx skb in tx interrupt\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (unlikely(ctrl1 & MSGLST_SET)) {
|
||||
stats->rx_over_errors++;
|
||||
stats->rx_errors++;
|
||||
}
|
||||
|
||||
/* When the CC770 is sending an RTR message and it receives a regular
|
||||
* message that matches the id of the RTR message, it will overwrite the
|
||||
* outgoing message in the TX register. When this happens we must
|
||||
* process the received message and try to transmit the outgoing skb
|
||||
* again.
|
||||
*/
|
||||
if (unlikely(ctrl1 & NEWDAT_SET)) {
|
||||
cc770_rx(dev, mo, ctrl1);
|
||||
cc770_tx(dev, mo);
|
||||
return;
|
||||
}
|
||||
|
||||
can_put_echo_skb(priv->tx_skb, dev, 0);
|
||||
can_get_echo_skb(dev, 0);
|
||||
|
||||
cf = (struct can_frame *)priv->tx_skb->data;
|
||||
stats->tx_bytes += cf->can_dlc;
|
||||
stats->tx_packets++;
|
||||
|
||||
priv->tx_skb = NULL;
|
||||
|
||||
netif_wake_queue(dev);
|
||||
}
|
||||
|
||||
@ -804,6 +826,7 @@ struct net_device *alloc_cc770dev(int sizeof_priv)
|
||||
priv->can.do_set_bittiming = cc770_set_bittiming;
|
||||
priv->can.do_set_mode = cc770_set_mode;
|
||||
priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES;
|
||||
priv->tx_skb = NULL;
|
||||
|
||||
memcpy(priv->obj_flags, cc770_obj_flags, sizeof(cc770_obj_flags));
|
||||
|
||||
|
@ -193,6 +193,8 @@ struct cc770_priv {
|
||||
u8 cpu_interface; /* CPU interface register */
|
||||
u8 clkout; /* Clock out register */
|
||||
u8 bus_config; /* Bus conffiguration register */
|
||||
|
||||
struct sk_buff *tx_skb;
|
||||
};
|
||||
|
||||
struct net_device *alloc_cc770dev(int sizeof_priv);
|
||||
|
Loading…
Reference in New Issue
Block a user