public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Matthew Galgoci <mgalgoci@redhat.com>
To: Andrew Morton <andrewm@uow.edu.au>
Cc: linux-kernel@vger.kernel.org, torvalds@transmeta.com
Subject: Re: cardbus pirq conflict
Date: Mon, 11 Dec 2000 12:48:16 -0500	[thread overview]
Message-ID: <20001211124816.L3738@redhat.com> (raw)
In-Reply-To: <20001208130148.B19712@redhat.com> <3A3191FE.83C14585@uow.edu.au>
In-Reply-To: <3A3191FE.83C14585@uow.edu.au>; from andrewm@uow.edu.au on Sat, Dec 09, 2000 at 12:59:26PM +1100


Hello,

I tried this patch against test12-pre7, and all that I get is 
"cs: socket c7604800 timed out during reset. Try increasing
setup_delay." 

Performing cardctl reset yields the same message. I think that 
cardctl reset takes away the possibility that increasing
setup_delay would actually help.

The Oops on shutdown no longer occurs, so I believe that you
have fixed the race contition you descdibed. The Oops was
also occuring on apm resume, but that has ceased as well.

I will try testing some other cardbus cards later today, and will
also experiment with an unpatch test12-pre8

Cheers!

--Matt Galgoci

> 
> Could you please test this stuff?
> 
> 
> 
> --- linux-2.4.0-test12-pre7/include/linux/sched.h	Thu Dec  7 22:05:21 2000
> +++ linux-akpm/include/linux/sched.h	Sat Dec  9 01:36:19 2000
> @@ -152,6 +152,7 @@
>  extern int schedule_task(struct tq_struct *task);
>  extern void run_schedule_tasks(void);
>  extern int start_context_thread(void);
> +extern int current_is_keventd(void);
>  
>  /*
>   * The default fd array needs to be at least BITS_PER_LONG,
> --- linux-2.4.0-test12-pre7/include/linux/kernel.h	Thu Dec  7 22:05:21 2000
> +++ linux-akpm/include/linux/kernel.h	Sat Dec  9 01:22:18 2000
> @@ -63,6 +63,8 @@
>  extern int get_option(char **str, int *pint);
>  extern char *get_options(char *str, int nints, int *ints);
>  extern unsigned long memparse(char *ptr, char **retptr);
> +extern void dev_probe_lock(void);
> +extern void dev_probe_unlock(void);
>  
>  extern int session_of_pgrp(int pgrp);
>  
> --- linux-2.4.0-test12-pre7/drivers/pci/pci.c	Thu Dec  7 22:05:20 2000
> +++ linux-akpm/drivers/pci/pci.c	Sat Dec  9 01:24:46 2000
> @@ -300,18 +300,25 @@
>  pci_announce_device(struct pci_driver *drv, struct pci_dev *dev)
>  {
>  	const struct pci_device_id *id;
> +	int ret = 0;
>  
>  	if (drv->id_table) {
>  		id = pci_match_device(drv->id_table, dev);
> -		if (!id)
> -			return 0;
> +		if (!id) {
> +			ret = 0;
> +			goto out;
> +		}
>  	} else
>  		id = NULL;
> +
> +	dev_probe_lock();
>  	if (drv->probe(dev, id) >= 0) {
>  		dev->driver = drv;
> -		return 1;
> +		ret = 1;
>  	}
> -	return 0;
> +	dev_probe_unlock();
> +out:
> +	return ret;
>  }
>  
>  int
> @@ -360,9 +367,9 @@
>  	if (!hotplug_path[0])
>  		return;
>  
> -	sprintf(class_id, "PCI_CLASS=%X", pdev->class);
> -	sprintf(id, "PCI_ID=%X/%X", pdev->vendor, pdev->device);
> -	sprintf(sub_id, "PCI_SUBSYS_ID=%X/%X", pdev->subsystem_vendor, pdev->subsystem_device);
> +	sprintf(class_id, "PCI_CLASS=%04X", pdev->class);
> +	sprintf(id, "PCI_ID=%04X:%04X", pdev->vendor, pdev->device);
> +	sprintf(sub_id, "PCI_SUBSYS_ID=%04X:%04X", pdev->subsystem_vendor, pdev->subsystem_device);
>  	sprintf(bus_id, "PCI_SLOT_NAME=%s", pdev->slot_name);
>  
>  	i = 0;
> --- linux-2.4.0-test12-pre7/kernel/exit.c	Thu Dec  7 22:05:21 2000
> +++ linux-akpm/kernel/exit.c	Fri Dec  8 22:38:30 2000
> @@ -302,9 +302,9 @@
>  {
>  	struct mm_struct * mm = tsk->mm;
>  
> +	mm_release();
>  	if (mm) {
>  		atomic_inc(&mm->mm_count);
> -		mm_release();
>  		if (mm != tsk->active_mm) BUG();
>  		/* more a memory barrier than a real lock */
>  		task_lock(tsk);
> --- linux-2.4.0-test12-pre7/kernel/kmod.c	Thu Dec  7 22:05:21 2000
> +++ linux-akpm/kernel/kmod.c	Sat Dec  9 11:53:32 2000
> @@ -256,21 +256,6 @@
>  
>  #endif /* CONFIG_HOTPLUG */
>  
> -
> -static int exec_helper (void *arg)
> -{
> -	long ret;
> -	void **params = (void **) arg;
> -	char *path = (char *) params [0];
> -	char **argv = (char **) params [1];
> -	char **envp = (char **) params [2];
> -
> -	ret = exec_usermodehelper (path, argv, envp);
> -	if (ret < 0)
> -		ret = -ret;
> -	do_exit(ret);
> -}
> -
>  struct subprocess_info {
>  	struct semaphore *sem;
>  	char *path;
> @@ -279,73 +264,36 @@
>  	int retval;
>  };
>  
> -/*
> - * This is a standalone child of keventd.  It forks off another thread which
> - * is the desired usermode helper and then waits for the child to exit.
> - * We return the usermode process's exit code, or some -ve error code.
> - */
>  static int ____call_usermodehelper(void *data)
>  {
>  	struct subprocess_info *sub_info = data;
> -	struct task_struct *curtask = current;
> -	void *params [3] = { sub_info->path, sub_info->argv, sub_info->envp };
> -	pid_t pid, pid2;
> -	mm_segment_t fs;
> -	int retval = 0;
> +	int retval;
>  
> -	if (!curtask->fs->root) {
> -		printk(KERN_ERR "call_usermodehelper[%s]: no root fs\n", sub_info->path);
> -		retval = -EPERM;
> -		goto up_and_out;
> -	}
> -	if ((pid = kernel_thread(exec_helper, (void *) params, 0)) < 0) {
> -		printk(KERN_ERR "failed fork2 %s, errno = %d", sub_info->argv[0], -pid);
> -		retval = pid;
> -		goto up_and_out;
> -	}
> +	retval = -EPERM;
> +	if (current->fs->root)
> +		retval = exec_usermodehelper(sub_info->path, sub_info->argv, sub_info->envp);
>  
> -	if (retval >= 0) {
> -		/* Block everything but SIGKILL/SIGSTOP */
> -		spin_lock_irq(&curtask->sigmask_lock);
> -		siginitsetinv(&curtask->blocked, sigmask(SIGKILL) | sigmask(SIGSTOP));
> -		recalc_sigpending(curtask);
> -		spin_unlock_irq(&curtask->sigmask_lock);
> -
> -		/* Allow the system call to access kernel memory */
> -		fs = get_fs();
> -		set_fs(KERNEL_DS);
> -		pid2 = waitpid(pid, &retval, __WCLONE);
> -		if (pid2 == -1 && errno < 0)
> -			pid2 = errno;
> -		set_fs(fs);
> -
> -		if (pid2 != pid) {
> -			printk(KERN_ERR "waitpid(%d) failed, %d\n", pid, pid2);
> -			retval = (pid2 < 0) ? pid2 : -1;
> -		}
> -	}
> -
> -up_and_out:
> +	/* Exec failed? */
>  	sub_info->retval = retval;
> -	curtask->exit_signal = SIGCHLD;		/* Wake up parent */
> -	up_and_exit(sub_info->sem, retval);
> +	do_exit(0);
>  }
>  
>  /*
> - * This is a schedule_task function, so we must not sleep for very long at all.
> - * But the exec'ed process could do anything at all.  So we launch another
> - * kernel thread.
> + * This is run by keventd.
>   */
>  static void __call_usermodehelper(void *data)
>  {
>  	struct subprocess_info *sub_info = data;
>  	pid_t pid;
>  
> -	if ((pid = kernel_thread (____call_usermodehelper, (void *)sub_info, 0)) < 0) {
> -		printk(KERN_ERR "failed fork1 %s, errno = %d", sub_info->argv[0], -pid);
> +	/*
> +	 * CLONE_VFORK: wait until the usermode helper has execve'd successfully
> +	 * We need the data structures to stay around until that is done.
> +	 */
> +	pid = kernel_thread (____call_usermodehelper, sub_info, CLONE_VFORK | SIGCHLD);
> +	if (pid < 0)
>  		sub_info->retval = pid;
> -		up(sub_info->sem);
> -	}
> +	up(sub_info->sem);
>  }
>  
>  /*
> @@ -358,22 +306,50 @@
>  {
>  	DECLARE_MUTEX_LOCKED(sem);
>  	struct subprocess_info sub_info = {
> -		sem:	&sem,
> -		path:	path,
> -		argv:	argv,
> -		envp:	envp,
> -		retval:	0,
> -	};
> -	struct tq_struct tqs = {
> -		next:		0,
> -		sync:		0,
> -		routine:	__call_usermodehelper,
> -		data:		&sub_info,
> +		sem:		&sem,
> +		path:		path,
> +		argv:		argv,
> +		envp:		envp,
> +		retval:		0,
>  	};
> +	int retval = 0;
> +
> +	if (path[0] == '\0')
> +		goto out;
>  
> -	schedule_task(&tqs);
> -	down(&sem);		/* Wait for an error or completion */
> -	return sub_info.retval;
> +	if (current_is_keventd()) {
> +		/* We can't wait on keventd! */
> +		__call_usermodehelper(&sub_info);
> +	} else {
> +		struct tq_struct tqs = {
> +			next:		0,
> +			sync:		0,
> +			routine:	__call_usermodehelper,
> +			data:		&sub_info,
> +		};
> +
> +		schedule_task(&tqs);
> +		down(&sem);		/* Wait for an error or completion */
> +	}
> +	retval = sub_info.retval;
> +out:
> +	return retval;
> +}
> +
> +/*
> + * This is for the serialisation of device probe() functions
> + * against device open() functions
> + */
> +static DECLARE_MUTEX(dev_probe_sem);
> +
> +void dev_probe_lock(void)
> +{
> +	down(&dev_probe_sem);
> +}
> +
> +void dev_probe_unlock(void)
> +{
> +	up(&dev_probe_sem);
>  }
>  
>  EXPORT_SYMBOL(exec_usermodehelper);
> --- linux-2.4.0-test12-pre7/kernel/context.c	Thu Dec  7 22:05:21 2000
> +++ linux-akpm/kernel/context.c	Fri Dec  8 22:38:30 2000
> @@ -18,6 +18,17 @@
>  static DECLARE_TASK_QUEUE(tq_context);
>  static DECLARE_WAIT_QUEUE_HEAD(context_task_wq);
>  static int keventd_running;
> +static struct task_struct *keventd_task;
> +
> +int current_is_keventd(void)
> +{
> +	int ret = 0;
> +	if (keventd_running == 0)
> +		printk(KERN_ERR "current_is_keventd(): keventd has not started\n");
> +	else
> +		ret = (current == keventd_task);
> +	return ret;
> +}
>  
>  int schedule_task(struct tq_struct *task)
>  {
> @@ -38,6 +49,7 @@
>  	daemonize();
>  	strcpy(curtask->comm, "keventd");
>  	keventd_running = 1;
> +	keventd_task = curtask;
>  
>  	spin_lock_irq(&curtask->sigmask_lock);
>  	siginitsetinv(&curtask->blocked, sigmask(SIGCHLD));
> --- linux-2.4.0-test12-pre7/net/core/dev.c	Thu Dec  7 22:05:21 2000
> +++ linux-akpm/net/core/dev.c	Sat Dec  9 02:11:10 2000
> @@ -154,6 +154,12 @@
>  static struct timer_list samp_timer = { function: sample_queue };
>  #endif
>  
> +#ifdef CONFIG_HOTPLUG
> +static int net_run_sbin_hotplug(struct net_device *dev, char *action);
> +#else
> +#define net_run_sbin_hotplug(dev, action) ({ 0; })
> +#endif
> +
>  /*
>   *	Our notifier list
>   */
> @@ -2196,9 +2202,11 @@
>  			if (!capable(CAP_NET_ADMIN))
>  				return -EPERM;
>  			dev_load(ifr.ifr_name);
> +			dev_probe_lock();
>  			rtnl_lock();
>  			ret = dev_ifsioc(&ifr, cmd);
>  			rtnl_unlock();
> +			dev_probe_unlock();
>  			return ret;
>  	
>  		case SIOCGIFMEM:
> @@ -2217,9 +2225,11 @@
>  			if (cmd >= SIOCDEVPRIVATE &&
>  			    cmd <= SIOCDEVPRIVATE + 15) {
>  				dev_load(ifr.ifr_name);
> +				dev_probe_lock();
>  				rtnl_lock();
>  				ret = dev_ifsioc(&ifr, cmd);
>  				rtnl_unlock();
> +				dev_probe_unlock();
>  				if (!ret && copy_to_user(arg, &ifr, sizeof(struct ifreq)))
>  					return -EFAULT;
>  				return ret;
> @@ -2388,10 +2398,12 @@
>  	if (ret)
>  		return ret;
>  #endif /* CONFIG_NET_DIVERT */
> -	
> +
>  	/* Notify protocols, that a new device appeared. */
>  	notifier_call_chain(&netdev_chain, NETDEV_REGISTER, dev);
>  
> +	net_run_sbin_hotplug(dev, "register");
> +
>  	return 0;
>  }
>  
> @@ -2475,6 +2487,8 @@
>  		/* Shutdown queueing discipline. */
>  		dev_shutdown(dev);
>  
> +		net_run_sbin_hotplug(dev, "unregister");
> +
>  		/* Notify protocols, that we are about to destroy
>  		   this device. They should clean all the things.
>  		 */
> @@ -2714,29 +2728,15 @@
>  /* Notify userspace when a netdevice event occurs,
>   * by running '/sbin/hotplug net' with certain
>   * environment variables set.
> - *
> - * Currently reported events are listed in netdev_event_names[].
>   */
>  
> -/* /sbin/hotplug ONLY executes for events named here */
> -static char *netdev_event_names[] = {
> -	[NETDEV_REGISTER]	= "register",
> -	[NETDEV_UNREGISTER]	= "unregister",
> -};
> -
> -static int run_sbin_hotplug(struct notifier_block *this,
> -			    unsigned long event, void *ptr)
> +static int net_run_sbin_hotplug(struct net_device *dev, char *action)
>  {
> -	struct net_device *dev = (struct net_device *) ptr;
> -	char *argv[3], *envp[5], ifname[12 + IFNAMSIZ], action[32];
> +	char *argv[3], *envp[5], ifname[12 + IFNAMSIZ], action_str[32];
>  	int i;
>  
> -	if ((event >= ARRAY_SIZE(netdev_event_names)) ||
> -	    !netdev_event_names[event])
> -		return NOTIFY_DONE;
> -
>  	sprintf(ifname, "INTERFACE=%s", dev->name);
> -	sprintf(action, "ACTION=%s", netdev_event_names[event]);
> +	sprintf(action_str, "ACTION=%s", action);
>  
>          i = 0;
>          argv[i++] = hotplug_path;
> @@ -2748,27 +2748,11 @@
>  	envp [i++] = "HOME=/";
>  	envp [i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
>  	envp [i++] = ifname;
> -	envp [i++] = action;
> +	envp [i++] = action_str;
>  	envp [i] = 0;
>  	
>  	call_usermodehelper (argv [0], argv, envp);
>  
>  	return NOTIFY_DONE;
> -}
> -
> -static struct notifier_block sbin_hotplug = {
> -	notifier_call: run_sbin_hotplug,
> -};
> -
> -/*
> - * called from init/main.c, -after- all the initcalls are complete.
> - * Registers a hook that calls /sbin/hotplug on every netdev
> - * addition and removal.
> - */
> -void __init net_notifier_init (void)
> -{
> -	if (register_netdevice_notifier(&sbin_hotplug))
> -		printk (KERN_WARNING "unable to register netdev notifier\n"
> -			KERN_WARNING "/sbin/hotplug will not be run.\n");
>  }
>  #endif
> --- linux-2.4.0-test12-pre7/net/ipv4/devinet.c	Thu Aug 24 21:07:25 2000
> +++ linux-akpm/net/ipv4/devinet.c	Sat Dec  9 11:14:03 2000
> @@ -519,6 +519,7 @@
>  		return -EINVAL;
>  	}
>  
> +	dev_probe_lock();
>  	rtnl_lock();
>  
>  	if ((dev = __dev_get_by_name(ifr.ifr_name)) == NULL) {
> @@ -649,10 +650,12 @@
>  	}
>  done:
>  	rtnl_unlock();
> +	dev_probe_unlock();
>  	return ret;
>  
>  rarok:
>  	rtnl_unlock();
> +	dev_probe_unlock();
>  	if (copy_to_user(arg, &ifr, sizeof(struct ifreq)))
>  		return -EFAULT;
>  	return 0;
> --- linux-2.4.0-test12-pre7/init/main.c	Thu Dec  7 22:05:21 2000
> +++ linux-akpm/init/main.c	Sat Dec  9 00:47:46 2000
> @@ -716,14 +716,6 @@
>  	/* Mount the root filesystem.. */
>  	mount_root();
>  
> -#if defined(CONFIG_HOTPLUG) && defined(CONFIG_NET)
> -	/* do this after other 'do this last' stuff, because we want
> -	 * to minimize spurious executions of /sbin/hotplug
> -	 * during boot-up
> -	 */
> -	net_notifier_init();
> -#endif
> -
>  	mount_devfs_fs ();
>  
>  #ifdef CONFIG_BLK_DEV_INITRD

-- 
"Hey Y'all, Watch this!" --Mike Wangsmo
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
Please read the FAQ at http://www.tux.org/lkml/

  reply	other threads:[~2000-12-11 18:19 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2000-12-08 18:01 cardbus pirq conflict Matthew Galgoci
2000-12-09  1:59 ` Andrew Morton
2000-12-11 17:48   ` Matthew Galgoci [this message]
2000-12-11 20:03     ` Matthew Galgoci
2000-12-11 20:30       ` Linus Torvalds
2000-12-11 20:55         ` Martin Mares

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20001211124816.L3738@redhat.com \
    --to=mgalgoci@redhat.com \
    --cc=andrewm@uow.edu.au \
    --cc=linux-kernel@vger.kernel.org \
    --cc=torvalds@transmeta.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox