]> rtime.felk.cvut.cz Git - frescor/fna.git/blob - src_frescan/frescan.c
acquire lock when allocating memory.. (TODO: check tlsf to provide locking) and add...
[frescor/fna.git] / src_frescan / frescan.c
1 /*!
2  * @file frescan.c
3  *
4  * @brief the FRESCAN protocol
5  *
6  * @version 0.01
7  *
8  * @date 20-Feb-2008
9  *
10  * @author
11  *      Daniel Sangorrin
12  *
13  * @comments
14  *
15  * This file contains the implementation of the FRESCAN protocol
16  *
17  * @license
18  *
19  * -----------------------------------------------------------------------
20  *  Copyright (C) 2006 - 2008 FRESCOR consortium partners:
21  *
22  *    Universidad de Cantabria,              SPAIN
23  *    University of York,                    UK
24  *    Scuola Superiore Sant'Anna,            ITALY
25  *    Kaiserslautern University,             GERMANY
26  *    Univ. Politécnica  Valencia,           SPAIN
27  *    Czech Technical University in Prague,  CZECH REPUBLIC
28  *    ENEA                                   SWEDEN
29  *    Thales Communication S.A.              FRANCE
30  *    Visual Tools S.A.                      SPAIN
31  *    Rapita Systems Ltd                     UK
32  *    Evidence                               ITALY
33  *
34  *    See http://www.frescor.org for a link to partners' websites
35  *
36  *           FRESCOR project (FP6/2005/IST/5-034026) is funded
37  *        in part by the European Union Sixth Framework Programme
38  *        The European Union is not liable of any use that may be
39  *        made of this code.
40  *
41  *  This file is part of FRESCAN
42  *
43  *  FRESCAN is free software; you can  redistribute it and/or  modify
44  *  it under the terms of  the GNU General Public License as published by
45  *  the Free Software Foundation;  either  version 2, or (at  your option)
46  *  any later version.
47  *
48  *  FRESCAN  is distributed  in  the hope  that  it  will  be useful,  but
49  *  WITHOUT  ANY  WARRANTY;     without  even the   implied   warranty  of
50  *  MERCHANTABILITY  or  FITNESS FOR  A  PARTICULAR PURPOSE. See  the  GNU
51  *  General Public License for more details.
52  *
53  *  You should have  received a  copy of  the  GNU  General Public License
54  *  distributed  with  FRESCAN;  see file COPYING.   If not,  write to the
55  *  Free Software  Foundation,  59 Temple Place  -  Suite 330,  Boston, MA
56  *  02111-1307, USA.
57  *
58  * As a special exception, including FRESCAN header files in a file,
59  * instantiating FRESCAN generics or templates, or linking other files
60  * with FRESCAN objects to produce an executable application, does not
61  * by itself cause the resulting executable application to be covered
62  * by the GNU General Public License. This exception does not
63  * however invalidate any other reasons why the executable file might be
64  * covered by the GNU Public License.
65  * -----------------------------------------------------------------------
66  *
67  */
68
69 #include <sys/marte_configuration_parameters.h> // PATH_MX
70 #include <fcntl.h>  // open
71 #include <unistd.h> // ioctl
72 #include <stdlib.h> // malloc
73 #include <string.h> // memcpy
74 #include <assert.h>
75
76 #include <drivers/can.h>       // can_chip_t, can_frame_t
77 #include "frescan.h"           // frescan_init_params_t, frescan_send_params_t
78 #include "frescan_queues.h"    // init, enqueue, requeue
79 #include "frescan_data.h"      // init, frescan_data
80 #include "frescan_servers.h"   // init, frame_sent
81 #include "frescan_debug.h"     // DEBUG
82 #include "frescan_id.h"        // frescan_id_set_field, frescan_id_get_field
83 #include "frescan_hw_buffer.h" // frescan_hw_buffer_update
84 #include "frescan_packets.h"
85
86 static int frescan_hook_frame_recv (const struct can_chip_t *chip,
87                                     struct can_frame_t *frame);
88
89 static int frescan_hook_frame_sent(const struct can_chip_t *chip);
90
91 static int frescan_hook_frame_aborted(const struct can_chip_t *chip);
92
93 /**
94  * frescan_init - initializes the network and the internal structures
95  *
96  * @params: the initialization parameters
97  *
98  * This function initializes the frescan network protocol.
99  *
100  * First it opens and configures the corresponding CAN chip device. For the
101  * CAN chip acceptance filter we use a dual filter configuration. The first
102  * filter is to set my local address address and the second one is to allow
103  * broadcast messages.
104  *
105  * Once the CAN chip is configured we call the initialization functions of
106  * the rest of modules of frescan.
107  *
108  */
109
110 int frescan_init(frescan_init_params_t *params)
111 {
112         int fd, ret;
113         char can_path[PATH_MX];
114         struct ioctl_filters_t ioctl_filters;
115         struct can_filter_t filters[2];
116
117         snprintf(can_path, PATH_MX, "/dev/can%u", params->net);
118
119         DEBUG(FRESCAN_INIT_ENABLE_DEBUG, "open %s\n", can_path);
120
121         fd = open (can_path, O_RDWR);
122         if (fd == -1) {
123                 FRESCAN_ERROR ("could not open /dev/can%u\n", params->net);
124                 return -1;
125         }
126
127         DEBUG(FRESCAN_INIT_ENABLE_DEBUG, "set acceptance filters\n");
128
129         filters[0].mask = 0xFFFFFFFF;
130         frescan_id_set_field(&filters[0].mask, FRESCAN_FIELD_DEST,0x00);
131         filters[0].code = 0;
132         frescan_id_set_field(&filters[0].code, FRESCAN_FIELD_DEST,params->node);
133
134         filters[1].mask = filters[0].mask;
135         filters[1].code = 0;
136         frescan_id_set_field(&filters[1].code,
137                              FRESCAN_FIELD_DEST,
138                              FRESCAN_BROADCAST_ADDR);
139
140         ioctl_filters.filters = filters;
141         ioctl_filters.len = 2;
142
143         ret = ioctl(fd, CAN_IOCTL_SET_FILTERS, &ioctl_filters);
144         if (ret == -1) {
145                 FRESCAN_ERROR ("ioctl CAN_IOCTL_SET_FILTERS failed /dev/can%u\n",
146                        params->net);
147                 return -1;
148         }
149
150         DEBUG(FRESCAN_INIT_ENABLE_DEBUG, "set tx, rx, abort hooks\n");
151
152         ret = ioctl(fd, CAN_IOCTL_SET_TX_HOOK, frescan_hook_frame_sent);
153         if (ret == -1) {
154                 FRESCAN_ERROR ("ioctl CAN_IOCTL_SET_TX_HOOK failed /dev/can%u\n",
155                        params->net);
156                 return -1;
157         }
158
159         ret = ioctl(fd, CAN_IOCTL_SET_RX_HOOK, frescan_hook_frame_recv);
160         if (ret == -1) {
161                 FRESCAN_ERROR ("ioctl CAN_IOCTL_SET_RX_HOOK failed /dev/can%u\n",
162                        params->net);
163                 return -1;
164         }
165
166         ret = ioctl(fd, CAN_IOCTL_SET_AB_HOOK, frescan_hook_frame_aborted);
167         if (ret == -1) {
168                 FRESCAN_ERROR ("ioctl CAN_IOCTL_SET_AB_HOOK failed /dev/can%u\n",
169                        params->net);
170                 return -1;
171         }
172
173         DEBUG(FRESCAN_INIT_ENABLE_DEBUG, "init the rest of modules\n");
174
175         ret = frescan_data_init(fd, params);
176         if (ret != 0) {
177                 FRESCAN_ERROR("could not initialize the global data\n");
178                 return -1;
179         }
180
181         ret = frescan_packets_init();
182         if (ret != 0) {
183                 FRESCAN_ERROR("could not initialize the packets pool\n");
184                 return -1;
185         }
186
187         ret = frescan_queues_init(&frescan_data[params->net].queues, params);
188         if (ret != 0) {
189                 FRESCAN_ERROR("could not initialize the queues\n");
190                 return -1;
191         }
192
193         ret = frescan_servers_init(params->net);
194         if (ret != 0) {
195                 FRESCAN_ERROR("could not initialize the servers\n");
196                 return -1;
197         }
198
199         return 0;
200 }
201
202 /**
203  * frescan_send - send a message
204  *
205  * @params: the parameters needed by the protocol to send the message
206  * @msg: the message buffer
207  * @size: the size of the message
208  *
209  * This is one of the main functions of the protocol and it provides the
210  * means to send a message through the protocol stack.
211  */
212
213 int frescan_send(const frescan_send_params_t *params,
214                  const uint8_t *msg,
215                  const size_t size)
216 {
217         int ret;
218         frescan_packet_t *packet;
219         frescan_prio_queue_t *pqueue;
220
221         DEBUG(FRESCAN_SEND_ENABLE_DEBUG || FRESCAN_FRAG_ENABLE_DEBUG,
222               "checking arguments (msg size=%d)\n", size);
223
224         if ((params == NULL) || (msg == NULL) || (size == 0)) {
225                 FRESCAN_ERROR("arguments are not ok\n");
226                 return -1;
227         }
228
229         DEBUG(FRESCAN_SEND_ENABLE_DEBUG, "allocating a packet\n");
230
231         FRESCAN_ACQUIRE_LOCK(&frescan_data[params->net].lock);
232         packet = frescan_packets_alloc();
233         FRESCAN_RELEASE_LOCK(&frescan_data[params->net].lock);
234
235         if (packet == NULL) {
236                 FRESCAN_ERROR("could not allocate packet\n");
237                 return -1;
238         }
239         packet->flags = params->flags; // set the flags (to remember them)
240
241         DEBUG(FRESCAN_SEND_ENABLE_DEBUG, "allocating a frame\n");
242
243         FRESCAN_ACQUIRE_LOCK(&frescan_data[params->net].lock);
244         packet->frame = can_framespool_alloc();
245         FRESCAN_RELEASE_LOCK(&frescan_data[params->net].lock);
246
247         if (packet->frame == NULL) {
248                 FRESCAN_ERROR("could not allocate frame\n");
249                 return -1;
250         }
251
252         DEBUG(FRESCAN_SEND_ENABLE_DEBUG, "set values for the frame header\n");
253         packet->frame->is_extended_format = true;
254         packet->frame->is_rtr = false;
255
256         if (params->flags & FRESCAN_FP) {
257                 // NOTE: frag id for fp is: FRESCAN_MX_IDS, so the servers can
258                 // have IDs in the range (0 .. FRESCAN_MX_IDS-1)
259                 frescan_id_set_field(&packet->frame->id,
260                                      FRESCAN_FIELD_FRAG_ID,
261                                      (uint32_t)FRESCAN_MX_IDS);
262
263                 frescan_id_set_field(&packet->frame->id,
264                                       FRESCAN_FIELD_PRIO,
265                                       (uint32_t)params->prio);
266         } else {
267                 // NOTE: the priority is put when the packet is dequeued
268                 // and it is the priority of th server
269                 frescan_id_set_field(&packet->frame->id,
270                                      FRESCAN_FIELD_FRAG_ID,
271                                      (uint32_t)params->ss);
272         }
273
274         frescan_id_set_field(&packet->frame->id,
275                              FRESCAN_FIELD_DEST,
276                              (uint32_t)params->to);
277
278         frescan_id_set_field(&packet->frame->id,
279                              FRESCAN_FIELD_SRC,
280                              (uint32_t)frescan_data[params->net].local_node);
281
282         frescan_id_set_field(&packet->frame->id,
283                               FRESCAN_FIELD_CHAN,
284                               (uint32_t)params->channel);
285
286         DEBUG(FRESCAN_SEND_ENABLE_DEBUG, "set the packet data bytes\n");
287         if (params->flags & FRESCAN_ASYNC) {
288                 // allocate a buffer and copy the data
289                 // NOTE: instead of this we could use a chain of frames but
290                 // i think it would be inefficient since each one can only
291                 // hold 8 user bytes and we need to write its headers.
292                 FRESCAN_ACQUIRE_LOCK(&frescan_data[params->net].lock);
293                 packet->buffer_head = (uint8_t *)malloc(size*sizeof(uint8_t)); // TODO: FREE IT!!!
294                 FRESCAN_RELEASE_LOCK(&frescan_data[params->net].lock);
295                 memcpy(packet->buffer_head, msg, size);
296         } else {
297                 packet->buffer_head = (uint8_t *)msg;
298         }
299
300         packet->buffer_read_pointer = packet->buffer_head;
301         packet->buffer_pending_bytes = size;
302         pqueue = frescan_data[params->net].queues.tx_fp_queue;
303
304         DEBUG(FRESCAN_SEND_ENABLE_DEBUG, "enqueue the packet\n");
305         if (packet->flags & FRESCAN_FP) {
306                 FRESCAN_ACQUIRE_LOCK(&frescan_data[params->net].lock);
307                 ret = frescan_pqueue_enqueue(pqueue, packet, params->prio);
308                 FRESCAN_RELEASE_LOCK(&frescan_data[params->net].lock);
309
310                 if (ret != 0) {
311                         FRESCAN_ERROR("could not enqueue the packet\n");
312                         return -1;
313                 }
314         } else {
315                 FRESCAN_ACQUIRE_LOCK(&frescan_data[params->net].lock);
316                 ret = frescan_servers_enqueue(params->net, params->ss, packet);
317                 FRESCAN_RELEASE_LOCK(&frescan_data[params->net].lock);
318
319                 if (ret != 0) {
320                         FRESCAN_ERROR("could not enqueue the packet\n");
321                         return -1;
322                 }
323         }
324
325         FRESCAN_ACQUIRE_LOCK(&frescan_data[params->net].lock);
326         ret = frescan_hw_buffer_update(params->net);
327         FRESCAN_RELEASE_LOCK(&frescan_data[params->net].lock);
328
329         if (ret != 0) {
330                 FRESCAN_ERROR("could not update hw buffer\n");
331                 return -1;
332         }
333
334         return 0;
335 }
336
337 /**
338  * frescan_recv - receive a message
339  *
340  * @params: the parameters needed by the protocol to receive the message
341  * @msg: the message buffer
342  * @size: the size of the message buffer
343  * @recv_bytes: the number of bytes received
344  * @from: the node that sent the message
345  * @prio: the priority of the message
346  *
347  * This is one of the main functions of the protocol and it provides the
348  * means to receive a message through the protocol stack.
349  */
350
351 int frescan_recv(const frescan_recv_params_t *params,
352                  uint8_t *msg,
353                  const size_t size,
354                  size_t *recv_bytes,
355                  frescan_node_t *from,
356                  frescan_prio_t *prio)
357 {
358         int ret;
359         frescan_prio_queue_t *pqueue;
360         bool blocking;
361         frescan_packet_t *head, *packet;
362
363         if (params->flags & FRESCAN_SYNC) {
364                 DEBUG(FRESCAN_RECV_ENABLE_DEBUG,
365                       "receive a packet in blocking mode\n");
366                 blocking = true;
367         } else {
368                 DEBUG(FRESCAN_RECV_ENABLE_DEBUG,
369                       "receive a packet in non-blocking mode\n");
370                 blocking = false;
371         }
372
373         pqueue = frescan_data[params->net].queues.rx_channel_queues
374                                                              [params->channel];
375
376         ret = frescan_pqueue_dequeue(pqueue, &head, prio, blocking);
377         if (ret != 0) {
378                 FRESCAN_ERROR ("could not dequeue packet\n");
379                 return -1;
380         }
381
382         if (head == NULL) {
383                 if (blocking == false) {
384                         DEBUG(FRESCAN_RECV_ENABLE_DEBUG,
385                               "blocking false, no packets\n");
386                         *recv_bytes = 0;
387                         return 0;
388                 } else {
389                         FRESCAN_ERROR ("blocking true, and packet = null\n");
390                         return -1;
391                 }
392         }
393
394         DEBUG(FRESCAN_RECV_ENABLE_DEBUG,
395               "traverse the list of packets for this message\n");
396
397         *recv_bytes = 0;
398
399         FRESCAN_ACQUIRE_LOCK(&frescan_data[params->net].lock);
400
401         list_for_each_entry(packet, &head->msg_list, msg_list) {
402                 // TODO: memory checks, delete the packets
403                 memcpy(msg + *recv_bytes,
404                        packet->frame->data,
405                        packet->frame->dlc);
406                 *recv_bytes += packet->frame->dlc;
407
408                 *from = (frescan_node_t)frescan_id_get_field(packet->frame->id,
409                                                              FRESCAN_FIELD_SRC);
410                 DEBUG(FRESCAN_RECV_ENABLE_DEBUG,
411                       "ID Packet, dlc: %u, frame pool pos: %u, from:%u\n",
412                       packet->frame->dlc, packet->frame->pool_pos, *from);
413
414                 ret = can_framespool_free(packet->frame);
415                 if (ret != 0) {
416                         FRESCAN_ERROR("could not free frame\n");
417                         return -1;
418                 }
419
420                 ret = frescan_packets_free(packet);
421                 if (ret != 0) {
422                         FRESCAN_ERROR("could not free packet\n");
423                         return -1;
424                 }
425         }
426
427         ret = frescan_packets_free(head);
428
429         FRESCAN_RELEASE_LOCK(&frescan_data[params->net].lock);
430
431         if (ret != 0) {
432                 FRESCAN_ERROR("could not free head packet\n");
433                 return -1;
434         }
435
436         DEBUG(FRESCAN_RECV_ENABLE_DEBUG,
437               "received bytes: %u\n", *recv_bytes);
438
439         return 0;
440 }
441
442
443 /**
444  * frescan_hook_frame_recv - frame received hook
445  *
446  * This function will be called by the CAN driver's IRQ handler when a frame
447  * is received so we can store it in an appropiate queue.
448  *
449  * NOTE: in the future it could consist simply of signaling a semaphore to
450  * let a bottom half thread do the hard work.
451  */
452
453
454 static int frescan_hook_frame_recv (const struct can_chip_t *chip,
455                                     struct can_frame_t *frame)
456 {
457         int i, ret;
458         uint32_t prio, dest, src, channel, frag_id, frag_flag;
459         frescan_packet_t *packet, *head;
460         frescan_prio_queue_t *pqueue;
461         int net;
462
463         net = chip->minor;
464
465         DEBUG(FRESCAN_RX_HOOK_ENABLE_DEBUG, "received a frame, net=%d\n", net);
466         DEBUG(FRESCAN_RX_HOOK_ENABLE_DEBUG || FRESCAN_FRAG_ENABLE_DEBUG,
467               "%s %s, id=0x%X, dlc=%u, pool:%u\n",
468               (frame->is_extended_format) ? "Ext" : "Stnd",
469               (frame->is_rtr) ? "RTR Frame" : "DATA Frame",
470               frame->id,
471               frame->dlc,
472               frame->pool_pos);
473
474         for (i=0; i<frame->dlc; i++) {
475                 DEBUG(FRESCAN_RX_HOOK_ENABLE_DEBUG,
476                       "data[%d] = 0x%X;\n", i, frame->data[i]);
477         }
478
479         prio      = frescan_id_get_field(frame->id, FRESCAN_FIELD_PRIO);
480         dest      = frescan_id_get_field(frame->id, FRESCAN_FIELD_DEST);
481         src       = frescan_id_get_field(frame->id, FRESCAN_FIELD_SRC);
482         channel   = frescan_id_get_field(frame->id, FRESCAN_FIELD_CHAN);
483         frag_id   = frescan_id_get_field(frame->id, FRESCAN_FIELD_FRAG_ID);
484         frag_flag = frescan_id_get_field(frame->id, FRESCAN_FIELD_FRAG_FLAG);
485
486         DEBUG(FRESCAN_RX_HOOK_ENABLE_DEBUG || FRESCAN_FRAG_ENABLE_DEBUG,
487               "prio:%u dest:%u src:%u chan:%u id:%u flag:%u\n",
488               prio, dest, src, channel, frag_id, frag_flag);
489
490         DEBUG(FRESCAN_RX_HOOK_ENABLE_DEBUG,
491               "enqueue the packet in ID queue\n");
492         packet = frescan_packets_alloc();
493         packet->frame = frame;
494
495         if (frag_id == FRESCAN_MX_IDS) {
496                 head = frescan_data[net].id_fp_queues[src][prio];
497         } else {
498                 head = frescan_data[net].id_queues[src][frag_id];
499         }
500
501         if (head == NULL) {
502                 DEBUG(FRESCAN_RX_HOOK_ENABLE_DEBUG ||
503                                 FRESCAN_FRAG_ENABLE_DEBUG,
504                 "allocate head for id=%u\n", frag_id);
505                 head = frescan_packets_alloc();
506                 INIT_LIST_HEAD(&head->msg_list);
507
508                 if (frag_id == FRESCAN_MX_IDS) {
509                         frescan_data[net].id_fp_queues[src][prio] = head;
510                 } else {
511                         frescan_data[net].id_queues[src][frag_id] = head;
512                 }
513         }
514
515         list_add_tail(&packet->msg_list, &head->msg_list);
516
517         if (frag_flag == false) {
518                 DEBUG(FRESCAN_RX_HOOK_ENABLE_DEBUG ||
519                                 FRESCAN_FRAG_ENABLE_DEBUG,
520                 "message complete, move msg to channel\n");
521                 // TODO: select the highest priority??
522                 pqueue = frescan_data[net].queues.rx_channel_queues[channel];
523                 ret = frescan_pqueue_enqueue(pqueue, head, prio);
524                 if (ret != 0) {
525                         FRESCAN_ERROR("could not enqueue message in channel queue\n");
526                         return -1;
527                 }
528
529                 if (frag_id == FRESCAN_MX_IDS) {
530                         frescan_data[net].id_fp_queues[src][prio] = NULL;
531                 } else {
532                         frescan_data[net].id_queues[src][frag_id] = NULL;
533                 }
534
535         } else {
536                 DEBUG(FRESCAN_RX_HOOK_ENABLE_DEBUG ||
537                                 FRESCAN_FRAG_ENABLE_DEBUG,
538                 "message not complete, wait for more fragments\n");
539         }
540
541         // NOTE: don't forget to free the frame and the packet when it is
542         // read by the user application
543
544         return 0;
545 };
546
547 /**
548  * frescan_hook_frame_sent - frame sent hook
549  *
550  * This function will be called by the CAN driver's IRQ handler when a frame
551  * is sent through the CAN bus so we can enqueue another one, signal a
552  * semaphore, consume sporadic server capacity...
553  */
554
555 static int frescan_hook_frame_sent(const struct can_chip_t *chip)
556 {
557         int ret;
558         frescan_packet_t *packet;
559         frescan_prio_queue_t *pqueue;
560         frescan_prio_t prio;
561         frescan_ss_t id;
562
563         packet = frescan_data[chip->minor].last_packet;
564         assert(packet != NULL);
565
566         id = frescan_id_get_field(packet->frame->id,
567                                   FRESCAN_FIELD_FRAG_ID);
568
569         DEBUG(FRESCAN_SENT_HOOK_ENABLE_DEBUG,
570               "frame sent, minor:%u flags:0x%X frag_id:0x%X\n",
571               chip->minor, packet->flags, id);
572
573         if (packet->flags & FRESCAN_SS) {
574                 DEBUG(FRESCAN_SENT_HOOK_ENABLE_DEBUG,
575                       "calling frame_sent + program repl for id:%u\n", id);
576
577                 ret = frescan_servers_frame_sent(chip->minor, id, packet);
578                 if (ret != 0) {
579                         FRESCAN_ERROR("could not let the server a frame was sent\n");
580                         return -1;
581                 }
582         }
583
584         DEBUG(FRESCAN_SENT_HOOK_ENABLE_DEBUG || FRESCAN_FRAG_ENABLE_DEBUG,
585               "last packet buffer_pending_bytes=%u\n",
586               packet->buffer_pending_bytes);
587
588         if (packet->buffer_pending_bytes > 0) {
589                 if (packet->flags & FRESCAN_FP) {
590                         prio = frescan_id_get_field(packet->frame->id,
591                                         FRESCAN_FIELD_PRIO);
592
593                         DEBUG(FRESCAN_FRAG_ENABLE_DEBUG,
594                               "requeue fp packet, prio:%u\n", prio);
595
596                         pqueue = frescan_data[chip->minor].queues.tx_fp_queue;
597                         ret = frescan_pqueue_requeue(pqueue, packet, prio);
598                         if (ret != 0) {
599                                 FRESCAN_ERROR("could not requeue the packet packet:%p flags:0x%X\n", packet, packet->flags);
600                                 return -1;
601                         }
602                 } else if (packet->flags & FRESCAN_SS) {
603                         DEBUG(FRESCAN_FRAG_ENABLE_DEBUG,
604                               "requeue server %u packet\n", id);
605                         ret = frescan_servers_requeue(chip->minor, id, packet);
606                         if (ret != 0) {
607                                 FRESCAN_ERROR("could not requeue the packet\n");
608                                 return -1;
609                         }
610                 } else {
611                         FRESCAN_ERROR("flags are not correct\n");
612                         return -1;
613                 }
614         } else {
615                 DEBUG(FRESCAN_FRAG_ENABLE_DEBUG,
616                       "all packet fragmets sent, freeing the packet\n");
617
618                 ret = can_framespool_free(packet->frame);
619                 if (ret != 0)  {
620                         FRESCAN_ERROR ("could not free the frame\n");
621                         return ret;
622                 }
623
624                 ret = frescan_packets_free(packet);
625                 if (ret != 0)  {
626                         FRESCAN_ERROR ("could not free the packet\n");
627                         return ret;
628                 }
629
630                 // TODO: signal semaphore for send_sync
631         }
632
633         frescan_data[chip->minor].last_packet = NULL;
634
635         ret = frescan_hw_buffer_update(chip->minor);
636         if (ret != 0) {
637                 FRESCAN_ERROR("could not update hw buffer\n");
638                 return -1;
639         }
640
641         return 0;
642 };
643
644 /**
645  * frescan_hook_frame_aborted - frame frame aborted hook
646  *
647  * This function will be called by the CAN driver's IRQ handler when a frame
648  * is aborted (because another frame with higher priority is waiting). We
649  * have to requeue the frame and update the buffer.
650  */
651
652 static int frescan_hook_frame_aborted(const struct can_chip_t *chip)
653 {
654         int ret;
655         frescan_packet_t *packet;
656         frescan_prio_queue_t *pqueue;
657         frescan_prio_t prio;
658         frescan_ss_t id;
659
660         packet = frescan_data[chip->minor].last_packet;
661
662         id = frescan_id_get_field(packet->frame->id,
663                                   FRESCAN_FIELD_FRAG_ID);
664
665         DEBUG(FRESCAN_SENT_HOOK_ENABLE_DEBUG,
666               "frame aborted, minor:%u flags:0x%X frag_id:0x%X\n",
667               chip->minor, packet->flags, id);
668
669         if (packet->flags & FRESCAN_FP) {
670                 prio = frescan_id_get_field(packet->frame->id,
671                                             FRESCAN_FIELD_PRIO);
672
673                 DEBUG(FRESCAN_FRAG_ENABLE_DEBUG,
674                       "requeue fp packet, prio:%u\n", prio);
675
676                 pqueue = frescan_data[chip->minor].queues.tx_fp_queue;
677                 ret = frescan_pqueue_requeue(pqueue, packet, prio);
678                 if (ret != 0) {
679                         FRESCAN_ERROR("could not requeue the packet\n");
680                         return -1;
681                 }
682         } else if (packet->flags & FRESCAN_SS) {
683                 DEBUG(FRESCAN_FRAG_ENABLE_DEBUG,
684                       "requeue server %u packet\n", id);
685
686                 ret = frescan_servers_requeue(chip->minor, id, packet);
687                 if (ret != 0) {
688                         FRESCAN_ERROR("could not requeue the packet\n");
689                         return -1;
690                 }
691         } else {
692                 FRESCAN_ERROR("flags are not correct\n");
693                 return -1;
694         }
695
696         frescan_data[chip->minor].last_packet = NULL;
697
698         ret = frescan_hw_buffer_update(chip->minor);
699         if (ret != 0) {
700                 FRESCAN_ERROR("could not update hw buffer\n");
701                 return -1;
702         }
703
704         return 0;
705 }