param: simple locking for sysfs-writable charp parameters

Since the writing to sysfs can free the old one, we need to block that
when we access.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Reviewed-by: Takashi Iwai <tiwai@suse.de>
---
 arch/um/drivers/hostaudio_kern.c          |   10 ++++++++++
 drivers/net/wireless/libertas/if_usb.c    |    3 +++
 drivers/net/wireless/libertas_tf/if_usb.c |    3 +++
 drivers/scsi/bfa/bfad.c                   |    2 ++
 drivers/usb/atm/ueagle-atm.c              |    2 ++
 drivers/video/vt8623fb.c                  |    2 ++
 net/mac80211/rate.c                       |    2 ++
 7 files changed, 24 insertions(+)

diff --git a/arch/um/drivers/hostaudio_kern.c b/arch/um/drivers/hostaudio_kern.c
--- a/arch/um/drivers/hostaudio_kern.c
+++ b/arch/um/drivers/hostaudio_kern.c
@@ -186,7 +186,9 @@ static int hostaudio_open(struct inode *
 	int ret;
 
 #ifdef DEBUG
+	kparam_block_sysfs_write(dsp);
 	printk(KERN_DEBUG "hostaudio: open called (host: %s)\n", dsp);
+	kparam_unblock_sysfs_write(dsp);
 #endif
 
 	state = kmalloc(sizeof(struct hostaudio_state), GFP_KERNEL);
@@ -198,7 +200,9 @@ static int hostaudio_open(struct inode *
 	if (file->f_mode & FMODE_WRITE)
 		w = 1;
 
+	kparam_block_sysfs_write(dsp);
 	ret = os_open_file(dsp, of_set_rw(OPENFLAGS(), r, w), 0);
+	kparam_unblock_sysfs_write(dsp);
 	if (ret < 0) {
 		kfree(state);
 		return ret;
@@ -254,11 +258,15 @@ static int hostmixer_open_mixdev(struct 
 	if (file->f_mode & FMODE_WRITE)
 		w = 1;
 
+	kparam_block_sysfs_write(mixer);
 	ret = os_open_file(mixer, of_set_rw(OPENFLAGS(), r, w), 0);
+	kparam_unblock_sysfs_write(mixer);
 
 	if (ret < 0) {
+		kparam_block_sysfs_write(dsp);
 		printk(KERN_ERR "hostaudio_open_mixdev failed to open '%s', "
 		       "err = %d\n", dsp, -ret);
+		kparam_unblock_sysfs_write(dsp);
 		kfree(state);
 		return ret;
 	}
@@ -314,8 +322,10 @@ MODULE_LICENSE("GPL");
 
 static int __init hostaudio_init_module(void)
 {
+	__kernel_param_lock();
 	printk(KERN_INFO "UML Audio Relay (host dsp = %s, host mixer = %s)\n",
 	       dsp, mixer);
+	__kernel_param_unlock();
 
 	module_data.dev_audio = register_sound_dsp(&hostaudio_fops, -1);
 	if (module_data.dev_audio < 0) {
diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c
--- a/drivers/net/wireless/libertas/if_usb.c
+++ b/drivers/net/wireless/libertas/if_usb.c
@@ -288,10 +288,13 @@ static int if_usb_probe(struct usb_inter
 	}
 
 	/* Upload firmware */
+	kparam_block_sysfs_write(fw_name);
 	if (__if_usb_prog_firmware(cardp, lbs_fw_name, BOOT_CMD_FW_BY_USB)) {
+		kparam_unblock_sysfs_write(fw_name);
 		lbs_deb_usbd(&udev->dev, "FW upload failed\n");
 		goto err_prog_firmware;
 	}
+	kparam_unblock_sysfs_write(fw_name);
 
 	if (!(priv = lbs_add_card(cardp, &udev->dev)))
 		goto err_prog_firmware;
diff --git a/drivers/net/wireless/libertas_tf/if_usb.c b/drivers/net/wireless/libertas_tf/if_usb.c
--- a/drivers/net/wireless/libertas_tf/if_usb.c
+++ b/drivers/net/wireless/libertas_tf/if_usb.c
@@ -648,12 +648,15 @@ static int if_usb_prog_firmware(struct i
 	static int reset_count = 10;
 	int ret = 0;
 
+	kparam_block_sysfs_write(fw_name);
 	ret = request_firmware(&cardp->fw, lbtf_fw_name, &cardp->udev->dev);
 	if (ret < 0) {
 		printk(KERN_INFO "libertastf: firmware %s not found\n",
 		       lbtf_fw_name);
+		kparam_unblock_sysfs_write(fw_name);
 		goto done;
 	}
+	kparam_unblock_sysfs_write(fw_name);
 
 	if (check_fwfile_format(cardp->fw->data, cardp->fw->size))
 		goto release_fw;
diff --git a/drivers/scsi/bfa/bfad.c b/drivers/scsi/bfa/bfad.c
--- a/drivers/scsi/bfa/bfad.c
+++ b/drivers/scsi/bfa/bfad.c
@@ -726,6 +726,7 @@ bfad_drv_init(struct bfad_s *bfad)
 	memset(&driver_info, 0, sizeof(driver_info));
 	strncpy(driver_info.version, BFAD_DRIVER_VERSION,
 		sizeof(driver_info.version) - 1);
+	__kernel_param_lock();
 	if (host_name)
 		strncpy(driver_info.host_machine_name, host_name,
 			sizeof(driver_info.host_machine_name) - 1);
@@ -735,6 +736,7 @@ bfad_drv_init(struct bfad_s *bfad)
 	if (os_patch)
 		strncpy(driver_info.host_os_patch, os_patch,
 			sizeof(driver_info.host_os_patch) - 1);
+	__kernel_param_unlock();
 
 	strncpy(driver_info.os_device_name, bfad->pci_name,
 		sizeof(driver_info.os_device_name - 1));
diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c
--- a/drivers/usb/atm/ueagle-atm.c
+++ b/drivers/usb/atm/ueagle-atm.c
@@ -1550,6 +1550,7 @@ static void cmvs_file_name(struct uea_so
 	char file_arr[] = "CMVxy.bin";
 	char *file;
 
+	kparam_block_sysfs_write(cmv_file);
 	/* set proper name corresponding modem version and line type */
 	if (cmv_file[sc->modem_index] == NULL) {
 		if (UEA_CHIP_VERSION(sc) == ADI930)
@@ -1568,6 +1569,7 @@ static void cmvs_file_name(struct uea_so
 	strlcat(cmv_name, file, UEA_FW_NAME_MAX);
 	if (ver == 2)
 		strlcat(cmv_name, ".v2", UEA_FW_NAME_MAX);
+	kparam_unblock_sysfs_write(cmv_file);
 }
 
 static int request_cmvs_old(struct uea_softc *sc,
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c
--- a/net/mac80211/rate.c
+++ b/net/mac80211/rate.c
@@ -102,6 +102,7 @@ ieee80211_rate_control_ops_get(const cha
 	struct rate_control_ops *ops;
 	const char *alg_name;
 
+	kparam_block_sysfs_write(ieee80211_default_rc_algo);
 	if (!name)
 		alg_name = ieee80211_default_rc_algo;
 	else
@@ -119,6 +120,7 @@ ieee80211_rate_control_ops_get(const cha
 	/* try built-in one if specific alg requested but not found */
 	if (!ops && strlen(CONFIG_MAC80211_RC_DEFAULT))
 		ops = ieee80211_try_rate_control_ops_get(CONFIG_MAC80211_RC_DEFAULT);
+	kparam_unblock_sysfs_write(ieee80211_default_rc_algo);
 
 	return ops;
 }
diff --git a/drivers/video/vt8623fb.c b/drivers/video/vt8623fb.c
--- a/drivers/video/vt8623fb.c
+++ b/drivers/video/vt8623fb.c
@@ -727,7 +727,9 @@ static int __devinit vt8623_pci_probe(st
 
 	/* Prepare startup mode */
 
+	kparam_block_sysfs_write(mode_option);
 	rc = fb_find_mode(&(info->var), info, mode_option, NULL, 0, NULL, 8);
+	kparam_unblock_sysfs_write(mode_option);
 	if (! ((rc == 1) || (rc == 2))) {
 		rc = -EINVAL;
 		dev_err(info->device, "mode %s not found\n", mode_option);
