X-Git-Url: http://rtime.felk.cvut.cz/gitweb/lincan.git/blobdiff_plain/d33757f945ce0ca4556780f3634d7a35b8d8d58d..b29ebe97fb5acced24e8ce9bb30e5d4dcad58815:/lincan/src/proc.c diff --git a/lincan/src/proc.c b/lincan/src/proc.c index 34ecc43..b9d3419 100644 --- a/lincan/src/proc.c +++ b/lincan/src/proc.c @@ -40,9 +40,11 @@ #define __NO_VERSION__ #include +#include 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); @@ -60,6 +62,7 @@ static int cc=0; /* static counter for each CAN chip */ 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 */ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)) @@ -291,6 +294,9 @@ int can_init_procdir(void) { int board; struct candevice_t *candev; + + mutex_init(&proc_mutex); + base->can_proc_entry = can_proc_mkdir_mode("can", S_IFDIR | S_IRUGO | S_IXUGO, CAN_PROC_ROOT); if (base->can_proc_entry == NULL) @@ -304,10 +310,22 @@ int can_init_procdir(void) 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_proc_remove(base->can_proc_entry)) @@ -316,6 +334,15 @@ int can_delete_procdir(void) 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; +} + static int can_chip_procinfo_show(can_proc_seq_file_t *sqf, void *data) { struct canchip_t *chip=can_seq_data(sqf); @@ -347,57 +374,106 @@ int add_channel_to_procdir(struct candevice_t *candev) { 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_proc_mkdir_mode( - base->channel[cc]->ch_name, + base->channel[i]->ch_entry = can_proc_mkdir_mode( + 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); can_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_ops, - 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_proc_remove(base->channel[cc]->ch_entry)) + if (can_proc_remove(base->channel[i]->ch_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_proc_remove(base->channel[i]->ch_entry)){ + mutex_unlock(&proc_mutex); + return -ENODEV; + } + + can_checked_free(base->channel[i]); + base->channel[i] = NULL; + + cc--; } + mutex_unlock(&proc_mutex); return 0; }