|
54 | 54 | #include <linux/kernel.h> |
55 | 55 | #include <linux/workqueue.h> |
56 | 56 | #include <linux/can.h> |
| 57 | +#include <linux/can/dev.h> |
57 | 58 | #include <linux/can/skb.h> |
58 | 59 | #include <linux/can/can-ml.h> |
59 | 60 |
|
@@ -143,85 +144,80 @@ static struct net_device **slcan_devs; |
143 | 144 | static void slc_bump(struct slcan *sl) |
144 | 145 | { |
145 | 146 | struct sk_buff *skb; |
146 | | - struct can_frame cf; |
| 147 | + struct can_frame *cf; |
147 | 148 | int i, tmp; |
148 | 149 | u32 tmpid; |
149 | 150 | char *cmd = sl->rbuff; |
150 | 151 |
|
151 | | - memset(&cf, 0, sizeof(cf)); |
| 152 | + skb = alloc_can_skb(sl->dev, &cf); |
| 153 | + if (unlikely(!skb)) { |
| 154 | + sl->dev->stats.rx_dropped++; |
| 155 | + return; |
| 156 | + } |
152 | 157 |
|
153 | 158 | switch (*cmd) { |
154 | 159 | case 'r': |
155 | | - cf.can_id = CAN_RTR_FLAG; |
| 160 | + cf->can_id = CAN_RTR_FLAG; |
156 | 161 | fallthrough; |
157 | 162 | case 't': |
158 | 163 | /* store dlc ASCII value and terminate SFF CAN ID string */ |
159 | | - cf.len = sl->rbuff[SLC_CMD_LEN + SLC_SFF_ID_LEN]; |
| 164 | + cf->len = sl->rbuff[SLC_CMD_LEN + SLC_SFF_ID_LEN]; |
160 | 165 | sl->rbuff[SLC_CMD_LEN + SLC_SFF_ID_LEN] = 0; |
161 | 166 | /* point to payload data behind the dlc */ |
162 | 167 | cmd += SLC_CMD_LEN + SLC_SFF_ID_LEN + 1; |
163 | 168 | break; |
164 | 169 | case 'R': |
165 | | - cf.can_id = CAN_RTR_FLAG; |
| 170 | + cf->can_id = CAN_RTR_FLAG; |
166 | 171 | fallthrough; |
167 | 172 | case 'T': |
168 | | - cf.can_id |= CAN_EFF_FLAG; |
| 173 | + cf->can_id |= CAN_EFF_FLAG; |
169 | 174 | /* store dlc ASCII value and terminate EFF CAN ID string */ |
170 | | - cf.len = sl->rbuff[SLC_CMD_LEN + SLC_EFF_ID_LEN]; |
| 175 | + cf->len = sl->rbuff[SLC_CMD_LEN + SLC_EFF_ID_LEN]; |
171 | 176 | sl->rbuff[SLC_CMD_LEN + SLC_EFF_ID_LEN] = 0; |
172 | 177 | /* point to payload data behind the dlc */ |
173 | 178 | cmd += SLC_CMD_LEN + SLC_EFF_ID_LEN + 1; |
174 | 179 | break; |
175 | 180 | default: |
176 | | - return; |
| 181 | + goto decode_failed; |
177 | 182 | } |
178 | 183 |
|
179 | 184 | if (kstrtou32(sl->rbuff + SLC_CMD_LEN, 16, &tmpid)) |
180 | | - return; |
| 185 | + goto decode_failed; |
181 | 186 |
|
182 | | - cf.can_id |= tmpid; |
| 187 | + cf->can_id |= tmpid; |
183 | 188 |
|
184 | 189 | /* get len from sanitized ASCII value */ |
185 | | - if (cf.len >= '0' && cf.len < '9') |
186 | | - cf.len -= '0'; |
| 190 | + if (cf->len >= '0' && cf->len < '9') |
| 191 | + cf->len -= '0'; |
187 | 192 | else |
188 | | - return; |
| 193 | + goto decode_failed; |
189 | 194 |
|
190 | 195 | /* RTR frames may have a dlc > 0 but they never have any data bytes */ |
191 | | - if (!(cf.can_id & CAN_RTR_FLAG)) { |
192 | | - for (i = 0; i < cf.len; i++) { |
| 196 | + if (!(cf->can_id & CAN_RTR_FLAG)) { |
| 197 | + for (i = 0; i < cf->len; i++) { |
193 | 198 | tmp = hex_to_bin(*cmd++); |
194 | 199 | if (tmp < 0) |
195 | | - return; |
196 | | - cf.data[i] = (tmp << 4); |
| 200 | + goto decode_failed; |
| 201 | + |
| 202 | + cf->data[i] = (tmp << 4); |
197 | 203 | tmp = hex_to_bin(*cmd++); |
198 | 204 | if (tmp < 0) |
199 | | - return; |
200 | | - cf.data[i] |= tmp; |
| 205 | + goto decode_failed; |
| 206 | + |
| 207 | + cf->data[i] |= tmp; |
201 | 208 | } |
202 | 209 | } |
203 | 210 |
|
204 | | - skb = dev_alloc_skb(sizeof(struct can_frame) + |
205 | | - sizeof(struct can_skb_priv)); |
206 | | - if (!skb) |
207 | | - return; |
208 | | - |
209 | | - skb->dev = sl->dev; |
210 | | - skb->protocol = htons(ETH_P_CAN); |
211 | | - skb->pkt_type = PACKET_BROADCAST; |
212 | | - skb->ip_summed = CHECKSUM_UNNECESSARY; |
213 | | - |
214 | | - can_skb_reserve(skb); |
215 | | - can_skb_prv(skb)->ifindex = sl->dev->ifindex; |
216 | | - can_skb_prv(skb)->skbcnt = 0; |
217 | | - |
218 | | - skb_put_data(skb, &cf, sizeof(struct can_frame)); |
219 | | - |
220 | 211 | sl->dev->stats.rx_packets++; |
221 | | - if (!(cf.can_id & CAN_RTR_FLAG)) |
222 | | - sl->dev->stats.rx_bytes += cf.len; |
| 212 | + if (!(cf->can_id & CAN_RTR_FLAG)) |
| 213 | + sl->dev->stats.rx_bytes += cf->len; |
223 | 214 |
|
224 | 215 | netif_rx(skb); |
| 216 | + return; |
| 217 | + |
| 218 | +decode_failed: |
| 219 | + sl->dev->stats.rx_errors++; |
| 220 | + dev_kfree_skb(skb); |
225 | 221 | } |
226 | 222 |
|
227 | 223 | /* parse tty input stream */ |
|
0 commit comments