linux-can-fixes-for-3.15-20140424
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iEYEABECAAYFAlNZf5EACgkQjTAFq1RaXHPFhACghgdQaxG++36VEhtToY+H8o2x 3UUAniZ+DbwtSapriPekjVKRC7VuQFsD =N5FA -----END PGP SIGNATURE----- Merge tag 'linux-can-fixes-for-3.15-20140424' of git://gitorious.org/linux-can/linux-can Marc Kleine-Budde says: ==================== this is a pull request for net/master, for the v3.15 release cycle, consisting of 26 patches. Thomas Gleixner contributes 21 patches for the c_can driver, which address several shortcomings in the driver like hardware initialisation, concurrency, message ordering and poor performance. Two patches Oliver Hartkopp, one adds a missing lock to the sja1000_isa driver, the other one fixes the return value in the generic bit time configuration function. And finally a patch by Alexander Stein, that fixes the slcan driver to use the correct spinlock variant. To make it 26 patches, Wolfgang Grandegger patch for the c_can_pci driver, which enables the bus master only for MSI and a patch by Wolfram Sang, which converts the 'instance' in the c_can driver to the proper type. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
69d268b772
8 changed files with 346 additions and 385 deletions
|
@ -14,6 +14,13 @@ config CAN_C_CAN_PLATFORM
|
||||||
SPEAr1310 and SPEAr320 evaluation boards & TI (www.ti.com)
|
SPEAr1310 and SPEAr320 evaluation boards & TI (www.ti.com)
|
||||||
boards like am335x, dm814x, dm813x and dm811x.
|
boards like am335x, dm814x, dm813x and dm811x.
|
||||||
|
|
||||||
|
config CAN_C_CAN_STRICT_FRAME_ORDERING
|
||||||
|
bool "Force a strict RX CAN frame order (may cause frame loss)"
|
||||||
|
---help---
|
||||||
|
The RX split buffer prevents packet reordering but can cause packet
|
||||||
|
loss. Only enable this option when you accept to lose CAN frames
|
||||||
|
in favour of getting the received CAN frames in the correct order.
|
||||||
|
|
||||||
config CAN_C_CAN_PCI
|
config CAN_C_CAN_PCI
|
||||||
tristate "Generic PCI Bus based C_CAN/D_CAN driver"
|
tristate "Generic PCI Bus based C_CAN/D_CAN driver"
|
||||||
depends on PCI
|
depends on PCI
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -22,14 +22,6 @@
|
||||||
#ifndef C_CAN_H
|
#ifndef C_CAN_H
|
||||||
#define C_CAN_H
|
#define C_CAN_H
|
||||||
|
|
||||||
/*
|
|
||||||
* IFx register masks:
|
|
||||||
* allow easy operation on 16-bit registers when the
|
|
||||||
* argument is 32-bit instead
|
|
||||||
*/
|
|
||||||
#define IFX_WRITE_LOW_16BIT(x) ((x) & 0xFFFF)
|
|
||||||
#define IFX_WRITE_HIGH_16BIT(x) (((x) & 0xFFFF0000) >> 16)
|
|
||||||
|
|
||||||
/* message object split */
|
/* message object split */
|
||||||
#define C_CAN_NO_OF_OBJECTS 32
|
#define C_CAN_NO_OF_OBJECTS 32
|
||||||
#define C_CAN_MSG_OBJ_RX_NUM 16
|
#define C_CAN_MSG_OBJ_RX_NUM 16
|
||||||
|
@ -45,8 +37,6 @@
|
||||||
|
|
||||||
#define C_CAN_MSG_OBJ_RX_SPLIT 9
|
#define C_CAN_MSG_OBJ_RX_SPLIT 9
|
||||||
#define C_CAN_MSG_RX_LOW_LAST (C_CAN_MSG_OBJ_RX_SPLIT - 1)
|
#define C_CAN_MSG_RX_LOW_LAST (C_CAN_MSG_OBJ_RX_SPLIT - 1)
|
||||||
|
|
||||||
#define C_CAN_NEXT_MSG_OBJ_MASK (C_CAN_MSG_OBJ_TX_NUM - 1)
|
|
||||||
#define RECEIVE_OBJECT_BITS 0x0000ffff
|
#define RECEIVE_OBJECT_BITS 0x0000ffff
|
||||||
|
|
||||||
enum reg {
|
enum reg {
|
||||||
|
@ -183,23 +173,20 @@ struct c_can_priv {
|
||||||
struct napi_struct napi;
|
struct napi_struct napi;
|
||||||
struct net_device *dev;
|
struct net_device *dev;
|
||||||
struct device *device;
|
struct device *device;
|
||||||
spinlock_t xmit_lock;
|
atomic_t tx_active;
|
||||||
int tx_object;
|
unsigned long tx_dir;
|
||||||
int current_status;
|
|
||||||
int last_status;
|
int last_status;
|
||||||
u16 (*read_reg) (struct c_can_priv *priv, enum reg index);
|
u16 (*read_reg) (struct c_can_priv *priv, enum reg index);
|
||||||
void (*write_reg) (struct c_can_priv *priv, enum reg index, u16 val);
|
void (*write_reg) (struct c_can_priv *priv, enum reg index, u16 val);
|
||||||
void __iomem *base;
|
void __iomem *base;
|
||||||
const u16 *regs;
|
const u16 *regs;
|
||||||
unsigned long irq_flags; /* for request_irq() */
|
|
||||||
unsigned int tx_next;
|
|
||||||
unsigned int tx_echo;
|
|
||||||
void *priv; /* for board-specific data */
|
void *priv; /* for board-specific data */
|
||||||
u16 irqstatus;
|
|
||||||
enum c_can_dev_id type;
|
enum c_can_dev_id type;
|
||||||
u32 __iomem *raminit_ctrlreg;
|
u32 __iomem *raminit_ctrlreg;
|
||||||
unsigned int instance;
|
int instance;
|
||||||
void (*raminit) (const struct c_can_priv *priv, bool enable);
|
void (*raminit) (const struct c_can_priv *priv, bool enable);
|
||||||
|
u32 comm_rcv_high;
|
||||||
|
u32 rxmasked;
|
||||||
u32 dlc[C_CAN_MSG_OBJ_TX_NUM];
|
u32 dlc[C_CAN_MSG_OBJ_TX_NUM];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -84,8 +84,11 @@ static int c_can_pci_probe(struct pci_dev *pdev,
|
||||||
goto out_disable_device;
|
goto out_disable_device;
|
||||||
}
|
}
|
||||||
|
|
||||||
pci_set_master(pdev);
|
ret = pci_enable_msi(pdev);
|
||||||
pci_enable_msi(pdev);
|
if (!ret) {
|
||||||
|
dev_info(&pdev->dev, "MSI enabled\n");
|
||||||
|
pci_set_master(pdev);
|
||||||
|
}
|
||||||
|
|
||||||
addr = pci_iomap(pdev, 0, pci_resource_len(pdev, 0));
|
addr = pci_iomap(pdev, 0, pci_resource_len(pdev, 0));
|
||||||
if (!addr) {
|
if (!addr) {
|
||||||
|
@ -132,6 +135,8 @@ static int c_can_pci_probe(struct pci_dev *pdev,
|
||||||
goto out_free_c_can;
|
goto out_free_c_can;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
priv->type = c_can_pci_data->type;
|
||||||
|
|
||||||
/* Configure access to registers */
|
/* Configure access to registers */
|
||||||
switch (c_can_pci_data->reg_align) {
|
switch (c_can_pci_data->reg_align) {
|
||||||
case C_CAN_REG_ALIGN_32:
|
case C_CAN_REG_ALIGN_32:
|
||||||
|
|
|
@ -222,7 +222,7 @@ static int c_can_plat_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
|
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
|
||||||
priv->raminit_ctrlreg = devm_ioremap_resource(&pdev->dev, res);
|
priv->raminit_ctrlreg = devm_ioremap_resource(&pdev->dev, res);
|
||||||
if (IS_ERR(priv->raminit_ctrlreg) || (int)priv->instance < 0)
|
if (IS_ERR(priv->raminit_ctrlreg) || priv->instance < 0)
|
||||||
dev_info(&pdev->dev, "control memory is not used for raminit\n");
|
dev_info(&pdev->dev, "control memory is not used for raminit\n");
|
||||||
else
|
else
|
||||||
priv->raminit = c_can_hw_raminit;
|
priv->raminit = c_can_hw_raminit;
|
||||||
|
|
|
@ -256,7 +256,7 @@ static int can_get_bittiming(struct net_device *dev, struct can_bittiming *bt,
|
||||||
|
|
||||||
/* Check if the CAN device has bit-timing parameters */
|
/* Check if the CAN device has bit-timing parameters */
|
||||||
if (!btc)
|
if (!btc)
|
||||||
return -ENOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Depending on the given can_bittiming parameter structure the CAN
|
* Depending on the given can_bittiming parameter structure the CAN
|
||||||
|
|
|
@ -46,6 +46,7 @@ static int clk[MAXDEV];
|
||||||
static unsigned char cdr[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff};
|
static unsigned char cdr[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff};
|
||||||
static unsigned char ocr[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff};
|
static unsigned char ocr[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff};
|
||||||
static int indirect[MAXDEV] = {[0 ... (MAXDEV - 1)] = -1};
|
static int indirect[MAXDEV] = {[0 ... (MAXDEV - 1)] = -1};
|
||||||
|
static spinlock_t indirect_lock[MAXDEV]; /* lock for indirect access mode */
|
||||||
|
|
||||||
module_param_array(port, ulong, NULL, S_IRUGO);
|
module_param_array(port, ulong, NULL, S_IRUGO);
|
||||||
MODULE_PARM_DESC(port, "I/O port number");
|
MODULE_PARM_DESC(port, "I/O port number");
|
||||||
|
@ -101,19 +102,26 @@ static void sja1000_isa_port_write_reg(const struct sja1000_priv *priv,
|
||||||
static u8 sja1000_isa_port_read_reg_indirect(const struct sja1000_priv *priv,
|
static u8 sja1000_isa_port_read_reg_indirect(const struct sja1000_priv *priv,
|
||||||
int reg)
|
int reg)
|
||||||
{
|
{
|
||||||
unsigned long base = (unsigned long)priv->reg_base;
|
unsigned long flags, base = (unsigned long)priv->reg_base;
|
||||||
|
u8 readval;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&indirect_lock[priv->dev->dev_id], flags);
|
||||||
outb(reg, base);
|
outb(reg, base);
|
||||||
return inb(base + 1);
|
readval = inb(base + 1);
|
||||||
|
spin_unlock_irqrestore(&indirect_lock[priv->dev->dev_id], flags);
|
||||||
|
|
||||||
|
return readval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sja1000_isa_port_write_reg_indirect(const struct sja1000_priv *priv,
|
static void sja1000_isa_port_write_reg_indirect(const struct sja1000_priv *priv,
|
||||||
int reg, u8 val)
|
int reg, u8 val)
|
||||||
{
|
{
|
||||||
unsigned long base = (unsigned long)priv->reg_base;
|
unsigned long flags, base = (unsigned long)priv->reg_base;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&indirect_lock[priv->dev->dev_id], flags);
|
||||||
outb(reg, base);
|
outb(reg, base);
|
||||||
outb(val, base + 1);
|
outb(val, base + 1);
|
||||||
|
spin_unlock_irqrestore(&indirect_lock[priv->dev->dev_id], flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sja1000_isa_probe(struct platform_device *pdev)
|
static int sja1000_isa_probe(struct platform_device *pdev)
|
||||||
|
@ -169,6 +177,7 @@ static int sja1000_isa_probe(struct platform_device *pdev)
|
||||||
if (iosize == SJA1000_IOSIZE_INDIRECT) {
|
if (iosize == SJA1000_IOSIZE_INDIRECT) {
|
||||||
priv->read_reg = sja1000_isa_port_read_reg_indirect;
|
priv->read_reg = sja1000_isa_port_read_reg_indirect;
|
||||||
priv->write_reg = sja1000_isa_port_write_reg_indirect;
|
priv->write_reg = sja1000_isa_port_write_reg_indirect;
|
||||||
|
spin_lock_init(&indirect_lock[idx]);
|
||||||
} else {
|
} else {
|
||||||
priv->read_reg = sja1000_isa_port_read_reg;
|
priv->read_reg = sja1000_isa_port_read_reg;
|
||||||
priv->write_reg = sja1000_isa_port_write_reg;
|
priv->write_reg = sja1000_isa_port_write_reg;
|
||||||
|
@ -198,6 +207,7 @@ static int sja1000_isa_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
platform_set_drvdata(pdev, dev);
|
platform_set_drvdata(pdev, dev);
|
||||||
SET_NETDEV_DEV(dev, &pdev->dev);
|
SET_NETDEV_DEV(dev, &pdev->dev);
|
||||||
|
dev->dev_id = idx;
|
||||||
|
|
||||||
err = register_sja1000dev(dev);
|
err = register_sja1000dev(dev);
|
||||||
if (err) {
|
if (err) {
|
||||||
|
|
|
@ -322,13 +322,13 @@ static void slcan_write_wakeup(struct tty_struct *tty)
|
||||||
if (!sl || sl->magic != SLCAN_MAGIC || !netif_running(sl->dev))
|
if (!sl || sl->magic != SLCAN_MAGIC || !netif_running(sl->dev))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
spin_lock(&sl->lock);
|
spin_lock_bh(&sl->lock);
|
||||||
if (sl->xleft <= 0) {
|
if (sl->xleft <= 0) {
|
||||||
/* Now serial buffer is almost free & we can start
|
/* Now serial buffer is almost free & we can start
|
||||||
* transmission of another packet */
|
* transmission of another packet */
|
||||||
sl->dev->stats.tx_packets++;
|
sl->dev->stats.tx_packets++;
|
||||||
clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
|
clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
|
||||||
spin_unlock(&sl->lock);
|
spin_unlock_bh(&sl->lock);
|
||||||
netif_wake_queue(sl->dev);
|
netif_wake_queue(sl->dev);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -336,7 +336,7 @@ static void slcan_write_wakeup(struct tty_struct *tty)
|
||||||
actual = tty->ops->write(tty, sl->xhead, sl->xleft);
|
actual = tty->ops->write(tty, sl->xhead, sl->xleft);
|
||||||
sl->xleft -= actual;
|
sl->xleft -= actual;
|
||||||
sl->xhead += actual;
|
sl->xhead += actual;
|
||||||
spin_unlock(&sl->lock);
|
spin_unlock_bh(&sl->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send a can_frame to a TTY queue. */
|
/* Send a can_frame to a TTY queue. */
|
||||||
|
|
Loading…
Add table
Reference in a new issue