Commit 43996fdd authored by David S. Miller's avatar David S. Miller

Merge tag 'linux-can-next-for-4.2-20150506' of...

Merge tag 'linux-can-next-for-4.2-20150506' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next

Marc Kleine-Budde says:

====================
pull-request: can-next 2015-05-06

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

Andreas Gröger contributes two patches for the janz-ican3 driver. In
the first patch, the documentation for already existing sysfs entries
is added, the second patch adds support for another module/firmware
variant. A patch by Shawn Landden makes the padding in the struct
can_frame explicit. The next 4 patches target the flexcan driver, the
first one is by David Jander adding some documentation, the reaming
three by me add more documentation and two small code cleanups.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents a5898ea0 10d089bd
What: /sys/bus/pci/drivers/janz-cmodio/.../modulbus_number
Date: May 2010
KernelVersion: 2.6.35
Contact: Ira W. Snyder <ira.snyder@gmail.com>
Description:
Value representing the HEX switch S2 of the janz carrier board CMOD-IO or CAN-PCI2
Read-only: value of the configuration switch (0..15)
What: /sys/class/net/<iface>/termination
Date: May 2010
KernelVersion: 2.6.35
Contact: Ira W. Snyder <ira.snyder@gmail.com>
Description:
Value representing the can bus termination
Default: 1 (termination active)
Reading: get actual termination state
Writing: set actual termination state (0=no termination, 1=termination active)
What: /sys/class/net/<iface>/fwinfo
Date: May 2015
KernelVersion: 3.19
Contact: Andreas Gröger <andreas24groeger@gmail.com>
Description:
Firmware stamp of ican3 module
Read-only: 32 byte string identification of the ICAN3 module
(known values: "JANZ-ICAN3 ICANOS 1.xx", "JANZ-ICAN3 CAL/CANopen 1.xx")
...@@ -268,6 +268,9 @@ solution for a couple of reasons: ...@@ -268,6 +268,9 @@ solution for a couple of reasons:
struct can_frame { struct can_frame {
canid_t can_id; /* 32 bit CAN_ID + EFF/RTR/ERR flags */ canid_t can_id; /* 32 bit CAN_ID + EFF/RTR/ERR flags */
__u8 can_dlc; /* frame payload length in byte (0 .. 8) */ __u8 can_dlc; /* frame payload length in byte (0 .. 8) */
__u8 __pad; /* padding */
__u8 __res0; /* reserved / padding */
__u8 __res1; /* reserved / padding */
__u8 data[8] __attribute__((aligned(8))); __u8 data[8] __attribute__((aligned(8)));
}; };
......
...@@ -267,6 +267,10 @@ static void cmodio_pci_remove(struct pci_dev *dev) ...@@ -267,6 +267,10 @@ static void cmodio_pci_remove(struct pci_dev *dev)
static const struct pci_device_id cmodio_pci_ids[] = { static const struct pci_device_id cmodio_pci_ids[] = {
{ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030, PCI_VENDOR_ID_JANZ, 0x0101 }, { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030, PCI_VENDOR_ID_JANZ, 0x0101 },
{ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, PCI_VENDOR_ID_JANZ, 0x0100 }, { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, PCI_VENDOR_ID_JANZ, 0x0100 },
{ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030, PCI_VENDOR_ID_JANZ, 0x0201 },
{ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030, PCI_VENDOR_ID_JANZ, 0x0202 },
{ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, PCI_VENDOR_ID_JANZ, 0x0201 },
{ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, PCI_VENDOR_ID_JANZ, 0x0202 },
{ 0, } { 0, }
}; };
MODULE_DEVICE_TABLE(pci, cmodio_pci_ids); MODULE_DEVICE_TABLE(pci, cmodio_pci_ids);
......
...@@ -93,13 +93,13 @@ ...@@ -93,13 +93,13 @@
(FLEXCAN_CTRL_ERR_BUS | FLEXCAN_CTRL_ERR_STATE) (FLEXCAN_CTRL_ERR_BUS | FLEXCAN_CTRL_ERR_STATE)
/* FLEXCAN control register 2 (CTRL2) bits */ /* FLEXCAN control register 2 (CTRL2) bits */
#define FLEXCAN_CRL2_ECRWRE BIT(29) #define FLEXCAN_CTRL2_ECRWRE BIT(29)
#define FLEXCAN_CRL2_WRMFRZ BIT(28) #define FLEXCAN_CTRL2_WRMFRZ BIT(28)
#define FLEXCAN_CRL2_RFFN(x) (((x) & 0x0f) << 24) #define FLEXCAN_CTRL2_RFFN(x) (((x) & 0x0f) << 24)
#define FLEXCAN_CRL2_TASD(x) (((x) & 0x1f) << 19) #define FLEXCAN_CTRL2_TASD(x) (((x) & 0x1f) << 19)
#define FLEXCAN_CRL2_MRP BIT(18) #define FLEXCAN_CTRL2_MRP BIT(18)
#define FLEXCAN_CRL2_RRS BIT(17) #define FLEXCAN_CTRL2_RRS BIT(17)
#define FLEXCAN_CRL2_EACEN BIT(16) #define FLEXCAN_CTRL2_EACEN BIT(16)
/* FLEXCAN memory error control register (MECR) bits */ /* FLEXCAN memory error control register (MECR) bits */
#define FLEXCAN_MECR_ECRWRDIS BIT(31) #define FLEXCAN_MECR_ECRWRDIS BIT(31)
...@@ -158,7 +158,6 @@ ...@@ -158,7 +158,6 @@
FLEXCAN_IFLAG_BUF(FLEXCAN_TX_BUF_ID)) FLEXCAN_IFLAG_BUF(FLEXCAN_TX_BUF_ID))
/* FLEXCAN message buffers */ /* FLEXCAN message buffers */
#define FLEXCAN_MB_CNT_CODE(x) (((x) & 0xf) << 24)
#define FLEXCAN_MB_CODE_RX_INACTIVE (0x0 << 24) #define FLEXCAN_MB_CODE_RX_INACTIVE (0x0 << 24)
#define FLEXCAN_MB_CODE_RX_EMPTY (0x4 << 24) #define FLEXCAN_MB_CODE_RX_EMPTY (0x4 << 24)
#define FLEXCAN_MB_CODE_RX_FULL (0x2 << 24) #define FLEXCAN_MB_CODE_RX_FULL (0x2 << 24)
...@@ -184,14 +183,14 @@ ...@@ -184,14 +183,14 @@
* FLEXCAN hardware feature flags * FLEXCAN hardware feature flags
* *
* Below is some version info we got: * Below is some version info we got:
* SOC Version IP-Version Glitch- [TR]WRN_INT Memory err * SOC Version IP-Version Glitch- [TR]WRN_INT Memory err RTR re-
* Filter? connected? detection * Filter? connected? detection ception in MB
* MX25 FlexCAN2 03.00.00.00 no no no * MX25 FlexCAN2 03.00.00.00 no no no no
* MX28 FlexCAN2 03.00.04.00 yes yes no * MX28 FlexCAN2 03.00.04.00 yes yes no no
* MX35 FlexCAN2 03.00.00.00 no no no * MX35 FlexCAN2 03.00.00.00 no no no no
* MX53 FlexCAN2 03.00.00.00 yes no no * MX53 FlexCAN2 03.00.00.00 yes no no no
* MX6s FlexCAN3 10.00.12.00 yes yes no * MX6s FlexCAN3 10.00.12.00 yes yes no yes
* VF610 FlexCAN3 ? no yes yes * VF610 FlexCAN3 ? no yes yes yes?
* *
* Some SOCs do not have the RX_WARN & TX_WARN interrupt line connected. * Some SOCs do not have the RX_WARN & TX_WARN interrupt line connected.
*/ */
...@@ -221,7 +220,7 @@ struct flexcan_regs { ...@@ -221,7 +220,7 @@ struct flexcan_regs {
u32 imask1; /* 0x28 */ u32 imask1; /* 0x28 */
u32 iflag2; /* 0x2c */ u32 iflag2; /* 0x2c */
u32 iflag1; /* 0x30 */ u32 iflag1; /* 0x30 */
u32 crl2; /* 0x34 */ u32 ctrl2; /* 0x34 */
u32 esr2; /* 0x38 */ u32 esr2; /* 0x38 */
u32 imeur; /* 0x3c */ u32 imeur; /* 0x3c */
u32 lrfr; /* 0x40 */ u32 lrfr; /* 0x40 */
...@@ -230,6 +229,16 @@ struct flexcan_regs { ...@@ -230,6 +229,16 @@ struct flexcan_regs {
u32 rxfir; /* 0x4c */ u32 rxfir; /* 0x4c */
u32 _reserved3[12]; /* 0x50 */ u32 _reserved3[12]; /* 0x50 */
struct flexcan_mb cantxfg[64]; /* 0x80 */ struct flexcan_mb cantxfg[64]; /* 0x80 */
/* FIFO-mode:
* MB
* 0x080...0x08f 0 RX message buffer
* 0x090...0x0df 1-5 reserverd
* 0x0e0...0x0ff 6-7 8 entry ID table
* (mx25, mx28, mx35, mx53)
* 0x0e0...0x2df 6-7..37 8..128 entry ID table
* size conf'ed via ctrl2::RFFN
* (mx6, vf610)
*/
u32 _reserved4[408]; u32 _reserved4[408];
u32 mecr; /* 0xae0 */ u32 mecr; /* 0xae0 */
u32 erriar; /* 0xae4 */ u32 erriar; /* 0xae4 */
...@@ -468,7 +477,7 @@ static int flexcan_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -468,7 +477,7 @@ static int flexcan_start_xmit(struct sk_buff *skb, struct net_device *dev)
struct flexcan_regs __iomem *regs = priv->base; struct flexcan_regs __iomem *regs = priv->base;
struct can_frame *cf = (struct can_frame *)skb->data; struct can_frame *cf = (struct can_frame *)skb->data;
u32 can_id; u32 can_id;
u32 ctrl = FLEXCAN_MB_CNT_CODE(0xc) | (cf->can_dlc << 16); u32 ctrl = FLEXCAN_MB_CODE_TX_DATA | (cf->can_dlc << 16);
if (can_dropped_invalid_skb(dev, skb)) if (can_dropped_invalid_skb(dev, skb))
return NETDEV_TX_OK; return NETDEV_TX_OK;
...@@ -815,7 +824,7 @@ static int flexcan_chip_start(struct net_device *dev) ...@@ -815,7 +824,7 @@ static int flexcan_chip_start(struct net_device *dev)
{ {
struct flexcan_priv *priv = netdev_priv(dev); struct flexcan_priv *priv = netdev_priv(dev);
struct flexcan_regs __iomem *regs = priv->base; struct flexcan_regs __iomem *regs = priv->base;
u32 reg_mcr, reg_ctrl, reg_crl2, reg_mecr; u32 reg_mcr, reg_ctrl, reg_ctrl2, reg_mecr;
int err, i; int err, i;
/* enable module */ /* enable module */
...@@ -918,9 +927,9 @@ static int flexcan_chip_start(struct net_device *dev) ...@@ -918,9 +927,9 @@ static int flexcan_chip_start(struct net_device *dev)
* and Correction of Memory Errors" to write to * and Correction of Memory Errors" to write to
* MECR register * MECR register
*/ */
reg_crl2 = flexcan_read(&regs->crl2); reg_ctrl2 = flexcan_read(&regs->ctrl2);
reg_crl2 |= FLEXCAN_CRL2_ECRWRE; reg_ctrl2 |= FLEXCAN_CTRL2_ECRWRE;
flexcan_write(reg_crl2, &regs->crl2); flexcan_write(reg_ctrl2, &regs->ctrl2);
reg_mecr = flexcan_read(&regs->mecr); reg_mecr = flexcan_read(&regs->mecr);
reg_mecr &= ~FLEXCAN_MECR_ECRWRDIS; reg_mecr &= ~FLEXCAN_MECR_ECRWRDIS;
......
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
#define MSYNC_PEER 0x00 /* ICAN only */ #define MSYNC_PEER 0x00 /* ICAN only */
#define MSYNC_LOCL 0x01 /* host only */ #define MSYNC_LOCL 0x01 /* host only */
#define TARGET_RUNNING 0x02 #define TARGET_RUNNING 0x02
#define FIRMWARE_STAMP 0x60 /* big endian firmware stamp */
#define MSYNC_RB0 0x01 #define MSYNC_RB0 0x01
#define MSYNC_RB1 0x02 #define MSYNC_RB1 0x02
...@@ -83,6 +84,7 @@ ...@@ -83,6 +84,7 @@
#define MSG_COFFREQ 0x42 #define MSG_COFFREQ 0x42
#define MSG_CONREQ 0x43 #define MSG_CONREQ 0x43
#define MSG_CCONFREQ 0x47 #define MSG_CCONFREQ 0x47
#define MSG_LMTS 0xb4
/* /*
* Janz ICAN3 CAN Inquiry Message Types * Janz ICAN3 CAN Inquiry Message Types
...@@ -165,6 +167,12 @@ ...@@ -165,6 +167,12 @@
/* SJA1000 Clock Input */ /* SJA1000 Clock Input */
#define ICAN3_CAN_CLOCK 8000000 #define ICAN3_CAN_CLOCK 8000000
/* Janz ICAN3 firmware types */
enum ican3_fwtype {
ICAN3_FWTYPE_ICANOS,
ICAN3_FWTYPE_CAL_CANOPEN,
};
/* Driver Name */ /* Driver Name */
#define DRV_NAME "janz-ican3" #define DRV_NAME "janz-ican3"
...@@ -215,6 +223,10 @@ struct ican3_dev { ...@@ -215,6 +223,10 @@ struct ican3_dev {
struct completion buserror_comp; struct completion buserror_comp;
struct can_berr_counter bec; struct can_berr_counter bec;
/* firmware type */
enum ican3_fwtype fwtype;
char fwinfo[32];
/* old and new style host interface */ /* old and new style host interface */
unsigned int iftype; unsigned int iftype;
...@@ -750,13 +762,61 @@ static int ican3_set_id_filter(struct ican3_dev *mod, bool accept) ...@@ -750,13 +762,61 @@ static int ican3_set_id_filter(struct ican3_dev *mod, bool accept)
*/ */
static int ican3_set_bus_state(struct ican3_dev *mod, bool on) static int ican3_set_bus_state(struct ican3_dev *mod, bool on)
{ {
struct can_bittiming *bt = &mod->can.bittiming;
struct ican3_msg msg; struct ican3_msg msg;
u8 btr0, btr1;
int res;
memset(&msg, 0, sizeof(msg)); /* This algorithm was stolen from drivers/net/can/sja1000/sja1000.c */
msg.spec = on ? MSG_CONREQ : MSG_COFFREQ; /* The bittiming register command for the ICAN3 just sets the bit timing */
msg.len = cpu_to_le16(0); /* registers on the SJA1000 chip directly */
btr0 = ((bt->brp - 1) & 0x3f) | (((bt->sjw - 1) & 0x3) << 6);
btr1 = ((bt->prop_seg + bt->phase_seg1 - 1) & 0xf) |
(((bt->phase_seg2 - 1) & 0x7) << 4);
if (mod->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)
btr1 |= 0x80;
return ican3_send_msg(mod, &msg); if (mod->fwtype == ICAN3_FWTYPE_ICANOS) {
if (on) {
/* set bittiming */
memset(&msg, 0, sizeof(msg));
msg.spec = MSG_CBTRREQ;
msg.len = cpu_to_le16(4);
msg.data[0] = 0x00;
msg.data[1] = 0x00;
msg.data[2] = btr0;
msg.data[3] = btr1;
res = ican3_send_msg(mod, &msg);
if (res)
return res;
}
/* can-on/off request */
memset(&msg, 0, sizeof(msg));
msg.spec = on ? MSG_CONREQ : MSG_COFFREQ;
msg.len = cpu_to_le16(0);
return ican3_send_msg(mod, &msg);
} else if (mod->fwtype == ICAN3_FWTYPE_CAL_CANOPEN) {
memset(&msg, 0, sizeof(msg));
msg.spec = MSG_LMTS;
if (on) {
msg.len = cpu_to_le16(4);
msg.data[0] = 0;
msg.data[1] = 0;
msg.data[2] = btr0;
msg.data[3] = btr1;
} else {
msg.len = cpu_to_le16(2);
msg.data[0] = 1;
msg.data[1] = 0;
}
return ican3_send_msg(mod, &msg);
}
return -ENOTSUPP;
} }
static int ican3_set_termination(struct ican3_dev *mod, bool on) static int ican3_set_termination(struct ican3_dev *mod, bool on)
...@@ -1402,7 +1462,7 @@ static int ican3_reset_module(struct ican3_dev *mod) ...@@ -1402,7 +1462,7 @@ static int ican3_reset_module(struct ican3_dev *mod)
return 0; return 0;
msleep(10); msleep(10);
} while (time_before(jiffies, start + HZ / 4)); } while (time_before(jiffies, start + HZ / 2));
netdev_err(mod->ndev, "failed to reset CAN module\n"); netdev_err(mod->ndev, "failed to reset CAN module\n");
return -ETIMEDOUT; return -ETIMEDOUT;
...@@ -1427,6 +1487,17 @@ static int ican3_startup_module(struct ican3_dev *mod) ...@@ -1427,6 +1487,17 @@ static int ican3_startup_module(struct ican3_dev *mod)
return ret; return ret;
} }
/* detect firmware */
memcpy_fromio(mod->fwinfo, mod->dpm + FIRMWARE_STAMP, sizeof(mod->fwinfo) - 1);
if (strncmp(mod->fwinfo, "JANZ-ICAN3", 10)) {
netdev_err(mod->ndev, "ICAN3 not detected (found %s)\n", mod->fwinfo);
return -ENODEV;
}
if (strstr(mod->fwinfo, "CAL/CANopen"))
mod->fwtype = ICAN3_FWTYPE_CAL_CANOPEN;
else
mod->fwtype = ICAN3_FWTYPE_ICANOS;
/* re-enable interrupts so we can send messages */ /* re-enable interrupts so we can send messages */
iowrite8(1 << mod->num, &mod->ctrl->int_enable); iowrite8(1 << mod->num, &mod->ctrl->int_enable);
...@@ -1615,36 +1686,6 @@ static const struct can_bittiming_const ican3_bittiming_const = { ...@@ -1615,36 +1686,6 @@ static const struct can_bittiming_const ican3_bittiming_const = {
.brp_inc = 1, .brp_inc = 1,
}; };
/*
* This routine was stolen from drivers/net/can/sja1000/sja1000.c
*
* The bittiming register command for the ICAN3 just sets the bit timing
* registers on the SJA1000 chip directly
*/
static int ican3_set_bittiming(struct net_device *ndev)
{
struct ican3_dev *mod = netdev_priv(ndev);
struct can_bittiming *bt = &mod->can.bittiming;
struct ican3_msg msg;
u8 btr0, btr1;
btr0 = ((bt->brp - 1) & 0x3f) | (((bt->sjw - 1) & 0x3) << 6);
btr1 = ((bt->prop_seg + bt->phase_seg1 - 1) & 0xf) |
(((bt->phase_seg2 - 1) & 0x7) << 4);
if (mod->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)
btr1 |= 0x80;
memset(&msg, 0, sizeof(msg));
msg.spec = MSG_CBTRREQ;
msg.len = cpu_to_le16(4);
msg.data[0] = 0x00;
msg.data[1] = 0x00;
msg.data[2] = btr0;
msg.data[3] = btr1;
return ican3_send_msg(mod, &msg);
}
static int ican3_set_mode(struct net_device *ndev, enum can_mode mode) static int ican3_set_mode(struct net_device *ndev, enum can_mode mode)
{ {
struct ican3_dev *mod = netdev_priv(ndev); struct ican3_dev *mod = netdev_priv(ndev);
...@@ -1730,11 +1771,22 @@ static ssize_t ican3_sysfs_set_term(struct device *dev, ...@@ -1730,11 +1771,22 @@ static ssize_t ican3_sysfs_set_term(struct device *dev,
return count; return count;
} }
static ssize_t ican3_sysfs_show_fwinfo(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct ican3_dev *mod = netdev_priv(to_net_dev(dev));
return scnprintf(buf, PAGE_SIZE, "%s\n", mod->fwinfo);
}
static DEVICE_ATTR(termination, S_IWUSR | S_IRUGO, ican3_sysfs_show_term, static DEVICE_ATTR(termination, S_IWUSR | S_IRUGO, ican3_sysfs_show_term,
ican3_sysfs_set_term); ican3_sysfs_set_term);
static DEVICE_ATTR(fwinfo, S_IRUSR | S_IRUGO, ican3_sysfs_show_fwinfo, NULL);
static struct attribute *ican3_sysfs_attrs[] = { static struct attribute *ican3_sysfs_attrs[] = {
&dev_attr_termination.attr, &dev_attr_termination.attr,
&dev_attr_fwinfo.attr,
NULL, NULL,
}; };
...@@ -1794,7 +1846,6 @@ static int ican3_probe(struct platform_device *pdev) ...@@ -1794,7 +1846,6 @@ static int ican3_probe(struct platform_device *pdev)
mod->can.clock.freq = ICAN3_CAN_CLOCK; mod->can.clock.freq = ICAN3_CAN_CLOCK;
mod->can.bittiming_const = &ican3_bittiming_const; mod->can.bittiming_const = &ican3_bittiming_const;
mod->can.do_set_bittiming = ican3_set_bittiming;
mod->can.do_set_mode = ican3_set_mode; mod->can.do_set_mode = ican3_set_mode;
mod->can.do_get_berr_counter = ican3_get_berr_counter; mod->can.do_get_berr_counter = ican3_get_berr_counter;
mod->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES mod->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES
...@@ -1866,7 +1917,7 @@ static int ican3_probe(struct platform_device *pdev) ...@@ -1866,7 +1917,7 @@ static int ican3_probe(struct platform_device *pdev)
goto out_free_irq; goto out_free_irq;
} }
dev_info(dev, "module %d: registered CAN device\n", pdata->modno); netdev_info(mod->ndev, "module %d: registered CAN device\n", pdata->modno);
return 0; return 0;
out_free_irq: out_free_irq:
......
...@@ -95,11 +95,17 @@ typedef __u32 can_err_mask_t; ...@@ -95,11 +95,17 @@ typedef __u32 can_err_mask_t;
* @can_dlc: frame payload length in byte (0 .. 8) aka data length code * @can_dlc: frame payload length in byte (0 .. 8) aka data length code
* N.B. the DLC field from ISO 11898-1 Chapter 8.4.2.3 has a 1:1 * N.B. the DLC field from ISO 11898-1 Chapter 8.4.2.3 has a 1:1
* mapping of the 'data length code' to the real payload length * mapping of the 'data length code' to the real payload length
* @__pad: padding
* @__res0: reserved / padding
* @__res1: reserved / padding
* @data: CAN frame payload (up to 8 byte) * @data: CAN frame payload (up to 8 byte)
*/ */
struct can_frame { struct can_frame {
canid_t can_id; /* 32 bit CAN_ID + EFF/RTR/ERR flags */ canid_t can_id; /* 32 bit CAN_ID + EFF/RTR/ERR flags */
__u8 can_dlc; /* frame payload length in byte (0 .. CAN_MAX_DLEN) */ __u8 can_dlc; /* frame payload length in byte (0 .. CAN_MAX_DLEN) */
__u8 __pad; /* padding */
__u8 __res0; /* reserved / padding */
__u8 __res1; /* reserved / padding */
__u8 data[CAN_MAX_DLEN] __attribute__((aligned(8))); __u8 data[CAN_MAX_DLEN] __attribute__((aligned(8)));
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment