Commit 2a62df36 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge tag 'linux-can-fixes-for-5.16-20211207' of...

Merge tag 'linux-can-fixes-for-5.16-20211207' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can

Marc Kleine-Budde says:

====================
can 2021-12-07

The 1st patch is by Vincent Mailhol and fixes a use after free in the
pch_can driver.

Dan Carpenter fixes a use after free in the ems_pcmcia sja1000 driver.

The remaining 7 patches target the m_can driver. Brian Silverman
contributes a patch to disable and ignore the ELO interrupt, which is
currently not handled in the driver and may lead to an interrupt
storm. Vincent Mailhol's patch fixes a memory leak in the error path
of the m_can_read_fifo() function. The remaining patches are
contributed by Matthias Schiffer, first a iomap_read_fifo() and
iomap_write_fifo() functions are fixed in the PCI glue driver, then
the clock rate for the Intel Ekhart Lake platform is fixed, the last 3
patches add support for the custom bit timings on the Elkhart Lake
platform.

* tag 'linux-can-fixes-for-5.16-20211207' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can:
  can: m_can: pci: use custom bit timings for Elkhart Lake
  can: m_can: make custom bittiming fields const
  Revert "can: m_can: remove support for custom bit timing"
  can: m_can: pci: fix incorrect reference clock rate
  can: m_can: pci: fix iomap_read_fifo() and iomap_write_fifo()
  can: m_can: m_can_read_fifo: fix memory leak in error branch
  can: m_can: Disable and ignore ELO interrupt
  can: sja1000: fix use after free in ems_pcmcia_add_card()
  can: pch_can: pch_can_rx_normal: fix use after free
====================

Link: https://lore.kernel.org/r/20211207102420.120131-1-mkl@pengutronix.de


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 4dbb0dad ea4c1787
Loading
Loading
Loading
Loading
+27 −15
Original line number Diff line number Diff line
@@ -204,16 +204,16 @@ enum m_can_reg {

/* Interrupts for version 3.0.x */
#define IR_ERR_LEC_30X	(IR_STE	| IR_FOE | IR_ACKE | IR_BE | IR_CRCE)
#define IR_ERR_BUS_30X	(IR_ERR_LEC_30X | IR_WDI | IR_ELO | IR_BEU | \
			 IR_BEC | IR_TOO | IR_MRAF | IR_TSW | IR_TEFL | \
			 IR_RF1L | IR_RF0L)
#define IR_ERR_BUS_30X	(IR_ERR_LEC_30X | IR_WDI | IR_BEU | IR_BEC | \
			 IR_TOO | IR_MRAF | IR_TSW | IR_TEFL | IR_RF1L | \
			 IR_RF0L)
#define IR_ERR_ALL_30X	(IR_ERR_STATE | IR_ERR_BUS_30X)

/* Interrupts for version >= 3.1.x */
#define IR_ERR_LEC_31X	(IR_PED | IR_PEA)
#define IR_ERR_BUS_31X      (IR_ERR_LEC_31X | IR_WDI | IR_ELO | IR_BEU | \
			 IR_BEC | IR_TOO | IR_MRAF | IR_TSW | IR_TEFL | \
			 IR_RF1L | IR_RF0L)
#define IR_ERR_BUS_31X      (IR_ERR_LEC_31X | IR_WDI | IR_BEU | IR_BEC | \
			 IR_TOO | IR_MRAF | IR_TSW | IR_TEFL | IR_RF1L | \
			 IR_RF0L)
#define IR_ERR_ALL_31X	(IR_ERR_STATE | IR_ERR_BUS_31X)

/* Interrupt Line Select (ILS) */
@@ -517,7 +517,7 @@ static int m_can_read_fifo(struct net_device *dev, u32 rxfs)
		err = m_can_fifo_read(cdev, fgi, M_CAN_FIFO_DATA,
				      cf->data, DIV_ROUND_UP(cf->len, 4));
		if (err)
			goto out_fail;
			goto out_free_skb;
	}

	/* acknowledge rx fifo 0 */
@@ -532,6 +532,8 @@ static int m_can_read_fifo(struct net_device *dev, u32 rxfs)

	return 0;

out_free_skb:
	kfree_skb(skb);
out_fail:
	netdev_err(dev, "FIFO read returned %d\n", err);
	return err;
@@ -810,8 +812,6 @@ static void m_can_handle_other_err(struct net_device *dev, u32 irqstatus)
{
	if (irqstatus & IR_WDI)
		netdev_err(dev, "Message RAM Watchdog event due to missing READY\n");
	if (irqstatus & IR_ELO)
		netdev_err(dev, "Error Logging Overflow\n");
	if (irqstatus & IR_BEU)
		netdev_err(dev, "Bit Error Uncorrected\n");
	if (irqstatus & IR_BEC)
@@ -1494,20 +1494,32 @@ static int m_can_dev_setup(struct m_can_classdev *cdev)
	case 30:
		/* CAN_CTRLMODE_FD_NON_ISO is fixed with M_CAN IP v3.0.x */
		can_set_static_ctrlmode(dev, CAN_CTRLMODE_FD_NON_ISO);
		cdev->can.bittiming_const = &m_can_bittiming_const_30X;
		cdev->can.data_bittiming_const = &m_can_data_bittiming_const_30X;
		cdev->can.bittiming_const = cdev->bit_timing ?
			cdev->bit_timing : &m_can_bittiming_const_30X;

		cdev->can.data_bittiming_const = cdev->data_timing ?
			cdev->data_timing :
			&m_can_data_bittiming_const_30X;
		break;
	case 31:
		/* CAN_CTRLMODE_FD_NON_ISO is fixed with M_CAN IP v3.1.x */
		can_set_static_ctrlmode(dev, CAN_CTRLMODE_FD_NON_ISO);
		cdev->can.bittiming_const = &m_can_bittiming_const_31X;
		cdev->can.data_bittiming_const = &m_can_data_bittiming_const_31X;
		cdev->can.bittiming_const = cdev->bit_timing ?
			cdev->bit_timing : &m_can_bittiming_const_31X;

		cdev->can.data_bittiming_const = cdev->data_timing ?
			cdev->data_timing :
			&m_can_data_bittiming_const_31X;
		break;
	case 32:
	case 33:
		/* Support both MCAN version v3.2.x and v3.3.0 */
		cdev->can.bittiming_const = &m_can_bittiming_const_31X;
		cdev->can.data_bittiming_const = &m_can_data_bittiming_const_31X;
		cdev->can.bittiming_const = cdev->bit_timing ?
			cdev->bit_timing : &m_can_bittiming_const_31X;

		cdev->can.data_bittiming_const = cdev->data_timing ?
			cdev->data_timing :
			&m_can_data_bittiming_const_31X;

		cdev->can.ctrlmode_supported |=
			(m_can_niso_supported(cdev) ?
+3 −0
Original line number Diff line number Diff line
@@ -85,6 +85,9 @@ struct m_can_classdev {
	struct sk_buff *tx_skb;
	struct phy *transceiver;

	const struct can_bittiming_const *bit_timing;
	const struct can_bittiming_const *data_timing;

	struct m_can_ops *ops;

	int version;
+56 −6
Original line number Diff line number Diff line
@@ -18,9 +18,14 @@

#define M_CAN_PCI_MMIO_BAR		0

#define M_CAN_CLOCK_FREQ_EHL		100000000
#define CTL_CSR_INT_CTL_OFFSET		0x508

struct m_can_pci_config {
	const struct can_bittiming_const *bit_timing;
	const struct can_bittiming_const *data_timing;
	unsigned int clock_freq;
};

struct m_can_pci_priv {
	struct m_can_classdev cdev;

@@ -42,8 +47,13 @@ static u32 iomap_read_reg(struct m_can_classdev *cdev, int reg)
static int iomap_read_fifo(struct m_can_classdev *cdev, int offset, void *val, size_t val_count)
{
	struct m_can_pci_priv *priv = cdev_to_priv(cdev);
	void __iomem *src = priv->base + offset;

	ioread32_rep(priv->base + offset, val, val_count);
	while (val_count--) {
		*(unsigned int *)val = ioread32(src);
		val += 4;
		src += 4;
	}

	return 0;
}
@@ -61,8 +71,13 @@ static int iomap_write_fifo(struct m_can_classdev *cdev, int offset,
			    const void *val, size_t val_count)
{
	struct m_can_pci_priv *priv = cdev_to_priv(cdev);
	void __iomem *dst = priv->base + offset;

	iowrite32_rep(priv->base + offset, val, val_count);
	while (val_count--) {
		iowrite32(*(unsigned int *)val, dst);
		val += 4;
		dst += 4;
	}

	return 0;
}
@@ -74,9 +89,40 @@ static struct m_can_ops m_can_pci_ops = {
	.read_fifo = iomap_read_fifo,
};

static const struct can_bittiming_const m_can_bittiming_const_ehl = {
	.name = KBUILD_MODNAME,
	.tseg1_min = 2,		/* Time segment 1 = prop_seg + phase_seg1 */
	.tseg1_max = 64,
	.tseg2_min = 1,		/* Time segment 2 = phase_seg2 */
	.tseg2_max = 128,
	.sjw_max = 128,
	.brp_min = 1,
	.brp_max = 512,
	.brp_inc = 1,
};

static const struct can_bittiming_const m_can_data_bittiming_const_ehl = {
	.name = KBUILD_MODNAME,
	.tseg1_min = 2,		/* Time segment 1 = prop_seg + phase_seg1 */
	.tseg1_max = 16,
	.tseg2_min = 1,		/* Time segment 2 = phase_seg2 */
	.tseg2_max = 8,
	.sjw_max = 4,
	.brp_min = 1,
	.brp_max = 32,
	.brp_inc = 1,
};

static const struct m_can_pci_config m_can_pci_ehl = {
	.bit_timing = &m_can_bittiming_const_ehl,
	.data_timing = &m_can_data_bittiming_const_ehl,
	.clock_freq = 200000000,
};

static int m_can_pci_probe(struct pci_dev *pci, const struct pci_device_id *id)
{
	struct device *dev = &pci->dev;
	const struct m_can_pci_config *cfg;
	struct m_can_classdev *mcan_class;
	struct m_can_pci_priv *priv;
	void __iomem *base;
@@ -104,6 +150,8 @@ static int m_can_pci_probe(struct pci_dev *pci, const struct pci_device_id *id)
	if (!mcan_class)
		return -ENOMEM;

	cfg = (const struct m_can_pci_config *)id->driver_data;

	priv = cdev_to_priv(mcan_class);

	priv->base = base;
@@ -115,7 +163,9 @@ static int m_can_pci_probe(struct pci_dev *pci, const struct pci_device_id *id)
	mcan_class->dev = &pci->dev;
	mcan_class->net->irq = pci_irq_vector(pci, 0);
	mcan_class->pm_clock_support = 1;
	mcan_class->can.clock.freq = id->driver_data;
	mcan_class->bit_timing = cfg->bit_timing;
	mcan_class->data_timing = cfg->data_timing;
	mcan_class->can.clock.freq = cfg->clock_freq;
	mcan_class->ops = &m_can_pci_ops;

	pci_set_drvdata(pci, mcan_class);
@@ -168,8 +218,8 @@ static SIMPLE_DEV_PM_OPS(m_can_pci_pm_ops,
			 m_can_pci_suspend, m_can_pci_resume);

static const struct pci_device_id m_can_pci_id_table[] = {
	{ PCI_VDEVICE(INTEL, 0x4bc1), M_CAN_CLOCK_FREQ_EHL, },
	{ PCI_VDEVICE(INTEL, 0x4bc2), M_CAN_CLOCK_FREQ_EHL, },
	{ PCI_VDEVICE(INTEL, 0x4bc1), (kernel_ulong_t)&m_can_pci_ehl, },
	{ PCI_VDEVICE(INTEL, 0x4bc2), (kernel_ulong_t)&m_can_pci_ehl, },
	{  }	/* Terminating Entry */
};
MODULE_DEVICE_TABLE(pci, m_can_pci_id_table);
+1 −1
Original line number Diff line number Diff line
@@ -692,11 +692,11 @@ static int pch_can_rx_normal(struct net_device *ndev, u32 obj_num, int quota)
			cf->data[i + 1] = data_reg >> 8;
		}

		netif_receive_skb(skb);
		rcv_pkts++;
		stats->rx_packets++;
		quota--;
		stats->rx_bytes += cf->len;
		netif_receive_skb(skb);

		pch_fifo_thresh(priv, obj_num);
		obj_num++;
+6 −1
Original line number Diff line number Diff line
@@ -234,7 +234,12 @@ static int ems_pcmcia_add_card(struct pcmcia_device *pdev, unsigned long base)
			free_sja1000dev(dev);
	}

	err = request_irq(dev->irq, &ems_pcmcia_interrupt, IRQF_SHARED,
	if (!card->channels) {
		err = -ENODEV;
		goto failure_cleanup;
	}

	err = request_irq(pdev->irq, &ems_pcmcia_interrupt, IRQF_SHARED,
			  DRV_NAME, card);
	if (!err)
		return 0;