Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  *  linux/drivers/net/netconsole.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  *  Copyright (C) 2001  Ingo Molnar <mingo@redhat.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  *  This file contains the implementation of an IRQ-safe, crash-safe
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  *  kernel console implementation that outputs kernel messages to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  *  network.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)  * Modification history:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13)  * 2001-09-17    started by Ingo Molnar.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14)  * 2003-08-11    2.6 port by Matt Mackall
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15)  *               simplified options
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16)  *               generic card hooks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17)  *               works non-modular
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18)  * 2003-09-07    rewritten with netpoll api
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) /****************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23)  ****************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) #include <linux/console.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) #include <linux/moduleparam.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) #include <linux/netpoll.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) #include <linux/inet.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) #include <linux/configfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) #include <linux/etherdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) MODULE_AUTHOR("Maintainer: Matt Mackall <mpm@selenic.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) MODULE_DESCRIPTION("Console driver for network interfaces");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) #define MAX_PARAM_LENGTH	256
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) #define MAX_PRINT_CHUNK		1000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) static char config[MAX_PARAM_LENGTH];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) module_param_string(netconsole, config, MAX_PARAM_LENGTH, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) MODULE_PARM_DESC(netconsole, " netconsole=[src-port]@[src-ip]/[dev],[tgt-port]@<tgt-ip>/[tgt-macaddr]");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) static bool oops_only = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) module_param(oops_only, bool, 0600);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) MODULE_PARM_DESC(oops_only, "Only log oops messages");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) #ifndef	MODULE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) static int __init option_setup(char *opt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 	strlcpy(config, opt, MAX_PARAM_LENGTH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) __setup("netconsole=", option_setup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) #endif	/* MODULE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) /* Linked list of all configured targets */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) static LIST_HEAD(target_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) /* This needs to be a spinlock because write_msg() cannot sleep */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) static DEFINE_SPINLOCK(target_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71)  * Console driver for extended netconsoles.  Registered on the first use to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72)  * avoid unnecessarily enabling ext message formatting.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) static struct console netconsole_ext;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77)  * struct netconsole_target - Represents a configured netconsole target.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78)  * @list:	Links this target into the target_list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79)  * @item:	Links us into the configfs subsystem hierarchy.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80)  * @enabled:	On / off knob to enable / disable target.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81)  *		Visible from userspace (read-write).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82)  *		We maintain a strict 1:1 correspondence between this and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83)  *		whether the corresponding netpoll is active or inactive.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84)  *		Also, other parameters of a target may be modified at
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85)  *		runtime only when it is disabled (enabled == 0).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86)  * @np:		The netpoll structure for this target.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87)  *		Contains the other userspace visible parameters:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88)  *		dev_name	(read-write)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89)  *		local_port	(read-write)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90)  *		remote_port	(read-write)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91)  *		local_ip	(read-write)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92)  *		remote_ip	(read-write)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93)  *		local_mac	(read-only)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94)  *		remote_mac	(read-write)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) struct netconsole_target {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	struct list_head	list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) #ifdef	CONFIG_NETCONSOLE_DYNAMIC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	struct config_item	item;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	bool			enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	bool			extended;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	struct netpoll		np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) #ifdef	CONFIG_NETCONSOLE_DYNAMIC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) static struct configfs_subsystem netconsole_subsys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) static DEFINE_MUTEX(dynamic_netconsole_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) static int __init dynamic_netconsole_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 	config_group_init(&netconsole_subsys.su_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	mutex_init(&netconsole_subsys.su_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	return configfs_register_subsystem(&netconsole_subsys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) static void __exit dynamic_netconsole_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	configfs_unregister_subsystem(&netconsole_subsys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)  * Targets that were created by parsing the boot/module option string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)  * do not exist in the configfs hierarchy (and have NULL names) and will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)  * never go away, so make these a no-op for them.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) static void netconsole_target_get(struct netconsole_target *nt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	if (config_item_name(&nt->item))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 		config_item_get(&nt->item);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) static void netconsole_target_put(struct netconsole_target *nt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	if (config_item_name(&nt->item))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 		config_item_put(&nt->item);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) #else	/* !CONFIG_NETCONSOLE_DYNAMIC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) static int __init dynamic_netconsole_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) static void __exit dynamic_netconsole_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)  * No danger of targets going away from under us when dynamic
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)  * reconfigurability is off.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) static void netconsole_target_get(struct netconsole_target *nt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) static void netconsole_target_put(struct netconsole_target *nt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) #endif	/* CONFIG_NETCONSOLE_DYNAMIC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) /* Allocate new target (from boot/module param) and setup netpoll for it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) static struct netconsole_target *alloc_param_target(char *target_config)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 	int err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 	struct netconsole_target *nt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	 * Allocate and initialize with defaults.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 	 * Note that these targets get their config_item fields zeroed-out.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 	nt = kzalloc(sizeof(*nt), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	if (!nt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 		goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 	nt->np.name = "netconsole";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	strlcpy(nt->np.dev_name, "eth0", IFNAMSIZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 	nt->np.local_port = 6665;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 	nt->np.remote_port = 6666;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 	eth_broadcast_addr(nt->np.remote_mac);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 	if (*target_config == '+') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 		nt->extended = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 		target_config++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	/* Parse parameters and setup netpoll */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 	err = netpoll_parse_options(&nt->np, target_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 	if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 		goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 	err = netpoll_setup(&nt->np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 	if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 		goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 	nt->enabled = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 	return nt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 	kfree(nt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 	return ERR_PTR(err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) /* Cleanup netpoll for given target (from boot/module param) and free it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) static void free_param_target(struct netconsole_target *nt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 	netpoll_cleanup(&nt->np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 	kfree(nt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) #ifdef	CONFIG_NETCONSOLE_DYNAMIC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)  * Our subsystem hierarchy is:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)  * /sys/kernel/config/netconsole/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)  *				|
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)  *				<target>/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)  *				|	enabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)  *				|	dev_name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)  *				|	local_port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)  *				|	remote_port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)  *				|	local_ip
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)  *				|	remote_ip
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)  *				|	local_mac
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)  *				|	remote_mac
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)  *				|
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)  *				<target>/...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) static struct netconsole_target *to_target(struct config_item *item)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 	return item ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 		container_of(item, struct netconsole_target, item) :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 		NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)  * Attribute operations for netconsole_target.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) static ssize_t enabled_show(struct config_item *item, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 	return snprintf(buf, PAGE_SIZE, "%d\n", to_target(item)->enabled);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) static ssize_t extended_show(struct config_item *item, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 	return snprintf(buf, PAGE_SIZE, "%d\n", to_target(item)->extended);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) static ssize_t dev_name_show(struct config_item *item, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 	return snprintf(buf, PAGE_SIZE, "%s\n", to_target(item)->np.dev_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) static ssize_t local_port_show(struct config_item *item, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 	return snprintf(buf, PAGE_SIZE, "%d\n", to_target(item)->np.local_port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) static ssize_t remote_port_show(struct config_item *item, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 	return snprintf(buf, PAGE_SIZE, "%d\n", to_target(item)->np.remote_port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) static ssize_t local_ip_show(struct config_item *item, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 	struct netconsole_target *nt = to_target(item);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 	if (nt->np.ipv6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 		return snprintf(buf, PAGE_SIZE, "%pI6c\n", &nt->np.local_ip.in6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 		return snprintf(buf, PAGE_SIZE, "%pI4\n", &nt->np.local_ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) static ssize_t remote_ip_show(struct config_item *item, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 	struct netconsole_target *nt = to_target(item);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 	if (nt->np.ipv6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 		return snprintf(buf, PAGE_SIZE, "%pI6c\n", &nt->np.remote_ip.in6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 		return snprintf(buf, PAGE_SIZE, "%pI4\n", &nt->np.remote_ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) static ssize_t local_mac_show(struct config_item *item, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 	struct net_device *dev = to_target(item)->np.dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 	static const u8 bcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 	return snprintf(buf, PAGE_SIZE, "%pM\n", dev ? dev->dev_addr : bcast);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) static ssize_t remote_mac_show(struct config_item *item, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 	return snprintf(buf, PAGE_SIZE, "%pM\n", to_target(item)->np.remote_mac);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)  * This one is special -- targets created through the configfs interface
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)  * are not enabled (and the corresponding netpoll activated) by default.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)  * The user is expected to set the desired parameters first (which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)  * would enable him to dynamically add new netpoll targets for new
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)  * network interfaces as and when they come up).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) static ssize_t enabled_store(struct config_item *item,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 		const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 	struct netconsole_target *nt = to_target(item);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 	int enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 	mutex_lock(&dynamic_netconsole_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 	err = kstrtoint(buf, 10, &enabled);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 	if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 		goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 	err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 	if (enabled < 0 || enabled > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 		goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 	if ((bool)enabled == nt->enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 		pr_info("network logging has already %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 			nt->enabled ? "started" : "stopped");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 		goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 	if (enabled) {	/* true */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 		if (nt->extended && !(netconsole_ext.flags & CON_ENABLED)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 			netconsole_ext.flags |= CON_ENABLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 			register_console(&netconsole_ext);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 		 * Skip netpoll_parse_options() -- all the attributes are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 		 * already configured via configfs. Just print them out.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 		netpoll_print_options(&nt->np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 		err = netpoll_setup(&nt->np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 		if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 			goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 		pr_info("network logging started\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 	} else {	/* false */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 		/* We need to disable the netconsole before cleaning it up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 		 * otherwise we might end up in write_msg() with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 		 * nt->np.dev == NULL and nt->enabled == true
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 		spin_lock_irqsave(&target_list_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 		nt->enabled = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 		spin_unlock_irqrestore(&target_list_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 		netpoll_cleanup(&nt->np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 	nt->enabled = enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 	mutex_unlock(&dynamic_netconsole_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 	return strnlen(buf, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) out_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 	mutex_unlock(&dynamic_netconsole_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) static ssize_t extended_store(struct config_item *item, const char *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 		size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 	struct netconsole_target *nt = to_target(item);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 	int extended;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 	mutex_lock(&dynamic_netconsole_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 	if (nt->enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 		pr_err("target (%s) is enabled, disable to update parameters\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 		       config_item_name(&nt->item));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 		err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 		goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 	err = kstrtoint(buf, 10, &extended);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 	if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 		goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 	if (extended < 0 || extended > 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 		err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 		goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 	nt->extended = extended;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 	mutex_unlock(&dynamic_netconsole_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 	return strnlen(buf, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) out_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 	mutex_unlock(&dynamic_netconsole_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) static ssize_t dev_name_store(struct config_item *item, const char *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 		size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 	struct netconsole_target *nt = to_target(item);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 	size_t len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 	mutex_lock(&dynamic_netconsole_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 	if (nt->enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 		pr_err("target (%s) is enabled, disable to update parameters\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 		       config_item_name(&nt->item));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 		mutex_unlock(&dynamic_netconsole_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 	strlcpy(nt->np.dev_name, buf, IFNAMSIZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 	/* Get rid of possible trailing newline from echo(1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 	len = strnlen(nt->np.dev_name, IFNAMSIZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 	if (nt->np.dev_name[len - 1] == '\n')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 		nt->np.dev_name[len - 1] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 	mutex_unlock(&dynamic_netconsole_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 	return strnlen(buf, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) static ssize_t local_port_store(struct config_item *item, const char *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 		size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 	struct netconsole_target *nt = to_target(item);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 	int rv = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 	mutex_lock(&dynamic_netconsole_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 	if (nt->enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 		pr_err("target (%s) is enabled, disable to update parameters\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 		       config_item_name(&nt->item));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 		goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 	rv = kstrtou16(buf, 10, &nt->np.local_port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 	if (rv < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 		goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 	mutex_unlock(&dynamic_netconsole_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 	return strnlen(buf, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) out_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 	mutex_unlock(&dynamic_netconsole_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 	return rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) static ssize_t remote_port_store(struct config_item *item,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 		const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 	struct netconsole_target *nt = to_target(item);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 	int rv = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 	mutex_lock(&dynamic_netconsole_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 	if (nt->enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 		pr_err("target (%s) is enabled, disable to update parameters\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 		       config_item_name(&nt->item));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 		goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 	rv = kstrtou16(buf, 10, &nt->np.remote_port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 	if (rv < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 		goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 	mutex_unlock(&dynamic_netconsole_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 	return strnlen(buf, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) out_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 	mutex_unlock(&dynamic_netconsole_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 	return rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) static ssize_t local_ip_store(struct config_item *item, const char *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) 		size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) 	struct netconsole_target *nt = to_target(item);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 	mutex_lock(&dynamic_netconsole_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 	if (nt->enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 		pr_err("target (%s) is enabled, disable to update parameters\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) 		       config_item_name(&nt->item));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 		goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) 	if (strnchr(buf, count, ':')) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 		const char *end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 		if (in6_pton(buf, count, nt->np.local_ip.in6.s6_addr, -1, &end) > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 			if (*end && *end != '\n') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) 				pr_err("invalid IPv6 address at: <%c>\n", *end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 				goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 			nt->np.ipv6 = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 		} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 			goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) 		if (!nt->np.ipv6) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 			nt->np.local_ip.ip = in_aton(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) 		} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 			goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) 	mutex_unlock(&dynamic_netconsole_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) 	return strnlen(buf, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) out_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) 	mutex_unlock(&dynamic_netconsole_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) 	return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) static ssize_t remote_ip_store(struct config_item *item, const char *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) 	       size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) 	struct netconsole_target *nt = to_target(item);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) 	mutex_lock(&dynamic_netconsole_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) 	if (nt->enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) 		pr_err("target (%s) is enabled, disable to update parameters\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) 		       config_item_name(&nt->item));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) 		goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) 	if (strnchr(buf, count, ':')) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) 		const char *end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) 		if (in6_pton(buf, count, nt->np.remote_ip.in6.s6_addr, -1, &end) > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) 			if (*end && *end != '\n') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) 				pr_err("invalid IPv6 address at: <%c>\n", *end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) 				goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) 			nt->np.ipv6 = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) 		} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) 			goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) 		if (!nt->np.ipv6) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) 			nt->np.remote_ip.ip = in_aton(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) 		} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) 			goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) 	mutex_unlock(&dynamic_netconsole_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) 	return strnlen(buf, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) out_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) 	mutex_unlock(&dynamic_netconsole_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) 	return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) static ssize_t remote_mac_store(struct config_item *item, const char *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) 		size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) 	struct netconsole_target *nt = to_target(item);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) 	u8 remote_mac[ETH_ALEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) 	mutex_lock(&dynamic_netconsole_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) 	if (nt->enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) 		pr_err("target (%s) is enabled, disable to update parameters\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) 		       config_item_name(&nt->item));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) 		goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) 	if (!mac_pton(buf, remote_mac))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) 		goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) 	if (buf[3 * ETH_ALEN - 1] && buf[3 * ETH_ALEN - 1] != '\n')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) 		goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) 	memcpy(nt->np.remote_mac, remote_mac, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) 	mutex_unlock(&dynamic_netconsole_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) 	return strnlen(buf, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) out_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) 	mutex_unlock(&dynamic_netconsole_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) 	return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) CONFIGFS_ATTR(, enabled);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) CONFIGFS_ATTR(, extended);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) CONFIGFS_ATTR(, dev_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) CONFIGFS_ATTR(, local_port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) CONFIGFS_ATTR(, remote_port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) CONFIGFS_ATTR(, local_ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) CONFIGFS_ATTR(, remote_ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) CONFIGFS_ATTR_RO(, local_mac);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) CONFIGFS_ATTR(, remote_mac);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) static struct configfs_attribute *netconsole_target_attrs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) 	&attr_enabled,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) 	&attr_extended,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) 	&attr_dev_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) 	&attr_local_port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) 	&attr_remote_port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) 	&attr_local_ip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) 	&attr_remote_ip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) 	&attr_local_mac,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) 	&attr_remote_mac,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) 	NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595)  * Item operations and type for netconsole_target.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) static void netconsole_target_release(struct config_item *item)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) 	kfree(to_target(item));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) static struct configfs_item_operations netconsole_target_item_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) 	.release		= netconsole_target_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) static const struct config_item_type netconsole_target_type = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) 	.ct_attrs		= netconsole_target_attrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) 	.ct_item_ops		= &netconsole_target_item_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) 	.ct_owner		= THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614)  * Group operations and type for netconsole_subsys.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) static struct config_item *make_netconsole_target(struct config_group *group,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) 						  const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) 	struct netconsole_target *nt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) 	 * Allocate and initialize with defaults.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) 	 * Target is disabled at creation (!enabled).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) 	nt = kzalloc(sizeof(*nt), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) 	if (!nt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) 		return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) 	nt->np.name = "netconsole";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) 	strlcpy(nt->np.dev_name, "eth0", IFNAMSIZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) 	nt->np.local_port = 6665;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) 	nt->np.remote_port = 6666;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) 	eth_broadcast_addr(nt->np.remote_mac);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) 	/* Initialize the config_item member */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) 	config_item_init_type_name(&nt->item, name, &netconsole_target_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) 	/* Adding, but it is disabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) 	spin_lock_irqsave(&target_list_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) 	list_add(&nt->list, &target_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) 	spin_unlock_irqrestore(&target_list_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) 	return &nt->item;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) static void drop_netconsole_target(struct config_group *group,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) 				   struct config_item *item)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) 	struct netconsole_target *nt = to_target(item);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) 	spin_lock_irqsave(&target_list_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) 	list_del(&nt->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) 	spin_unlock_irqrestore(&target_list_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) 	 * The target may have never been enabled, or was manually disabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) 	 * before being removed so netpoll may have already been cleaned up.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) 	if (nt->enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) 		netpoll_cleanup(&nt->np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) 	config_item_put(&nt->item);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) static struct configfs_group_operations netconsole_subsys_group_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) 	.make_item	= make_netconsole_target,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) 	.drop_item	= drop_netconsole_target,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) static const struct config_item_type netconsole_subsys_type = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) 	.ct_group_ops	= &netconsole_subsys_group_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) 	.ct_owner	= THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) /* The netconsole configfs subsystem */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) static struct configfs_subsystem netconsole_subsys = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) 	.su_group	= {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) 		.cg_item	= {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) 			.ci_namebuf	= "netconsole",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) 			.ci_type	= &netconsole_subsys_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) 		},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) #endif	/* CONFIG_NETCONSOLE_DYNAMIC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) /* Handle network interface device notifications */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) static int netconsole_netdev_event(struct notifier_block *this,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) 				   unsigned long event, void *ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) 	struct netconsole_target *nt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) 	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) 	bool stopped = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) 	if (!(event == NETDEV_CHANGENAME || event == NETDEV_UNREGISTER ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) 	      event == NETDEV_RELEASE || event == NETDEV_JOIN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) 		goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) 	spin_lock_irqsave(&target_list_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) restart:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) 	list_for_each_entry(nt, &target_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) 		netconsole_target_get(nt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) 		if (nt->np.dev == dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) 			switch (event) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) 			case NETDEV_CHANGENAME:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) 				strlcpy(nt->np.dev_name, dev->name, IFNAMSIZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) 			case NETDEV_RELEASE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) 			case NETDEV_JOIN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) 			case NETDEV_UNREGISTER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) 				/* rtnl_lock already held
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) 				 * we might sleep in __netpoll_cleanup()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) 				 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) 				spin_unlock_irqrestore(&target_list_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) 				__netpoll_cleanup(&nt->np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) 				spin_lock_irqsave(&target_list_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) 				dev_put(nt->np.dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) 				nt->np.dev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) 				nt->enabled = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) 				stopped = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) 				netconsole_target_put(nt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) 				goto restart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) 		netconsole_target_put(nt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) 	spin_unlock_irqrestore(&target_list_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) 	if (stopped) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) 		const char *msg = "had an event";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) 		switch (event) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) 		case NETDEV_UNREGISTER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) 			msg = "unregistered";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) 		case NETDEV_RELEASE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) 			msg = "released slaves";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) 		case NETDEV_JOIN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) 			msg = "is joining a master device";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) 		pr_info("network logging stopped on interface %s as it %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) 			dev->name, msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) 	return NOTIFY_DONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) static struct notifier_block netconsole_netdev_notifier = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) 	.notifier_call  = netconsole_netdev_event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760)  * send_ext_msg_udp - send extended log message to target
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761)  * @nt: target to send message to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762)  * @msg: extended log message to send
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763)  * @msg_len: length of message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765)  * Transfer extended log @msg to @nt.  If @msg is longer than
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766)  * MAX_PRINT_CHUNK, it'll be split and transmitted in multiple chunks with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767)  * ncfrag header field added to identify them.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) static void send_ext_msg_udp(struct netconsole_target *nt, const char *msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) 			     int msg_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) 	static char buf[MAX_PRINT_CHUNK]; /* protected by target_list_lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) 	const char *header, *body;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) 	int offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) 	int header_len, body_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) 	if (msg_len <= MAX_PRINT_CHUNK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) 		netpoll_send_udp(&nt->np, msg, msg_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) 	/* need to insert extra header fields, detect header and body */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) 	header = msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) 	body = memchr(msg, ';', msg_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) 	if (WARN_ON_ONCE(!body))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) 	header_len = body - header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) 	body_len = msg_len - header_len - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) 	body++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) 	 * Transfer multiple chunks with the following extra header.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) 	 * "ncfrag=<byte-offset>/<total-bytes>"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) 	memcpy(buf, header, header_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) 	while (offset < body_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) 		int this_header = header_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) 		int this_chunk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) 		this_header += scnprintf(buf + this_header,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) 					 sizeof(buf) - this_header,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) 					 ",ncfrag=%d/%d;", offset, body_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) 		this_chunk = min(body_len - offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) 				 MAX_PRINT_CHUNK - this_header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) 		if (WARN_ON_ONCE(this_chunk <= 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) 			return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) 		memcpy(buf + this_header, body + offset, this_chunk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) 		netpoll_send_udp(&nt->np, buf, this_header + this_chunk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) 		offset += this_chunk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) static void write_ext_msg(struct console *con, const char *msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) 			  unsigned int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) 	struct netconsole_target *nt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) 	if ((oops_only && !oops_in_progress) || list_empty(&target_list))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) 	spin_lock_irqsave(&target_list_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) 	list_for_each_entry(nt, &target_list, list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) 		if (nt->extended && nt->enabled && netif_running(nt->np.dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) 			send_ext_msg_udp(nt, msg, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) 	spin_unlock_irqrestore(&target_list_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) static void write_msg(struct console *con, const char *msg, unsigned int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) 	int frag, left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) 	struct netconsole_target *nt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) 	const char *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) 	if (oops_only && !oops_in_progress)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) 	/* Avoid taking lock and disabling interrupts unnecessarily */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) 	if (list_empty(&target_list))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) 	spin_lock_irqsave(&target_list_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) 	list_for_each_entry(nt, &target_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) 		if (!nt->extended && nt->enabled && netif_running(nt->np.dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) 			/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) 			 * We nest this inside the for-each-target loop above
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) 			 * so that we're able to get as much logging out to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) 			 * at least one target if we die inside here, instead
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) 			 * of unnecessarily keeping all targets in lock-step.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) 			tmp = msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) 			for (left = len; left;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) 				frag = min(left, MAX_PRINT_CHUNK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) 				netpoll_send_udp(&nt->np, tmp, frag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) 				tmp += frag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) 				left -= frag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) 	spin_unlock_irqrestore(&target_list_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) static struct console netconsole_ext = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) 	.name	= "netcon_ext",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) 	.flags	= CON_EXTENDED,	/* starts disabled, registered on first use */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) 	.write	= write_ext_msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) static struct console netconsole = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) 	.name	= "netcon",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) 	.flags	= CON_ENABLED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) 	.write	= write_msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) static int __init init_netconsole(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) 	struct netconsole_target *nt, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) 	char *target_config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) 	char *input = config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) 	if (strnlen(input, MAX_PARAM_LENGTH)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) 		while ((target_config = strsep(&input, ";"))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) 			nt = alloc_param_target(target_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) 			if (IS_ERR(nt)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) 				err = PTR_ERR(nt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) 				goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) 			/* Dump existing printks when we register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) 			if (nt->extended)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) 				netconsole_ext.flags |= CON_PRINTBUFFER |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) 							CON_ENABLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) 			else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) 				netconsole.flags |= CON_PRINTBUFFER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) 			spin_lock_irqsave(&target_list_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) 			list_add(&nt->list, &target_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) 			spin_unlock_irqrestore(&target_list_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) 	err = register_netdevice_notifier(&netconsole_netdev_notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) 	if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) 		goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) 	err = dynamic_netconsole_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) 	if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) 		goto undonotifier;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) 	if (netconsole_ext.flags & CON_ENABLED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) 		register_console(&netconsole_ext);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) 	register_console(&netconsole);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) 	pr_info("network logging started\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) undonotifier:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) 	unregister_netdevice_notifier(&netconsole_netdev_notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) 	pr_err("cleaning up\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) 	 * Remove all targets and destroy them (only targets created
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) 	 * from the boot/module option exist here). Skipping the list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) 	 * lock is safe here, and netpoll_cleanup() will sleep.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) 	list_for_each_entry_safe(nt, tmp, &target_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) 		list_del(&nt->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) 		free_param_target(nt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) static void __exit cleanup_netconsole(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) 	struct netconsole_target *nt, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) 	unregister_console(&netconsole_ext);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) 	unregister_console(&netconsole);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) 	dynamic_netconsole_exit();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) 	unregister_netdevice_notifier(&netconsole_netdev_notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) 	 * Targets created via configfs pin references on our module
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) 	 * and would first be rmdir(2)'ed from userspace. We reach
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) 	 * here only when they are already destroyed, and only those
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) 	 * created from the boot/module option are left, so remove and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) 	 * destroy them. Skipping the list lock is safe here, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) 	 * netpoll_cleanup() will sleep.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) 	list_for_each_entry_safe(nt, tmp, &target_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) 		list_del(&nt->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) 		free_param_target(nt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967)  * Use late_initcall to ensure netconsole is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968)  * initialized after network device driver if built-in.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970)  * late_initcall() and module_init() are identical if built as module.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) late_initcall(init_netconsole);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) module_exit(cleanup_netconsole);