]> rtime.felk.cvut.cz Git - lincan.git/blob - lincan/src/finish.c
Merge branch 'master' into can-usb1
[lincan.git] / lincan / src / finish.c
1 /**************************************************************************/
2 /* File: finish.c - finalization of the driver operations                 */
3 /*                                                                        */
4 /* LinCAN - (Not only) Linux CAN bus driver                               */
5 /* Copyright (C) 2002-2009 DCE FEE CTU Prague <http://dce.felk.cvut.cz>   */
6 /* Copyright (C) 2002-2009 Pavel Pisa <pisa@cmp.felk.cvut.cz>             */
7 /* Funded by OCERA and FRESCOR IST projects                               */
8 /* Based on CAN driver code by Arnaud Westenberg <arnaud@wanadoo.nl>      */
9 /*                                                                        */
10 /* LinCAN is free software; you can redistribute it and/or modify it      */
11 /* under terms of the GNU General Public License as published by the      */
12 /* Free Software Foundation; either version 2, or (at your option) any    */
13 /* later version.  LinCAN is distributed in the hope that it will be      */
14 /* useful, but WITHOUT ANY WARRANTY; without even the implied warranty    */
15 /* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU    */
16 /* General Public License for more details. You should have received a    */
17 /* copy of the GNU General Public License along with LinCAN; see file     */
18 /* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
19 /* Cambridge, MA 02139, USA.                                              */
20 /*                                                                        */
21 /* To allow use of LinCAN in the compact embedded systems firmware        */
22 /* and RT-executives (RTEMS for example), main authors agree with next    */
23 /* special exception:                                                     */
24 /*                                                                        */
25 /* Including LinCAN header files in a file, instantiating LinCAN generics */
26 /* or templates, or linking other files with LinCAN objects to produce    */
27 /* an application image/executable, does not by itself cause the          */
28 /* resulting application image/executable to be covered by                */
29 /* the GNU General Public License.                                        */
30 /* This exception does not however invalidate any other reasons           */
31 /* why the executable file might be covered by the GNU Public License.    */
32 /* Publication of enhanced or derived LinCAN files is required although.  */
33 /**************************************************************************/
34
35 #include "../include/can.h"
36 #include "../include/can_sysdep.h"
37 #include "../include/main.h"
38 #include "../include/devcommon.h"
39 #include "../include/finish.h"
40 #include "../include/setup.h"
41
42 extern int next_minor;
43 /**
44  * msgobj_done - destroys one CAN message object
45  * @obj: pointer to CAN message object structure
46  */
47 void msgobj_done(struct msgobj_t *obj)
48 {
49         int delayed=0;
50         if(obj->qends) {
51                 delayed=canqueue_ends_done_chip(obj->qends);
52                 if(delayed < 0)
53                         CANMSG("msgobj_done: problem with chip queue ends\n");
54         }
55
56         if((obj->hostchip) && (obj->object>0)) {
57                 if(obj->hostchip->msgobj[obj->object-1] == obj)
58                         obj->hostchip->msgobj[obj->object-1]=NULL;
59                 else
60                         CANMSG("msgobj_done: not registered in the canchip_t\n");
61                 obj->hostchip=NULL;
62         }
63
64         if((obj->minor>=0)) {
65                 if(objects_p[obj->minor] == obj){
66                         objects_p[obj->minor] = NULL;
67                         if (--next_minor<0)
68                                 next_minor=0;
69                 }
70                 else
71                         CANMSG("msgobj_done: not registered as minor\n");
72         }
73
74         del_timer_sync(&obj->tx_timeout);
75
76         if(obj->qends) {
77                 /*delayed free could be required there in the future,
78                   actual use patter cannot generate such situation*/
79                 if(!delayed) {
80                         can_checked_free(obj->qends);
81                 }
82         }
83         obj->qends=NULL;
84 }
85
86
87 /**
88  * canchip_done - destroys one CAN chip representation
89  * @chip: pointer to CAN chip structure
90  */
91 void canchip_done(struct canchip_t *chip)
92 {
93
94         int i;
95         struct msgobj_t *obj;
96
97         if(chip->flags & CHIP_ATTACHED){
98                 chip->chipspecops->release_chip(chip);
99                 chip->flags &= ~CHIP_ATTACHED;
100         }
101
102         if((chip->hostdevice) && (chip->chip_idx>=0)) {
103                 if(chip->hostdevice->chip[chip->chip_idx] == chip)
104                         chip->hostdevice->chip[chip->chip_idx] = NULL;
105                 else
106                         CANMSG("canchip_done: not registered in hostdevice\n");
107         }
108
109         can_chip_free_irq(chip);
110
111         can_synchronize_irq(chip->chip_irq);
112
113         for(i=0; i<chip->max_objects; i++){
114                 if((obj=chip->msgobj[i])==NULL)
115                         continue;
116                 msgobj_done(obj);
117                 can_checked_free(obj);
118         }
119
120         can_checked_free(chip->chipspecops);
121        
122         if(~chip->flags & CHIP_KEEP_DATA)
123                 can_checked_free(chip->chip_data);
124         chip->chip_data = NULL;
125         chip->chipspecops=NULL;
126
127 }
128
129 /**
130  * candevice_done - destroys representation of one CAN device/board
131  * @candev: pointer to CAN device/board structure
132  */
133 void candevice_done(struct candevice_t *candev)
134 {
135         int i;
136         struct canchip_t *chip;
137
138         for(i=0; i<candev->nr_all_chips; i++){
139                 if((chip=candev->chip[i])==NULL)
140                         continue;
141                 canchip_done(chip);
142                 can_checked_free(chip);
143
144         }
145         if(candev->flags & CANDEV_IO_RESERVED) {
146                 candev->hwspecops->release_io(candev);
147                 candev->flags &= ~CANDEV_IO_RESERVED;
148         }
149         if(candev->hwspecops->done_hw_data != NULL)
150                 candev->hwspecops->done_hw_data(candev);
151
152         can_checked_free(candev->hwspecops);
153         candev->hwspecops=NULL;
154 }
155
156 /**
157  * candevice_done - destroys representation of all CAN devices/boards
158  * @canhw: pointer to the root of all CAN hardware representation
159  */
160 void canhardware_done(struct canhardware_t *canhw)
161 {
162         int i;
163         struct candevice_t *candev;
164
165         for(i=0; i<MAX_HW_CARDS; i++){
166                 if((candev=canhw->candevice[i])==NULL)
167                         continue;
168                 candevice_done(candev);
169                 can_checked_free(candev);
170         }
171
172 }