Created
February 6, 2016 23:29
-
-
Save vstk/9c4307bb9ae0a6ae0208 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
c_can.o: file format elf32-littlearm | |
Disassembly of section .text: | |
00000000 <c_can_irq_control>: | |
if (priv->raminit) | |
priv->raminit(priv, enable); | |
} | |
static void c_can_irq_control(struct c_can_priv *priv, bool enable) | |
{ | |
0: e1a0c00d mov ip, sp | |
4: e92dd830 push {r4, r5, fp, ip, lr, pc} | |
8: e24cb004 sub fp, ip, #4 | |
c: e52de004 push {lr} ; (str lr, [sp, #-4]!) | |
10: ebfffffe bl 0 <__gnu_mcount_nc> | |
14: e1a05001 mov r5, r1 | |
u32 ctrl = priv->read_reg(priv, C_CAN_CTRL_REG) & ~CONTROL_IRQMSK; | |
18: e3a01000 mov r1, #0 | |
1c: e5903134 ldr r3, [r0, #308] ; 0x134 | |
if (priv->raminit) | |
priv->raminit(priv, enable); | |
} | |
static void c_can_irq_control(struct c_can_priv *priv, bool enable) | |
{ | |
20: e1a04000 mov r4, r0 | |
u32 ctrl = priv->read_reg(priv, C_CAN_CTRL_REG) & ~CONTROL_IRQMSK; | |
24: e12fff33 blx r3 | |
if (enable) | |
28: e3550000 cmp r5, #0 | |
priv->raminit(priv, enable); | |
} | |
static void c_can_irq_control(struct c_can_priv *priv, bool enable) | |
{ | |
u32 ctrl = priv->read_reg(priv, C_CAN_CTRL_REG) & ~CONTROL_IRQMSK; | |
2c: e3c0200e bic r2, r0, #14 | |
if (enable) | |
ctrl |= CONTROL_IRQMSK; | |
30: 1382200e orrne r2, r2, #14 | |
priv->write_reg(priv, C_CAN_CTRL_REG, ctrl); | |
34: e5943138 ldr r3, [r4, #312] ; 0x138 | |
38: e6ff2072 uxth r2, r2 | |
3c: e1a00004 mov r0, r4 | |
40: e3a01000 mov r1, #0 | |
44: e12fff33 blx r3 | |
48: e89da830 ldm sp, {r4, r5, fp, sp, pc} | |
0000004c <c_can_stop>: | |
return 0; | |
} | |
static void c_can_stop(struct net_device *dev) | |
{ | |
4c: e1a0c00d mov ip, sp | |
50: e92dd830 push {r4, r5, fp, ip, lr, pc} | |
54: e24cb004 sub fp, ip, #4 | |
58: e52de004 push {lr} ; (str lr, [sp, #-4]!) | |
5c: ebfffffe bl 0 <__gnu_mcount_nc> | |
struct c_can_priv *priv = netdev_priv(dev); | |
60: e2805d13 add r5, r0, #1216 ; 0x4c0 | |
return 0; | |
} | |
static void c_can_stop(struct net_device *dev) | |
{ | |
64: e1a04000 mov r4, r0 | |
struct c_can_priv *priv = netdev_priv(dev); | |
c_can_irq_control(priv, false); | |
68: e3a01000 mov r1, #0 | |
6c: e1a00005 mov r0, r5 | |
70: ebffffe2 bl 0 <c_can_irq_control> | |
/* put ctrl to init on stop to end ongoing transmission */ | |
priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_INIT); | |
74: e59435f8 ldr r3, [r4, #1528] ; 0x5f8 | |
78: e1a00005 mov r0, r5 | |
7c: e3a01000 mov r1, #0 | |
80: e3a02001 mov r2, #1 | |
84: e12fff33 blx r3 | |
/* deactivate pins */ | |
pinctrl_pm_select_sleep_state(dev->dev.parent); | |
priv->can.state = CAN_STATE_STOPPED; | |
88: e3a03004 mov r3, #4 | |
8c: e5843524 str r3, [r4, #1316] ; 0x524 | |
90: e89da830 ldm sp, {r4, r5, fp, sp, pc} | |
00000094 <alloc_c_can_dev>: | |
return 0; | |
} | |
struct net_device *alloc_c_can_dev(void) | |
{ | |
94: e1a0c00d mov ip, sp | |
98: e92dd818 push {r3, r4, fp, ip, lr, pc} | |
9c: e24cb004 sub fp, ip, #4 | |
a0: e52de004 push {lr} ; (str lr, [sp, #-4]!) | |
a4: ebfffffe bl 0 <__gnu_mcount_nc> | |
struct net_device *dev; | |
struct c_can_priv *priv; | |
dev = alloc_candev(sizeof(struct c_can_priv), C_CAN_MSG_OBJ_TX_NUM); | |
a8: e3a00e1b mov r0, #432 ; 0x1b0 | |
ac: e3a01010 mov r1, #16 | |
b0: ebfffffe bl 0 <alloc_candev> | |
if (!dev) | |
b4: e2504000 subs r4, r0, #0 | |
b8: 0a000010 beq 100 <alloc_c_can_dev+0x6c> | |
return NULL; | |
priv = netdev_priv(dev); | |
netif_napi_add(dev, &priv->napi, c_can_poll, C_CAN_NAPI_WEIGHT); | |
bc: e3002000 movw r2, #0 | |
c0: e2841e57 add r1, r4, #1392 ; 0x570 | |
c4: e3402000 movt r2, #0 | |
c8: e3a03010 mov r3, #16 | |
cc: ebfffffe bl 0 <netif_napi_add> | |
priv->dev = dev; | |
priv->can.bittiming_const = &c_can_bittiming_const; | |
d0: e3001000 movw r1, #0 | |
priv->can.do_set_mode = c_can_set_mode; | |
d4: e3002000 movw r2, #0 | |
priv->can.do_get_berr_counter = c_can_get_berr_counter; | |
d8: e3003000 movw r3, #0 | |
priv = netdev_priv(dev); | |
netif_napi_add(dev, &priv->napi, c_can_poll, C_CAN_NAPI_WEIGHT); | |
priv->dev = dev; | |
priv->can.bittiming_const = &c_can_bittiming_const; | |
dc: e3401000 movt r1, #0 | |
priv->can.do_set_mode = c_can_set_mode; | |
e0: e3402000 movt r2, #0 | |
priv->can.do_get_berr_counter = c_can_get_berr_counter; | |
e4: e3403000 movt r3, #0 | |
priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK | | |
e8: e3a00013 mov r0, #19 | |
return NULL; | |
priv = netdev_priv(dev); | |
netif_napi_add(dev, &priv->napi, c_can_poll, C_CAN_NAPI_WEIGHT); | |
priv->dev = dev; | |
ec: e58445e0 str r4, [r4, #1504] ; 0x5e0 | |
priv->can.bittiming_const = &c_can_bittiming_const; | |
f0: e5841518 str r1, [r4, #1304] ; 0x518 | |
priv->can.do_set_mode = c_can_set_mode; | |
f4: e5842558 str r2, [r4, #1368] ; 0x558 | |
priv->can.do_get_berr_counter = c_can_get_berr_counter; | |
f8: e5843560 str r3, [r4, #1376] ; 0x560 | |
priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK | | |
fc: e584052c str r0, [r4, #1324] ; 0x52c | |
CAN_CTRLMODE_LISTENONLY | | |
CAN_CTRLMODE_BERR_REPORTING; | |
return dev; | |
} | |
100: e1a00004 mov r0, r4 | |
104: e89da818 ldm sp, {r3, r4, fp, sp, pc} | |
00000108 <c_can_get_berr_counter>: | |
return 0; | |
} | |
static int c_can_get_berr_counter(const struct net_device *dev, | |
struct can_berr_counter *bec) | |
{ | |
108: e1a0c00d mov ip, sp | |
10c: e92dd830 push {r4, r5, fp, ip, lr, pc} | |
110: e24cb004 sub fp, ip, #4 | |
114: e52de004 push {lr} ; (str lr, [sp, #-4]!) | |
118: ebfffffe bl 0 <__gnu_mcount_nc> | |
11c: e1a04000 mov r4, r0 | |
120: e1a05001 mov r5, r1 | |
pm_runtime_disable(priv->device); | |
} | |
static inline void c_can_pm_runtime_get_sync(const struct c_can_priv *priv) | |
{ | |
if (priv->device) | |
124: e59005e4 ldr r0, [r0, #1508] ; 0x5e4 | |
128: e3500000 cmp r0, #0 | |
12c: 0a000001 beq 138 <c_can_get_berr_counter+0x30> | |
return __pm_runtime_resume(dev, RPM_GET_PUT | RPM_ASYNC); | |
} | |
static inline int pm_runtime_get_sync(struct device *dev) | |
{ | |
return __pm_runtime_resume(dev, RPM_GET_PUT); | |
130: e3a01004 mov r1, #4 | |
134: ebfffffe bl 0 <__pm_runtime_resume> | |
struct can_berr_counter *bec) | |
{ | |
unsigned int reg_err_counter; | |
struct c_can_priv *priv = netdev_priv(dev); | |
reg_err_counter = priv->read_reg(priv, C_CAN_ERR_CNT_REG); | |
138: e59435f4 ldr r3, [r4, #1524] ; 0x5f4 | |
13c: e2840d13 add r0, r4, #1216 ; 0x4c0 | |
140: e3a01003 mov r1, #3 | |
144: e12fff33 blx r3 | |
bec->rxerr = (reg_err_counter & ERR_CNT_REC_MASK) >> | |
ERR_CNT_REC_SHIFT; | |
bec->txerr = reg_err_counter & ERR_CNT_TEC_MASK; | |
148: e6ef3070 uxtb r3, r0 | |
{ | |
unsigned int reg_err_counter; | |
struct c_can_priv *priv = netdev_priv(dev); | |
reg_err_counter = priv->read_reg(priv, C_CAN_ERR_CNT_REG); | |
bec->rxerr = (reg_err_counter & ERR_CNT_REC_MASK) >> | |
14c: e7e60450 ubfx r0, r0, #8, #7 | |
150: e1c500b2 strh r0, [r5, #2] | |
ERR_CNT_REC_SHIFT; | |
bec->txerr = reg_err_counter & ERR_CNT_TEC_MASK; | |
154: e1c530b0 strh r3, [r5] | |
pm_runtime_get_sync(priv->device); | |
} | |
static inline void c_can_pm_runtime_put_sync(const struct c_can_priv *priv) | |
{ | |
if (priv->device) | |
158: e59405e4 ldr r0, [r4, #1508] ; 0x5e4 | |
15c: e3500000 cmp r0, #0 | |
160: 0a000001 beq 16c <c_can_get_berr_counter+0x64> | |
RPM_GET_PUT | RPM_ASYNC | RPM_AUTO); | |
} | |
static inline int pm_runtime_put_sync(struct device *dev) | |
{ | |
return __pm_runtime_idle(dev, RPM_GET_PUT); | |
164: e3a01004 mov r1, #4 | |
168: ebfffffe bl 0 <__pm_runtime_idle> | |
c_can_pm_runtime_get_sync(priv); | |
err = __c_can_get_berr_counter(dev, bec); | |
c_can_pm_runtime_put_sync(priv); | |
return err; | |
} | |
16c: e3a00000 mov r0, #0 | |
170: e89da830 ldm sp, {r4, r5, fp, sp, pc} | |
00000174 <c_can_obj_update>: | |
priv->write_reg(priv, C_CAN_CTRL_REG, ctrl); | |
} | |
static void c_can_obj_update(struct net_device *dev, int iface, u32 cmd, u32 obj) | |
{ | |
174: e1a0c00d mov ip, sp | |
178: e92dd9f8 push {r3, r4, r5, r6, r7, r8, fp, ip, lr, pc} | |
17c: e24cb004 sub fp, ip, #4 | |
180: e52de004 push {lr} ; (str lr, [sp, #-4]!) | |
184: ebfffffe bl 0 <__gnu_mcount_nc> | |
struct c_can_priv *priv = netdev_priv(dev); | |
int cnt, reg = C_CAN_IFACE(COMREQ_REG, iface); | |
188: e0818101 add r8, r1, r1, lsl #2 | |
priv->write_reg(priv, C_CAN_CTRL_REG, ctrl); | |
} | |
static void c_can_obj_update(struct net_device *dev, int iface, u32 cmd, u32 obj) | |
{ | |
struct c_can_priv *priv = netdev_priv(dev); | |
18c: e2807d13 add r7, r0, #1216 ; 0x4c0 | |
priv->write_reg(priv, C_CAN_CTRL_REG, ctrl); | |
} | |
static void c_can_obj_update(struct net_device *dev, int iface, u32 cmd, u32 obj) | |
{ | |
190: e1a05000 mov r5, r0 | |
struct c_can_priv *priv = netdev_priv(dev); | |
int cnt, reg = C_CAN_IFACE(COMREQ_REG, iface); | |
priv->write_reg32(priv, reg, (cmd << 16) | obj); | |
194: e1832802 orr r2, r3, r2, lsl #16 | |
} | |
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); | |
198: e0811088 add r1, r1, r8, lsl #1 | |
priv->write_reg32(priv, reg, (cmd << 16) | obj); | |
for (cnt = MIN_TIMEOUT_VALUE; cnt; cnt--) { | |
if (!(priv->read_reg(priv, reg) & IF_COMR_BUSY)) | |
return; | |
udelay(1); | |
19c: e3006000 movw r6, #0 | |
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_reg32(priv, reg, (cmd << 16) | obj); | |
1a0: e5903600 ldr r3, [r0, #1536] ; 0x600 | |
1a4: e1a00007 mov r0, r7 | |
} | |
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); | |
1a8: e2818008 add r8, r1, #8 | |
priv->write_reg32(priv, reg, (cmd << 16) | obj); | |
for (cnt = MIN_TIMEOUT_VALUE; cnt; cnt--) { | |
if (!(priv->read_reg(priv, reg) & IF_COMR_BUSY)) | |
return; | |
udelay(1); | |
1ac: e3406000 movt r6, #0 | |
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_reg32(priv, reg, (cmd << 16) | obj); | |
1b0: e1a01008 mov r1, r8 | |
1b4: e3a04006 mov r4, #6 | |
1b8: e12fff33 blx r3 | |
for (cnt = MIN_TIMEOUT_VALUE; cnt; cnt--) { | |
if (!(priv->read_reg(priv, reg) & IF_COMR_BUSY)) | |
1bc: e59535f4 ldr r3, [r5, #1524] ; 0x5f4 | |
1c0: e1a00007 mov r0, r7 | |
1c4: e1a01008 mov r1, r8 | |
1c8: e12fff33 blx r3 | |
1cc: e3100902 tst r0, #32768 ; 0x8000 | |
return; | |
udelay(1); | |
1d0: e30a036e movw r0, #41838 ; 0xa36e | |
1d4: e3400001 movt r0, #1 | |
int cnt, reg = C_CAN_IFACE(COMREQ_REG, iface); | |
priv->write_reg32(priv, reg, (cmd << 16) | obj); | |
for (cnt = MIN_TIMEOUT_VALUE; cnt; cnt--) { | |
if (!(priv->read_reg(priv, reg) & IF_COMR_BUSY)) | |
1d8: 089da9f8 ldmeq sp, {r3, r4, r5, r6, r7, r8, fp, sp, pc} | |
return; | |
udelay(1); | |
1dc: e5963004 ldr r3, [r6, #4] | |
1e0: e12fff33 blx r3 | |
struct c_can_priv *priv = netdev_priv(dev); | |
int cnt, reg = C_CAN_IFACE(COMREQ_REG, iface); | |
priv->write_reg32(priv, reg, (cmd << 16) | obj); | |
for (cnt = MIN_TIMEOUT_VALUE; cnt; cnt--) { | |
1e4: e2544001 subs r4, r4, #1 | |
1e8: 1afffff3 bne 1bc <c_can_obj_update+0x48> | |
if (!(priv->read_reg(priv, reg) & IF_COMR_BUSY)) | |
return; | |
udelay(1); | |
} | |
netdev_err(dev, "Updating object timed out\n"); | |
1ec: e3001000 movw r1, #0 | |
1f0: e1a00005 mov r0, r5 | |
1f4: e3401000 movt r1, #0 | |
1f8: ebfffffe bl 0 <netdev_err> | |
1fc: e89da9f8 ldm sp, {r3, r4, r5, r6, r7, r8, fp, sp, pc} | |
00000200 <c_can_inval_tx_object>: | |
* Note: According to documentation clearing TXIE while MSGVAL is set | |
* is not allowed, but works nicely on C/DCAN. And that lowers the I/O | |
* load significantly. | |
*/ | |
static void c_can_inval_tx_object(struct net_device *dev, int iface, int obj) | |
{ | |
200: e1a0c00d mov ip, sp | |
204: e92dd878 push {r3, r4, r5, r6, fp, ip, lr, pc} | |
208: e24cb004 sub fp, ip, #4 | |
20c: e52de004 push {lr} ; (str lr, [sp, #-4]!) | |
210: ebfffffe bl 0 <__gnu_mcount_nc> | |
214: e1a04001 mov r4, r1 | |
struct c_can_priv *priv = netdev_priv(dev); | |
priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), 0); | |
218: e0811101 add r1, r1, r1, lsl #2 | |
21c: e59035f8 ldr r3, [r0, #1528] ; 0x5f8 | |
* Note: According to documentation clearing TXIE while MSGVAL is set | |
* is not allowed, but works nicely on C/DCAN. And that lowers the I/O | |
* load significantly. | |
*/ | |
static void c_can_inval_tx_object(struct net_device *dev, int iface, int obj) | |
{ | |
220: e1a05000 mov r5, r0 | |
struct c_can_priv *priv = netdev_priv(dev); | |
priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), 0); | |
224: e0841081 add r1, r4, r1, lsl #1 | |
* Note: According to documentation clearing TXIE while MSGVAL is set | |
* is not allowed, but works nicely on C/DCAN. And that lowers the I/O | |
* load significantly. | |
*/ | |
static void c_can_inval_tx_object(struct net_device *dev, int iface, int obj) | |
{ | |
228: e1a06002 mov r6, r2 | |
struct c_can_priv *priv = netdev_priv(dev); | |
priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), 0); | |
22c: e2800d13 add r0, r0, #1216 ; 0x4c0 | |
230: e3a02000 mov r2, #0 | |
234: e281100e add r1, r1, #14 | |
238: e12fff33 blx r3 | |
} | |
static inline void c_can_object_put(struct net_device *dev, int iface, | |
u32 obj, u32 cmd) | |
{ | |
c_can_obj_update(dev, iface, cmd | IF_COMM_WR, obj); | |
23c: e1a00005 mov r0, r5 | |
240: e1a01004 mov r1, r4 | |
244: e1a03006 mov r3, r6 | |
248: e3a020b0 mov r2, #176 ; 0xb0 | |
24c: ebffffc8 bl 174 <c_can_obj_update> | |
250: e89da878 ldm sp, {r3, r4, r5, r6, fp, sp, pc} | |
00000254 <c_can_inval_msg_object>: | |
priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), 0); | |
c_can_object_put(dev, iface, obj, IF_COMM_INVAL); | |
} | |
static void c_can_inval_msg_object(struct net_device *dev, int iface, int obj) | |
{ | |
254: e1a0c00d mov ip, sp | |
258: e92dd9f8 push {r3, r4, r5, r6, r7, r8, fp, ip, lr, pc} | |
25c: e24cb004 sub fp, ip, #4 | |
260: e52de004 push {lr} ; (str lr, [sp, #-4]!) | |
264: ebfffffe bl 0 <__gnu_mcount_nc> | |
struct c_can_priv *priv = netdev_priv(dev); | |
priv->write_reg(priv, C_CAN_IFACE(ARB1_REG, iface), 0); | |
268: e0817101 add r7, r1, r1, lsl #2 | |
c_can_object_put(dev, iface, obj, IF_COMM_INVAL); | |
} | |
static void c_can_inval_msg_object(struct net_device *dev, int iface, int obj) | |
{ | |
struct c_can_priv *priv = netdev_priv(dev); | |
26c: e2806d13 add r6, r0, #1216 ; 0x4c0 | |
priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), 0); | |
c_can_object_put(dev, iface, obj, IF_COMM_INVAL); | |
} | |
static void c_can_inval_msg_object(struct net_device *dev, int iface, int obj) | |
{ | |
270: e1a05000 mov r5, r0 | |
struct c_can_priv *priv = netdev_priv(dev); | |
priv->write_reg(priv, C_CAN_IFACE(ARB1_REG, iface), 0); | |
274: e59035f8 ldr r3, [r0, #1528] ; 0x5f8 | |
278: e0817087 add r7, r1, r7, lsl #1 | |
priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), 0); | |
c_can_object_put(dev, iface, obj, IF_COMM_INVAL); | |
} | |
static void c_can_inval_msg_object(struct net_device *dev, int iface, int obj) | |
{ | |
27c: e1a04001 mov r4, r1 | |
280: e1a08002 mov r8, r2 | |
struct c_can_priv *priv = netdev_priv(dev); | |
priv->write_reg(priv, C_CAN_IFACE(ARB1_REG, iface), 0); | |
284: e1a00006 mov r0, r6 | |
288: e287100c add r1, r7, #12 | |
28c: e3a02000 mov r2, #0 | |
290: e12fff33 blx r3 | |
priv->write_reg(priv, C_CAN_IFACE(ARB2_REG, iface), 0); | |
294: e287100d add r1, r7, #13 | |
298: e1a00006 mov r0, r6 | |
29c: e59535f8 ldr r3, [r5, #1528] ; 0x5f8 | |
2a0: e3a02000 mov r2, #0 | |
2a4: e12fff33 blx r3 | |
c_can_inval_tx_object(dev, iface, obj); | |
2a8: e1a00005 mov r0, r5 | |
2ac: e1a01004 mov r1, r4 | |
2b0: e1a02008 mov r2, r8 | |
2b4: ebffffd1 bl 200 <c_can_inval_tx_object> | |
2b8: e89da9f8 ldm sp, {r3, r4, r5, r6, r7, r8, fp, sp, pc} | |
000002bc <c_can_wait_for_ctrl_init>: | |
return NETDEV_TX_OK; | |
} | |
static int c_can_wait_for_ctrl_init(struct net_device *dev, | |
struct c_can_priv *priv, u32 init) | |
{ | |
2bc: e1a0c00d mov ip, sp | |
2c0: e92dd9f8 push {r3, r4, r5, r6, r7, r8, fp, ip, lr, pc} | |
2c4: e24cb004 sub fp, ip, #4 | |
2c8: e52de004 push {lr} ; (str lr, [sp, #-4]!) | |
2cc: ebfffffe bl 0 <__gnu_mcount_nc> | |
int retry = 0; | |
while (init != (priv->read_reg(priv, C_CAN_CTRL_REG) & CONTROL_INIT)) { | |
udelay(10); | |
2d0: e3006000 movw r6, #0 | |
return NETDEV_TX_OK; | |
} | |
static int c_can_wait_for_ctrl_init(struct net_device *dev, | |
struct c_can_priv *priv, u32 init) | |
{ | |
2d4: e1a08000 mov r8, r0 | |
2d8: e1a05001 mov r5, r1 | |
2dc: e1a07002 mov r7, r2 | |
int retry = 0; | |
while (init != (priv->read_reg(priv, C_CAN_CTRL_REG) & CONTROL_INIT)) { | |
udelay(10); | |
2e0: e3406000 movt r6, #0 | |
static int c_can_wait_for_ctrl_init(struct net_device *dev, | |
struct c_can_priv *priv, u32 init) | |
{ | |
int retry = 0; | |
while (init != (priv->read_reg(priv, C_CAN_CTRL_REG) & CONTROL_INIT)) { | |
2e4: e30043ea movw r4, #1002 ; 0x3ea | |
2e8: ea000003 b 2fc <c_can_wait_for_ctrl_init+0x40> | |
udelay(10); | |
2ec: e5963004 ldr r3, [r6, #4] | |
2f0: e12fff33 blx r3 | |
if (retry++ > 1000) { | |
2f4: e2544001 subs r4, r4, #1 | |
2f8: 0a00000a beq 328 <c_can_wait_for_ctrl_init+0x6c> | |
static int c_can_wait_for_ctrl_init(struct net_device *dev, | |
struct c_can_priv *priv, u32 init) | |
{ | |
int retry = 0; | |
while (init != (priv->read_reg(priv, C_CAN_CTRL_REG) & CONTROL_INIT)) { | |
2fc: e5953134 ldr r3, [r5, #308] ; 0x134 | |
300: e1a00005 mov r0, r5 | |
304: e3a01000 mov r1, #0 | |
308: e12fff33 blx r3 | |
30c: e2003001 and r3, r0, #1 | |
udelay(10); | |
310: e306024c movw r0, #25164 ; 0x624c | |
static int c_can_wait_for_ctrl_init(struct net_device *dev, | |
struct c_can_priv *priv, u32 init) | |
{ | |
int retry = 0; | |
while (init != (priv->read_reg(priv, C_CAN_CTRL_REG) & CONTROL_INIT)) { | |
314: e1530007 cmp r3, r7 | |
udelay(10); | |
318: e3400010 movt r0, #16 | |
static int c_can_wait_for_ctrl_init(struct net_device *dev, | |
struct c_can_priv *priv, u32 init) | |
{ | |
int retry = 0; | |
while (init != (priv->read_reg(priv, C_CAN_CTRL_REG) & CONTROL_INIT)) { | |
31c: 1afffff2 bne 2ec <c_can_wait_for_ctrl_init+0x30> | |
if (retry++ > 1000) { | |
netdev_err(dev, "CCTRL: set CONTROL_INIT failed\n"); | |
return -EIO; | |
} | |
} | |
return 0; | |
320: e3a00000 mov r0, #0 | |
} | |
324: e89da9f8 ldm sp, {r3, r4, r5, r6, r7, r8, fp, sp, pc} | |
int retry = 0; | |
while (init != (priv->read_reg(priv, C_CAN_CTRL_REG) & CONTROL_INIT)) { | |
udelay(10); | |
if (retry++ > 1000) { | |
netdev_err(dev, "CCTRL: set CONTROL_INIT failed\n"); | |
328: e3001000 movw r1, #0 | |
32c: e1a00008 mov r0, r8 | |
330: e3401000 movt r1, #0 | |
334: ebfffffe bl 0 <netdev_err> | |
return -EIO; | |
338: e3e00004 mvn r0, #4 | |
33c: e89da9f8 ldm sp, {r3, r4, r5, r6, r7, r8, fp, sp, pc} | |
00000340 <c_can_handle_state_change>: | |
return pkts; | |
} | |
static int c_can_handle_state_change(struct net_device *dev, | |
enum c_can_bus_error_types error_type) | |
{ | |
340: e1a0c00d mov ip, sp | |
344: e92dd9f0 push {r4, r5, r6, r7, r8, fp, ip, lr, pc} | |
348: e24cb004 sub fp, ip, #4 | |
34c: e24dd00c sub sp, sp, #12 | |
350: e52de004 push {lr} ; (str lr, [sp, #-4]!) | |
354: ebfffffe bl 0 <__gnu_mcount_nc> | |
struct net_device_stats *stats = &dev->stats; | |
struct can_frame *cf; | |
struct sk_buff *skb; | |
struct can_berr_counter bec; | |
switch (error_type) { | |
358: e3510002 cmp r1, #2 | |
return pkts; | |
} | |
static int c_can_handle_state_change(struct net_device *dev, | |
enum c_can_bus_error_types error_type) | |
{ | |
35c: e1a05001 mov r5, r1 | |
360: e1a04000 mov r4, r0 | |
unsigned int reg_err_counter; | |
unsigned int rx_err_passive; | |
struct c_can_priv *priv = netdev_priv(dev); | |
364: e2807d13 add r7, r0, #1216 ; 0x4c0 | |
struct net_device_stats *stats = &dev->stats; | |
struct can_frame *cf; | |
struct sk_buff *skb; | |
struct can_berr_counter bec; | |
switch (error_type) { | |
368: 0a00004b beq 49c <c_can_handle_state_change+0x15c> | |
36c: e3510003 cmp r1, #3 | |
370: 0a000043 beq 484 <c_can_handle_state_change+0x144> | |
374: e3510001 cmp r1, #1 | |
378: 0a00003b beq 46c <c_can_handle_state_change+0x12c> | |
default: | |
break; | |
} | |
/* propagate the error condition to the CAN stack */ | |
skb = alloc_can_err_skb(dev, &cf); | |
37c: e1a00004 mov r0, r4 | |
380: e24b1028 sub r1, fp, #40 ; 0x28 | |
384: ebfffffe bl 0 <alloc_can_err_skb> | |
if (unlikely(!skb)) | |
388: e2506000 subs r6, r0, #0 | |
38c: 0a000055 beq 4e8 <c_can_handle_state_change+0x1a8> | |
struct can_berr_counter *bec) | |
{ | |
unsigned int reg_err_counter; | |
struct c_can_priv *priv = netdev_priv(dev); | |
reg_err_counter = priv->read_reg(priv, C_CAN_ERR_CNT_REG); | |
390: e59435f4 ldr r3, [r4, #1524] ; 0x5f4 | |
394: e1a00007 mov r0, r7 | |
398: e3a01003 mov r1, #3 | |
39c: e12fff33 blx r3 | |
skb = alloc_can_err_skb(dev, &cf); | |
if (unlikely(!skb)) | |
return 0; | |
__c_can_get_berr_counter(dev, &bec); | |
reg_err_counter = priv->read_reg(priv, C_CAN_ERR_CNT_REG); | |
3a0: e59425f4 ldr r2, [r4, #1524] ; 0x5f4 | |
struct can_berr_counter *bec) | |
{ | |
unsigned int reg_err_counter; | |
struct c_can_priv *priv = netdev_priv(dev); | |
reg_err_counter = priv->read_reg(priv, C_CAN_ERR_CNT_REG); | |
3a4: e1a03000 mov r3, r0 | |
skb = alloc_can_err_skb(dev, &cf); | |
if (unlikely(!skb)) | |
return 0; | |
__c_can_get_berr_counter(dev, &bec); | |
reg_err_counter = priv->read_reg(priv, C_CAN_ERR_CNT_REG); | |
3a8: e3a01003 mov r1, #3 | |
3ac: e1a00007 mov r0, r7 | |
struct c_can_priv *priv = netdev_priv(dev); | |
reg_err_counter = priv->read_reg(priv, C_CAN_ERR_CNT_REG); | |
bec->rxerr = (reg_err_counter & ERR_CNT_REC_MASK) >> | |
ERR_CNT_REC_SHIFT; | |
bec->txerr = reg_err_counter & ERR_CNT_TEC_MASK; | |
3b0: e6ef8073 uxtb r8, r3 | |
{ | |
unsigned int reg_err_counter; | |
struct c_can_priv *priv = netdev_priv(dev); | |
reg_err_counter = priv->read_reg(priv, C_CAN_ERR_CNT_REG); | |
bec->rxerr = (reg_err_counter & ERR_CNT_REC_MASK) >> | |
3b4: e7e67453 ubfx r7, r3, #8, #7 | |
skb = alloc_can_err_skb(dev, &cf); | |
if (unlikely(!skb)) | |
return 0; | |
__c_can_get_berr_counter(dev, &bec); | |
reg_err_counter = priv->read_reg(priv, C_CAN_ERR_CNT_REG); | |
3b8: e12fff32 blx r2 | |
rx_err_passive = (reg_err_counter & ERR_CNT_RP_MASK) >> | |
ERR_CNT_RP_SHIFT; | |
switch (error_type) { | |
3bc: e3550002 cmp r5, #2 | |
3c0: 0a00003b beq 4b4 <c_can_handle_state_change+0x174> | |
3c4: e3550003 cmp r5, #3 | |
3c8: 0a000015 beq 424 <c_can_handle_state_change+0xe4> | |
3cc: e3550001 cmp r5, #1 | |
3d0: 1a000005 bne 3ec <c_can_handle_state_change+0xac> | |
cf->data[6] = bec.txerr; | |
cf->data[7] = bec.rxerr; | |
break; | |
case C_CAN_BUS_OFF: | |
/* bus-off state */ | |
cf->can_id |= CAN_ERR_BUSOFF; | |
3d4: e51b3028 ldr r3, [fp, #-40] ; 0x28 | |
can_bus_off(dev); | |
3d8: e1a00004 mov r0, r4 | |
cf->data[6] = bec.txerr; | |
cf->data[7] = bec.rxerr; | |
break; | |
case C_CAN_BUS_OFF: | |
/* bus-off state */ | |
cf->can_id |= CAN_ERR_BUSOFF; | |
3dc: e5932000 ldr r2, [r3] | |
3e0: e3822040 orr r2, r2, #64 ; 0x40 | |
3e4: e5832000 str r2, [r3] | |
can_bus_off(dev); | |
3e8: ebfffffe bl 0 <can_bus_off> | |
3ec: e51b2028 ldr r2, [fp, #-40] ; 0x28 | |
break; | |
default: | |
break; | |
} | |
stats->rx_packets++; | |
3f0: e59430c0 ldr r3, [r4, #192] ; 0xc0 | |
int netif_rx(struct sk_buff *skb); | |
int netif_rx_ni(struct sk_buff *skb); | |
int netif_receive_skb_sk(struct sock *sk, struct sk_buff *skb); | |
static inline int netif_receive_skb(struct sk_buff *skb) | |
{ | |
return netif_receive_skb_sk(skb->sk, skb); | |
3f4: e1a01006 mov r1, r6 | |
stats->rx_bytes += cf->can_dlc; | |
3f8: e59400c8 ldr r0, [r4, #200] ; 0xc8 | |
break; | |
default: | |
break; | |
} | |
stats->rx_packets++; | |
3fc: e2833001 add r3, r3, #1 | |
400: e58430c0 str r3, [r4, #192] ; 0xc0 | |
stats->rx_bytes += cf->can_dlc; | |
404: e5d23004 ldrb r3, [r2, #4] | |
408: e0803003 add r3, r0, r3 | |
40c: e58430c8 str r3, [r4, #200] ; 0xc8 | |
410: e5960010 ldr r0, [r6, #16] | |
414: ebfffffe bl 0 <netif_receive_skb_sk> | |
netif_receive_skb(skb); | |
return 1; | |
418: e3a00001 mov r0, #1 | |
} | |
41c: e24bd020 sub sp, fp, #32 | |
420: e89da9f0 ldm sp, {r4, r5, r6, r7, r8, fp, sp, pc} | |
cf->data[7] = bec.rxerr; | |
break; | |
case C_CAN_ERROR_PASSIVE: | |
/* error passive state */ | |
cf->can_id |= CAN_ERR_CRTL; | |
424: e51b3028 ldr r3, [fp, #-40] ; 0x28 | |
if (rx_err_passive) | |
428: e3100902 tst r0, #32768 ; 0x8000 | |
cf->data[7] = bec.rxerr; | |
break; | |
case C_CAN_ERROR_PASSIVE: | |
/* error passive state */ | |
cf->can_id |= CAN_ERR_CRTL; | |
42c: e5932000 ldr r2, [r3] | |
430: e3822004 orr r2, r2, #4 | |
434: e5832000 str r2, [r3] | |
if (rx_err_passive) | |
cf->data[1] |= CAN_ERR_CRTL_RX_PASSIVE; | |
438: 151b3028 ldrne r3, [fp, #-40] ; 0x28 | |
43c: 051b2028 ldreq r2, [fp, #-40] ; 0x28 | |
440: 15d31009 ldrbne r1, [r3, #9] | |
444: 11a02003 movne r2, r3 | |
448: 13811010 orrne r1, r1, #16 | |
44c: 15c31009 strbne r1, [r3, #9] | |
if (bec.txerr > 127) | |
450: e358007f cmp r8, #127 ; 0x7f | |
cf->data[1] |= CAN_ERR_CRTL_TX_PASSIVE; | |
454: 85d23009 ldrbhi r3, [r2, #9] | |
cf->data[6] = bec.txerr; | |
458: e5c2800e strb r8, [r2, #14] | |
cf->data[7] = bec.rxerr; | |
45c: e5c2700f strb r7, [r2, #15] | |
/* error passive state */ | |
cf->can_id |= CAN_ERR_CRTL; | |
if (rx_err_passive) | |
cf->data[1] |= CAN_ERR_CRTL_RX_PASSIVE; | |
if (bec.txerr > 127) | |
cf->data[1] |= CAN_ERR_CRTL_TX_PASSIVE; | |
460: 83833020 orrhi r3, r3, #32 | |
464: 85c23009 strbhi r3, [r2, #9] | |
cf->data[6] = bec.txerr; | |
cf->data[7] = bec.rxerr; | |
break; | |
468: eaffffe0 b 3f0 <c_can_handle_state_change+0xb0> | |
priv->can.state = CAN_STATE_ERROR_PASSIVE; | |
break; | |
case C_CAN_BUS_OFF: | |
/* bus-off state */ | |
priv->can.state = CAN_STATE_BUS_OFF; | |
priv->can.can_stats.bus_off++; | |
46c: e59034cc ldr r3, [r0, #1228] ; 0x4cc | |
priv->can.can_stats.error_passive++; | |
priv->can.state = CAN_STATE_ERROR_PASSIVE; | |
break; | |
case C_CAN_BUS_OFF: | |
/* bus-off state */ | |
priv->can.state = CAN_STATE_BUS_OFF; | |
470: e3a02003 mov r2, #3 | |
474: e5802524 str r2, [r0, #1316] ; 0x524 | |
priv->can.can_stats.bus_off++; | |
478: e2833001 add r3, r3, #1 | |
47c: e58034cc str r3, [r0, #1228] ; 0x4cc | |
break; | |
480: eaffffbd b 37c <c_can_handle_state_change+0x3c> | |
priv->can.can_stats.error_warning++; | |
priv->can.state = CAN_STATE_ERROR_WARNING; | |
break; | |
case C_CAN_ERROR_PASSIVE: | |
/* error passive state */ | |
priv->can.can_stats.error_passive++; | |
484: e59034c8 ldr r3, [r0, #1224] ; 0x4c8 | |
priv->can.state = CAN_STATE_ERROR_PASSIVE; | |
488: e3a02002 mov r2, #2 | |
48c: e5802524 str r2, [r0, #1316] ; 0x524 | |
priv->can.can_stats.error_warning++; | |
priv->can.state = CAN_STATE_ERROR_WARNING; | |
break; | |
case C_CAN_ERROR_PASSIVE: | |
/* error passive state */ | |
priv->can.can_stats.error_passive++; | |
490: e2833001 add r3, r3, #1 | |
494: e58034c8 str r3, [r0, #1224] ; 0x4c8 | |
priv->can.state = CAN_STATE_ERROR_PASSIVE; | |
break; | |
498: eaffffb7 b 37c <c_can_handle_state_change+0x3c> | |
struct can_berr_counter bec; | |
switch (error_type) { | |
case C_CAN_ERROR_WARNING: | |
/* error warning state */ | |
priv->can.can_stats.error_warning++; | |
49c: e59034c4 ldr r3, [r0, #1220] ; 0x4c4 | |
priv->can.state = CAN_STATE_ERROR_WARNING; | |
4a0: e3a02001 mov r2, #1 | |
4a4: e5802524 str r2, [r0, #1316] ; 0x524 | |
struct can_berr_counter bec; | |
switch (error_type) { | |
case C_CAN_ERROR_WARNING: | |
/* error warning state */ | |
priv->can.can_stats.error_warning++; | |
4a8: e0833002 add r3, r3, r2 | |
4ac: e58034c4 str r3, [r0, #1220] ; 0x4c4 | |
priv->can.state = CAN_STATE_ERROR_WARNING; | |
break; | |
4b0: eaffffb1 b 37c <c_can_handle_state_change+0x3c> | |
ERR_CNT_RP_SHIFT; | |
switch (error_type) { | |
case C_CAN_ERROR_WARNING: | |
/* error warning state */ | |
cf->can_id |= CAN_ERR_CRTL; | |
4b4: e51b3028 ldr r3, [fp, #-40] ; 0x28 | |
cf->data[1] = (bec.txerr > bec.rxerr) ? | |
4b8: e1570008 cmp r7, r8 | |
4bc: 23a01004 movcs r1, #4 | |
4c0: 33a01008 movcc r1, #8 | |
ERR_CNT_RP_SHIFT; | |
switch (error_type) { | |
case C_CAN_ERROR_WARNING: | |
/* error warning state */ | |
cf->can_id |= CAN_ERR_CRTL; | |
4c4: e5932000 ldr r2, [r3] | |
4c8: e3822004 orr r2, r2, #4 | |
4cc: e5832000 str r2, [r3] | |
cf->data[1] = (bec.txerr > bec.rxerr) ? | |
4d0: e51b3028 ldr r3, [fp, #-40] ; 0x28 | |
CAN_ERR_CRTL_TX_WARNING : | |
CAN_ERR_CRTL_RX_WARNING; | |
cf->data[6] = bec.txerr; | |
4d4: e5c3800e strb r8, [r3, #14] | |
cf->data[7] = bec.rxerr; | |
break; | |
4d8: e1a02003 mov r2, r3 | |
cf->can_id |= CAN_ERR_CRTL; | |
cf->data[1] = (bec.txerr > bec.rxerr) ? | |
CAN_ERR_CRTL_TX_WARNING : | |
CAN_ERR_CRTL_RX_WARNING; | |
cf->data[6] = bec.txerr; | |
cf->data[7] = bec.rxerr; | |
4dc: e5c3700f strb r7, [r3, #15] | |
switch (error_type) { | |
case C_CAN_ERROR_WARNING: | |
/* error warning state */ | |
cf->can_id |= CAN_ERR_CRTL; | |
cf->data[1] = (bec.txerr > bec.rxerr) ? | |
4e0: e5c31009 strb r1, [r3, #9] | |
CAN_ERR_CRTL_TX_WARNING : | |
CAN_ERR_CRTL_RX_WARNING; | |
cf->data[6] = bec.txerr; | |
cf->data[7] = bec.rxerr; | |
break; | |
4e4: eaffffc1 b 3f0 <c_can_handle_state_change+0xb0> | |
} | |
/* propagate the error condition to the CAN stack */ | |
skb = alloc_can_err_skb(dev, &cf); | |
if (unlikely(!skb)) | |
return 0; | |
4e8: e1a00006 mov r0, r6 | |
4ec: eaffffca b 41c <c_can_handle_state_change+0xdc> | |
000004f0 <c_can_power_down>: | |
} | |
EXPORT_SYMBOL_GPL(alloc_c_can_dev); | |
#ifdef CONFIG_PM | |
int c_can_power_down(struct net_device *dev) | |
{ | |
4f0: e1a0c00d mov ip, sp | |
4f4: e92dd8f0 push {r4, r5, r6, r7, fp, ip, lr, pc} | |
4f8: e24cb004 sub fp, ip, #4 | |
4fc: e52de004 push {lr} ; (str lr, [sp, #-4]!) | |
500: ebfffffe bl 0 <__gnu_mcount_nc> | |
504: e1a04000 mov r4, r0 | |
u32 val; | |
unsigned long time_out; | |
struct c_can_priv *priv = netdev_priv(dev); | |
if (!(dev->flags & IFF_UP)) | |
508: e5903130 ldr r3, [r0, #304] ; 0x130 | |
50c: e3130001 tst r3, #1 | |
510: 0a00002d beq 5cc <c_can_power_down+0xdc> | |
return 0; | |
WARN_ON(priv->type != BOSCH_D_CAN); | |
514: e5903610 ldr r3, [r0, #1552] ; 0x610 | |
518: e3530002 cmp r3, #2 | |
51c: 1a00002e bne 5dc <c_can_power_down+0xec> | |
#ifdef CONFIG_PM | |
int c_can_power_down(struct net_device *dev) | |
{ | |
u32 val; | |
unsigned long time_out; | |
struct c_can_priv *priv = netdev_priv(dev); | |
520: e2846d13 add r6, r4, #1216 ; 0x4c0 | |
return 0; | |
WARN_ON(priv->type != BOSCH_D_CAN); | |
/* set PDR value so the device goes to power down mode */ | |
val = priv->read_reg(priv, C_CAN_CTRL_EX_REG); | |
524: e59435f4 ldr r3, [r4, #1524] ; 0x5f4 | |
528: e3a01001 mov r1, #1 | |
52c: e1a00006 mov r0, r6 | |
530: e12fff33 blx r3 | |
val |= CONTROL_EX_PDR; | |
priv->write_reg(priv, C_CAN_CTRL_EX_REG, val); | |
/* Wait for the PDA bit to get set */ | |
time_out = jiffies + msecs_to_jiffies(INIT_WAIT_MS); | |
534: e3005000 movw r5, #0 | |
WARN_ON(priv->type != BOSCH_D_CAN); | |
/* set PDR value so the device goes to power down mode */ | |
val = priv->read_reg(priv, C_CAN_CTRL_EX_REG); | |
val |= CONTROL_EX_PDR; | |
538: e3802c01 orr r2, r0, #256 ; 0x100 | |
priv->write_reg(priv, C_CAN_CTRL_EX_REG, val); | |
53c: e6ff2072 uxth r2, r2 | |
540: e1a00006 mov r0, r6 | |
544: e59435f8 ldr r3, [r4, #1528] ; 0x5f8 | |
548: e3a01001 mov r1, #1 | |
/* Wait for the PDA bit to get set */ | |
time_out = jiffies + msecs_to_jiffies(INIT_WAIT_MS); | |
54c: e3405000 movt r5, #0 | |
WARN_ON(priv->type != BOSCH_D_CAN); | |
/* set PDR value so the device goes to power down mode */ | |
val = priv->read_reg(priv, C_CAN_CTRL_EX_REG); | |
val |= CONTROL_EX_PDR; | |
priv->write_reg(priv, C_CAN_CTRL_EX_REG, val); | |
550: e12fff33 blx r3 | |
/* Wait for the PDA bit to get set */ | |
time_out = jiffies + msecs_to_jiffies(INIT_WAIT_MS); | |
554: e5957000 ldr r7, [r5] | |
558: e2877064 add r7, r7, #100 ; 0x64 | |
while (!(priv->read_reg(priv, C_CAN_STS_REG) & STATUS_PDA) && | |
55c: ea000003 b 570 <c_can_power_down+0x80> | |
time_after(time_out, jiffies)) | |
560: e5953000 ldr r3, [r5] | |
564: e0673003 rsb r3, r7, r3 | |
568: e3530000 cmp r3, #0 | |
56c: aa000005 bge 588 <c_can_power_down+0x98> | |
val |= CONTROL_EX_PDR; | |
priv->write_reg(priv, C_CAN_CTRL_EX_REG, val); | |
/* Wait for the PDA bit to get set */ | |
time_out = jiffies + msecs_to_jiffies(INIT_WAIT_MS); | |
while (!(priv->read_reg(priv, C_CAN_STS_REG) & STATUS_PDA) && | |
570: e59435f4 ldr r3, [r4, #1524] ; 0x5f4 | |
574: e1a00006 mov r0, r6 | |
578: e3a01002 mov r1, #2 | |
57c: e12fff33 blx r3 | |
580: e3100b01 tst r0, #1024 ; 0x400 | |
584: 0afffff5 beq 560 <c_can_power_down+0x70> | |
time_after(time_out, jiffies)) | |
cpu_relax(); | |
if (time_after(jiffies, time_out)) | |
588: e5953000 ldr r3, [r5] | |
58c: e0637007 rsb r7, r3, r7 | |
590: e3570000 cmp r7, #0 | |
594: ba00000e blt 5d4 <c_can_power_down+0xe4> | |
return -ETIMEDOUT; | |
c_can_stop(dev); | |
598: e1a00004 mov r0, r4 | |
59c: ebfffeaa bl 4c <c_can_stop> | |
pm_runtime_put_sync(priv->device); | |
} | |
static inline void c_can_reset_ram(const struct c_can_priv *priv, bool enable) | |
{ | |
if (priv->raminit) | |
5a0: e5943620 ldr r3, [r4, #1568] ; 0x620 | |
5a4: e3530000 cmp r3, #0 | |
5a8: 0a000002 beq 5b8 <c_can_power_down+0xc8> | |
priv->raminit(priv, enable); | |
5ac: e1a00006 mov r0, r6 | |
5b0: e3a01000 mov r1, #0 | |
5b4: e12fff33 blx r3 | |
pm_runtime_get_sync(priv->device); | |
} | |
static inline void c_can_pm_runtime_put_sync(const struct c_can_priv *priv) | |
{ | |
if (priv->device) | |
5b8: e59405e4 ldr r0, [r4, #1508] ; 0x5e4 | |
5bc: e3500000 cmp r0, #0 | |
5c0: 0a000001 beq 5cc <c_can_power_down+0xdc> | |
5c4: e3a01004 mov r1, #4 | |
5c8: ebfffffe bl 0 <__pm_runtime_idle> | |
c_can_stop(dev); | |
c_can_reset_ram(priv, false); | |
c_can_pm_runtime_put_sync(priv); | |
return 0; | |
5cc: e3a00000 mov r0, #0 | |
5d0: e89da8f0 ldm sp, {r4, r5, r6, r7, fp, sp, pc} | |
while (!(priv->read_reg(priv, C_CAN_STS_REG) & STATUS_PDA) && | |
time_after(time_out, jiffies)) | |
cpu_relax(); | |
if (time_after(jiffies, time_out)) | |
return -ETIMEDOUT; | |
5d4: e3e0006d mvn r0, #109 ; 0x6d | |
c_can_reset_ram(priv, false); | |
c_can_pm_runtime_put_sync(priv); | |
return 0; | |
} | |
5d8: e89da8f0 ldm sp, {r4, r5, r6, r7, fp, sp, pc} | |
struct c_can_priv *priv = netdev_priv(dev); | |
if (!(dev->flags & IFF_UP)) | |
return 0; | |
WARN_ON(priv->type != BOSCH_D_CAN); | |
5dc: e3000000 movw r0, #0 | |
5e0: e3001497 movw r1, #1175 ; 0x497 | |
5e4: e3400000 movt r0, #0 | |
5e8: ebfffffe bl 0 <warn_slowpath_null> | |
5ec: eaffffcb b 520 <c_can_power_down+0x30> | |
000005f0 <free_c_can_dev>: | |
} | |
EXPORT_SYMBOL_GPL(c_can_power_up); | |
#endif | |
void free_c_can_dev(struct net_device *dev) | |
{ | |
5f0: e1a0c00d mov ip, sp | |
5f4: e92dd818 push {r3, r4, fp, ip, lr, pc} | |
5f8: e24cb004 sub fp, ip, #4 | |
5fc: e52de004 push {lr} ; (str lr, [sp, #-4]!) | |
600: ebfffffe bl 0 <__gnu_mcount_nc> | |
604: e1a04000 mov r4, r0 | |
struct c_can_priv *priv = netdev_priv(dev); | |
netif_napi_del(&priv->napi); | |
608: e2800e57 add r0, r0, #1392 ; 0x570 | |
60c: ebfffffe bl 0 <netif_napi_del> | |
free_candev(dev); | |
610: e1a00004 mov r0, r4 | |
614: ebfffffe bl 0 <free_candev> | |
618: e89da818 ldm sp, {r3, r4, fp, sp, pc} | |
0000061c <c_can_close>: | |
c_can_pm_runtime_put_sync(priv); | |
return err; | |
} | |
static int c_can_close(struct net_device *dev) | |
{ | |
61c: e1a0c00d mov ip, sp | |
620: e92dd830 push {r4, r5, fp, ip, lr, pc} | |
624: e24cb004 sub fp, ip, #4 | |
628: e52de004 push {lr} ; (str lr, [sp, #-4]!) | |
62c: ebfffffe bl 0 <__gnu_mcount_nc> | |
630: e1a04000 mov r4, r0 | |
} | |
} | |
static inline void netif_tx_stop_queue(struct netdev_queue *dev_queue) | |
{ | |
set_bit(__QUEUE_STATE_DRV_XOFF, &dev_queue->state); | |
634: e3a00000 mov r0, #0 | |
638: e5941240 ldr r1, [r4, #576] ; 0x240 | |
struct c_can_priv *priv = netdev_priv(dev); | |
netif_stop_queue(dev); | |
napi_disable(&priv->napi); | |
63c: e2845d13 add r5, r4, #1216 ; 0x4c0 | |
640: e2811050 add r1, r1, #80 ; 0x50 | |
644: ebfffffe bl 0 <_set_bit> | |
648: e2840e57 add r0, r4, #1392 ; 0x570 | |
64c: ebfffffe bl 0 <napi_disable> | |
c_can_stop(dev); | |
650: e1a00004 mov r0, r4 | |
654: ebfffe7c bl 4c <c_can_stop> | |
free_irq(dev->irq, dev); | |
658: e5940028 ldr r0, [r4, #40] ; 0x28 | |
65c: e1a01004 mov r1, r4 | |
660: ebfffffe bl 0 <free_irq> | |
close_candev(dev); | |
664: e1a00004 mov r0, r4 | |
668: ebfffffe bl 0 <close_candev> | |
pm_runtime_put_sync(priv->device); | |
} | |
static inline void c_can_reset_ram(const struct c_can_priv *priv, bool enable) | |
{ | |
if (priv->raminit) | |
66c: e5943620 ldr r3, [r4, #1568] ; 0x620 | |
670: e3530000 cmp r3, #0 | |
674: 0a000002 beq 684 <c_can_close+0x68> | |
priv->raminit(priv, enable); | |
678: e1a00005 mov r0, r5 | |
67c: e3a01000 mov r1, #0 | |
680: e12fff33 blx r3 | |
pm_runtime_get_sync(priv->device); | |
} | |
static inline void c_can_pm_runtime_put_sync(const struct c_can_priv *priv) | |
{ | |
if (priv->device) | |
684: e59405e4 ldr r0, [r4, #1508] ; 0x5e4 | |
688: e3500000 cmp r0, #0 | |
68c: 0a000001 beq 698 <c_can_close+0x7c> | |
690: e3a01004 mov r1, #4 | |
694: ebfffffe bl 0 <__pm_runtime_idle> | |
c_can_pm_runtime_put_sync(priv); | |
can_led_event(dev, CAN_LED_EVENT_STOP); | |
return 0; | |
} | |
698: e3a00000 mov r0, #0 | |
69c: e89da830 ldm sp, {r4, r5, fp, sp, pc} | |
000006a0 <c_can_isr>: | |
return work_done; | |
} | |
static irqreturn_t c_can_isr(int irq, void *dev_id) | |
{ | |
6a0: e1a0c00d mov ip, sp | |
6a4: e92dd830 push {r4, r5, fp, ip, lr, pc} | |
6a8: e24cb004 sub fp, ip, #4 | |
6ac: e52de004 push {lr} ; (str lr, [sp, #-4]!) | |
6b0: ebfffffe bl 0 <__gnu_mcount_nc> | |
6b4: e1a04001 mov r4, r1 | |
struct net_device *dev = (struct net_device *)dev_id; | |
struct c_can_priv *priv = netdev_priv(dev); | |
if (!priv->read_reg(priv, C_CAN_INT_REG)) | |
6b8: e3a01005 mov r1, #5 | |
} | |
static irqreturn_t c_can_isr(int irq, void *dev_id) | |
{ | |
struct net_device *dev = (struct net_device *)dev_id; | |
struct c_can_priv *priv = netdev_priv(dev); | |
6bc: e2845d13 add r5, r4, #1216 ; 0x4c0 | |
if (!priv->read_reg(priv, C_CAN_INT_REG)) | |
6c0: e59435f4 ldr r3, [r4, #1524] ; 0x5f4 | |
6c4: e1a00005 mov r0, r5 | |
6c8: e12fff33 blx r3 | |
6cc: e3500000 cmp r0, #0 | |
6d0: 089da830 ldmeq sp, {r4, r5, fp, sp, pc} | |
return IRQ_NONE; | |
/* disable all interrupts and schedule the NAPI */ | |
c_can_irq_control(priv, false); | |
6d4: e1a00005 mov r0, r5 | |
6d8: e3a01000 mov r1, #0 | |
6dc: ebfffe47 bl 0 <c_can_irq_control> | |
* @nr: bit number to test | |
* @addr: Address to start counting from | |
*/ | |
static inline int test_bit(int nr, const volatile unsigned long *addr) | |
{ | |
return 1UL & (addr[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG-1))); | |
6e0: e5940578 ldr r0, [r4, #1400] ; 0x578 | |
6e4: e7e000d0 ubfx r0, r0, #1, #1 | |
* insure only one NAPI poll instance runs. We also make | |
* sure there is no pending NAPI disable. | |
*/ | |
static inline bool napi_schedule_prep(struct napi_struct *n) | |
{ | |
return !napi_disable_pending(n) && | |
6e8: e3500000 cmp r0, #0 | |
6ec: 0a000001 beq 6f8 <c_can_isr+0x58> | |
napi_schedule(&priv->napi); | |
return IRQ_HANDLED; | |
6f0: e3a00001 mov r0, #1 | |
} | |
6f4: e89da830 ldm sp, {r4, r5, fp, sp, pc} | |
!test_and_set_bit(NAPI_STATE_SCHED, &n->state); | |
6f8: e2844e57 add r4, r4, #1392 ; 0x570 | |
6fc: e2841008 add r1, r4, #8 | |
700: ebfffffe bl 0 <_test_and_set_bit> | |
* insure only one NAPI poll instance runs. We also make | |
* sure there is no pending NAPI disable. | |
*/ | |
static inline bool napi_schedule_prep(struct napi_struct *n) | |
{ | |
return !napi_disable_pending(n) && | |
704: e3500000 cmp r0, #0 | |
708: 1afffff8 bne 6f0 <c_can_isr+0x50> | |
* running. | |
*/ | |
static inline void napi_schedule(struct napi_struct *n) | |
{ | |
if (napi_schedule_prep(n)) | |
__napi_schedule(n); | |
70c: e1a00004 mov r0, r4 | |
710: ebfffffe bl 0 <__napi_schedule> | |
/* disable all interrupts and schedule the NAPI */ | |
c_can_irq_control(priv, false); | |
napi_schedule(&priv->napi); | |
return IRQ_HANDLED; | |
714: e3a00001 mov r0, #1 | |
718: e89da830 ldm sp, {r4, r5, fp, sp, pc} | |
0000071c <unregister_c_can_dev>: | |
return err; | |
} | |
EXPORT_SYMBOL_GPL(register_c_can_dev); | |
void unregister_c_can_dev(struct net_device *dev) | |
{ | |
71c: e1a0c00d mov ip, sp | |
720: e92dd818 push {r3, r4, fp, ip, lr, pc} | |
724: e24cb004 sub fp, ip, #4 | |
728: e52de004 push {lr} ; (str lr, [sp, #-4]!) | |
72c: ebfffffe bl 0 <__gnu_mcount_nc> | |
730: e1a04000 mov r4, r0 | |
struct c_can_priv *priv = netdev_priv(dev); | |
unregister_candev(dev); | |
734: ebfffffe bl 0 <unregister_candev> | |
pm_runtime_enable(priv->device); | |
} | |
static inline void c_can_pm_runtime_disable(const struct c_can_priv *priv) | |
{ | |
if (priv->device) | |
738: e59405e4 ldr r0, [r4, #1508] ; 0x5e4 | |
73c: e3500000 cmp r0, #0 | |
740: 089da818 ldmeq sp, {r3, r4, fp, sp, pc} | |
__pm_runtime_set_status(dev, RPM_SUSPENDED); | |
} | |
static inline void pm_runtime_disable(struct device *dev) | |
{ | |
__pm_runtime_disable(dev, true); | |
744: e3a01001 mov r1, #1 | |
748: ebfffffe bl 0 <__pm_runtime_disable> | |
74c: e89da818 ldm sp, {r3, r4, fp, sp, pc} | |
00000750 <register_c_can_dev>: | |
.ndo_start_xmit = c_can_start_xmit, | |
.ndo_change_mtu = can_change_mtu, | |
}; | |
int register_c_can_dev(struct net_device *dev) | |
{ | |
750: e1a0c00d mov ip, sp | |
754: e92dd830 push {r4, r5, fp, ip, lr, pc} | |
758: e24cb004 sub fp, ip, #4 | |
75c: e52de004 push {lr} ; (str lr, [sp, #-4]!) | |
760: ebfffffe bl 0 <__gnu_mcount_nc> | |
764: e1a04000 mov r4, r0 | |
.brp_inc = 1, | |
}; | |
static inline void c_can_pm_runtime_enable(const struct c_can_priv *priv) | |
{ | |
if (priv->device) | |
768: e59005e4 ldr r0, [r0, #1508] ; 0x5e4 | |
76c: e3500000 cmp r0, #0 | |
770: 0a000000 beq 778 <register_c_can_dev+0x28> | |
pm_runtime_enable(priv->device); | |
774: ebfffffe bl 0 <pm_runtime_enable> | |
*/ | |
pinctrl_pm_select_sleep_state(dev->dev.parent); | |
c_can_pm_runtime_enable(priv); | |
dev->flags |= IFF_ECHO; /* we support local echo */ | |
778: e5942130 ldr r2, [r4, #304] ; 0x130 | |
dev->netdev_ops = &c_can_netdev_ops; | |
err = register_candev(dev); | |
77c: e1a00004 mov r0, r4 | |
pinctrl_pm_select_sleep_state(dev->dev.parent); | |
c_can_pm_runtime_enable(priv); | |
dev->flags |= IFF_ECHO; /* we support local echo */ | |
dev->netdev_ops = &c_can_netdev_ops; | |
780: e59f3030 ldr r3, [pc, #48] ; 7b8 <register_c_can_dev+0x68> | |
*/ | |
pinctrl_pm_select_sleep_state(dev->dev.parent); | |
c_can_pm_runtime_enable(priv); | |
dev->flags |= IFF_ECHO; /* we support local echo */ | |
784: e3822701 orr r2, r2, #262144 ; 0x40000 | |
788: e5842130 str r2, [r4, #304] ; 0x130 | |
dev->netdev_ops = &c_can_netdev_ops; | |
78c: e5843124 str r3, [r4, #292] ; 0x124 | |
err = register_candev(dev); | |
790: ebfffffe bl 0 <register_candev> | |
if (err) | |
794: e2505000 subs r5, r0, #0 | |
798: 0a000004 beq 7b0 <register_c_can_dev+0x60> | |
pm_runtime_enable(priv->device); | |
} | |
static inline void c_can_pm_runtime_disable(const struct c_can_priv *priv) | |
{ | |
if (priv->device) | |
79c: e59405e4 ldr r0, [r4, #1508] ; 0x5e4 | |
7a0: e3500000 cmp r0, #0 | |
7a4: 0a000001 beq 7b0 <register_c_can_dev+0x60> | |
7a8: e3a01001 mov r1, #1 | |
7ac: ebfffffe bl 0 <__pm_runtime_disable> | |
c_can_pm_runtime_disable(priv); | |
else | |
devm_can_led_init(dev); | |
return err; | |
} | |
7b0: e1a00005 mov r0, r5 | |
7b4: e89da830 ldm sp, {r4, r5, fp, sp, pc} | |
7b8: 00000030 .word 0x00000030 | |
000007bc <c_can_setup_receive_object.constprop.2>: | |
netif_receive_skb(skb); | |
return 0; | |
} | |
static void c_can_setup_receive_object(struct net_device *dev, int iface, | |
7bc: e1a0c00d mov ip, sp | |
7c0: e92dd8f0 push {r4, r5, r6, r7, fp, ip, lr, pc} | |
7c4: e24cb004 sub fp, ip, #4 | |
7c8: e52de004 push {lr} ; (str lr, [sp, #-4]!) | |
7cc: ebfffffe bl 0 <__gnu_mcount_nc> | |
7d0: e1a04000 mov r4, r0 | |
u32 obj, u32 mask, u32 id, u32 mcont) | |
{ | |
struct c_can_priv *priv = netdev_priv(dev); | |
7d4: e2805d13 add r5, r0, #1216 ; 0x4c0 | |
netif_receive_skb(skb); | |
return 0; | |
} | |
static void c_can_setup_receive_object(struct net_device *dev, int iface, | |
7d8: e1a06001 mov r6, r1 | |
7dc: e1a07002 mov r7, r2 | |
u32 obj, u32 mask, u32 id, u32 mcont) | |
{ | |
struct c_can_priv *priv = netdev_priv(dev); | |
mask |= BIT(29); | |
priv->write_reg32(priv, C_CAN_IFACE(MASK1_REG, iface), mask); | |
7e0: e1a00005 mov r0, r5 | |
7e4: e5943600 ldr r3, [r4, #1536] ; 0x600 | |
7e8: e3a0100a mov r1, #10 | |
7ec: e3a02202 mov r2, #536870912 ; 0x20000000 | |
7f0: e12fff33 blx r3 | |
id |= IF_ARB_MSGVAL; | |
priv->write_reg32(priv, C_CAN_IFACE(ARB1_REG, iface), id); | |
7f4: e1a00005 mov r0, r5 | |
7f8: e5943600 ldr r3, [r4, #1536] ; 0x600 | |
7fc: e3a0100c mov r1, #12 | |
800: e3a02102 mov r2, #-2147483648 ; 0x80000000 | |
804: e12fff33 blx r3 | |
priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), mcont); | |
808: e1a00005 mov r0, r5 | |
80c: e6ff2077 uxth r2, r7 | |
810: e59435f8 ldr r3, [r4, #1528] ; 0x5f8 | |
814: e3a0100e mov r1, #14 | |
818: e12fff33 blx r3 | |
} | |
static inline void c_can_object_put(struct net_device *dev, int iface, | |
u32 obj, u32 cmd) | |
{ | |
c_can_obj_update(dev, iface, cmd | IF_COMM_WR, obj); | |
81c: e1a00004 mov r0, r4 | |
820: e1a03006 mov r3, r6 | |
824: e3a01000 mov r1, #0 | |
828: e3a020f0 mov r2, #240 ; 0xf0 | |
82c: ebfffe50 bl 174 <c_can_obj_update> | |
830: e89da8f0 ldm sp, {r4, r5, r6, r7, fp, sp, pc} | |
00000834 <c_can_start>: | |
/* set bittiming params */ | |
return c_can_set_bittiming(dev); | |
} | |
static int c_can_start(struct net_device *dev) | |
{ | |
834: e1a0c00d mov ip, sp | |
838: e92ddbf0 push {r4, r5, r6, r7, r8, r9, fp, ip, lr, pc} | |
83c: e24cb004 sub fp, ip, #4 | |
840: e52de004 push {lr} ; (str lr, [sp, #-4]!) | |
844: ebfffffe bl 0 <__gnu_mcount_nc> | |
static int c_can_chip_config(struct net_device *dev) | |
{ | |
struct c_can_priv *priv = netdev_priv(dev); | |
/* enable automatic retransmission */ | |
priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_ENABLE_AR); | |
848: e3a01000 mov r1, #0 | |
* - set operating mode | |
* - configure message objects | |
*/ | |
static int c_can_chip_config(struct net_device *dev) | |
{ | |
struct c_can_priv *priv = netdev_priv(dev); | |
84c: e2806d13 add r6, r0, #1216 ; 0x4c0 | |
/* enable automatic retransmission */ | |
priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_ENABLE_AR); | |
850: e59035f8 ldr r3, [r0, #1528] ; 0x5f8 | |
/* set bittiming params */ | |
return c_can_set_bittiming(dev); | |
} | |
static int c_can_start(struct net_device *dev) | |
{ | |
854: e1a05000 mov r5, r0 | |
static int c_can_chip_config(struct net_device *dev) | |
{ | |
struct c_can_priv *priv = netdev_priv(dev); | |
/* enable automatic retransmission */ | |
priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_ENABLE_AR); | |
858: e1a02001 mov r2, r1 | |
85c: e1a00006 mov r0, r6 | |
860: e12fff33 blx r3 | |
if ((priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) && | |
864: e5953528 ldr r3, [r5, #1320] ; 0x528 | |
868: e2032003 and r2, r3, #3 | |
86c: e3520003 cmp r2, #3 | |
870: 0a00007c beq a68 <c_can_start+0x234> | |
(priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK)) { | |
/* loopback + silent mode : useful for hot self-test */ | |
priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_TEST); | |
priv->write_reg(priv, C_CAN_TEST_REG, TEST_LBACK | TEST_SILENT); | |
} else if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) { | |
874: e2131001 ands r1, r3, #1 | |
878: 1a00006f bne a3c <c_can_start+0x208> | |
/* loopback mode : useful for self-test function */ | |
priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_TEST); | |
priv->write_reg(priv, C_CAN_TEST_REG, TEST_LBACK); | |
} else if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) { | |
87c: e3130002 tst r3, #2 | |
880: 1a000046 bne 9a0 <c_can_start+0x16c> | |
/* set bittiming params */ | |
return c_can_set_bittiming(dev); | |
} | |
static int c_can_start(struct net_device *dev) | |
{ | |
884: e3a04001 mov r4, #1 | |
{ | |
int i; | |
/* first invalidate all message objects */ | |
for (i = C_CAN_MSG_OBJ_RX_FIRST; i <= C_CAN_NO_OF_OBJECTS; i++) | |
c_can_inval_msg_object(dev, IF_RX, i); | |
888: e1a02004 mov r2, r4 | |
88c: e1a00005 mov r0, r5 | |
890: e3a01000 mov r1, #0 | |
static void c_can_configure_msg_objects(struct net_device *dev) | |
{ | |
int i; | |
/* first invalidate all message objects */ | |
for (i = C_CAN_MSG_OBJ_RX_FIRST; i <= C_CAN_NO_OF_OBJECTS; i++) | |
894: e2844001 add r4, r4, #1 | |
c_can_inval_msg_object(dev, IF_RX, i); | |
898: ebfffe6d bl 254 <c_can_inval_msg_object> | |
static void c_can_configure_msg_objects(struct net_device *dev) | |
{ | |
int i; | |
/* first invalidate all message objects */ | |
for (i = C_CAN_MSG_OBJ_RX_FIRST; i <= C_CAN_NO_OF_OBJECTS; i++) | |
89c: e3540021 cmp r4, #33 ; 0x21 | |
8a0: 1afffff8 bne 888 <c_can_start+0x54> | |
8a4: e3a04001 mov r4, #1 | |
c_can_inval_msg_object(dev, IF_RX, i); | |
/* setup receive message objects */ | |
for (i = C_CAN_MSG_OBJ_RX_FIRST; i < C_CAN_MSG_OBJ_RX_LAST; i++) | |
c_can_setup_receive_object(dev, IF_RX, i, 0, 0, IF_MCONT_RCV); | |
8a8: e1a01004 mov r1, r4 | |
8ac: e1a00005 mov r0, r5 | |
8b0: e3a02b05 mov r2, #5120 ; 0x1400 | |
/* first invalidate all message objects */ | |
for (i = C_CAN_MSG_OBJ_RX_FIRST; i <= C_CAN_NO_OF_OBJECTS; i++) | |
c_can_inval_msg_object(dev, IF_RX, i); | |
/* setup receive message objects */ | |
for (i = C_CAN_MSG_OBJ_RX_FIRST; i < C_CAN_MSG_OBJ_RX_LAST; i++) | |
8b4: e2844001 add r4, r4, #1 | |
c_can_setup_receive_object(dev, IF_RX, i, 0, 0, IF_MCONT_RCV); | |
8b8: ebffffbf bl 7bc <c_can_setup_receive_object.constprop.2> | |
/* first invalidate all message objects */ | |
for (i = C_CAN_MSG_OBJ_RX_FIRST; i <= C_CAN_NO_OF_OBJECTS; i++) | |
c_can_inval_msg_object(dev, IF_RX, i); | |
/* setup receive message objects */ | |
for (i = C_CAN_MSG_OBJ_RX_FIRST; i < C_CAN_MSG_OBJ_RX_LAST; i++) | |
8bc: e3540010 cmp r4, #16 | |
8c0: 1afffff8 bne 8a8 <c_can_start+0x74> | |
c_can_setup_receive_object(dev, IF_RX, i, 0, 0, IF_MCONT_RCV); | |
c_can_setup_receive_object(dev, IF_RX, C_CAN_MSG_OBJ_RX_LAST, 0, 0, | |
8c4: e1a01004 mov r1, r4 | |
8c8: e1a00005 mov r0, r5 | |
8cc: e3a02d52 mov r2, #5248 ; 0x1480 | |
/* set a `lec` value so that we can check for updates later */ | |
priv->write_reg(priv, C_CAN_STS_REG, LEC_UNUSED); | |
/* Clear all internal status */ | |
atomic_set(&priv->tx_active, 0); | |
8d0: e3a04000 mov r4, #0 | |
/* setup receive message objects */ | |
for (i = C_CAN_MSG_OBJ_RX_FIRST; i < C_CAN_MSG_OBJ_RX_LAST; i++) | |
c_can_setup_receive_object(dev, IF_RX, i, 0, 0, IF_MCONT_RCV); | |
c_can_setup_receive_object(dev, IF_RX, C_CAN_MSG_OBJ_RX_LAST, 0, 0, | |
8d4: ebffffb8 bl 7bc <c_can_setup_receive_object.constprop.2> | |
/* configure message objects */ | |
c_can_configure_msg_objects(dev); | |
/* set a `lec` value so that we can check for updates later */ | |
priv->write_reg(priv, C_CAN_STS_REG, LEC_UNUSED); | |
8d8: e59535f8 ldr r3, [r5, #1528] ; 0x5f8 | |
8dc: e1a00006 mov r0, r6 | |
8e0: e3a01002 mov r1, #2 | |
8e4: e3a02007 mov r2, #7 | |
8e8: e12fff33 blx r3 | |
/* c_can provides a 6-bit brp and 4-bit brpe fields */ | |
ten_bit_brp = bt->brp - 1; | |
brp = ten_bit_brp & BTR_BRP_MASK; | |
brpe = ten_bit_brp >> 6; | |
sjw = bt->sjw - 1; | |
8ec: e59574f0 ldr r7, [r5, #1264] ; 0x4f0 | |
tseg2 = bt->phase_seg2 - 1; | |
reg_btr = brp | (sjw << BTR_SJW_SHIFT) | (tseg1 << BTR_TSEG1_SHIFT) | | |
(tseg2 << BTR_TSEG2_SHIFT); | |
reg_brpe = brpe & BRP_EXT_BRPE_MASK; | |
netdev_info(dev, | |
8f0: e3001000 movw r1, #0 | |
struct c_can_priv *priv = netdev_priv(dev); | |
const struct can_bittiming *bt = &priv->can.bittiming; | |
int res; | |
/* c_can provides a 6-bit brp and 4-bit brpe fields */ | |
ten_bit_brp = bt->brp - 1; | |
8f4: e59534f4 ldr r3, [r5, #1268] ; 0x4f4 | |
tseg2 = bt->phase_seg2 - 1; | |
reg_btr = brp | (sjw << BTR_SJW_SHIFT) | (tseg1 << BTR_TSEG1_SHIFT) | | |
(tseg2 << BTR_TSEG2_SHIFT); | |
reg_brpe = brpe & BRP_EXT_BRPE_MASK; | |
netdev_info(dev, | |
8f8: e3401000 movt r1, #0 | |
brp = ten_bit_brp & BTR_BRP_MASK; | |
brpe = ten_bit_brp >> 6; | |
sjw = bt->sjw - 1; | |
tseg1 = bt->prop_seg + bt->phase_seg1 - 1; | |
tseg2 = bt->phase_seg2 - 1; | |
8fc: e59524ec ldr r2, [r5, #1260] ; 0x4ec | |
reg_btr = brp | (sjw << BTR_SJW_SHIFT) | (tseg1 << BTR_TSEG1_SHIFT) | | |
(tseg2 << BTR_TSEG2_SHIFT); | |
reg_brpe = brpe & BRP_EXT_BRPE_MASK; | |
netdev_info(dev, | |
900: e1a00005 mov r0, r5 | |
ten_bit_brp = bt->brp - 1; | |
brp = ten_bit_brp & BTR_BRP_MASK; | |
brpe = ten_bit_brp >> 6; | |
sjw = bt->sjw - 1; | |
tseg1 = bt->prop_seg + bt->phase_seg1 - 1; | |
904: e595e4e8 ldr lr, [r5, #1256] ; 0x4e8 | |
/* c_can provides a 6-bit brp and 4-bit brpe fields */ | |
ten_bit_brp = bt->brp - 1; | |
brp = ten_bit_brp & BTR_BRP_MASK; | |
brpe = ten_bit_brp >> 6; | |
sjw = bt->sjw - 1; | |
908: e2477001 sub r7, r7, #1 | |
tseg1 = bt->prop_seg + bt->phase_seg1 - 1; | |
90c: e59584e4 ldr r8, [r5, #1252] ; 0x4e4 | |
struct c_can_priv *priv = netdev_priv(dev); | |
const struct can_bittiming *bt = &priv->can.bittiming; | |
int res; | |
/* c_can provides a 6-bit brp and 4-bit brpe fields */ | |
ten_bit_brp = bt->brp - 1; | |
910: e2433001 sub r3, r3, #1 | |
brpe = ten_bit_brp >> 6; | |
sjw = bt->sjw - 1; | |
tseg1 = bt->prop_seg + bt->phase_seg1 - 1; | |
tseg2 = bt->phase_seg2 - 1; | |
reg_btr = brp | (sjw << BTR_SJW_SHIFT) | (tseg1 << BTR_TSEG1_SHIFT) | | |
914: e6ef7077 uxtb r7, r7 | |
918: e203c03f and ip, r3, #63 ; 0x3f | |
brp = ten_bit_brp & BTR_BRP_MASK; | |
brpe = ten_bit_brp >> 6; | |
sjw = bt->sjw - 1; | |
tseg1 = bt->prop_seg + bt->phase_seg1 - 1; | |
tseg2 = bt->phase_seg2 - 1; | |
91c: e2422001 sub r2, r2, #1 | |
/* set a `lec` value so that we can check for updates later */ | |
priv->write_reg(priv, C_CAN_STS_REG, LEC_UNUSED); | |
/* Clear all internal status */ | |
atomic_set(&priv->tx_active, 0); | |
920: e58545e8 str r4, [r5, #1512] ; 0x5e8 | |
brpe = ten_bit_brp >> 6; | |
sjw = bt->sjw - 1; | |
tseg1 = bt->prop_seg + bt->phase_seg1 - 1; | |
tseg2 = bt->phase_seg2 - 1; | |
reg_btr = brp | (sjw << BTR_SJW_SHIFT) | (tseg1 << BTR_TSEG1_SHIFT) | | |
924: e18cc307 orr ip, ip, r7, lsl #6 | |
ten_bit_brp = bt->brp - 1; | |
brp = ten_bit_brp & BTR_BRP_MASK; | |
brpe = ten_bit_brp >> 6; | |
sjw = bt->sjw - 1; | |
tseg1 = bt->prop_seg + bt->phase_seg1 - 1; | |
928: e088800e add r8, r8, lr | |
tseg2 = bt->phase_seg2 - 1; | |
reg_btr = brp | (sjw << BTR_SJW_SHIFT) | (tseg1 << BTR_TSEG1_SHIFT) | | |
(tseg2 << BTR_TSEG2_SHIFT); | |
92c: e6ef2072 uxtb r2, r2 | |
ten_bit_brp = bt->brp - 1; | |
brp = ten_bit_brp & BTR_BRP_MASK; | |
brpe = ten_bit_brp >> 6; | |
sjw = bt->sjw - 1; | |
tseg1 = bt->prop_seg + bt->phase_seg1 - 1; | |
930: e2488001 sub r8, r8, #1 | |
tseg2 = bt->phase_seg2 - 1; | |
reg_btr = brp | (sjw << BTR_SJW_SHIFT) | (tseg1 << BTR_TSEG1_SHIFT) | | |
934: e6ef8078 uxtb r8, r8 | |
(tseg2 << BTR_TSEG2_SHIFT); | |
reg_brpe = brpe & BRP_EXT_BRPE_MASK; | |
938: e7e37353 ubfx r7, r3, #6, #4 | |
brpe = ten_bit_brp >> 6; | |
sjw = bt->sjw - 1; | |
tseg1 = bt->prop_seg + bt->phase_seg1 - 1; | |
tseg2 = bt->phase_seg2 - 1; | |
reg_btr = brp | (sjw << BTR_SJW_SHIFT) | (tseg1 << BTR_TSEG1_SHIFT) | | |
93c: e18c2602 orr r2, ip, r2, lsl #12 | |
/* set a `lec` value so that we can check for updates later */ | |
priv->write_reg(priv, C_CAN_STS_REG, LEC_UNUSED); | |
/* Clear all internal status */ | |
atomic_set(&priv->tx_active, 0); | |
priv->rxmasked = 0; | |
940: e5854628 str r4, [r5, #1576] ; 0x628 | |
priv->tx_dir = 0; | |
944: e58545ec str r4, [r5, #1516] ; 0x5ec | |
tseg2 = bt->phase_seg2 - 1; | |
reg_btr = brp | (sjw << BTR_SJW_SHIFT) | (tseg1 << BTR_TSEG1_SHIFT) | | |
(tseg2 << BTR_TSEG2_SHIFT); | |
reg_brpe = brpe & BRP_EXT_BRPE_MASK; | |
netdev_info(dev, | |
948: e1a03007 mov r3, r7 | |
brpe = ten_bit_brp >> 6; | |
sjw = bt->sjw - 1; | |
tseg1 = bt->prop_seg + bt->phase_seg1 - 1; | |
tseg2 = bt->phase_seg2 - 1; | |
reg_btr = brp | (sjw << BTR_SJW_SHIFT) | (tseg1 << BTR_TSEG1_SHIFT) | | |
94c: e1828408 orr r8, r2, r8, lsl #8 | |
(tseg2 << BTR_TSEG2_SHIFT); | |
reg_brpe = brpe & BRP_EXT_BRPE_MASK; | |
netdev_info(dev, | |
950: e1a02008 mov r2, r8 | |
954: ebfffffe bl 0 <netdev_info> | |
"setting BTR=%04x BRPE=%04x\n", reg_btr, reg_brpe); | |
ctrl_save = priv->read_reg(priv, C_CAN_CTRL_REG); | |
958: e1a01004 mov r1, r4 | |
95c: e59535f4 ldr r3, [r5, #1524] ; 0x5f4 | |
960: e1a00006 mov r0, r6 | |
964: e12fff33 blx r3 | |
ctrl_save &= ~CONTROL_INIT; | |
priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_CCE | CONTROL_INIT); | |
968: e1a01004 mov r1, r4 | |
96c: e59535f8 ldr r3, [r5, #1528] ; 0x5f8 | |
970: e3a02041 mov r2, #65 ; 0x41 | |
reg_brpe = brpe & BRP_EXT_BRPE_MASK; | |
netdev_info(dev, | |
"setting BTR=%04x BRPE=%04x\n", reg_btr, reg_brpe); | |
ctrl_save = priv->read_reg(priv, C_CAN_CTRL_REG); | |
974: e1a09000 mov r9, r0 | |
ctrl_save &= ~CONTROL_INIT; | |
priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_CCE | CONTROL_INIT); | |
978: e1a00006 mov r0, r6 | |
97c: e12fff33 blx r3 | |
res = c_can_wait_for_ctrl_init(dev, priv, CONTROL_INIT); | |
980: e1a00005 mov r0, r5 | |
984: e1a01006 mov r1, r6 | |
988: e3a02001 mov r2, #1 | |
98c: ebfffe4a bl 2bc <c_can_wait_for_ctrl_init> | |
if (res) | |
990: e2504000 subs r4, r0, #0 | |
994: 0a00000b beq 9c8 <c_can_start+0x194> | |
998: e1a00004 mov r0, r4 | |
pinctrl_put(p); | |
else | |
pinctrl_pm_select_default_state(priv->device); | |
return 0; | |
} | |
99c: e89dabf0 ldm sp, {r4, r5, r6, r7, r8, r9, fp, sp, pc} | |
/* loopback mode : useful for self-test function */ | |
priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_TEST); | |
priv->write_reg(priv, C_CAN_TEST_REG, TEST_LBACK); | |
} else if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) { | |
/* silent mode : bus-monitoring mode */ | |
priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_TEST); | |
9a0: e59535f8 ldr r3, [r5, #1528] ; 0x5f8 | |
9a4: e1a00006 mov r0, r6 | |
9a8: e3a02080 mov r2, #128 ; 0x80 | |
9ac: e12fff33 blx r3 | |
priv->write_reg(priv, C_CAN_TEST_REG, TEST_SILENT); | |
9b0: e59535f8 ldr r3, [r5, #1528] ; 0x5f8 | |
9b4: e1a00006 mov r0, r6 | |
9b8: e3a01006 mov r1, #6 | |
9bc: e3a02008 mov r2, #8 | |
9c0: e12fff33 blx r3 | |
9c4: eaffffae b 884 <c_can_start+0x50> | |
priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_CCE | CONTROL_INIT); | |
res = c_can_wait_for_ctrl_init(dev, priv, CONTROL_INIT); | |
if (res) | |
return res; | |
priv->write_reg(priv, C_CAN_BTR_REG, reg_btr); | |
9c8: e6ff2078 uxth r2, r8 | |
9cc: e59535f8 ldr r3, [r5, #1528] ; 0x5f8 | |
9d0: e1a00006 mov r0, r6 | |
9d4: e3a01004 mov r1, #4 | |
9d8: e12fff33 blx r3 | |
priv->write_reg(priv, C_CAN_BRPEXT_REG, reg_brpe); | |
9dc: e1a02007 mov r2, r7 | |
9e0: e59535f8 ldr r3, [r5, #1528] ; 0x5f8 | |
9e4: e1a00006 mov r0, r6 | |
9e8: e3a01007 mov r1, #7 | |
9ec: e12fff33 blx r3 | |
priv->write_reg(priv, C_CAN_CTRL_REG, ctrl_save); | |
9f0: e30f2ffe movw r2, #65534 ; 0xfffe | |
9f4: e59535f8 ldr r3, [r5, #1528] ; 0x5f8 | |
9f8: e0022009 and r2, r2, r9 | |
9fc: e1a00006 mov r0, r6 | |
a00: e1a01004 mov r1, r4 | |
a04: e12fff33 blx r3 | |
return c_can_wait_for_ctrl_init(dev, priv, 0); | |
a08: e1a00005 mov r0, r5 | |
a0c: e1a01006 mov r1, r6 | |
a10: e1a02004 mov r2, r4 | |
a14: ebfffe28 bl 2bc <c_can_wait_for_ctrl_init> | |
int err; | |
struct pinctrl *p; | |
/* basic c_can configuration */ | |
err = c_can_chip_config(dev); | |
if (err) | |
a18: e3500000 cmp r0, #0 | |
a1c: 189dabf0 ldmne sp, {r4, r5, r6, r7, r8, r9, fp, sp, pc} | |
return err; | |
/* Setup the command for new messages */ | |
priv->comm_rcv_high = priv->type != BOSCH_D_CAN ? | |
a20: e5953610 ldr r3, [r5, #1552] ; 0x610 | |
IF_COMM_RCV_LOW : IF_COMM_RCV_HIGH; | |
priv->can.state = CAN_STATE_ERROR_ACTIVE; | |
a24: e5850524 str r0, [r5, #1316] ; 0x524 | |
err = c_can_chip_config(dev); | |
if (err) | |
return err; | |
/* Setup the command for new messages */ | |
priv->comm_rcv_high = priv->type != BOSCH_D_CAN ? | |
a28: e3530002 cmp r3, #2 | |
a2c: 03a0307f moveq r3, #127 ; 0x7f | |
a30: 13a0307b movne r3, #123 ; 0x7b | |
a34: e5853624 str r3, [r5, #1572] ; 0x624 | |
a38: e89dabf0 ldm sp, {r4, r5, r6, r7, r8, r9, fp, sp, pc} | |
/* loopback + silent mode : useful for hot self-test */ | |
priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_TEST); | |
priv->write_reg(priv, C_CAN_TEST_REG, TEST_LBACK | TEST_SILENT); | |
} else if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) { | |
/* loopback mode : useful for self-test function */ | |
priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_TEST); | |
a3c: e59535f8 ldr r3, [r5, #1528] ; 0x5f8 | |
a40: e1a00006 mov r0, r6 | |
a44: e3a01000 mov r1, #0 | |
a48: e3a02080 mov r2, #128 ; 0x80 | |
a4c: e12fff33 blx r3 | |
priv->write_reg(priv, C_CAN_TEST_REG, TEST_LBACK); | |
a50: e59535f8 ldr r3, [r5, #1528] ; 0x5f8 | |
a54: e1a00006 mov r0, r6 | |
a58: e3a01006 mov r1, #6 | |
a5c: e3a02010 mov r2, #16 | |
a60: e12fff33 blx r3 | |
a64: eaffff86 b 884 <c_can_start+0x50> | |
priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_ENABLE_AR); | |
if ((priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) && | |
(priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK)) { | |
/* loopback + silent mode : useful for hot self-test */ | |
priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_TEST); | |
a68: e59535f8 ldr r3, [r5, #1528] ; 0x5f8 | |
a6c: e1a00006 mov r0, r6 | |
a70: e3a01000 mov r1, #0 | |
a74: e3a02080 mov r2, #128 ; 0x80 | |
a78: e12fff33 blx r3 | |
priv->write_reg(priv, C_CAN_TEST_REG, TEST_LBACK | TEST_SILENT); | |
a7c: e59535f8 ldr r3, [r5, #1528] ; 0x5f8 | |
a80: e1a00006 mov r0, r6 | |
a84: e3a01006 mov r1, #6 | |
a88: e3a02018 mov r2, #24 | |
a8c: e12fff33 blx r3 | |
a90: eaffff7b b 884 <c_can_start+0x50> | |
00000a94 <c_can_set_mode>: | |
pinctrl_pm_select_sleep_state(dev->dev.parent); | |
priv->can.state = CAN_STATE_STOPPED; | |
} | |
static int c_can_set_mode(struct net_device *dev, enum can_mode mode) | |
{ | |
a94: e1a0c00d mov ip, sp | |
a98: e92dd878 push {r3, r4, r5, r6, fp, ip, lr, pc} | |
a9c: e24cb004 sub fp, ip, #4 | |
aa0: e52de004 push {lr} ; (str lr, [sp, #-4]!) | |
aa4: ebfffffe bl 0 <__gnu_mcount_nc> | |
struct c_can_priv *priv = netdev_priv(dev); | |
int err; | |
switch (mode) { | |
aa8: e3510001 cmp r1, #1 | |
pinctrl_pm_select_sleep_state(dev->dev.parent); | |
priv->can.state = CAN_STATE_STOPPED; | |
} | |
static int c_can_set_mode(struct net_device *dev, enum can_mode mode) | |
{ | |
aac: e1a04001 mov r4, r1 | |
ab0: e1a06000 mov r6, r0 | |
struct c_can_priv *priv = netdev_priv(dev); | |
int err; | |
switch (mode) { | |
ab4: 1a00000b bne ae8 <c_can_set_mode+0x54> | |
case CAN_MODE_START: | |
err = c_can_start(dev); | |
ab8: ebffff5d bl 834 <c_can_start> | |
if (err) | |
abc: e2505000 subs r5, r0, #0 | |
ac0: 0a000001 beq acc <c_can_set_mode+0x38> | |
ac4: e1a00005 mov r0, r5 | |
default: | |
return -EOPNOTSUPP; | |
} | |
return 0; | |
} | |
ac8: e89da878 ldm sp, {r3, r4, r5, r6, fp, sp, pc} | |
* Allow upper layers to call the device hard_start_xmit routine. | |
* Used for flow control when transmit resources are available. | |
*/ | |
static inline void netif_wake_queue(struct net_device *dev) | |
{ | |
netif_tx_wake_queue(netdev_get_tx_queue(dev, 0)); | |
acc: e5960240 ldr r0, [r6, #576] ; 0x240 | |
ad0: ebfffffe bl 0 <netif_tx_wake_queue> | |
case CAN_MODE_START: | |
err = c_can_start(dev); | |
if (err) | |
return err; | |
netif_wake_queue(dev); | |
c_can_irq_control(priv, true); | |
ad4: e2860d13 add r0, r6, #1216 ; 0x4c0 | |
ad8: e1a01004 mov r1, r4 | |
adc: ebfffd47 bl 0 <c_can_irq_control> | |
break; | |
default: | |
return -EOPNOTSUPP; | |
} | |
return 0; | |
ae0: e1a00005 mov r0, r5 | |
ae4: e89da878 ldm sp, {r3, r4, r5, r6, fp, sp, pc} | |
return err; | |
netif_wake_queue(dev); | |
c_can_irq_control(priv, true); | |
break; | |
default: | |
return -EOPNOTSUPP; | |
ae8: e3e0005e mvn r0, #94 ; 0x5e | |
aec: e89da878 ldm sp, {r3, r4, r5, r6, fp, sp, pc} | |
00000af0 <c_can_power_up>: | |
return 0; | |
} | |
EXPORT_SYMBOL_GPL(c_can_power_down); | |
int c_can_power_up(struct net_device *dev) | |
{ | |
af0: e1a0c00d mov ip, sp | |
af4: e92dd8f0 push {r4, r5, r6, r7, fp, ip, lr, pc} | |
af8: e24cb004 sub fp, ip, #4 | |
afc: e52de004 push {lr} ; (str lr, [sp, #-4]!) | |
b00: ebfffffe bl 0 <__gnu_mcount_nc> | |
b04: e1a04000 mov r4, r0 | |
u32 val; | |
unsigned long time_out; | |
struct c_can_priv *priv = netdev_priv(dev); | |
int ret; | |
if (!(dev->flags & IFF_UP)) | |
b08: e5900130 ldr r0, [r0, #304] ; 0x130 | |
b0c: e2100001 ands r0, r0, #1 | |
b10: 089da8f0 ldmeq sp, {r4, r5, r6, r7, fp, sp, pc} | |
return 0; | |
WARN_ON(priv->type != BOSCH_D_CAN); | |
b14: e5943610 ldr r3, [r4, #1552] ; 0x610 | |
b18: e3530002 cmp r3, #2 | |
b1c: 1a00003f bne c20 <c_can_power_up+0x130> | |
pm_runtime_disable(priv->device); | |
} | |
static inline void c_can_pm_runtime_get_sync(const struct c_can_priv *priv) | |
{ | |
if (priv->device) | |
b20: e59405e4 ldr r0, [r4, #1508] ; 0x5e4 | |
b24: e3500000 cmp r0, #0 | |
b28: 0a000001 beq b34 <c_can_power_up+0x44> | |
return __pm_runtime_resume(dev, RPM_GET_PUT | RPM_ASYNC); | |
} | |
static inline int pm_runtime_get_sync(struct device *dev) | |
{ | |
return __pm_runtime_resume(dev, RPM_GET_PUT); | |
b2c: e3a01004 mov r1, #4 | |
b30: ebfffffe bl 0 <__pm_runtime_resume> | |
pm_runtime_put_sync(priv->device); | |
} | |
static inline void c_can_reset_ram(const struct c_can_priv *priv, bool enable) | |
{ | |
if (priv->raminit) | |
b34: e5943620 ldr r3, [r4, #1568] ; 0x620 | |
int c_can_power_up(struct net_device *dev) | |
{ | |
u32 val; | |
unsigned long time_out; | |
struct c_can_priv *priv = netdev_priv(dev); | |
b38: e2845d13 add r5, r4, #1216 ; 0x4c0 | |
pm_runtime_put_sync(priv->device); | |
} | |
static inline void c_can_reset_ram(const struct c_can_priv *priv, bool enable) | |
{ | |
if (priv->raminit) | |
b3c: e3530000 cmp r3, #0 | |
b40: 0a000002 beq b50 <c_can_power_up+0x60> | |
priv->raminit(priv, enable); | |
b44: e1a00005 mov r0, r5 | |
b48: e3a01001 mov r1, #1 | |
b4c: e12fff33 blx r3 | |
c_can_pm_runtime_get_sync(priv); | |
c_can_reset_ram(priv, true); | |
/* Clear PDR and INIT bits */ | |
val = priv->read_reg(priv, C_CAN_CTRL_EX_REG); | |
b50: e59435f4 ldr r3, [r4, #1524] ; 0x5f4 | |
b54: e3a01001 mov r1, #1 | |
b58: e1a00005 mov r0, r5 | |
val = priv->read_reg(priv, C_CAN_CTRL_REG); | |
val &= ~CONTROL_INIT; | |
priv->write_reg(priv, C_CAN_CTRL_REG, val); | |
/* Wait for the PDA bit to get clear */ | |
time_out = jiffies + msecs_to_jiffies(INIT_WAIT_MS); | |
b5c: e3006000 movw r6, #0 | |
c_can_pm_runtime_get_sync(priv); | |
c_can_reset_ram(priv, true); | |
/* Clear PDR and INIT bits */ | |
val = priv->read_reg(priv, C_CAN_CTRL_EX_REG); | |
b60: e12fff33 blx r3 | |
val &= ~CONTROL_EX_PDR; | |
priv->write_reg(priv, C_CAN_CTRL_EX_REG, val); | |
b64: e30f2eff movw r2, #65279 ; 0xfeff | |
b68: e59435f8 ldr r3, [r4, #1528] ; 0x5f8 | |
b6c: e0022000 and r2, r2, r0 | |
b70: e3a01001 mov r1, #1 | |
b74: e1a00005 mov r0, r5 | |
val = priv->read_reg(priv, C_CAN_CTRL_REG); | |
val &= ~CONTROL_INIT; | |
priv->write_reg(priv, C_CAN_CTRL_REG, val); | |
/* Wait for the PDA bit to get clear */ | |
time_out = jiffies + msecs_to_jiffies(INIT_WAIT_MS); | |
b78: e3406000 movt r6, #0 | |
c_can_reset_ram(priv, true); | |
/* Clear PDR and INIT bits */ | |
val = priv->read_reg(priv, C_CAN_CTRL_EX_REG); | |
val &= ~CONTROL_EX_PDR; | |
priv->write_reg(priv, C_CAN_CTRL_EX_REG, val); | |
b7c: e12fff33 blx r3 | |
val = priv->read_reg(priv, C_CAN_CTRL_REG); | |
b80: e59435f4 ldr r3, [r4, #1524] ; 0x5f4 | |
b84: e3a01000 mov r1, #0 | |
b88: e1a00005 mov r0, r5 | |
b8c: e12fff33 blx r3 | |
val &= ~CONTROL_INIT; | |
priv->write_reg(priv, C_CAN_CTRL_REG, val); | |
b90: e30f2ffe movw r2, #65534 ; 0xfffe | |
b94: e59435f8 ldr r3, [r4, #1528] ; 0x5f8 | |
b98: e0022000 and r2, r2, r0 | |
b9c: e3a01000 mov r1, #0 | |
ba0: e1a00005 mov r0, r5 | |
ba4: e12fff33 blx r3 | |
/* Wait for the PDA bit to get clear */ | |
time_out = jiffies + msecs_to_jiffies(INIT_WAIT_MS); | |
ba8: e5967000 ldr r7, [r6] | |
bac: e2877064 add r7, r7, #100 ; 0x64 | |
while ((priv->read_reg(priv, C_CAN_STS_REG) & STATUS_PDA) && | |
bb0: ea000003 b bc4 <c_can_power_up+0xd4> | |
time_after(time_out, jiffies)) | |
bb4: e5963000 ldr r3, [r6] | |
bb8: e0673003 rsb r3, r7, r3 | |
bbc: e3530000 cmp r3, #0 | |
bc0: aa000005 bge bdc <c_can_power_up+0xec> | |
val &= ~CONTROL_INIT; | |
priv->write_reg(priv, C_CAN_CTRL_REG, val); | |
/* Wait for the PDA bit to get clear */ | |
time_out = jiffies + msecs_to_jiffies(INIT_WAIT_MS); | |
while ((priv->read_reg(priv, C_CAN_STS_REG) & STATUS_PDA) && | |
bc4: e59435f4 ldr r3, [r4, #1524] ; 0x5f4 | |
bc8: e1a00005 mov r0, r5 | |
bcc: e3a01002 mov r1, #2 | |
bd0: e12fff33 blx r3 | |
bd4: e3100b01 tst r0, #1024 ; 0x400 | |
bd8: 1afffff5 bne bb4 <c_can_power_up+0xc4> | |
time_after(time_out, jiffies)) | |
cpu_relax(); | |
if (time_after(jiffies, time_out)) | |
bdc: e5963000 ldr r3, [r6] | |
be0: e0637007 rsb r7, r3, r7 | |
be4: e3570000 cmp r7, #0 | |
be8: ba00000a blt c18 <c_can_power_up+0x128> | |
return -ETIMEDOUT; | |
ret = c_can_start(dev); | |
bec: e1a00004 mov r0, r4 | |
bf0: ebffff0f bl 834 <c_can_start> | |
if (!ret) | |
bf4: e2504000 subs r4, r0, #0 | |
bf8: 0a000001 beq c04 <c_can_power_up+0x114> | |
bfc: e1a00004 mov r0, r4 | |
c_can_irq_control(priv, true); | |
return ret; | |
} | |
c00: e89da8f0 ldm sp, {r4, r5, r6, r7, fp, sp, pc} | |
if (time_after(jiffies, time_out)) | |
return -ETIMEDOUT; | |
ret = c_can_start(dev); | |
if (!ret) | |
c_can_irq_control(priv, true); | |
c04: e1a00005 mov r0, r5 | |
c08: e3a01001 mov r1, #1 | |
c0c: ebfffcfb bl 0 <c_can_irq_control> | |
c10: e1a00004 mov r0, r4 | |
c14: e89da8f0 ldm sp, {r4, r5, r6, r7, fp, sp, pc} | |
while ((priv->read_reg(priv, C_CAN_STS_REG) & STATUS_PDA) && | |
time_after(time_out, jiffies)) | |
cpu_relax(); | |
if (time_after(jiffies, time_out)) | |
return -ETIMEDOUT; | |
c18: e3e0006d mvn r0, #109 ; 0x6d | |
c1c: e89da8f0 ldm sp, {r4, r5, r6, r7, fp, sp, pc} | |
int ret; | |
if (!(dev->flags & IFF_UP)) | |
return 0; | |
WARN_ON(priv->type != BOSCH_D_CAN); | |
c20: e3000000 movw r0, #0 | |
c24: e30014ba movw r1, #1210 ; 0x4ba | |
c28: e3400000 movt r0, #0 | |
c2c: ebfffffe bl 0 <warn_slowpath_null> | |
c30: eaffffba b b20 <c_can_power_up+0x30> | |
00000c34 <c_can_open>: | |
return IRQ_HANDLED; | |
} | |
static int c_can_open(struct net_device *dev) | |
{ | |
c34: e1a0c00d mov ip, sp | |
c38: e92dd870 push {r4, r5, r6, fp, ip, lr, pc} | |
c3c: e24cb004 sub fp, ip, #4 | |
c40: e24dd00c sub sp, sp, #12 | |
c44: e52de004 push {lr} ; (str lr, [sp, #-4]!) | |
c48: ebfffffe bl 0 <__gnu_mcount_nc> | |
c4c: e1a04000 mov r4, r0 | |
pm_runtime_disable(priv->device); | |
} | |
static inline void c_can_pm_runtime_get_sync(const struct c_can_priv *priv) | |
{ | |
if (priv->device) | |
c50: e59005e4 ldr r0, [r0, #1508] ; 0x5e4 | |
} | |
static int c_can_open(struct net_device *dev) | |
{ | |
int err; | |
struct c_can_priv *priv = netdev_priv(dev); | |
c54: e2846d13 add r6, r4, #1216 ; 0x4c0 | |
pm_runtime_disable(priv->device); | |
} | |
static inline void c_can_pm_runtime_get_sync(const struct c_can_priv *priv) | |
{ | |
if (priv->device) | |
c58: e3500000 cmp r0, #0 | |
c5c: 0a000001 beq c68 <c_can_open+0x34> | |
c60: e3a01004 mov r1, #4 | |
c64: ebfffffe bl 0 <__pm_runtime_resume> | |
pm_runtime_put_sync(priv->device); | |
} | |
static inline void c_can_reset_ram(const struct c_can_priv *priv, bool enable) | |
{ | |
if (priv->raminit) | |
c68: e5943620 ldr r3, [r4, #1568] ; 0x620 | |
c6c: e3530000 cmp r3, #0 | |
c70: 0a000002 beq c80 <c_can_open+0x4c> | |
priv->raminit(priv, enable); | |
c74: e1a00006 mov r0, r6 | |
c78: e3a01001 mov r1, #1 | |
c7c: e12fff33 blx r3 | |
c_can_pm_runtime_get_sync(priv); | |
c_can_reset_ram(priv, true); | |
/* open the can device */ | |
err = open_candev(dev); | |
c80: e1a00004 mov r0, r4 | |
c84: ebfffffe bl 0 <open_candev> | |
if (err) { | |
c88: e2505000 subs r5, r0, #0 | |
c8c: 0a000012 beq cdc <c_can_open+0xa8> | |
netdev_err(dev, "failed to open can device\n"); | |
c90: e3001000 movw r1, #0 | |
c94: e1a00004 mov r0, r4 | |
c98: e3401000 movt r1, #0 | |
c9c: ebfffffe bl 0 <netdev_err> | |
pm_runtime_put_sync(priv->device); | |
} | |
static inline void c_can_reset_ram(const struct c_can_priv *priv, bool enable) | |
{ | |
if (priv->raminit) | |
ca0: e5943620 ldr r3, [r4, #1568] ; 0x620 | |
ca4: e3530000 cmp r3, #0 | |
ca8: 0a000002 beq cb8 <c_can_open+0x84> | |
priv->raminit(priv, enable); | |
cac: e1a00006 mov r0, r6 | |
cb0: e3a01000 mov r1, #0 | |
cb4: e12fff33 blx r3 | |
pm_runtime_get_sync(priv->device); | |
} | |
static inline void c_can_pm_runtime_put_sync(const struct c_can_priv *priv) | |
{ | |
if (priv->device) | |
cb8: e59405e4 ldr r0, [r4, #1508] ; 0x5e4 | |
cbc: e3500000 cmp r0, #0 | |
exit_irq_fail: | |
close_candev(dev); | |
exit_open_fail: | |
c_can_reset_ram(priv, false); | |
c_can_pm_runtime_put_sync(priv); | |
return err; | |
cc0: 01a00005 moveq r0, r5 | |
pm_runtime_get_sync(priv->device); | |
} | |
static inline void c_can_pm_runtime_put_sync(const struct c_can_priv *priv) | |
{ | |
if (priv->device) | |
cc4: 0a000002 beq cd4 <c_can_open+0xa0> | |
RPM_GET_PUT | RPM_ASYNC | RPM_AUTO); | |
} | |
static inline int pm_runtime_put_sync(struct device *dev) | |
{ | |
return __pm_runtime_idle(dev, RPM_GET_PUT); | |
cc8: e3a01004 mov r1, #4 | |
ccc: ebfffffe bl 0 <__pm_runtime_idle> | |
exit_irq_fail: | |
close_candev(dev); | |
exit_open_fail: | |
c_can_reset_ram(priv, false); | |
c_can_pm_runtime_put_sync(priv); | |
return err; | |
cd0: e1a00005 mov r0, r5 | |
} | |
cd4: e24bd018 sub sp, fp, #24 | |
cd8: e89da870 ldm sp, {r4, r5, r6, fp, sp, pc} | |
static inline int __must_check | |
request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, | |
const char *name, void *dev) | |
{ | |
return request_threaded_irq(irq, handler, NULL, flags, name, dev); | |
cdc: e3001000 movw r1, #0 | |
ce0: e5940028 ldr r0, [r4, #40] ; 0x28 | |
ce4: e1a02005 mov r2, r5 | |
ce8: e58d4000 str r4, [sp] | |
cec: e58d4004 str r4, [sp, #4] | |
cf0: e3401000 movt r1, #0 | |
cf4: e3a03080 mov r3, #128 ; 0x80 | |
cf8: ebfffffe bl 0 <request_threaded_irq> | |
} | |
/* register interrupt handler */ | |
err = request_irq(dev->irq, &c_can_isr, IRQF_SHARED, dev->name, | |
dev); | |
if (err < 0) { | |
cfc: e2505000 subs r5, r0, #0 | |
d00: ba000019 blt d6c <c_can_open+0x138> | |
netdev_err(dev, "failed to request interrupt\n"); | |
goto exit_irq_fail; | |
} | |
/* start the c_can controller */ | |
err = c_can_start(dev); | |
d04: e1a00004 mov r0, r4 | |
d08: ebfffec9 bl 834 <c_can_start> | |
if (err) | |
d0c: e2505000 subs r5, r0, #0 | |
d10: 1a00001c bne d88 <c_can_open+0x154> | |
d14: e5943578 ldr r3, [r4, #1400] ; 0x578 | |
* Resume NAPI from being scheduled on this context. | |
* Must be paired with napi_disable. | |
*/ | |
static inline void napi_enable(struct napi_struct *n) | |
{ | |
BUG_ON(!test_bit(NAPI_STATE_SCHED, &n->state)); | |
d18: e3130001 tst r3, #1 | |
d1c: 0a00001d beq d98 <c_can_open+0x164> | |
smp_mb__before_atomic(); | |
d20: f57ff05b dmb ish | |
clear_bit(NAPI_STATE_SCHED, &n->state); | |
d24: e2845e57 add r5, r4, #1392 ; 0x570 | |
d28: e3a00000 mov r0, #0 | |
d2c: e2855008 add r5, r5, #8 | |
d30: e1a01005 mov r1, r5 | |
d34: ebfffffe bl 0 <_clear_bit> | |
clear_bit(NAPI_STATE_NPSVC, &n->state); | |
d38: e1a01005 mov r1, r5 | |
d3c: e3a00002 mov r0, #2 | |
d40: ebfffffe bl 0 <_clear_bit> | |
can_led_event(dev, CAN_LED_EVENT_OPEN); | |
napi_enable(&priv->napi); | |
/* enable status change, error and module interrupts */ | |
c_can_irq_control(priv, true); | |
d44: e1a00006 mov r0, r6 | |
d48: e3a01001 mov r1, #1 | |
d4c: ebfffcab bl 0 <c_can_irq_control> | |
netif_schedule_queue(netdev_get_tx_queue(dev, i)); | |
} | |
static inline void netif_tx_start_queue(struct netdev_queue *dev_queue) | |
{ | |
clear_bit(__QUEUE_STATE_DRV_XOFF, &dev_queue->state); | |
d50: e5941240 ldr r1, [r4, #576] ; 0x240 | |
d54: e3a00000 mov r0, #0 | |
d58: e2811050 add r1, r1, #80 ; 0x50 | |
d5c: ebfffffe bl 0 <_clear_bit> | |
netif_start_queue(dev); | |
return 0; | |
d60: e3a00000 mov r0, #0 | |
close_candev(dev); | |
exit_open_fail: | |
c_can_reset_ram(priv, false); | |
c_can_pm_runtime_put_sync(priv); | |
return err; | |
} | |
d64: e24bd018 sub sp, fp, #24 | |
d68: e89da870 ldm sp, {r4, r5, r6, fp, sp, pc} | |
/* register interrupt handler */ | |
err = request_irq(dev->irq, &c_can_isr, IRQF_SHARED, dev->name, | |
dev); | |
if (err < 0) { | |
netdev_err(dev, "failed to request interrupt\n"); | |
d6c: e3001000 movw r1, #0 | |
d70: e1a00004 mov r0, r4 | |
d74: e3401000 movt r1, #0 | |
d78: ebfffffe bl 0 <netdev_err> | |
return 0; | |
exit_start_fail: | |
free_irq(dev->irq, dev); | |
exit_irq_fail: | |
close_candev(dev); | |
d7c: e1a00004 mov r0, r4 | |
d80: ebfffffe bl 0 <close_candev> | |
d84: eaffffc5 b ca0 <c_can_open+0x6c> | |
netif_start_queue(dev); | |
return 0; | |
exit_start_fail: | |
free_irq(dev->irq, dev); | |
d88: e5940028 ldr r0, [r4, #40] ; 0x28 | |
d8c: e1a01004 mov r1, r4 | |
d90: ebfffffe bl 0 <free_irq> | |
d94: eafffff8 b d7c <c_can_open+0x148> | |
d98: e7f001f2 .word 0xe7f001f2 | |
00000d9c <c_can_poll>: | |
netif_receive_skb(skb); | |
return 1; | |
} | |
static int c_can_poll(struct napi_struct *napi, int quota) | |
{ | |
d9c: e1a0c00d mov ip, sp | |
da0: e92ddff0 push {r4, r5, r6, r7, r8, r9, sl, fp, ip, lr, pc} | |
da4: e24cb004 sub fp, ip, #4 | |
da8: e24dd034 sub sp, sp, #52 ; 0x34 | |
dac: e52de004 push {lr} ; (str lr, [sp, #-4]!) | |
db0: ebfffffe bl 0 <__gnu_mcount_nc> | |
struct net_device *dev = napi->dev; | |
db4: e5904018 ldr r4, [r0, #24] | |
netif_receive_skb(skb); | |
return 1; | |
} | |
static int c_can_poll(struct napi_struct *napi, int quota) | |
{ | |
db8: e50b0058 str r0, [fp, #-88] ; 0x58 | |
dbc: e50b1050 str r1, [fp, #-80] ; 0x50 | |
struct net_device *dev = napi->dev; | |
struct c_can_priv *priv = netdev_priv(dev); | |
u16 curr, last = priv->last_status; | |
int work_done = 0; | |
priv->last_status = curr = priv->read_reg(priv, C_CAN_STS_REG); | |
dc0: e3a01002 mov r1, #2 | |
} | |
static int c_can_poll(struct napi_struct *napi, int quota) | |
{ | |
struct net_device *dev = napi->dev; | |
struct c_can_priv *priv = netdev_priv(dev); | |
dc4: e2848d13 add r8, r4, #1216 ; 0x4c0 | |
u16 curr, last = priv->last_status; | |
int work_done = 0; | |
priv->last_status = curr = priv->read_reg(priv, C_CAN_STS_REG); | |
dc8: e59435f4 ldr r3, [r4, #1524] ; 0x5f4 | |
dcc: e1a00008 mov r0, r8 | |
static int c_can_poll(struct napi_struct *napi, int quota) | |
{ | |
struct net_device *dev = napi->dev; | |
struct c_can_priv *priv = netdev_priv(dev); | |
u16 curr, last = priv->last_status; | |
dd0: e59475f0 ldr r7, [r4, #1520] ; 0x5f0 | |
int work_done = 0; | |
priv->last_status = curr = priv->read_reg(priv, C_CAN_STS_REG); | |
dd4: e12fff33 blx r3 | |
/* Ack status on C_CAN. D_CAN is self clearing */ | |
if (priv->type != BOSCH_D_CAN) | |
dd8: e5943610 ldr r3, [r4, #1552] ; 0x610 | |
struct net_device *dev = napi->dev; | |
struct c_can_priv *priv = netdev_priv(dev); | |
u16 curr, last = priv->last_status; | |
int work_done = 0; | |
priv->last_status = curr = priv->read_reg(priv, C_CAN_STS_REG); | |
ddc: e1a05000 mov r5, r0 | |
de0: e58405f0 str r0, [r4, #1520] ; 0x5f0 | |
/* Ack status on C_CAN. D_CAN is self clearing */ | |
if (priv->type != BOSCH_D_CAN) | |
de4: e3530002 cmp r3, #2 | |
de8: 0a000004 beq e00 <c_can_poll+0x64> | |
priv->write_reg(priv, C_CAN_STS_REG, LEC_UNUSED); | |
dec: e59435f8 ldr r3, [r4, #1528] ; 0x5f8 | |
df0: e1a00008 mov r0, r8 | |
df4: e3a01002 mov r1, #2 | |
df8: e3a02007 mov r2, #7 | |
dfc: e12fff33 blx r3 | |
/* handle state changes */ | |
if ((curr & STATUS_EWARN) && (!(last & STATUS_EWARN))) { | |
e00: e205a040 and sl, r5, #64 ; 0x40 | |
e04: e6ff7077 uxth r7, r7 | |
e08: e6ffa07a uxth sl, sl | |
e0c: e35a0000 cmp sl, #0 | |
e10: 0a000002 beq e20 <c_can_poll+0x84> | |
e14: e3170040 tst r7, #64 ; 0x40 | |
static int c_can_poll(struct napi_struct *napi, int quota) | |
{ | |
struct net_device *dev = napi->dev; | |
struct c_can_priv *priv = netdev_priv(dev); | |
u16 curr, last = priv->last_status; | |
int work_done = 0; | |
e18: 13a0a000 movne sl, #0 | |
/* Ack status on C_CAN. D_CAN is self clearing */ | |
if (priv->type != BOSCH_D_CAN) | |
priv->write_reg(priv, C_CAN_STS_REG, LEC_UNUSED); | |
/* handle state changes */ | |
if ((curr & STATUS_EWARN) && (!(last & STATUS_EWARN))) { | |
e1c: 0a000170 beq 13e4 <c_can_poll+0x648> | |
netdev_dbg(dev, "entered error warning state\n"); | |
work_done += c_can_handle_state_change(dev, C_CAN_ERROR_WARNING); | |
} | |
if ((curr & STATUS_EPASS) && (!(last & STATUS_EPASS))) { | |
e20: e2056020 and r6, r5, #32 | |
e24: e6ff6076 uxth r6, r6 | |
e28: e3560000 cmp r6, #0 | |
e2c: 0a000001 beq e38 <c_can_poll+0x9c> | |
e30: e3170020 tst r7, #32 | |
e34: 0a00015f beq 13b8 <c_can_poll+0x61c> | |
netdev_dbg(dev, "entered error passive state\n"); | |
work_done += c_can_handle_state_change(dev, C_CAN_ERROR_PASSIVE); | |
} | |
if ((curr & STATUS_BOFF) && (!(last & STATUS_BOFF))) { | |
e38: e2059080 and r9, r5, #128 ; 0x80 | |
e3c: e6ff9079 uxth r9, r9 | |
e40: e3590000 cmp r9, #0 | |
e44: 1a000114 bne 129c <c_can_poll+0x500> | |
work_done += c_can_handle_state_change(dev, C_CAN_BUS_OFF); | |
goto end; | |
} | |
/* handle bus recovery events */ | |
if ((!(curr & STATUS_BOFF)) && (last & STATUS_BOFF)) { | |
e48: e3170080 tst r7, #128 ; 0x80 | |
e4c: 1a00016f bne 1410 <c_can_poll+0x674> | |
netdev_dbg(dev, "left bus off state\n"); | |
priv->can.state = CAN_STATE_ERROR_ACTIVE; | |
} | |
if ((!(curr & STATUS_EPASS)) && (last & STATUS_EPASS)) { | |
e50: e3560000 cmp r6, #0 | |
e54: 0a00012d beq 1310 <c_can_poll+0x574> | |
/* | |
* early exit if no lec update or no error. | |
* no lec update means that no CAN bus event has been detected | |
* since CPU wrote 0x7 value to status reg. | |
*/ | |
if (lec_type == LEC_UNUSED || lec_type == LEC_NO_ERROR) | |
e58: e2155007 ands r5, r5, #7 | |
e5c: 03a03001 moveq r3, #1 | |
e60: 13a03000 movne r3, #0 | |
e64: e3550007 cmp r5, #7 | |
e68: 03833001 orreq r3, r3, #1 | |
e6c: e3530000 cmp r3, #0 | |
e70: 1a000002 bne e80 <c_can_poll+0xe4> | |
return 0; | |
if (!(priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)) | |
e74: e5943528 ldr r3, [r4, #1320] ; 0x528 | |
e78: e3130010 tst r3, #16 | |
e7c: 1a00012d bne 1338 <c_can_poll+0x59c> | |
* early exit if no lec update or no error. | |
* no lec update means that no CAN bus event has been detected | |
* since CPU wrote 0x7 value to status reg. | |
*/ | |
if (lec_type == LEC_UNUSED || lec_type == LEC_NO_ERROR) | |
return 0; | |
e80: e3a03000 mov r3, #0 | |
/* handle lec errors on the bus */ | |
work_done += c_can_handle_bus_err(dev, curr & LEC_MASK); | |
/* Handle Tx/Rx events. We do this unconditionally */ | |
work_done += c_can_do_rx_poll(dev, (quota - work_done)); | |
e84: e51b0050 ldr r0, [fp, #-80] ; 0x50 | |
netdev_dbg(dev, "left error passive state\n"); | |
priv->can.state = CAN_STATE_ERROR_ACTIVE; | |
} | |
/* handle lec errors on the bus */ | |
work_done += c_can_handle_bus_err(dev, curr & LEC_MASK); | |
e88: e08a3003 add r3, sl, r3 | |
e8c: e50b3054 str r3, [fp, #-84] ; 0x54 | |
/* Handle Tx/Rx events. We do this unconditionally */ | |
work_done += c_can_do_rx_poll(dev, (quota - work_done)); | |
e90: e0630000 rsb r0, r3, r0 | |
* for a maximum number of 16 objects. | |
*/ | |
BUILD_BUG_ON_MSG(C_CAN_MSG_OBJ_RX_LAST > 16, | |
"Implementation does not support more message objects than 16"); | |
while (quota > 0) { | |
e94: e3500000 cmp r0, #0 | |
/* handle lec errors on the bus */ | |
work_done += c_can_handle_bus_err(dev, curr & LEC_MASK); | |
/* Handle Tx/Rx events. We do this unconditionally */ | |
work_done += c_can_do_rx_poll(dev, (quota - work_done)); | |
e98: e50b0040 str r0, [fp, #-64] ; 0x40 | |
* for a maximum number of 16 objects. | |
*/ | |
BUILD_BUG_ON_MSG(C_CAN_MSG_OBJ_RX_LAST > 16, | |
"Implementation does not support more message objects than 16"); | |
while (quota > 0) { | |
e9c: da000165 ble 1438 <c_can_poll+0x69c> | |
/* | |
* Find the first set bit after the gap. We walk backwards | |
* from the last set bit. | |
*/ | |
for (lasts--; pend & (1 << (lasts - 1)); lasts--); | |
ea0: e3a0a001 mov sl, #1 | |
* This can result in packet reordering when the readout is slow. | |
*/ | |
static int c_can_do_rx_poll(struct net_device *dev, int quota) | |
{ | |
struct c_can_priv *priv = netdev_priv(dev); | |
u32 pkts = 0, pend = 0, toread, n; | |
ea4: e3a02000 mov r2, #0 | |
ea8: e50b204c str r2, [fp, #-76] ; 0x4c | |
eac: e50b2038 str r2, [fp, #-56] ; 0x38 | |
*/ | |
BUILD_BUG_ON_MSG(C_CAN_MSG_OBJ_RX_LAST > 16, | |
"Implementation does not support more message objects than 16"); | |
while (quota > 0) { | |
if (!pend) { | |
eb0: e51b3038 ldr r3, [fp, #-56] ; 0x38 | |
eb4: e3530000 cmp r3, #0 | |
eb8: 0a000090 beq 1100 <c_can_poll+0x364> | |
ebc: e51b5038 ldr r5, [fp, #-56] ; 0x38 | |
ec0: e1e03003 mvn r3, r3 | |
toread = c_can_adjust_pending(pend); | |
} else { | |
toread = pend; | |
} | |
/* Remove the bits from pend */ | |
pend &= ~toread; | |
ec4: e51b2038 ldr r2, [fp, #-56] ; 0x38 | |
} | |
static int c_can_read_objects(struct net_device *dev, struct c_can_priv *priv, | |
u32 pend, int quota) | |
{ | |
u32 pkts = 0, ctrl, obj; | |
ec8: e3a09000 mov r9, #0 | |
toread = c_can_adjust_pending(pend); | |
} else { | |
toread = pend; | |
} | |
/* Remove the bits from pend */ | |
pend &= ~toread; | |
ecc: e51b7040 ldr r7, [fp, #-64] ; 0x40 | |
ed0: e0022003 and r2, r2, r3 | |
ed4: e50b2038 str r2, [fp, #-56] ; 0x38 | |
* ffs() returns zero if the input was zero, otherwise returns the bit | |
* position of the first set bit, where the LSB is 1 and MSB is 32. | |
*/ | |
static inline int ffs(int x) | |
{ | |
return fls(x & -x); | |
ed8: e2653000 rsb r3, r5, #0 | |
edc: e0033005 and r3, r3, r5 | |
*/ | |
static inline unsigned int __clz(unsigned int x) | |
{ | |
unsigned int ret; | |
asm("clz\t%0, %1" : "=r" (ret) : "r" (x)); | |
ee0: e16f3f13 clz r3, r3 | |
static int c_can_read_objects(struct net_device *dev, struct c_can_priv *priv, | |
u32 pend, int quota) | |
{ | |
u32 pkts = 0, ctrl, obj; | |
while ((obj = ffs(pend)) && quota > 0) { | |
ee4: e2736020 rsbs r6, r3, #32 | |
ee8: 0a0000a2 beq 1178 <c_can_poll+0x3dc> | |
eec: e3570000 cmp r7, #0 | |
ef0: 0a0000a0 beq 1178 <c_can_poll+0x3dc> | |
pend &= ~BIT(obj - 1); | |
ef4: e263c01f rsb ip, r3, #31 | |
} | |
static inline void c_can_object_get(struct net_device *dev, int iface, | |
u32 obj, u32 cmd) | |
{ | |
c_can_obj_update(dev, iface, cmd, obj); | |
ef8: e5942624 ldr r2, [r4, #1572] ; 0x624 | |
efc: e1a00004 mov r0, r4 | |
f00: e3a01000 mov r1, #0 | |
f04: e1a03006 mov r3, r6 | |
u32 pend, int quota) | |
{ | |
u32 pkts = 0, ctrl, obj; | |
while ((obj = ffs(pend)) && quota > 0) { | |
pend &= ~BIT(obj - 1); | |
f08: e1c55c1a bic r5, r5, sl, lsl ip | |
} | |
static inline void c_can_object_get(struct net_device *dev, int iface, | |
u32 obj, u32 cmd) | |
{ | |
c_can_obj_update(dev, iface, cmd, obj); | |
f0c: ebfffc98 bl 174 <c_can_obj_update> | |
while ((obj = ffs(pend)) && quota > 0) { | |
pend &= ~BIT(obj - 1); | |
c_can_rx_object_get(dev, priv, obj); | |
ctrl = priv->read_reg(priv, C_CAN_IFACE(MSGCTRL_REG, IF_RX)); | |
f10: e59435f4 ldr r3, [r4, #1524] ; 0x5f4 | |
f14: e1a00008 mov r0, r8 | |
f18: e3a0100e mov r1, #14 | |
f1c: e12fff33 blx r3 | |
if (ctrl & IF_MCONT_MSGLST) { | |
f20: e3100901 tst r0, #16384 ; 0x4000 | |
while ((obj = ffs(pend)) && quota > 0) { | |
pend &= ~BIT(obj - 1); | |
c_can_rx_object_get(dev, priv, obj); | |
ctrl = priv->read_reg(priv, C_CAN_IFACE(MSGCTRL_REG, IF_RX)); | |
f24: e1a02000 mov r2, r0 | |
if (ctrl & IF_MCONT_MSGLST) { | |
f28: 1a00004b bne 105c <c_can_poll+0x2c0> | |
/* | |
* This really should not happen, but this covers some | |
* odd HW behaviour. Do not remove that unless you | |
* want to brick your machine. | |
*/ | |
if (!(ctrl & IF_MCONT_NEWDAT)) | |
f2c: e3100902 tst r0, #32768 ; 0x8000 | |
f30: 0affffe8 beq ed8 <c_can_poll+0x13c> | |
struct c_can_priv *priv = netdev_priv(dev); | |
struct can_frame *frame; | |
struct sk_buff *skb; | |
u32 arb, data; | |
skb = alloc_can_skb(dev, &frame); | |
f34: e1a00004 mov r0, r4 | |
f38: e24b1030 sub r1, fp, #48 ; 0x30 | |
f3c: e50b205c str r2, [fp, #-92] ; 0x5c | |
f40: ebfffffe bl 0 <alloc_can_skb> | |
if (!skb) { | |
f44: e3500000 cmp r0, #0 | |
f48: e51b205c ldr r2, [fp, #-92] ; 0x5c | |
f4c: e50b003c str r0, [fp, #-60] ; 0x3c | |
f50: 0a000111 beq 139c <c_can_poll+0x600> | |
stats->rx_dropped++; | |
return -ENOMEM; | |
} | |
frame->can_dlc = get_can_dlc(ctrl & 0x0F); | |
f54: e202200f and r2, r2, #15 | |
f58: e51b3030 ldr r3, [fp, #-48] ; 0x30 | |
f5c: e3520008 cmp r2, #8 | |
arb = priv->read_reg32(priv, C_CAN_IFACE(ARB1_REG, iface)); | |
f60: e1a00008 mov r0, r8 | |
if (!skb) { | |
stats->rx_dropped++; | |
return -ENOMEM; | |
} | |
frame->can_dlc = get_can_dlc(ctrl & 0x0F); | |
f64: 23a02008 movcs r2, #8 | |
arb = priv->read_reg32(priv, C_CAN_IFACE(ARB1_REG, iface)); | |
f68: e3a0100c mov r1, #12 | |
if (!skb) { | |
stats->rx_dropped++; | |
return -ENOMEM; | |
} | |
frame->can_dlc = get_can_dlc(ctrl & 0x0F); | |
f6c: e5c32004 strb r2, [r3, #4] | |
arb = priv->read_reg32(priv, C_CAN_IFACE(ARB1_REG, iface)); | |
f70: e59435fc ldr r3, [r4, #1532] ; 0x5fc | |
f74: e12fff33 blx r3 | |
if (arb & IF_ARB_MSGXTD) | |
frame->can_id = (arb & CAN_EFF_MASK) | CAN_EFF_FLAG; | |
f78: e51b3030 ldr r3, [fp, #-48] ; 0x30 | |
frame->can_dlc = get_can_dlc(ctrl & 0x0F); | |
arb = priv->read_reg32(priv, C_CAN_IFACE(ARB1_REG, iface)); | |
if (arb & IF_ARB_MSGXTD) | |
f7c: e3100101 tst r0, #1073741824 ; 0x40000000 | |
frame->can_id = (arb & CAN_EFF_MASK) | CAN_EFF_FLAG; | |
f80: 13c0220e bicne r2, r0, #-536870912 ; 0xe0000000 | |
else | |
frame->can_id = (arb >> 18) & CAN_SFF_MASK; | |
f84: 07ea2950 ubfxeq r2, r0, #18, #11 | |
frame->can_dlc = get_can_dlc(ctrl & 0x0F); | |
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; | |
f88: 13822102 orrne r2, r2, #-2147483648 ; 0x80000000 | |
else | |
frame->can_id = (arb >> 18) & CAN_SFF_MASK; | |
f8c: e5832000 str r2, [r3] | |
if (arb & IF_ARB_TRANSMIT) { | |
f90: e2103202 ands r3, r0, #536870912 ; 0x20000000 | |
f94: 1a000053 bne 10e8 <c_can_poll+0x34c> | |
frame->can_id |= CAN_RTR_FLAG; | |
} else { | |
int i, dreg = C_CAN_IFACE(DATA1_REG, iface); | |
for (i = 0; i < frame->can_dlc; i += 2, dreg ++) { | |
f98: e51b0030 ldr r0, [fp, #-48] ; 0x30 | |
f9c: e5d02004 ldrb r2, [r0, #4] | |
fa0: e3520000 cmp r2, #0 | |
fa4: 0a000017 beq 1008 <c_can_poll+0x26c> | |
fa8: e3a0200f mov r2, #15 | |
fac: e50b5044 str r5, [fp, #-68] ; 0x44 | |
fb0: e50b6048 str r6, [fp, #-72] ; 0x48 | |
fb4: e1a05004 mov r5, r4 | |
fb8: e1a06002 mov r6, r2 | |
fbc: e1a04003 mov r4, r3 | |
data = priv->read_reg(priv, dreg); | |
fc0: e1a01006 mov r1, r6 | |
fc4: e595c5f4 ldr ip, [r5, #1524] ; 0x5f4 | |
fc8: e1a00008 mov r0, r8 | |
if (arb & IF_ARB_TRANSMIT) { | |
frame->can_id |= CAN_RTR_FLAG; | |
} else { | |
int i, dreg = C_CAN_IFACE(DATA1_REG, iface); | |
for (i = 0; i < frame->can_dlc; i += 2, dreg ++) { | |
fcc: e2866001 add r6, r6, #1 | |
data = priv->read_reg(priv, dreg); | |
fd0: e12fff3c blx ip | |
frame->data[i] = data; | |
fd4: e51b1030 ldr r1, [fp, #-48] ; 0x30 | |
frame->data[i + 1] = data >> 8; | |
fd8: e1a0e420 lsr lr, r0, #8 | |
} else { | |
int i, dreg = C_CAN_IFACE(DATA1_REG, iface); | |
for (i = 0; i < frame->can_dlc; i += 2, dreg ++) { | |
data = priv->read_reg(priv, dreg); | |
frame->data[i] = data; | |
fdc: e081c004 add ip, r1, r4 | |
if (arb & IF_ARB_TRANSMIT) { | |
frame->can_id |= CAN_RTR_FLAG; | |
} else { | |
int i, dreg = C_CAN_IFACE(DATA1_REG, iface); | |
for (i = 0; i < frame->can_dlc; i += 2, dreg ++) { | |
fe0: e2844002 add r4, r4, #2 | |
data = priv->read_reg(priv, dreg); | |
frame->data[i] = data; | |
frame->data[i + 1] = data >> 8; | |
fe4: e5cce009 strb lr, [ip, #9] | |
} else { | |
int i, dreg = C_CAN_IFACE(DATA1_REG, iface); | |
for (i = 0; i < frame->can_dlc; i += 2, dreg ++) { | |
data = priv->read_reg(priv, dreg); | |
frame->data[i] = data; | |
fe8: e5cc0008 strb r0, [ip, #8] | |
if (arb & IF_ARB_TRANSMIT) { | |
frame->can_id |= CAN_RTR_FLAG; | |
} else { | |
int i, dreg = C_CAN_IFACE(DATA1_REG, iface); | |
for (i = 0; i < frame->can_dlc; i += 2, dreg ++) { | |
fec: e5d10004 ldrb r0, [r1, #4] | |
ff0: e1540000 cmp r4, r0 | |
ff4: bafffff1 blt fc0 <c_can_poll+0x224> | |
ff8: e1a04005 mov r4, r5 | |
ffc: e51b6048 ldr r6, [fp, #-72] ; 0x48 | |
1000: e51b5044 ldr r5, [fp, #-68] ; 0x44 | |
data = priv->read_reg(priv, dreg); | |
frame->data[i] = data; | |
1004: e1a00001 mov r0, r1 | |
frame->data[i + 1] = data >> 8; | |
} | |
} | |
stats->rx_packets++; | |
1008: e59430c0 ldr r3, [r4, #192] ; 0xc0 | |
stats->rx_bytes += frame->can_dlc; | |
100c: e59420c8 ldr r2, [r4, #200] ; 0xc8 | |
int netif_rx(struct sk_buff *skb); | |
int netif_rx_ni(struct sk_buff *skb); | |
int netif_receive_skb_sk(struct sock *sk, struct sk_buff *skb); | |
static inline int netif_receive_skb(struct sk_buff *skb) | |
{ | |
return netif_receive_skb_sk(skb->sk, skb); | |
1010: e51b103c ldr r1, [fp, #-60] ; 0x3c | |
frame->data[i] = data; | |
frame->data[i + 1] = data >> 8; | |
} | |
} | |
stats->rx_packets++; | |
1014: e2833001 add r3, r3, #1 | |
1018: e58430c0 str r3, [r4, #192] ; 0xc0 | |
stats->rx_bytes += frame->can_dlc; | |
101c: e5d03004 ldrb r3, [r0, #4] | |
1020: e0823003 add r3, r2, r3 | |
1024: e58430c8 str r3, [r4, #200] ; 0xc8 | |
1028: e5910010 ldr r0, [r1, #16] | |
102c: ebfffffe bl 0 <netif_receive_skb_sk> | |
} | |
static inline void c_can_rx_finalize(struct net_device *dev, | |
struct c_can_priv *priv, u32 obj) | |
{ | |
if (priv->type != BOSCH_D_CAN) | |
1030: e5943610 ldr r3, [r4, #1552] ; 0x610 | |
1034: e3530002 cmp r3, #2 | |
1038: 0a000004 beq 1050 <c_can_poll+0x2b4> | |
} | |
static inline void c_can_object_get(struct net_device *dev, int iface, | |
u32 obj, u32 cmd) | |
{ | |
c_can_obj_update(dev, iface, cmd, obj); | |
103c: e1a03006 mov r3, r6 | |
1040: e1a00004 mov r0, r4 | |
1044: e3a01000 mov r1, #0 | |
1048: e3a02004 mov r2, #4 | |
104c: ebfffc48 bl 174 <c_can_obj_update> | |
/* read the data from the message object */ | |
c_can_read_msg_object(dev, IF_RX, ctrl); | |
c_can_rx_finalize(dev, priv, obj); | |
pkts++; | |
1050: e2899001 add r9, r9, #1 | |
quota--; | |
1054: e2477001 sub r7, r7, #1 | |
1058: eaffff9e b ed8 <c_can_poll+0x13c> | |
struct c_can_priv *priv = netdev_priv(dev); | |
struct can_frame *frame; | |
struct sk_buff *skb; | |
ctrl &= ~(IF_MCONT_MSGLST | IF_MCONT_INTPND | IF_MCONT_NEWDAT); | |
priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), ctrl); | |
105c: e7ec2050 ubfx r2, r0, #0, #13 | |
1060: e59435f8 ldr r3, [r4, #1528] ; 0x5f8 | |
1064: e1a00008 mov r0, r8 | |
1068: e3a0100e mov r1, #14 | |
106c: e12fff33 blx r3 | |
} | |
static inline void c_can_object_put(struct net_device *dev, int iface, | |
u32 obj, u32 cmd) | |
{ | |
c_can_obj_update(dev, iface, cmd | IF_COMM_WR, obj); | |
1070: e1a00004 mov r0, r4 | |
1074: e1a03006 mov r3, r6 | |
1078: e3a01000 mov r1, #0 | |
107c: e3a02090 mov r2, #144 ; 0x90 | |
1080: ebfffc3b bl 174 <c_can_obj_update> | |
ctrl &= ~(IF_MCONT_MSGLST | IF_MCONT_INTPND | IF_MCONT_NEWDAT); | |
priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), ctrl); | |
c_can_object_put(dev, iface, objno, IF_COMM_CONTROL); | |
stats->rx_errors++; | |
1084: e59420d0 ldr r2, [r4, #208] ; 0xd0 | |
stats->rx_over_errors++; | |
/* create an error msg */ | |
skb = alloc_can_err_skb(dev, &frame); | |
1088: e1a00004 mov r0, r4 | |
ctrl &= ~(IF_MCONT_MSGLST | IF_MCONT_INTPND | IF_MCONT_NEWDAT); | |
priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), ctrl); | |
c_can_object_put(dev, iface, objno, IF_COMM_CONTROL); | |
stats->rx_errors++; | |
stats->rx_over_errors++; | |
108c: e59430ec ldr r3, [r4, #236] ; 0xec | |
/* create an error msg */ | |
skb = alloc_can_err_skb(dev, &frame); | |
1090: e24b1030 sub r1, fp, #48 ; 0x30 | |
ctrl &= ~(IF_MCONT_MSGLST | IF_MCONT_INTPND | IF_MCONT_NEWDAT); | |
priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), ctrl); | |
c_can_object_put(dev, iface, objno, IF_COMM_CONTROL); | |
stats->rx_errors++; | |
1094: e2822001 add r2, r2, #1 | |
stats->rx_over_errors++; | |
1098: e2833001 add r3, r3, #1 | |
ctrl &= ~(IF_MCONT_MSGLST | IF_MCONT_INTPND | IF_MCONT_NEWDAT); | |
priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), ctrl); | |
c_can_object_put(dev, iface, objno, IF_COMM_CONTROL); | |
stats->rx_errors++; | |
109c: e58420d0 str r2, [r4, #208] ; 0xd0 | |
stats->rx_over_errors++; | |
10a0: e58430ec str r3, [r4, #236] ; 0xec | |
/* create an error msg */ | |
skb = alloc_can_err_skb(dev, &frame); | |
10a4: ebfffffe bl 0 <alloc_can_err_skb> | |
if (unlikely(!skb)) | |
10a8: e3500000 cmp r0, #0 | |
10ac: 0a000138 beq 1594 <c_can_poll+0x7f8> | |
return 0; | |
frame->can_id |= CAN_ERR_CRTL; | |
10b0: e51b3030 ldr r3, [fp, #-48] ; 0x30 | |
10b4: e1a01000 mov r1, r0 | |
10b8: e5932000 ldr r2, [r3] | |
10bc: e3822004 orr r2, r2, #4 | |
10c0: e5832000 str r2, [r3] | |
frame->data[1] = CAN_ERR_CRTL_RX_OVERFLOW; | |
10c4: e51b3030 ldr r3, [fp, #-48] ; 0x30 | |
10c8: e5c3a009 strb sl, [r3, #9] | |
10cc: e5900010 ldr r0, [r0, #16] | |
10d0: ebfffffe bl 0 <netif_receive_skb_sk> | |
10d4: e3a03001 mov r3, #1 | |
netif_receive_skb(skb); | |
return 1; | |
10d8: e1a02003 mov r2, r3 | |
ctrl = priv->read_reg(priv, C_CAN_IFACE(MSGCTRL_REG, IF_RX)); | |
if (ctrl & IF_MCONT_MSGLST) { | |
int n = c_can_handle_lost_msg_obj(dev, IF_RX, obj, ctrl); | |
pkts += n; | |
10dc: e0899003 add r9, r9, r3 | |
quota -= n; | |
10e0: e0627007 rsb r7, r2, r7 | |
10e4: eaffff7b b ed8 <c_can_poll+0x13c> | |
frame->can_id = (arb & CAN_EFF_MASK) | CAN_EFF_FLAG; | |
else | |
frame->can_id = (arb >> 18) & CAN_SFF_MASK; | |
if (arb & IF_ARB_TRANSMIT) { | |
frame->can_id |= CAN_RTR_FLAG; | |
10e8: e51b3030 ldr r3, [fp, #-48] ; 0x30 | |
10ec: e5932000 ldr r2, [r3] | |
10f0: e3822101 orr r2, r2, #1073741824 ; 0x40000000 | |
10f4: e5832000 str r2, [r3] | |
10f8: e51b0030 ldr r0, [fp, #-48] ; 0x30 | |
10fc: eaffffc1 b 1008 <c_can_poll+0x26c> | |
return pkts; | |
} | |
static inline u32 c_can_get_pending(struct c_can_priv *priv) | |
{ | |
u32 pend = priv->read_reg(priv, C_CAN_NEWDAT1_REG); | |
1100: e59435f4 ldr r3, [r4, #1524] ; 0x5f4 | |
1104: e1a00008 mov r0, r8 | |
1108: e3a01020 mov r1, #32 | |
110c: e12fff33 blx r3 | |
"Implementation does not support more message objects than 16"); | |
while (quota > 0) { | |
if (!pend) { | |
pend = c_can_get_pending(priv); | |
if (!pend) | |
1110: e3500000 cmp r0, #0 | |
return pkts; | |
} | |
static inline u32 c_can_get_pending(struct c_can_priv *priv) | |
{ | |
u32 pend = priv->read_reg(priv, C_CAN_NEWDAT1_REG); | |
1114: e50b0038 str r0, [fp, #-56] ; 0x38 | |
1118: e1a06000 mov r6, r0 | |
"Implementation does not support more message objects than 16"); | |
while (quota > 0) { | |
if (!pend) { | |
pend = c_can_get_pending(priv); | |
if (!pend) | |
111c: 0a00001d beq 1198 <c_can_poll+0x3fc> | |
*/ | |
static u32 c_can_adjust_pending(u32 pend) | |
{ | |
u32 weight, lasts; | |
if (pend == RECEIVE_OBJECT_BITS) | |
1120: e51b2038 ldr r2, [fp, #-56] ; 0x38 | |
1124: e30f3fff movw r3, #65535 ; 0xffff | |
1128: e1520003 cmp r2, r3 | |
112c: 0a000052 beq 127c <c_can_poll+0x4e0> | |
#include <asm/types.h> | |
static inline unsigned int __arch_hweight32(unsigned int w) | |
{ | |
return __sw_hweight32(w); | |
1130: ebfffffe bl 0 <__sw_hweight32> | |
1134: e51b3038 ldr r3, [fp, #-56] ; 0x38 | |
1138: e16f2f13 clz r2, r3 | |
static inline int fls(int x) | |
{ | |
if (__builtin_constant_p(x)) | |
return constant_fls(x); | |
return 32 - __clz(x); | |
113c: e2623020 rsb r3, r2, #32 | |
*/ | |
weight = hweight32(pend); | |
lasts = fls(pend); | |
/* If the bits are linear, nothing to do */ | |
if (lasts == weight) | |
1140: e1500003 cmp r0, r3 | |
/* | |
* Find the first set bit after the gap. We walk backwards | |
* from the last set bit. | |
*/ | |
for (lasts--; pend & (1 << (lasts - 1)); lasts--); | |
1144: 1262201f rsbne r2, r2, #31 | |
*/ | |
weight = hweight32(pend); | |
lasts = fls(pend); | |
/* If the bits are linear, nothing to do */ | |
if (lasts == weight) | |
1148: 1a000001 bne 1154 <c_can_poll+0x3b8> | |
114c: ea00004e b 128c <c_can_poll+0x4f0> | |
/* | |
* Find the first set bit after the gap. We walk backwards | |
* from the last set bit. | |
*/ | |
for (lasts--; pend & (1 << (lasts - 1)); lasts--); | |
1150: e1a02003 mov r2, r3 | |
1154: e2423001 sub r3, r2, #1 | |
1158: e3a01001 mov r1, #1 | |
115c: e016031a ands r0, r6, sl, lsl r3 | |
1160: 1afffffa bne 1150 <c_can_poll+0x3b4> | |
return pend & ~((1 << lasts) - 1); | |
1164: e1a05211 lsl r5, r1, r2 | |
1168: e2655000 rsb r5, r5, #0 | |
116c: e0055006 and r5, r5, r6 | |
1170: e1e03005 mvn r3, r5 | |
1174: eaffff52 b ec4 <c_can_poll+0x128> | |
/* Remove the bits from pend */ | |
pend &= ~toread; | |
/* Read the objects */ | |
n = c_can_read_objects(dev, priv, toread, quota); | |
pkts += n; | |
quota -= n; | |
1178: e51b0040 ldr r0, [fp, #-64] ; 0x40 | |
} | |
/* Remove the bits from pend */ | |
pend &= ~toread; | |
/* Read the objects */ | |
n = c_can_read_objects(dev, priv, toread, quota); | |
pkts += n; | |
117c: e51b204c ldr r2, [fp, #-76] ; 0x4c | |
quota -= n; | |
1180: e0690000 rsb r0, r9, r0 | |
* for a maximum number of 16 objects. | |
*/ | |
BUILD_BUG_ON_MSG(C_CAN_MSG_OBJ_RX_LAST > 16, | |
"Implementation does not support more message objects than 16"); | |
while (quota > 0) { | |
1184: e3500000 cmp r0, #0 | |
} | |
/* Remove the bits from pend */ | |
pend &= ~toread; | |
/* Read the objects */ | |
n = c_can_read_objects(dev, priv, toread, quota); | |
pkts += n; | |
1188: e0822009 add r2, r2, r9 | |
quota -= n; | |
118c: e50b0040 str r0, [fp, #-64] ; 0x40 | |
} | |
/* Remove the bits from pend */ | |
pend &= ~toread; | |
/* Read the objects */ | |
n = c_can_read_objects(dev, priv, toread, quota); | |
pkts += n; | |
1190: e50b204c str r2, [fp, #-76] ; 0x4c | |
* for a maximum number of 16 objects. | |
*/ | |
BUILD_BUG_ON_MSG(C_CAN_MSG_OBJ_RX_LAST > 16, | |
"Implementation does not support more message objects than 16"); | |
while (quota > 0) { | |
1194: caffff45 bgt eb0 <c_can_poll+0x114> | |
1198: e51ba04c ldr sl, [fp, #-76] ; 0x4c | |
/* handle lec errors on the bus */ | |
work_done += c_can_handle_bus_err(dev, curr & LEC_MASK); | |
/* Handle Tx/Rx events. We do this unconditionally */ | |
work_done += c_can_do_rx_poll(dev, (quota - work_done)); | |
119c: e51b2054 ldr r2, [fp, #-84] ; 0x54 | |
{ | |
struct c_can_priv *priv = netdev_priv(dev); | |
struct net_device_stats *stats = &dev->stats; | |
u32 idx, obj, pkts = 0, bytes = 0, pend, clr; | |
clr = pend = priv->read_reg(priv, C_CAN_INTPND2_REG); | |
11a0: e1a00008 mov r0, r8 | |
11a4: e59435f4 ldr r3, [r4, #1524] ; 0x5f4 | |
11a8: e3a01023 mov r1, #35 ; 0x23 | |
static void c_can_do_tx(struct net_device *dev) | |
{ | |
struct c_can_priv *priv = netdev_priv(dev); | |
struct net_device_stats *stats = &dev->stats; | |
u32 idx, obj, pkts = 0, bytes = 0, pend, clr; | |
11ac: e3a09000 mov r9, #0 | |
clr = pend = priv->read_reg(priv, C_CAN_INTPND2_REG); | |
while ((idx = ffs(pend))) { | |
idx--; | |
pend &= ~(1 << idx); | |
11b0: e3a07001 mov r7, #1 | |
/* handle lec errors on the bus */ | |
work_done += c_can_handle_bus_err(dev, curr & LEC_MASK); | |
/* Handle Tx/Rx events. We do this unconditionally */ | |
work_done += c_can_do_rx_poll(dev, (quota - work_done)); | |
11b4: e082a00a add sl, r2, sl | |
11b8: e50ba03c str sl, [fp, #-60] ; 0x3c | |
static void c_can_do_tx(struct net_device *dev) | |
{ | |
struct c_can_priv *priv = netdev_priv(dev); | |
struct net_device_stats *stats = &dev->stats; | |
u32 idx, obj, pkts = 0, bytes = 0, pend, clr; | |
11bc: e1a0a009 mov sl, r9 | |
clr = pend = priv->read_reg(priv, C_CAN_INTPND2_REG); | |
11c0: e12fff33 blx r3 | |
11c4: e50b0038 str r0, [fp, #-56] ; 0x38 | |
11c8: e1a05000 mov r5, r0 | |
11cc: ea000007 b 11f0 <c_can_poll+0x454> | |
while ((idx = ffs(pend))) { | |
idx--; | |
pend &= ~(1 << idx); | |
obj = idx + C_CAN_MSG_OBJ_TX_FIRST; | |
c_can_inval_tx_object(dev, IF_RX, obj); | |
11d0: ebfffc0a bl 200 <c_can_inval_tx_object> | |
can_get_echo_skb(dev, idx); | |
11d4: e1a01006 mov r1, r6 | |
bytes += priv->dlc[idx]; | |
11d8: e0846106 add r6, r4, r6, lsl #2 | |
while ((idx = ffs(pend))) { | |
idx--; | |
pend &= ~(1 << idx); | |
obj = idx + C_CAN_MSG_OBJ_TX_FIRST; | |
c_can_inval_tx_object(dev, IF_RX, obj); | |
can_get_echo_skb(dev, idx); | |
11dc: e1a00004 mov r0, r4 | |
11e0: ebfffffe bl 0 <can_get_echo_skb> | |
bytes += priv->dlc[idx]; | |
11e4: e596362c ldr r3, [r6, #1580] ; 0x62c | |
pkts++; | |
11e8: e28aa001 add sl, sl, #1 | |
idx--; | |
pend &= ~(1 << idx); | |
obj = idx + C_CAN_MSG_OBJ_TX_FIRST; | |
c_can_inval_tx_object(dev, IF_RX, obj); | |
can_get_echo_skb(dev, idx); | |
bytes += priv->dlc[idx]; | |
11ec: e0899003 add r9, r9, r3 | |
* ffs() returns zero if the input was zero, otherwise returns the bit | |
* position of the first set bit, where the LSB is 1 and MSB is 32. | |
*/ | |
static inline int ffs(int x) | |
{ | |
return fls(x & -x); | |
11f0: e2653000 rsb r3, r5, #0 | |
while ((idx = ffs(pend))) { | |
idx--; | |
pend &= ~(1 << idx); | |
obj = idx + C_CAN_MSG_OBJ_TX_FIRST; | |
c_can_inval_tx_object(dev, IF_RX, obj); | |
11f4: e1a00004 mov r0, r4 | |
11f8: e0033005 and r3, r3, r5 | |
11fc: e3a01000 mov r1, #0 | |
*/ | |
static inline unsigned int __clz(unsigned int x) | |
{ | |
unsigned int ret; | |
asm("clz\t%0, %1" : "=r" (ret) : "r" (x)); | |
1200: e16f3f13 clz r3, r3 | |
struct net_device_stats *stats = &dev->stats; | |
u32 idx, obj, pkts = 0, bytes = 0, pend, clr; | |
clr = pend = priv->read_reg(priv, C_CAN_INTPND2_REG); | |
while ((idx = ffs(pend))) { | |
1204: e3530020 cmp r3, #32 | |
idx--; | |
1208: e263601f rsb r6, r3, #31 | |
pend &= ~(1 << idx); | |
obj = idx + C_CAN_MSG_OBJ_TX_FIRST; | |
c_can_inval_tx_object(dev, IF_RX, obj); | |
120c: e2632030 rsb r2, r3, #48 ; 0x30 | |
clr = pend = priv->read_reg(priv, C_CAN_INTPND2_REG); | |
while ((idx = ffs(pend))) { | |
idx--; | |
pend &= ~(1 << idx); | |
1210: e1c55617 bic r5, r5, r7, lsl r6 | |
struct net_device_stats *stats = &dev->stats; | |
u32 idx, obj, pkts = 0, bytes = 0, pend, clr; | |
clr = pend = priv->read_reg(priv, C_CAN_INTPND2_REG); | |
while ((idx = ffs(pend))) { | |
1214: 1affffed bne 11d0 <c_can_poll+0x434> | |
bytes += priv->dlc[idx]; | |
pkts++; | |
} | |
/* Clear the bits in the tx_active mask */ | |
atomic_sub(clr, &priv->tx_active); | |
1218: e2882f4a add r2, r8, #296 ; 0x128 | |
#if __LINUX_ARM_ARCH__ >= 7 && defined(CONFIG_SMP) | |
#define ARCH_HAS_PREFETCHW | |
static inline void prefetchw(const void *ptr) | |
{ | |
__asm__ __volatile__( | |
121c: f592f000 pldw [r2] | |
#define ATOMIC_OPS(op, c_op, asm_op) \ | |
ATOMIC_OP(op, c_op, asm_op) \ | |
ATOMIC_OP_RETURN(op, c_op, asm_op) | |
ATOMIC_OPS(add, +=, add) | |
ATOMIC_OPS(sub, -=, sub) | |
1220: e51b3038 ldr r3, [fp, #-56] ; 0x38 | |
1224: e1921f9f ldrex r1, [r2] | |
1228: e0411003 sub r1, r1, r3 | |
122c: e1820f91 strex r0, r1, [r2] | |
1230: e3300000 teq r0, #0 | |
1234: 1afffffa bne 1224 <c_can_poll+0x488> | |
if (clr & (1 << (C_CAN_MSG_OBJ_TX_NUM - 1))) | |
1238: e3130902 tst r3, #32768 ; 0x8000 | |
123c: 1a00005a bne 13ac <c_can_poll+0x610> | |
netif_wake_queue(dev); | |
if (pkts) { | |
1240: e35a0000 cmp sl, #0 | |
1244: 0a000005 beq 1260 <c_can_poll+0x4c4> | |
stats->tx_bytes += bytes; | |
1248: e59410cc ldr r1, [r4, #204] ; 0xcc | |
stats->tx_packets += pkts; | |
124c: e59420c4 ldr r2, [r4, #196] ; 0xc4 | |
if (clr & (1 << (C_CAN_MSG_OBJ_TX_NUM - 1))) | |
netif_wake_queue(dev); | |
if (pkts) { | |
stats->tx_bytes += bytes; | |
1250: e081c009 add ip, r1, r9 | |
stats->tx_packets += pkts; | |
1254: e082300a add r3, r2, sl | |
if (clr & (1 << (C_CAN_MSG_OBJ_TX_NUM - 1))) | |
netif_wake_queue(dev); | |
if (pkts) { | |
stats->tx_bytes += bytes; | |
1258: e584c0cc str ip, [r4, #204] ; 0xcc | |
stats->tx_packets += pkts; | |
125c: e58430c4 str r3, [r4, #196] ; 0xc4 | |
/* Handle Tx/Rx events. We do this unconditionally */ | |
work_done += c_can_do_rx_poll(dev, (quota - work_done)); | |
c_can_do_tx(dev); | |
end: | |
if (work_done < quota) { | |
1260: e51b303c ldr r3, [fp, #-60] ; 0x3c | |
1264: e51b0050 ldr r0, [fp, #-80] ; 0x50 | |
1268: e1530000 cmp r3, r0 | |
126c: ba00001b blt 12e0 <c_can_poll+0x544> | |
if (priv->can.state != CAN_STATE_BUS_OFF) | |
c_can_irq_control(priv, true); | |
} | |
return work_done; | |
} | |
1270: e51b003c ldr r0, [fp, #-60] ; 0x3c | |
1274: e24bd028 sub sp, fp, #40 ; 0x28 | |
1278: e89daff0 ldm sp, {r4, r5, r6, r7, r8, r9, sl, fp, sp, pc} | |
*/ | |
static u32 c_can_adjust_pending(u32 pend) | |
{ | |
u32 weight, lasts; | |
if (pend == RECEIVE_OBJECT_BITS) | |
127c: e51b5038 ldr r5, [fp, #-56] ; 0x38 | |
1280: e3a03000 mov r3, #0 | |
1284: e7df3815 bfi r3, r5, #16, #16 | |
1288: eaffff0d b ec4 <c_can_poll+0x128> | |
128c: e51b0038 ldr r0, [fp, #-56] ; 0x38 | |
1290: e1e03000 mvn r3, r0 | |
*/ | |
weight = hweight32(pend); | |
lasts = fls(pend); | |
/* If the bits are linear, nothing to do */ | |
if (lasts == weight) | |
1294: e1a05000 mov r5, r0 | |
1298: eaffff09 b ec4 <c_can_poll+0x128> | |
if ((curr & STATUS_EPASS) && (!(last & STATUS_EPASS))) { | |
netdev_dbg(dev, "entered error passive state\n"); | |
work_done += c_can_handle_state_change(dev, C_CAN_ERROR_PASSIVE); | |
} | |
if ((curr & STATUS_BOFF) && (!(last & STATUS_BOFF))) { | |
129c: e3170080 tst r7, #128 ; 0x80 | |
12a0: 1afffeea bne e50 <c_can_poll+0xb4> | |
netdev_dbg(dev, "entered bus off state\n"); | |
12a4: e3000000 movw r0, #0 | |
12a8: e3002000 movw r2, #0 | |
12ac: e3400000 movt r0, #0 | |
12b0: e3402000 movt r2, #0 | |
12b4: e1a01004 mov r1, r4 | |
12b8: ebfffffe bl 0 <netdev_printk> | |
work_done += c_can_handle_state_change(dev, C_CAN_BUS_OFF); | |
12bc: e1a00004 mov r0, r4 | |
12c0: e3a01001 mov r1, #1 | |
12c4: ebfffc1d bl 340 <c_can_handle_state_change> | |
12c8: e080a00a add sl, r0, sl | |
/* Handle Tx/Rx events. We do this unconditionally */ | |
work_done += c_can_do_rx_poll(dev, (quota - work_done)); | |
c_can_do_tx(dev); | |
end: | |
if (work_done < quota) { | |
12cc: e51b0050 ldr r0, [fp, #-80] ; 0x50 | |
work_done += c_can_handle_state_change(dev, C_CAN_ERROR_PASSIVE); | |
} | |
if ((curr & STATUS_BOFF) && (!(last & STATUS_BOFF))) { | |
netdev_dbg(dev, "entered bus off state\n"); | |
work_done += c_can_handle_state_change(dev, C_CAN_BUS_OFF); | |
12d0: e50ba03c str sl, [fp, #-60] ; 0x3c | |
/* Handle Tx/Rx events. We do this unconditionally */ | |
work_done += c_can_do_rx_poll(dev, (quota - work_done)); | |
c_can_do_tx(dev); | |
end: | |
if (work_done < quota) { | |
12d4: e51b303c ldr r3, [fp, #-60] ; 0x3c | |
12d8: e1530000 cmp r3, r0 | |
12dc: aaffffe3 bge 1270 <c_can_poll+0x4d4> | |
* Mark NAPI processing as complete. | |
* Consider using napi_complete_done() instead. | |
*/ | |
static inline void napi_complete(struct napi_struct *n) | |
{ | |
return napi_complete_done(n, 0); | |
12e0: e51b0058 ldr r0, [fp, #-88] ; 0x58 | |
12e4: e3a01000 mov r1, #0 | |
12e8: ebfffffe bl 0 <napi_complete_done> | |
napi_complete(napi); | |
/* enable all IRQs if we are not in bus off state */ | |
if (priv->can.state != CAN_STATE_BUS_OFF) | |
12ec: e5943524 ldr r3, [r4, #1316] ; 0x524 | |
12f0: e3530003 cmp r3, #3 | |
12f4: 0affffdd beq 1270 <c_can_poll+0x4d4> | |
c_can_irq_control(priv, true); | |
12f8: e1a00008 mov r0, r8 | |
12fc: e3a01001 mov r1, #1 | |
1300: ebfffb3e bl 0 <c_can_irq_control> | |
} | |
return work_done; | |
} | |
1304: e51b003c ldr r0, [fp, #-60] ; 0x3c | |
1308: e24bd028 sub sp, fp, #40 ; 0x28 | |
130c: e89daff0 ldm sp, {r4, r5, r6, r7, r8, r9, sl, fp, sp, pc} | |
/* handle bus recovery events */ | |
if ((!(curr & STATUS_BOFF)) && (last & STATUS_BOFF)) { | |
netdev_dbg(dev, "left bus off state\n"); | |
priv->can.state = CAN_STATE_ERROR_ACTIVE; | |
} | |
if ((!(curr & STATUS_EPASS)) && (last & STATUS_EPASS)) { | |
1310: e3170020 tst r7, #32 | |
1314: 0afffecf beq e58 <c_can_poll+0xbc> | |
netdev_dbg(dev, "left error passive state\n"); | |
1318: e3000000 movw r0, #0 | |
131c: e3002000 movw r2, #0 | |
1320: e3400000 movt r0, #0 | |
1324: e3402000 movt r2, #0 | |
1328: e1a01004 mov r1, r4 | |
132c: ebfffffe bl 0 <netdev_printk> | |
priv->can.state = CAN_STATE_ERROR_ACTIVE; | |
1330: e5846524 str r6, [r4, #1316] ; 0x524 | |
1334: eafffec7 b e58 <c_can_poll+0xbc> | |
if (!(priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)) | |
return 0; | |
/* common for all type of bus errors */ | |
priv->can.can_stats.bus_error++; | |
1338: e59424c0 ldr r2, [r4, #1216] ; 0x4c0 | |
stats->rx_errors++; | |
/* propagate the error condition to the CAN stack */ | |
skb = alloc_can_err_skb(dev, &cf); | |
133c: e1a00004 mov r0, r4 | |
if (!(priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)) | |
return 0; | |
/* common for all type of bus errors */ | |
priv->can.can_stats.bus_error++; | |
stats->rx_errors++; | |
1340: e59430d0 ldr r3, [r4, #208] ; 0xd0 | |
/* propagate the error condition to the CAN stack */ | |
skb = alloc_can_err_skb(dev, &cf); | |
1344: e24b1030 sub r1, fp, #48 ; 0x30 | |
if (!(priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)) | |
return 0; | |
/* common for all type of bus errors */ | |
priv->can.can_stats.bus_error++; | |
1348: e2822001 add r2, r2, #1 | |
stats->rx_errors++; | |
134c: e2833001 add r3, r3, #1 | |
if (!(priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)) | |
return 0; | |
/* common for all type of bus errors */ | |
priv->can.can_stats.bus_error++; | |
1350: e58424c0 str r2, [r4, #1216] ; 0x4c0 | |
stats->rx_errors++; | |
1354: e58430d0 str r3, [r4, #208] ; 0xd0 | |
/* propagate the error condition to the CAN stack */ | |
skb = alloc_can_err_skb(dev, &cf); | |
1358: ebfffffe bl 0 <alloc_can_err_skb> | |
if (unlikely(!skb)) | |
135c: e2506000 subs r6, r0, #0 | |
1360: 0afffec6 beq e80 <c_can_poll+0xe4> | |
/* | |
* check for 'last error code' which tells us the | |
* type of the last error to occur on the CAN bus | |
*/ | |
cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR; | |
1364: e51b3030 ldr r3, [fp, #-48] ; 0x30 | |
cf->data[2] |= CAN_ERR_PROT_UNSPEC; | |
switch (lec_type) { | |
1368: e2455001 sub r5, r5, #1 | |
/* | |
* check for 'last error code' which tells us the | |
* type of the last error to occur on the CAN bus | |
*/ | |
cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR; | |
136c: e5932000 ldr r2, [r3] | |
1370: e3822088 orr r2, r2, #136 ; 0x88 | |
1374: e5832000 str r2, [r3] | |
cf->data[2] |= CAN_ERR_PROT_UNSPEC; | |
switch (lec_type) { | |
1378: e3550005 cmp r5, #5 | |
137c: 979ff105 ldrls pc, [pc, r5, lsl #2] | |
1380: ea000081 b 158c <c_can_poll+0x7f0> | |
1384: 0000155c .word 0x0000155c | |
1388: 0000149c .word 0x0000149c | |
138c: 000014cc .word 0x000014cc | |
1390: 000014fc .word 0x000014fc | |
1394: 0000152c .word 0x0000152c | |
1398: 00001440 .word 0x00001440 | |
struct sk_buff *skb; | |
u32 arb, data; | |
skb = alloc_can_skb(dev, &frame); | |
if (!skb) { | |
stats->rx_dropped++; | |
139c: e59430d8 ldr r3, [r4, #216] ; 0xd8 | |
13a0: e2833001 add r3, r3, #1 | |
13a4: e58430d8 str r3, [r4, #216] ; 0xd8 | |
13a8: eaffff20 b 1030 <c_can_poll+0x294> | |
* Allow upper layers to call the device hard_start_xmit routine. | |
* Used for flow control when transmit resources are available. | |
*/ | |
static inline void netif_wake_queue(struct net_device *dev) | |
{ | |
netif_tx_wake_queue(netdev_get_tx_queue(dev, 0)); | |
13ac: e5940240 ldr r0, [r4, #576] ; 0x240 | |
13b0: ebfffffe bl 0 <netif_tx_wake_queue> | |
13b4: eaffffa1 b 1240 <c_can_poll+0x4a4> | |
netdev_dbg(dev, "entered error warning state\n"); | |
work_done += c_can_handle_state_change(dev, C_CAN_ERROR_WARNING); | |
} | |
if ((curr & STATUS_EPASS) && (!(last & STATUS_EPASS))) { | |
netdev_dbg(dev, "entered error passive state\n"); | |
13b8: e3000000 movw r0, #0 | |
13bc: e3002000 movw r2, #0 | |
13c0: e3400000 movt r0, #0 | |
13c4: e3402000 movt r2, #0 | |
13c8: e1a01004 mov r1, r4 | |
13cc: ebfffffe bl 0 <netdev_printk> | |
work_done += c_can_handle_state_change(dev, C_CAN_ERROR_PASSIVE); | |
13d0: e1a00004 mov r0, r4 | |
13d4: e3a01003 mov r1, #3 | |
13d8: ebfffbd8 bl 340 <c_can_handle_state_change> | |
13dc: e08aa000 add sl, sl, r0 | |
13e0: eafffe94 b e38 <c_can_poll+0x9c> | |
if (priv->type != BOSCH_D_CAN) | |
priv->write_reg(priv, C_CAN_STS_REG, LEC_UNUSED); | |
/* handle state changes */ | |
if ((curr & STATUS_EWARN) && (!(last & STATUS_EWARN))) { | |
netdev_dbg(dev, "entered error warning state\n"); | |
13e4: e3000000 movw r0, #0 | |
13e8: e3002000 movw r2, #0 | |
13ec: e3400000 movt r0, #0 | |
13f0: e3402000 movt r2, #0 | |
13f4: e1a01004 mov r1, r4 | |
13f8: ebfffffe bl 0 <netdev_printk> | |
work_done += c_can_handle_state_change(dev, C_CAN_ERROR_WARNING); | |
13fc: e1a00004 mov r0, r4 | |
1400: e3a01002 mov r1, #2 | |
1404: ebfffbcd bl 340 <c_can_handle_state_change> | |
1408: e1a0a000 mov sl, r0 | |
140c: eafffe83 b e20 <c_can_poll+0x84> | |
goto end; | |
} | |
/* handle bus recovery events */ | |
if ((!(curr & STATUS_BOFF)) && (last & STATUS_BOFF)) { | |
netdev_dbg(dev, "left bus off state\n"); | |
1410: e3000000 movw r0, #0 | |
1414: e3002000 movw r2, #0 | |
1418: e3400000 movt r0, #0 | |
141c: e3402000 movt r2, #0 | |
1420: e1a01004 mov r1, r4 | |
1424: ebfffffe bl 0 <netdev_printk> | |
priv->can.state = CAN_STATE_ERROR_ACTIVE; | |
} | |
if ((!(curr & STATUS_EPASS)) && (last & STATUS_EPASS)) { | |
1428: e3560000 cmp r6, #0 | |
} | |
/* handle bus recovery events */ | |
if ((!(curr & STATUS_BOFF)) && (last & STATUS_BOFF)) { | |
netdev_dbg(dev, "left bus off state\n"); | |
priv->can.state = CAN_STATE_ERROR_ACTIVE; | |
142c: e5849524 str r9, [r4, #1316] ; 0x524 | |
} | |
if ((!(curr & STATUS_EPASS)) && (last & STATUS_EPASS)) { | |
1430: 1afffe88 bne e58 <c_can_poll+0xbc> | |
1434: eaffffb5 b 1310 <c_can_poll+0x574> | |
* for a maximum number of 16 objects. | |
*/ | |
BUILD_BUG_ON_MSG(C_CAN_MSG_OBJ_RX_LAST > 16, | |
"Implementation does not support more message objects than 16"); | |
while (quota > 0) { | |
1438: e3a0a000 mov sl, #0 | |
143c: eaffff56 b 119c <c_can_poll+0x400> | |
case LEC_BIT0_ERROR: | |
netdev_dbg(dev, "bit0 error\n"); | |
cf->data[2] |= CAN_ERR_PROT_BIT0; | |
break; | |
case LEC_CRC_ERROR: | |
netdev_dbg(dev, "CRC error\n"); | |
1440: e3000000 movw r0, #0 | |
1444: e3002000 movw r2, #0 | |
1448: e3402000 movt r2, #0 | |
144c: e1a01004 mov r1, r4 | |
1450: e3400000 movt r0, #0 | |
1454: ebfffffe bl 0 <netdev_printk> | |
cf->data[3] |= (CAN_ERR_PROT_LOC_CRC_SEQ | | |
1458: e51b2030 ldr r2, [fp, #-48] ; 0x30 | |
145c: e5d2100b ldrb r1, [r2, #11] | |
1460: e1a03002 mov r3, r2 | |
1464: e3811018 orr r1, r1, #24 | |
1468: e5c2100b strb r1, [r2, #11] | |
break; | |
default: | |
break; | |
} | |
stats->rx_packets++; | |
146c: e59400c0 ldr r0, [r4, #192] ; 0xc0 | |
int netif_rx(struct sk_buff *skb); | |
int netif_rx_ni(struct sk_buff *skb); | |
int netif_receive_skb_sk(struct sock *sk, struct sk_buff *skb); | |
static inline int netif_receive_skb(struct sk_buff *skb) | |
{ | |
return netif_receive_skb_sk(skb->sk, skb); | |
1470: e1a01006 mov r1, r6 | |
stats->rx_bytes += cf->can_dlc; | |
1474: e59420c8 ldr r2, [r4, #200] ; 0xc8 | |
break; | |
default: | |
break; | |
} | |
stats->rx_packets++; | |
1478: e2800001 add r0, r0, #1 | |
147c: e58400c0 str r0, [r4, #192] ; 0xc0 | |
stats->rx_bytes += cf->can_dlc; | |
1480: e5d33004 ldrb r3, [r3, #4] | |
1484: e0823003 add r3, r2, r3 | |
1488: e58430c8 str r3, [r4, #200] ; 0xc8 | |
148c: e5960010 ldr r0, [r6, #16] | |
1490: ebfffffe bl 0 <netif_receive_skb_sk> | |
netif_receive_skb(skb); | |
return 1; | |
1494: e3a03001 mov r3, #1 | |
1498: eafffe79 b e84 <c_can_poll+0xe8> | |
case LEC_STUFF_ERROR: | |
netdev_dbg(dev, "stuff error\n"); | |
cf->data[2] |= CAN_ERR_PROT_STUFF; | |
break; | |
case LEC_FORM_ERROR: | |
netdev_dbg(dev, "form error\n"); | |
149c: e3000000 movw r0, #0 | |
14a0: e3002000 movw r2, #0 | |
14a4: e3402000 movt r2, #0 | |
14a8: e1a01004 mov r1, r4 | |
14ac: e3400000 movt r0, #0 | |
14b0: ebfffffe bl 0 <netdev_printk> | |
cf->data[2] |= CAN_ERR_PROT_FORM; | |
14b4: e51b2030 ldr r2, [fp, #-48] ; 0x30 | |
14b8: e5d2100a ldrb r1, [r2, #10] | |
14bc: e1a03002 mov r3, r2 | |
14c0: e3811002 orr r1, r1, #2 | |
14c4: e5c2100a strb r1, [r2, #10] | |
14c8: eaffffe7 b 146c <c_can_poll+0x6d0> | |
break; | |
case LEC_ACK_ERROR: | |
netdev_dbg(dev, "ack error\n"); | |
14cc: e3000000 movw r0, #0 | |
14d0: e3002000 movw r2, #0 | |
14d4: e3402000 movt r2, #0 | |
14d8: e1a01004 mov r1, r4 | |
14dc: e3400000 movt r0, #0 | |
14e0: ebfffffe bl 0 <netdev_printk> | |
cf->data[3] |= (CAN_ERR_PROT_LOC_ACK | | |
14e4: e51b2030 ldr r2, [fp, #-48] ; 0x30 | |
14e8: e5d2100b ldrb r1, [r2, #11] | |
14ec: e1a03002 mov r3, r2 | |
14f0: e381101b orr r1, r1, #27 | |
14f4: e5c2100b strb r1, [r2, #11] | |
14f8: eaffffdb b 146c <c_can_poll+0x6d0> | |
CAN_ERR_PROT_LOC_ACK_DEL); | |
break; | |
case LEC_BIT1_ERROR: | |
netdev_dbg(dev, "bit1 error\n"); | |
14fc: e3000000 movw r0, #0 | |
1500: e3002000 movw r2, #0 | |
1504: e3402000 movt r2, #0 | |
1508: e1a01004 mov r1, r4 | |
150c: e3400000 movt r0, #0 | |
1510: ebfffffe bl 0 <netdev_printk> | |
cf->data[2] |= CAN_ERR_PROT_BIT1; | |
1514: e51b2030 ldr r2, [fp, #-48] ; 0x30 | |
1518: e5d2100a ldrb r1, [r2, #10] | |
151c: e1a03002 mov r3, r2 | |
1520: e3811010 orr r1, r1, #16 | |
1524: e5c2100a strb r1, [r2, #10] | |
1528: eaffffcf b 146c <c_can_poll+0x6d0> | |
break; | |
case LEC_BIT0_ERROR: | |
netdev_dbg(dev, "bit0 error\n"); | |
152c: e3000000 movw r0, #0 | |
1530: e3002000 movw r2, #0 | |
1534: e3402000 movt r2, #0 | |
1538: e1a01004 mov r1, r4 | |
153c: e3400000 movt r0, #0 | |
1540: ebfffffe bl 0 <netdev_printk> | |
cf->data[2] |= CAN_ERR_PROT_BIT0; | |
1544: e51b2030 ldr r2, [fp, #-48] ; 0x30 | |
1548: e5d2100a ldrb r1, [r2, #10] | |
154c: e1a03002 mov r3, r2 | |
1550: e3811008 orr r1, r1, #8 | |
1554: e5c2100a strb r1, [r2, #10] | |
1558: eaffffc3 b 146c <c_can_poll+0x6d0> | |
cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR; | |
cf->data[2] |= CAN_ERR_PROT_UNSPEC; | |
switch (lec_type) { | |
case LEC_STUFF_ERROR: | |
netdev_dbg(dev, "stuff error\n"); | |
155c: e3000000 movw r0, #0 | |
1560: e3002000 movw r2, #0 | |
1564: e3402000 movt r2, #0 | |
1568: e1a01004 mov r1, r4 | |
156c: e3400000 movt r0, #0 | |
1570: ebfffffe bl 0 <netdev_printk> | |
cf->data[2] |= CAN_ERR_PROT_STUFF; | |
1574: e51b2030 ldr r2, [fp, #-48] ; 0x30 | |
1578: e5d2100a ldrb r1, [r2, #10] | |
157c: e1a03002 mov r3, r2 | |
1580: e3811004 orr r1, r1, #4 | |
1584: e5c2100a strb r1, [r2, #10] | |
1588: eaffffb7 b 146c <c_can_poll+0x6d0> | |
158c: e51b3030 ldr r3, [fp, #-48] ; 0x30 | |
1590: eaffffb5 b 146c <c_can_poll+0x6d0> | |
stats->rx_errors++; | |
stats->rx_over_errors++; | |
/* create an error msg */ | |
skb = alloc_can_err_skb(dev, &frame); | |
if (unlikely(!skb)) | |
1594: e1a03000 mov r3, r0 | |
return 0; | |
1598: e1a02000 mov r2, r0 | |
159c: eafffece b 10dc <c_can_poll+0x340> | |
000015a0 <c_can_start_xmit>: | |
c_can_object_put(dev, iface, obj, IF_COMM_RCV_SETUP); | |
} | |
static netdev_tx_t c_can_start_xmit(struct sk_buff *skb, | |
struct net_device *dev) | |
{ | |
15a0: e1a0c00d mov ip, sp | |
15a4: e92ddff0 push {r4, r5, r6, r7, r8, r9, sl, fp, ip, lr, pc} | |
15a8: e24cb004 sub fp, ip, #4 | |
15ac: e24dd00c sub sp, sp, #12 | |
15b0: e52de004 push {lr} ; (str lr, [sp, #-4]!) | |
15b4: ebfffffe bl 0 <__gnu_mcount_nc> | |
static inline int can_dropped_invalid_skb(struct net_device *dev, | |
struct sk_buff *skb) | |
{ | |
const struct canfd_frame *cfd = (struct canfd_frame *)skb->data; | |
if (skb->protocol == htons(ETH_P_CAN)) { | |
15b8: e1d038bc ldrh r3, [r0, #140] ; 0x8c | |
15bc: e1a09000 mov r9, r0 | |
15c0: e1a04001 mov r4, r1 | |
struct can_frame *frame = (struct can_frame *)skb->data; | |
15c4: e59060a0 ldr r6, [r0, #160] ; 0xa0 | |
15c8: e3530b03 cmp r3, #3072 ; 0xc00 | |
15cc: 0a000009 beq 15f8 <c_can_start_xmit+0x58> | |
if (unlikely(skb->len != CAN_MTU || | |
cfd->len > CAN_MAX_DLEN)) | |
goto inval_skb; | |
} else if (skb->protocol == htons(ETH_P_CANFD)) { | |
15d0: e3530c0d cmp r3, #3328 ; 0xd00 | |
15d4: 0a000068 beq 177c <c_can_start_xmit+0x1dc> | |
goto inval_skb; | |
return 0; | |
inval_skb: | |
kfree_skb(skb); | |
15d8: e1a00009 mov r0, r9 | |
15dc: ebfffffe bl 0 <kfree_skb> | |
dev->stats.tx_dropped++; | |
15e0: e59430dc ldr r3, [r4, #220] ; 0xdc | |
atomic_add((1 << idx), &priv->tx_active); | |
/* Start transmission */ | |
c_can_object_put(dev, IF_TX, obj, IF_COMM_TX); | |
return NETDEV_TX_OK; | |
} | |
15e4: e3a00000 mov r0, #0 | |
15e8: e2833001 add r3, r3, #1 | |
15ec: e58430dc str r3, [r4, #220] ; 0xdc | |
15f0: e24bd028 sub sp, fp, #40 ; 0x28 | |
15f4: e89daff0 ldm sp, {r4, r5, r6, r7, r8, r9, sl, fp, sp, pc} | |
struct sk_buff *skb) | |
{ | |
const struct canfd_frame *cfd = (struct canfd_frame *)skb->data; | |
if (skb->protocol == htons(ETH_P_CAN)) { | |
if (unlikely(skb->len != CAN_MTU || | |
15f8: e5903054 ldr r3, [r0, #84] ; 0x54 | |
15fc: e3530010 cmp r3, #16 | |
1600: 1afffff4 bne 15d8 <c_can_start_xmit+0x38> | |
1604: e5d63004 ldrb r3, [r6, #4] | |
1608: e3530008 cmp r3, #8 | |
160c: 8afffff1 bhi 15d8 <c_can_start_xmit+0x38> | |
return NETDEV_TX_OK; | |
/* | |
* This is not a FIFO. C/D_CAN sends out the buffers | |
* prioritized. The lowest buffer number wins. | |
*/ | |
idx = fls(atomic_read(&priv->tx_active)); | |
1610: e594a5e8 ldr sl, [r4, #1512] ; 0x5e8 | |
1614: e16faf1a clz sl, sl | |
static inline int fls(int x) | |
{ | |
if (__builtin_constant_p(x)) | |
return constant_fls(x); | |
return 32 - __clz(x); | |
1618: e26a7020 rsb r7, sl, #32 | |
obj = idx + C_CAN_MSG_OBJ_TX_FIRST; | |
161c: e26aa031 rsb sl, sl, #49 ; 0x31 | |
/* If this is the last buffer, stop the xmit queue */ | |
if (idx == C_CAN_MSG_OBJ_TX_NUM - 1) | |
1620: e357000f cmp r7, #15 | |
/* | |
* This is not a FIFO. C/D_CAN sends out the buffers | |
* prioritized. The lowest buffer number wins. | |
*/ | |
idx = fls(atomic_read(&priv->tx_active)); | |
obj = idx + C_CAN_MSG_OBJ_TX_FIRST; | |
1624: e50ba030 str sl, [fp, #-48] ; 0x30 | |
/* If this is the last buffer, stop the xmit queue */ | |
if (idx == C_CAN_MSG_OBJ_TX_NUM - 1) | |
1628: 0a00005a beq 1798 <c_can_start_xmit+0x1f8> | |
static void c_can_setup_tx_object(struct net_device *dev, int iface, | |
struct can_frame *frame, int idx) | |
{ | |
struct c_can_priv *priv = netdev_priv(dev); | |
u16 ctrl = IF_MCONT_TX | frame->can_dlc; | |
bool rtr = frame->can_id & CAN_RTR_FLAG; | |
162c: e5963000 ldr r3, [r6] | |
1630: e287001f add r0, r7, #31 | |
} | |
static void c_can_setup_tx_object(struct net_device *dev, int iface, | |
struct can_frame *frame, int idx) | |
{ | |
struct c_can_priv *priv = netdev_priv(dev); | |
1634: e2848d13 add r8, r4, #1216 ; 0x4c0 | |
1638: e207101f and r1, r7, #31 | |
/* | |
* If we change the DIR bit, we need to invalidate the buffer | |
* first, i.e. clear the MSGVAL flag in the arbiter. | |
*/ | |
if (rtr != (bool)test_bit(idx, &priv->tx_dir)) { | |
163c: e288cf4b add ip, r8, #300 ; 0x12c | |
static void c_can_setup_tx_object(struct net_device *dev, int iface, | |
struct can_frame *frame, int idx) | |
{ | |
struct c_can_priv *priv = netdev_priv(dev); | |
u16 ctrl = IF_MCONT_TX | frame->can_dlc; | |
1640: e5d65004 ldrb r5, [r6, #4] | |
bool rtr = frame->can_id & CAN_RTR_FLAG; | |
u32 arb = IF_ARB_MSGVAL; | |
int i; | |
if (frame->can_id & CAN_EFF_FLAG) { | |
1644: e3530000 cmp r3, #0 | |
static void c_can_setup_tx_object(struct net_device *dev, int iface, | |
struct can_frame *frame, int idx) | |
{ | |
struct c_can_priv *priv = netdev_priv(dev); | |
u16 ctrl = IF_MCONT_TX | frame->can_dlc; | |
bool rtr = frame->can_id & CAN_RTR_FLAG; | |
1648: e7e02f53 ubfx r2, r3, #30, #1 | |
if (frame->can_id & CAN_EFF_FLAG) { | |
arb |= frame->can_id & CAN_EFF_MASK; | |
arb |= IF_ARB_MSGXTD; | |
} else { | |
arb |= (frame->can_id & CAN_SFF_MASK) << 18; | |
164c: a7ea3053 ubfxge r3, r3, #0, #11 | |
bool rtr = frame->can_id & CAN_RTR_FLAG; | |
u32 arb = IF_ARB_MSGVAL; | |
int i; | |
if (frame->can_id & CAN_EFF_FLAG) { | |
arb |= frame->can_id & CAN_EFF_MASK; | |
1650: b3c3320e biclt r3, r3, #-536870912 ; 0xe0000000 | |
arb |= IF_ARB_MSGXTD; | |
} else { | |
arb |= (frame->can_id & CAN_SFF_MASK) << 18; | |
1654: a1a03903 lslge r3, r3, #18 | |
u32 arb = IF_ARB_MSGVAL; | |
int i; | |
if (frame->can_id & CAN_EFF_FLAG) { | |
arb |= frame->can_id & CAN_EFF_MASK; | |
arb |= IF_ARB_MSGXTD; | |
1658: b383a103 orrlt sl, r3, #-1073741824 ; 0xc0000000 | |
static void c_can_setup_tx_object(struct net_device *dev, int iface, | |
struct can_frame *frame, int idx) | |
{ | |
struct c_can_priv *priv = netdev_priv(dev); | |
u16 ctrl = IF_MCONT_TX | frame->can_dlc; | |
165c: e3855d22 orr r5, r5, #2176 ; 0x880 | |
if (frame->can_id & CAN_EFF_FLAG) { | |
arb |= frame->can_id & CAN_EFF_MASK; | |
arb |= IF_ARB_MSGXTD; | |
} else { | |
arb |= (frame->can_id & CAN_SFF_MASK) << 18; | |
1660: a383a102 orrge sl, r3, #-2147483648 ; 0x80000000 | |
} | |
if (!rtr) | |
1664: e3520000 cmp r2, #0 | |
arb |= IF_ARB_TRANSMIT; | |
1668: 038aa202 orreq sl, sl, #536870912 ; 0x20000000 | |
166c: e3570000 cmp r7, #0 | |
1670: a1a00007 movge r0, r7 | |
1674: e1a002c0 asr r0, r0, #5 | |
1678: e79c0100 ldr r0, [ip, r0, lsl #2] | |
167c: e1a01130 lsr r1, r0, r1 | |
1680: e2011001 and r1, r1, #1 | |
/* | |
* If we change the DIR bit, we need to invalidate the buffer | |
* first, i.e. clear the MSGVAL flag in the arbiter. | |
*/ | |
if (rtr != (bool)test_bit(idx, &priv->tx_dir)) { | |
1684: e1520001 cmp r2, r1 | |
1688: 0a000008 beq 16b0 <c_can_start_xmit+0x110> | |
u32 obj = idx + C_CAN_MSG_OBJ_TX_FIRST; | |
c_can_inval_msg_object(dev, iface, obj); | |
168c: e1a00004 mov r0, r4 | |
1690: e3a01001 mov r1, #1 | |
1694: e2872011 add r2, r7, #17 | |
1698: e50bc034 str ip, [fp, #-52] ; 0x34 | |
169c: ebfffaec bl 254 <c_can_inval_msg_object> | |
change_bit(idx, &priv->tx_dir); | |
16a0: e51bc034 ldr ip, [fp, #-52] ; 0x34 | |
16a4: e1a00007 mov r0, r7 | |
16a8: e1a0100c mov r1, ip | |
16ac: ebfffffe bl 0 <_change_bit> | |
} | |
priv->write_reg32(priv, C_CAN_IFACE(ARB1_REG, iface), arb); | |
16b0: e1a0200a mov r2, sl | |
16b4: e5943600 ldr r3, [r4, #1536] ; 0x600 | |
16b8: e1a00008 mov r0, r8 | |
16bc: e3a01017 mov r1, #23 | |
16c0: e12fff33 blx r3 | |
priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), ctrl); | |
16c4: e1a02005 mov r2, r5 | |
16c8: e59435f8 ldr r3, [r4, #1528] ; 0x5f8 | |
16cc: e1a00008 mov r0, r8 | |
16d0: e3a01019 mov r1, #25 | |
16d4: e12fff33 blx r3 | |
for (i = 0; i < frame->can_dlc; i += 2) { | |
16d8: e5d62004 ldrb r2, [r6, #4] | |
16dc: e3520000 cmp r2, #0 | |
16e0: 0a00000e beq 1720 <c_can_start_xmit+0x180> | |
16e4: e1a0a006 mov sl, r6 | |
16e8: e3a05000 mov r5, #0 | |
priv->write_reg(priv, C_CAN_IFACE(DATA1_REG, iface) + i / 2, | |
frame->data[i] | (frame->data[i + 1] << 8)); | |
16ec: e5dae009 ldrb lr, [sl, #9] | |
priv->write_reg32(priv, C_CAN_IFACE(ARB1_REG, iface), arb); | |
priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), ctrl); | |
for (i = 0; i < frame->can_dlc; i += 2) { | |
priv->write_reg(priv, C_CAN_IFACE(DATA1_REG, iface) + i / 2, | |
16f0: e1a010c5 asr r1, r5, #1 | |
16f4: e5da2008 ldrb r2, [sl, #8] | |
16f8: e1a00008 mov r0, r8 | |
16fc: e281101a add r1, r1, #26 | |
1700: e594c5f8 ldr ip, [r4, #1528] ; 0x5f8 | |
priv->write_reg32(priv, C_CAN_IFACE(ARB1_REG, iface), arb); | |
priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), ctrl); | |
for (i = 0; i < frame->can_dlc; i += 2) { | |
1704: e2855002 add r5, r5, #2 | |
1708: e28aa002 add sl, sl, #2 | |
priv->write_reg(priv, C_CAN_IFACE(DATA1_REG, iface) + i / 2, | |
170c: e182240e orr r2, r2, lr, lsl #8 | |
1710: e12fff3c blx ip | |
priv->write_reg32(priv, C_CAN_IFACE(ARB1_REG, iface), arb); | |
priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), ctrl); | |
for (i = 0; i < frame->can_dlc; i += 2) { | |
1714: e5d62004 ldrb r2, [r6, #4] | |
1718: e1550002 cmp r5, r2 | |
171c: bafffff2 blt 16ec <c_can_start_xmit+0x14c> | |
* Store the message in the interface so we can call | |
* can_put_echo_skb(). We must do this before we enable | |
* transmit as we might race against do_tx(). | |
*/ | |
c_can_setup_tx_object(dev, IF_TX, frame, idx); | |
priv->dlc[idx] = frame->can_dlc; | |
1720: e0843107 add r3, r4, r7, lsl #2 | |
can_put_echo_skb(skb, dev, idx); | |
1724: e1a00009 mov r0, r9 | |
1728: e1a01004 mov r1, r4 | |
* Store the message in the interface so we can call | |
* can_put_echo_skb(). We must do this before we enable | |
* transmit as we might race against do_tx(). | |
*/ | |
c_can_setup_tx_object(dev, IF_TX, frame, idx); | |
priv->dlc[idx] = frame->can_dlc; | |
172c: e583262c str r2, [r3, #1580] ; 0x62c | |
can_put_echo_skb(skb, dev, idx); | |
1730: e1a02007 mov r2, r7 | |
1734: ebfffffe bl 0 <can_put_echo_skb> | |
/* Update the active bits */ | |
atomic_add((1 << idx), &priv->tx_active); | |
1738: e2888f4a add r8, r8, #296 ; 0x128 | |
173c: f598f000 pldw [r8] | |
1740: e3a03001 mov r3, #1 | |
1744: e1a07713 lsl r7, r3, r7 | |
#define ATOMIC_OPS(op, c_op, asm_op) \ | |
ATOMIC_OP(op, c_op, asm_op) \ | |
ATOMIC_OP_RETURN(op, c_op, asm_op) | |
ATOMIC_OPS(add, +=, add) | |
1748: e1983f9f ldrex r3, [r8] | |
174c: e0833007 add r3, r3, r7 | |
1750: e1882f93 strex r2, r3, [r8] | |
1754: e3320000 teq r2, #0 | |
1758: 1afffffa bne 1748 <c_can_start_xmit+0x1a8> | |
} | |
static inline void c_can_object_put(struct net_device *dev, int iface, | |
u32 obj, u32 cmd) | |
{ | |
c_can_obj_update(dev, iface, cmd | IF_COMM_WR, obj); | |
175c: e3a01001 mov r1, #1 | |
1760: e1a00004 mov r0, r4 | |
1764: e51b3030 ldr r3, [fp, #-48] ; 0x30 | |
1768: e3a020b7 mov r2, #183 ; 0xb7 | |
176c: ebfffa80 bl 174 <c_can_obj_update> | |
atomic_add((1 << idx), &priv->tx_active); | |
/* Start transmission */ | |
c_can_object_put(dev, IF_TX, obj, IF_COMM_TX); | |
return NETDEV_TX_OK; | |
} | |
1770: e3a00000 mov r0, #0 | |
1774: e24bd028 sub sp, fp, #40 ; 0x28 | |
1778: e89daff0 ldm sp, {r4, r5, r6, r7, r8, r9, sl, fp, sp, pc} | |
cfd->len > CAN_MAX_DLEN)) | |
goto inval_skb; | |
} else if (skb->protocol == htons(ETH_P_CANFD)) { | |
if (unlikely(skb->len != CANFD_MTU || | |
177c: e5903054 ldr r3, [r0, #84] ; 0x54 | |
1780: e3530048 cmp r3, #72 ; 0x48 | |
1784: 1affff93 bne 15d8 <c_can_start_xmit+0x38> | |
1788: e5d63004 ldrb r3, [r6, #4] | |
178c: e3530040 cmp r3, #64 ; 0x40 | |
1790: 9affff9e bls 1610 <c_can_start_xmit+0x70> | |
1794: eaffff8f b 15d8 <c_can_start_xmit+0x38> | |
} | |
} | |
static inline void netif_tx_stop_queue(struct netdev_queue *dev_queue) | |
{ | |
set_bit(__QUEUE_STATE_DRV_XOFF, &dev_queue->state); | |
1798: e5941240 ldr r1, [r4, #576] ; 0x240 | |
179c: e3a00000 mov r0, #0 | |
17a0: e2811050 add r1, r1, #80 ; 0x50 | |
17a4: ebfffffe bl 0 <_set_bit> | |
17a8: eaffff9f b 162c <c_can_start_xmit+0x8c> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment