Skip to content

Commit

Permalink
Merge tag 'linux-can-next-for-3.16-20140519' of git://gitorious.org/l…
Browse files Browse the repository at this point in the history
…inux-can/linux-can-next

Marc Kleine-Budde says:

====================
pull-request: can-next 2014-05-19

this is a pull request of 13 patches for net-next/master.

A patch by Dan Carpenter fixes a coccinelle warning in the mcp251x
driver. Jean Delvare contributes three patches to tightening the
Kconfig dependencies for some drivers. Then come three patches by Pavel
Machek that improve the c_can driver support on the socfpga platform.
Sergei Shtylyov's patch brings support for the CAN hardware found on
Renesas R-Car CAN controllers. Four patches by Oliver Hartkopp, the
first cleans up the guard macros in the CAN headers the other three
improve the EFF frame filtering. Maximilian Schneider's patch adds
support for the GS_USB CAN devices.

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed May 21, 2014
2 parents 7d10d26 + d08e973 commit 2a7ede5
Show file tree
Hide file tree
Showing 31 changed files with 2,170 additions and 95 deletions.
35 changes: 35 additions & 0 deletions Documentation/networking/can.txt
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,41 @@ solution for a couple of reasons:
having this 'send only' use-case we may remove the receive list in the
Kernel to save a little (really a very little!) CPU usage.

4.1.1.1 CAN filter usage optimisation

The CAN filters are processed in per-device filter lists at CAN frame
reception time. To reduce the number of checks that need to be performed
while walking through the filter lists the CAN core provides an optimized
filter handling when the filter subscription focusses on a single CAN ID.

For the possible 2048 SFF CAN identifiers the identifier is used as an index
to access the corresponding subscription list without any further checks.
For the 2^29 possible EFF CAN identifiers a 10 bit XOR folding is used as
hash function to retrieve the EFF table index.

To benefit from the optimized filters for single CAN identifiers the
CAN_SFF_MASK or CAN_EFF_MASK have to be set into can_filter.mask together
with set CAN_EFF_FLAG and CAN_RTR_FLAG bits. A set CAN_EFF_FLAG bit in the
can_filter.mask makes clear that it matters whether a SFF or EFF CAN ID is
subscribed. E.g. in the example from above

rfilter[0].can_id = 0x123;
rfilter[0].can_mask = CAN_SFF_MASK;

both SFF frames with CAN ID 0x123 and EFF frames with 0xXXXXX123 can pass.

To filter for only 0x123 (SFF) and 0x12345678 (EFF) CAN identifiers the
filter has to be defined in this way to benefit from the optimized filters:

struct can_filter rfilter[2];

rfilter[0].can_id = 0x123;
rfilter[0].can_mask = (CAN_EFF_FLAG | CAN_RTR_FLAG | CAN_SFF_MASK);
rfilter[1].can_id = 0x12345678 | CAN_EFF_FLAG;
rfilter[1].can_mask = (CAN_EFF_FLAG | CAN_RTR_FLAG | CAN_EFF_MASK);

setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, &rfilter, sizeof(rfilter));

4.1.2 RAW socket option CAN_RAW_ERR_FILTER

As described in chapter 3.4 the CAN interface driver can generate so
Expand Down
14 changes: 12 additions & 2 deletions drivers/net/can/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ config CAN_LEDS

config CAN_AT91
tristate "Atmel AT91 onchip CAN controller"
depends on ARM
depends on ARCH_AT91 || COMPILE_TEST
---help---
This is a driver for the SoC CAN controller in Atmel's AT91SAM9263
and AT91SAM9X5 processors.
Expand Down Expand Up @@ -104,7 +104,7 @@ config CAN_FLEXCAN

config PCH_CAN
tristate "Intel EG20T PCH CAN controller"
depends on PCI
depends on PCI && (X86_32 || COMPILE_TEST)
---help---
This driver is for PCH CAN of Topcliff (Intel EG20T PCH) which
is an IOH for x86 embedded processor (Intel Atom E6xx series).
Expand All @@ -119,6 +119,16 @@ config CAN_GRCAN
endian syntheses of the cores would need some modifications on
the hardware level to work.

config CAN_RCAR
tristate "Renesas R-Car CAN controller"
depends on ARM
---help---
Say Y here if you want to use CAN controller found on Renesas R-Car
SoCs.

To compile this driver as a module, choose M here: the module will
be called rcar_can.

source "drivers/net/can/mscan/Kconfig"

source "drivers/net/can/sja1000/Kconfig"
Expand Down
1 change: 1 addition & 0 deletions drivers/net/can/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,6 @@ obj-$(CONFIG_CAN_JANZ_ICAN3) += janz-ican3.o
obj-$(CONFIG_CAN_FLEXCAN) += flexcan.o
obj-$(CONFIG_PCH_CAN) += pch_can.o
obj-$(CONFIG_CAN_GRCAN) += grcan.o
obj-$(CONFIG_CAN_RCAR) += rcar_can.o

ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
15 changes: 5 additions & 10 deletions drivers/net/can/c_can/c_can.c
Original file line number Diff line number Diff line change
Expand Up @@ -252,8 +252,7 @@ static void c_can_obj_update(struct net_device *dev, int iface, u32 cmd, u32 obj
struct c_can_priv *priv = netdev_priv(dev);
int cnt, reg = C_CAN_IFACE(COMREQ_REG, iface);

priv->write_reg(priv, reg + 1, cmd);
priv->write_reg(priv, reg, obj);
priv->write_reg32(priv, reg, (cmd << 16) | obj);

for (cnt = MIN_TIMEOUT_VALUE; cnt; cnt--) {
if (!(priv->read_reg(priv, reg) & IF_COMR_BUSY))
Expand Down Expand Up @@ -328,8 +327,7 @@ static void c_can_setup_tx_object(struct net_device *dev, int iface,
change_bit(idx, &priv->tx_dir);
}

priv->write_reg(priv, C_CAN_IFACE(ARB1_REG, iface), arb);
priv->write_reg(priv, C_CAN_IFACE(ARB2_REG, iface), arb >> 16);
priv->write_reg32(priv, C_CAN_IFACE(ARB1_REG, iface), arb);

priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), ctrl);

Expand Down Expand Up @@ -391,8 +389,7 @@ static int c_can_read_msg_object(struct net_device *dev, int iface, u32 ctrl)

frame->can_dlc = get_can_dlc(ctrl & 0x0F);

arb = priv->read_reg(priv, C_CAN_IFACE(ARB1_REG, iface));
arb |= priv->read_reg(priv, C_CAN_IFACE(ARB2_REG, iface)) << 16;
arb = priv->read_reg32(priv, C_CAN_IFACE(ARB1_REG, iface));

if (arb & IF_ARB_MSGXTD)
frame->can_id = (arb & CAN_EFF_MASK) | CAN_EFF_FLAG;
Expand Down Expand Up @@ -424,12 +421,10 @@ static void c_can_setup_receive_object(struct net_device *dev, int iface,
struct c_can_priv *priv = netdev_priv(dev);

mask |= BIT(29);
priv->write_reg(priv, C_CAN_IFACE(MASK1_REG, iface), mask);
priv->write_reg(priv, C_CAN_IFACE(MASK2_REG, iface), mask >> 16);
priv->write_reg32(priv, C_CAN_IFACE(MASK1_REG, iface), mask);

id |= IF_ARB_MSGVAL;
priv->write_reg(priv, C_CAN_IFACE(ARB1_REG, iface), id);
priv->write_reg(priv, C_CAN_IFACE(ARB2_REG, iface), id >> 16);
priv->write_reg32(priv, C_CAN_IFACE(ARB1_REG, iface), id);

priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), mcont);
c_can_object_put(dev, iface, obj, IF_COMM_RCV_SETUP);
Expand Down
8 changes: 6 additions & 2 deletions drivers/net/can/c_can/c_can.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ enum reg {
C_CAN_INTPND2_REG,
C_CAN_MSGVAL1_REG,
C_CAN_MSGVAL2_REG,
C_CAN_FUNCTION_REG,
};

static const u16 reg_map_c_can[] = {
Expand Down Expand Up @@ -129,6 +130,7 @@ static const u16 reg_map_d_can[] = {
[C_CAN_BRPEXT_REG] = 0x0E,
[C_CAN_INT_REG] = 0x10,
[C_CAN_TEST_REG] = 0x14,
[C_CAN_FUNCTION_REG] = 0x18,
[C_CAN_TXRQST1_REG] = 0x88,
[C_CAN_TXRQST2_REG] = 0x8A,
[C_CAN_NEWDAT1_REG] = 0x9C,
Expand Down Expand Up @@ -176,8 +178,10 @@ struct c_can_priv {
atomic_t tx_active;
unsigned long tx_dir;
int last_status;
u16 (*read_reg) (struct c_can_priv *priv, enum reg index);
void (*write_reg) (struct c_can_priv *priv, enum reg index, u16 val);
u16 (*read_reg) (const struct c_can_priv *priv, enum reg index);
void (*write_reg) (const struct c_can_priv *priv, enum reg index, u16 val);
u32 (*read_reg32) (const struct c_can_priv *priv, enum reg index);
void (*write_reg32) (const struct c_can_priv *priv, enum reg index, u32 val);
void __iomem *base;
const u16 *regs;
void *priv; /* for board-specific data */
Expand Down
31 changes: 25 additions & 6 deletions drivers/net/can/c_can/c_can_pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,42 +47,59 @@ struct c_can_pci_data {
* registers can be aligned to a 16-bit boundary or 32-bit boundary etc.
* Handle the same by providing a common read/write interface.
*/
static u16 c_can_pci_read_reg_aligned_to_16bit(struct c_can_priv *priv,
static u16 c_can_pci_read_reg_aligned_to_16bit(const struct c_can_priv *priv,
enum reg index)
{
return readw(priv->base + priv->regs[index]);
}

static void c_can_pci_write_reg_aligned_to_16bit(struct c_can_priv *priv,
static void c_can_pci_write_reg_aligned_to_16bit(const struct c_can_priv *priv,
enum reg index, u16 val)
{
writew(val, priv->base + priv->regs[index]);
}

static u16 c_can_pci_read_reg_aligned_to_32bit(struct c_can_priv *priv,
static u16 c_can_pci_read_reg_aligned_to_32bit(const struct c_can_priv *priv,
enum reg index)
{
return readw(priv->base + 2 * priv->regs[index]);
}

static void c_can_pci_write_reg_aligned_to_32bit(struct c_can_priv *priv,
static void c_can_pci_write_reg_aligned_to_32bit(const struct c_can_priv *priv,
enum reg index, u16 val)
{
writew(val, priv->base + 2 * priv->regs[index]);
}

static u16 c_can_pci_read_reg_32bit(struct c_can_priv *priv,
static u16 c_can_pci_read_reg_32bit(const struct c_can_priv *priv,
enum reg index)
{
return (u16)ioread32(priv->base + 2 * priv->regs[index]);
}

static void c_can_pci_write_reg_32bit(struct c_can_priv *priv,
static void c_can_pci_write_reg_32bit(const struct c_can_priv *priv,
enum reg index, u16 val)
{
iowrite32((u32)val, priv->base + 2 * priv->regs[index]);
}

static u32 c_can_pci_read_reg32(const struct c_can_priv *priv, enum reg index)
{
u32 val;

val = priv->read_reg(priv, index);
val |= ((u32) priv->read_reg(priv, index + 1)) << 16;

return val;
}

static void c_can_pci_write_reg32(const struct c_can_priv *priv, enum reg index,
u32 val)
{
priv->write_reg(priv, index + 1, val >> 16);
priv->write_reg(priv, index, val);
}

static void c_can_pci_reset_pch(const struct c_can_priv *priv, bool enable)
{
if (enable) {
Expand Down Expand Up @@ -187,6 +204,8 @@ static int c_can_pci_probe(struct pci_dev *pdev,
ret = -EINVAL;
goto out_free_c_can;
}
priv->read_reg32 = c_can_pci_read_reg32;
priv->write_reg32 = c_can_pci_write_reg32;

priv->raminit = c_can_pci_data->init;

Expand Down
Loading

0 comments on commit 2a7ede5

Please sign in to comment.