mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-11-26 13:20:50 +07:00
linux-can-fixes-for-4.14-20171019
-----BEGIN PGP SIGNATURE----- iQFHBAABCgAxFiEE4bay/IylYqM/npjQHv7KIOw4HPYFAlnohyMTHG1rbEBwZW5n dXRyb25peC5kZQAKCRAe/sog7Dgc9jRFCACmSBz2H1yW5VfjrN3ZgoEoUo8P5qCZ 7mXvTstTASF20T7kFqNS2K94CMVjBYRUIHvihp0LmPmPAmpmQRNedAssWuZpMflw xhaH8T8YWbyzHU2MBZP9WtTjrTilPEPcjvFSgYw6wpHW7VC3S/ffEN8Mj3ymR6bW KRw7gemXpvYUxPrGGCzyvFy4G+KptyPcAD6I8ceDUtdkwK4TXGYqEAoSqxtAIUHX dgRLzheOv8sDh+dM+ZNpH6UUkzK0gVHQ40lgXydZazEwPPq9zdj2Ec/6qpR5fkUH dnCIhzLNiCJOMGSfzkf0Esef1zBpU8oJmILbgf97CdayaW9cA1EUleGW =HYTx -----END PGP SIGNATURE----- Merge tag 'linux-can-fixes-for-4.14-20171019' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can Marc Kleine-Budde says: ==================== pull-request: can 2017-10-19 this is a pull request of 11 patches for the upcoming 4.14 release. There are 6 patches by ZHU Yi for the flexcan driver, that work around the CAN error handling state transition problems found in various incarnations of the flexcan IP core. The patch by Colin Ian King fixes a potential NULL pointer deref in the CAN broad cast manager (bcm). One patch by me replaces a direct deref of a RCU protected pointer by rcu_access_pointer. My second patch adds missing OOM error handling in af_can. A patch by Stefan Mätje for the esd_usb2 driver fixes the dlc in received RTR frames. And the last patch is by Wolfgang Grandegger, it fixes a busy loop in the gs_usb driver in case it runs out of TX contexts. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
c69d75ae15
@ -182,22 +182,23 @@
|
||||
/* FLEXCAN hardware feature flags
|
||||
*
|
||||
* Below is some version info we got:
|
||||
* SOC Version IP-Version Glitch- [TR]WRN_INT Memory err RTR re-
|
||||
* Filter? connected? detection ception in MB
|
||||
* MX25 FlexCAN2 03.00.00.00 no no no no
|
||||
* MX28 FlexCAN2 03.00.04.00 yes yes no no
|
||||
* MX35 FlexCAN2 03.00.00.00 no no no no
|
||||
* MX53 FlexCAN2 03.00.00.00 yes no no no
|
||||
* MX6s FlexCAN3 10.00.12.00 yes yes no yes
|
||||
* VF610 FlexCAN3 ? no yes yes yes?
|
||||
* SOC Version IP-Version Glitch- [TR]WRN_INT IRQ Err Memory err RTR re-
|
||||
* Filter? connected? Passive detection ception in MB
|
||||
* MX25 FlexCAN2 03.00.00.00 no no ? no no
|
||||
* MX28 FlexCAN2 03.00.04.00 yes yes no no no
|
||||
* MX35 FlexCAN2 03.00.00.00 no no ? no no
|
||||
* MX53 FlexCAN2 03.00.00.00 yes no no no no
|
||||
* MX6s FlexCAN3 10.00.12.00 yes yes no no yes
|
||||
* VF610 FlexCAN3 ? no yes ? yes yes?
|
||||
*
|
||||
* Some SOCs do not have the RX_WARN & TX_WARN interrupt line connected.
|
||||
*/
|
||||
#define FLEXCAN_QUIRK_BROKEN_ERR_STATE BIT(1) /* [TR]WRN_INT not connected */
|
||||
#define FLEXCAN_QUIRK_BROKEN_WERR_STATE BIT(1) /* [TR]WRN_INT not connected */
|
||||
#define FLEXCAN_QUIRK_DISABLE_RXFG BIT(2) /* Disable RX FIFO Global mask */
|
||||
#define FLEXCAN_QUIRK_ENABLE_EACEN_RRS BIT(3) /* Enable EACEN and RRS bit in ctrl2 */
|
||||
#define FLEXCAN_QUIRK_DISABLE_MECR BIT(4) /* Disable Memory error detection */
|
||||
#define FLEXCAN_QUIRK_USE_OFF_TIMESTAMP BIT(5) /* Use timestamp based offloading */
|
||||
#define FLEXCAN_QUIRK_BROKEN_PERR_STATE BIT(6) /* No interrupt for error passive */
|
||||
|
||||
/* Structure of the message buffer */
|
||||
struct flexcan_mb {
|
||||
@ -281,14 +282,17 @@ struct flexcan_priv {
|
||||
};
|
||||
|
||||
static const struct flexcan_devtype_data fsl_p1010_devtype_data = {
|
||||
.quirks = FLEXCAN_QUIRK_BROKEN_ERR_STATE,
|
||||
.quirks = FLEXCAN_QUIRK_BROKEN_WERR_STATE |
|
||||
FLEXCAN_QUIRK_BROKEN_PERR_STATE,
|
||||
};
|
||||
|
||||
static const struct flexcan_devtype_data fsl_imx28_devtype_data;
|
||||
static const struct flexcan_devtype_data fsl_imx28_devtype_data = {
|
||||
.quirks = FLEXCAN_QUIRK_BROKEN_PERR_STATE,
|
||||
};
|
||||
|
||||
static const struct flexcan_devtype_data fsl_imx6q_devtype_data = {
|
||||
.quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_ENABLE_EACEN_RRS |
|
||||
FLEXCAN_QUIRK_USE_OFF_TIMESTAMP,
|
||||
FLEXCAN_QUIRK_USE_OFF_TIMESTAMP | FLEXCAN_QUIRK_BROKEN_PERR_STATE,
|
||||
};
|
||||
|
||||
static const struct flexcan_devtype_data fsl_vf610_devtype_data = {
|
||||
@ -335,6 +339,22 @@ static inline void flexcan_write(u32 val, void __iomem *addr)
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline void flexcan_error_irq_enable(const struct flexcan_priv *priv)
|
||||
{
|
||||
struct flexcan_regs __iomem *regs = priv->regs;
|
||||
u32 reg_ctrl = (priv->reg_ctrl_default | FLEXCAN_CTRL_ERR_MSK);
|
||||
|
||||
flexcan_write(reg_ctrl, ®s->ctrl);
|
||||
}
|
||||
|
||||
static inline void flexcan_error_irq_disable(const struct flexcan_priv *priv)
|
||||
{
|
||||
struct flexcan_regs __iomem *regs = priv->regs;
|
||||
u32 reg_ctrl = (priv->reg_ctrl_default & ~FLEXCAN_CTRL_ERR_MSK);
|
||||
|
||||
flexcan_write(reg_ctrl, ®s->ctrl);
|
||||
}
|
||||
|
||||
static inline int flexcan_transceiver_enable(const struct flexcan_priv *priv)
|
||||
{
|
||||
if (!priv->reg_xceiver)
|
||||
@ -713,6 +733,7 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
|
||||
struct flexcan_regs __iomem *regs = priv->regs;
|
||||
irqreturn_t handled = IRQ_NONE;
|
||||
u32 reg_iflag1, reg_esr;
|
||||
enum can_state last_state = priv->can.state;
|
||||
|
||||
reg_iflag1 = flexcan_read(®s->iflag1);
|
||||
|
||||
@ -765,8 +786,10 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
|
||||
flexcan_write(reg_esr & FLEXCAN_ESR_ALL_INT, ®s->esr);
|
||||
}
|
||||
|
||||
/* state change interrupt */
|
||||
if (reg_esr & FLEXCAN_ESR_ERR_STATE)
|
||||
/* state change interrupt or broken error state quirk fix is enabled */
|
||||
if ((reg_esr & FLEXCAN_ESR_ERR_STATE) ||
|
||||
(priv->devtype_data->quirks & (FLEXCAN_QUIRK_BROKEN_WERR_STATE |
|
||||
FLEXCAN_QUIRK_BROKEN_PERR_STATE)))
|
||||
flexcan_irq_state(dev, reg_esr);
|
||||
|
||||
/* bus error IRQ - handle if bus error reporting is activated */
|
||||
@ -774,6 +797,44 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
|
||||
(priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING))
|
||||
flexcan_irq_bus_err(dev, reg_esr);
|
||||
|
||||
/* availability of error interrupt among state transitions in case
|
||||
* bus error reporting is de-activated and
|
||||
* FLEXCAN_QUIRK_BROKEN_PERR_STATE is enabled:
|
||||
* +--------------------------------------------------------------+
|
||||
* | +----------------------------------------------+ [stopped / |
|
||||
* | | | sleeping] -+
|
||||
* +-+-> active <-> warning <-> passive -> bus off -+
|
||||
* ___________^^^^^^^^^^^^_______________________________
|
||||
* disabled(1) enabled disabled
|
||||
*
|
||||
* (1): enabled if FLEXCAN_QUIRK_BROKEN_WERR_STATE is enabled
|
||||
*/
|
||||
if ((last_state != priv->can.state) &&
|
||||
(priv->devtype_data->quirks & FLEXCAN_QUIRK_BROKEN_PERR_STATE) &&
|
||||
!(priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)) {
|
||||
switch (priv->can.state) {
|
||||
case CAN_STATE_ERROR_ACTIVE:
|
||||
if (priv->devtype_data->quirks &
|
||||
FLEXCAN_QUIRK_BROKEN_WERR_STATE)
|
||||
flexcan_error_irq_enable(priv);
|
||||
else
|
||||
flexcan_error_irq_disable(priv);
|
||||
break;
|
||||
|
||||
case CAN_STATE_ERROR_WARNING:
|
||||
flexcan_error_irq_enable(priv);
|
||||
break;
|
||||
|
||||
case CAN_STATE_ERROR_PASSIVE:
|
||||
case CAN_STATE_BUS_OFF:
|
||||
flexcan_error_irq_disable(priv);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
@ -887,7 +948,7 @@ static int flexcan_chip_start(struct net_device *dev)
|
||||
* on most Flexcan cores, too. Otherwise we don't get
|
||||
* any error warning or passive interrupts.
|
||||
*/
|
||||
if (priv->devtype_data->quirks & FLEXCAN_QUIRK_BROKEN_ERR_STATE ||
|
||||
if (priv->devtype_data->quirks & FLEXCAN_QUIRK_BROKEN_WERR_STATE ||
|
||||
priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)
|
||||
reg_ctrl |= FLEXCAN_CTRL_ERR_MSK;
|
||||
else
|
||||
|
@ -333,7 +333,7 @@ static void esd_usb2_rx_can_msg(struct esd_usb2_net_priv *priv,
|
||||
}
|
||||
|
||||
cf->can_id = id & ESD_IDMASK;
|
||||
cf->can_dlc = get_can_dlc(msg->msg.rx.dlc);
|
||||
cf->can_dlc = get_can_dlc(msg->msg.rx.dlc & ~ESD_RTR);
|
||||
|
||||
if (id & ESD_EXTID)
|
||||
cf->can_id |= CAN_EFF_FLAG;
|
||||
|
@ -375,6 +375,8 @@ static void gs_usb_receive_bulk_callback(struct urb *urb)
|
||||
|
||||
gs_free_tx_context(txc);
|
||||
|
||||
atomic_dec(&dev->active_tx_urbs);
|
||||
|
||||
netif_wake_queue(netdev);
|
||||
}
|
||||
|
||||
@ -463,14 +465,6 @@ static void gs_usb_xmit_callback(struct urb *urb)
|
||||
urb->transfer_buffer_length,
|
||||
urb->transfer_buffer,
|
||||
urb->transfer_dma);
|
||||
|
||||
atomic_dec(&dev->active_tx_urbs);
|
||||
|
||||
if (!netif_device_present(netdev))
|
||||
return;
|
||||
|
||||
if (netif_queue_stopped(netdev))
|
||||
netif_wake_queue(netdev);
|
||||
}
|
||||
|
||||
static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb,
|
||||
|
@ -78,7 +78,7 @@ MODULE_PARM_DESC(stats_timer, "enable timer for statistics (default:on)");
|
||||
static struct kmem_cache *rcv_cache __read_mostly;
|
||||
|
||||
/* table of registered CAN protocols */
|
||||
static const struct can_proto *proto_tab[CAN_NPROTO] __read_mostly;
|
||||
static const struct can_proto __rcu *proto_tab[CAN_NPROTO] __read_mostly;
|
||||
static DEFINE_MUTEX(proto_tab_lock);
|
||||
|
||||
static atomic_t skbcounter = ATOMIC_INIT(0);
|
||||
@ -788,7 +788,7 @@ int can_proto_register(const struct can_proto *cp)
|
||||
|
||||
mutex_lock(&proto_tab_lock);
|
||||
|
||||
if (proto_tab[proto]) {
|
||||
if (rcu_access_pointer(proto_tab[proto])) {
|
||||
pr_err("can: protocol %d already registered\n", proto);
|
||||
err = -EBUSY;
|
||||
} else
|
||||
@ -812,7 +812,7 @@ void can_proto_unregister(const struct can_proto *cp)
|
||||
int proto = cp->protocol;
|
||||
|
||||
mutex_lock(&proto_tab_lock);
|
||||
BUG_ON(proto_tab[proto] != cp);
|
||||
BUG_ON(rcu_access_pointer(proto_tab[proto]) != cp);
|
||||
RCU_INIT_POINTER(proto_tab[proto], NULL);
|
||||
mutex_unlock(&proto_tab_lock);
|
||||
|
||||
@ -875,9 +875,14 @@ static int can_pernet_init(struct net *net)
|
||||
spin_lock_init(&net->can.can_rcvlists_lock);
|
||||
net->can.can_rx_alldev_list =
|
||||
kzalloc(sizeof(struct dev_rcv_lists), GFP_KERNEL);
|
||||
|
||||
if (!net->can.can_rx_alldev_list)
|
||||
goto out;
|
||||
net->can.can_stats = kzalloc(sizeof(struct s_stats), GFP_KERNEL);
|
||||
if (!net->can.can_stats)
|
||||
goto out_free_alldev_list;
|
||||
net->can.can_pstats = kzalloc(sizeof(struct s_pstats), GFP_KERNEL);
|
||||
if (!net->can.can_pstats)
|
||||
goto out_free_can_stats;
|
||||
|
||||
if (IS_ENABLED(CONFIG_PROC_FS)) {
|
||||
/* the statistics are updated every second (timer triggered) */
|
||||
@ -892,6 +897,13 @@ static int can_pernet_init(struct net *net)
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out_free_can_stats:
|
||||
kfree(net->can.can_stats);
|
||||
out_free_alldev_list:
|
||||
kfree(net->can.can_rx_alldev_list);
|
||||
out:
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static void can_pernet_exit(struct net *net)
|
||||
|
@ -1493,13 +1493,14 @@ static int bcm_init(struct sock *sk)
|
||||
static int bcm_release(struct socket *sock)
|
||||
{
|
||||
struct sock *sk = sock->sk;
|
||||
struct net *net = sock_net(sk);
|
||||
struct net *net;
|
||||
struct bcm_sock *bo;
|
||||
struct bcm_op *op, *next;
|
||||
|
||||
if (sk == NULL)
|
||||
if (!sk)
|
||||
return 0;
|
||||
|
||||
net = sock_net(sk);
|
||||
bo = bcm_sk(sk);
|
||||
|
||||
/* remove bcm_ops, timer, rx_unregister(), etc. */
|
||||
|
Loading…
Reference in New Issue
Block a user