#define __NO_VERSION__
#include <linux/module.h>
+#include <linux/mutex.h>
int add_channel_to_procdir(struct candevice_t *candev);
-int remove_channel_from_procdir(void);
+int remove_channels_from_procdir(void);
+int remove_channel_from_procdir(struct candevice_t *candev);
int add_object_to_procdir(int chip_nr);
int remove_object_from_procdir(int chip_nr);
static struct canproc_t can_proc_base;
static struct canproc_t *base=&can_proc_base;
+DEFINE_MUTEX(proc_mutex); /* synchronize access to canproc_t array */
/* The following functions are needed only for kernel version 2.2. Kernel
* version 2.4 already defines them for us.
{
int board;
struct candevice_t *candev;
+
+ mutex_init(&proc_mutex);
+
base->can_proc_entry = can_create_proc_entry("can", S_IFDIR | S_IRUGO |
S_IXUGO, CAN_PROC_ROOT);
if (base->can_proc_entry == NULL)
return 0;
}
+/* can_init_procentry registers entry of a new board in CAN directory tree at
+ * the proc system.
+ */
+int can_init_procentry(int board)
+{
+ struct candevice_t *candev;
+ candev=hardware_p->candevice[board];
+ if(candev)
+ return add_channel_to_procdir(candev);
+ return -ENODEV;
+}
+
/* can_delete_procdir removes the entire CAN tree from the proc system */
int can_delete_procdir(void)
{
- if (remove_channel_from_procdir())
+ if (remove_channels_from_procdir())
return -ENODEV;
/* name: "can" */
- if (can_remove_proc_entry(base->can_proc_entry, CAN_PROC_ROOT))
+ if (can_remove_proc_entry(base->can_proc_entry, CAN_PROC_ROOT))
+ return -ENODEV;
+
+ return 0;
+}
+
+/* can_delete_procentry removes device entries from CAN tree in the proc system */
+int can_delete_procentry(struct candevice_t *candev)
+{
+ if (remove_channel_from_procdir(candev))
return -ENODEV;
return 0;
{
int i=0;
- for (i=0; i < candev->nr_all_chips; i++) {
+ mutex_lock(&proc_mutex);
+ for (i=0; i < MAX_TOT_CHIPS; i++){
+ if (!chips_p[i]) continue;
+ if (chips_p[i]->hostdevice != candev) continue;
- base->channel[cc] = (struct channelproc_t *)
+ base->channel[i] = (struct channelproc_t *)
can_checked_malloc(sizeof(struct channelproc_t));
- if (base->channel[cc] == NULL)
+ if (base->channel[i] == NULL){
+ mutex_unlock(&proc_mutex);
return -ENOMEM;
+ }
- sprintf(base->channel[cc]->ch_name, "channel%d",cc);
+ sprintf(base->channel[i]->ch_name, "channel%d",i);
- base->channel[cc]->ch_entry = can_create_proc_entry(
- base->channel[cc]->ch_name,
+ base->channel[i]->ch_entry = can_create_proc_entry(
+ base->channel[i]->ch_name,
S_IFDIR | S_IRUGO |S_IXUGO,
base->can_proc_entry);
- if (base->channel[cc]->ch_entry == NULL)
+ if (base->channel[i]->ch_entry == NULL){
+ mutex_unlock(&proc_mutex);
return -ENODEV;
+ }
- add_object_to_procdir(cc);
+ add_object_to_procdir(i);
create_proc_read_entry("chip_info", /* proc entry name */
0, /* protection mask, 0->default */
- base->channel[cc]->ch_entry, /* parent dir, NULL->/proc */
+ base->channel[i]->ch_entry, /* parent dir, NULL->/proc */
can_chip_procinfo,
- candev->chip[i]);
-
+ chips_p[i]);
cc++;
}
+ mutex_unlock(&proc_mutex);
return 0;
}
-int remove_channel_from_procdir(void)
+int remove_channels_from_procdir(void)
{
+ int i=0;
+
+ mutex_lock(&proc_mutex);
+ for (i=0; i < MAX_TOT_CHIPS; i++){
+ if (!chips_p[i]) continue;
- while (cc != 0) {
cc--;
- if(!base->channel[cc]) continue;
+ if(!base->channel[i]) continue;
- remove_proc_entry("chip_info", base->channel[cc]->ch_entry);
+ remove_proc_entry("chip_info", base->channel[i]->ch_entry);
- if (remove_object_from_procdir(cc))
+ if (remove_object_from_procdir(i)){
+ mutex_unlock(&proc_mutex);
return -ENODEV;
+ }
/* name: base->channel[cc]->ch_name */
- if (can_remove_proc_entry(base->channel[cc]->ch_entry,
- base->can_proc_entry))
+ if (can_remove_proc_entry(base->channel[i]->ch_entry,
+ base->can_proc_entry)){
+ mutex_unlock(&proc_mutex);
return -ENODEV;
+ }
- can_checked_free(base->channel[cc]);
- base->channel[cc] = NULL;
+ can_checked_free(base->channel[i]);
+ base->channel[i] = NULL;
+ }
+ mutex_unlock(&proc_mutex);
+
+ return 0;
+}
+
+int remove_channel_from_procdir(struct candevice_t *candev)
+{
+ int i=0,j=0;
+
+ mutex_lock(&proc_mutex);
+ for (i=0; i < MAX_TOT_CHIPS; i++){
+ if (!chips_p[i]) continue;
+ if (chips_p[i]->hostdevice != candev) continue;
+ if (!base->channel[i]) continue;
+
+ remove_proc_entry("chip_info", base->channel[i]->ch_entry);
+
+ if (remove_object_from_procdir(i)){
+ mutex_unlock(&proc_mutex);
+ return -ENODEV;
+ }
+
+ /* name: base->channel[cc]->ch_name */
+ if (can_remove_proc_entry(base->channel[i]->ch_entry,
+ base->can_proc_entry)){
+ mutex_unlock(&proc_mutex);
+ return -ENODEV;
+ }
+
+ can_checked_free(base->channel[i]);
+ base->channel[i] = NULL;
+
+ cc--;
}
+ mutex_unlock(&proc_mutex);
return 0;
}