proc.c 14.6 KB
Newer Older
1
// SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)
O
Oliver Hartkopp 已提交
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
/*
 * proc.c - procfs support for Protocol family CAN core module
 *
 * Copyright (c) 2002-2007 Volkswagen Group Electronic Research
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of Volkswagen nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * Alternatively, provided that this notice is retained in full, this
 * software may be distributed under the terms of the GNU General
 * Public License ("GPL") version 2, in which case the provisions of the
 * GPL apply INSTEAD OF those given above.
 *
 * The provided data structures and external interfaces from this code
 * are not restricted to be used by modules with a GPL compatible license.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
 * DAMAGE.
 *
 */

#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/list.h>
#include <linux/rcupdate.h>
47
#include <linux/if_arp.h>
O
Oliver Hartkopp 已提交
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
#include <linux/can/core.h>

#include "af_can.h"

/*
 * proc filenames for the PF_CAN core
 */

#define CAN_PROC_VERSION     "version"
#define CAN_PROC_STATS       "stats"
#define CAN_PROC_RESET_STATS "reset_stats"
#define CAN_PROC_RCVLIST_ALL "rcvlist_all"
#define CAN_PROC_RCVLIST_FIL "rcvlist_fil"
#define CAN_PROC_RCVLIST_INV "rcvlist_inv"
#define CAN_PROC_RCVLIST_SFF "rcvlist_sff"
#define CAN_PROC_RCVLIST_EFF "rcvlist_eff"
#define CAN_PROC_RCVLIST_ERR "rcvlist_err"

static int user_reset;

static const char rx_list_name[][8] = {
	[RX_ERR] = "rx_err",
	[RX_ALL] = "rx_all",
	[RX_FIL] = "rx_fil",
	[RX_INV] = "rx_inv",
};

/*
 * af_can statistics stuff
 */

79
static void can_init_stats(struct net *net)
O
Oliver Hartkopp 已提交
80
{
81 82
	struct can_pkg_stats *can_stats = net->can.pkg_stats;
	struct can_rcv_lists_stats *can_pstats = net->can.rcv_lists_stats;
O
Oliver Hartkopp 已提交
83 84 85 86 87
	/*
	 * This memset function is called from a timer context (when
	 * can_stattimer is active which is the default) OR in a process
	 * context (reading the proc_fs when can_stattimer is disabled).
	 */
88
	memset(can_stats, 0, sizeof(struct can_pkg_stats));
89
	can_stats->jiffies_init = jiffies;
O
Oliver Hartkopp 已提交
90

91
	can_pstats->stats_reset++;
O
Oliver Hartkopp 已提交
92 93 94

	if (user_reset) {
		user_reset = 0;
95
		can_pstats->user_reset++;
O
Oliver Hartkopp 已提交
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
	}
}

static unsigned long calc_rate(unsigned long oldjif, unsigned long newjif,
			       unsigned long count)
{
	unsigned long rate;

	if (oldjif == newjif)
		return 0;

	/* see can_stat_update() - this should NEVER happen! */
	if (count > (ULONG_MAX / HZ)) {
		printk(KERN_ERR "can: calc_rate: count exceeded! %ld\n",
		       count);
		return 99999999;
	}

	rate = (count * HZ) / (newjif - oldjif);

	return rate;
}

119
void can_stat_update(struct timer_list *t)
O
Oliver Hartkopp 已提交
120
{
121
	struct net *net = from_timer(net, t, can.can_stattimer);
122
	struct can_pkg_stats *can_stats = net->can.pkg_stats;
O
Oliver Hartkopp 已提交
123 124 125 126
	unsigned long j = jiffies; /* snapshot */

	/* restart counting in timer context on user request */
	if (user_reset)
127
		can_init_stats(net);
O
Oliver Hartkopp 已提交
128 129

	/* restart counting on jiffies overflow */
130 131
	if (j < can_stats->jiffies_init)
		can_init_stats(net);
O
Oliver Hartkopp 已提交
132 133

	/* prevent overflow in calc_rate() */
134 135
	if (can_stats->rx_frames > (ULONG_MAX / HZ))
		can_init_stats(net);
O
Oliver Hartkopp 已提交
136 137

	/* prevent overflow in calc_rate() */
138 139
	if (can_stats->tx_frames > (ULONG_MAX / HZ))
		can_init_stats(net);
O
Oliver Hartkopp 已提交
140 141

	/* matches overflow - very improbable */
142 143
	if (can_stats->matches > (ULONG_MAX / 100))
		can_init_stats(net);
O
Oliver Hartkopp 已提交
144 145

	/* calc total values */
146 147 148
	if (can_stats->rx_frames)
		can_stats->total_rx_match_ratio = (can_stats->matches * 100) /
			can_stats->rx_frames;
O
Oliver Hartkopp 已提交
149

150 151 152 153
	can_stats->total_tx_rate = calc_rate(can_stats->jiffies_init, j,
					    can_stats->tx_frames);
	can_stats->total_rx_rate = calc_rate(can_stats->jiffies_init, j,
					    can_stats->rx_frames);
O
Oliver Hartkopp 已提交
154 155

	/* calc current values */
156 157 158 159
	if (can_stats->rx_frames_delta)
		can_stats->current_rx_match_ratio =
			(can_stats->matches_delta * 100) /
			can_stats->rx_frames_delta;
O
Oliver Hartkopp 已提交
160

161 162
	can_stats->current_tx_rate = calc_rate(0, HZ, can_stats->tx_frames_delta);
	can_stats->current_rx_rate = calc_rate(0, HZ, can_stats->rx_frames_delta);
O
Oliver Hartkopp 已提交
163 164

	/* check / update maximum values */
165 166
	if (can_stats->max_tx_rate < can_stats->current_tx_rate)
		can_stats->max_tx_rate = can_stats->current_tx_rate;
O
Oliver Hartkopp 已提交
167

168 169
	if (can_stats->max_rx_rate < can_stats->current_rx_rate)
		can_stats->max_rx_rate = can_stats->current_rx_rate;
O
Oliver Hartkopp 已提交
170

171 172
	if (can_stats->max_rx_match_ratio < can_stats->current_rx_match_ratio)
		can_stats->max_rx_match_ratio = can_stats->current_rx_match_ratio;
O
Oliver Hartkopp 已提交
173 174

	/* clear values for 'current rate' calculation */
175 176 177
	can_stats->tx_frames_delta = 0;
	can_stats->rx_frames_delta = 0;
	can_stats->matches_delta   = 0;
O
Oliver Hartkopp 已提交
178 179

	/* restart timer (one second) */
180
	mod_timer(&net->can.can_stattimer, round_jiffies(jiffies + HZ));
O
Oliver Hartkopp 已提交
181 182 183 184 185 186
}

/*
 * proc read functions
 */

A
Alexey Dobriyan 已提交
187 188
static void can_print_rcvlist(struct seq_file *m, struct hlist_head *rx_list,
			      struct net_device *dev)
O
Oliver Hartkopp 已提交
189 190 191
{
	struct receiver *r;

192
	hlist_for_each_entry_rcu(r, rx_list, list) {
O
Oliver Hartkopp 已提交
193
		char *fmt = (r->can_id & CAN_EFF_FLAG)?
194 195
			"   %-5s  %08x  %08x  %pK  %pK  %8ld  %s\n" :
			"   %-5s     %03x    %08x  %pK  %pK  %8ld  %s\n";
O
Oliver Hartkopp 已提交
196

A
Alexey Dobriyan 已提交
197
		seq_printf(m, fmt, DNAME(dev), r->can_id, r->mask,
198
				r->func, r->data, r->matches, r->ident);
O
Oliver Hartkopp 已提交
199 200 201
	}
}

A
Alexey Dobriyan 已提交
202
static void can_print_recv_banner(struct seq_file *m)
O
Oliver Hartkopp 已提交
203 204 205 206 207
{
	/*
	 *                  can1.  00000000  00000000  00000000
	 *                 .......          0  tp20
	 */
A
Alexey Dobriyan 已提交
208
	seq_puts(m, "  device   can_id   can_mask  function"
O
Oliver Hartkopp 已提交
209 210 211
			"  userdata   matches  ident\n");
}

A
Alexey Dobriyan 已提交
212
static int can_stats_proc_show(struct seq_file *m, void *v)
O
Oliver Hartkopp 已提交
213
{
214
	struct net *net = m->private;
215 216
	struct can_pkg_stats *can_stats = net->can.pkg_stats;
	struct can_rcv_lists_stats *can_pstats = net->can.rcv_lists_stats;
217

A
Alexey Dobriyan 已提交
218
	seq_putc(m, '\n');
219 220 221
	seq_printf(m, " %8ld transmitted frames (TXF)\n", can_stats->tx_frames);
	seq_printf(m, " %8ld received frames (RXF)\n", can_stats->rx_frames);
	seq_printf(m, " %8ld matched frames (RXMF)\n", can_stats->matches);
O
Oliver Hartkopp 已提交
222

A
Alexey Dobriyan 已提交
223
	seq_putc(m, '\n');
O
Oliver Hartkopp 已提交
224

225
	if (net->can.can_stattimer.function == can_stat_update) {
A
Alexey Dobriyan 已提交
226
		seq_printf(m, " %8ld %% total match ratio (RXMR)\n",
227
				can_stats->total_rx_match_ratio);
O
Oliver Hartkopp 已提交
228

A
Alexey Dobriyan 已提交
229
		seq_printf(m, " %8ld frames/s total tx rate (TXR)\n",
230
				can_stats->total_tx_rate);
A
Alexey Dobriyan 已提交
231
		seq_printf(m, " %8ld frames/s total rx rate (RXR)\n",
232
				can_stats->total_rx_rate);
O
Oliver Hartkopp 已提交
233

A
Alexey Dobriyan 已提交
234
		seq_putc(m, '\n');
O
Oliver Hartkopp 已提交
235

A
Alexey Dobriyan 已提交
236
		seq_printf(m, " %8ld %% current match ratio (CRXMR)\n",
237
				can_stats->current_rx_match_ratio);
O
Oliver Hartkopp 已提交
238

A
Alexey Dobriyan 已提交
239
		seq_printf(m, " %8ld frames/s current tx rate (CTXR)\n",
240
				can_stats->current_tx_rate);
A
Alexey Dobriyan 已提交
241
		seq_printf(m, " %8ld frames/s current rx rate (CRXR)\n",
242
				can_stats->current_rx_rate);
O
Oliver Hartkopp 已提交
243

A
Alexey Dobriyan 已提交
244
		seq_putc(m, '\n');
O
Oliver Hartkopp 已提交
245

A
Alexey Dobriyan 已提交
246
		seq_printf(m, " %8ld %% max match ratio (MRXMR)\n",
247
				can_stats->max_rx_match_ratio);
O
Oliver Hartkopp 已提交
248

A
Alexey Dobriyan 已提交
249
		seq_printf(m, " %8ld frames/s max tx rate (MTXR)\n",
250
				can_stats->max_tx_rate);
A
Alexey Dobriyan 已提交
251
		seq_printf(m, " %8ld frames/s max rx rate (MRXR)\n",
252
				can_stats->max_rx_rate);
O
Oliver Hartkopp 已提交
253

A
Alexey Dobriyan 已提交
254
		seq_putc(m, '\n');
O
Oliver Hartkopp 已提交
255 256
	}

A
Alexey Dobriyan 已提交
257
	seq_printf(m, " %8ld current receive list entries (CRCV)\n",
258
			can_pstats->rcv_entries);
A
Alexey Dobriyan 已提交
259
	seq_printf(m, " %8ld maximum receive list entries (MRCV)\n",
260
			can_pstats->rcv_entries_max);
O
Oliver Hartkopp 已提交
261

262
	if (can_pstats->stats_reset)
A
Alexey Dobriyan 已提交
263
		seq_printf(m, "\n %8ld statistic resets (STR)\n",
264
				can_pstats->stats_reset);
O
Oliver Hartkopp 已提交
265

266
	if (can_pstats->user_reset)
A
Alexey Dobriyan 已提交
267
		seq_printf(m, " %8ld user statistic resets (USTR)\n",
268
				can_pstats->user_reset);
O
Oliver Hartkopp 已提交
269

A
Alexey Dobriyan 已提交
270 271
	seq_putc(m, '\n');
	return 0;
O
Oliver Hartkopp 已提交
272 273
}

A
Alexey Dobriyan 已提交
274 275
static int can_reset_stats_proc_show(struct seq_file *m, void *v)
{
276
	struct net *net = m->private;
277 278
	struct can_rcv_lists_stats *can_pstats = net->can.rcv_lists_stats;
	struct can_pkg_stats *can_stats = net->can.pkg_stats;
279

O
Oliver Hartkopp 已提交
280 281
	user_reset = 1;

282
	if (net->can.can_stattimer.function == can_stat_update) {
A
Alexey Dobriyan 已提交
283
		seq_printf(m, "Scheduled statistic reset #%ld.\n",
284
				can_pstats->stats_reset + 1);
O
Oliver Hartkopp 已提交
285
	} else {
286 287
		if (can_stats->jiffies_init != jiffies)
			can_init_stats(net);
O
Oliver Hartkopp 已提交
288

A
Alexey Dobriyan 已提交
289
		seq_printf(m, "Performed statistic reset #%ld.\n",
290
				can_pstats->stats_reset);
O
Oliver Hartkopp 已提交
291
	}
A
Alexey Dobriyan 已提交
292 293
	return 0;
}
O
Oliver Hartkopp 已提交
294

A
Alexey Dobriyan 已提交
295
static int can_version_proc_show(struct seq_file *m, void *v)
O
Oliver Hartkopp 已提交
296
{
A
Alexey Dobriyan 已提交
297 298 299
	seq_printf(m, "%s\n", CAN_VERSION_STRING);
	return 0;
}
O
Oliver Hartkopp 已提交
300

301 302
static inline void can_rcvlist_proc_show_one(struct seq_file *m, int idx,
					     struct net_device *dev,
303
					     struct can_dev_rcv_lists *d)
304 305 306 307 308 309 310 311 312
{
	if (!hlist_empty(&d->rx[idx])) {
		can_print_recv_banner(m);
		can_print_rcvlist(m, &d->rx[idx], dev);
	} else
		seq_printf(m, "  (%s: no entry)\n", DNAME(dev));

}

A
Alexey Dobriyan 已提交
313
static int can_rcvlist_proc_show(struct seq_file *m, void *v)
O
Oliver Hartkopp 已提交
314 315
{
	/* double cast to prevent GCC warning */
316
	int idx = (int)(long)PDE_DATA(m->file->f_inode);
317
	struct net_device *dev;
318
	struct can_dev_rcv_lists *d;
319
	struct net *net = m->private;
O
Oliver Hartkopp 已提交
320

A
Alexey Dobriyan 已提交
321
	seq_printf(m, "\nreceive list '%s':\n", rx_list_name[idx]);
O
Oliver Hartkopp 已提交
322 323 324

	rcu_read_lock();

325
	/* receive list for 'all' CAN devices (dev == NULL) */
326
	d = net->can.can_rx_alldev_list;
327 328 329
	can_rcvlist_proc_show_one(m, idx, NULL, d);

	/* receive list for registered CAN devices */
330
	for_each_netdev_rcu(net, dev) {
331 332
		if (dev->type == ARPHRD_CAN && dev->ml_priv)
			can_rcvlist_proc_show_one(m, idx, dev, dev->ml_priv);
O
Oliver Hartkopp 已提交
333
	}
334

O
Oliver Hartkopp 已提交
335 336
	rcu_read_unlock();

A
Alexey Dobriyan 已提交
337 338 339
	seq_putc(m, '\n');
	return 0;
}
O
Oliver Hartkopp 已提交
340

341 342 343 344
static inline void can_rcvlist_proc_show_array(struct seq_file *m,
					       struct net_device *dev,
					       struct hlist_head *rcv_array,
					       unsigned int rcv_array_sz)
345
{
346
	unsigned int i;
347 348
	int all_empty = 1;

349
	/* check whether at least one list is non-empty */
350 351
	for (i = 0; i < rcv_array_sz; i++)
		if (!hlist_empty(&rcv_array[i])) {
352 353 354 355 356 357
			all_empty = 0;
			break;
		}

	if (!all_empty) {
		can_print_recv_banner(m);
358 359 360
		for (i = 0; i < rcv_array_sz; i++) {
			if (!hlist_empty(&rcv_array[i]))
				can_print_rcvlist(m, &rcv_array[i], dev);
361 362 363 364 365
		}
	} else
		seq_printf(m, "  (%s: no entry)\n", DNAME(dev));
}

A
Alexey Dobriyan 已提交
366
static int can_rcvlist_sff_proc_show(struct seq_file *m, void *v)
O
Oliver Hartkopp 已提交
367
{
368
	struct net_device *dev;
369
	struct can_dev_rcv_lists *d;
370
	struct net *net = m->private;
O
Oliver Hartkopp 已提交
371 372

	/* RX_SFF */
A
Alexey Dobriyan 已提交
373
	seq_puts(m, "\nreceive list 'rx_sff':\n");
O
Oliver Hartkopp 已提交
374 375

	rcu_read_lock();
376 377

	/* sff receive list for 'all' CAN devices (dev == NULL) */
378
	d = net->can.can_rx_alldev_list;
379
	can_rcvlist_proc_show_array(m, NULL, d->rx_sff, ARRAY_SIZE(d->rx_sff));
380 381

	/* sff receive list for registered CAN devices */
382
	for_each_netdev_rcu(net, dev) {
383 384 385 386 387
		if (dev->type == ARPHRD_CAN && dev->ml_priv) {
			d = dev->ml_priv;
			can_rcvlist_proc_show_array(m, dev, d->rx_sff,
						    ARRAY_SIZE(d->rx_sff));
		}
O
Oliver Hartkopp 已提交
388
	}
389

O
Oliver Hartkopp 已提交
390 391
	rcu_read_unlock();

A
Alexey Dobriyan 已提交
392 393 394
	seq_putc(m, '\n');
	return 0;
}
O
Oliver Hartkopp 已提交
395

396 397 398
static int can_rcvlist_eff_proc_show(struct seq_file *m, void *v)
{
	struct net_device *dev;
399
	struct can_dev_rcv_lists *d;
400
	struct net *net = m->private;
401 402 403 404 405 406 407

	/* RX_EFF */
	seq_puts(m, "\nreceive list 'rx_eff':\n");

	rcu_read_lock();

	/* eff receive list for 'all' CAN devices (dev == NULL) */
408
	d = net->can.can_rx_alldev_list;
409 410 411
	can_rcvlist_proc_show_array(m, NULL, d->rx_eff, ARRAY_SIZE(d->rx_eff));

	/* eff receive list for registered CAN devices */
412
	for_each_netdev_rcu(net, dev) {
413 414 415 416 417 418 419 420 421 422 423 424 425
		if (dev->type == ARPHRD_CAN && dev->ml_priv) {
			d = dev->ml_priv;
			can_rcvlist_proc_show_array(m, dev, d->rx_eff,
						    ARRAY_SIZE(d->rx_eff));
		}
	}

	rcu_read_unlock();

	seq_putc(m, '\n');
	return 0;
}

O
Oliver Hartkopp 已提交
426 427 428
/*
 * can_init_proc - create main CAN proc directory and procfs entries
 */
429
void can_init_proc(struct net *net)
O
Oliver Hartkopp 已提交
430 431
{
	/* create /proc/net/can directory */
432
	net->can.proc_dir = proc_net_mkdir(net, "can", net->proc_net);
O
Oliver Hartkopp 已提交
433

434 435 436
	if (!net->can.proc_dir) {
		printk(KERN_INFO "can: failed to create /proc/net/can . "
			   "CONFIG_PROC_FS missing?\n");
O
Oliver Hartkopp 已提交
437 438 439 440
		return;
	}

	/* own procfs entries from the AF_CAN core */
441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463
	net->can.pde_version = proc_create_net_single(CAN_PROC_VERSION, 0644,
			net->can.proc_dir, can_version_proc_show, NULL);
	net->can.pde_stats = proc_create_net_single(CAN_PROC_STATS, 0644,
			net->can.proc_dir, can_stats_proc_show, NULL);
	net->can.pde_reset_stats = proc_create_net_single(CAN_PROC_RESET_STATS,
			0644, net->can.proc_dir, can_reset_stats_proc_show,
			NULL);
	net->can.pde_rcvlist_err = proc_create_net_single(CAN_PROC_RCVLIST_ERR,
			0644, net->can.proc_dir, can_rcvlist_proc_show,
			(void *)RX_ERR);
	net->can.pde_rcvlist_all = proc_create_net_single(CAN_PROC_RCVLIST_ALL,
			0644, net->can.proc_dir, can_rcvlist_proc_show,
			(void *)RX_ALL);
	net->can.pde_rcvlist_fil = proc_create_net_single(CAN_PROC_RCVLIST_FIL,
			0644, net->can.proc_dir, can_rcvlist_proc_show,
			(void *)RX_FIL);
	net->can.pde_rcvlist_inv = proc_create_net_single(CAN_PROC_RCVLIST_INV,
			0644, net->can.proc_dir, can_rcvlist_proc_show,
			(void *)RX_INV);
	net->can.pde_rcvlist_eff = proc_create_net_single(CAN_PROC_RCVLIST_EFF,
			0644, net->can.proc_dir, can_rcvlist_eff_proc_show, NULL);
	net->can.pde_rcvlist_sff = proc_create_net_single(CAN_PROC_RCVLIST_SFF,
			0644, net->can.proc_dir, can_rcvlist_sff_proc_show, NULL);
O
Oliver Hartkopp 已提交
464 465 466 467 468
}

/*
 * can_remove_proc - remove procfs entries and main CAN proc directory
 */
469
void can_remove_proc(struct net *net)
O
Oliver Hartkopp 已提交
470
{
471 472
	if (net->can.pde_version)
		remove_proc_entry(CAN_PROC_VERSION, net->can.proc_dir);
O
Oliver Hartkopp 已提交
473

474 475
	if (net->can.pde_stats)
		remove_proc_entry(CAN_PROC_STATS, net->can.proc_dir);
O
Oliver Hartkopp 已提交
476

477 478
	if (net->can.pde_reset_stats)
		remove_proc_entry(CAN_PROC_RESET_STATS, net->can.proc_dir);
O
Oliver Hartkopp 已提交
479

480 481
	if (net->can.pde_rcvlist_err)
		remove_proc_entry(CAN_PROC_RCVLIST_ERR, net->can.proc_dir);
O
Oliver Hartkopp 已提交
482

483 484
	if (net->can.pde_rcvlist_all)
		remove_proc_entry(CAN_PROC_RCVLIST_ALL, net->can.proc_dir);
O
Oliver Hartkopp 已提交
485

486 487
	if (net->can.pde_rcvlist_fil)
		remove_proc_entry(CAN_PROC_RCVLIST_FIL, net->can.proc_dir);
O
Oliver Hartkopp 已提交
488

489 490
	if (net->can.pde_rcvlist_inv)
		remove_proc_entry(CAN_PROC_RCVLIST_INV, net->can.proc_dir);
O
Oliver Hartkopp 已提交
491

492 493
	if (net->can.pde_rcvlist_eff)
		remove_proc_entry(CAN_PROC_RCVLIST_EFF, net->can.proc_dir);
O
Oliver Hartkopp 已提交
494

495 496
	if (net->can.pde_rcvlist_sff)
		remove_proc_entry(CAN_PROC_RCVLIST_SFF, net->can.proc_dir);
O
Oliver Hartkopp 已提交
497

498 499
	if (net->can.proc_dir)
		remove_proc_entry("can", net->proc_net);
O
Oliver Hartkopp 已提交
500
}