All of lore.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.