linux-can-fixes-for-5.16-20211207
-----BEGIN PGP SIGNATURE----- iQFHBAABCgAxFiEEK3kIWJt9yTYMP3ehqclaivrt76kFAmGvM24THG1rbEBwZW5n dXRyb25peC5kZQAKCRCpyVqK+u3vqZL8CACmYXCIKdLxumCmfa7z61r6Y839grFl weBo1dgrg/FIIyxro0EEmGi3ZRGrVcQNyQOQKl9xtt8FFmkrl5yCioQ5N+ib/Qt7 6BhMN0kdaWQDzgyIT5BT8Ba/13S4Hpjb7baDBf+Rqw7WemeX2hni8Dx4WxflfMbo lpxuRyDtUvndUHVzATkbB8TLsmB50wdTinzZkY3IV8bAhLcznQ2vYvV4HblbeNlA BtEEtAjsR7zFfyqDmxOIOdqMD4m4vjUnaOoT6KQznNIy1EYxFgX7VFNAp3DeGaX3 bM4CTEbVm980hPgm8tjFL0p6BExWWR9q6lR/x41O/P2cQ2PKNDSuBnuo =4e0K -----END PGP SIGNATURE----- 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: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
2a62df3692
drivers/net/can
@ -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) ?
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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++;
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user