From 38432d0516cbbffae1278fa7dc2d317df885b289 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sat, 23 Feb 2002 21:36:00 +0100 Subject: - new, less intrusive and faster migration method: /* * This is how migration works: * * 1) we queue a migration_req_t structure in the source CPU's * runqueue and wake up that CPU's migration thread. * 2) we down() the locked semaphore => thread blocks. * 3) migration thread wakes up (implicitly it forces the migrated * thread off the CPU) * 4) it gets the migration request and checks whether the migrated * task is still in the wrong runqueue. * 5) if it's in the wrong runqueue then the migration thread removes * it and puts it into the right queue. * 6) migration thread up()s the semaphore. * 7) we wake up and the migration is done. */ --- include/linux/init_task.h | 2 -- include/linux/sched.h | 3 --- 2 files changed, 5 deletions(-) (limited to 'include/linux') diff --git a/include/linux/init_task.h b/include/linux/init_task.h index f97e245dcddc..9f34e057079a 100644 --- a/include/linux/init_task.h +++ b/include/linux/init_task.h @@ -52,8 +52,6 @@ mm: NULL, \ active_mm: &init_mm, \ run_list: LIST_HEAD_INIT(tsk.run_list), \ - migration_list: LIST_HEAD_INIT(tsk.migration_list), \ - migration_sem: __MUTEX_INITIALIZER(tsk.migration_sem), \ time_slice: HZ, \ next_task: &tsk, \ prev_task: &tsk, \ diff --git a/include/linux/sched.h b/include/linux/sched.h index 2992fe65e6aa..c71390735df2 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -286,9 +286,6 @@ struct task_struct { wait_queue_head_t wait_chldexit; /* for wait4() */ struct completion *vfork_done; /* for vfork() */ - list_t migration_list; - struct semaphore migration_sem; - unsigned long rt_priority; unsigned long it_real_value, it_prof_value, it_virt_value; unsigned long it_real_incr, it_prof_incr, it_virt_incr; -- cgit v1.2.3 From 5e37545cf526580b165d3805652f241324a850ac Mon Sep 17 00:00:00 2001 From: Alexander Viro Date: Sun, 24 Feb 2002 22:07:54 -0800 Subject: [PATCH] ->d_parent fixes Protect d_parent with "dparent_lock", making ready to get rid of BKL for d_move(). --- fs/dcache.c | 3 +++ fs/fat/inode.c | 2 ++ fs/reiserfs/inode.c | 12 +++++++----- fs/smbfs/dir.c | 2 ++ fs/smbfs/proc.c | 10 ++++++++-- include/linux/dcache.h | 1 + include/linux/dnotify.h | 6 +++--- include/linux/fs.h | 4 ++-- 8 files changed, 28 insertions(+), 12 deletions(-) (limited to 'include/linux') diff --git a/fs/dcache.c b/fs/dcache.c index a421788191fb..fab5e57765f7 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -30,6 +30,7 @@ /* #define DCACHE_DEBUG 1 */ spinlock_t dcache_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED; +rwlock_t dparent_lock __cacheline_aligned_in_smp = RW_LOCK_UNLOCKED; /* Right now the dcache depends on the kernel lock */ #define check_lock() if (!kernel_locked()) BUG() @@ -916,7 +917,9 @@ void d_move(struct dentry * dentry, struct dentry * target) /* Switch the parents and the names.. */ switch_names(dentry, target); + write_lock(&dparent_lock); do_switch(dentry->d_parent, target->d_parent); + write_unlock(&dparent_lock); do_switch(dentry->d_name.len, target->d_name.len); do_switch(dentry->d_name.hash, target->d_name.hash); diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 73859637332d..10efdd661c63 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -516,7 +516,9 @@ int fat_dentry_to_fh(struct dentry *de, __u32 *fh, int *lenp, int needparent) fh[1] = inode->i_generation; fh[2] = MSDOS_I(inode)->i_location; fh[3] = MSDOS_I(inode)->i_logstart; + read_lock(&dparent_lock); fh[4] = MSDOS_I(de->d_parent->d_inode)->i_logstart; + read_unlock(&dparent_lock); return 3; } diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index 34462717de56..9ef75e6fe69c 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c @@ -1325,15 +1325,17 @@ int reiserfs_dentry_to_fh(struct dentry *dentry, __u32 *data, int *lenp, int nee if (maxlen < 5 || ! need_parent) return 3 ; + read_lock(&dparent_lock); inode = dentry->d_parent->d_inode ; data[3] = inode->i_ino ; data[4] = le32_to_cpu(INODE_PKEY (inode)->k_dir_id) ; *lenp = 5 ; - if (maxlen < 6) - return 5 ; - data[5] = inode->i_generation ; - *lenp = 6 ; - return 6 ; + if (maxlen >= 6) { + data[5] = inode->i_generation ; + *lenp = 6 ; + } + read_unlock(&dparent_lock); + return *lenp ; } diff --git a/fs/smbfs/dir.c b/fs/smbfs/dir.c index 991822bc0796..09d025004c4a 100644 --- a/fs/smbfs/dir.c +++ b/fs/smbfs/dir.c @@ -378,12 +378,14 @@ smb_new_dentry(struct dentry *dentry) void smb_renew_times(struct dentry * dentry) { + read_lock(&dparent_lock); for (;;) { dentry->d_time = jiffies; if (IS_ROOT(dentry)) break; dentry = dentry->d_parent; } + read_unlock(&dparent_lock); } static struct dentry * diff --git a/fs/smbfs/proc.c b/fs/smbfs/proc.c index 4075626db7a4..e2df6e23d73a 100644 --- a/fs/smbfs/proc.c +++ b/fs/smbfs/proc.c @@ -245,15 +245,20 @@ static int smb_build_path(struct smb_sb_info *server, char * buf, int maxlen, * Build the path string walking the tree backward from end to ROOT * and store it in reversed order [see reverse_string()] */ + read_lock(&dparent_lock); while (!IS_ROOT(entry)) { - if (maxlen < 3) + if (maxlen < 3) { + read_unlock(&dparent_lock); return -ENAMETOOLONG; + } len = server->convert(path, maxlen-2, entry->d_name.name, entry->d_name.len, server->local_nls, server->remote_nls); - if (len < 0) + if (len < 0) { + read_unlock(&dparent_lock); return len; + } reverse_string(path, len); path += len; *path++ = '\\'; @@ -263,6 +268,7 @@ static int smb_build_path(struct smb_sb_info *server, char * buf, int maxlen, if (IS_ROOT(entry)) break; } + read_unlock(&dparent_lock); reverse_string(buf, path-buf); /* maxlen is at least 1 */ diff --git a/include/linux/dcache.h b/include/linux/dcache.h index 3649086ed83f..21da57231050 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h @@ -126,6 +126,7 @@ d_iput: no no yes #define DCACHE_REFERENCED 0x0008 /* Recently used, don't discard. */ extern spinlock_t dcache_lock; +extern rwlock_t dparent_lock; /** * d_drop - drop a dentry diff --git a/include/linux/dnotify.h b/include/linux/dnotify.h index 794fd096f31f..60c1e2117f10 100644 --- a/include/linux/dnotify.h +++ b/include/linux/dnotify.h @@ -33,13 +33,13 @@ static inline void inode_dir_notify(struct inode *inode, unsigned long event) static inline void dnotify_parent(struct dentry *dentry, unsigned long event) { struct dentry *parent; - spin_lock(&dcache_lock); + read_lock(&dparent_lock); parent = dentry->d_parent; if (parent->d_inode->i_dnotify_mask & event) { dget(parent); - spin_unlock(&dcache_lock); + read_unlock(&dparent_lock); __inode_dir_notify(parent->d_inode, event); dput(parent); } else - spin_unlock(&dcache_lock); + read_unlock(&dparent_lock); } diff --git a/include/linux/fs.h b/include/linux/fs.h index 7bb0610ba3a6..89208aabe5b8 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1511,9 +1511,9 @@ extern int inode_setattr(struct inode *, struct iattr *); static inline ino_t parent_ino(struct dentry *dentry) { ino_t res; - spin_lock(&dcache_lock); + read_lock(&dparent_lock); res = dentry->d_parent->d_inode->i_ino; - spin_unlock(&dcache_lock); + read_unlock(&dparent_lock); return res; } -- cgit v1.2.3 From dd56376dcd8c94342857257aa34a5720baeb807a Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 25 Feb 2002 19:43:26 -0800 Subject: [PATCH] Patch - sharing RTC timer between kernel and user space (2nd) This patch to allow using of RTC timer inside the kernel space. We can use the RTC timer as timing source for ALSA sequencer. Patch by Takashi. The patch adds these three functions and one structure to rtc.h and rtc.c: typedef struct rtc_task { void (*func)(void *private_data); void *private_data; } rtc_task_t; int rtc_register(rtc_task_t *task); int rtc_unregister(rtc_task_t *task); int rtc_control(rtc_task_t *t, unsigned int cmd, unsigned long arg); Jaroslav --- drivers/char/Makefile | 2 +- drivers/char/rtc.c | 114 +++++++++++++++++++++++++++++++++++++++++++++----- include/linux/rtc.h | 13 ++++++ 3 files changed, 118 insertions(+), 11 deletions(-) (limited to 'include/linux') diff --git a/drivers/char/Makefile b/drivers/char/Makefile index cae9ed93433c..1a9647b4a052 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -23,7 +23,7 @@ obj-y += mem.o tty_io.o n_tty.o tty_ioctl.o raw.o pty.o misc.o random.o export-objs := busmouse.o console.o keyboard.o sysrq.o \ misc.o pty.o random.o selection.o serial.o \ - sonypi.o tty_io.o tty_ioctl.o generic_serial.o + sonypi.o tty_io.o tty_ioctl.o generic_serial.o rtc.o mod-subdirs := ftape drm pcmcia diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index 6f27a6120c2c..2ebca07cf1d7 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c @@ -41,9 +41,11 @@ * 1.10c Cesar Barros: SMP locking fixes and cleanup * 1.10d Paul Gortmaker: delete paranoia check in rtc_exit * 1.10e Maciej W. Rozycki: Handle DECstation's year weirdness. + * 1.11 Takashi Iwai: Kernel access functions + * rtc_register/rtc_unregister/rtc_control */ -#define RTC_VERSION "1.10e" +#define RTC_VERSION "1.11" #define RTC_IO_EXTENT 0x10 /* Only really two ports, but... */ @@ -139,6 +141,11 @@ static unsigned long rtc_status = 0; /* bitmapped status byte. */ static unsigned long rtc_freq = 0; /* Current periodic IRQ rate */ static unsigned long rtc_irq_data = 0; /* our output to the world */ +#if RTC_IRQ +static spinlock_t rtc_task_lock = SPIN_LOCK_UNLOCKED; +static rtc_task_t *rtc_callback = NULL; +#endif + /* * If this driver ever becomes modularised, it will be really nice * to make the epoch retain its value across module reload... @@ -180,6 +187,10 @@ static void rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs) spin_unlock (&rtc_lock); /* Now do the rest of the actions */ + spin_lock(&rtc_task_lock); + if (rtc_callback) + rtc_callback->func(rtc_callback->private_data); + spin_unlock(&rtc_task_lock); wake_up_interruptible(&rtc_wait); kill_fasync (&rtc_async_queue, SIGIO, POLL_IN); @@ -244,8 +255,7 @@ static ssize_t rtc_read(struct file *file, char *buf, #endif } -static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg) +static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel) { struct rtc_time wtime; @@ -295,7 +305,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, * We don't really want Joe User enabling more * than 64Hz of interrupts on a multi-user machine. */ - if ((rtc_freq > 64) && (!capable(CAP_SYS_RESOURCE))) + if (!kernel && (rtc_freq > 64) && (!capable(CAP_SYS_RESOURCE))) return -EACCES; if (!(rtc_status & RTC_TIMER_ON)) { @@ -493,7 +503,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, * We don't really want Joe User generating more * than 64Hz of interrupts on a multi-user machine. */ - if ((arg > 64) && (!capable(CAP_SYS_RESOURCE))) + if (!kernel && (arg > 64) && (!capable(CAP_SYS_RESOURCE))) return -EACCES; while (arg > (1<func == NULL) + return -EINVAL; + spin_lock_irq(&rtc_lock); + if (rtc_status & RTC_IS_OPEN) { + spin_unlock_irq(&rtc_lock); + return -EBUSY; + } + spin_lock(&rtc_task_lock); + if (rtc_callback) { + spin_unlock(&rtc_task_lock); + spin_unlock_irq(&rtc_lock); + return -EBUSY; + } + rtc_status |= RTC_IS_OPEN; + rtc_callback = task; + spin_unlock(&rtc_task_lock); + spin_unlock_irq(&rtc_lock); + return 0; +#endif +} + +int rtc_unregister(rtc_task_t *task) +{ +#if !RTC_IRQ + return -EIO; +#else + unsigned char tmp; + + spin_lock_irq(&rtc_task_lock); + if (rtc_callback != task) { + spin_unlock_irq(&rtc_task_lock); + return -ENXIO; + } + rtc_callback = NULL; + spin_lock(&rtc_lock); + /* disable controls */ + tmp = CMOS_READ(RTC_CONTROL); + tmp &= ~RTC_PIE; + tmp &= ~RTC_AIE; + tmp &= ~RTC_UIE; + CMOS_WRITE(tmp, RTC_CONTROL); + CMOS_READ(RTC_INTR_FLAGS); + if (rtc_status & RTC_TIMER_ON) { + rtc_status &= ~RTC_TIMER_ON; + del_timer(&rtc_irq_timer); + } + rtc_status &= ~RTC_IS_OPEN; + spin_unlock(&rtc_lock); + spin_unlock_irq(&rtc_task_lock); + return 0; +#endif +} + +int rtc_control(rtc_task_t *task, unsigned int cmd, unsigned long arg) +{ +#if !RTC_IRQ + return -EIO; +#else + spin_lock_irq(&rtc_task_lock); + if (rtc_callback != task) { + spin_unlock_irq(&rtc_task_lock); + return -ENXIO; + } + spin_unlock_irq(&rtc_task_lock); + return rtc_do_ioctl(cmd, arg, 1); +#endif +} + + /* * The various file operations we support. */ @@ -822,7 +917,6 @@ static void __exit rtc_exit (void) module_init(rtc_init); module_exit(rtc_exit); -EXPORT_NO_SYMBOLS; #if RTC_IRQ /* diff --git a/include/linux/rtc.h b/include/linux/rtc.h index df958b66ada6..e99a2357ab28 100644 --- a/include/linux/rtc.h +++ b/include/linux/rtc.h @@ -66,4 +66,17 @@ struct rtc_wkalrm { #define RTC_WKALM_SET _IOW('p', 0x0f, struct rtc_wkalrm)/* Set wakeup alarm*/ #define RTC_WKALM_RD _IOR('p', 0x10, struct rtc_wkalrm)/* Get wakeup alarm*/ +#ifdef __KERNEL__ + +typedef struct rtc_task { + void (*func)(void *private_data); + void *private_data; +} rtc_task_t; + +int rtc_register(rtc_task_t *task); +int rtc_unregister(rtc_task_t *task); +int rtc_control(rtc_task_t *t, unsigned int cmd, unsigned long arg); + +#endif /* __KERNEL__ */ + #endif /* _LINUX_RTC_H_ */ -- cgit v1.2.3 From 0fa9c2fa4896cf1b6557c9c3a20fc248f9f790af Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Mon, 25 Feb 2002 21:19:05 -0800 Subject: [PATCH] x86_64 irqstat change x86_64 does not have an irq_stat array. It puts the interrupt information into its per CPU area instead, allowing more efficient access to it. This patch allows the architecture to overwrite the __IRQ_STAT access macro in linux/irq_cpustat.h. It is required to make the x86_64 port compile. -Andi --- include/linux/irq_cpustat.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include/linux') diff --git a/include/linux/irq_cpustat.h b/include/linux/irq_cpustat.h index 24696e15dacc..dfd73c5ec60d 100644 --- a/include/linux/irq_cpustat.h +++ b/include/linux/irq_cpustat.h @@ -19,11 +19,13 @@ extern irq_cpustat_t irq_stat[]; /* defined in asm/hardirq.h */ +#ifndef __ARCH_IRQ_STAT /* Some architectures can do this more efficiently */ #ifdef CONFIG_SMP #define __IRQ_STAT(cpu, member) (irq_stat[cpu].member) #else #define __IRQ_STAT(cpu, member) ((void)(cpu), irq_stat[0].member) #endif +#endif /* arch independent irq_stat fields */ #define softirq_pending(cpu) __IRQ_STAT((cpu), __softirq_pending) -- cgit v1.2.3 From dd63f4c1098fc3d69ab16cc5c3efe9b56c36bd9d Mon Sep 17 00:00:00 2001 From: Neil Brown Date: Mon, 25 Feb 2002 22:22:45 -0800 Subject: [PATCH] PATCH 1/16: NFSD: Compilation Fix Fix include file so syscall compiles when NFSD not configured --- include/linux/nfsd/interface.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/nfsd/interface.h b/include/linux/nfsd/interface.h index 807a4fc6c5f5..80c65165778d 100644 --- a/include/linux/nfsd/interface.h +++ b/include/linux/nfsd/interface.h @@ -12,13 +12,15 @@ #include -#ifdef CONFIG_NFSD_MODULE +#ifndef CONFIG_NFSD +#ifdef CONFIG_MODULES extern struct nfsd_linkage { long (*do_nfsservctl)(int cmd, void *argp, void *resp); struct module *owner; } * nfsd_linkage; +#endif #endif #endif /* LINUX_NFSD_INTERFACE_H */ -- cgit v1.2.3 From 8244559fdb8a3a6aa407b2509a259b6f3e30d74b Mon Sep 17 00:00:00 2001 From: Neil Brown Date: Mon, 25 Feb 2002 22:22:50 -0800 Subject: [PATCH] PATCH 2/16: NFSD: BKL Removal: Lock export table Change export table lock to (SMP safe) rwsemaphore As a first step to removing the BKL from nfsd, this patch changes the lock used for the export table to be a rwsem semaphore. Previously it had the same functionality but depended on the BKL for correctness. As there is no "down_write_interruptible" this patch removes the posibility of interrupting the write_lock request, but this should never be needed anyway. --- fs/nfsd/export.c | 123 +++++++++++++++++--------------------------- fs/nfsd/lockd.c | 2 +- fs/nfsd/nfsctl.c | 4 +- fs/nfsd/nfssvc.c | 2 +- include/linux/nfsd/export.h | 3 +- 5 files changed, 51 insertions(+), 83 deletions(-) (limited to 'include/linux') diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index 6961ba4011fa..6f7339fb8b26 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -60,10 +61,6 @@ struct svc_clnthash { static struct svc_clnthash * clnt_hash[CLIENT_HASHMAX]; static svc_client * clients; -static int hash_lock; -static int want_lock; -static int hash_count; -static DECLARE_WAIT_QUEUE_HEAD( hash_wait ); /* * Find the client's export entry matching xdev/xino. @@ -162,6 +159,39 @@ static void exp_change_parents(svc_client *clp, svc_export *old, svc_export *new } } +/* + * Hashtable locking. Write locks are placed only by user processes + * wanting to modify export information. + * Write locking only done in this file. Read locking + * needed externally. + */ + +static DECLARE_RWSEM(hash_sem); + +void +exp_readlock(void) +{ + down_read(&hash_sem); +} + +static inline void +exp_writelock(void) +{ + down_write(&hash_sem); +} + +void +exp_readunlock(void) +{ + up_read(&hash_sem); +} + +static inline void +exp_writeunlock(void) +{ + up_write(&hash_sem); +} + /* * Export a file system. */ @@ -189,11 +219,9 @@ exp_export(struct nfsctl_export *nxp) ino = nxp->ex_ino; /* Try to lock the export table for update */ - if ((err = exp_writelock()) < 0) - goto out; + exp_writelock(); /* Look up client info */ - err = -EINVAL; if (!(clp = exp_getclientbyname(nxp->ex_client))) goto out_unlock; @@ -278,7 +306,7 @@ exp_export(struct nfsctl_export *nxp) /* Unlock hashtable */ out_unlock: - exp_unlock(); + exp_writeunlock(); out: return err; @@ -345,8 +373,7 @@ exp_unexport(struct nfsctl_export *nxp) if (!exp_verify_string(nxp->ex_client, NFSCLNT_IDMAX)) return -EINVAL; - if ((err = exp_writelock()) < 0) - goto out; + exp_writelock(); err = -EINVAL; clp = exp_getclientbyname(nxp->ex_client); @@ -361,8 +388,7 @@ exp_unexport(struct nfsctl_export *nxp) } } - exp_unlock(); -out: + exp_writeunlock(); return err; } @@ -415,58 +441,6 @@ out: return err; } -/* - * Hashtable locking. Write locks are placed only by user processes - * wanting to modify export information. - */ -void -exp_readlock(void) -{ - while (hash_lock || want_lock) - sleep_on(&hash_wait); - hash_count++; -} - -int -exp_writelock(void) -{ - /* fast track */ - if (!hash_count && !hash_lock) { - lock_it: - hash_lock = 1; - return 0; - } - - clear_thread_flag(TIF_SIGPENDING); - want_lock++; - while (hash_count || hash_lock) { - interruptible_sleep_on(&hash_wait); - if (signal_pending(current)) - break; - } - want_lock--; - - /* restore the task's signals */ - spin_lock_irq(¤t->sigmask_lock); - recalc_sigpending(); - spin_unlock_irq(¤t->sigmask_lock); - - if (!hash_count && !hash_lock) - goto lock_it; - return -EINTR; -} - -void -exp_unlock(void) -{ - if (!hash_count && !hash_lock) - printk(KERN_WARNING "exp_unlock: not locked!\n"); - if (hash_count) - hash_count--; - else - hash_lock = 0; - wake_up(&hash_wait); -} /* * Find a valid client given an inet address. We always move the most @@ -572,7 +546,7 @@ static void *e_next(struct seq_file *m, void *p, loff_t *pos) static void e_stop(struct seq_file *m, void *p) { - exp_unlock(); + exp_readunlock(); } struct flags { @@ -688,8 +662,7 @@ exp_addclient(struct nfsctl_client *ncp) goto out; /* Lock the hashtable */ - if ((err = exp_writelock()) < 0) - goto out; + exp_writelock(); /* First check if this is a change request for a client. */ for (clp = clients; clp; clp = clp->cl_next) @@ -754,7 +727,7 @@ exp_addclient(struct nfsctl_client *ncp) err = 0; out_unlock: - exp_unlock(); + exp_writeunlock(); out: return err; } @@ -773,10 +746,8 @@ exp_delclient(struct nfsctl_client *ncp) goto out; /* Lock the hashtable */ - if ((err = exp_writelock()) < 0) - goto out; + exp_writelock(); - err = -EINVAL; for (clpp = &clients; (clp = *clpp); clpp = &(clp->cl_next)) if (!strcmp(ncp->cl_ident, clp->cl_ident)) break; @@ -787,7 +758,7 @@ exp_delclient(struct nfsctl_client *ncp) err = 0; } - exp_unlock(); + exp_writeunlock(); out: return err; } @@ -893,16 +864,14 @@ nfsd_export_shutdown(void) dprintk("nfsd: shutting down export module.\n"); - if (exp_writelock() < 0) { - printk(KERN_WARNING "Weird: hashtable locked in exp_shutdown"); - return; - } + exp_writelock(); + for (i = 0; i < CLIENT_HASHMAX; i++) { while (clnt_hash[i]) exp_freeclient(clnt_hash[i]->h_client); } clients = NULL; /* we may be restarted before the module unloads */ - exp_unlock(); + exp_writeunlock(); dprintk("nfsd: export shutdown complete.\n"); } diff --git a/fs/nfsd/lockd.c b/fs/nfsd/lockd.c index 5bed6b8ae320..a09b4e891f0b 100644 --- a/fs/nfsd/lockd.c +++ b/fs/nfsd/lockd.c @@ -62,7 +62,7 @@ nlm_fclose(struct file *filp) struct nlmsvc_binding nfsd_nlm_ops = { exp_readlock, /* lock export table for reading */ - exp_unlock, /* unlock export table */ + exp_readunlock, /* unlock export table */ exp_getclient, /* look up NFS client */ nlm_fopen, /* open file for locking */ nlm_fclose, /* close file */ diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index 3a6f89c3bf55..77b1cbcc9255 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -121,7 +121,7 @@ nfsctl_getfs(struct nfsctl_fsparm *data, struct knfsd_fh *res) err = -EPERM; else err = exp_rootfh(clp, data->gd_path, res, data->gd_maxlen); - exp_unlock(); + exp_readunlock(); return err; } @@ -144,7 +144,7 @@ nfsctl_getfd(struct nfsctl_fdparm *data, __u8 *res) err = -EPERM; else err = exp_rootfh(clp, data->gd_path, &fh, NFS_FHSIZE); - exp_unlock(); + exp_readunlock(); if (err == 0) { if (fh.fh_size > NFS_FHSIZE) diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index 3c4d5630f760..782ad1434074 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c @@ -211,7 +211,7 @@ nfsd(struct svc_rqst *rqstp) svc_process(serv, rqstp); /* Unlock export hash tables */ - exp_unlock(); + exp_readunlock(); update_thread_usage(nfsd_busy); nfsd_busy--; } diff --git a/include/linux/nfsd/export.h b/include/linux/nfsd/export.h index 6f3e970f40d4..1125d2fa1cbf 100644 --- a/include/linux/nfsd/export.h +++ b/include/linux/nfsd/export.h @@ -87,8 +87,7 @@ struct svc_export { void nfsd_export_init(void); void nfsd_export_shutdown(void); void exp_readlock(void); -int exp_writelock(void); -void exp_unlock(void); +void exp_readunlock(void); struct svc_client * exp_getclient(struct sockaddr_in *sin); void exp_putclient(struct svc_client *clp); struct svc_export * exp_get(struct svc_client *clp, kdev_t dev, ino_t ino); -- cgit v1.2.3 From fac5a35a1ce389ce9ed21458023ce5eb2f076385 Mon Sep 17 00:00:00 2001 From: Neil Brown Date: Mon, 25 Feb 2002 22:23:22 -0800 Subject: [PATCH] PATCH 8/16: NFSD: RPC lists tidyup Change sunrpc to use more list.h lists The sunrpc client code uses home-grown doubly linked lists to group - idle server threads - pending server sockets - waiting rpc tasks - all rpc tasks. This patch converts all of these lists to lists and also makes the list of all server sockets for a particular server into a list.h list instead of a single-link list. Possibly the least obvious change is replacing RPC_INIT_WAITQ with RPC_WAITQ and INIT_RPC_WAITQ. These follow the model of LIST_HEAD and INIT_LIST_HEAD defined in list.h and are needed to initialise the list_head in the rpc_waitq properly. --- fs/nfs/flushd.c | 2 +- fs/nfs/unlink.c | 2 +- include/linux/sunrpc/sched.h | 34 +++++++++--- include/linux/sunrpc/svc.h | 9 ++-- include/linux/sunrpc/svcsock.h | 6 +-- include/linux/sunrpc/types.h | 55 +------------------ net/sunrpc/clnt.c | 2 +- net/sunrpc/sched.c | 116 +++++++++++++++++++---------------------- net/sunrpc/svc.c | 9 +++- net/sunrpc/svcsock.c | 54 ++++++++++--------- net/sunrpc/xprt.c | 26 +++------ 11 files changed, 134 insertions(+), 181 deletions(-) (limited to 'include/linux') diff --git a/fs/nfs/flushd.c b/fs/nfs/flushd.c index c1e64de64535..c636ab35f8f8 100644 --- a/fs/nfs/flushd.c +++ b/fs/nfs/flushd.c @@ -50,7 +50,7 @@ /* * This is the wait queue all cluster daemons sleep on */ -static struct rpc_wait_queue flushd_queue = RPC_INIT_WAITQ("nfs_flushd"); +static RPC_WAITQ(flushd_queue, "nfs_flushd"); /* * Local function declarations. diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c index 800fc5767459..5c4489a3a279 100644 --- a/fs/nfs/unlink.c +++ b/fs/nfs/unlink.c @@ -24,7 +24,7 @@ struct nfs_unlinkdata { }; static struct nfs_unlinkdata *nfs_deletes; -static struct rpc_wait_queue nfs_delete_queue = RPC_INIT_WAITQ("nfs_delete_queue"); +static RPC_WAITQ(nfs_delete_queue, "nfs_delete_queue"); /** * nfs_detach_unlinkdata - Remove asynchronous unlink from global list diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h index eee6756b842a..892565ca4721 100644 --- a/include/linux/sunrpc/sched.h +++ b/include/linux/sunrpc/sched.h @@ -34,13 +34,11 @@ struct rpc_message { * This is the RPC task struct */ struct rpc_task { - struct rpc_task * tk_prev; /* wait queue links */ - struct rpc_task * tk_next; + struct list_head tk_list; /* wait queue links */ #ifdef RPC_DEBUG unsigned long tk_magic; /* 0xf00baa */ #endif - struct rpc_task * tk_next_task; /* global list of tasks */ - struct rpc_task * tk_prev_task; /* global list of tasks */ + struct list_head tk_task; /* global list of tasks */ struct rpc_clnt * tk_client; /* RPC client */ struct rpc_rqst * tk_rqstp; /* RPC request */ int tk_status; /* result of last operation */ @@ -88,6 +86,20 @@ struct rpc_task { #define tk_auth tk_client->cl_auth #define tk_xprt tk_client->cl_xprt +/* support walking a list of tasks on a wait queue */ +#define task_for_each(task, pos, head) \ + list_for_each(pos, head) \ + if ((task=list_entry(pos, struct rpc_task, tk_list)),1) + +#define task_for_first(task, head) \ + if (!list_empty(head) && \ + ((task=list_entry((head)->next, struct rpc_task, tk_list)),1)) + +/* .. and walking list of all tasks */ +#define alltask_for_each(task, pos, head) \ + list_for_each(pos, head) \ + if ((task=list_entry(pos, struct rpc_task, tk_task)),1) + typedef void (*rpc_action)(struct rpc_task *); /* @@ -133,16 +145,24 @@ typedef void (*rpc_action)(struct rpc_task *); * RPC synchronization objects */ struct rpc_wait_queue { - struct rpc_task * task; + struct list_head tasks; #ifdef RPC_DEBUG char * name; #endif }; #ifndef RPC_DEBUG -# define RPC_INIT_WAITQ(name) ((struct rpc_wait_queue) { NULL }) +# define RPC_WAITQ_INIT(var,qname) ((struct rpc_wait_queue) {LIST_HEAD_INIT(var)}) +# define RPC_WAITQ(var,qname) struct rpc_wait_queue var = RPC_WAITQ_INIT(var.tasks,qname) +# define INIT_RPC_WAITQ(ptr,qname) do { \ + INIT_LIST_HEAD(&(ptr)->tasks); \ + } while(0) #else -# define RPC_INIT_WAITQ(name) ((struct rpc_wait_queue) { NULL, name }) +# define RPC_WAITQ_INIT(var,qname) ((struct rpc_wait_queue) {LIST_HEAD_INIT(var.tasks), qname}) +# define RPC_WAITQ(var,qname) struct rpc_wait_queue var = RPC_WAITQ_INIT(var,qname) +# define INIT_RPC_WAITQ(ptr,qname) do { \ + INIT_LIST_HEAD(&(ptr)->tasks); (ptr)->name = qname; \ + } while(0) #endif /* diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h index f6439cb4facf..003b89a68852 100644 --- a/include/linux/sunrpc/svc.h +++ b/include/linux/sunrpc/svc.h @@ -27,8 +27,8 @@ * We currently do not support more than one RPC program per daemon. */ struct svc_serv { - struct svc_rqst * sv_threads; /* idle server threads */ - struct svc_sock * sv_sockets; /* pending sockets */ + struct list_head sv_threads; /* idle server threads */ + struct list_head sv_sockets; /* pending sockets */ struct svc_program * sv_program; /* RPC program */ struct svc_stat * sv_stats; /* RPC statistics */ spinlock_t sv_lock; @@ -36,7 +36,7 @@ struct svc_serv { unsigned int sv_bufsz; /* datagram buffer size */ unsigned int sv_xdrsize; /* XDR buffer size */ - struct svc_sock * sv_allsocks; /* all sockets */ + struct list_head sv_allsocks; /* all sockets */ char * sv_name; /* service name */ }; @@ -89,8 +89,7 @@ struct svc_buf { * NOTE: First two items must be prev/next. */ struct svc_rqst { - struct svc_rqst * rq_prev; /* idle list */ - struct svc_rqst * rq_next; + struct list_head rq_list; /* idle list */ struct svc_sock * rq_sock; /* socket */ struct sockaddr_in rq_addr; /* peer address */ int rq_addrlen; diff --git a/include/linux/sunrpc/svcsock.h b/include/linux/sunrpc/svcsock.h index 82d9678d4905..0c565502e272 100644 --- a/include/linux/sunrpc/svcsock.h +++ b/include/linux/sunrpc/svcsock.h @@ -13,12 +13,10 @@ /* * RPC server socket. - * NOTE: First two items must be prev/next. */ struct svc_sock { - struct svc_sock * sk_prev; /* list of ready sockets */ - struct svc_sock * sk_next; - struct svc_sock * sk_list; /* list of all sockets */ + struct list_head sk_ready; /* list of ready sockets */ + struct list_head sk_list; /* list of all sockets */ struct socket * sk_sock; /* berkeley socket layer */ struct sock * sk_sk; /* INET layer */ spinlock_t sk_lock; diff --git a/include/linux/sunrpc/types.h b/include/linux/sunrpc/types.h index 232ac45c725e..d524016fb4ba 100644 --- a/include/linux/sunrpc/types.h +++ b/include/linux/sunrpc/types.h @@ -12,60 +12,7 @@ #include #include #include - -/* - * These are the RPC list manipulation primitives used everywhere. - */ -struct rpc_listitem { - struct rpc_listitem * prev; - struct rpc_listitem * next; -}; - -static __inline__ void -__rpc_append_list(struct rpc_listitem **q, struct rpc_listitem *item) -{ - struct rpc_listitem *next, *prev; - - if (!(next = *q)) { - *q = item->next = item->prev = item; - } else { - prev = next->prev; - prev->next = item; - next->prev = item; - item->next = next; - item->prev = prev; - } -} - -static __inline__ void -__rpc_insert_list(struct rpc_listitem **q, struct rpc_listitem *item) -{ - __rpc_append_list(q, item); - *q = item; -} - -static __inline__ void -__rpc_remove_list(struct rpc_listitem **q, struct rpc_listitem *item) -{ - struct rpc_listitem *prev = item->prev, - *next = item->next; - - if (item != prev) { - next->prev = prev; - prev->next = next; - } else { - next = NULL; - } - if (*q == item) - *q = next; -} - -#define rpc_insert_list(q, i) \ - __rpc_insert_list((struct rpc_listitem **) q, (struct rpc_listitem *) i) -#define rpc_append_list(q, i) \ - __rpc_append_list((struct rpc_listitem **) q, (struct rpc_listitem *) i) -#define rpc_remove_list(q, i) \ - __rpc_remove_list((struct rpc_listitem **) q, (struct rpc_listitem *) i) +#include /* * Shorthands diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 30fc84523fdb..8fbb82e7d704 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c @@ -103,7 +103,7 @@ rpc_create_client(struct rpc_xprt *xprt, char *servname, clnt->cl_vers = version->number; clnt->cl_prot = xprt->prot; clnt->cl_stats = program->stats; - clnt->cl_bindwait = RPC_INIT_WAITQ("bindwait"); + INIT_RPC_WAITQ(&clnt->cl_bindwait, "bindwait"); if (!clnt->cl_port) clnt->cl_autobind = 1; diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index 30d86ec293a2..c75a5cd47e82 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c @@ -41,23 +41,23 @@ static void rpciod_killall(void); * handler, or while executing another RPC task, it is put on * schedq, and rpciod is woken up. */ -static struct rpc_wait_queue schedq = RPC_INIT_WAITQ("schedq"); +static RPC_WAITQ(schedq, "schedq"); /* * RPC tasks that create another task (e.g. for contacting the portmapper) * will wait on this queue for their child's completion */ -static struct rpc_wait_queue childq = RPC_INIT_WAITQ("childq"); +static RPC_WAITQ(childq, "childq"); /* * RPC tasks sit here while waiting for conditions to improve. */ -static struct rpc_wait_queue delay_queue = RPC_INIT_WAITQ("delayq"); +static RPC_WAITQ(delay_queue, "delayq"); /* * All RPC tasks are linked into this list */ -static struct rpc_task * all_tasks; +static LIST_HEAD(all_tasks); /* * rpciod-related stuff @@ -194,9 +194,9 @@ __rpc_add_wait_queue(struct rpc_wait_queue *queue, struct rpc_task *task) return -EWOULDBLOCK; } if (RPC_IS_SWAPPER(task)) - rpc_insert_list(&queue->task, task); + list_add(&task->tk_list, &queue->tasks); else - rpc_append_list(&queue->task, task); + list_add_tail(&task->tk_list, &queue->tasks); task->tk_rpcwait = queue; dprintk("RPC: %4d added to queue %p \"%s\"\n", @@ -228,7 +228,7 @@ __rpc_remove_wait_queue(struct rpc_task *task) if (!queue) return; - rpc_remove_list(&queue->task, task); + list_del(&task->tk_list); task->tk_rpcwait = NULL; dprintk("RPC: %4d removed from queue %p \"%s\"\n", @@ -450,11 +450,11 @@ rpc_wake_up_task(struct rpc_task *task) struct rpc_task * rpc_wake_up_next(struct rpc_wait_queue *queue) { - struct rpc_task *task; + struct rpc_task *task = NULL; dprintk("RPC: wake_up_next(%p \"%s\")\n", queue, rpc_qname(queue)); spin_lock_bh(&rpc_queue_lock); - if ((task = queue->task) != 0) + task_for_first(task, &queue->tasks) __rpc_wake_up_task(task); spin_unlock_bh(&rpc_queue_lock); @@ -470,9 +470,12 @@ rpc_wake_up_next(struct rpc_wait_queue *queue) void rpc_wake_up(struct rpc_wait_queue *queue) { + struct rpc_task *task; + spin_lock_bh(&rpc_queue_lock); - while (queue->task) - __rpc_wake_up_task(queue->task); + while (!list_empty(&queue->tasks)) + task_for_first(task, &queue->tasks) + __rpc_wake_up_task(task); spin_unlock_bh(&rpc_queue_lock); } @@ -486,12 +489,14 @@ rpc_wake_up(struct rpc_wait_queue *queue) void rpc_wake_up_status(struct rpc_wait_queue *queue, int status) { - struct rpc_task *task; + struct rpc_task *task; spin_lock_bh(&rpc_queue_lock); - while ((task = queue->task) != NULL) { - task->tk_status = status; - __rpc_wake_up_task(task); + while (!list_empty(&queue->tasks)) { + task_for_first(task, &queue->tasks) { + task->tk_status = status; + __rpc_wake_up_task(task); + } } spin_unlock_bh(&rpc_queue_lock); } @@ -703,23 +708,25 @@ __rpc_schedule(void) rpciod_tcp_dispatcher(); spin_lock_bh(&rpc_queue_lock); - if (!(task = schedq.task)) { - spin_unlock_bh(&rpc_queue_lock); - break; - } - if (task->tk_lock) { - spin_unlock_bh(&rpc_queue_lock); - printk(KERN_ERR "RPC: Locked task was scheduled !!!!\n"); + + task_for_first(task, &schedq.tasks) { + if (task->tk_lock) { + spin_unlock_bh(&rpc_queue_lock); + printk(KERN_ERR "RPC: Locked task was scheduled !!!!\n"); #ifdef RPC_DEBUG - rpc_debug = ~0; - rpc_show_tasks(); + rpc_debug = ~0; + rpc_show_tasks(); #endif + break; + } + __rpc_remove_wait_queue(task); + spin_unlock_bh(&rpc_queue_lock); + + __rpc_execute(task); + } else { + spin_unlock_bh(&rpc_queue_lock); break; } - __rpc_remove_wait_queue(task); - spin_unlock_bh(&rpc_queue_lock); - - __rpc_execute(task); if (++count >= 200 || need_resched()) { count = 0; @@ -814,11 +821,7 @@ rpc_init_task(struct rpc_task *task, struct rpc_clnt *clnt, /* Add to global list of all tasks */ spin_lock(&rpc_sched_lock); - task->tk_next_task = all_tasks; - task->tk_prev_task = NULL; - if (all_tasks) - all_tasks->tk_prev_task = task; - all_tasks = task; + list_add(&task->tk_task, &all_tasks); spin_unlock(&rpc_sched_lock); if (clnt) @@ -877,8 +880,6 @@ cleanup: void rpc_release_task(struct rpc_task *task) { - struct rpc_task *next, *prev; - dprintk("RPC: %4d release task\n", task->tk_pid); #ifdef RPC_DEBUG @@ -892,15 +893,7 @@ rpc_release_task(struct rpc_task *task) /* Remove from global task list */ spin_lock(&rpc_sched_lock); - prev = task->tk_prev_task; - next = task->tk_next_task; - if (next) - next->tk_prev_task = prev; - if (prev) - prev->tk_next_task = next; - else - all_tasks = next; - task->tk_next_task = task->tk_prev_task = NULL; + list_del(&task->tk_task); spin_unlock(&rpc_sched_lock); /* Protect the execution below. */ @@ -954,14 +947,13 @@ static inline struct rpc_task * rpc_find_parent(struct rpc_task *child) { struct rpc_task *task, *parent; + struct list_head *le; parent = (struct rpc_task *) child->tk_calldata; - if ((task = childq.task) != NULL) { - do { - if (task == parent) - return parent; - } while ((task = task->tk_next) != childq.task); - } + task_for_each(task, le, &childq.tasks) + if (task == parent) + return parent; + return NULL; } @@ -1015,7 +1007,8 @@ rpc_run_child(struct rpc_task *task, struct rpc_task *child, rpc_action func) void rpc_killall_tasks(struct rpc_clnt *clnt) { - struct rpc_task **q, *rovr; + struct rpc_task *rovr; + struct list_head *le; dprintk("RPC: killing all tasks for client %p\n", clnt); @@ -1023,13 +1016,12 @@ rpc_killall_tasks(struct rpc_clnt *clnt) * Spin lock all_tasks to prevent changes... */ spin_lock(&rpc_sched_lock); - for (q = &all_tasks; (rovr = *q); q = &rovr->tk_next_task) { + alltask_for_each(rovr, le, &all_tasks) if (!clnt || rovr->tk_client == clnt) { rovr->tk_flags |= RPC_TASK_KILLED; rpc_exit(rovr, -EIO); rpc_wake_up_task(rovr); } - } spin_unlock(&rpc_sched_lock); } @@ -1038,7 +1030,7 @@ static DECLARE_MUTEX_LOCKED(rpciod_running); static inline int rpciod_task_pending(void) { - return schedq.task != NULL || xprt_tcp_pending(); + return !list_empty(&schedq.tasks) || xprt_tcp_pending(); } @@ -1090,7 +1082,7 @@ rpciod(void *ptr) } dprintk("RPC: rpciod shutdown commences\n"); - if (all_tasks) { + if (!list_empty(&all_tasks)) { printk(KERN_ERR "rpciod: active tasks at shutdown?!\n"); rpciod_killall(); } @@ -1108,11 +1100,11 @@ rpciod_killall(void) { unsigned long flags; - while (all_tasks) { + while (!list_empty(&all_tasks)) { clear_thread_flag(TIF_SIGPENDING); rpc_killall_tasks(NULL); __rpc_schedule(); - if (all_tasks) { + if (!list_empty(&all_tasks)) { dprintk("rpciod_killall: waiting for tasks to exit\n"); yield(); } @@ -1207,25 +1199,23 @@ out: #ifdef RPC_DEBUG void rpc_show_tasks(void) { - struct rpc_task *t = all_tasks, *next; + struct list_head *le; + struct rpc_task *t; spin_lock(&rpc_sched_lock); - t = all_tasks; - if (!t) { + if (list_empty(&all_tasks)) { spin_unlock(&rpc_sched_lock); return; } printk("-pid- proc flgs status -client- -prog- --rqstp- -timeout " "-rpcwait -action- --exit--\n"); - for (; t; t = next) { - next = t->tk_next_task; + alltask_for_each(t, le, &all_tasks) printk("%05d %04d %04x %06d %8p %6d %8p %08ld %8s %8p %8p\n", t->tk_pid, t->tk_msg.rpc_proc, t->tk_flags, t->tk_status, t->tk_client, t->tk_client->cl_prog, t->tk_rqstp, t->tk_timeout, t->tk_rpcwait ? rpc_qname(t->tk_rpcwait) : " ", t->tk_action, t->tk_exit); - } spin_unlock(&rpc_sched_lock); } #endif diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index b4cc3d7f87d0..4e046495969a 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c @@ -44,6 +44,9 @@ svc_create(struct svc_program *prog, unsigned int bufsize, unsigned int xdrsize) serv->sv_stats = prog->pg_stats; serv->sv_bufsz = bufsize? bufsize : 4096; serv->sv_xdrsize = xdrsize; + INIT_LIST_HEAD(&serv->sv_threads); + INIT_LIST_HEAD(&serv->sv_sockets); + INIT_LIST_HEAD(&serv->sv_allsocks); spin_lock_init(&serv->sv_lock); serv->sv_name = prog->pg_name; @@ -72,8 +75,12 @@ svc_destroy(struct svc_serv *serv) } else printk("svc_destroy: no threads for serv=%p!\n", serv); - while ((svsk = serv->sv_allsocks) != NULL) + while (!list_empty(&serv->sv_allsocks)) { + svsk = list_entry(serv->sv_allsocks.next, + struct svc_sock, + sk_list); svc_delete_socket(svsk); + } /* Unregister service with the portmapper */ svc_register(serv, 0, 0); diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index 3aabbbf08581..646a8c982f0f 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c @@ -63,11 +63,14 @@ static int svc_udp_sendto(struct svc_rqst *); /* * Queue up an idle server thread. Must have serv->sv_lock held. + * Note: this is really a stack rather than a queue, so that we only + * use as many different threads as we need, and the rest don't polute + * the cache. */ static inline void svc_serv_enqueue(struct svc_serv *serv, struct svc_rqst *rqstp) { - rpc_append_list(&serv->sv_threads, rqstp); + list_add(&rqstp->rq_list, &serv->sv_threads); } /* @@ -76,7 +79,7 @@ svc_serv_enqueue(struct svc_serv *serv, struct svc_rqst *rqstp) static inline void svc_serv_dequeue(struct svc_serv *serv, struct svc_rqst *rqstp) { - rpc_remove_list(&serv->sv_threads, rqstp); + list_del(&rqstp->rq_list); } /* @@ -110,7 +113,8 @@ svc_sock_enqueue(struct svc_sock *svsk) /* NOTE: Local BH is already disabled by our caller. */ spin_lock(&serv->sv_lock); - if (serv->sv_threads && serv->sv_sockets) + if (!list_empty(&serv->sv_threads) && + !list_empty(&serv->sv_sockets)) printk(KERN_ERR "svc_sock_enqueue: threads and sockets both waiting??\n"); @@ -126,7 +130,10 @@ svc_sock_enqueue(struct svc_sock *svsk) */ svsk->sk_busy = 1; - if ((rqstp = serv->sv_threads) != NULL) { + if (!list_empty(&serv->sv_threads)) { + rqstp = list_entry(serv->sv_threads.next, + struct svc_rqst, + rq_list); dprintk("svc: socket %p served by daemon %p\n", svsk->sk_sk, rqstp); svc_serv_dequeue(serv, rqstp); @@ -139,7 +146,7 @@ svc_sock_enqueue(struct svc_sock *svsk) wake_up(&rqstp->rq_wait); } else { dprintk("svc: socket %p put into queue\n", svsk->sk_sk); - rpc_append_list(&serv->sv_sockets, svsk); + list_add_tail(&svsk->sk_ready, &serv->sv_sockets); svsk->sk_qued = 1; } @@ -155,14 +162,16 @@ svc_sock_dequeue(struct svc_serv *serv) { struct svc_sock *svsk; - if ((svsk = serv->sv_sockets) != NULL) - rpc_remove_list(&serv->sv_sockets, svsk); + if (list_empty(&serv->sv_sockets)) + return NULL; - if (svsk) { - dprintk("svc: socket %p dequeued, inuse=%d\n", - svsk->sk_sk, svsk->sk_inuse); - svsk->sk_qued = 0; - } + svsk = list_entry(serv->sv_sockets.next, + struct svc_sock, sk_ready); + list_del(&svsk->sk_ready); + + dprintk("svc: socket %p dequeued, inuse=%d\n", + svsk->sk_sk, svsk->sk_inuse); + svsk->sk_qued = 0; return svsk; } @@ -238,7 +247,10 @@ svc_wake_up(struct svc_serv *serv) struct svc_rqst *rqstp; spin_lock_bh(&serv->sv_lock); - if ((rqstp = serv->sv_threads) != NULL) { + if (!list_empty(&serv->sv_threads)) { + rqstp = list_entry(serv->sv_threads.next, + struct svc_rqst, + rq_list); dprintk("svc: daemon %p woken up.\n", rqstp); /* svc_serv_dequeue(serv, rqstp); @@ -958,8 +970,7 @@ if (svsk->sk_sk == NULL) } spin_lock_bh(&serv->sv_lock); - svsk->sk_list = serv->sv_allsocks; - serv->sv_allsocks = svsk; + list_add(&svsk->sk_list, &serv->sv_allsocks); spin_unlock_bh(&serv->sv_lock); dprintk("svc: svc_setup_socket created %p (inet %p)\n", @@ -1020,7 +1031,6 @@ bummer: void svc_delete_socket(struct svc_sock *svsk) { - struct svc_sock **rsk; struct svc_serv *serv; struct sock *sk; @@ -1034,17 +1044,9 @@ svc_delete_socket(struct svc_sock *svsk) spin_lock_bh(&serv->sv_lock); - for (rsk = &serv->sv_allsocks; *rsk; rsk = &(*rsk)->sk_list) { - if (*rsk == svsk) - break; - } - if (!*rsk) { - spin_unlock_bh(&serv->sv_lock); - return; - } - *rsk = svsk->sk_list; + list_del(&svsk->sk_list); if (svsk->sk_qued) - rpc_remove_list(&serv->sv_sockets, svsk); + list_del(&svsk->sk_ready); svsk->sk_dead = 1; diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index fb70c6c76728..3c429ef6ca93 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c @@ -542,25 +542,15 @@ xprt_reconn_status(struct rpc_task *task) static inline struct rpc_rqst * xprt_lookup_rqst(struct rpc_xprt *xprt, u32 xid) { - struct rpc_task *head, *task; struct rpc_rqst *req; - int safe = 0; + struct list_head *le; + struct rpc_task *task; spin_lock_bh(&rpc_queue_lock); - if ((head = xprt->pending.task) != NULL) { - task = head; - do { - if ((req = task->tk_rqstp) && req->rq_xid == xid) - goto out; - task = task->tk_next; - if (++safe > 100) { - printk("xprt_lookup_rqst: loop in Q!\n"); - goto out_bad; - } - } while (task != head); - } + task_for_each(task, le, &xprt->pending.tasks) + if ((req = task->tk_rqstp) && req->rq_xid == xid) + goto out; dprintk("RPC: unknown XID %08x in reply.\n", xid); - out_bad: req = NULL; out: if (req && !__rpc_lock_task(req->rq_task)) @@ -1487,9 +1477,9 @@ xprt_setup(struct socket *sock, int proto, } else xprt_default_timeout(&xprt->timeout, xprt->prot); - xprt->pending = RPC_INIT_WAITQ("xprt_pending"); - xprt->sending = RPC_INIT_WAITQ("xprt_sending"); - xprt->backlog = RPC_INIT_WAITQ("xprt_backlog"); + INIT_RPC_WAITQ(&xprt->pending, "xprt_pending"); + INIT_RPC_WAITQ(&xprt->sending, "xprt_sending"); + INIT_RPC_WAITQ(&xprt->backlog, "xprt_backlog"); /* initialize free list */ for (i = 0, req = xprt->slot; i < RPC_MAXREQS-1; i++, req++) -- cgit v1.2.3 From 294d77d98b929017f6d8e3929c58ccfa189e44d7 Mon Sep 17 00:00:00 2001 From: Neil Brown Date: Mon, 25 Feb 2002 22:23:32 -0800 Subject: [PATCH] PATCH 10/16: NFSD: TCP: rationalise locking in RPC server routines Tidy up SMP locking for svc_sock sk_lock is not necessary and is now removed. The only things that were happening under sk_lock but not the more global sv_lock were testing and setting some of the flags: sk_busy, sk_conn, sk_data etc. These have been changed to bits in a flags word which are atomically set and tested. Also, by establishing some simple rules about that must be done after setting these flags, the locking is not needed. With this patch sk_conn and sk_data are now flags, not counts (sk_data was already a flag for udp). They are set if there might be a connection or data, and only clear when we are sure there aren't (or when we are about to check if there is). svc_sock_accepted becomes identical to svc_sock_recieved and so is discarded in favour of the latter. sk_rqstp was never used and is now gone. --- include/linux/sunrpc/svcsock.h | 20 +++--- net/sunrpc/svcsock.c | 148 +++++++++++++++++------------------------ 2 files changed, 69 insertions(+), 99 deletions(-) (limited to 'include/linux') diff --git a/include/linux/sunrpc/svcsock.h b/include/linux/sunrpc/svcsock.h index 0c565502e272..e4bdc96ab6d8 100644 --- a/include/linux/sunrpc/svcsock.h +++ b/include/linux/sunrpc/svcsock.h @@ -19,17 +19,18 @@ struct svc_sock { struct list_head sk_list; /* list of all sockets */ struct socket * sk_sock; /* berkeley socket layer */ struct sock * sk_sk; /* INET layer */ - spinlock_t sk_lock; struct svc_serv * sk_server; /* service for this socket */ unsigned char sk_inuse; /* use count */ - unsigned char sk_busy; /* enqueued/receiving */ - unsigned char sk_conn; /* conn pending */ - unsigned char sk_close; /* dead or dying */ - int sk_data; /* data pending */ - unsigned int sk_temp : 1, /* temp socket */ - sk_qued : 1, /* on serv->sk_sockets */ - sk_dead : 1; /* socket closed */ + unsigned int sk_flags; +#define SK_BUSY 0 /* enqueued/receiving */ +#define SK_CONN 1 /* conn pending */ +#define SK_CLOSE 2 /* dead or dying */ +#define SK_DATA 3 /* data pending */ +#define SK_TEMP 4 /* temp (TCP) socket */ +#define SK_QUED 5 /* on serv->sk_sockets */ +#define SK_DEAD 6 /* socket closed */ + int (*sk_recvfrom)(struct svc_rqst *rqstp); int (*sk_sendto)(struct svc_rqst *rqstp); @@ -40,9 +41,6 @@ struct svc_sock { /* private TCP part */ int sk_reclen; /* length of record */ int sk_tcplen; /* current read length */ - - /* Debugging */ - struct svc_rqst * sk_rqstp; }; /* diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index 646a8c982f0f..288819609ca7 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c @@ -45,10 +45,19 @@ /* SMP locking strategy: * - * svc_sock->sk_lock and svc_serv->sv_lock protect their - * respective structures. + * svc_serv->sv_lock protects most stuff for that service. + * + * Some flags can be set to certain values at any time + * providing that certain rules are followed: + * + * SK_BUSY can be set to 0 at any time. + * svc_sock_enqueue must be called afterwards + * SK_CONN, SK_DATA, can be set or cleared at any time. + * after a set, svc_sock_enqueue must be called. + * after a clear, the socket must be read/accepted + * if this succeeds, it must be set again. + * SK_CLOSE can set at any time. It is never cleared. * - * Antideadlock ordering is sk_lock --> sv_lock. */ #define RPCDBG_FACILITY RPCDBG_SVCSOCK @@ -102,7 +111,6 @@ svc_release_skb(struct svc_rqst *rqstp) * Queue up a socket with data pending. If there are idle nfsd * processes, wake 'em up. * - * This must be called with svsk->sk_lock held. */ static void svc_sock_enqueue(struct svc_sock *svsk) @@ -110,15 +118,18 @@ svc_sock_enqueue(struct svc_sock *svsk) struct svc_serv *serv = svsk->sk_server; struct svc_rqst *rqstp; - /* NOTE: Local BH is already disabled by our caller. */ - spin_lock(&serv->sv_lock); + if (!(svsk->sk_flags & + ( (1<sv_lock); if (!list_empty(&serv->sv_threads) && !list_empty(&serv->sv_sockets)) printk(KERN_ERR "svc_sock_enqueue: threads and sockets both waiting??\n"); - if (svsk->sk_busy) { + if (test_bit(SK_BUSY, &svsk->sk_flags)) { /* Don't enqueue socket while daemon is receiving */ dprintk("svc: socket %p busy, not enqueued\n", svsk->sk_sk); goto out_unlock; @@ -128,7 +139,7 @@ svc_sock_enqueue(struct svc_sock *svsk) * server has processed all pending data and put the socket back * on the idle list. */ - svsk->sk_busy = 1; + set_bit(SK_BUSY, &svsk->sk_flags); if (!list_empty(&serv->sv_threads)) { rqstp = list_entry(serv->sv_threads.next, @@ -147,11 +158,11 @@ svc_sock_enqueue(struct svc_sock *svsk) } else { dprintk("svc: socket %p put into queue\n", svsk->sk_sk); list_add_tail(&svsk->sk_ready, &serv->sv_sockets); - svsk->sk_qued = 1; + set_bit(SK_QUED, &svsk->sk_flags); } out_unlock: - spin_unlock(&serv->sv_lock); + spin_unlock_bh(&serv->sv_lock); } /* @@ -171,49 +182,24 @@ svc_sock_dequeue(struct svc_serv *serv) dprintk("svc: socket %p dequeued, inuse=%d\n", svsk->sk_sk, svsk->sk_inuse); - svsk->sk_qued = 0; + clear_bit(SK_QUED, &svsk->sk_flags); return svsk; } /* - * Having read count bytes from a socket, check whether it + * Having read something from a socket, check whether it * needs to be re-enqueued. + * Note: SK_DATA only gets cleared when a read-attempt finds + * no (or insufficient) data. */ static inline void -svc_sock_received(struct svc_sock *svsk, int count) +svc_sock_received(struct svc_sock *svsk) { - spin_lock_bh(&svsk->sk_lock); - if ((svsk->sk_data -= count) < 0) { - printk(KERN_NOTICE "svc: sk_data negative!\n"); - svsk->sk_data = 0; - } - svsk->sk_rqstp = NULL; /* XXX */ - svsk->sk_busy = 0; - if (svsk->sk_conn || svsk->sk_data || svsk->sk_close) { - dprintk("svc: socket %p re-enqueued after receive\n", - svsk->sk_sk); - svc_sock_enqueue(svsk); - } - spin_unlock_bh(&svsk->sk_lock); + clear_bit(SK_BUSY, &svsk->sk_flags); + svc_sock_enqueue(svsk); } -/* - * Dequeue a new connection. - */ -static inline void -svc_sock_accepted(struct svc_sock *svsk) -{ - spin_lock_bh(&svsk->sk_lock); - svsk->sk_busy = 0; - svsk->sk_conn--; - if (svsk->sk_conn || svsk->sk_data || svsk->sk_close) { - dprintk("svc: socket %p re-enqueued after accept\n", - svsk->sk_sk); - svc_sock_enqueue(svsk); - } - spin_unlock_bh(&svsk->sk_lock); -} /* * Release a socket after use. @@ -228,7 +214,7 @@ svc_sock_release(struct svc_rqst *rqstp) rqstp->rq_sock = NULL; spin_lock_bh(&serv->sv_lock); - if (!--(svsk->sk_inuse) && svsk->sk_dead) { + if (!--(svsk->sk_inuse) && test_bit(SK_DEAD, &svsk->sk_flags)) { spin_unlock_bh(&serv->sv_lock); dprintk("svc: releasing dead socket\n"); sock_release(svsk->sk_sock); @@ -363,11 +349,9 @@ svc_udp_data_ready(struct sock *sk, int count) if (!svsk) goto out; dprintk("svc: socket %p(inet %p), count=%d, busy=%d\n", - svsk, sk, count, svsk->sk_busy); - spin_lock_bh(&svsk->sk_lock); - svsk->sk_data = 1; + svsk, sk, count, test_bit(SK_BUSY, &svsk->sk_flags)); + set_bit(SK_DATA, &svsk->sk_flags); svc_sock_enqueue(svsk); - spin_unlock_bh(&svsk->sk_lock); out: if (sk->sleep && waitqueue_active(sk->sleep)) wake_up_interruptible(sk->sleep); @@ -385,20 +369,21 @@ svc_udp_recvfrom(struct svc_rqst *rqstp) u32 *data; int err, len; - svsk->sk_data = 0; + clear_bit(SK_DATA, &svsk->sk_flags); while ((skb = skb_recv_datagram(svsk->sk_sk, 0, 1, &err)) == NULL) { - svc_sock_received(svsk, 0); + svc_sock_received(svsk); if (err == -EAGAIN) return err; /* possibly an icmp error */ dprintk("svc: recvfrom returned error %d\n", -err); } + set_bit(SK_DATA, &svsk->sk_flags); /* there may be more data... */ /* Sorry. */ if (skb_is_nonlinear(skb)) { if (skb_linearize(skb, GFP_KERNEL) != 0) { kfree_skb(skb); - svc_sock_received(svsk, 0); + svc_sock_received(svsk); return 0; } } @@ -406,13 +391,11 @@ svc_udp_recvfrom(struct svc_rqst *rqstp) if (skb->ip_summed != CHECKSUM_UNNECESSARY) { if ((unsigned short)csum_fold(skb_checksum(skb, 0, skb->len, skb->csum))) { skb_free_datagram(svsk->sk_sk, skb); - svc_sock_received(svsk, 0); + svc_sock_received(svsk); return 0; } } - /* There may be more data */ - svsk->sk_data = 1; len = skb->len - sizeof(struct udphdr); data = (u32 *) (skb->data + sizeof(struct udphdr)); @@ -434,7 +417,7 @@ svc_udp_recvfrom(struct svc_rqst *rqstp) /* One down, maybe more to go... */ svsk->sk_sk->stamp = skb->stamp; - svc_sock_received(svsk, 0); + svc_sock_received(svsk); return len; } @@ -494,10 +477,8 @@ svc_tcp_listen_data_ready(struct sock *sk, int count_unused) printk("svc: socket %p: no user data\n", sk); goto out; } - spin_lock_bh(&svsk->sk_lock); - svsk->sk_conn++; + set_bit(SK_CONN, &svsk->sk_flags); svc_sock_enqueue(svsk); - spin_unlock_bh(&svsk->sk_lock); out: if (sk->sleep && waitqueue_active(sk->sleep)) wake_up_interruptible_all(sk->sleep); @@ -518,10 +499,8 @@ svc_tcp_state_change(struct sock *sk) printk("svc: socket %p: no user data\n", sk); goto out; } - spin_lock_bh(&svsk->sk_lock); - svsk->sk_close = 1; + set_bit(SK_CLOSE, &svsk->sk_flags); svc_sock_enqueue(svsk); - spin_unlock_bh(&svsk->sk_lock); out: if (sk->sleep && waitqueue_active(sk->sleep)) wake_up_interruptible_all(sk->sleep); @@ -536,10 +515,8 @@ svc_tcp_data_ready(struct sock *sk, int count) sk, sk->user_data); if (!(svsk = (struct svc_sock *)(sk->user_data))) goto out; - spin_lock_bh(&svsk->sk_lock); - svsk->sk_data++; + set_bit(SK_DATA, &svsk->sk_flags); svc_sock_enqueue(svsk); - spin_unlock_bh(&svsk->sk_lock); out: if (sk->sleep && waitqueue_active(sk->sleep)) wake_up_interruptible(sk->sleep); @@ -572,13 +549,14 @@ svc_tcp_accept(struct svc_sock *svsk) newsock->type = sock->type; newsock->ops = ops = sock->ops; + clear_bit(SK_CONN, &svsk->sk_flags); if ((err = ops->accept(sock, newsock, O_NONBLOCK)) < 0) { - if (net_ratelimit()) + if (err != -EAGAIN && net_ratelimit()) printk(KERN_WARNING "%s: accept failed (err %d)!\n", serv->sv_name, -err); goto failed; /* aborted connection or whatever */ } - + set_bit(SK_CONN, &svsk->sk_flags); slen = sizeof(sin); err = ops->getname(newsock, (struct sockaddr *) &sin, &slen, 1); if (err < 0) { @@ -609,11 +587,9 @@ svc_tcp_accept(struct svc_sock *svsk) /* Precharge. Data may have arrived on the socket before we * installed the data_ready callback. */ - spin_lock_bh(&newsvsk->sk_lock); - newsvsk->sk_data = 1; - newsvsk->sk_temp = 1; + set_bit(SK_DATA, &newsvsk->sk_flags); + set_bit(SK_TEMP, &newsvsk->sk_flags); svc_sock_enqueue(newsvsk); - spin_unlock_bh(&newsvsk->sk_lock); if (serv->sv_stats) serv->sv_stats->nettcpconn++; @@ -634,23 +610,25 @@ svc_tcp_recvfrom(struct svc_rqst *rqstp) struct svc_sock *svsk = rqstp->rq_sock; struct svc_serv *serv = svsk->sk_server; struct svc_buf *bufp = &rqstp->rq_argbuf; - int len, ready, used; + int len; dprintk("svc: tcp_recv %p data %d conn %d close %d\n", - svsk, svsk->sk_data, svsk->sk_conn, svsk->sk_close); + svsk, test_bit(SK_DATA, &svsk->sk_flags), + test_bit(SK_CONN, &svsk->sk_flags), + test_bit(SK_CLOSE, &svsk->sk_flags)); - if (svsk->sk_close) { + if (test_bit(SK_CLOSE, &svsk->sk_flags)) { svc_delete_socket(svsk); return 0; } - if (svsk->sk_conn) { + if (test_bit(SK_CONN, &svsk->sk_flags)) { svc_tcp_accept(svsk); - svc_sock_accepted(svsk); + svc_sock_received(svsk); return 0; } - ready = svsk->sk_data; + clear_bit(SK_DATA, &svsk->sk_flags); /* Receive data. If we haven't got the record length yet, get * the next four bytes. Otherwise try to gobble up as much as @@ -694,15 +672,10 @@ svc_tcp_recvfrom(struct svc_rqst *rqstp) */ dprintk("svc: incomplete TCP record (%d of %d)\n", len, svsk->sk_reclen); - svc_sock_received(svsk, ready); + svc_sock_received(svsk); return -EAGAIN; /* record not complete */ } - /* if we think there is only one more record to read, but - * it is bigger than we expect, then two records must have arrived - * together, so pretend we aren't using the record.. */ - if (len > svsk->sk_reclen && ready == 1) - used = 0; - else used = 1; + set_bit(SK_DATA, &svsk->sk_flags); /* Frob argbuf */ bufp->iov[0].iov_base += 4; @@ -729,7 +702,7 @@ svc_tcp_recvfrom(struct svc_rqst *rqstp) svsk->sk_reclen = 0; svsk->sk_tcplen = 0; - svc_sock_received(svsk, used); + svc_sock_received(svsk); if (serv->sv_stats) serv->sv_stats->nettcpcnt++; @@ -738,11 +711,11 @@ svc_tcp_recvfrom(struct svc_rqst *rqstp) error: if (len == -EAGAIN) { dprintk("RPC: TCP recvfrom got EAGAIN\n"); - svc_sock_received(svsk, ready); /* Clear data ready */ + svc_sock_received(svsk); } else { printk(KERN_NOTICE "%s: recvfrom returned errno %d\n", svsk->sk_server->sv_name, -len); - svc_sock_received(svsk, 0); + svc_sock_received(svsk); } return len; @@ -949,7 +922,6 @@ svc_setup_socket(struct svc_serv *serv, struct socket *sock, svsk->sk_ostate = inet->state_change; svsk->sk_odata = inet->data_ready; svsk->sk_server = serv; - spin_lock_init(&svsk->sk_lock); /* Initialize the socket */ if (sock->type == SOCK_DGRAM) @@ -1045,11 +1017,11 @@ svc_delete_socket(struct svc_sock *svsk) spin_lock_bh(&serv->sv_lock); list_del(&svsk->sk_list); - if (svsk->sk_qued) + if (test_bit(SK_QUED, &svsk->sk_flags)) list_del(&svsk->sk_ready); - svsk->sk_dead = 1; + set_bit(SK_DEAD, &svsk->sk_flags); if (!svsk->sk_inuse) { spin_unlock_bh(&serv->sv_lock); -- cgit v1.2.3 From cbf593fcd65839fb89ff55a6696896b7841d77cb Mon Sep 17 00:00:00 2001 From: Neil Brown Date: Mon, 25 Feb 2002 22:23:44 -0800 Subject: [PATCH] PATCH 12/16: NFSD: TCP: Close idle TCP connections Close idle rpc/tcp sockets We split the list of sv_allsocks into two, one of permanent sockets (udp, tcp listener) and one of temporary sockets (tcp data). Whenever we complete a successful receive on a temp socket, it gets pushed to the end of the list. Whenever a thread wants to do something, it first checks if the oldest temp socket has not has a receive for 6 mintutes (should possibly be configurable). It so, we simulate a close. Finally we make sure that threads wake up every few minutes so that if the server is completely idle, all temp sockets will get closed. --- fs/nfsd/nfssvc.c | 2 +- include/linux/sunrpc/svc.h | 3 ++- include/linux/sunrpc/svcsock.h | 1 + net/sunrpc/svc.c | 13 ++++++++++--- net/sunrpc/svcsock.c | 40 ++++++++++++++++++++++++++++++++++++---- 5 files changed, 50 insertions(+), 9 deletions(-) (limited to 'include/linux') diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index 38553d55f902..06a92f835975 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c @@ -195,7 +195,7 @@ nfsd(struct svc_rqst *rqstp) * recvfrom routine. */ while ((err = svc_recv(serv, rqstp, - MAX_SCHEDULE_TIMEOUT)) == -EAGAIN) + 5*60*HZ)) == -EAGAIN) ; if (err < 0) break; diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h index 003b89a68852..a7f2bcc327a1 100644 --- a/include/linux/sunrpc/svc.h +++ b/include/linux/sunrpc/svc.h @@ -36,7 +36,8 @@ struct svc_serv { unsigned int sv_bufsz; /* datagram buffer size */ unsigned int sv_xdrsize; /* XDR buffer size */ - struct list_head sv_allsocks; /* all sockets */ + struct list_head sv_permsocks; /* all permanent sockets */ + struct list_head sv_tempsocks; /* all temporary sockets */ char * sv_name; /* service name */ }; diff --git a/include/linux/sunrpc/svcsock.h b/include/linux/sunrpc/svcsock.h index e4bdc96ab6d8..b8ca275d5ab5 100644 --- a/include/linux/sunrpc/svcsock.h +++ b/include/linux/sunrpc/svcsock.h @@ -41,6 +41,7 @@ struct svc_sock { /* private TCP part */ int sk_reclen; /* length of record */ int sk_tcplen; /* current read length */ + time_t sk_lastrecv; /* time of last received request */ }; /* diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index 1c47cf4ac3c4..6656922011e0 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c @@ -42,7 +42,8 @@ svc_create(struct svc_program *prog, unsigned int bufsize, unsigned int xdrsize) serv->sv_xdrsize = xdrsize; INIT_LIST_HEAD(&serv->sv_threads); INIT_LIST_HEAD(&serv->sv_sockets); - INIT_LIST_HEAD(&serv->sv_allsocks); + INIT_LIST_HEAD(&serv->sv_tempsocks); + INIT_LIST_HEAD(&serv->sv_permsocks); spin_lock_init(&serv->sv_lock); serv->sv_name = prog->pg_name; @@ -71,8 +72,14 @@ svc_destroy(struct svc_serv *serv) } else printk("svc_destroy: no threads for serv=%p!\n", serv); - while (!list_empty(&serv->sv_allsocks)) { - svsk = list_entry(serv->sv_allsocks.next, + while (!list_empty(&serv->sv_tempsocks)) { + svsk = list_entry(serv->sv_tempsocks.next, + struct svc_sock, + sk_list); + svc_delete_socket(svsk); + } + while (!list_empty(&serv->sv_permsocks)) { + svsk = list_entry(serv->sv_permsocks.next, struct svc_sock, sk_list); svc_delete_socket(svsk); diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index cbb060ed28dd..35a5fb3e0011 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c @@ -585,7 +585,6 @@ svc_tcp_accept(struct svc_sock *svsk) * installed the data_ready callback. */ set_bit(SK_DATA, &newsvsk->sk_flags); - set_bit(SK_TEMP, &newsvsk->sk_flags); svc_sock_enqueue(newsvsk); if (serv->sv_stats) @@ -781,7 +780,7 @@ svc_tcp_init(struct svc_sock *svsk) int svc_recv(struct svc_serv *serv, struct svc_rqst *rqstp, long timeout) { - struct svc_sock *svsk; + struct svc_sock *svsk =NULL; int len; DECLARE_WAITQUEUE(wait, current); @@ -805,7 +804,24 @@ svc_recv(struct svc_serv *serv, struct svc_rqst *rqstp, long timeout) return -EINTR; spin_lock_bh(&serv->sv_lock); - if ((svsk = svc_sock_dequeue(serv)) != NULL) { + if (!list_empty(&serv->sv_tempsocks)) { + svsk = list_entry(serv->sv_tempsocks.next, + struct svc_sock, sk_list); + /* apparently the "standard" is that clients close + * idle connections after 5 minutes, servers after + * 6 minutes + * http://www.connectathon.org/talks96/nfstcp.pdf + */ + if (CURRENT_TIME - svsk->sk_lastrecv < 6*60 + || test_bit(SK_BUSY, &svsk->sk_flags)) + svsk = NULL; + } + if (svsk) { + set_bit(SK_BUSY, &svsk->sk_flags); + set_bit(SK_CLOSE, &svsk->sk_flags); + rqstp->rq_sock = svsk; + svsk->sk_inuse++; + } else if ((svsk = svc_sock_dequeue(serv)) != NULL) { rqstp->rq_sock = svsk; svsk->sk_inuse++; } else { @@ -844,6 +860,14 @@ svc_recv(struct svc_serv *serv, struct svc_rqst *rqstp, long timeout) svc_sock_release(rqstp); return -EAGAIN; } + svsk->sk_lastrecv = CURRENT_TIME; + if (test_bit(SK_TEMP, &svsk->sk_flags)) { + /* push active sockets to end of list */ + spin_lock_bh(&serv->sv_lock); + list_del(&svsk->sk_list); + list_add_tail(&svsk->sk_list, &serv->sv_tempsocks); + spin_unlock_bh(&serv->sv_lock); + } rqstp->rq_secure = ntohs(rqstp->rq_addr.sin_port) < 1024; rqstp->rq_userset = 0; @@ -921,6 +945,7 @@ svc_setup_socket(struct svc_serv *serv, struct socket *sock, svsk->sk_ostate = inet->state_change; svsk->sk_odata = inet->data_ready; svsk->sk_server = serv; + svsk->sk_lastrecv = CURRENT_TIME; /* Initialize the socket */ if (sock->type == SOCK_DGRAM) @@ -940,8 +965,15 @@ if (svsk->sk_sk == NULL) return NULL; } + spin_lock_bh(&serv->sv_lock); - list_add(&svsk->sk_list, &serv->sv_allsocks); + if (!pmap_register) { + set_bit(SK_TEMP, &svsk->sk_flags); + list_add(&svsk->sk_list, &serv->sv_tempsocks); + } else { + clear_bit(SK_TEMP, &svsk->sk_flags); + list_add(&svsk->sk_list, &serv->sv_permsocks); + } spin_unlock_bh(&serv->sv_lock); dprintk("svc: svc_setup_socket created %p (inet %p)\n", -- cgit v1.2.3 From a87d73921a20f3e5df824eb27edff866e8a5169c Mon Sep 17 00:00:00 2001 From: Neil Brown Date: Mon, 25 Feb 2002 22:23:49 -0800 Subject: [PATCH] PATCH 13/16: NFSD: TCP: Reserve space on sndbuf so we never block when writing Make sure there is alway adequate sndbuf space for replies. We keep track of how much space might be needed for replies and never dequeue a request unless there is adequate space for a maximal reply. We assume each request will generate a maximal sized reply until the request is partly decoded. Each RPC program/procedure can specify the maximum size of a reply to the precedure (though they don't yet). The wspace callback is used to enqueue sockets that may be waiting for sndbuf space to become available. As there should always be enough buffer space to the full reply, the only reason that sock_sendmsg could block is due to a kmalloc delay. As this is likely to be fairly quick (and if it isn't the server is clagged anyway) we remove the MSG_DONTWAIT flag, but set a 30 second timeout on waiting. If the wait ever times out, we close the connection. If it doesn't we can be sure that we did a complete write. When a request completes, we make sure that the space used for the reply does not exceed the space reserved. This is an internal consistancy check. This patchs sets the sndbuf and rcvbuf sizes for all sockets used for rpc service. This size if dependant on the servers bufsize (S) and partially on the number of threads (N). For UDP sndbuf == 5*S rcvbuf == (N+2)*S for TCP sndbuf == N*S rcvbuf == 3*S see code for rationale (in comments). --- include/linux/sunrpc/svc.h | 6 ++ include/linux/sunrpc/svcsock.h | 4 + net/sunrpc/svc.c | 11 ++- net/sunrpc/svcsock.c | 175 ++++++++++++++++++++++++++++++++++++++++- 4 files changed, 192 insertions(+), 4 deletions(-) (limited to 'include/linux') diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h index a7f2bcc327a1..c56c9d726bd0 100644 --- a/include/linux/sunrpc/svc.h +++ b/include/linux/sunrpc/svc.h @@ -115,6 +115,10 @@ struct svc_rqst { void * rq_argp; /* decoded arguments */ void * rq_resp; /* xdr'd results */ + int rq_reserved; /* space on socket outq + * reserved for this request + */ + /* Catering to nfsd */ struct svc_client * rq_client; /* RPC peer info */ struct svc_cacherep * rq_cacherep; /* cache info */ @@ -163,6 +167,7 @@ struct svc_procedure { unsigned int pc_ressize; /* result struct size */ unsigned int pc_count; /* call count */ unsigned int pc_cachetype; /* cache info (NFS) */ + unsigned int pc_xdrressize; /* maximum size of XDR reply */ }; /* @@ -180,5 +185,6 @@ void svc_destroy(struct svc_serv *); int svc_process(struct svc_serv *, struct svc_rqst *); int svc_register(struct svc_serv *, int, unsigned short); void svc_wake_up(struct svc_serv *); +void svc_reserve(struct svc_rqst *rqstp, int space); #endif /* SUNRPC_SVC_H */ diff --git a/include/linux/sunrpc/svcsock.h b/include/linux/sunrpc/svcsock.h index b8ca275d5ab5..95f52982b49e 100644 --- a/include/linux/sunrpc/svcsock.h +++ b/include/linux/sunrpc/svcsock.h @@ -31,12 +31,15 @@ struct svc_sock { #define SK_QUED 5 /* on serv->sk_sockets */ #define SK_DEAD 6 /* socket closed */ + int sk_reserved; /* space on outq that is reserved */ + int (*sk_recvfrom)(struct svc_rqst *rqstp); int (*sk_sendto)(struct svc_rqst *rqstp); /* We keep the old state_change and data_ready CB's here */ void (*sk_ostate)(struct sock *); void (*sk_odata)(struct sock *, int bytes); + void (*sk_owspace)(struct sock *); /* private TCP part */ int sk_reclen; /* length of record */ @@ -52,5 +55,6 @@ void svc_delete_socket(struct svc_sock *); int svc_recv(struct svc_serv *, struct svc_rqst *, long); int svc_send(struct svc_rqst *); void svc_drop(struct svc_rqst *); +void svc_sock_update_bufs(struct svc_serv *serv); #endif /* SUNRPC_SVCSOCK_H */ diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index 6656922011e0..d76ba789eb07 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c @@ -67,8 +67,10 @@ svc_destroy(struct svc_serv *serv) serv->sv_nrthreads); if (serv->sv_nrthreads) { - if (--(serv->sv_nrthreads) != 0) + if (--(serv->sv_nrthreads) != 0) { + svc_sock_update_bufs(serv); return; + } } else printk("svc_destroy: no threads for serv=%p!\n", serv); @@ -148,6 +150,7 @@ svc_create_thread(svc_thread_fn func, struct svc_serv *serv) error = kernel_thread((int (*)(void *)) func, rqstp, 0); if (error < 0) goto out_thread; + svc_sock_update_bufs(serv); error = 0; out: return error; @@ -306,6 +309,12 @@ svc_process(struct svc_serv *serv, struct svc_rqst *rqstp) memset(rqstp->rq_argp, 0, procp->pc_argsize); memset(rqstp->rq_resp, 0, procp->pc_ressize); + /* un-reserve some of the out-queue now that we have a + * better idea of reply size + */ + if (procp->pc_xdrressize) + svc_reserve(rqstp, procp->pc_xdrressize<<2); + /* Call the function that processes the request. */ if (!versp->vs_dispatch) { /* Decode arguments */ diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index 35a5fb3e0011..31d671bbd995 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c @@ -135,6 +135,17 @@ svc_sock_enqueue(struct svc_sock *svsk) goto out_unlock; } + if (((svsk->sk_reserved + serv->sv_bufsz)*2 + > sock_wspace(svsk->sk_sk)) + && !test_bit(SK_CLOSE, &svsk->sk_flags) + && !test_bit(SK_CONN, &svsk->sk_flags)) { + /* Don't enqueue while not enough space for reply */ + dprintk("svc: socket %p no space, %d > %ld, not enqueued\n", + svsk->sk_sk, svsk->sk_reserved+serv->sv_bufsz, + sock_wspace(svsk->sk_sk)); + goto out_unlock; + } + /* Mark socket as busy. It will remain in this state until the * server has processed all pending data and put the socket back * on the idle list. @@ -154,6 +165,8 @@ svc_sock_enqueue(struct svc_sock *svsk) rqstp, rqstp->rq_sock); rqstp->rq_sock = svsk; svsk->sk_inuse++; + rqstp->rq_reserved = serv->sv_bufsz; + svsk->sk_reserved += rqstp->rq_reserved; wake_up(&rqstp->rq_wait); } else { dprintk("svc: socket %p put into queue\n", svsk->sk_sk); @@ -201,6 +214,31 @@ svc_sock_received(struct svc_sock *svsk) } +/** + * svc_reserve - change the space reserved for the reply to a request. + * @rqstp: The request in question + * @space: new max space to reserve + * + * Each request reserves some space on the output queue of the socket + * to make sure the reply fits. This function reduces that reserved + * space to be the amount of space used already, plus @space. + * + */ +void svc_reserve(struct svc_rqst *rqstp, int space) +{ + space += rqstp->rq_resbuf.len<<2; + + if (space < rqstp->rq_reserved) { + struct svc_sock *svsk = rqstp->rq_sock; + spin_lock_bh(&svsk->sk_server->sv_lock); + svsk->sk_reserved -= (rqstp->rq_reserved - space); + rqstp->rq_reserved = space; + spin_unlock_bh(&svsk->sk_server->sv_lock); + + svc_sock_enqueue(svsk); + } +} + /* * Release a socket after use. */ @@ -211,6 +249,20 @@ svc_sock_release(struct svc_rqst *rqstp) struct svc_serv *serv = svsk->sk_server; svc_release_skb(rqstp); + + /* Reset response buffer and release + * the reservation. + * But first, check that enough space was reserved + * for the reply, otherwise we have a bug! + */ + if ((rqstp->rq_resbuf.len<<2) > rqstp->rq_reserved) + printk(KERN_ERR "RPC request reserved %d but used %d\n", + rqstp->rq_reserved, + rqstp->rq_resbuf.len<<2); + + rqstp->rq_resbuf.buf = rqstp->rq_resbuf.base; + rqstp->rq_resbuf.len = 0; + svc_reserve(rqstp, 0); rqstp->rq_sock = NULL; spin_lock_bh(&serv->sv_lock); @@ -269,7 +321,13 @@ svc_sendto(struct svc_rqst *rqstp, struct iovec *iov, int nr) msg.msg_control = NULL; msg.msg_controllen = 0; - msg.msg_flags = MSG_DONTWAIT; + /* This was MSG_DONTWAIT, but I now want it to wait. + * The only thing that it would wait for is memory and + * if we are fairly low on memory, then we aren't likely + * to make much progress anyway. + * sk->sndtimeo is set to 30seconds just in case. + */ + msg.msg_flags = 0; oldfs = get_fs(); set_fs(KERNEL_DS); len = sock_sendmsg(sock, &msg, buflen); @@ -338,6 +396,32 @@ svc_recvfrom(struct svc_rqst *rqstp, struct iovec *iov, int nr, int buflen) return len; } +/* + * Set socket snd and rcv buffer lengths + */ +static inline void +svc_sock_setbufsize(struct socket *sock, unsigned int snd, unsigned int rcv) +{ +#if 0 + mm_segment_t oldfs; + oldfs = get_fs(); set_fs(KERNEL_DS); + sock_setsockopt(sock, SOL_SOCKET, SO_SNDBUF, + (char*)&snd, sizeof(snd)); + sock_setsockopt(sock, SOL_SOCKET, SO_RCVBUF, + (char*)&rcv, sizeof(rcv)); +#else + /* sock_setsockopt limits use to sysctl_?mem_max, + * which isn't acceptable. Until that is made conditional + * on not having CAP_SYS_RESOURCE or similar, we go direct... + * DaveM said I could! + */ + lock_sock(sock->sk); + sock->sk->sndbuf = snd * 2; + sock->sk->rcvbuf = rcv * 2; + sock->sk->userlocks |= SOCK_SNDBUF_LOCK|SOCK_RCVBUF_LOCK; + release_sock(sock->sk); +#endif +} /* * INET callback when data has been received on the socket. */ @@ -357,6 +441,27 @@ svc_udp_data_ready(struct sock *sk, int count) wake_up_interruptible(sk->sleep); } +/* + * INET callback when space is newly available on the socket. + */ +static void +svc_write_space(struct sock *sk) +{ + struct svc_sock *svsk = (struct svc_sock *)(sk->user_data); + + if (svsk) { + dprintk("svc: socket %p(inet %p), write_space busy=%d\n", + svsk, sk, test_bit(SK_BUSY, &svsk->sk_flags)); + svc_sock_enqueue(svsk); + } + + if (sk->sleep && waitqueue_active(sk->sleep)) { + printk(KERN_WARNING "RPC svc_write_space: some sleeping on %p\n", + svsk); + wake_up_interruptible(sk->sleep); + } +} + /* * Receive a datagram from a UDP socket. */ @@ -448,6 +553,7 @@ static int svc_udp_init(struct svc_sock *svsk) { svsk->sk_sk->data_ready = svc_udp_data_ready; + svsk->sk_sk->write_space = svc_write_space; svsk->sk_recvfrom = svc_udp_recvfrom; svsk->sk_sendto = svc_udp_sendto; @@ -581,6 +687,11 @@ svc_tcp_accept(struct svc_sock *svsk) if (!(newsvsk = svc_setup_socket(serv, newsock, &err, 0))) goto failed; + /* make sure that a write doesn't block forever when + * low on memory + */ + newsock->sk->sndtimeo = HZ*30; + /* Precharge. Data may have arrived on the socket before we * installed the data_ready callback. */ @@ -723,8 +834,6 @@ svc_tcp_recvfrom(struct svc_rqst *rqstp) /* * Send out data on TCP socket. - * FIXME: Make the sendto call non-blocking in order not to hang - * a daemon on a dead client. Requires write queue maintenance. */ static int svc_tcp_sendto(struct svc_rqst *rqstp) @@ -766,14 +875,70 @@ svc_tcp_init(struct svc_sock *svsk) dprintk("setting up TCP socket for reading\n"); sk->state_change = svc_tcp_state_change; sk->data_ready = svc_tcp_data_ready; + sk->write_space = svc_write_space; svsk->sk_reclen = 0; svsk->sk_tcplen = 0; + + /* sndbuf needs to have room for one request + * per thread, otherwise we can stall even when the + * network isn't a bottleneck. + * rcvbuf just needs to be able to hold a few requests. + * Normally they will be removed from the queue + * as soon a a complete request arrives. + */ + svc_sock_setbufsize(svsk->sk_sock, + svsk->sk_server->sv_nrthreads * + svsk->sk_server->sv_bufsz, + 3 * svsk->sk_server->sv_bufsz); } return 0; } +void +svc_sock_update_bufs(struct svc_serv *serv) +{ + /* + * The number of server threads has changed. Update + * rcvbuf and sndbuf accordingly on all sockets + */ + struct list_head *le; + + spin_lock_bh(&serv->sv_lock); + list_for_each(le, &serv->sv_permsocks) { + struct svc_sock *svsk = + list_entry(le, struct svc_sock, sk_list); + struct socket *sock = svsk->sk_sock; + if (sock->type == SOCK_DGRAM) { + /* udp sockets need large rcvbuf as all pending + * requests are still in that buffer. + * As outgoing requests do not wait for an + * ACK, only a moderate sndbuf is needed + */ + svc_sock_setbufsize(sock, + 5 * serv->sv_bufsz, + (serv->sv_nrthreads+2)* serv->sv_bufsz); + } else if (svsk->sk_sk->state != TCP_LISTEN) { + printk(KERN_ERR "RPC update_bufs: permanent sock neither UDP or TCP_LISTEN\n"); + } + } + list_for_each(le, &serv->sv_tempsocks) { + struct svc_sock *svsk = + list_entry(le, struct svc_sock, sk_list); + struct socket *sock = svsk->sk_sock; + if (sock->type == SOCK_STREAM) { + /* See svc_tcp_init above for rationale on buffer sizes */ + svc_sock_setbufsize(sock, + serv->sv_nrthreads * + serv->sv_bufsz, + 3 * serv->sv_bufsz); + } else + printk(KERN_ERR "RPC update_bufs: temp sock not TCP\n"); + } + spin_unlock_bh(&serv->sv_lock); +} + /* * Receive the next request on any socket. */ @@ -824,6 +989,8 @@ svc_recv(struct svc_serv *serv, struct svc_rqst *rqstp, long timeout) } else if ((svsk = svc_sock_dequeue(serv)) != NULL) { rqstp->rq_sock = svsk; svsk->sk_inuse++; + rqstp->rq_reserved = serv->sv_bufsz; + svsk->sk_reserved += rqstp->rq_reserved; } else { /* No data pending. Go to sleep */ svc_serv_enqueue(serv, rqstp); @@ -944,6 +1111,7 @@ svc_setup_socket(struct svc_serv *serv, struct socket *sock, svsk->sk_sk = inet; svsk->sk_ostate = inet->state_change; svsk->sk_odata = inet->data_ready; + svsk->sk_owspace = inet->write_space; svsk->sk_server = serv; svsk->sk_lastrecv = CURRENT_TIME; @@ -1044,6 +1212,7 @@ svc_delete_socket(struct svc_sock *svsk) sk->state_change = svsk->sk_ostate; sk->data_ready = svsk->sk_odata; + sk->write_space = svsk->sk_owspace; spin_lock_bh(&serv->sv_lock); -- cgit v1.2.3 From afdb4fa2b04a7e90e0746bc3d031a552656c7709 Mon Sep 17 00:00:00 2001 From: Neil Brown Date: Mon, 25 Feb 2002 22:24:00 -0800 Subject: [PATCH] PATCH 15/16: NFSD: TCP: Limit number of active tcp connections to an RPC service Limit number of active tcp connections to an RPC service If a connection comes in and that results in number of connections being more than 5 times the number of threads, then we close a connection. We randomly drop with the oldest or the newest connection. Thus if we are flooded with connection requests, some will get in and hopefully stay long enough to service at least one request. --- include/linux/sunrpc/svc.h | 1 + net/sunrpc/svcsock.c | 59 ++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 50 insertions(+), 10 deletions(-) (limited to 'include/linux') diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h index c56c9d726bd0..2d2461bb38c8 100644 --- a/include/linux/sunrpc/svc.h +++ b/include/linux/sunrpc/svc.h @@ -38,6 +38,7 @@ struct svc_serv { struct list_head sv_permsocks; /* all permanent sockets */ struct list_head sv_tempsocks; /* all temporary sockets */ + int sv_tmpcnt; /* count of temporary sockets */ char * sv_name; /* service name */ }; diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index 31d671bbd995..919a095f6953 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c @@ -243,10 +243,25 @@ void svc_reserve(struct svc_rqst *rqstp, int space) * Release a socket after use. */ static inline void +svc_sock_put(struct svc_sock *svsk) +{ + struct svc_serv *serv = svsk->sk_server; + + spin_lock_bh(&serv->sv_lock); + if (!--(svsk->sk_inuse) && test_bit(SK_DEAD, &svsk->sk_flags)) { + spin_unlock_bh(&serv->sv_lock); + dprintk("svc: releasing dead socket\n"); + sock_release(svsk->sk_sock); + kfree(svsk); + } + else + spin_unlock_bh(&serv->sv_lock); +} + +static void svc_sock_release(struct svc_rqst *rqstp) { struct svc_sock *svsk = rqstp->rq_sock; - struct svc_serv *serv = svsk->sk_server; svc_release_skb(rqstp); @@ -265,15 +280,7 @@ svc_sock_release(struct svc_rqst *rqstp) svc_reserve(rqstp, 0); rqstp->rq_sock = NULL; - spin_lock_bh(&serv->sv_lock); - if (!--(svsk->sk_inuse) && test_bit(SK_DEAD, &svsk->sk_flags)) { - spin_unlock_bh(&serv->sv_lock); - dprintk("svc: releasing dead socket\n"); - sock_release(svsk->sk_sock); - kfree(svsk); - } - else - spin_unlock_bh(&serv->sv_lock); + svc_sock_put(svsk); } /* @@ -698,6 +705,35 @@ svc_tcp_accept(struct svc_sock *svsk) set_bit(SK_DATA, &newsvsk->sk_flags); svc_sock_enqueue(newsvsk); + /* make sure that we don't have too many active connections. + * If we have, something must be dropped. + * We randomly choose between newest and oldest (in terms + * of recent activity) and drop it. + */ + if (serv->sv_tmpcnt > serv->sv_nrthreads*5) { + struct svc_sock *svsk = NULL; + spin_lock_bh(&serv->sv_lock); + if (!list_empty(&serv->sv_tempsocks)) { + if (net_random()&1) + svsk = list_entry(serv->sv_tempsocks.prev, + struct svc_sock, + sk_list); + else + svsk = list_entry(serv->sv_tempsocks.next, + struct svc_sock, + sk_list); + set_bit(SK_CLOSE, &svsk->sk_flags); + svsk->sk_inuse ++; + } + spin_unlock_bh(&serv->sv_lock); + + if (svsk) { + svc_sock_enqueue(svsk); + svc_sock_put(svsk); + } + + } + if (serv->sv_stats) serv->sv_stats->nettcpconn++; @@ -1138,6 +1174,7 @@ if (svsk->sk_sk == NULL) if (!pmap_register) { set_bit(SK_TEMP, &svsk->sk_flags); list_add(&svsk->sk_list, &serv->sv_tempsocks); + serv->sv_tmpcnt++; } else { clear_bit(SK_TEMP, &svsk->sk_flags); list_add(&svsk->sk_list, &serv->sv_permsocks); @@ -1217,6 +1254,8 @@ svc_delete_socket(struct svc_sock *svsk) spin_lock_bh(&serv->sv_lock); list_del(&svsk->sk_list); + if (test_bit(SK_TEMP, &svsk->sk_flags)) + serv->sv_tmpcnt--; if (test_bit(SK_QUED, &svsk->sk_flags)) list_del(&svsk->sk_ready); -- cgit v1.2.3 From 34a7eea964236ed2e780f6376b79d7791e6b0ec0 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 26 Feb 2002 00:57:44 -0800 Subject: [PATCH] updates. Forward ports from 2.4, Various janitor bits, and some fixes by me to make the thing work again in 2.5. I munged the MTDRAM driver to work also (seperate patch to follow), and it seems to work. David Woodhouse gave this the once over, and approved the changes. Complete changelog below: o Don't create two slabcaches with the same name. o Don't corrupt eraseblock lists on mount o Don't mark nodes obsolete during mount o __attribute__((packed)) on the node definitions. o Fix up() without down() in jffs2_readdir(). o Fix duplicate version number usage - s/highest_version++/++highest_version/ o Fix (i.e. implement) mtime/ctime on directories. maybe too busy with the bk stuff o Don't allow hardlinks of directories. o s/(mode&S_IFMT)==S_IFLNK/S_ISLNK(mode)/ et al to keep Al happy. o Fix for garbage-collection of holes, where we used to write nodes out with csize/dsize swapped. Workarounds for existing such brokenness. o Improve wear levelling by rotating node lists on mount, to avoid starting at one end of the flash every time. o Remember to get internal inode-semaphore on symlink operations. --- fs/jffs/intrep.c | 2 +- fs/jffs2/dir.c | 75 +++++++++++++++++++++++++++------------------ fs/jffs2/erase.c | 12 +++++--- fs/jffs2/file.c | 13 ++++---- fs/jffs2/gc.c | 13 ++++---- fs/jffs2/malloc.c | 2 +- fs/jffs2/nodelist.c | 40 ++++++++++++++++-------- fs/jffs2/nodelist.h | 5 +-- fs/jffs2/readinode.c | 34 ++++++++++++++------ fs/jffs2/scan.c | 62 +++++++++++++++++++++++++++++++++++-- fs/jffs2/super.c | 9 ++++-- fs/jffs2/symlink.c | 11 +++++-- include/linux/jffs2.h | 8 ++--- include/linux/jffs2_fs_sb.h | 3 +- 14 files changed, 203 insertions(+), 86 deletions(-) (limited to 'include/linux') diff --git a/fs/jffs/intrep.c b/fs/jffs/intrep.c index e1a0d5d9b833..b0df6fbaca37 100644 --- a/fs/jffs/intrep.c +++ b/fs/jffs/intrep.c @@ -2643,7 +2643,7 @@ jffs_print_tree(struct jffs_file *first_file, int indent) void jffs_print_memory_allocation_statistics(void) { - static long printout = 0; + static long printout; printk("________ Memory printout #%ld ________\n", ++printout); printk("no_jffs_file = %ld\n", no_jffs_file); printk("no_jffs_node = %ld\n", no_jffs_node); diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c index daadcf077ade..c505416ae609 100644 --- a/fs/jffs2/dir.c +++ b/fs/jffs2/dir.c @@ -31,7 +31,7 @@ * provisions above, a recipient may use your version of this file * under either the RHEPL or the GPL. * - * $Id: dir.c,v 1.42 2001/05/24 22:24:39 dwmw2 Exp $ + * $Id: dir.c,v 1.45.2.5 2002/02/23 14:31:09 dwmw2 Exp $ * */ @@ -39,6 +39,7 @@ #include #include #include +#include /* For completion */ #include #include #include @@ -181,11 +182,11 @@ static int jffs2_readdir(struct file *filp, void *dirent, filldir_t filldir) } D2(printk(KERN_DEBUG "Dirent %ld: \"%s\", ino #%u, type %d\n", offset, fd->name, fd->ino, fd->type)); if (filldir(dirent, fd->name, strlen(fd->name), offset, fd->ino, fd->type) < 0) - goto out; + break; offset++; } - out: up(&f->sem); + out: filp->f_pos = offset; return 0; } @@ -305,7 +306,7 @@ static int jffs2_create(struct inode *dir_i, struct dentry *dentry, int mode) rd->hdr_crc = crc32(0, rd, sizeof(struct jffs2_unknown_node)-4); rd->pino = dir_i->i_ino; - rd->version = dir_f->highest_version++; + rd->version = ++dir_f->highest_version; rd->ino = inode->i_ino; rd->mctime = CURRENT_TIME; rd->nsize = namelen; @@ -316,17 +317,21 @@ static int jffs2_create(struct inode *dir_i, struct dentry *dentry, int mode) fd = jffs2_write_dirent(dir_i, rd, dentry->d_name.name, namelen, phys_ofs, &writtenlen); jffs2_complete_reservation(c); - jffs2_free_raw_dirent(rd); - + if (IS_ERR(fd)) { /* dirent failed to write. Delete the inode normally as if it were the final unlink() */ + jffs2_free_raw_dirent(rd); up(&dir_f->sem); jffs2_clear_inode(inode); unlock_kernel(); return PTR_ERR(fd); } + dir_i->i_mtime = dir_i->i_ctime = rd->mctime; + + jffs2_free_raw_dirent(rd); + /* Link the fd into the inode's list, obsoleting an old one if necessary. */ jffs2_add_fd_to_list(c, fd, &dir_f->dents); @@ -373,7 +378,7 @@ static int jffs2_do_unlink(struct inode *dir_i, struct dentry *dentry, int renam rd->hdr_crc = crc32(0, rd, sizeof(struct jffs2_unknown_node)-4); rd->pino = dir_i->i_ino; - rd->version = dir_f->highest_version++; + rd->version = ++dir_f->highest_version; rd->ino = 0; rd->mctime = CURRENT_TIME; rd->nsize = dentry->d_name.len; @@ -464,7 +469,7 @@ static int jffs2_do_link (struct dentry *old_dentry, struct inode *dir_i, struct rd->hdr_crc = crc32(0, rd, sizeof(struct jffs2_unknown_node)-4); rd->pino = dir_i->i_ino; - rd->version = dir_f->highest_version++; + rd->version = ++dir_f->highest_version; rd->ino = old_dentry->d_inode->i_ino; rd->mctime = CURRENT_TIME; rd->nsize = dentry->d_name.len; @@ -503,6 +508,9 @@ static int jffs2_link (struct dentry *old_dentry, struct inode *dir_i, struct de { int ret; + if (S_ISDIR(old_dentry->d_inode->i_mode)) + return -EPERM; + lock_kernel(); ret = jffs2_do_link(old_dentry, dir_i, dentry, 0); if (!ret) { @@ -567,7 +575,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char f = JFFS2_INODE_INFO(inode); - ri->dsize = ri->csize = strlen(target); + inode->i_size = ri->isize = ri->dsize = ri->csize = strlen(target); ri->totlen = sizeof(*ri) + ri->dsize; ri->hdr_crc = crc32(0, ri, sizeof(struct jffs2_unknown_node)-4); @@ -628,7 +636,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char rd->hdr_crc = crc32(0, rd, sizeof(struct jffs2_unknown_node)-4); rd->pino = dir_i->i_ino; - rd->version = dir_f->highest_version++; + rd->version = ++dir_f->highest_version; rd->ino = inode->i_ino; rd->mctime = CURRENT_TIME; rd->nsize = namelen; @@ -639,16 +647,19 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char fd = jffs2_write_dirent(dir_i, rd, dentry->d_name.name, namelen, phys_ofs, &writtenlen); jffs2_complete_reservation(c); - jffs2_free_raw_dirent(rd); if (IS_ERR(fd)) { /* dirent failed to write. Delete the inode normally as if it were the final unlink() */ + jffs2_free_raw_dirent(rd); up(&dir_f->sem); jffs2_clear_inode(inode); unlock_kernel(); return PTR_ERR(fd); } + dir_i->i_mtime = dir_i->i_ctime = rd->mctime; + + jffs2_free_raw_dirent(rd); /* Link the fd into the inode's list, obsoleting an old one if necessary. */ @@ -768,7 +779,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode) rd->hdr_crc = crc32(0, rd, sizeof(struct jffs2_unknown_node)-4); rd->pino = dir_i->i_ino; - rd->version = dir_f->highest_version++; + rd->version = ++dir_f->highest_version; rd->ino = inode->i_ino; rd->mctime = CURRENT_TIME; rd->nsize = namelen; @@ -779,17 +790,21 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode) fd = jffs2_write_dirent(dir_i, rd, dentry->d_name.name, namelen, phys_ofs, &writtenlen); jffs2_complete_reservation(c); - jffs2_free_raw_dirent(rd); if (IS_ERR(fd)) { /* dirent failed to write. Delete the inode normally as if it were the final unlink() */ + jffs2_free_raw_dirent(rd); up(&dir_f->sem); jffs2_clear_inode(inode); unlock_kernel(); return PTR_ERR(fd); } + dir_i->i_mtime = dir_i->i_ctime = rd->mctime; + + jffs2_free_raw_dirent(rd); + /* Link the fd into the inode's list, obsoleting an old one if necessary. */ jffs2_add_fd_to_list(c, fd, &dir_f->dents); @@ -841,8 +856,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, in c = JFFS2_SB_INFO(dir_i->i_sb); - if ((mode & S_IFMT) == S_IFBLK || - (mode & S_IFMT) == S_IFCHR) { + if (S_ISBLK(mode) || S_ISCHR(mode)) { dev = (MAJOR(rdev) << 8) | MINOR(rdev); devlen = sizeof(dev); } @@ -933,7 +947,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, in rd->hdr_crc = crc32(0, rd, sizeof(struct jffs2_unknown_node)-4); rd->pino = dir_i->i_ino; - rd->version = dir_f->highest_version++; + rd->version = ++dir_f->highest_version; rd->ino = inode->i_ino; rd->mctime = CURRENT_TIME; rd->nsize = namelen; @@ -947,17 +961,21 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, in fd = jffs2_write_dirent(dir_i, rd, dentry->d_name.name, namelen, phys_ofs, &writtenlen); jffs2_complete_reservation(c); - jffs2_free_raw_dirent(rd); if (IS_ERR(fd)) { /* dirent failed to write. Delete the inode normally as if it were the final unlink() */ + jffs2_free_raw_dirent(rd); up(&dir_f->sem); jffs2_clear_inode(inode); unlock_kernel(); return PTR_ERR(fd); } + dir_i->i_mtime = dir_i->i_ctime = rd->mctime; + + jffs2_free_raw_dirent(rd); + /* Link the fd into the inode's list, obsoleting an old one if necessary. */ jffs2_add_fd_to_list(c, fd, &dir_f->dents); @@ -965,6 +983,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, in unlock_kernel(); d_instantiate(dentry, inode); + return 0; } @@ -989,20 +1008,16 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry, ret = jffs2_do_unlink(old_dir_i, old_dentry, 1); if (ret) { - /* Try to delete the _new_ link to return a clean failure */ - int ret2 = jffs2_do_unlink(new_dir_i, new_dentry, 1); - if (ret2) { - struct jffs2_inode_info *f = JFFS2_INODE_INFO(old_dentry->d_inode); - down(&f->sem); - old_dentry->d_inode->i_nlink = f->inocache->nlink++; - up(&f->sem); + /* Oh shit. We really ought to make a single node which can do both atomically */ + struct jffs2_inode_info *f = JFFS2_INODE_INFO(old_dentry->d_inode); + down(&f->sem); + old_dentry->d_inode->i_nlink = f->inocache->nlink++; + up(&f->sem); - printk(KERN_NOTICE "jffs2_rename(): Link succeeded, unlink failed (old err %d, new err %d). You now have a hard link\n", ret, ret2); - /* Might as well let the VFS know */ - d_instantiate(new_dentry, old_dentry->d_inode); - atomic_inc(&old_dentry->d_inode->i_count); - } - + printk(KERN_NOTICE "jffs2_rename(): Link succeeded, unlink failed (err %d). You now have a hard link\n", ret); + /* Might as well let the VFS know */ + d_instantiate(new_dentry, old_dentry->d_inode); + atomic_inc(&old_dentry->d_inode->i_count); } unlock_kernel(); return ret; diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c index 2dc9b5f38294..be16d7cc263d 100644 --- a/fs/jffs2/erase.c +++ b/fs/jffs2/erase.c @@ -31,7 +31,7 @@ * provisions above, a recipient may use your version of this file * under either the RHEPL or the GPL. * - * $Id: erase.c,v 1.23 2001/09/19 21:51:11 dwmw2 Exp $ + * $Id: erase.c,v 1.24 2001/12/06 16:38:38 dwmw2 Exp $ * */ #include @@ -214,8 +214,8 @@ static inline void jffs2_remove_node_refs_from_ino_list(struct jffs2_sb_info *c, D2({ int i=0; - struct jffs2_raw_node_ref *this; - printk(KERN_DEBUG "After remove_node_refs_from_ino_list: \n" KERN_DEBUG); + struct jffs2_raw_node_ref *this; + printk(KERN_DEBUG "After remove_node_refs_from_ino_list: \n" KERN_DEBUG); this = ic->nodes; @@ -262,7 +262,11 @@ void jffs2_erase_pending_trigger(struct jffs2_sb_info *c) void jffs2_mark_erased_blocks(struct jffs2_sb_info *c) { - static struct jffs2_unknown_node marker = {JFFS2_MAGIC_BITMASK, JFFS2_NODETYPE_CLEANMARKER, sizeof(struct jffs2_unknown_node)}; + static struct jffs2_unknown_node marker = { + magic: JFFS2_MAGIC_BITMASK, + nodetype: JFFS2_NODETYPE_CLEANMARKER, + totlen: sizeof(struct jffs2_unknown_node) + }; struct jffs2_eraseblock *jeb; struct jffs2_raw_node_ref *marker_ref; unsigned char *ebuf; diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c index f0446acb9194..190a428acff8 100644 --- a/fs/jffs2/file.c +++ b/fs/jffs2/file.c @@ -31,7 +31,7 @@ * provisions above, a recipient may use your version of this file * under either the RHEPL or the GPL. * - * $Id: file.c,v 1.58 2001/09/20 15:28:31 dwmw2 Exp $ + * $Id: file.c,v 1.58.2.1 2002/02/23 14:25:36 dwmw2 Exp $ * */ @@ -102,15 +102,14 @@ int jffs2_setattr (struct dentry *dentry, struct iattr *iattr) must read the original data associated with the node (i.e. the device numbers or the target name) and write it out again with the appropriate data attached */ - if ((inode->i_mode & S_IFMT) == S_IFBLK || - (inode->i_mode & S_IFMT) == S_IFCHR) { + if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) { /* For these, we don't actually need to read the old node */ dev = (major(dentry->d_inode->i_rdev) << 8) | minor(dentry->d_inode->i_rdev); mdata = (char *)&dev; mdatalen = sizeof(dev); D1(printk(KERN_DEBUG "jffs2_setattr(): Writing %d bytes of kdev_t\n", mdatalen)); - } else if ((inode->i_mode & S_IFMT) == S_IFLNK) { + } else if (S_ISLNK(inode->i_mode)) { mdatalen = f->metadata->size; mdata = kmalloc(f->metadata->size, GFP_USER); if (!mdata) @@ -125,7 +124,7 @@ int jffs2_setattr (struct dentry *dentry, struct iattr *iattr) ri = jffs2_alloc_raw_inode(); if (!ri) { - if ((inode->i_mode & S_IFMT) == S_IFLNK) + if (S_ISLNK(inode->i_mode)) kfree(mdata); return -ENOMEM; } @@ -133,7 +132,7 @@ int jffs2_setattr (struct dentry *dentry, struct iattr *iattr) ret = jffs2_reserve_space(c, sizeof(*ri) + mdatalen, &phys_ofs, &alloclen, ALLOC_NORMAL); if (ret) { jffs2_free_raw_inode(ri); - if ((inode->i_mode & S_IFMT) == S_IFLNK) + if (S_ISLNK(inode->i_mode)) kfree(mdata); return ret; } @@ -177,7 +176,7 @@ int jffs2_setattr (struct dentry *dentry, struct iattr *iattr) ri->data_crc = 0; new_metadata = jffs2_write_dnode(inode, ri, mdata, mdatalen, phys_ofs, NULL); - if ((inode->i_mode & S_IFMT) == S_IFLNK) + if (S_ISLNK(inode->i_mode)) kfree(mdata); jffs2_complete_reservation(c); diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c index fc4ab75ea921..f61cbf699414 100644 --- a/fs/jffs2/gc.c +++ b/fs/jffs2/gc.c @@ -31,7 +31,7 @@ * provisions above, a recipient may use your version of this file * under either the RHEPL or the GPL. * - * $Id: gc.c,v 1.52 2001/09/19 21:53:47 dwmw2 Exp $ + * $Id: gc.c,v 1.52.2.2 2002/02/23 14:25:36 dwmw2 Exp $ * */ @@ -266,15 +266,14 @@ static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_ __u32 alloclen, phys_ofs; int ret; - if ((inode->i_mode & S_IFMT) == S_IFBLK || - (inode->i_mode & S_IFMT) == S_IFCHR) { + if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) { /* For these, we don't actually need to read the old node */ dev = (major(inode->i_rdev) << 8) | minor(inode->i_rdev); mdata = (char *)&dev; mdatalen = sizeof(dev); D1(printk(KERN_DEBUG "jffs2_garbage_collect_metadata(): Writing %d bytes of kdev_t\n", mdatalen)); - } else if ((inode->i_mode & S_IFMT) == S_IFLNK) { + } else if (S_ISLNK(inode->i_mode)) { mdatalen = fn->size; mdata = kmalloc(fn->size, GFP_KERNEL); if (!mdata) { @@ -331,7 +330,7 @@ static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_ jffs2_free_full_dnode(fn); f->metadata = new_fn; out: - if ((inode->i_mode & S_IFMT) == S_IFLNK) + if (S_ISLNK(inode->i_mode)) kfree(mdata); return ret; } @@ -466,8 +465,8 @@ static int jffs2_garbage_collect_hole(struct jffs2_sb_info *c, struct jffs2_eras ri.ino = inode->i_ino; ri.version = ++f->highest_version; ri.offset = start; - ri.csize = end - start; - ri.dsize = 0; + ri.dsize = end - start; + ri.csize = 0; ri.compr = JFFS2_COMPR_ZERO; } ri.mode = inode->i_mode; diff --git a/fs/jffs2/malloc.c b/fs/jffs2/malloc.c index 18874665d265..b43333100b19 100644 --- a/fs/jffs2/malloc.c +++ b/fs/jffs2/malloc.c @@ -139,7 +139,7 @@ int __init jffs2_create_slab_caches(void) if (!jffs2_inode_cachep) goto err; - inode_cache_slab = kmem_cache_create("jffs2_inode_cache", sizeof(struct jffs2_inode_cache), 0, JFFS2_SLAB_POISON, NULL, NULL); + inode_cache_slab = kmem_cache_create("jffs2_inode", sizeof(struct jffs2_inode_cache), 0, JFFS2_SLAB_POISON, NULL, NULL); if (inode_cache_slab) return 0; diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c index 27e90b8b366e..285971b48542 100644 --- a/fs/jffs2/nodelist.c +++ b/fs/jffs2/nodelist.c @@ -1,7 +1,7 @@ /* * JFFS2 -- Journalling Flash File System, Version 2. * - * Copyright (C) 2001 Red Hat, Inc. + * Copyright (C) 2001, 2002 Red Hat, Inc. * * Created by David Woodhouse * @@ -31,7 +31,7 @@ * provisions above, a recipient may use your version of this file * under either the RHEPL or the GPL. * - * $Id: nodelist.c,v 1.30 2001/11/14 10:35:21 dwmw2 Exp $ + * $Id: nodelist.c,v 1.30.2.3 2002/02/23 14:04:44 dwmw2 Exp $ * */ @@ -94,7 +94,8 @@ void jffs2_add_tn_to_list(struct jffs2_tmp_dnode_info *tn, struct jffs2_tmp_dnod int jffs2_get_inode_nodes(struct jffs2_sb_info *c, ino_t ino, struct jffs2_inode_info *f, struct jffs2_tmp_dnode_info **tnp, struct jffs2_full_dirent **fdp, - __u32 *highest_version) + __u32 *highest_version, __u32 *latest_mctime, + __u32 *mctime_ver) { struct jffs2_raw_node_ref *ref = f->inocache->nodes; struct jffs2_tmp_dnode_info *tn, *ret_tn = NULL; @@ -104,6 +105,8 @@ int jffs2_get_inode_nodes(struct jffs2_sb_info *c, ino_t ino, struct jffs2_inode size_t retlen; int err; + *mctime_ver = 0; + D1(printk(KERN_DEBUG "jffs2_get_inode_nodes(): ino #%lu\n", ino)); if (!f->inocache->nodes) { printk(KERN_WARNING "Eep. no nodes for ino #%lu\n", ino); @@ -115,7 +118,7 @@ int jffs2_get_inode_nodes(struct jffs2_sb_info *c, ino_t ino, struct jffs2_inode D1(printk(KERN_DEBUG "node at 0x%08x is obsoleted. Ignoring.\n", ref->flash_offset &~3)); continue; } - err = c->mtd->read(c->mtd, (ref->flash_offset & ~3), sizeof(node), &retlen, (void *)&node); + err = c->mtd->read(c->mtd, (ref->flash_offset & ~3), min(ref->totlen, sizeof(node)), &retlen, (void *)&node); if (err) { printk(KERN_WARNING "error %d reading node at 0x%08x in get_inode_nodes()\n", err, (ref->flash_offset) & ~3); goto free_out; @@ -123,7 +126,7 @@ int jffs2_get_inode_nodes(struct jffs2_sb_info *c, ino_t ino, struct jffs2_inode /* Check we've managed to read at least the common node header */ - if (retlen < sizeof(node.u)) { + if (retlen < min(ref->totlen, sizeof(node.u))) { printk(KERN_WARNING "short read in get_inode_nodes()\n"); err = -EIO; goto free_out; @@ -153,15 +156,22 @@ int jffs2_get_inode_nodes(struct jffs2_sb_info *c, ino_t ino, struct jffs2_inode fd->version = node.d.version; fd->ino = node.d.ino; fd->type = node.d.type; - /* memcpy as much of the name as possible from the raw - dirent we've already read from the flash - */ + + /* Pick out the mctime of the latest dirent */ + if(fd->version > *mctime_ver) { + *mctime_ver = fd->version; + *latest_mctime = node.d.mctime; + } + + /* memcpy as much of the name as possible from the raw + dirent we've already read from the flash + */ if (retlen > sizeof(struct jffs2_raw_dirent)) memcpy(&fd->name[0], &node.d.name[0], min((__u32)node.d.nsize, (retlen-sizeof(struct jffs2_raw_dirent)))); - /* Do we need to copy any more of the name directly - from the flash? - */ + /* Do we need to copy any more of the name directly + from the flash? + */ if (node.d.nsize + sizeof(struct jffs2_raw_dirent) > retlen) { int already = retlen - sizeof(struct jffs2_raw_dirent); @@ -217,7 +227,12 @@ int jffs2_get_inode_nodes(struct jffs2_sb_info *c, ino_t ino, struct jffs2_inode } tn->version = node.i.version; tn->fn->ofs = node.i.offset; - tn->fn->size = node.i.dsize; + /* There was a bug where we wrote hole nodes out with + csize/dsize swapped. Deal with it */ + if (node.i.compr == JFFS2_COMPR_ZERO && !node.i.dsize && node.i.csize) + tn->fn->size = node.i.csize; + else // normal case... + tn->fn->size = node.i.dsize; tn->fn->raw = ref; D1(printk(KERN_DEBUG "dnode @%08x: ver %u, offset %04x, dsize %04x\n", ref->flash_offset &~3, node.i.version, node.i.offset, node.i.dsize)); jffs2_add_tn_to_list(tn, &ret_tn); @@ -242,6 +257,7 @@ int jffs2_get_inode_nodes(struct jffs2_sb_info *c, ino_t ino, struct jffs2_inode } *tnp = ret_tn; *fdp = ret_fd; + return 0; free_out: diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h index 850817ef84b0..bec082a02fc8 100644 --- a/fs/jffs2/nodelist.h +++ b/fs/jffs2/nodelist.h @@ -31,7 +31,7 @@ * provisions above, a recipient may use your version of this file * under either the RHEPL or the GPL. * - * $Id: nodelist.h,v 1.46 2001/09/18 23:43:05 dwmw2 Exp $ + * $Id: nodelist.h,v 1.46.2.1 2002/02/23 14:04:44 dwmw2 Exp $ * */ @@ -248,7 +248,8 @@ void jffs2_add_fd_to_list(struct jffs2_sb_info *c, struct jffs2_full_dirent *new void jffs2_add_tn_to_list(struct jffs2_tmp_dnode_info *tn, struct jffs2_tmp_dnode_info **list); int jffs2_get_inode_nodes(struct jffs2_sb_info *c, ino_t ino, struct jffs2_inode_info *f, struct jffs2_tmp_dnode_info **tnp, struct jffs2_full_dirent **fdp, - __u32 *highest_version); + __u32 *highest_version, __u32 *latest_mctime, + __u32 *mctime_ver); struct jffs2_inode_cache *jffs2_get_ino_cache(struct jffs2_sb_info *c, int ino); void jffs2_add_ino_cache (struct jffs2_sb_info *c, struct jffs2_inode_cache *new); void jffs2_del_ino_cache(struct jffs2_sb_info *c, struct jffs2_inode_cache *old); diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index 1824be09fcd9..d18ee615bca2 100644 --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c @@ -31,7 +31,7 @@ * provisions above, a recipient may use your version of this file * under either the RHEPL or the GPL. * - * $Id: readinode.c,v 1.56 2001/07/26 20:32:39 dwmw2 Exp $ + * $Id: readinode.c,v 1.58.2.2 2002/02/23 14:25:37 dwmw2 Exp $ * */ @@ -173,12 +173,12 @@ int jffs2_add_full_dnode_to_fraglist(struct jffs2_sb_info *c, struct jffs2_node_ jffs2_free_node_frag(newfrag); return -ENOMEM; } - printk(KERN_DEBUG "split old frag 0x%04x-0x%04x -->", this->ofs, this->ofs+this->size); + D1(printk(KERN_DEBUG "split old frag 0x%04x-0x%04x -->", this->ofs, this->ofs+this->size); if (this->node) printk("phys 0x%08x\n", this->node->raw->flash_offset &~3); else printk("hole\n"); - + ) newfrag2->ofs = fn->ofs + fn->size; newfrag2->size = (this->ofs+this->size) - newfrag2->ofs; newfrag2->next = this->next; @@ -251,6 +251,7 @@ void jffs2_read_inode (struct inode *inode) struct jffs2_full_dnode *fn = NULL; struct jffs2_sb_info *c; struct jffs2_raw_inode latest_node; + __u32 latest_mctime, mctime_ver; int ret; ssize_t retlen; @@ -292,7 +293,7 @@ void jffs2_read_inode (struct inode *inode) inode->i_nlink = f->inocache->nlink; /* Grab all nodes relevant to this ino */ - ret = jffs2_get_inode_nodes(c, inode->i_ino, f, &tn_list, &fd_list, &f->highest_version); + ret = jffs2_get_inode_nodes(c, inode->i_ino, f, &tn_list, &fd_list, &f->highest_version, &latest_mctime, &mctime_ver); if (ret) { printk(KERN_CRIT "jffs2_get_inode_nodes() for ino %lu returned %d\n", inode->i_ino, ret); @@ -302,7 +303,7 @@ void jffs2_read_inode (struct inode *inode) f->dents = fd_list; while (tn_list) { - static __u32 mdata_ver = 0; + static __u32 mdata_ver; tn = tn_list; @@ -339,6 +340,7 @@ void jffs2_read_inode (struct inode *inode) printk(KERN_WARNING "jffs2_read_inode(): But it has children so we fake some modes for it\n"); } inode->i_mode = S_IFDIR | S_IRUGO | S_IWUSR | S_IXUGO; + latest_node.version = 0; inode->i_atime = inode->i_ctime = inode->i_mtime = CURRENT_TIME; inode->i_nlink = f->inocache->nlink; inode->i_size = 0; @@ -366,7 +368,7 @@ void jffs2_read_inode (struct inode *inode) inode->i_uid = latest_node.uid; inode->i_gid = latest_node.gid; inode->i_size = latest_node.isize; - if ((inode->i_mode & S_IFMT) == S_IFREG) + if (S_ISREG(inode->i_mode)) jffs2_truncate_fraglist(c, &f->fraglist, latest_node.isize); inode->i_atime = latest_node.atime; inode->i_mtime = latest_node.mtime; @@ -376,9 +378,8 @@ void jffs2_read_inode (struct inode *inode) /* OK, now the special cases. Certain inode types should have only one data node, and it's kept as the metadata node */ - if ((inode->i_mode & S_IFMT) == S_IFBLK || - (inode->i_mode & S_IFMT) == S_IFCHR || - (inode->i_mode & S_IFMT) == S_IFLNK) { + if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode) || + S_ISLNK(inode->i_mode)) { if (f->metadata) { printk(KERN_WARNING "Argh. Special inode #%lu with mode 0%o had metadata node\n", inode->i_ino, inode->i_mode); jffs2_clear_inode(inode); @@ -393,7 +394,8 @@ void jffs2_read_inode (struct inode *inode) } /* ASSERT: f->fraglist != NULL */ if (f->fraglist->next) { - printk(KERN_WARNING "Argh. Special inode #%lu had more than one node\n", inode->i_ino); + printk(KERN_WARNING "Argh. Special inode #%lu with mode 0%o had more than one node\n", inode->i_ino, inode->i_mode); + /* FIXME: Deal with it - check crc32, check for duplicate node, check times and discard the older one */ jffs2_clear_inode(inode); make_bad_inode(inode); return; @@ -412,9 +414,21 @@ void jffs2_read_inode (struct inode *inode) case S_IFLNK: inode->i_op = &jffs2_symlink_inode_operations; + /* Hack to work around broken isize in old symlink code. + Remove this when dwmw2 comes to his senses and stops + symlinks from being an entirely gratuitous special + case. */ + if (!inode->i_size) + inode->i_size = latest_node.dsize; break; case S_IFDIR: + if (mctime_ver > latest_node.version) { + /* The times in the latest_node are actually older than + mctime in the latest dirent. Cheat. */ + inode->i_mtime = inode->i_ctime = inode->i_atime = + latest_mctime; + } inode->i_op = &jffs2_dir_inode_operations; inode->i_fop = &jffs2_dir_operations; break; diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c index d1b870bd59df..f97cc6078040 100644 --- a/fs/jffs2/scan.c +++ b/fs/jffs2/scan.c @@ -31,7 +31,7 @@ * provisions above, a recipient may use your version of this file * under either the RHEPL or the GPL. * - * $Id: scan.c,v 1.51 2001/09/19 00:06:35 dwmw2 Exp $ + * $Id: scan.c,v 1.51.2.2 2002/02/23 13:34:31 dwmw2 Exp $ * */ #include @@ -62,6 +62,9 @@ } \ } while(0) +static uint32_t pseudo_random; +static void jffs2_rotate_lists(struct jffs2_sb_info *c); + static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); /* These helper functions _must_ increase ofs and also do the dirty/used space accounting. @@ -142,6 +145,9 @@ int jffs2_scan_medium(struct jffs2_sb_info *c) c->nr_erasing_blocks++; } } + /* Rotate the lists by some number to ensure wear levelling */ + jffs2_rotate_lists(c); + if (c->nr_erasing_blocks) { if (!c->used_size && empty_blocks != c->nr_blocks) { printk(KERN_NOTICE "Cowardly refusing to erase blocks on filesystem with no valid JFFS2 nodes\n"); @@ -444,6 +450,12 @@ static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_erasebloc *ofs += 4; return 0; } + /* There was a bug where we wrote hole nodes out with csize/dsize + swapped. Deal with it */ + if (ri.compr == JFFS2_COMPR_ZERO && !ri.dsize && ri.csize) { + ri.dsize = ri.csize; + ri.csize = 0; + } if (ri.csize) { /* Check data CRC too */ @@ -474,7 +486,7 @@ static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_erasebloc *ofs, ri.data_crc, crc); DIRTY_SPACE(PAD(ri.totlen)); *ofs += PAD(ri.totlen); - return -0; + return 0; } } @@ -518,6 +530,8 @@ static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_erasebloc D1(printk(KERN_DEBUG "Node is ino #%u, version %d. Range 0x%x-0x%x\n", ri.ino, ri.version, ri.offset, ri.offset+ri.dsize)); + pseudo_random += ri.version; + for (tn_list = &ic->scan->tmpnodes; *tn_list; tn_list = &((*tn_list)->next)) { if ((*tn_list)->version < ri.version) continue; @@ -613,6 +627,8 @@ static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblo return 0; } + pseudo_random += rd.version; + fd = jffs2_alloc_full_dirent(rd.nsize+1); if (!fd) { return -ENOMEM; @@ -686,3 +702,45 @@ static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblo *ofs += PAD(rd.totlen); return 0; } + +static int count_list(struct list_head *l) +{ + uint32_t count = 0; + struct list_head *tmp; + + list_for_each(tmp, l) { + count++; + } + return count; +} + +/* Note: This breaks if list_empty(head). I don't care. You + might, if you copy this code and use it elsewhere :) */ +static void rotate_list(struct list_head *head, uint32_t count) +{ + struct list_head *n = head->next; + + list_del(head); + while(count--) + n = n->next; + list_add(head, n); +} + +static void jffs2_rotate_lists(struct jffs2_sb_info *c) +{ + uint32_t x; + + x = count_list(&c->clean_list); + if (x) + rotate_list((&c->clean_list), pseudo_random % x); + + x = count_list(&c->dirty_list); + if (x) + rotate_list((&c->dirty_list), pseudo_random % x); + + if (c->nr_erasing_blocks) + rotate_list((&c->erase_pending_list), pseudo_random % c->nr_erasing_blocks); + + if (c->nr_free_blocks) /* Not that it should ever be zero */ + rotate_list((&c->free_list), pseudo_random % c->nr_free_blocks); +} diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c index 05f1185aa809..6c491da8d374 100644 --- a/fs/jffs2/super.c +++ b/fs/jffs2/super.c @@ -31,7 +31,7 @@ * provisions above, a recipient may use your version of this file * under either the RHEPL or the GPL. * - * $Id: super.c,v 1.48 2001/10/02 09:16:23 dwmw2 Exp $ + * $Id: super.c,v 1.48.2.1 2002/02/23 14:13:34 dwmw2 Exp $ * */ @@ -214,7 +214,7 @@ static int jffs2_fill_super(struct super_block *sb, void *data, int silent) c->mtd = get_mtd_device(NULL, minor(sb->s_dev)); if (!c->mtd) { - D1(printk(KERN_DEBUG "jffs2: MTD device #%u doesn't appear to exist\n", MINOR(sb->s_dev))); + D1(printk(KERN_DEBUG "jffs2: MTD device #%u doesn't appear to exist\n", minor(sb->s_dev))); return -EINVAL; } c->sector_size = c->mtd->erasesize; @@ -249,10 +249,15 @@ static int jffs2_fill_super(struct super_block *sb, void *data, int silent) INIT_LIST_HEAD(&c->bad_used_list); c->highest_ino = 1; + c->flags |= JFFS2_SB_FLAG_MOUNTING; + if (jffs2_build_filesystem(c)) { D1(printk(KERN_DEBUG "build_fs failed\n")); goto out_nodes; } + + c->flags &= ~JFFS2_SB_FLAG_MOUNTING; + sb->s_op = &jffs2_super_operations; D1(printk(KERN_DEBUG "jffs2_read_super(): Getting root inode\n")); diff --git a/fs/jffs2/symlink.c b/fs/jffs2/symlink.c index c6746ed7c425..e1f7dec49f61 100644 --- a/fs/jffs2/symlink.c +++ b/fs/jffs2/symlink.c @@ -1,7 +1,7 @@ /* * JFFS2 -- Journalling Flash File System, Version 2. * - * Copyright (C) 2001 Red Hat, Inc. + * Copyright (C) 2001, 2002 Red Hat, Inc. * * Created by David Woodhouse * @@ -31,7 +31,7 @@ * provisions above, a recipient may use your version of this file * under either the RHEPL or the GPL. * - * $Id: symlink.c,v 1.5 2001/03/15 15:38:24 dwmw2 Exp $ + * $Id: symlink.c,v 1.5.2.1 2002/01/15 10:39:06 dwmw2 Exp $ * */ @@ -58,16 +58,21 @@ static char *jffs2_getlink(struct dentry *dentry) char *buf; int ret; + down(&f->sem); if (!f->metadata) { + up(&f->sem); printk(KERN_NOTICE "No metadata for symlink inode #%lu\n", dentry->d_inode->i_ino); return ERR_PTR(-EINVAL); } buf = kmalloc(f->metadata->size+1, GFP_USER); - if (!buf) + if (!buf) { + up(&f->sem); return ERR_PTR(-ENOMEM); + } buf[f->metadata->size]=0; ret = jffs2_read_dnode(JFFS2_SB_INFO(dentry->d_inode->i_sb), f->metadata, buf, 0, f->metadata->size); + up(&f->sem); if (ret) { kfree(buf); return ERR_PTR(ret); diff --git a/include/linux/jffs2.h b/include/linux/jffs2.h index 37d3d931e416..9c67732fb12f 100644 --- a/include/linux/jffs2.h +++ b/include/linux/jffs2.h @@ -31,7 +31,7 @@ * provisions above, a recipient may use your version of this file * under either the RHEPL or the GPL. * - * $Id: jffs2.h,v 1.18 2001/03/25 22:36:12 dwmw2 Exp $ + * $Id: jffs2.h,v 1.19 2001/10/09 13:20:23 dwmw2 Exp $ * */ @@ -103,7 +103,7 @@ struct jffs2_unknown_node __u16 nodetype; __u32 totlen; /* So we can skip over nodes we don't grok */ __u32 hdr_crc; -}; +} __attribute__((packed)); struct jffs2_raw_dirent { @@ -121,7 +121,7 @@ struct jffs2_raw_dirent __u32 node_crc; __u32 name_crc; __u8 name[0]; -}; +} __attribute__((packed)); /* The JFFS2 raw inode structure: Used for storage on physical media. */ /* The uid, gid, atime, mtime and ctime members could be longer, but @@ -153,7 +153,7 @@ struct jffs2_raw_inode __u32 data_crc; /* CRC for the (compressed) data. */ __u32 node_crc; /* CRC for the raw inode (excluding data) */ // __u8 data[dsize]; -}; +} __attribute__((packed)); union jffs2_node_union { struct jffs2_raw_inode i; diff --git a/include/linux/jffs2_fs_sb.h b/include/linux/jffs2_fs_sb.h index 2d9ad4e54f5f..626c8c57fb72 100644 --- a/include/linux/jffs2_fs_sb.h +++ b/include/linux/jffs2_fs_sb.h @@ -1,4 +1,4 @@ -/* $Id: jffs2_fs_sb.h,v 1.16 2001/09/18 20:15:18 dwmw2 Exp $ */ +/* $Id: jffs2_fs_sb.h,v 1.16.2.1 2002/02/23 14:13:34 dwmw2 Exp $ */ #ifndef _JFFS2_FS_SB #define _JFFS2_FS_SB @@ -12,6 +12,7 @@ #define INOCACHE_HASHSIZE 1 #define JFFS2_SB_FLAG_RO 1 +#define JFFS2_SB_FLAG_MOUNTING 2 /* A struct for the overall file system control. Pointers to jffs2_sb_info structs are named `c' in the source code. -- cgit v1.2.3 From 29b78b5a5b245ce39d1fdc60b983fea639c98c59 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Tue, 26 Feb 2002 23:15:11 -0800 Subject: This is another USB API cleanup patch. It's against 2.5.5: - Moves 8 functions from usb.[hc] to hcd.[hc] - Also moves some data structures and types - Now usbdevfs and "old" HCDs #include "hcd.h" - Minor tweaks to the "hcd" layer (one less FIXME) - Minor kernel doc and comment cleanups Basically this continues moving the HCD-only functionality out of the way of normal USB device drivers. Converging "usb_bus" and "usb_hcd" (later!) will be a bit easier too. I did basic sanity tests, there's little to break ... :) There are still a few functions in usb.c that aren't for general driver use. They're mostly for enumeration, in areas where the hub driver and HCD root hubs need to do various kinds of magic. It wasn't clear how to decouple those, they can certainly wait. --- drivers/usb/devices.c | 8 +- drivers/usb/hcd.c | 421 ++++++++++++++++++++++++++++++++++++++++++++----- drivers/usb/hcd.h | 85 +++++++++- drivers/usb/usb-ohci.c | 1 + drivers/usb/usb-uhci.c | 1 + drivers/usb/usb.c | 343 +++++----------------------------------- include/linux/usb.h | 58 +------ 7 files changed, 510 insertions(+), 407 deletions(-) (limited to 'include/linux') diff --git a/drivers/usb/devices.c b/drivers/usb/devices.c index 3e8b1d79b270..575a451d80ec 100644 --- a/drivers/usb/devices.c +++ b/drivers/usb/devices.c @@ -4,8 +4,6 @@ * (C) Copyright 1999,2000 Thomas Sailer . (proc file per device) * (C) Copyright 1999 Deti Fliegl (new USB architecture) * - * $id$ - * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -61,6 +59,8 @@ #include #include +#include "hcd.h" + #define MAX_TOPO_LEVEL 6 /* Define ALLOW_SERIAL_NUMBER if you want to see the serial number of devices */ @@ -429,6 +429,10 @@ static ssize_t usb_device_dump(char **buffer, size_t *nbytes, loff_t *skip_bytes * count = device count at this level */ /* If this is the root hub, display the bandwidth information */ + /* FIXME high speed reserves 20% frametime for non-periodic, + * while full/low speed reserves only 10% ... so this is wrong + * for high speed busses. also, change how bandwidth is recorded. + */ if (level == 0) data_end += sprintf(data_end, format_bandwidth, bus->bandwidth_allocated, FRAME_TIME_MAX_USECS_ALLOC, diff --git a/drivers/usb/hcd.c b/drivers/usb/hcd.c index 265143a39d3c..188d38a3e4a0 100644 --- a/drivers/usb/hcd.c +++ b/drivers/usb/hcd.c @@ -1,5 +1,11 @@ /* - * Copyright (c) 2001 by David Brownell + * (C) Copyright Linus Torvalds 1999 + * (C) Copyright Johannes Erdfelt 1999-2001 + * (C) Copyright Andreas Gal 1999 + * (C) Copyright Gregory P. Smith 1999 + * (C) Copyright Deti Fliegl 1999 + * (C) Copyright Randy Dunlap 2000 + * (C) Copyright David Brownell 2000-2002 * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -33,9 +39,6 @@ #include #include /* for UTS_SYSNAME */ -#ifndef CONFIG_USB_DEBUG - #define CONFIG_USB_DEBUG /* this is experimental! */ -#endif #ifdef CONFIG_USB_DEBUG #define DEBUG @@ -53,6 +56,8 @@ #include +// #define USB_BANDWIDTH_MESSAGES + /*-------------------------------------------------------------------------*/ /* @@ -78,19 +83,28 @@ * usb client device drivers. * * Contributors of ideas or unattributed patches include: David Brownell, - * Roman Weissgaerber, Rory Bolt, ... + * Roman Weissgaerber, Rory Bolt, Greg Kroah-Hartman, ... * * HISTORY: + * 2002-02-21 Pull in most of the usb_bus support from usb.c; some + * associated cleanup. "usb_hcd" still != "usb_bus". * 2001-12-12 Initial patch version for Linux 2.5.1 kernel. */ /*-------------------------------------------------------------------------*/ /* host controllers we manage */ -static LIST_HEAD (hcd_list); +LIST_HEAD (usb_bus_list); + +/* used when allocating bus numbers */ +#define USB_MAXBUS 64 +struct usb_busmap { + unsigned long busmap [USB_MAXBUS / (8*sizeof (unsigned long))]; +}; +static struct usb_busmap busmap; /* used when updating list of hcds */ -static DECLARE_MUTEX (hcd_list_lock); +DECLARE_MUTEX (usb_bus_list_lock); /* exported only for usbfs */ /* used when updating hcd data */ static spinlock_t hcd_data_lock = SPIN_LOCK_UNLOCKED; @@ -105,6 +119,9 @@ static struct usb_operations hcd_operations; /*-------------------------------------------------------------------------*/ +#define KERNEL_REL ((LINUX_VERSION_CODE >> 16) & 0x0ff) +#define KERNEL_VER ((LINUX_VERSION_CODE >> 8) & 0x0ff) + /* usb 2.0 root hub device descriptor */ static const u8 usb2_rh_dev_descriptor [18] = { 0x12, /* __u8 bLength; */ @@ -118,7 +135,7 @@ static const u8 usb2_rh_dev_descriptor [18] = { 0x00, 0x00, /* __u16 idVendor; */ 0x00, 0x00, /* __u16 idProduct; */ - 0x40, 0x02, /* __u16 bcdDevice; (v2.4) */ + KERNEL_VER, KERNEL_REL, /* __u16 bcdDevice */ 0x03, /* __u8 iManufacturer; */ 0x02, /* __u8 iProduct; */ @@ -141,7 +158,7 @@ static const u8 usb11_rh_dev_descriptor [18] = { 0x00, 0x00, /* __u16 idVendor; */ 0x00, 0x00, /* __u16 idProduct; */ - 0x40, 0x02, /* __u16 bcdDevice; (v2.4) */ + KERNEL_VER, KERNEL_REL, /* __u16 bcdDevice */ 0x03, /* __u8 iManufacturer; */ 0x02, /* __u8 iProduct; */ @@ -504,6 +521,346 @@ static void rh_status_dequeue (struct usb_hcd *hcd, struct urb *urb) usb_hcd_giveback_urb (hcd, urb); } +/*-------------------------------------------------------------------------*/ + +/* exported only within usbcore */ +void usb_bus_get (struct usb_bus *bus) +{ + atomic_inc (&bus->refcnt); +} + +/* exported only within usbcore */ +void usb_bus_put (struct usb_bus *bus) +{ + if (atomic_dec_and_test (&bus->refcnt)) + kfree (bus); +} + +/*-------------------------------------------------------------------------*/ + +/* shared initialization code */ +static void usb_init_bus (struct usb_bus *bus) +{ + memset (&bus->devmap, 0, sizeof(struct usb_devmap)); + +#ifdef DEVNUM_ROUND_ROBIN + bus->devnum_next = 1; +#endif /* DEVNUM_ROUND_ROBIN */ + + bus->root_hub = NULL; + bus->hcpriv = NULL; + bus->busnum = -1; + bus->bandwidth_allocated = 0; + bus->bandwidth_int_reqs = 0; + bus->bandwidth_isoc_reqs = 0; + + INIT_LIST_HEAD (&bus->bus_list); + + atomic_set (&bus->refcnt, 1); +} + +/** + * usb_alloc_bus - creates a new USB host controller structure + * @op: pointer to a struct usb_operations that this bus structure should use + * Context: !in_interrupt() + * + * Creates a USB host controller bus structure with the specified + * usb_operations and initializes all the necessary internal objects. + * + * If no memory is available, NULL is returned. + * + * The caller should call usb_free_bus() when it is finished with the structure. + */ +struct usb_bus *usb_alloc_bus (struct usb_operations *op) +{ + struct usb_bus *bus; + + bus = kmalloc (sizeof *bus, GFP_KERNEL); + if (!bus) + return NULL; + usb_init_bus (bus); + bus->op = op; + return bus; +} +EXPORT_SYMBOL (usb_alloc_bus); + +/** + * usb_free_bus - frees the memory used by a bus structure + * @bus: pointer to the bus to free + * + * To be invoked by a HCD, only as the last step of decoupling from + * hardware. It is an error to call this if the reference count is + * anything but one. That would indicate that some system component + * did not correctly shut down, and thought the hardware was still + * accessible. + */ +void usb_free_bus (struct usb_bus *bus) +{ + if (!bus) + return; + if (atomic_read (&bus->refcnt) != 1) + err ("usb_free_bus #%d, count != 1", bus->busnum); + usb_bus_put (bus); +} +EXPORT_SYMBOL (usb_free_bus); + +/*-------------------------------------------------------------------------*/ + +/** + * usb_register_bus - registers the USB host controller with the usb core + * @bus: pointer to the bus to register + * Context: !in_interrupt() + * + * Assigns a bus number, and links the controller into usbcore data + * structures so that it can be seen by scanning the bus list. + */ +void usb_register_bus(struct usb_bus *bus) +{ + int busnum; + + down (&usb_bus_list_lock); + busnum = find_next_zero_bit (busmap.busmap, USB_MAXBUS, 1); + if (busnum < USB_MAXBUS) { + set_bit (busnum, busmap.busmap); + bus->busnum = busnum; + } else + warn ("too many buses"); + + usb_bus_get (bus); + + /* Add it to the list of buses */ + list_add (&bus->bus_list, &usb_bus_list); + up (&usb_bus_list_lock); + + usbfs_add_bus (bus); + + info ("new USB bus registered, assigned bus number %d", bus->busnum); +} +EXPORT_SYMBOL (usb_register_bus); + +/** + * usb_deregister_bus - deregisters the USB host controller + * @bus: pointer to the bus to deregister + * Context: !in_interrupt() + * + * Recycles the bus number, and unlinks the controller from usbcore data + * structures so that it won't be seen by scanning the bus list. + */ +void usb_deregister_bus (struct usb_bus *bus) +{ + info ("USB bus %d deregistered", bus->busnum); + + /* + * NOTE: make sure that all the devices are removed by the + * controller code, as well as having it call this when cleaning + * itself up + */ + down (&usb_bus_list_lock); + list_del (&bus->bus_list); + up (&usb_bus_list_lock); + + usbfs_remove_bus (bus); + + clear_bit (bus->busnum, busmap.busmap); + + usb_bus_put (bus); +} +EXPORT_SYMBOL (usb_deregister_bus); + +/** + * usb_register_root_hub - called by HCD to register its root hub + * @usb_dev: the usb root hub device to be registered. + * @parent_dev: the parent device of this root hub. + * + * The USB host controller calls this function to register the root hub + * properly with the USB subsystem. It sets up the device properly in + * the driverfs tree, and then calls usb_new_device() to register the + * usb device. + */ +int usb_register_root_hub (struct usb_device *usb_dev, struct device *parent_dev) +{ + int retval; + + usb_dev->dev.parent = parent_dev; + strcpy (&usb_dev->dev.name[0], "usb_name"); + strcpy (&usb_dev->dev.bus_id[0], "usb_bus"); + retval = usb_new_device (usb_dev); + if (retval) + put_device (&usb_dev->dev); + return retval; +} +EXPORT_SYMBOL (usb_register_root_hub); + + +/*-------------------------------------------------------------------------*/ + +/* + * usb_calc_bus_time: + * Returns approximate bus time in nanoseconds for a periodic transaction. + * See USB 2.0 spec section 5.11.3 + */ +static long usb_calc_bus_time (int speed, int is_input, int isoc, int bytecount) +{ + unsigned long tmp; + + switch (speed) { + case USB_SPEED_LOW: /* INTR only */ + if (is_input) { + tmp = (67667L * (31L + 10L * BitTime (bytecount))) / 1000L; + return (64060L + (2 * BW_HUB_LS_SETUP) + BW_HOST_DELAY + tmp); + } else { + tmp = (66700L * (31L + 10L * BitTime (bytecount))) / 1000L; + return (64107L + (2 * BW_HUB_LS_SETUP) + BW_HOST_DELAY + tmp); + } + case USB_SPEED_FULL: /* ISOC or INTR */ + if (isoc) { + tmp = (8354L * (31L + 10L * BitTime (bytecount))) / 1000L; + return (((is_input) ? 7268L : 6265L) + BW_HOST_DELAY + tmp); + } else { + tmp = (8354L * (31L + 10L * BitTime (bytecount))) / 1000L; + return (9107L + BW_HOST_DELAY + tmp); + } + case USB_SPEED_HIGH: /* ISOC or INTR */ + // FIXME merge from EHCI code; caller will need to handle + // each part of a split separately. + return 0; + default: + dbg ("bogus device speed!"); + return -1; + } +} + +/* + * usb_check_bandwidth(): + * + * old_alloc is from host_controller->bandwidth_allocated in microseconds; + * bustime is from calc_bus_time(), but converted to microseconds. + * + * returns if successful, + * or -ENOSPC if bandwidth request fails. + * + * FIXME: + * This initial implementation does not use Endpoint.bInterval + * in managing bandwidth allocation. + * It probably needs to be expanded to use Endpoint.bInterval. + * This can be done as a later enhancement (correction). + * + * This will also probably require some kind of + * frame allocation tracking...meaning, for example, + * that if multiple drivers request interrupts every 10 USB frames, + * they don't all have to be allocated at + * frame numbers N, N+10, N+20, etc. Some of them could be at + * N+11, N+21, N+31, etc., and others at + * N+12, N+22, N+32, etc. + * + * Similarly for isochronous transfers... + * + * Individual HCDs can schedule more directly ... this logic + * is not correct for high speed transfers. + */ +int usb_check_bandwidth (struct usb_device *dev, struct urb *urb) +{ + unsigned int pipe = urb->pipe; + long bustime; + int is_in = usb_pipein (pipe); + int is_iso = usb_pipeisoc (pipe); + int old_alloc = dev->bus->bandwidth_allocated; + int new_alloc; + + + bustime = NS_TO_US (usb_calc_bus_time (dev->speed, is_in, is_iso, + usb_maxpacket (dev, pipe, !is_in))); + if (is_iso) + bustime /= urb->number_of_packets; + + new_alloc = old_alloc + (int) bustime; + if (new_alloc > FRAME_TIME_MAX_USECS_ALLOC) { +#ifdef DEBUG + char *mode = +#ifdef CONFIG_USB_BANDWIDTH + ""; +#else + "would have "; +#endif + dbg ("usb_check_bandwidth %sFAILED: %d + %ld = %d usec", + mode, old_alloc, bustime, new_alloc); +#endif +#ifdef CONFIG_USB_BANDWIDTH + bustime = -ENOSPC; /* report error */ +#endif + } + + return bustime; +} +EXPORT_SYMBOL (usb_check_bandwidth); + + +/** + * usb_claim_bandwidth - records bandwidth for a periodic transfer + * @dev: source/target of request + * @urb: request (urb->dev == dev) + * @bustime: bandwidth consumed, in (average) microseconds per frame + * @isoc: true iff the request is isochronous + * + * Bus bandwidth reservations are recorded purely for diagnostic purposes. + * HCDs are expected not to overcommit periodic bandwidth, and to record such + * reservations whenever endpoints are added to the periodic schedule. + * + * FIXME averaging per-frame is suboptimal. Better to sum over the HCD's + * entire periodic schedule ... 32 frames for OHCI, 1024 for UHCI, settable + * for EHCI (256/512/1024 frames, default 1024) and have the bus expose how + * large its periodic schedule is. + */ +void usb_claim_bandwidth (struct usb_device *dev, struct urb *urb, int bustime, int isoc) +{ + dev->bus->bandwidth_allocated += bustime; + if (isoc) + dev->bus->bandwidth_isoc_reqs++; + else + dev->bus->bandwidth_int_reqs++; + urb->bandwidth = bustime; + +#ifdef USB_BANDWIDTH_MESSAGES + dbg ("bandwidth alloc increased by %d (%s) to %d for %d requesters", + bustime, + isoc ? "ISOC" : "INTR", + dev->bus->bandwidth_allocated, + dev->bus->bandwidth_int_reqs + dev->bus->bandwidth_isoc_reqs); +#endif +} +EXPORT_SYMBOL (usb_claim_bandwidth); + + +/** + * usb_release_bandwidth - reverses effect of usb_claim_bandwidth() + * @dev: source/target of request + * @urb: request (urb->dev == dev) + * @isoc: true iff the request is isochronous + * + * This records that previously allocated bandwidth has been released. + * Bandwidth is released when endpoints are removed from the host controller's + * periodic schedule. + */ +void usb_release_bandwidth (struct usb_device *dev, struct urb *urb, int isoc) +{ + dev->bus->bandwidth_allocated -= urb->bandwidth; + if (isoc) + dev->bus->bandwidth_isoc_reqs--; + else + dev->bus->bandwidth_int_reqs--; + +#ifdef USB_BANDWIDTH_MESSAGES + dbg ("bandwidth alloc reduced by %d (%s) to %d for %d requesters", + urb->bandwidth, + isoc ? "ISOC" : "INTR", + dev->bus->bandwidth_allocated, + dev->bus->bandwidth_int_reqs + dev->bus->bandwidth_isoc_reqs); +#endif + urb->bandwidth = 0; +} +EXPORT_SYMBOL (usb_release_bandwidth); + + /*-------------------------------------------------------------------------*/ #ifdef CONFIG_PCI @@ -522,6 +879,7 @@ static void hc_died (struct usb_hcd *hcd); * usb_hcd_pci_probe - initialize PCI-based HCDs * @dev: USB Host Controller being probed * @id: pci hotplug id connecting controller to HCD framework + * Context: !in_interrupt() * * Allocates basic PCI resources for this USB host controller, and * then invokes the start() method for the HCD associated with it @@ -535,7 +893,6 @@ int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id) unsigned long resource, len; void *base; u8 latency, limit; - struct usb_bus *bus; struct usb_hcd *hcd; int retval, region; char buf [8], *bufp = buf; @@ -631,7 +988,6 @@ clean_2: != 0) { err ("request interrupt %s failed", bufp); retval = -EBUSY; -clean_3: driver->hcd_free (hcd); goto clean_2; } @@ -643,26 +999,15 @@ clean_3: (driver->flags & HCD_MEMORY) ? "pci mem" : "io base", base); -// FIXME simpler: make "bus" be that data, not pointer to it. - bus = usb_alloc_bus (&hcd_operations); - if (bus == NULL) { - dbg ("usb_alloc_bus fail"); - retval = -ENOMEM; - free_irq (dev->irq, hcd); - goto clean_3; - } - hcd->bus = bus; + usb_init_bus (&hcd->self); + hcd->self.op = &hcd_operations; + hcd->self.hcpriv = (void *) hcd; + hcd->bus = &hcd->self; hcd->bus_name = dev->slot_name; - bus->hcpriv = (void *) hcd; INIT_LIST_HEAD (&hcd->dev_list); - INIT_LIST_HEAD (&hcd->hcd_list); - down (&hcd_list_lock); - list_add (&hcd->hcd_list, &hcd_list); - up (&hcd_list_lock); - - usb_register_bus (bus); + usb_register_bus (&hcd->self); if ((retval = driver->start (hcd)) < 0) usb_hcd_pci_remove (dev); @@ -678,6 +1023,7 @@ EXPORT_SYMBOL (usb_hcd_pci_probe); /** * usb_hcd_pci_remove - shutdown processing for PCI-based HCDs * @dev: USB Host Controller being removed + * Context: !in_interrupt() * * Reverses the effect of usb_hcd_pci_probe(), first invoking * the HCD's stop() method. It is always called from a thread @@ -717,12 +1063,9 @@ void usb_hcd_pci_remove (struct pci_dev *dev) pci_resource_len (dev, hcd->region)); } - down (&hcd_list_lock); - list_del (&hcd->hcd_list); - up (&hcd_list_lock); - usb_deregister_bus (hcd->bus); - usb_free_bus (hcd->bus); + if (atomic_read (&hcd->self.refcnt) != 1) + err ("usb_hcd_pci_remove %s, count != 1", hcd->bus_name); hcd->bus = NULL; hcd->driver->hcd_free (hcd); @@ -1257,6 +1600,7 @@ static void hcd_irq (int irq, void *__hcd, struct pt_regs * r) * usb_hcd_giveback_urb - return URB from HCD to device driver * @hcd: host controller returning the URB * @urb: urb being returned to the USB device driver. + * Context: in_interrupt() * * This hands the URB from HCD to its USB device driver, using its * completion function. The HCD has freed all per-urb resources @@ -1279,16 +1623,9 @@ void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb) struct usb_device *dev; /* Release periodic transfer bandwidth */ - if (urb->bandwidth) { - switch (usb_pipetype (urb->pipe)) { - case PIPE_INTERRUPT: - usb_release_bandwidth (urb->dev, urb, 0); - break; - case PIPE_ISOCHRONOUS: - usb_release_bandwidth (urb->dev, urb, 1); - break; - } - } + if (urb->bandwidth) + usb_release_bandwidth (urb->dev, urb, + usb_pipeisoc (urb->pipe)); /* clear all state linking urb to this dev (and hcd) */ diff --git a/drivers/usb/hcd.h b/drivers/usb/hcd.h index 37ef85bd92aa..19698b04a6eb 100644 --- a/drivers/usb/hcd.h +++ b/drivers/usb/hcd.h @@ -1,6 +1,6 @@ /* - * Copyright (c) 2001 by David Brownell - * + * Copyright (c) 2001-2002 by David Brownell + * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your @@ -17,6 +17,8 @@ */ +#ifdef __KERNEL__ + /*-------------------------------------------------------------------------*/ /* @@ -33,8 +35,8 @@ struct usb_hcd { /* usb_bus.hcpriv points to this */ /* * housekeeping */ - struct usb_bus *bus; /* hcd is-a bus */ - struct list_head hcd_list; + struct usb_bus *bus; /* FIXME only use "self" */ + struct usb_bus self; /* hcd is-a bus */ const char *bus_name; @@ -98,6 +100,19 @@ struct hcd_timeout { /* timeouts we allocate */ /*-------------------------------------------------------------------------*/ +/* + * FIXME usb_operations should vanish or become hc_driver, + * when usb_bus and usb_hcd become the same thing. + */ + +struct usb_operations { + int (*allocate)(struct usb_device *); + int (*deallocate)(struct usb_device *); + int (*get_frame_number) (struct usb_device *usb_dev); + int (*submit_urb) (struct urb *urb, int mem_flags); + int (*unlink_urb) (struct urb *urb); +}; + /* each driver provides one of these, and hardware init support */ struct hc_driver { @@ -126,8 +141,6 @@ struct hc_driver { /* return current frame number */ int (*get_frame_number) (struct usb_hcd *hcd); -// FIXME: rework generic-to-specific HCD linkage (specific contains generic) - /* memory lifecycle */ struct usb_hcd *(*hcd_alloc) (void); void (*hcd_free) (struct usb_hcd *hcd); @@ -152,7 +165,8 @@ struct hc_driver { extern void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb); #ifdef CONFIG_PCI - +struct pci_dev; +struct pci_device_id; extern int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id); extern void usb_hcd_pci_remove (struct pci_dev *dev); @@ -204,6 +218,59 @@ extern int usb_hcd_pci_resume (struct pci_dev *dev); #define SetPortFeature (0x2300 | USB_REQ_SET_FEATURE) +/*-------------------------------------------------------------------------*/ + +/* + * Generic bandwidth allocation constants/support + */ +#define FRAME_TIME_USECS 1000L +#define BitTime(bytecount) (7 * 8 * bytecount / 6) /* with integer truncation */ + /* Trying not to use worst-case bit-stuffing + of (7/6 * 8 * bytecount) = 9.33 * bytecount */ + /* bytecount = data payload byte count */ + +#define NS_TO_US(ns) ((ns + 500L) / 1000L) + /* convert & round nanoseconds to microseconds */ + +extern void usb_claim_bandwidth (struct usb_device *dev, struct urb *urb, + int bustime, int isoc); +extern void usb_release_bandwidth (struct usb_device *dev, struct urb *urb, + int isoc); + +/* + * Full/low speed bandwidth allocation constants/support. + */ +#define BW_HOST_DELAY 1000L /* nanoseconds */ +#define BW_HUB_LS_SETUP 333L /* nanoseconds */ + /* 4 full-speed bit times (est.) */ + +#define FRAME_TIME_BITS 12000L /* frame = 1 millisecond */ +#define FRAME_TIME_MAX_BITS_ALLOC (90L * FRAME_TIME_BITS / 100L) +#define FRAME_TIME_MAX_USECS_ALLOC (90L * FRAME_TIME_USECS / 100L) + +extern int usb_check_bandwidth (struct usb_device *dev, struct urb *urb); + +/*-------------------------------------------------------------------------*/ + +extern struct usb_bus *usb_alloc_bus (struct usb_operations *); +extern void usb_free_bus (struct usb_bus *); + +extern void usb_register_bus (struct usb_bus *); +extern void usb_deregister_bus (struct usb_bus *); + +extern int usb_register_root_hub (struct usb_device *usb_dev, + struct device *parent_dev); + +/*-------------------------------------------------------------------------*/ + +/* exported only within usbcore */ + +extern struct list_head usb_bus_list; +extern struct semaphore usb_bus_list_lock; + +extern void usb_bus_get (struct usb_bus *bus); +extern void usb_bus_put (struct usb_bus *bus); + /*-------------------------------------------------------------------------*/ /* hub.h ... DeviceRemovable in 2.4.2-ac11, gone in 2.4.10 */ @@ -217,3 +284,7 @@ extern int usb_hcd_pci_resume (struct pci_dev *dev); #define RUN_CONTEXT (in_irq () ? "in_irq" \ : (in_interrupt () ? "in_interrupt" : "can sleep")) + + +#endif /* __KERNEL__ */ + diff --git a/drivers/usb/usb-ohci.c b/drivers/usb/usb-ohci.c index 32a17a937c70..1359625c81cf 100644 --- a/drivers/usb/usb-ohci.c +++ b/drivers/usb/usb-ohci.c @@ -73,6 +73,7 @@ #define OHCI_USE_NPS // force NoPowerSwitching mode // #define OHCI_VERBOSE_DEBUG /* not always helpful */ +#include "hcd.h" #include "usb-ohci.h" diff --git a/drivers/usb/usb-uhci.c b/drivers/usb/usb-uhci.c index 00346153dbab..98fbc9980e8e 100644 --- a/drivers/usb/usb-uhci.c +++ b/drivers/usb/usb-uhci.c @@ -57,6 +57,7 @@ #define VERSTR "$Revision: 1.275 $ time " __TIME__ " " __DATE__ #include +#include "hcd.h" #include "usb-uhci.h" #include "usb-uhci-debug.h" diff --git a/drivers/usb/usb.c b/drivers/usb/usb.c index 70ec3c5492d3..c61c0ea55b41 100644 --- a/drivers/usb/usb.c +++ b/drivers/usb/usb.c @@ -40,12 +40,7 @@ #endif #include -static const int usb_bandwidth_option = -#ifdef CONFIG_USB_BANDWIDTH - 1; -#else - 0; -#endif +#include "hcd.h" extern int usb_hub_init(void); extern void usb_hub_cleanup(void); @@ -61,13 +56,9 @@ static void usb_check_support(struct usb_device *); * We have a per-interface "registered driver" list. */ LIST_HEAD(usb_driver_list); -LIST_HEAD(usb_bus_list); -struct semaphore usb_bus_list_lock; devfs_handle_t usb_devfs_handle; /* /dev/usb dir. */ -static struct usb_busmap busmap; - static struct usb_driver *usb_minors[16]; /** @@ -105,6 +96,7 @@ int usb_register(struct usb_driver *new_driver) /** * usb_scan_devices - scans all unclaimed USB interfaces + * Context: !in_interrupt () * * Goes through all unclaimed USB interfaces, and offers them to all * registered USB drivers through the 'probe' function. @@ -173,6 +165,7 @@ static void usb_drivers_purge(struct usb_driver *driver,struct usb_device *dev) /** * usb_deregister - unregister a USB driver * @driver: USB operations of the driver to unregister + * Context: !in_interrupt () * * Unlinks the specified driver from the internal USB driver list. */ @@ -257,259 +250,6 @@ struct usb_endpoint_descriptor *usb_epnum_to_ep_desc(struct usb_device *dev, uns return NULL; } -/* - * usb_calc_bus_time: - * - * returns (approximate) USB bus time in nanoseconds for a USB transaction. - */ -static long usb_calc_bus_time (int low_speed, int input_dir, int isoc, int bytecount) -{ - unsigned long tmp; - - if (low_speed) /* no isoc. here */ - { - if (input_dir) - { - tmp = (67667L * (31L + 10L * BitTime (bytecount))) / 1000L; - return (64060L + (2 * BW_HUB_LS_SETUP) + BW_HOST_DELAY + tmp); - } - else - { - tmp = (66700L * (31L + 10L * BitTime (bytecount))) / 1000L; - return (64107L + (2 * BW_HUB_LS_SETUP) + BW_HOST_DELAY + tmp); - } - } - - /* for full-speed: */ - - if (!isoc) /* Input or Output */ - { - tmp = (8354L * (31L + 10L * BitTime (bytecount))) / 1000L; - return (9107L + BW_HOST_DELAY + tmp); - } /* end not Isoc */ - - /* for isoc: */ - - tmp = (8354L * (31L + 10L * BitTime (bytecount))) / 1000L; - return (((input_dir) ? 7268L : 6265L) + BW_HOST_DELAY + tmp); -} - -/* - * usb_check_bandwidth(): - * - * old_alloc is from host_controller->bandwidth_allocated in microseconds; - * bustime is from calc_bus_time(), but converted to microseconds. - * - * returns if successful, - * or -ENOSPC if bandwidth request fails. - * - * FIXME: - * This initial implementation does not use Endpoint.bInterval - * in managing bandwidth allocation. - * It probably needs to be expanded to use Endpoint.bInterval. - * This can be done as a later enhancement (correction). - * This will also probably require some kind of - * frame allocation tracking...meaning, for example, - * that if multiple drivers request interrupts every 10 USB frames, - * they don't all have to be allocated at - * frame numbers N, N+10, N+20, etc. Some of them could be at - * N+11, N+21, N+31, etc., and others at - * N+12, N+22, N+32, etc. - * However, this first cut at USB bandwidth allocation does not - * contain any frame allocation tracking. - */ -int usb_check_bandwidth (struct usb_device *dev, struct urb *urb) -{ - int new_alloc; - int old_alloc = dev->bus->bandwidth_allocated; - unsigned int pipe = urb->pipe; - long bustime; - - bustime = usb_calc_bus_time (dev->speed == USB_SPEED_LOW, - usb_pipein(pipe), usb_pipeisoc(pipe), - usb_maxpacket(dev, pipe, usb_pipeout(pipe))); - if (usb_pipeisoc(pipe)) - bustime = NS_TO_US(bustime) / urb->number_of_packets; - else - bustime = NS_TO_US(bustime); - - new_alloc = old_alloc + (int)bustime; - /* what new total allocated bus time would be */ - - if (new_alloc > FRAME_TIME_MAX_USECS_ALLOC) - dbg("usb-check-bandwidth %sFAILED: was %u, would be %u, bustime = %ld us", - usb_bandwidth_option ? "" : "would have ", - old_alloc, new_alloc, bustime); - - if (!usb_bandwidth_option) /* don't enforce it */ - return (bustime); - return (new_alloc <= FRAME_TIME_MAX_USECS_ALLOC) ? bustime : -ENOSPC; -} - -void usb_claim_bandwidth (struct usb_device *dev, struct urb *urb, int bustime, int isoc) -{ - dev->bus->bandwidth_allocated += bustime; - if (isoc) - dev->bus->bandwidth_isoc_reqs++; - else - dev->bus->bandwidth_int_reqs++; - urb->bandwidth = bustime; - -#ifdef USB_BANDWIDTH_MESSAGES - dbg("bandwidth alloc increased by %d to %d for %d requesters", - bustime, - dev->bus->bandwidth_allocated, - dev->bus->bandwidth_int_reqs + dev->bus->bandwidth_isoc_reqs); -#endif -} - -/* - * usb_release_bandwidth(): - * - * called to release a pipe's bandwidth (in microseconds) - */ -void usb_release_bandwidth(struct usb_device *dev, struct urb *urb, int isoc) -{ - dev->bus->bandwidth_allocated -= urb->bandwidth; - if (isoc) - dev->bus->bandwidth_isoc_reqs--; - else - dev->bus->bandwidth_int_reqs--; - -#ifdef USB_BANDWIDTH_MESSAGES - dbg("bandwidth alloc reduced by %d to %d for %d requesters", - urb->bandwidth, - dev->bus->bandwidth_allocated, - dev->bus->bandwidth_int_reqs + dev->bus->bandwidth_isoc_reqs); -#endif - urb->bandwidth = 0; -} - -static void usb_bus_get(struct usb_bus *bus) -{ - atomic_inc(&bus->refcnt); -} - -static void usb_bus_put(struct usb_bus *bus) -{ - if (atomic_dec_and_test(&bus->refcnt)) - kfree(bus); -} - -/** - * usb_alloc_bus - creates a new USB host controller structure (usbcore-internal) - * @op: pointer to a struct usb_operations that this bus structure should use - * - * Creates a USB host controller bus structure with the specified - * usb_operations and initializes all the necessary internal objects. - * (For use only by USB Host Controller Drivers.) - * - * If no memory is available, NULL is returned. - * - * The caller should call usb_free_bus() when it is finished with the structure. - */ -struct usb_bus *usb_alloc_bus(struct usb_operations *op) -{ - struct usb_bus *bus; - - bus = kmalloc(sizeof(*bus), GFP_KERNEL); - if (!bus) - return NULL; - - memset(&bus->devmap, 0, sizeof(struct usb_devmap)); - -#ifdef DEVNUM_ROUND_ROBIN - bus->devnum_next = 1; -#endif /* DEVNUM_ROUND_ROBIN */ - - bus->op = op; - bus->root_hub = NULL; - bus->hcpriv = NULL; - bus->busnum = -1; - bus->bandwidth_allocated = 0; - bus->bandwidth_int_reqs = 0; - bus->bandwidth_isoc_reqs = 0; - - INIT_LIST_HEAD(&bus->bus_list); - - atomic_set(&bus->refcnt, 1); - - return bus; -} - -/** - * usb_free_bus - frees the memory used by a bus structure (usbcore-internal) - * @bus: pointer to the bus to free - * - * (For use only by USB Host Controller Drivers.) - */ -void usb_free_bus(struct usb_bus *bus) -{ - if (!bus) - return; - - usb_bus_put(bus); -} - -/** - * usb_register_bus - registers the USB host controller with the usb core (usbcore-internal) - * @bus: pointer to the bus to register - * - * (For use only by USB Host Controller Drivers.) - * - * This call is synchronous, and may not be used in an interrupt context. - */ -void usb_register_bus(struct usb_bus *bus) -{ - int busnum; - - down (&usb_bus_list_lock); - busnum = find_next_zero_bit(busmap.busmap, USB_MAXBUS, 1); - if (busnum < USB_MAXBUS) { - set_bit(busnum, busmap.busmap); - bus->busnum = busnum; - } else - warn("too many buses"); - - usb_bus_get(bus); - - /* Add it to the list of buses */ - list_add(&bus->bus_list, &usb_bus_list); - up (&usb_bus_list_lock); - - usbfs_add_bus(bus); - - info("new USB bus registered, assigned bus number %d", bus->busnum); -} - -/** - * usb_deregister_bus - deregisters the USB host controller (usbcore-internal) - * @bus: pointer to the bus to deregister - * - * (For use only by USB Host Controller Drivers.) - * - * This call is synchronous, and may not be used in an interrupt context. - */ -void usb_deregister_bus(struct usb_bus *bus) -{ - info("USB bus %d deregistered", bus->busnum); - - /* - * NOTE: make sure that all the devices are removed by the - * controller code, as well as having it call this when cleaning - * itself up - */ - down (&usb_bus_list_lock); - list_del(&bus->bus_list); - up (&usb_bus_list_lock); - - usbfs_remove_bus(bus); - - clear_bit(bus->busnum, busmap.busmap); - - usb_bus_put(bus); -} - /* * This function is for doing a depth-first search for devices which * have support, for dynamic loading of driver modules. @@ -1016,6 +756,7 @@ static void usb_find_drivers(struct usb_device *dev) * usb_alloc_dev - allocate a usb device structure (usbcore-internal) * @parent: hub to which device is connected * @bus: bus used to access the device + * Context: !in_interrupt () * * Only hub drivers (including virtual root hub drivers for host * controllers) should ever call this. @@ -1078,14 +819,12 @@ void usb_inc_dev_use(struct usb_device *dev) atomic_inc(&dev->refcnt); } -/* ---------------------------------------------------------------------- - * New USB Core Functions - * ----------------------------------------------------------------------*/ /** * usb_alloc_urb - creates a new urb for a USB driver to use * @iso_packets: number of iso packets for this urb - * @mem_flags: the type of memory to allocate, see kmalloc() for a list of valid options for this. + * @mem_flags: the type of memory to allocate, see kmalloc() for a list of + * valid options for this. * * Creates an urb for the USB driver to use, initializes a few internal * structures, incrementes the usage counter, and returns a pointer to it. @@ -1129,8 +868,10 @@ struct urb *usb_alloc_urb(int iso_packets, int mem_flags) void usb_free_urb(struct urb *urb) { if (urb) - if (atomic_dec_and_test(&urb->count)) + if (atomic_dec_and_test(&urb->count)) { + info ("really freeing urb"); kfree(urb); + } } /** @@ -1158,7 +899,8 @@ struct urb * usb_get_urb(struct urb *urb) /** * usb_submit_urb - asynchronously issue a transfer request for an endpoint * @urb: pointer to the urb describing the request - * @mem_flags: the type of memory to allocate, see kmalloc() for a list of valid options for this. + * @mem_flags: the type of memory to allocate, see kmalloc() for a list + * of valid options for this. * * This submits a transfer request, and transfers control of the URB * describing that request to the USB subsystem. Request completion will @@ -1393,7 +1135,9 @@ int usb_internal_control_msg(struct usb_device *usb_dev, unsigned int pipe, * @index: USB message index value * @data: pointer to the data to send * @size: length in bytes of the data to send - * @timeout: time to wait for the message to complete before timing out (if 0 the wait is forever) + * @timeout: time in jiffies to wait for the message to complete before + * timing out (if 0 the wait is forever) + * Context: !in_interrupt () * * This function sends a simple control message to a specified endpoint * and waits for the message to complete, or timeout. @@ -1401,7 +1145,7 @@ int usb_internal_control_msg(struct usb_device *usb_dev, unsigned int pipe, * If successful, it returns 0, otherwise a negative error number. * * Don't use this function from within an interrupt context, like a - * bottom half handler. If you need a asyncronous message, or need to send + * bottom half handler. If you need an asynchronous message, or need to send * a message from within interrupt context, use usb_submit_urb() */ int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype, @@ -1436,7 +1180,9 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u * @data: pointer to the data to send * @len: length in bytes of the data to send * @actual_length: pointer to a location to put the actual length transferred in bytes - * @timeout: time to wait for the message to complete before timing out (if 0 the wait is forever) + * @timeout: time in jiffies to wait for the message to complete before + * timing out (if 0 the wait is forever) + * Context: !in_interrupt () * * This function sends a simple bulk message to a specified endpoint * and waits for the message to complete, or timeout. @@ -1446,7 +1192,7 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u * actual_length paramater. * * Don't use this function from within an interrupt context, like a - * bottom half handler. If you need a asyncronous message, or need to + * bottom half handler. If you need an asynchronous message, or need to * send a message from within interrupt context, use usb_submit_urb() */ int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, @@ -1474,6 +1220,11 @@ int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, * Returns the current frame number for the USB host controller * used with the given USB device. This can be used when scheduling * isochronous requests. + * + * Note that different kinds of host controller have different + * "scheduling horizons". While one type might support scheduling only + * 32 frames into the future, others could support scheduling up to + * 1024 frames into the future. */ int usb_get_current_frame_number(struct usb_device *dev) { @@ -1946,6 +1697,7 @@ int __usb_get_extra_descriptor(char *buffer, unsigned size, unsigned char type, /** * usb_disconnect - disconnect a device (usbcore-internal) * @pdev: pointer to device being disconnected + * Context: !in_interrupt () * * Something got disconnected. Get rid of it, and all of its children. * @@ -2069,6 +1821,7 @@ int usb_set_address(struct usb_device *dev) * @index: the number of the descriptor * @buf: where to put the descriptor * @size: how big is "buf"? + * Context: !in_interrupt () * * Gets a USB descriptor. Convenience functions exist to simplify * getting some types of descriptors. Use @@ -2110,6 +1863,7 @@ int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char * @index: the number of the descriptor * @buf: where to put the string * @size: how big is "buf"? + * Context: !in_interrupt () * * Retrieves a string, encoded using UTF-16LE (Unicode, 16 bits per character, * in little-endian byte order). @@ -2135,6 +1889,7 @@ int usb_get_string(struct usb_device *dev, unsigned short langid, unsigned char /** * usb_get_device_descriptor - (re)reads the device descriptor * @dev: the device whose device descriptor is being updated + * Context: !in_interrupt () * * Updates the copy of the device descriptor stored in the device structure, * which dedicates space for this purpose. Note that several fields are @@ -2169,6 +1924,7 @@ int usb_get_device_descriptor(struct usb_device *dev) * @type: USB_RECIP_*; for device, interface, or endpoint * @target: zero (for device), else interface or endpoint number * @data: pointer to two bytes of bitmap data + * Context: !in_interrupt () * * Returns device, interface, or endpoint status. Normally only of * interest to see if the device is self powered, or has enabled the @@ -2227,6 +1983,7 @@ void usb_set_maxpacket(struct usb_device *dev) * usb_clear_halt - tells device to clear endpoint halt/stall condition * @dev: device whose endpoint is halted * @pipe: endpoint "pipe" being cleared + * Context: !in_interrupt () * * This is used to clear halt conditions for bulk and interrupt endpoints, * as reported by URB completion status. Endpoints that are halted are @@ -2298,6 +2055,7 @@ int usb_clear_halt(struct usb_device *dev, int pipe) * @dev: the device whose interface is being updated * @interface: the interface being updated * @alternate: the setting being chosen. + * Context: !in_interrupt () * * This is used to enable data transfers on interfaces that may not * be enabled by default. Not all devices support such configurability. @@ -2378,6 +2136,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate) * usb_set_configuration - Makes a particular device setting be current * @dev: the device whose configuration is being updated * @configuration: the configuration being chosen. + * Context: !in_interrupt () * * This is used to enable non-default device modes. Not all devices * support this kind of configurability. By default, configuration @@ -2540,6 +2299,7 @@ err: * @index: the number of the descriptor * @buf: where to put the string * @size: how big is "buf"? + * Context: !in_interrupt () * * This converts the UTF-16LE encoded strings returned by devices, from * usb_get_string_descriptor(), to null-terminated ISO-8859-1 encoded ones @@ -2619,8 +2379,11 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size) * @dev: the device whose path is being constructed * @buf: where to put the string * @size: how big is "buf"? + * Context: !in_interrupt () * * Returns length of the string (>= 0) or out of memory status (< 0). + * + * NOTE: prefer to use use dev->devpath directly. */ int usb_make_path(struct usb_device *dev, char *buf, size_t size) { @@ -2768,29 +2531,6 @@ int usb_new_device(struct usb_device *dev) return 0; } -/** - * usb_register_root_hub - called by a usb host controller to register the root hub device in the system - * @usb_dev: the usb root hub device to be registered. - * @parent_dev: the parent device of this root hub. - * - * The USB host controller calls this function to register the root hub - * properly with the USB subsystem. It sets up the device properly in - * the driverfs tree, and then calls usb_new_device() to register the - * usb device. - */ -int usb_register_root_hub (struct usb_device *usb_dev, struct device *parent_dev) -{ - int retval; - - usb_dev->dev.parent = parent_dev; - strcpy (&usb_dev->dev.name[0], "usb_name"); - strcpy (&usb_dev->dev.bus_id[0], "usb_bus"); - retval = usb_new_device (usb_dev); - if (retval) - put_device (&usb_dev->dev); - return retval; -} - static int usb_open(struct inode * inode, struct file * file) { int minor = minor(inode->i_rdev); @@ -2859,7 +2599,6 @@ struct list_head *usb_bus_get_list(void) */ static int __init usb_init(void) { - init_MUTEX(&usb_bus_list_lock); usb_major_init(); usbfs_init(); usb_hub_init(); @@ -2892,11 +2631,7 @@ EXPORT_SYMBOL(usb_epnum_to_ep_desc); EXPORT_SYMBOL(usb_register); EXPORT_SYMBOL(usb_deregister); EXPORT_SYMBOL(usb_scan_devices); -EXPORT_SYMBOL(usb_alloc_bus); -EXPORT_SYMBOL(usb_free_bus); -EXPORT_SYMBOL(usb_register_bus); -EXPORT_SYMBOL(usb_deregister_bus); -EXPORT_SYMBOL(usb_register_root_hub); + EXPORT_SYMBOL(usb_alloc_dev); EXPORT_SYMBOL(usb_free_dev); EXPORT_SYMBOL(usb_inc_dev_use); @@ -2912,10 +2647,6 @@ EXPORT_SYMBOL(usb_reset_device); EXPORT_SYMBOL(usb_connect); EXPORT_SYMBOL(usb_disconnect); -EXPORT_SYMBOL(usb_check_bandwidth); -EXPORT_SYMBOL(usb_claim_bandwidth); -EXPORT_SYMBOL(usb_release_bandwidth); - EXPORT_SYMBOL(__usb_get_extra_descriptor); EXPORT_SYMBOL(usb_get_current_frame_number); diff --git a/include/linux/usb.h b/include/linux/usb.h index 583af126199b..391668010831 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -44,8 +44,8 @@ /* * USB directions */ -#define USB_DIR_OUT 0 -#define USB_DIR_IN 0x80 +#define USB_DIR_OUT 0 /* to device */ +#define USB_DIR_IN 0x80 /* to host */ /* * Endpoints @@ -148,12 +148,6 @@ struct usb_devmap { unsigned long devicemap[128 / (8*sizeof(unsigned long))]; }; -#define USB_MAXBUS 64 - -struct usb_busmap { - unsigned long busmap[USB_MAXBUS / (8*sizeof(unsigned long))]; -}; - struct usb_device; /*-------------------------------------------------------------------------*/ @@ -516,7 +510,8 @@ struct usb_device_id { * work to connect to a device should be done when the device is opened, * and undone at the last close. The disconnect code needs to address * concurrency issues with respect to open() and close() methods, as - * well as cancel any I/O requests that are still pending. + * well as forcing all pending I/O requests to complete (by unlinking + * them as necessary, and blocking until the unlinks complete). */ struct usb_driver { struct module *owner; @@ -905,13 +900,7 @@ extern int usb_make_path(struct usb_device *dev, char *buf, size_t size); /* Host Controller Driver (HCD) support */ -struct usb_operations { - int (*allocate)(struct usb_device *); - int (*deallocate)(struct usb_device *); - int (*get_frame_number) (struct usb_device *usb_dev); - int (*submit_urb) (struct urb *urb, int mem_flags); - int (*unlink_urb) (struct urb *urb); -}; +struct usb_operations; #define DEVNUM_ROUND_ROBIN /***** OPTION *****/ @@ -944,40 +933,11 @@ struct usb_bus { atomic_t refcnt; }; -extern struct usb_bus *usb_alloc_bus(struct usb_operations *); -extern void usb_free_bus(struct usb_bus *); -extern void usb_register_bus(struct usb_bus *); -extern void usb_deregister_bus(struct usb_bus *); -extern int usb_register_root_hub(struct usb_device *usb_dev, struct device *parent_dev); - -extern int usb_check_bandwidth (struct usb_device *dev, struct urb *urb); -extern void usb_claim_bandwidth (struct usb_device *dev, struct urb *urb, - int bustime, int isoc); -extern void usb_release_bandwidth(struct usb_device *dev, struct urb *urb, - int isoc); +// FIXME: root_hub_string vanishes when "usb_hcd" conversion is done, +// along with pre-hcd versions of the OHCI and UHCI drivers. extern int usb_root_hub_string(int id, int serial, char *type, __u8 *data, int len); -/* - * Some USB 1.1 bandwidth allocation constants. - */ -#define BW_HOST_DELAY 1000L /* nanoseconds */ -#define BW_HUB_LS_SETUP 333L /* nanoseconds */ - /* 4 full-speed bit times (est.) */ - -#define FRAME_TIME_BITS 12000L /* frame = 1 millisecond */ -#define FRAME_TIME_MAX_BITS_ALLOC (90L * FRAME_TIME_BITS / 100L) -#define FRAME_TIME_USECS 1000L -#define FRAME_TIME_MAX_USECS_ALLOC (90L * FRAME_TIME_USECS / 100L) - -#define BitTime(bytecount) (7 * 8 * bytecount / 6) /* with integer truncation */ - /* Trying not to use worst-case bit-stuffing - of (7/6 * 8 * bytecount) = 9.33 * bytecount */ - /* bytecount = data payload byte count */ - -#define NS_TO_US(ns) ((ns + 500L) / 1000L) - /* convert & round nanoseconds to microseconds */ - /* * As of USB 2.0, full/low speed devices are segregated into trees. * One type grows from USB 1.1 host controllers (OHCI, UHCI etc). @@ -1209,13 +1169,11 @@ void usb_show_string(struct usb_device *dev, char *id, int index); /* -------------------------------------------------------------------------- */ /* - * bus and driver list + * driver list * exported only for usbfs (not visible outside usbcore) */ extern struct list_head usb_driver_list; -extern struct list_head usb_bus_list; -extern struct semaphore usb_bus_list_lock; /* * USB device fs stuff -- cgit v1.2.3 From f0a86f5a3cdfaff7153c542ead1174eb6d06c97a Mon Sep 17 00:00:00 2001 From: Martin Dalecki Date: Wed, 27 Feb 2002 20:15:12 -0800 Subject: [PATCH] 2.5.6-pre1 IDE cleanup 10 This is finishing the cleanup parts already started in ide-clean-9. It kills the ide_register_module() and ide_unregister_module() as well as associated idiosyncracies alltogether. It turns out that this patch is actually fixing a bug which was present in the driver before: the sub-module initialization functions where called at least twice - which is an abundance. Tough there is a bit of global namespace pollution caused by this patch - but I'm aware of it and will fix it just a bit later. (The terminology used inside the IDE code is anyway nothing common else in the linux universum...) The next targets will be: 1. Code obfuscation by "wrappers" around generic BIO level functions. 2. ide_hwgroup_t - which is only used to serialize multiple discs on the same interrupt and similar. This is however a tough one. 3. There is a plenty of code waste in the chipset drivers, where there is baroque informative code for the proc file system for static stuff, which in fact belongs just to syslog(). In fact the default RedHat distribution kernel is killing this gratitious abuse of the /proc concept since a long long time... I'm still awaiting the day of /proc/GPL, where GPL contains the full text of it... --- drivers/ide/ide-cd.c | 7 ++----- drivers/ide/ide-disk.c | 7 ++----- drivers/ide/ide-floppy.c | 7 ++----- drivers/ide/ide-proc.c | 17 ----------------- drivers/ide/ide-tape.c | 11 ++++------- drivers/ide/ide.c | 41 ++++++----------------------------------- drivers/scsi/ide-scsi.c | 7 ++----- include/linux/ide.h | 9 +-------- 8 files changed, 19 insertions(+), 87 deletions(-) (limited to 'include/linux') diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index a28197661bbc..07f6f767b166 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -2906,7 +2906,6 @@ int ide_cdrom_cleanup(ide_drive_t *drive) return 0; } -int ide_cdrom_init(void); int ide_cdrom_reinit (ide_drive_t *drive); static ide_driver_t ide_cdrom_driver = { @@ -2929,7 +2928,6 @@ static ide_driver_t ide_cdrom_driver = { capacity: ide_cdrom_capacity, special: NULL, proc: NULL, - driver_init: ide_cdrom_init, driver_reinit: ide_cdrom_reinit, }; @@ -2967,7 +2965,7 @@ int ide_cdrom_reinit (ide_drive_t *drive) DRIVER(drive)->busy--; failed--; - ide_register_module(&ide_cdrom_driver); + revalidate_drives(); MOD_DEC_USE_COUNT; return 0; } @@ -2982,7 +2980,6 @@ static void __exit ide_cdrom_exit(void) printk ("%s: cleanup_module() called while still busy\n", drive->name); failed++; } - ide_unregister_module (&ide_cdrom_driver); } int ide_cdrom_init(void) @@ -3026,7 +3023,7 @@ int ide_cdrom_init(void) DRIVER(drive)->busy--; failed--; } - ide_register_module(&ide_cdrom_driver); + revalidate_drives(); MOD_DEC_USE_COUNT; return 0; } diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index 294eb39427f0..43d9b957f429 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -1030,7 +1030,6 @@ static int idedisk_cleanup (ide_drive_t *drive) return ide_unregister_subdriver(drive); } -int idedisk_init (void); int idedisk_reinit(ide_drive_t *drive); /* @@ -1056,7 +1055,6 @@ static ide_driver_t idedisk_driver = { capacity: idedisk_capacity, special: idedisk_special, proc: idedisk_proc, - driver_init: idedisk_init, driver_reinit: idedisk_reinit, }; @@ -1083,7 +1081,7 @@ int idedisk_reinit (ide_drive_t *drive) DRIVER(drive)->busy--; failed--; - ide_register_module(&idedisk_driver); + revalidate_drives(); MOD_DEC_USE_COUNT; return 0; } @@ -1105,7 +1103,6 @@ static void __exit idedisk_exit (void) ide_remove_proc_entries(drive->proc, idedisk_proc); #endif } - ide_unregister_module(&idedisk_driver); } int idedisk_init (void) @@ -1130,7 +1127,7 @@ int idedisk_init (void) DRIVER(drive)->busy--; failed--; } - ide_register_module(&idedisk_driver); + revalidate_drives(); MOD_DEC_USE_COUNT; return 0; } diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index 9ea480ebb33a..2ded4cb94373 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -2046,7 +2046,6 @@ static ide_proc_entry_t idefloppy_proc[] = { #endif /* CONFIG_PROC_FS */ -int idefloppy_init(void); int idefloppy_reinit(ide_drive_t *drive); /* @@ -2072,7 +2071,6 @@ static ide_driver_t idefloppy_driver = { capacity: idefloppy_capacity, special: NULL, proc: idefloppy_proc, - driver_init: idefloppy_init, driver_reinit: idefloppy_reinit, }; @@ -2105,7 +2103,7 @@ int idefloppy_reinit (ide_drive_t *drive) DRIVER(drive)->busy--; failed--; } - ide_register_module(&idefloppy_driver); + revalidate_drives(); MOD_DEC_USE_COUNT; return 0; } @@ -2130,7 +2128,6 @@ static void __exit idefloppy_exit (void) ide_remove_proc_entries(drive->proc, idefloppy_proc); #endif } - ide_unregister_module(&idefloppy_driver); } /* @@ -2167,7 +2164,7 @@ int idefloppy_init (void) DRIVER(drive)->busy--; failed--; } - ide_register_module(&idefloppy_driver); + revalidate_drives(); MOD_DEC_USE_COUNT; return 0; } diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c index 139887984b2f..77af606a4aff 100644 --- a/drivers/ide/ide-proc.c +++ b/drivers/ide/ide-proc.c @@ -373,20 +373,6 @@ static int ide_getdigit(char c) return digit; } -static int proc_ide_read_drivers - (char *page, char **start, off_t off, int count, int *eof, void *data) -{ - char *out = page; - int len; - struct ide_driver_s * driver; - - for (driver = ide_drivers; driver; driver = driver->next) { - out += sprintf(out, "%s\n",driver->name); - } - len = out - page; - PROC_IDE_READ_RETURN(page,start,off,count,eof,len); -} - static int proc_ide_read_imodel (char *page, char **start, off_t off, int count, int *eof, void *data) { @@ -852,9 +838,6 @@ void proc_ide_create(void) create_proc_ide_interfaces(); - create_proc_read_entry("drivers", 0, proc_ide_root, - proc_ide_read_drivers, NULL); - #ifdef CONFIG_BLK_DEV_AEC62XX if ((aec62xx_display_info) && (aec62xx_proc)) create_proc_info_entry("aec62xx", 0, proc_ide_root, aec62xx_display_info); diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index f643d4248262..cc7f5d132703 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -6137,7 +6137,6 @@ static ide_proc_entry_t idetape_proc[] = { #endif -int idetape_init (void); int idetape_reinit(ide_drive_t *drive); /* @@ -6162,7 +6161,6 @@ static ide_driver_t idetape_driver = { pre_reset: idetape_pre_reset, capacity: NULL, proc: idetape_proc, - driver_init: idetape_init, driver_reinit: idetape_reinit, }; @@ -6193,7 +6191,7 @@ int idetape_reinit (ide_drive_t *drive) idetape_chrdevs[minor].drive = NULL; if ((drive = ide_scan_devices (ide_tape, idetape_driver.name, NULL, failed++)) == NULL) { - ide_register_module (&idetape_module); + revalidate_drives(); MOD_DEC_USE_COUNT; #if ONSTREAM_DEBUG printk(KERN_INFO "ide-tape: MOD_DEC_USE_COUNT in idetape_init\n"); @@ -6252,7 +6250,7 @@ int idetape_reinit (ide_drive_t *drive) devfs_unregister_chrdev (IDETAPE_MAJOR, "ht"); } else idetape_chrdev_present = 1; - ide_register_module (&idetape_module); + revalidate_drives(); MOD_DEC_USE_COUNT; #if ONSTREAM_DEBUG printk(KERN_INFO "ide-tape: MOD_DEC_USE_COUNT in idetape_init\n"); @@ -6277,7 +6275,6 @@ static void __exit idetape_exit (void) if (drive != NULL && idetape_cleanup (drive)) printk (KERN_ERR "ide-tape: %s: cleanup_module() called while still busy\n", drive->name); } - ide_unregister_module(&idetape_driver); } /* @@ -6298,7 +6295,7 @@ int idetape_init (void) idetape_chrdevs[minor].drive = NULL; if ((drive = ide_scan_devices (ide_tape, idetape_driver.name, NULL, failed++)) == NULL) { - ide_register_module (&idetape_driver); + revalidate_drives(); MOD_DEC_USE_COUNT; #if ONSTREAM_DEBUG printk(KERN_INFO "ide-tape: MOD_DEC_USE_COUNT in idetape_init\n"); @@ -6357,7 +6354,7 @@ int idetape_init (void) devfs_unregister_chrdev (IDETAPE_MAJOR, "ht"); } else idetape_chrdev_present = 1; - ide_register_module (&idetape_driver); + revalidate_drives(); MOD_DEC_USE_COUNT; #if ONSTREAM_DEBUG printk(KERN_INFO "ide-tape: MOD_DEC_USE_COUNT in idetape_init\n"); diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 56fc836fd330..c36c676da98c 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -195,11 +195,6 @@ static int ide_intr_lock; int noautodma = 0; -/* - * This is the anchor of the single linked list of ide device type drivers. - */ -struct ide_driver_s *ide_drivers; - /* * This is declared extern in ide.h, for access by other IDE modules: */ @@ -1842,7 +1837,11 @@ int ide_revalidate_disk (kdev_t i_rdev) return res; } -static void revalidate_drives (void) +/* + * Look again for all drives in the system on all interfaces. This is used + * after a new driver cathegory has been loaded as module. + */ +void revalidate_drives (void) { ide_hwif_t *hwif; ide_drive_t *drive; @@ -1870,15 +1869,12 @@ static void ide_probe_module (void) static void ide_driver_module (void) { int index; - struct ide_driver_s *d; for (index = 0; index < MAX_HWIFS; ++index) if (ide_hwifs[index].present) goto search; ide_probe_module(); search: - for (d = ide_drivers; d != NULL; d = d->next) - d->driver_init(); revalidate_drives(); } @@ -3610,30 +3606,6 @@ int ide_unregister_subdriver (ide_drive_t *drive) return 0; } -int ide_register_module (struct ide_driver_s *d) -{ - struct ide_driver_s *p = ide_drivers; - - while (p) { - if (p == d) - return 1; - p = p->next; - } - d->next = ide_drivers; - ide_drivers = d; - revalidate_drives(); - return 0; -} - -void ide_unregister_module (struct ide_driver_s *d) -{ - struct ide_driver_s **p; - - for (p = &ide_drivers; (*p) && (*p) != d; p = &((*p)->next)); - if (*p) - *p = (*p)->next; -} - struct block_device_operations ide_fops[] = {{ owner: THIS_MODULE, open: ide_open, @@ -3644,9 +3616,8 @@ struct block_device_operations ide_fops[] = {{ }}; EXPORT_SYMBOL(ide_hwifs); -EXPORT_SYMBOL(ide_register_module); -EXPORT_SYMBOL(ide_unregister_module); EXPORT_SYMBOL(ide_spin_wait_hwgroup); +EXPORT_SYMBOL(revalidate_drives); /* * Probe module diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c index 63bd1bb34547..bf6941762f70 100644 --- a/drivers/scsi/ide-scsi.c +++ b/drivers/scsi/ide-scsi.c @@ -535,7 +535,6 @@ static int idescsi_cleanup (ide_drive_t *drive) return 0; } -int idescsi_init(void); int idescsi_reinit(ide_drive_t *drive); /* @@ -561,7 +560,6 @@ static ide_driver_t idescsi_driver = { capacity: NULL, special: NULL, proc: NULL, - driver_init: idescsi_init, driver_reinit: idescsi_reinit, }; @@ -596,7 +594,7 @@ int idescsi_reinit (ide_drive_t *drive) failed--; } } - ide_register_module(&idescsi_module); + revalidate_drives(); MOD_DEC_USE_COUNT; #endif return 0; @@ -636,7 +634,7 @@ int idescsi_init (void) failed--; } } - ide_register_module(&idescsi_driver); + revalidate_drives(); MOD_DEC_USE_COUNT; return 0; } @@ -906,7 +904,6 @@ static void __exit exit_idescsi_module(void) failed++; } } - ide_unregister_module(&idescsi_driver); } module_init(init_idescsi_module); diff --git a/include/linux/ide.h b/include/linux/ide.h index b734a586cd45..31986f42acb4 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -722,12 +722,7 @@ typedef struct ide_driver_s { unsigned long (*capacity)(ide_drive_t *); ide_startstop_t (*special)(ide_drive_t *); ide_proc_entry_t *proc; - int (*driver_init)(void); int (*driver_reinit)(ide_drive_t *); - - /* FIXME: Single linked list of drivers for iteration. - */ - struct ide_driver_s *next; } ide_driver_t; #define DRIVER(drive) ((drive)->driver) @@ -742,7 +737,6 @@ typedef struct ide_driver_s { */ #ifndef _IDE_C extern struct hwif_s ide_hwifs[]; /* master data repository */ -extern struct ide_driver_s *ide_drivers; #endif extern int noautodma; @@ -1072,8 +1066,6 @@ int idescsi_init (void); #endif /* CONFIG_BLK_DEV_IDESCSI */ #endif /* _IDE_C */ -extern int ide_register_module (struct ide_driver_s *d); -extern void ide_unregister_module (struct ide_driver_s *d); ide_drive_t *ide_scan_devices (byte media, const char *name, ide_driver_t *driver, int n); extern int ide_register_subdriver(ide_drive_t *drive, ide_driver_t *driver); extern int ide_unregister_subdriver(ide_drive_t *drive); @@ -1108,5 +1100,6 @@ extern unsigned long ide_get_or_set_dma_base (ide_hwif_t *hwif, int extra, const extern spinlock_t ide_lock; extern int drive_is_ready(ide_drive_t *drive); +extern void revalidate_drives(void); #endif /* _IDE_H */ -- cgit v1.2.3 From ce43a9ec219c360539e390c20fe9357e22d7ad07 Mon Sep 17 00:00:00 2001 From: Martin Dalecki Date: Wed, 27 Feb 2002 20:15:18 -0800 Subject: [PATCH] 2.5.6-pre1 IDE cleanup 11 1. Start of driver tree usage upon suggestion from Pavel Machek. This still will needs a lot of further work in the future, but the current code doesn't hurt anything and allowa Pavel to work further from the base line. In esp. natively implemented suspend to file requires this - which I would love to see comming in,since I'm quite frequently using a notebook myself. 2. Kill the _IDE_C macro, which was playing games on entierly unnecessary declarations inside of header files in esp ide_modes.h 3. Replace the functionally totally equal system_bus_block() and ide_system_bus_speed() functions with one simple global variable: system_bus_speed. This saves quite a significatn amount of code. Unfortunately this is the part, which is makeing this patch to appear bigger then it really is... 4. Use ide_devalidate_drive() directly instead of idedisk_revalidate(). 5. Kill conditional CONFIG_KMOD as well as some other minor tweaks. Well this isn't that much in terms of functionality, but it took me quite q bit of time to catch up on the patch-2.5.5.gz ;-) --- drivers/ide/aec62xx.c | 8 +- drivers/ide/ali14xx.c | 5 +- drivers/ide/alim15x3.c | 9 +- drivers/ide/cmd640.c | 5 +- drivers/ide/cmd64x.c | 4 +- drivers/ide/cy82c693.c | 7 +- drivers/ide/ht6560b.c | 5 +- drivers/ide/ide-disk.c | 45 +++++++-- drivers/ide/ide-pnp.c | 6 +- drivers/ide/ide-probe.c | 12 +++ drivers/ide/ide.c | 264 +++++++++++++++++++++++++++++++++++++++--------- drivers/ide/ide_modes.h | 198 +----------------------------------- drivers/ide/opti621.c | 9 +- drivers/ide/qd65xx.c | 14 +-- drivers/ide/via82cxxx.c | 2 +- include/linux/blk.h | 5 - include/linux/ide.h | 49 ++++----- 17 files changed, 315 insertions(+), 332 deletions(-) (limited to 'include/linux') diff --git a/drivers/ide/aec62xx.c b/drivers/ide/aec62xx.c index c97c89f995e6..04f674033efa 100644 --- a/drivers/ide/aec62xx.c +++ b/drivers/ide/aec62xx.c @@ -203,22 +203,18 @@ extern char *ide_xfer_verbose (byte xfer_rate); static byte pci_bus_clock_list (byte speed, struct chipset_bus_clock_list_entry * chipset_table) { - int bus_speed = system_bus_clock(); - for ( ; chipset_table->xfer_speed ; chipset_table++) if (chipset_table->xfer_speed == speed) { - return ((byte) ((bus_speed <= 33) ? chipset_table->chipset_settings_33 : chipset_table->chipset_settings_34)); + return ((byte) ((system_bus_speed <= 33) ? chipset_table->chipset_settings_33 : chipset_table->chipset_settings_34)); } return 0x00; } static byte pci_bus_clock_list_ultra (byte speed, struct chipset_bus_clock_list_entry * chipset_table) { - int bus_speed = system_bus_clock(); - for ( ; chipset_table->xfer_speed ; chipset_table++) if (chipset_table->xfer_speed == speed) { - return ((byte) ((bus_speed <= 33) ? chipset_table->ultra_settings_33 : chipset_table->ultra_settings_34)); + return ((byte) ((system_bus_speed <= 33) ? chipset_table->ultra_settings_33 : chipset_table->ultra_settings_34)); } return 0x00; } diff --git a/drivers/ide/ali14xx.c b/drivers/ide/ali14xx.c index 4fbd305adc2b..43c01a4e25b1 100644 --- a/drivers/ide/ali14xx.c +++ b/drivers/ide/ali14xx.c @@ -119,15 +119,14 @@ static void ali14xx_tune_drive (ide_drive_t *drive, byte pio) byte param1, param2, param3, param4; unsigned long flags; ide_pio_data_t d; - int bus_speed = system_bus_clock(); pio = ide_get_best_pio_mode(drive, pio, ALI_MAX_PIO, &d); /* calculate timing, according to PIO mode */ time1 = d.cycle_time; time2 = ide_pio_timings[pio].active_time; - param3 = param1 = (time2 * bus_speed + 999) / 1000; - param4 = param2 = (time1 * bus_speed + 999) / 1000 - param1; + param3 = param1 = (time2 * system_bus_speed + 999) / 1000; + param4 = param2 = (time1 * system_bus_speed + 999) / 1000 - param1; if (pio < 3) { param3 += 8; param4 += 8; diff --git a/drivers/ide/alim15x3.c b/drivers/ide/alim15x3.c index ccdeb80c9605..2073fb4cb119 100644 --- a/drivers/ide/alim15x3.c +++ b/drivers/ide/alim15x3.c @@ -247,7 +247,6 @@ static void ali15x3_tune_drive (ide_drive_t *drive, byte pio) int s_time, a_time, c_time; byte s_clc, a_clc, r_clc; unsigned long flags; - int bus_speed = system_bus_clock(); int port = hwif->index ? 0x5c : 0x58; int portFIFO = hwif->channel ? 0x55 : 0x54; byte cd_dma_fifo = 0; @@ -255,18 +254,18 @@ static void ali15x3_tune_drive (ide_drive_t *drive, byte pio) pio = ide_get_best_pio_mode(drive, pio, 5, &d); s_time = ide_pio_timings[pio].setup_time; a_time = ide_pio_timings[pio].active_time; - if ((s_clc = (s_time * bus_speed + 999) / 1000) >= 8) + if ((s_clc = (s_time * system_bus_speed + 999) / 1000) >= 8) s_clc = 0; - if ((a_clc = (a_time * bus_speed + 999) / 1000) >= 8) + if ((a_clc = (a_time * system_bus_speed + 999) / 1000) >= 8) a_clc = 0; c_time = ide_pio_timings[pio].cycle_time; #if 0 - if ((r_clc = ((c_time - s_time - a_time) * bus_speed + 999) / 1000) >= 16) + if ((r_clc = ((c_time - s_time - a_time) * system_bus_speed + 999) / 1000) >= 16) r_clc = 0; #endif - if (!(r_clc = (c_time * bus_speed + 999) / 1000 - a_clc - s_clc)) { + if (!(r_clc = (c_time * system_bus_speed + 999) / 1000 - a_clc - s_clc)) { r_clc = 1; } else { if (r_clc >= 16) diff --git a/drivers/ide/cmd640.c b/drivers/ide/cmd640.c index cdb1df0a9027..a59c21146723 100644 --- a/drivers/ide/cmd640.c +++ b/drivers/ide/cmd640.c @@ -23,7 +23,7 @@ * * A.Hartgers@stud.tue.nl, JZDQC@CUNYVM.CUNY.edu, abramov@cecmow.enet.dec.com, * bardj@utopia.ppp.sn.no, bart@gaga.tue.nl, bbol001@cs.auckland.ac.nz, - * chrisc@dbass.demon.co.uk, dalecki@namu26.Num.Math.Uni-Goettingen.de, + * chrisc@dbass.demon.co.uk, dalecki@evision-ventures.com, * derekn@vw.ece.cmu.edu, florian@btp2x3.phy.uni-bayreuth.de, * flynn@dei.unipd.it, gadio@netvision.net.il, godzilla@futuris.net, * j@pobox.com, jkemp1@mises.uni-paderborn.de, jtoppe@hiwaay.net, @@ -596,14 +596,13 @@ static void cmd640_set_mode (unsigned int index, byte pio_mode, unsigned int cyc { int setup_time, active_time, recovery_time, clock_time; byte setup_count, active_count, recovery_count, recovery_count2, cycle_count; - int bus_speed = system_bus_clock(); if (pio_mode > 5) pio_mode = 5; setup_time = ide_pio_timings[pio_mode].setup_time; active_time = ide_pio_timings[pio_mode].active_time; recovery_time = cycle_time - (setup_time + active_time); - clock_time = 1000 / bus_speed; + clock_time = 1000 / system_bus_speed; cycle_count = (cycle_time + clock_time - 1) / clock_time; setup_count = (setup_time + clock_time - 1) / clock_time; diff --git a/drivers/ide/cmd64x.c b/drivers/ide/cmd64x.c index 64004b418efa..7a2dc2882973 100644 --- a/drivers/ide/cmd64x.c +++ b/drivers/ide/cmd64x.c @@ -283,8 +283,6 @@ static void cmd64x_tuneproc (ide_drive_t *drive, byte mode_wanted) int setup_time, active_time, recovery_time, clock_time, pio_mode, cycle_time; byte recovery_count2, cycle_count; int setup_count, active_count, recovery_count; - int bus_speed = system_bus_clock(); - /*byte b;*/ ide_pio_data_t d; switch (mode_wanted) { @@ -309,7 +307,7 @@ static void cmd64x_tuneproc (ide_drive_t *drive, byte mode_wanted) setup_time = ide_pio_timings[pio_mode].setup_time; active_time = ide_pio_timings[pio_mode].active_time; recovery_time = cycle_time - (setup_time + active_time); - clock_time = 1000 / bus_speed; + clock_time = 1000 / system_bus_speed; cycle_count = (cycle_time + clock_time - 1) / clock_time; setup_count = (setup_time + clock_time - 1) / clock_time; diff --git a/drivers/ide/cy82c693.c b/drivers/ide/cy82c693.c index 964dfc9fef79..208ef2db7cda 100644 --- a/drivers/ide/cy82c693.c +++ b/drivers/ide/cy82c693.c @@ -141,7 +141,6 @@ static int calc_clk (int time, int bus_speed) static void compute_clocks (byte pio, pio_clocks_t *p_pclk) { int clk1, clk2; - int bus_speed = system_bus_clock(); /* get speed of PCI bus */ /* we don't check against CY82C693's min and max speed, * so you can play with the idebus=xx parameter @@ -151,17 +150,17 @@ static void compute_clocks (byte pio, pio_clocks_t *p_pclk) pio = CY82C693_MAX_PIO; /* let's calc the address setup time clocks */ - p_pclk->address_time = (byte)calc_clk(ide_pio_timings[pio].setup_time, bus_speed); + p_pclk->address_time = (byte)calc_clk(ide_pio_timings[pio].setup_time, system_bus_speed); /* let's calc the active and recovery time clocks */ - clk1 = calc_clk(ide_pio_timings[pio].active_time, bus_speed); + clk1 = calc_clk(ide_pio_timings[pio].active_time, system_bus_speed); /* calc recovery timing */ clk2 = ide_pio_timings[pio].cycle_time - ide_pio_timings[pio].active_time - ide_pio_timings[pio].setup_time; - clk2 = calc_clk(clk2, bus_speed); + clk2 = calc_clk(clk2, system_bus_speed); clk1 = (clk1<<4)|clk2; /* combine active and recovery clocks */ diff --git a/drivers/ide/ht6560b.c b/drivers/ide/ht6560b.c index 3ba8e55eee71..e0eab96ad629 100644 --- a/drivers/ide/ht6560b.c +++ b/drivers/ide/ht6560b.c @@ -207,7 +207,6 @@ static byte ht_pio2timings(ide_drive_t *drive, byte pio) int active_time, recovery_time; int active_cycles, recovery_cycles; ide_pio_data_t d; - int bus_speed = system_bus_clock(); if (pio) { pio = ide_get_best_pio_mode(drive, pio, 5, &d); @@ -224,8 +223,8 @@ static byte ht_pio2timings(ide_drive_t *drive, byte pio) /* * Cycle times should be Vesa bus cycles */ - active_cycles = (active_time * bus_speed + 999) / 1000; - recovery_cycles = (recovery_time * bus_speed + 999) / 1000; + active_cycles = (active_time * system_bus_speed + 999) / 1000; + recovery_cycles = (recovery_time * system_bus_speed + 999) / 1000; /* * Upper and lower limits */ diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index 43d9b957f429..a3bf789fbf2d 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -378,11 +378,6 @@ static int idedisk_media_change (ide_drive_t *drive) return drive->removable; /* if removable, always assume it was changed */ } -static void idedisk_revalidate (ide_drive_t *drive) -{ - ide_revalidate_drive(drive); -} - /* * Queries for true maximum capacity of the drive. * Returns maximum LBA address (> 0) of the drive, 0 if failed. @@ -915,13 +910,22 @@ static void idedisk_add_settings(ide_drive_t *drive) ide_add_setting(drive, "max_failures", SETTING_RW, -1, -1, TYPE_INT, 0, 65535, 1, 1, &drive->max_failures, NULL); } -static void idedisk_setup (ide_drive_t *drive) +/* This is just a hook for the overall driver tree. + * + * FIXME: This is soon goig to replace the custom linked list games played up + * to great extend between the different components of the IDE drivers. + */ + +static struct device_driver idedisk_devdrv = {}; + +static void idedisk_setup(ide_drive_t *drive) { int i; - + struct hd_driveid *id = drive->id; unsigned long capacity; - + int drvid = -1; + idedisk_add_settings(drive); if (id == NULL) @@ -933,7 +937,7 @@ static void idedisk_setup (ide_drive_t *drive) */ if (drive->removable && !drive_is_flashcard(drive)) { /* - * Removable disks (eg. SYQUEST); ignore 'WD' drives + * Removable disks (eg. SYQUEST); ignore 'WD' drives. */ if (id->model[0] != 'W' || id->model[1] != 'D') { drive->doorlocking = 1; @@ -942,13 +946,26 @@ static void idedisk_setup (ide_drive_t *drive) for (i = 0; i < MAX_DRIVES; ++i) { ide_hwif_t *hwif = HWIF(drive); - if (drive != &hwif->drives[i]) continue; + if (drive != &hwif->drives[i]) + continue; + drvid = i; hwif->gd->de_arr[i] = drive->de; if (drive->removable) hwif->gd->flags[i] |= GENHD_FL_REMOVABLE; break; } + /* Register us within the device tree. + */ + + if (drvid != -1) { + sprintf(drive->device.bus_id, "%d", drvid); + sprintf(drive->device.name, "ide-disk"); + drive->device.driver = &idedisk_devdrv; + drive->device.parent = &HWIF(drive)->device; + device_register(&drive->device); + } + /* Extract geometry if we did not already have one for the drive */ if (!drive->cyl || !drive->head || !drive->sect) { drive->cyl = drive->bios_cyl = id->cyls; @@ -1023,6 +1040,12 @@ static void idedisk_setup (ide_drive_t *drive) static int idedisk_cleanup (ide_drive_t *drive) { + + /* FIXME: we will have to think twice whatever this is the proper place + * to do it. + */ + + put_device(&drive->device); if ((drive->id->cfs_enable_2 & 0x3000) && drive->wcache) if (do_idedisk_flushcache(drive)) printk (KERN_INFO "%s: Write Cache FAILED Flushing!\n", @@ -1050,7 +1073,7 @@ static ide_driver_t idedisk_driver = { open: idedisk_open, release: idedisk_release, media_change: idedisk_media_change, - revalidate: idedisk_revalidate, + revalidate: ide_revalidate_drive, pre_reset: idedisk_pre_reset, capacity: idedisk_capacity, special: idedisk_special, diff --git a/drivers/ide/ide-pnp.c b/drivers/ide/ide-pnp.c index ad4b52388507..462de4501072 100644 --- a/drivers/ide/ide-pnp.c +++ b/drivers/ide/ide-pnp.c @@ -57,6 +57,7 @@ struct pnp_dev_t { static int __init pnpide_generic_init(struct pci_dev *dev, int enable) { hw_regs_t hw; + ide_hwif_t *hwif; int index; if (!enable) @@ -69,10 +70,11 @@ static int __init pnpide_generic_init(struct pci_dev *dev, int enable) generic_ide_offsets, (ide_ioreg_t) DEV_IO(dev, 1), 0, NULL, DEV_IRQ(dev, 0)); - index = ide_register_hw(&hw, NULL); + index = ide_register_hw(&hw, &hwif); if (index != -1) { - printk("ide%d: %s IDE interface\n", index, DEV_NAME(dev)); + hwif->pci_dev = dev; + printk("ide%d: %s IDE interface\n", index, DEV_NAME(dev)); return 0; } diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 5577d55ca57b..838157105788 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include @@ -465,6 +466,17 @@ static int hwif_check_regions (ide_hwif_t *hwif) static void hwif_register (ide_hwif_t *hwif) { + /* Register this hardware interface within the global device tree. + */ + sprintf(hwif->device.bus_id, "%04x", hwif->io_ports[IDE_DATA_OFFSET]); + sprintf(hwif->device.name, "ide"); + hwif->device.driver_data = hwif; + if (hwif->pci_dev) + hwif->device.parent = &hwif->pci_dev->dev; + else + hwif->device.parent = NULL; /* Would like to do = &device_legacy */ + device_register(&hwif->device); + if (((unsigned long)hwif->io_ports[IDE_DATA_OFFSET] | 7) == ((unsigned long)hwif->io_ports[IDE_STATUS_OFFSET])) { ide_request_region(hwif->io_ports[IDE_DATA_OFFSET], 8, hwif->name); diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index c36c676da98c..a34c94881618 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -128,8 +128,6 @@ #undef REALLY_SLOW_IO /* most systems can safely undef this */ -#define _IDE_C /* Tell ide.h it's really us */ - #include #include #include @@ -153,6 +151,8 @@ #include #include #include +#include +#include #include #include @@ -162,17 +162,102 @@ #include "ide_modes.h" -#ifdef CONFIG_KMOD -#include -#endif /* CONFIG_KMOD */ +/* Constant tables for PIO mode programming: + */ + +const ide_pio_timings_t ide_pio_timings[6] = { + { 70, 165, 600 }, /* PIO Mode 0 */ + { 50, 125, 383 }, /* PIO Mode 1 */ + { 30, 100, 240 }, /* PIO Mode 2 */ + { 30, 80, 180 }, /* PIO Mode 3 with IORDY */ + { 25, 70, 120 }, /* PIO Mode 4 with IORDY */ + { 20, 50, 100 } /* PIO Mode 5 with IORDY (nonstandard) */ +}; + +/* + * Black list. Some drives incorrectly report their maximal PIO mode, + * at least in respect to CMD640. Here we keep info on some known drives. + */ +static struct ide_pio_info { + const char *name; + int pio; +} ide_pio_blacklist [] = { +/* { "Conner Peripherals 1275MB - CFS1275A", 4 }, */ + { "Conner Peripherals 540MB - CFS540A", 3 }, + + { "WDC AC2700", 3 }, + { "WDC AC2540", 3 }, + { "WDC AC2420", 3 }, + { "WDC AC2340", 3 }, + { "WDC AC2250", 0 }, + { "WDC AC2200", 0 }, + { "WDC AC21200", 4 }, + { "WDC AC2120", 0 }, + { "WDC AC2850", 3 }, + { "WDC AC1270", 3 }, + { "WDC AC1170", 1 }, + { "WDC AC1210", 1 }, + { "WDC AC280", 0 }, +/* { "WDC AC21000", 4 }, */ + { "WDC AC31000", 3 }, + { "WDC AC31200", 3 }, +/* { "WDC AC31600", 4 }, */ + + { "Maxtor 7131 AT", 1 }, + { "Maxtor 7171 AT", 1 }, + { "Maxtor 7213 AT", 1 }, + { "Maxtor 7245 AT", 1 }, + { "Maxtor 7345 AT", 1 }, + { "Maxtor 7546 AT", 3 }, + { "Maxtor 7540 AV", 3 }, + + { "SAMSUNG SHD-3121A", 1 }, + { "SAMSUNG SHD-3122A", 1 }, + { "SAMSUNG SHD-3172A", 1 }, + +/* { "ST51080A", 4 }, + * { "ST51270A", 4 }, + * { "ST31220A", 4 }, + * { "ST31640A", 4 }, + * { "ST32140A", 4 }, + * { "ST3780A", 4 }, + */ + { "ST5660A", 3 }, + { "ST3660A", 3 }, + { "ST3630A", 3 }, + { "ST3655A", 3 }, + { "ST3391A", 3 }, + { "ST3390A", 1 }, + { "ST3600A", 1 }, + { "ST3290A", 0 }, + { "ST3144A", 0 }, + { "ST3491A", 1 }, /* reports 3, should be 1 or 2 (depending on */ + /* drive) according to Seagates FIND-ATA program */ + + { "QUANTUM ELS127A", 0 }, + { "QUANTUM ELS170A", 0 }, + { "QUANTUM LPS240A", 0 }, + { "QUANTUM LPS210A", 3 }, + { "QUANTUM LPS270A", 3 }, + { "QUANTUM LPS365A", 3 }, + { "QUANTUM LPS540A", 3 }, + { "QUANTUM LIGHTNING 540A", 3 }, + { "QUANTUM LIGHTNING 730A", 3 }, + + { "QUANTUM FIREBALL_540", 3 }, /* Older Quantum Fireballs don't work */ + { "QUANTUM FIREBALL_640", 3 }, + { "QUANTUM FIREBALL_1080", 3 }, + { "QUANTUM FIREBALL_1280", 3 }, + { NULL, 0 } +}; /* default maximum number of failures */ -#define IDE_DEFAULT_MAX_FAILURES 1 +#define IDE_DEFAULT_MAX_FAILURES 1 static const byte ide_hwif_to_major[] = { IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR, IDE4_MAJOR, IDE5_MAJOR, IDE6_MAJOR, IDE7_MAJOR, IDE8_MAJOR, IDE9_MAJOR }; static int idebus_parameter; /* holds the "idebus=" parameter */ -static int system_bus_speed; /* holds what we think is VESA/PCI bus speed */ +int system_bus_speed; /* holds what we think is VESA/PCI bus speed */ static int initializing; /* set while initializing built-in drivers */ /* @@ -200,6 +285,106 @@ int noautodma = 0; */ ide_hwif_t ide_hwifs[MAX_HWIFS]; /* master data repository */ + +/* + * This routine searches the ide_pio_blacklist for an entry + * matching the start/whole of the supplied model name. + * + * Returns -1 if no match found. + * Otherwise returns the recommended PIO mode from ide_pio_blacklist[]. + */ +int ide_scan_pio_blacklist (char *model) +{ + struct ide_pio_info *p; + + for (p = ide_pio_blacklist; p->name != NULL; p++) { + if (strncmp(p->name, model, strlen(p->name)) == 0) + return p->pio; + } + return -1; +} + +/* + * This routine returns the recommended PIO settings for a given drive, + * based on the drive->id information and the ide_pio_blacklist[]. + * This is used by most chipset support modules when "auto-tuning". + */ + +/* + * Drive PIO mode auto selection + */ +byte ide_get_best_pio_mode (ide_drive_t *drive, byte mode_wanted, byte max_mode, ide_pio_data_t *d) +{ + int pio_mode; + int cycle_time = 0; + int use_iordy = 0; + struct hd_driveid* id = drive->id; + int overridden = 0; + int blacklisted = 0; + + if (mode_wanted != 255) { + pio_mode = mode_wanted; + } else if (!drive->id) { + pio_mode = 0; + } else if ((pio_mode = ide_scan_pio_blacklist(id->model)) != -1) { + overridden = 1; + blacklisted = 1; + use_iordy = (pio_mode > 2); + } else { + pio_mode = id->tPIO; + if (pio_mode > 2) { /* 2 is maximum allowed tPIO value */ + pio_mode = 2; + overridden = 1; + } + if (id->field_valid & 2) { /* drive implements ATA2? */ + if (id->capability & 8) { /* drive supports use_iordy? */ + use_iordy = 1; + cycle_time = id->eide_pio_iordy; + if (id->eide_pio_modes & 7) { + overridden = 0; + if (id->eide_pio_modes & 4) + pio_mode = 5; + else if (id->eide_pio_modes & 2) + pio_mode = 4; + else + pio_mode = 3; + } + } else { + cycle_time = id->eide_pio; + } + } + +#if 0 + if (drive->id->major_rev_num & 0x0004) printk("ATA-2 "); +#endif + + /* + * Conservative "downgrade" for all pre-ATA2 drives + */ + if (pio_mode && pio_mode < 4) { + pio_mode--; + overridden = 1; +#if 0 + use_iordy = (pio_mode > 2); +#endif + if (cycle_time && cycle_time < ide_pio_timings[pio_mode].cycle_time) + cycle_time = 0; /* use standard timing */ + } + } + if (pio_mode > max_mode) { + pio_mode = max_mode; + cycle_time = 0; + } + if (d) { + d->pio_mode = pio_mode; + d->cycle_time = cycle_time ? cycle_time : ide_pio_timings[pio_mode].cycle_time; + d->use_iordy = use_iordy; + d->overridden = overridden; + d->blacklisted = blacklisted; + } + return pio_mode; +} + #if (DISK_RECOVERY_TIME > 0) /* * For really screwy hardware (hey, at least it *can* be used with Linux) @@ -308,7 +493,6 @@ static void __init init_ide_data (void) ide_init_default_hwifs(); idebus_parameter = 0; - system_bus_speed = 0; } /* @@ -342,30 +526,6 @@ int drive_is_flashcard (ide_drive_t *drive) return 0; /* no, it is not a flash memory card */ } -/* - * ide_system_bus_speed() returns what we think is the system VESA/PCI - * bus speed (in MHz). This is used for calculating interface PIO timings. - * The default is 40 for known PCI systems, 50 otherwise. - * The "idebus=xx" parameter can be used to override this value. - * The actual value to be used is computed/displayed the first time through. - */ -int ide_system_bus_speed (void) -{ - if (!system_bus_speed) { - if (idebus_parameter) - system_bus_speed = idebus_parameter; /* user supplied value */ -#ifdef CONFIG_PCI - else if (pci_present()) - system_bus_speed = 33; /* safe default value for PCI */ -#endif /* CONFIG_PCI */ - else - system_bus_speed = 50; /* safe default value for VESA and PCI */ - printk("ide: Assuming %dMHz system bus speed for PIO modes%s\n", system_bus_speed, - idebus_parameter ? "" : "; override with idebus=xx"); - } - return system_bus_speed; -} - int __ide_end_request(ide_drive_t *drive, int uptodate, int nr_secs) { struct request *rq; @@ -2005,6 +2165,7 @@ void ide_unregister (unsigned int index) hwif = &ide_hwifs[index]; if (!hwif->present) goto abort; + put_device(&hwif->device); for (unit = 0; unit < MAX_DRIVES; ++unit) { drive = &hwif->drives[unit]; if (!drive->present) @@ -2489,11 +2650,6 @@ void ide_delay_50ms (void) #endif /* CONFIG_BLK_DEV_IDECS */ } -int system_bus_clock (void) -{ - return((int) ((!system_bus_speed) ? ide_system_bus_speed() : system_bus_speed )); -} - int ide_reinit_drive (ide_drive_t *drive) { switch (drive->media) { @@ -3676,9 +3832,6 @@ EXPORT_SYMBOL(ide_unregister); EXPORT_SYMBOL(ide_setup_ports); EXPORT_SYMBOL(get_info_ptr); EXPORT_SYMBOL(current_capacity); - -EXPORT_SYMBOL(system_bus_clock); - EXPORT_SYMBOL(ide_reinit_drive); static int ide_notify_reboot (struct notifier_block *this, unsigned long event, void *x) @@ -3730,17 +3883,32 @@ static struct notifier_block ide_notifier = { /* * This is gets invoked once during initialization, to set *everything* up */ -int __init ide_init (void) +int __init ide_init(void) { - static char banner_printed; int i; - if (!banner_printed) { - printk(KERN_INFO "Uniform Multi-Platform E-IDE driver " REVISION "\n"); - ide_devfs_handle = devfs_mk_dir (NULL, "ide", NULL); - system_bus_speed = ide_system_bus_speed(); - banner_printed = 1; - } + printk(KERN_INFO "Uniform Multi-Platform E-IDE driver " REVISION "\n"); + ide_devfs_handle = devfs_mk_dir (NULL, "ide", NULL); + + /* Initialize system bus speed. + * + * This can be changed by a particular chipse initialization module. + * Otherwise we assume 33MHz as a safe value for PCI bus based systems. + * 50MHz will be assumed for abolitions like VESA, since higher values + * result in more conservative timing setups. + * + * The kernel parameter idebus=XX overrides the default settings. + */ + + system_bus_speed = 50; + if (idebus_parameter) + system_bus_speed = idebus_parameter; +#ifdef CONFIG_PCI + else if (pci_present()) + system_bus_speed = 33; +#endif + + printk("ide: system bus speed %dMHz\n", system_bus_speed); init_ide_data (); diff --git a/drivers/ide/ide_modes.h b/drivers/ide/ide_modes.h index 16b8cf123a59..5431d6b074b1 100644 --- a/drivers/ide/ide_modes.h +++ b/drivers/ide/ide_modes.h @@ -11,9 +11,6 @@ /* * Shared data/functions for determining best PIO mode for an IDE drive. - * Most of this stuff originally lived in cmd640.c, and changes to the - * ide_pio_blacklist[] table should be made with EXTREME CAUTION to avoid - * breaking the fragile cmd640.c support. */ #ifdef CONFIG_BLK_DEV_IDE_MODES @@ -37,200 +34,9 @@ typedef struct ide_pio_data_s { byte blacklisted; unsigned int cycle_time; } ide_pio_data_t; - -#ifndef _IDE_C -int ide_scan_pio_blacklist (char *model); -byte ide_get_best_pio_mode (ide_drive_t *drive, byte mode_wanted, byte max_mode, ide_pio_data_t *d); +extern int ide_scan_pio_blacklist (char *model); +extern byte ide_get_best_pio_mode (ide_drive_t *drive, byte mode_wanted, byte max_mode, ide_pio_data_t *d); extern const ide_pio_timings_t ide_pio_timings[6]; - -#else /* _IDE_C */ - -const ide_pio_timings_t ide_pio_timings[6] = { - { 70, 165, 600 }, /* PIO Mode 0 */ - { 50, 125, 383 }, /* PIO Mode 1 */ - { 30, 100, 240 }, /* PIO Mode 2 */ - { 30, 80, 180 }, /* PIO Mode 3 with IORDY */ - { 25, 70, 120 }, /* PIO Mode 4 with IORDY */ - { 20, 50, 100 } /* PIO Mode 5 with IORDY (nonstandard) */ -}; - -/* - * Black list. Some drives incorrectly report their maximal PIO mode, - * at least in respect to CMD640. Here we keep info on some known drives. - */ -static struct ide_pio_info { - const char *name; - int pio; -} ide_pio_blacklist [] = { -/* { "Conner Peripherals 1275MB - CFS1275A", 4 }, */ - { "Conner Peripherals 540MB - CFS540A", 3 }, - - { "WDC AC2700", 3 }, - { "WDC AC2540", 3 }, - { "WDC AC2420", 3 }, - { "WDC AC2340", 3 }, - { "WDC AC2250", 0 }, - { "WDC AC2200", 0 }, - { "WDC AC21200", 4 }, - { "WDC AC2120", 0 }, - { "WDC AC2850", 3 }, - { "WDC AC1270", 3 }, - { "WDC AC1170", 1 }, - { "WDC AC1210", 1 }, - { "WDC AC280", 0 }, -/* { "WDC AC21000", 4 }, */ - { "WDC AC31000", 3 }, - { "WDC AC31200", 3 }, -/* { "WDC AC31600", 4 }, */ - - { "Maxtor 7131 AT", 1 }, - { "Maxtor 7171 AT", 1 }, - { "Maxtor 7213 AT", 1 }, - { "Maxtor 7245 AT", 1 }, - { "Maxtor 7345 AT", 1 }, - { "Maxtor 7546 AT", 3 }, - { "Maxtor 7540 AV", 3 }, - - { "SAMSUNG SHD-3121A", 1 }, - { "SAMSUNG SHD-3122A", 1 }, - { "SAMSUNG SHD-3172A", 1 }, - -/* { "ST51080A", 4 }, - * { "ST51270A", 4 }, - * { "ST31220A", 4 }, - * { "ST31640A", 4 }, - * { "ST32140A", 4 }, - * { "ST3780A", 4 }, - */ - { "ST5660A", 3 }, - { "ST3660A", 3 }, - { "ST3630A", 3 }, - { "ST3655A", 3 }, - { "ST3391A", 3 }, - { "ST3390A", 1 }, - { "ST3600A", 1 }, - { "ST3290A", 0 }, - { "ST3144A", 0 }, - { "ST3491A", 1 }, /* reports 3, should be 1 or 2 (depending on */ - /* drive) according to Seagates FIND-ATA program */ - - { "QUANTUM ELS127A", 0 }, - { "QUANTUM ELS170A", 0 }, - { "QUANTUM LPS240A", 0 }, - { "QUANTUM LPS210A", 3 }, - { "QUANTUM LPS270A", 3 }, - { "QUANTUM LPS365A", 3 }, - { "QUANTUM LPS540A", 3 }, - { "QUANTUM LIGHTNING 540A", 3 }, - { "QUANTUM LIGHTNING 730A", 3 }, - - { "QUANTUM FIREBALL_540", 3 }, /* Older Quantum Fireballs don't work */ - { "QUANTUM FIREBALL_640", 3 }, - { "QUANTUM FIREBALL_1080", 3 }, - { "QUANTUM FIREBALL_1280", 3 }, - { NULL, 0 } -}; - -/* - * This routine searches the ide_pio_blacklist for an entry - * matching the start/whole of the supplied model name. - * - * Returns -1 if no match found. - * Otherwise returns the recommended PIO mode from ide_pio_blacklist[]. - */ -int ide_scan_pio_blacklist (char *model) -{ - struct ide_pio_info *p; - - for (p = ide_pio_blacklist; p->name != NULL; p++) { - if (strncmp(p->name, model, strlen(p->name)) == 0) - return p->pio; - } - return -1; -} - -/* - * This routine returns the recommended PIO settings for a given drive, - * based on the drive->id information and the ide_pio_blacklist[]. - * This is used by most chipset support modules when "auto-tuning". - */ - -/* - * Drive PIO mode auto selection - */ -byte ide_get_best_pio_mode (ide_drive_t *drive, byte mode_wanted, byte max_mode, ide_pio_data_t *d) -{ - int pio_mode; - int cycle_time = 0; - int use_iordy = 0; - struct hd_driveid* id = drive->id; - int overridden = 0; - int blacklisted = 0; - - if (mode_wanted != 255) { - pio_mode = mode_wanted; - } else if (!drive->id) { - pio_mode = 0; - } else if ((pio_mode = ide_scan_pio_blacklist(id->model)) != -1) { - overridden = 1; - blacklisted = 1; - use_iordy = (pio_mode > 2); - } else { - pio_mode = id->tPIO; - if (pio_mode > 2) { /* 2 is maximum allowed tPIO value */ - pio_mode = 2; - overridden = 1; - } - if (id->field_valid & 2) { /* drive implements ATA2? */ - if (id->capability & 8) { /* drive supports use_iordy? */ - use_iordy = 1; - cycle_time = id->eide_pio_iordy; - if (id->eide_pio_modes & 7) { - overridden = 0; - if (id->eide_pio_modes & 4) - pio_mode = 5; - else if (id->eide_pio_modes & 2) - pio_mode = 4; - else - pio_mode = 3; - } - } else { - cycle_time = id->eide_pio; - } - } - -#if 0 - if (drive->id->major_rev_num & 0x0004) printk("ATA-2 "); #endif - - /* - * Conservative "downgrade" for all pre-ATA2 drives - */ - if (pio_mode && pio_mode < 4) { - pio_mode--; - overridden = 1; -#if 0 - use_iordy = (pio_mode > 2); #endif - if (cycle_time && cycle_time < ide_pio_timings[pio_mode].cycle_time) - cycle_time = 0; /* use standard timing */ - } - } - if (pio_mode > max_mode) { - pio_mode = max_mode; - cycle_time = 0; - } - if (d) { - d->pio_mode = pio_mode; - d->cycle_time = cycle_time ? cycle_time : ide_pio_timings[pio_mode].cycle_time; - d->use_iordy = use_iordy; - d->overridden = overridden; - d->blacklisted = blacklisted; - } - return pio_mode; -} - -#endif /* _IDE_C */ -#endif /* CONFIG_BLK_DEV_IDE_MODES */ -#endif /* _IDE_MODES_H */ diff --git a/drivers/ide/opti621.c b/drivers/ide/opti621.c index f2501a5a67a4..4de087b3675d 100644 --- a/drivers/ide/opti621.c +++ b/drivers/ide/opti621.c @@ -164,7 +164,7 @@ static void compute_pios(ide_drive_t *drive, byte pio) } } -int cmpt_clk(int time, int bus_speed) +static int cmpt_clk(int time, int bus_speed) /* Returns (rounded up) time in clocks for time in ns, * with bus_speed in MHz. * Example: bus_speed = 40 MHz, time = 80 ns @@ -216,14 +216,13 @@ static void compute_clocks(int pio, pio_clocks_t *clks) { if (pio != PIO_NOT_EXIST) { int adr_setup, data_pls; - int bus_speed = system_bus_clock(); adr_setup = ide_pio_timings[pio].setup_time; data_pls = ide_pio_timings[pio].active_time; - clks->address_time = cmpt_clk(adr_setup, bus_speed); - clks->data_time = cmpt_clk(data_pls, bus_speed); + clks->address_time = cmpt_clk(adr_setup, system_bus_speed); + clks->data_time = cmpt_clk(data_pls, system_bus_speed); clks->recovery_time = cmpt_clk(ide_pio_timings[pio].cycle_time - - adr_setup-data_pls, bus_speed); + - adr_setup-data_pls, system_bus_speed); if (clks->address_time<1) clks->address_time = 1; if (clks->address_time>4) clks->address_time = 4; if (clks->data_time<1) clks->data_time = 1; diff --git a/drivers/ide/qd65xx.c b/drivers/ide/qd65xx.c index 7f1a10be1066..2cd2430f040a 100644 --- a/drivers/ide/qd65xx.c +++ b/drivers/ide/qd65xx.c @@ -139,12 +139,12 @@ static byte qd6500_compute_timing (ide_hwif_t *hwif, int active_time, int recove { byte active_cycle,recovery_cycle; - if (ide_system_bus_speed()<=33) { - active_cycle = 9 - IDE_IN(active_time * ide_system_bus_speed() / 1000 + 1, 2, 9); - recovery_cycle = 15 - IDE_IN(recovery_time * ide_system_bus_speed() / 1000 + 1, 0, 15); + if (system_bus_speed <= 33) { + active_cycle = 9 - IDE_IN(active_time * system_bus_speed / 1000 + 1, 2, 9); + recovery_cycle = 15 - IDE_IN(recovery_time * system_bus_speed / 1000 + 1, 0, 15); } else { - active_cycle = 8 - IDE_IN(active_time * ide_system_bus_speed() / 1000 + 1, 1, 8); - recovery_cycle = 18 - IDE_IN(recovery_time * ide_system_bus_speed() / 1000 + 1, 3, 18); + active_cycle = 8 - IDE_IN(active_time * system_bus_speed / 1000 + 1, 1, 8); + recovery_cycle = 18 - IDE_IN(recovery_time * system_bus_speed / 1000 + 1, 3, 18); } return((recovery_cycle<<4) | 0x08 | active_cycle); @@ -158,8 +158,8 @@ static byte qd6500_compute_timing (ide_hwif_t *hwif, int active_time, int recove static byte qd6580_compute_timing (int active_time, int recovery_time) { - byte active_cycle = 17-IDE_IN(active_time * ide_system_bus_speed() / 1000 + 1, 2, 17); - byte recovery_cycle = 15-IDE_IN(recovery_time * ide_system_bus_speed() / 1000 + 1, 2, 15); + byte active_cycle = 17-IDE_IN(active_time * system_bus_speed / 1000 + 1, 2, 17); + byte recovery_cycle = 15-IDE_IN(recovery_time * system_bus_speed / 1000 + 1, 2, 15); return((recovery_cycle<<4) | active_cycle); } diff --git a/drivers/ide/via82cxxx.c b/drivers/ide/via82cxxx.c index d2cd5be30117..e7742397422b 100644 --- a/drivers/ide/via82cxxx.c +++ b/drivers/ide/via82cxxx.c @@ -484,7 +484,7 @@ unsigned int __init pci_init_via82cxxx(struct pci_dev *dev, const char *name) * Determine system bus clock. */ - via_clock = system_bus_clock() * 1000; + via_clock = system_bus_speed * 1000; switch (via_clock) { case 33000: via_clock = 33333; break; diff --git a/include/linux/blk.h b/include/linux/blk.h index b6507e62eb4b..173634d2264b 100644 --- a/include/linux/blk.h +++ b/include/linux/blk.h @@ -8,11 +8,6 @@ #include #include -/* - * get rid of this next... - */ -extern int ide_init(void); - extern void set_device_ro(kdev_t dev,int flag); extern void add_blkdev_randomness(int major); diff --git a/include/linux/ide.h b/include/linux/ide.h index 31986f42acb4..8746e02a9d9a 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -426,7 +427,7 @@ typedef struct ide_drive_s { unsigned long capacity; /* total number of sectors */ unsigned long long capacity48; /* total number of sectors */ unsigned int drive_data; /* for use by tuneproc/selectproc as needed */ - struct hwif_s *hwif; /* actually (ide_hwif_t *) */ + struct hwif_s *hwif; /* parent pointer to the interface we are attached to */ wait_queue_head_t wqueue; /* used to wait for drive in open() */ struct hd_driveid *id; /* drive model identification info */ struct hd_struct *part; /* drive partition table */ @@ -450,6 +451,7 @@ typedef struct ide_drive_s { byte acoustic; /* acoustic management */ unsigned int failures; /* current failure count */ unsigned int max_failures; /* maximum allowed failure count */ + struct device device; /* global device tree handle */ } ide_drive_t; /* @@ -582,6 +584,7 @@ typedef struct hwif_s { void *hwif_data; /* extra hwif data */ ide_busproc_t *busproc; /* driver soft-power interface */ byte bus_state; /* power state of the IDE bus */ + struct device device; /* global device tree handle */ } ide_hwif_t; /* @@ -735,9 +738,7 @@ typedef struct ide_driver_s { * structure directly (the allocation/layout may change!). * */ -#ifndef _IDE_C extern struct hwif_s ide_hwifs[]; /* master data repository */ -#endif extern int noautodma; /* @@ -812,7 +813,7 @@ unsigned long current_capacity (ide_drive_t *drive); /* * Revalidate (read partition tables) */ -void ide_revalidate_drive (ide_drive_t *drive); +extern void ide_revalidate_drive (ide_drive_t *drive); /* * Start a reset operation for an IDE interface. @@ -953,7 +954,6 @@ void do_taskfile (ide_drive_t *drive, struct hd_drive_task_hdr *taskfile, struct /* * Special Flagged Register Validation Caller */ -// ide_startstop_t flagged_taskfile (ide_drive_t *drive, ide_task_t *task); ide_startstop_t set_multmode_intr (ide_drive_t *drive); ide_startstop_t set_geometry_intr (ide_drive_t *drive); @@ -984,7 +984,6 @@ int pkt_taskfile_ioctl (ide_drive_t *drive, struct inode *inode, struct file *fi #endif /* CONFIG_PKT_TASK_IOCTL */ void ide_delay_50ms (void); -int system_bus_clock(void); byte ide_auto_reduce_xfer (ide_drive_t *drive); int ide_driveid_update (ide_drive_t *drive); @@ -993,13 +992,7 @@ int ide_config_drive_speed (ide_drive_t *drive, byte speed); byte eighty_ninty_three (ide_drive_t *drive); int set_transfer (ide_drive_t *drive, ide_task_t *args); -/* - * ide_system_bus_speed() returns what we think is the system VESA/PCI - * bus speed (in MHz). This is used for calculating interface PIO timings. - * The default is 40 for known PCI systems, 50 otherwise. - * The "idebus=xx" parameter can be used to override this value. - */ -int ide_system_bus_speed (void); +extern int system_bus_speed; /* * idedisk_input_data() is a wrapper around ide_input_data() which copes @@ -1031,40 +1024,36 @@ void ide_intr (int irq, void *dev_id, struct pt_regs *regs); void do_ide_request (request_queue_t * q); void ide_init_subdrivers (void); -#ifndef _IDE_C extern struct block_device_operations ide_fops[]; extern ide_proc_entry_t generic_subdriver_entries[]; -#endif -int ide_reinit_drive (ide_drive_t *drive); +extern int ide_reinit_drive (ide_drive_t *drive); -#ifdef _IDE_C -# ifdef CONFIG_BLK_DEV_IDE +#ifdef CONFIG_BLK_DEV_IDE /* Probe for devices attached to the systems host controllers. */ extern int ideprobe_init (void); -# endif +#endif #ifdef CONFIG_BLK_DEV_IDEDISK -int idedisk_reinit (ide_drive_t *drive); -int idedisk_init (void); +extern int idedisk_reinit (ide_drive_t *drive); +extern int idedisk_init (void); #endif /* CONFIG_BLK_DEV_IDEDISK */ #ifdef CONFIG_BLK_DEV_IDECD -int ide_cdrom_reinit (ide_drive_t *drive); -int ide_cdrom_init (void); +extern int ide_cdrom_reinit (ide_drive_t *drive); +extern int ide_cdrom_init (void); #endif /* CONFIG_BLK_DEV_IDECD */ #ifdef CONFIG_BLK_DEV_IDETAPE -int idetape_reinit (ide_drive_t *drive); -int idetape_init (void); +extern int idetape_reinit (ide_drive_t *drive); +extern int idetape_init (void); #endif /* CONFIG_BLK_DEV_IDETAPE */ #ifdef CONFIG_BLK_DEV_IDEFLOPPY -int idefloppy_reinit (ide_drive_t *drive); -int idefloppy_init (void); +extern int idefloppy_reinit (ide_drive_t *drive); +extern int idefloppy_init (void); #endif /* CONFIG_BLK_DEV_IDEFLOPPY */ #ifdef CONFIG_BLK_DEV_IDESCSI -int idescsi_reinit (ide_drive_t *drive); -int idescsi_init (void); +extern int idescsi_reinit (ide_drive_t *drive); +extern int idescsi_init (void); #endif /* CONFIG_BLK_DEV_IDESCSI */ -#endif /* _IDE_C */ ide_drive_t *ide_scan_devices (byte media, const char *name, ide_driver_t *driver, int n); extern int ide_register_subdriver(ide_drive_t *drive, ide_driver_t *driver); -- cgit v1.2.3 From c0bf94494a9afdc074c9680a56ee5a8b3519bccb Mon Sep 17 00:00:00 2001 From: Martin Dalecki Date: Wed, 27 Feb 2002 20:15:25 -0800 Subject: [PATCH] 2.5.5 IDE cleanup 12 1. Add some notes to Documentation/driver-model.txt about how and and where to mount the driverfs. 2. Reorganize and prepare the PCI scanning code for proper device dependant splitup. Basically tedious cleanup of macro games. 3. Use struct pci_dev name field as the name of PCI host dapaters instead of invention ambigious IDE special names. This makes the kernel bootup messages look a bit shifted, since those names are bit longer, but makes up for consistance and should allow one later to rearage things to fit into the generic PCI device initialization mechanisms provided by the kernel. 4. Set 3. Allowed us to make the host chip specific pci_init_xxx class functions have the proper signature of module initializers. This will make it possible to make true modules out of them later. 5. Make some functions in cmd64x.c static which where not used elsewhere. 6. rename ide_special_settings to trust_pci_irq - this is reflecting it's functionality better. And make it match the pci device vendor as well as the device ID. It was a BUG to match only the device id!. 7. Make the chanell setup more tollerant for BIOS-es which don't report IO and MEM bases properly. The code found previously there tryed but was inconsistant. 8. Start to use proper terminology in ide-pci.c: host chip, channel, drive instead of hwif, port, drive... 9. Enlarge the name field from ide_hwif_t to 64 bytes. It was only 6 previously and there where custom names there which where exceeding this!!! But since we use the proper pci devce name there now instead, we had to extend the size of this field anyway. 10. Add some explanatory comments and fix misguiding comments here and there. 11. Kill the proc_ide_write_config and proc_ide_read_config brain damage! Those where backdoors to the pci configuration registers on PCI devices and IO registers on directly connected ISA ATA controllers. They didn't discrement between them! Access to both of them *simply* doesn't belong into an operating system, which is supposed to abstract out the access to hardware! Did I mention that access to both can be done from user land without an IDE special interface! Any program which was using them (I hardly beleve there is one) just deserves to loose. The programmer responsible for it deserves to be fired immediately. 12. Move ide_map_xx and ide_unmap_xx tinny bio level wrappers away from the "global" ide.h to where those are actually used and kill trivial wrappers for otherwise generic bio_ routines. Just fighting code obfuscation. The "rq->bio is used or is not there" brain damage in ide-taskfile.c has to be fixed later. Possibly by killing ide-taskfile.c alltogether, becouse this should be a driver for users and not a driver for ATA disk disaster recovery companys... 13. Kill hwif->pci_devid and hwif->pci_venid. Just use the already present hwif->pci_dev field instead. 14. Kill unused big switch ide_reinit_drive function. This silly functon was switching upon every possible device driver cathegory and calling the correspondng reinit function directly. This idiocy was fortunately not used. That's all... Most will be clear if one starts looking at the changes in ide.h of course... In contrast to the previous patches this one is actually fixing two serious bugs. The next direct step will be to kill the sigle place global PCI device type recognition list from ide-pci.c by pushing the entries to where they belong -> the host chips setup modules. --- Documentation/driver-model.txt | 15 +- drivers/ide/aec62xx.c | 4 +- drivers/ide/alim15x3.c | 4 +- drivers/ide/amd74xx.c | 6 +- drivers/ide/cmd64x.c | 18 +- drivers/ide/cs5530.c | 6 +- drivers/ide/cy82c693.c | 10 +- drivers/ide/hpt34x.c | 2 +- drivers/ide/hpt366.c | 2 +- drivers/ide/ide-pci.c | 959 +++++++++++++++++++---------------------- drivers/ide/ide-proc.c | 235 ---------- drivers/ide/ide-taskfile.c | 22 +- drivers/ide/ide.c | 76 +--- drivers/ide/it8172.c | 3 +- drivers/ide/pdc202xx.c | 14 +- drivers/ide/pdc4030.c | 8 +- drivers/ide/pdcadma.c | 2 +- drivers/ide/piix.c | 2 +- drivers/ide/serverworks.c | 2 +- drivers/ide/sis5513.c | 2 +- drivers/ide/sl82c105.c | 2 +- drivers/ide/slc90e66.c | 2 +- drivers/ide/via82cxxx.c | 2 +- include/linux/ide.h | 45 +- 24 files changed, 543 insertions(+), 900 deletions(-) (limited to 'include/linux') diff --git a/Documentation/driver-model.txt b/Documentation/driver-model.txt index f77e051f0582..d2740203568f 100644 --- a/Documentation/driver-model.txt +++ b/Documentation/driver-model.txt @@ -118,7 +118,18 @@ User Interface By virtue of having a complete hierarchical view of all the devices in the system, exporting a complete hierarchical view to userspace becomes relatively -easy. +easy. This has been accomplished by implementing a special purpose virtual +file system named driverfs. It is hence possible for the user to mount the +whole driverfs on a particular mount point in the unified UNIX file hierarchy. + +This can be done permanently by providing the following entry into the +/dev/fstab (under the provision that the mount point does exist, of course): + +none /devices driverfs defaults 0 0 + +Or by hand on the command line: + +~: mount -t driverfs none /devices Whenever a device is inserted into the tree, a directory is created for it. This directory may be populated at each layer of discovery - the global layer, @@ -343,6 +354,8 @@ user requests the system to suspend, it will walk the device tree, as exported via driverfs, and tell each device to go to sleep. It will do this multiple times based on what the system policy is. +[ FIXME: URL pointer to the corresponding utility is missing here! ] + Device resume should happen in the same manner when the system awakens. Each suspend stage is described below: diff --git a/drivers/ide/aec62xx.c b/drivers/ide/aec62xx.c index 04f674033efa..545d6a4de567 100644 --- a/drivers/ide/aec62xx.c +++ b/drivers/ide/aec62xx.c @@ -518,11 +518,11 @@ int aec62xx_dmaproc (ide_dma_action_t func, ide_drive_t *drive) #endif /* CONFIG_BLK_DEV_IDEDMA */ #endif /* CONFIG_AEC62XX_TUNING */ -unsigned int __init pci_init_aec62xx (struct pci_dev *dev, const char *name) +unsigned int __init pci_init_aec62xx (struct pci_dev *dev) { if (dev->resource[PCI_ROM_RESOURCE].start) { pci_write_config_dword(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE); - printk("%s: ROM enabled at 0x%08lx\n", name, dev->resource[PCI_ROM_RESOURCE].start); + printk("%s: ROM enabled at 0x%08lx\n", dev->name, dev->resource[PCI_ROM_RESOURCE].start); } #if defined(DISPLAY_AEC62XX_TIMINGS) && defined(CONFIG_PROC_FS) diff --git a/drivers/ide/alim15x3.c b/drivers/ide/alim15x3.c index 2073fb4cb119..727161449214 100644 --- a/drivers/ide/alim15x3.c +++ b/drivers/ide/alim15x3.c @@ -504,7 +504,7 @@ static int ali15x3_dmaproc (ide_dma_action_t func, ide_drive_t *drive) } #endif /* CONFIG_BLK_DEV_IDEDMA */ -unsigned int __init pci_init_ali15x3 (struct pci_dev *dev, const char *name) +unsigned int __init pci_init_ali15x3(struct pci_dev *dev) { unsigned long fixdma_base = pci_resource_start(dev, 4); @@ -523,7 +523,7 @@ unsigned int __init pci_init_ali15x3 (struct pci_dev *dev, const char *name) outb(inb(fixdma_base+2) & 0x60, fixdma_base+2); if (inb(fixdma_base+2) & 0x80) - printk("%s: simplex device: DMA will fail!!\n", name); + printk("%s: simplex device: DMA will fail!!\n", dev->name); } #if defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) diff --git a/drivers/ide/amd74xx.c b/drivers/ide/amd74xx.c index 04583a837bd3..0e185381d026 100644 --- a/drivers/ide/amd74xx.c +++ b/drivers/ide/amd74xx.c @@ -406,13 +406,13 @@ int amd74xx_dmaproc (ide_dma_action_t func, ide_drive_t *drive) } #endif /* CONFIG_BLK_DEV_IDEDMA */ -unsigned int __init pci_init_amd74xx (struct pci_dev *dev, const char *name) +unsigned int __init pci_init_amd74xx(struct pci_dev *dev) { unsigned long fixdma_base = pci_resource_start(dev, 4); #ifdef CONFIG_BLK_DEV_IDEDMA if (!amd74xx_swdma_check(dev)) - printk("%s: disabling single-word DMA support (revision < C4)\n", name); + printk("%s: disabling single-word DMA support (revision < C4)\n", dev->name); #endif /* CONFIG_BLK_DEV_IDEDMA */ if (!fixdma_base) { @@ -426,7 +426,7 @@ unsigned int __init pci_init_amd74xx (struct pci_dev *dev, const char *name) outb(inb(fixdma_base+2) & 0x60, fixdma_base+2); if (inb(fixdma_base+2) & 0x80) - printk("%s: simplex device: DMA will fail!!\n", name); + printk("%s: simplex device: DMA will fail!!\n", dev->name); } #if defined(DISPLAY_VIPER_TIMINGS) && defined(CONFIG_PROC_FS) if (!amd74xx_proc) { diff --git a/drivers/ide/cmd64x.c b/drivers/ide/cmd64x.c index 7a2dc2882973..feeb938221c5 100644 --- a/drivers/ide/cmd64x.c +++ b/drivers/ide/cmd64x.c @@ -954,7 +954,7 @@ static int cmd680_busproc (ide_drive_t * drive, int state) return 0; } -void cmd680_reset (ide_drive_t *drive) +static void cmd680_reset (ide_drive_t *drive) { #if 0 ide_hwif_t *hwif = HWIF(drive); @@ -966,9 +966,9 @@ void cmd680_reset (ide_drive_t *drive) #endif } -unsigned int cmd680_pci_init (struct pci_dev *dev, const char *name) +static unsigned int cmd680_pci_init(struct pci_dev *dev) { - u8 tmpbyte = 0; + u8 tmpbyte = 0; pci_write_config_byte(dev, 0x80, 0x00); pci_write_config_byte(dev, 0x84, 0x00); pci_read_config_byte(dev, 0x8A, &tmpbyte); @@ -992,7 +992,7 @@ unsigned int cmd680_pci_init (struct pci_dev *dev, const char *name) return 0; } -unsigned int cmd64x_pci_init (struct pci_dev *dev, const char *name) +static unsigned int cmd64x_pci_init(struct pci_dev *dev) { unsigned char mrdmode; unsigned int class_rev; @@ -1003,7 +1003,7 @@ unsigned int cmd64x_pci_init (struct pci_dev *dev, const char *name) #ifdef __i386__ if (dev->resource[PCI_ROM_RESOURCE].start) { pci_write_config_byte(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE); - printk("%s: ROM enabled at 0x%08lx\n", name, dev->resource[PCI_ROM_RESOURCE].start); + printk("%s: ROM enabled at 0x%08lx\n", dev->name, dev->resource[PCI_ROM_RESOURCE].start); } #endif @@ -1011,7 +1011,7 @@ unsigned int cmd64x_pci_init (struct pci_dev *dev, const char *name) case PCI_DEVICE_ID_CMD_643: break; case PCI_DEVICE_ID_CMD_646: - printk("%s: chipset revision 0x%02X, ", name, class_rev); + printk("%s: chipset revision 0x%02X, ", dev->name, class_rev); switch(class_rev) { case 0x07: case 0x05: @@ -1081,11 +1081,11 @@ unsigned int cmd64x_pci_init (struct pci_dev *dev, const char *name) return 0; } -unsigned int __init pci_init_cmd64x (struct pci_dev *dev, const char *name) +unsigned int __init pci_init_cmd64x(struct pci_dev *dev) { if (dev->device == PCI_DEVICE_ID_CMD_680) - return cmd680_pci_init (dev, name); - return cmd64x_pci_init (dev, name); + return cmd680_pci_init (dev); + return cmd64x_pci_init (dev); } unsigned int cmd680_ata66 (ide_hwif_t *hwif) diff --git a/drivers/ide/cs5530.c b/drivers/ide/cs5530.c index 9a3678442544..ac5ce9924e31 100644 --- a/drivers/ide/cs5530.c +++ b/drivers/ide/cs5530.c @@ -251,7 +251,7 @@ int cs5530_dmaproc (ide_dma_action_t func, ide_drive_t *drive) /* * Initialize the cs5530 bridge for reliable IDE DMA operation. */ -unsigned int __init pci_init_cs5530 (struct pci_dev *dev, const char *name) +unsigned int __init pci_init_cs5530(struct pci_dev *dev) { struct pci_dev *master_0 = NULL, *cs5530_0 = NULL; unsigned short pcicmd = 0; @@ -278,11 +278,11 @@ unsigned int __init pci_init_cs5530 (struct pci_dev *dev, const char *name) } } if (!master_0) { - printk("%s: unable to locate PCI MASTER function\n", name); + printk("%s: unable to locate PCI MASTER function\n", dev->name); return 0; } if (!cs5530_0) { - printk("%s: unable to locate CS5530 LEGACY function\n", name); + printk("%s: unable to locate CS5530 LEGACY function\n", dev->name); return 0; } diff --git a/drivers/ide/cy82c693.c b/drivers/ide/cy82c693.c index 208ef2db7cda..e7f8e4fa1c94 100644 --- a/drivers/ide/cy82c693.c +++ b/drivers/ide/cy82c693.c @@ -383,7 +383,7 @@ static void cy82c693_tune_drive (ide_drive_t *drive, byte pio) * the device prior to INIT. */ -unsigned int __init pci_init_cy82c693(struct pci_dev *dev, const char *name) +unsigned int __init pci_init_cy82c693(struct pci_dev *dev) { #ifdef CY82C693_SETDMA_CLOCK byte data; @@ -399,7 +399,7 @@ unsigned int __init pci_init_cy82c693(struct pci_dev *dev, const char *name) data = IN_BYTE(CY82_DATA_PORT); #if CY82C693_DEBUG_INFO - printk (KERN_INFO "%s: Peripheral Configuration Register: 0x%X\n", name, data); + printk (KERN_INFO "%s: Peripheral Configuration Register: 0x%X\n", dev->name, data); #endif /* CY82C693_DEBUG_INFO */ /* @@ -420,7 +420,7 @@ unsigned int __init pci_init_cy82c693(struct pci_dev *dev, const char *name) OUT_BYTE(data, CY82_DATA_PORT); #if CY82C693_DEBUG_INFO - printk (KERN_INFO "%s: New Peripheral Configuration Register: 0x%X\n", name, data); + printk (KERN_INFO "%s: New Peripheral Configuration Register: 0x%X\n", dev->name, data); #endif /* CY82C693_DEBUG_INFO */ #endif /* CY82C693_SETDMA_CLOCK */ @@ -433,7 +433,7 @@ unsigned int __init pci_init_cy82c693(struct pci_dev *dev, const char *name) void __init ide_init_cy82c693(ide_hwif_t *hwif) { hwif->chipset = ide_cy82c693; - hwif->tuneproc = &cy82c693_tune_drive; + hwif->tuneproc = cy82c693_tune_drive; hwif->drives[0].autotune = 1; hwif->drives[1].autotune = 1; hwif->autodma = 0; @@ -441,7 +441,7 @@ void __init ide_init_cy82c693(ide_hwif_t *hwif) #ifdef CONFIG_BLK_DEV_IDEDMA if (hwif->dma_base) { hwif->highmem = 1; - hwif->dmaproc = &cy82c693_dmaproc; + hwif->dmaproc = cy82c693_dmaproc; if (!noautodma) hwif->autodma = 1; } diff --git a/drivers/ide/hpt34x.c b/drivers/ide/hpt34x.c index 296d02958933..6254a113075a 100644 --- a/drivers/ide/hpt34x.c +++ b/drivers/ide/hpt34x.c @@ -357,7 +357,7 @@ int hpt34x_dmaproc (ide_dma_action_t func, ide_drive_t *drive) */ #define HPT34X_PCI_INIT_REG 0x80 -unsigned int __init pci_init_hpt34x (struct pci_dev *dev, const char *name) +unsigned int __init pci_init_hpt34x(struct pci_dev *dev) { int i = 0; unsigned long hpt34xIoBase = pci_resource_start(dev, 4); diff --git a/drivers/ide/hpt366.c b/drivers/ide/hpt366.c index 8c98bad76eae..092f57bfe980 100644 --- a/drivers/ide/hpt366.c +++ b/drivers/ide/hpt366.c @@ -1097,7 +1097,7 @@ init_hpt370_done: udelay(100); } -unsigned int __init pci_init_hpt366 (struct pci_dev *dev, const char *name) +unsigned int __init pci_init_hpt366(struct pci_dev *dev) { byte test = 0; diff --git a/drivers/ide/ide-pci.c b/drivers/ide/ide-pci.c index d6cae3ffbaa6..2727e85cdc1c 100644 --- a/drivers/ide/ide-pci.c +++ b/drivers/ide/ide-pci.c @@ -9,7 +9,7 @@ /* * This module provides support for automatic detection and - * configuration of all PCI IDE interfaces present in a system. + * configuration of all PCI IDE interfaces present in a system. */ /* @@ -32,339 +32,226 @@ #include #include -#define DEVID_PIIXa ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371FB_0}) -#define DEVID_PIIXb ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371FB_1}) -#define DEVID_MPIIX ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371MX}) -#define DEVID_PIIX3 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_1}) -#define DEVID_PIIX4 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB}) -#define DEVID_ICH0 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_1}) -#define DEVID_PIIX4E2 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_1}) -#define DEVID_ICH ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_1}) -#define DEVID_PIIX4U2 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82372FB_1}) -#define DEVID_PIIX4NX ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82451NX}) -#define DEVID_ICH2 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_9}) -#define DEVID_ICH2M ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_8}) -#define DEVID_ICH3 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_10}) -#define DEVID_VIA_IDE ((ide_pci_devid_t){PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C561}) -#define DEVID_MR_IDE ((ide_pci_devid_t){PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C576_1}) -#define DEVID_VP_IDE ((ide_pci_devid_t){PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1}) -#define DEVID_PDC20246 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20246}) -#define DEVID_PDC20262 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20262}) -#define DEVID_PDC20265 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20265}) -#define DEVID_PDC20267 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20267}) -#define DEVID_PDC20268 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20268}) -#define DEVID_PDC20268R ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20268R}) -#define DEVID_PDC20269 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20269}) -#define DEVID_PDC20275 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20275}) -#define DEVID_RZ1000 ((ide_pci_devid_t){PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1000}) -#define DEVID_RZ1001 ((ide_pci_devid_t){PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1001}) -#define DEVID_SAMURAI ((ide_pci_devid_t){PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_SAMURAI_IDE}) -#define DEVID_CMD640 ((ide_pci_devid_t){PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_640}) -#define DEVID_CMD643 ((ide_pci_devid_t){PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_643}) -#define DEVID_CMD646 ((ide_pci_devid_t){PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_646}) -#define DEVID_CMD648 ((ide_pci_devid_t){PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_648}) -#define DEVID_CMD649 ((ide_pci_devid_t){PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_649}) -#define DEVID_CMD680 ((ide_pci_devid_t){PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_680}) -#define DEVID_SIS5513 ((ide_pci_devid_t){PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5513}) -#define DEVID_OPTI621 ((ide_pci_devid_t){PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C621}) -#define DEVID_OPTI621V ((ide_pci_devid_t){PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C558}) -#define DEVID_OPTI621X ((ide_pci_devid_t){PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C825}) -#define DEVID_TRM290 ((ide_pci_devid_t){PCI_VENDOR_ID_TEKRAM, PCI_DEVICE_ID_TEKRAM_DC290}) -#define DEVID_NS87410 ((ide_pci_devid_t){PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87410}) -#define DEVID_NS87415 ((ide_pci_devid_t){PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87415}) -#define DEVID_HT6565 ((ide_pci_devid_t){PCI_VENDOR_ID_HOLTEK, PCI_DEVICE_ID_HOLTEK_6565}) -#define DEVID_AEC6210 ((ide_pci_devid_t){PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP850UF}) -#define DEVID_AEC6260 ((ide_pci_devid_t){PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP860}) -#define DEVID_AEC6260R ((ide_pci_devid_t){PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP860R}) -#define DEVID_W82C105 ((ide_pci_devid_t){PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105}) -#define DEVID_UM8673F ((ide_pci_devid_t){PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8673F}) -#define DEVID_UM8886A ((ide_pci_devid_t){PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886A}) -#define DEVID_UM8886BF ((ide_pci_devid_t){PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886BF}) -#define DEVID_HPT34X ((ide_pci_devid_t){PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT343}) -#define DEVID_HPT366 ((ide_pci_devid_t){PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT366}) -#define DEVID_ALI15X3 ((ide_pci_devid_t){PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5229}) -#define DEVID_CY82C693 ((ide_pci_devid_t){PCI_VENDOR_ID_CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693}) -#define DEVID_HINT ((ide_pci_devid_t){0x3388, 0x8013}) -#define DEVID_CS5530 ((ide_pci_devid_t){PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_IDE}) -#define DEVID_AMD7401 ((ide_pci_devid_t){PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_COBRA_7401}) -#define DEVID_AMD7409 ((ide_pci_devid_t){PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7409}) -#define DEVID_AMD7411 ((ide_pci_devid_t){PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7411}) -#define DEVID_AMD7441 ((ide_pci_devid_t){PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7441}) -#define DEVID_PDCADMA ((ide_pci_devid_t){PCI_VENDOR_ID_PDC, PCI_DEVICE_ID_PDC_1841}) -#define DEVID_SLC90E66 ((ide_pci_devid_t){PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_1}) -#define DEVID_OSB4 ((ide_pci_devid_t){PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4IDE}) -#define DEVID_CSB5 ((ide_pci_devid_t){PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5IDE}) -#define DEVID_ITE8172G ((ide_pci_devid_t){PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_IT8172G}) +/* Missing PCI device IDs: */ +#define PCI_VENDOR_ID_HINT 0x3388 +#define PCI_DEVICE_ID_HINT 0x8013 #define IDE_IGNORE ((void *)-1) #define IDE_NO_DRIVER ((void *)-2) #ifdef CONFIG_BLK_DEV_AEC62XX -extern unsigned int pci_init_aec62xx(struct pci_dev *, const char *); +extern unsigned int pci_init_aec62xx(struct pci_dev *); extern unsigned int ata66_aec62xx(ide_hwif_t *); extern void ide_init_aec62xx(ide_hwif_t *); extern void ide_dmacapable_aec62xx(ide_hwif_t *, unsigned long); -#define PCI_AEC62XX &pci_init_aec62xx -#define ATA66_AEC62XX &ata66_aec62xx -#define INIT_AEC62XX &ide_init_aec62xx -#define DMA_AEC62XX &ide_dmacapable_aec62xx #else -#define PCI_AEC62XX NULL -#define ATA66_AEC62XX NULL -#define INIT_AEC62XX IDE_NO_DRIVER -#define DMA_AEC62XX NULL +# define pci_init_aec62xx NULL +# define ata66_aec62xx NULL +# define ide_init_aec62xx IDE_NO_DRIVER +# define ide_dmacapable_aec62xx NULL #endif #ifdef CONFIG_BLK_DEV_ALI15X3 -extern unsigned int pci_init_ali15x3(struct pci_dev *, const char *); +extern unsigned int pci_init_ali15x3(struct pci_dev *); extern unsigned int ata66_ali15x3(ide_hwif_t *); extern void ide_init_ali15x3(ide_hwif_t *); extern void ide_dmacapable_ali15x3(ide_hwif_t *, unsigned long); -#define PCI_ALI15X3 &pci_init_ali15x3 -#define ATA66_ALI15X3 &ata66_ali15x3 -#define INIT_ALI15X3 &ide_init_ali15x3 -#define DMA_ALI15X3 &ide_dmacapable_ali15x3 #else -#define PCI_ALI15X3 NULL -#define ATA66_ALI15X3 NULL -#define INIT_ALI15X3 IDE_NO_DRIVER -#define DMA_ALI15X3 NULL +# define pci_init_ali15x3 NULL +# define ata66_ali15x3 NULL +# define ide_init_ali15x3 IDE_NO_DRIVER +# define ide_dmacapable_ali15x3 NULL #endif #ifdef CONFIG_BLK_DEV_AMD74XX -extern unsigned int pci_init_amd74xx(struct pci_dev *, const char *); +extern unsigned int pci_init_amd74xx(struct pci_dev *); extern unsigned int ata66_amd74xx(ide_hwif_t *); extern void ide_init_amd74xx(ide_hwif_t *); extern void ide_dmacapable_amd74xx(ide_hwif_t *, unsigned long); -#define PCI_AMD74XX &pci_init_amd74xx -#define ATA66_AMD74XX &ata66_amd74xx -#define INIT_AMD74XX &ide_init_amd74xx -#define DMA_AMD74XX &ide_dmacapable_amd74xx #else -#define PCI_AMD74XX NULL -#define ATA66_AMD74XX NULL -#define INIT_AMD74XX IDE_NO_DRIVER -#define DMA_AMD74XX NULL +# define pci_init_amd74xx NULL +# define ata66_amd74xx NULL +# define ide_init_amd74xx IDE_NO_DRIVER +# define ide_dmacapable_amd74xx NULL #endif #ifdef CONFIG_BLK_DEV_CMD64X -extern unsigned int pci_init_cmd64x(struct pci_dev *, const char *); +extern unsigned int pci_init_cmd64x(struct pci_dev *); extern unsigned int ata66_cmd64x(ide_hwif_t *); extern void ide_init_cmd64x(ide_hwif_t *); extern void ide_dmacapable_cmd64x(ide_hwif_t *, unsigned long); -#define PCI_CMD64X &pci_init_cmd64x -#define ATA66_CMD64X &ata66_cmd64x -#define INIT_CMD64X &ide_init_cmd64x #else -#define PCI_CMD64X NULL -#define ATA66_CMD64X NULL -#ifdef __sparc_v9__ -#define INIT_CMD64X IDE_IGNORE -#else -#define INIT_CMD64X IDE_NO_DRIVER -#endif +# define pci_init_cmd64x NULL +# define ata66_cmd64x NULL +# ifdef __sparc_v9__ +# define ide_init_cmd64x IDE_IGNORE +# else +# define ide_init_cmd64x IDE_NO_DRIVER +# endif #endif #ifdef CONFIG_BLK_DEV_CY82C693 -extern unsigned int pci_init_cy82c693(struct pci_dev *, const char *); +extern unsigned int pci_init_cy82c693(struct pci_dev *); extern void ide_init_cy82c693(ide_hwif_t *); -#define PCI_CY82C693 &pci_init_cy82c693 -#define INIT_CY82C693 &ide_init_cy82c693 #else -#define PCI_CY82C693 NULL -#define INIT_CY82C693 IDE_NO_DRIVER +# define pci_init_cy82c693 NULL +# define ide_init_cy82c693 IDE_NO_DRIVER #endif #ifdef CONFIG_BLK_DEV_CS5530 -extern unsigned int pci_init_cs5530(struct pci_dev *, const char *); +extern unsigned int pci_init_cs5530(struct pci_dev *); extern void ide_init_cs5530(ide_hwif_t *); -#define PCI_CS5530 &pci_init_cs5530 -#define INIT_CS5530 &ide_init_cs5530 #else -#define PCI_CS5530 NULL -#define INIT_CS5530 IDE_NO_DRIVER +# define pci_init_cs5530 NULL +# define ide_init_cs5530 IDE_NO_DRIVER #endif #ifdef CONFIG_BLK_DEV_HPT34X -extern unsigned int pci_init_hpt34x(struct pci_dev *, const char *); +extern unsigned int pci_init_hpt34x(struct pci_dev *); extern void ide_init_hpt34x(ide_hwif_t *); -#define PCI_HPT34X &pci_init_hpt34x -#define INIT_HPT34X &ide_init_hpt34x #else -#define PCI_HPT34X NULL -#define INIT_HPT34X IDE_IGNORE +# define pci_init_hpt34x NULL +# define ide_init_hpt34x IDE_IGNORE #endif #ifdef CONFIG_BLK_DEV_HPT366 extern byte hpt363_shared_irq; extern byte hpt363_shared_pin; -extern unsigned int pci_init_hpt366(struct pci_dev *, const char *); + +extern unsigned int pci_init_hpt366(struct pci_dev *); extern unsigned int ata66_hpt366(ide_hwif_t *); extern void ide_init_hpt366(ide_hwif_t *); extern void ide_dmacapable_hpt366(ide_hwif_t *, unsigned long); -#define PCI_HPT366 &pci_init_hpt366 -#define ATA66_HPT366 &ata66_hpt366 -#define INIT_HPT366 &ide_init_hpt366 -#define DMA_HPT366 &ide_dmacapable_hpt366 #else static byte hpt363_shared_irq; static byte hpt363_shared_pin; -#define PCI_HPT366 NULL -#define ATA66_HPT366 NULL -#define INIT_HPT366 IDE_NO_DRIVER -#define DMA_HPT366 NULL + +# define pci_init_hpt366 NULL +# define ata66_hpt366 NULL +# define ide_init_hpt366 IDE_NO_DRIVER +# define ide_dmacapable_hpt366 NULL #endif #ifdef CONFIG_BLK_DEV_NS87415 extern void ide_init_ns87415(ide_hwif_t *); -#define INIT_NS87415 &ide_init_ns87415 #else -#define INIT_NS87415 IDE_IGNORE +# define ide_init_ns87415 IDE_IGNORE #endif #ifdef CONFIG_BLK_DEV_OPTI621 extern void ide_init_opti621(ide_hwif_t *); -#define INIT_OPTI621 &ide_init_opti621 #else -#define INIT_OPTI621 IDE_NO_DRIVER +# define ide_init_opti621 IDE_NO_DRIVER #endif #ifdef CONFIG_BLK_DEV_PDC_ADMA -extern unsigned int pci_init_pdcadma(struct pci_dev *, const char *); +extern unsigned int pci_init_pdcadma(struct pci_dev *); extern unsigned int ata66_pdcadma(ide_hwif_t *); extern void ide_init_pdcadma(ide_hwif_t *); extern void ide_dmacapable_pdcadma(ide_hwif_t *, unsigned long); -#define PCI_PDCADMA &pci_init_pdcadma -#define ATA66_PDCADMA &ata66_pdcadma -#define INIT_PDCADMA &ide_init_pdcadma -#define DMA_PDCADMA &ide_dmacapable_pdcadma #else -#define PCI_PDCADMA IDE_IGNORE -#define ATA66_PDCADMA IDE_IGNORE -#define INIT_PDCADMA IDE_IGNORE -#define DMA_PDCADMA IDE_IGNORE +# define pci_init_pdcadma NULL +# define ata66_pdcadma NULL +# define ide_init_pdcadma IDE_IGNORE +# define ide_dmacapable_pdcadma NULL #endif #ifdef CONFIG_BLK_DEV_PDC202XX -extern unsigned int pci_init_pdc202xx(struct pci_dev *, const char *); +extern unsigned int pci_init_pdc202xx(struct pci_dev *); extern unsigned int ata66_pdc202xx(ide_hwif_t *); extern void ide_init_pdc202xx(ide_hwif_t *); -#define PCI_PDC202XX &pci_init_pdc202xx -#define ATA66_PDC202XX &ata66_pdc202xx -#define INIT_PDC202XX &ide_init_pdc202xx #else -#define PCI_PDC202XX IDE_IGNORE -#define ATA66_PDC202XX IDE_IGNORE -#define INIT_PDC202XX IDE_IGNORE +# define pci_init_pdc202xx NULL +# define ata66_pdc202xx NULL +# define ide_init_pdc202xx IDE_IGNORE #endif #ifdef CONFIG_BLK_DEV_PIIX -extern unsigned int pci_init_piix(struct pci_dev *, const char *); +extern unsigned int pci_init_piix(struct pci_dev *); extern unsigned int ata66_piix(ide_hwif_t *); extern void ide_init_piix(ide_hwif_t *); -#define PCI_PIIX &pci_init_piix -#define ATA66_PIIX &ata66_piix -#define INIT_PIIX &ide_init_piix #else -#define PCI_PIIX NULL -#define ATA66_PIIX NULL -#define INIT_PIIX IDE_NO_DRIVER +# define pci_init_piix NULL +# define ata66_piix NULL +# define ide_init_piix IDE_NO_DRIVER #endif #ifdef CONFIG_BLK_DEV_IT8172 -extern unsigned int pci_init_it8172(struct pci_dev *, const char *); +extern unsigned int pci_init_it8172(struct pci_dev *); + +/* We assume that this function has not been added to the global setup lists + * due to a patch merge error. + */ extern unsigned int ata66_it8172(ide_hwif_t *); extern void ide_init_it8172(ide_hwif_t *); -#define PCI_IT8172 &pci_init_it8172 -#define INIT_IT8172 &ide_init_it8172 #else -#define PCI_IT8172 NULL -#define ATA66_IT8172 NULL -#define INIT_IT8172 IDE_NO_DRIVER +# define pci_init_it8172 NULL +# define ata66_it8172 NULL +# define ide_init_it8172 IDE_NO_DRIVER #endif #ifdef CONFIG_BLK_DEV_RZ1000 extern void ide_init_rz1000(ide_hwif_t *); -#define INIT_RZ1000 &ide_init_rz1000 #else -#define INIT_RZ1000 IDE_IGNORE +# define ide_init_rz1000 IDE_IGNORE #endif -#define INIT_SAMURAI NULL - #ifdef CONFIG_BLK_DEV_SVWKS -extern unsigned int pci_init_svwks(struct pci_dev *, const char *); +extern unsigned int pci_init_svwks(struct pci_dev *); extern unsigned int ata66_svwks(ide_hwif_t *); extern void ide_init_svwks(ide_hwif_t *); -#define PCI_SVWKS &pci_init_svwks -#define ATA66_SVWKS &ata66_svwks -#define INIT_SVWKS &ide_init_svwks #else -#define PCI_SVWKS NULL -#define ATA66_SVWKS NULL -#define INIT_SVWKS IDE_NO_DRIVER +# define pci_init_svwks NULL +# define ata66_svwks NULL +# define ide_init_svwks IDE_NO_DRIVER #endif #ifdef CONFIG_BLK_DEV_SIS5513 -extern unsigned int pci_init_sis5513(struct pci_dev *, const char *); +extern unsigned int pci_init_sis5513(struct pci_dev *); extern unsigned int ata66_sis5513(ide_hwif_t *); extern void ide_init_sis5513(ide_hwif_t *); -#define PCI_SIS5513 &pci_init_sis5513 -#define ATA66_SIS5513 &ata66_sis5513 -#define INIT_SIS5513 &ide_init_sis5513 #else -#define PCI_SIS5513 NULL -#define ATA66_SIS5513 NULL -#define INIT_SIS5513 IDE_NO_DRIVER +# define pci_init_sis5513 NULL +# define ata66_sis5513 NULL +# define ide_init_sis5513 IDE_NO_DRIVER #endif #ifdef CONFIG_BLK_DEV_SLC90E66 -extern unsigned int pci_init_slc90e66(struct pci_dev *, const char *); +extern unsigned int pci_init_slc90e66(struct pci_dev *); extern unsigned int ata66_slc90e66(ide_hwif_t *); extern void ide_init_slc90e66(ide_hwif_t *); -#define PCI_SLC90E66 &pci_init_slc90e66 -#define ATA66_SLC90E66 &ata66_slc90e66 -#define INIT_SLC90E66 &ide_init_slc90e66 #else -#define PCI_SLC90E66 NULL -#define ATA66_SLC90E66 NULL -#define INIT_SLC90E66 IDE_NO_DRIVER +# define pci_init_slc90e66 NULL +# define ata66_slc90e66 NULL +# define ide_init_slc90e66 IDE_NO_DRIVER #endif #ifdef CONFIG_BLK_DEV_SL82C105 -extern unsigned int pci_init_sl82c105(struct pci_dev *, const char *); +extern unsigned int pci_init_sl82c105(struct pci_dev *); extern void dma_init_sl82c105(ide_hwif_t *, unsigned long); extern void ide_init_sl82c105(ide_hwif_t *); -#define PCI_W82C105 &pci_init_sl82c105 -#define DMA_W82C105 &dma_init_sl82c105 -#define INIT_W82C105 &ide_init_sl82c105 #else -#define PCI_W82C105 NULL -#define DMA_W82C105 NULL -#define INIT_W82C105 IDE_IGNORE +# define pci_init_sl82c105 NULL +# define dma_init_sl82c105 NULL +# define ide_init_sl82c105 IDE_IGNORE #endif #ifdef CONFIG_BLK_DEV_TRM290 extern void ide_init_trm290(ide_hwif_t *); -#define INIT_TRM290 &ide_init_trm290 #else -#define INIT_TRM290 IDE_IGNORE +# define ide_init_trm290 IDE_IGNORE #endif #ifdef CONFIG_BLK_DEV_VIA82CXXX -extern unsigned int pci_init_via82cxxx(struct pci_dev *, const char *); +extern unsigned int pci_init_via82cxxx(struct pci_dev *); extern unsigned int ata66_via82cxxx(ide_hwif_t *); extern void ide_init_via82cxxx(ide_hwif_t *); extern void ide_dmacapable_via82cxxx(ide_hwif_t *, unsigned long); -#define PCI_VIA82CXXX &pci_init_via82cxxx -#define ATA66_VIA82CXXX &ata66_via82cxxx -#define INIT_VIA82CXXX &ide_init_via82cxxx -#define DMA_VIA82CXXX &ide_dmacapable_via82cxxx #else -#define PCI_VIA82CXXX NULL -#define ATA66_VIA82CXXX NULL -#define INIT_VIA82CXXX IDE_NO_DRIVER -#define DMA_VIA82CXXX NULL +# define pci_init_via82cxxx NULL +# define ata66_via82cxxx NULL +# define ide_init_via82cxxx IDE_NO_DRIVER +# define ide_dmacapable_via82cxxx NULL #endif typedef struct ide_pci_enablebit_s { @@ -374,115 +261,120 @@ typedef struct ide_pci_enablebit_s { } ide_pci_enablebit_t; typedef struct ide_pci_device_s { - ide_pci_devid_t devid; - char *name; - unsigned int (*init_chipset)(struct pci_dev *dev, const char *name); + unsigned short vendor; + unsigned short device; + unsigned int (*init_chipset)(struct pci_dev *dev); unsigned int (*ata66_check)(ide_hwif_t *hwif); - void (*init_hwif)(ide_hwif_t *hwif); + void (*init_hwif)(ide_hwif_t *hwif); void (*dma_init)(ide_hwif_t *hwif, unsigned long dmabase); ide_pci_enablebit_t enablebits[2]; byte bootable; unsigned int extra; } ide_pci_device_t; -static ide_pci_device_t ide_pci_chipsets[] __initdata = { - {DEVID_PIIXa, "PIIX", NULL, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_PIIXb, "PIIX", NULL, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_MPIIX, "MPIIX", NULL, NULL, INIT_PIIX, NULL, {{0x6D,0x80,0x80}, {0x6F,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_PIIX3, "PIIX3", PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_PIIX4, "PIIX4", PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_ICH0, "ICH0", PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_PIIX4E2, "PIIX4", PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_ICH, "ICH", PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_PIIX4U2, "PIIX4", PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_PIIX4NX, "PIIX4", PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_ICH2, "ICH2", PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_ICH2M, "ICH2-M", PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_ICH3, "ICH3", PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_VIA_IDE, "VIA_IDE", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_MR_IDE, "VP_IDE", PCI_VIA82CXXX, ATA66_VIA82CXXX,INIT_VIA82CXXX, DMA_VIA82CXXX, {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, ON_BOARD, 0 }, - {DEVID_VP_IDE, "VP_IDE", PCI_VIA82CXXX, ATA66_VIA82CXXX,INIT_VIA82CXXX, DMA_VIA82CXXX, {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, ON_BOARD, 0 }, +static ide_pci_device_t pci_chipsets[] __initdata = { + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371FB_0, NULL, NULL, ide_init_piix, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371FB_1, NULL, NULL, ide_init_piix, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371MX, NULL, NULL, ide_init_piix, NULL, {{0x6D,0x80,0x80}, {0x6F,0x80,0x80}}, ON_BOARD, 0 }, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_1, pci_init_piix, NULL, ide_init_piix, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB, pci_init_piix, NULL, ide_init_piix, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_1, pci_init_piix, NULL, ide_init_piix, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_1, pci_init_piix, NULL, ide_init_piix, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_1, pci_init_piix, ata66_piix, ide_init_piix, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82372FB_1, pci_init_piix, ata66_piix, ide_init_piix, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82451NX, pci_init_piix, NULL, ide_init_piix, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_9, pci_init_piix, ata66_piix, ide_init_piix, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_8, pci_init_piix, ata66_piix, ide_init_piix, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_10, pci_init_piix, ata66_piix, ide_init_piix, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C561, NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C576_1, pci_init_via82cxxx, ata66_via82cxxx, ide_init_via82cxxx, ide_dmacapable_via82cxxx, {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, ON_BOARD, 0 }, + {PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1, pci_init_via82cxxx, ata66_via82cxxx, ide_init_via82cxxx, ide_dmacapable_via82cxxx, {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, ON_BOARD, 0 }, #ifdef CONFIG_PDC202XX_FORCE - {DEVID_PDC20246,"PDC20246", PCI_PDC202XX, NULL, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 16 }, - {DEVID_PDC20262,"PDC20262", PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 48 }, - {DEVID_PDC20265,"PDC20265", PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 48 }, - {DEVID_PDC20267,"PDC20267", PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 48 }, + {PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20246, pci_init_pdc202xx, NULL, ide_init_pdc202xx, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 16 }, + {PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20262, pci_init_pdc202xx, ata66_pdc202xx, ide_init_pdc202xx, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 48 }, + {PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20265, pci_init_pdc202xx, ata66_pdc202xx, ide_init_pdc202xx, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 48 }, + {PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20267, pci_init_pdc202xx, ata66_pdc202xx, ide_init_pdc202xx, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 48 }, #else /* !CONFIG_PDC202XX_FORCE */ - {DEVID_PDC20246,"PDC20246", PCI_PDC202XX, NULL, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 16 }, - {DEVID_PDC20262,"PDC20262", PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 48 }, - {DEVID_PDC20265,"PDC20265", PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 48 }, - {DEVID_PDC20267,"PDC20267", PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 48 }, + {PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20246, pci_init_pdc202xx, NULL, ide_init_pdc202xx, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 16 }, + {PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20262, pci_init_pdc202xx, ata66_pdc202xx, ide_init_pdc202xx, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 48 }, + {PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20265, pci_init_pdc202xx, ata66_pdc202xx, ide_init_pdc202xx, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 48 }, + {PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20267, pci_init_pdc202xx, ata66_pdc202xx, ide_init_pdc202xx, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 48 }, #endif - {DEVID_PDC20268,"PDC20268", PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, + {PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20268, pci_init_pdc202xx, ata66_pdc202xx, ide_init_pdc202xx, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, /* Promise used a different PCI ident for the raid card apparently to try and prevent Linux detecting it and using our own raid code. We want to detect it for the ataraid drivers, so we have to list both here.. */ - {DEVID_PDC20268R,"PDC20270", PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, - {DEVID_PDC20269,"PDC20269", PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, - {DEVID_PDC20275,"PDC20275", PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, - {DEVID_RZ1000, "RZ1000", NULL, NULL, INIT_RZ1000, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_RZ1001, "RZ1001", NULL, NULL, INIT_RZ1000, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_SAMURAI, "SAMURAI", NULL, NULL, INIT_SAMURAI, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_CMD640, "CMD640", NULL, NULL, IDE_IGNORE, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_NS87410, "NS87410", NULL, NULL, NULL, NULL, {{0x43,0x08,0x08}, {0x47,0x08,0x08}}, ON_BOARD, 0 }, - {DEVID_SIS5513, "SIS5513", PCI_SIS5513, ATA66_SIS5513, INIT_SIS5513, NULL, {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, ON_BOARD, 0 }, - {DEVID_CMD643, "CMD643", PCI_CMD64X, NULL, INIT_CMD64X, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_CMD646, "CMD646", PCI_CMD64X, NULL, INIT_CMD64X, NULL, {{0x00,0x00,0x00}, {0x51,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_CMD648, "CMD648", PCI_CMD64X, ATA66_CMD64X, INIT_CMD64X, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_CMD649, "CMD649", PCI_CMD64X, ATA66_CMD64X, INIT_CMD64X, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_CMD680, "CMD680", PCI_CMD64X, ATA66_CMD64X, INIT_CMD64X, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_HT6565, "HT6565", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_OPTI621, "OPTI621", NULL, NULL, INIT_OPTI621, NULL, {{0x45,0x80,0x00}, {0x40,0x08,0x00}}, ON_BOARD, 0 }, - {DEVID_OPTI621X,"OPTI621X", NULL, NULL, INIT_OPTI621, NULL, {{0x45,0x80,0x00}, {0x40,0x08,0x00}}, ON_BOARD, 0 }, - {DEVID_TRM290, "TRM290", NULL, NULL, INIT_TRM290, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_NS87415, "NS87415", NULL, NULL, INIT_NS87415, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_AEC6210, "AEC6210", PCI_AEC62XX, NULL, INIT_AEC62XX, DMA_AEC62XX, {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, OFF_BOARD, 0 }, - {DEVID_AEC6260, "AEC6260", PCI_AEC62XX, ATA66_AEC62XX, INIT_AEC62XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, NEVER_BOARD, 0 }, - {DEVID_AEC6260R,"AEC6260R", PCI_AEC62XX, ATA66_AEC62XX, INIT_AEC62XX, NULL, {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, OFF_BOARD, 0 }, - {DEVID_W82C105, "W82C105", PCI_W82C105, NULL, INIT_W82C105, DMA_W82C105, {{0x40,0x01,0x01}, {0x40,0x10,0x10}}, ON_BOARD, 0 }, - {DEVID_UM8673F, "UM8673F", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_UM8886A, "UM8886A", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_UM8886BF,"UM8886BF", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_HPT34X, "HPT34X", PCI_HPT34X, NULL, INIT_HPT34X, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, NEVER_BOARD, 16 }, - {DEVID_HPT366, "HPT366", PCI_HPT366, ATA66_HPT366, INIT_HPT366, DMA_HPT366, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 240 }, - {DEVID_ALI15X3, "ALI15X3", PCI_ALI15X3, ATA66_ALI15X3, INIT_ALI15X3, DMA_ALI15X3, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_CY82C693,"CY82C693", PCI_CY82C693, NULL, INIT_CY82C693, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_HINT, "HINT_IDE", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_CS5530, "CS5530", PCI_CS5530, NULL, INIT_CS5530, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_AMD7401, "AMD7401", NULL, NULL, NULL, DMA_AMD74XX, {{0x40,0x01,0x01}, {0x40,0x02,0x02}}, ON_BOARD, 0 }, - {DEVID_AMD7409, "AMD7409", PCI_AMD74XX, ATA66_AMD74XX, INIT_AMD74XX, DMA_AMD74XX, {{0x40,0x01,0x01}, {0x40,0x02,0x02}}, ON_BOARD, 0 }, - {DEVID_AMD7411, "AMD7411", PCI_AMD74XX, ATA66_AMD74XX, INIT_AMD74XX, DMA_AMD74XX, {{0x40,0x01,0x01}, {0x40,0x02,0x02}}, ON_BOARD, 0 }, - {DEVID_AMD7441, "AMD7441", PCI_AMD74XX, ATA66_AMD74XX, INIT_AMD74XX, DMA_AMD74XX, {{0x40,0x01,0x01}, {0x40,0x02,0x02}}, ON_BOARD, 0 }, - {DEVID_PDCADMA, "PDCADMA", PCI_PDCADMA, ATA66_PDCADMA, INIT_PDCADMA, DMA_PDCADMA, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, - {DEVID_SLC90E66,"SLC90E66", PCI_SLC90E66, ATA66_SLC90E66, INIT_SLC90E66, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_OSB4, "ServerWorks OSB4", PCI_SVWKS, ATA66_SVWKS, INIT_SVWKS, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_CSB5, "ServerWorks CSB5", PCI_SVWKS, ATA66_SVWKS, INIT_SVWKS, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_ITE8172G,"IT8172G", PCI_IT8172, NULL, INIT_IT8172, NULL, {{0x00,0x00,0x00}, {0x40,0x00,0x01}}, ON_BOARD, 0 }, - {IDE_PCI_DEVID_NULL, "PCI_IDE", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }}; + {PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20268R, pci_init_pdc202xx, ata66_pdc202xx, ide_init_pdc202xx, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, + {PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20269, pci_init_pdc202xx, ata66_pdc202xx, ide_init_pdc202xx, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, + {PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20275, pci_init_pdc202xx, ata66_pdc202xx, ide_init_pdc202xx, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, + {PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1000, NULL, NULL, ide_init_rz1000, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1001, NULL, NULL, ide_init_rz1000, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_SAMURAI_IDE, NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_640, NULL, NULL, IDE_IGNORE, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87410, NULL, NULL, NULL, NULL, {{0x43,0x08,0x08}, {0x47,0x08,0x08}}, ON_BOARD, 0 }, + {PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5513, pci_init_sis5513, ata66_sis5513, ide_init_sis5513, NULL, {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, ON_BOARD, 0 }, + {PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_643, pci_init_cmd64x, NULL, ide_init_cmd64x, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_646, pci_init_cmd64x, NULL, ide_init_cmd64x, NULL, {{0x00,0x00,0x00}, {0x51,0x80,0x80}}, ON_BOARD, 0 }, + {PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_648, pci_init_cmd64x, ata66_cmd64x, ide_init_cmd64x, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_649, pci_init_cmd64x, ata66_cmd64x, ide_init_cmd64x, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_680, pci_init_cmd64x, ata66_cmd64x, ide_init_cmd64x, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {PCI_VENDOR_ID_HOLTEK, PCI_DEVICE_ID_HOLTEK_6565, NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C621, NULL, NULL, ide_init_opti621, NULL, {{0x45,0x80,0x00}, {0x40,0x08,0x00}}, ON_BOARD, 0 }, + {PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C825, NULL, NULL, ide_init_opti621, NULL, {{0x45,0x80,0x00}, {0x40,0x08,0x00}}, ON_BOARD, 0 }, + {PCI_VENDOR_ID_TEKRAM, PCI_DEVICE_ID_TEKRAM_DC290, NULL, NULL, ide_init_trm290, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87415, NULL, NULL, ide_init_ns87415, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP850UF, pci_init_aec62xx, NULL, ide_init_aec62xx, ide_dmacapable_aec62xx, {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, OFF_BOARD, 0 }, + {PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP860, pci_init_aec62xx, ata66_aec62xx, ide_init_aec62xx, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, NEVER_BOARD, 0 }, + {PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP860R, pci_init_aec62xx, ata66_aec62xx, ide_init_aec62xx, NULL, {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, OFF_BOARD, 0 }, + {PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105, pci_init_sl82c105, NULL, ide_init_sl82c105, dma_init_sl82c105, {{0x40,0x01,0x01}, {0x40,0x10,0x10}}, ON_BOARD, 0 }, + {PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8673F, NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886A, NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886BF, NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT343, pci_init_hpt34x, NULL, ide_init_hpt34x, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, NEVER_BOARD, 16 }, + {PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT366, pci_init_hpt366, ata66_hpt366, ide_init_hpt366, ide_dmacapable_hpt366, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 240 }, + {PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5229, pci_init_ali15x3, ata66_ali15x3, ide_init_ali15x3, ide_dmacapable_ali15x3, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {PCI_VENDOR_ID_CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693, pci_init_cy82c693, NULL, ide_init_cy82c693, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {PCI_VENDOR_ID_HINT, PCI_DEVICE_ID_HINT, NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_IDE, pci_init_cs5530, NULL, ide_init_cs5530, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_COBRA_7401, NULL, NULL, NULL, ide_dmacapable_amd74xx, {{0x40,0x01,0x01}, {0x40,0x02,0x02}}, ON_BOARD, 0 }, + {PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7409, pci_init_amd74xx, ata66_amd74xx, ide_init_amd74xx, ide_dmacapable_amd74xx, {{0x40,0x01,0x01}, {0x40,0x02,0x02}}, ON_BOARD, 0 }, + {PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7411, pci_init_amd74xx, ata66_amd74xx, ide_init_amd74xx, ide_dmacapable_amd74xx, {{0x40,0x01,0x01}, {0x40,0x02,0x02}}, ON_BOARD, 0 }, + {PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7441, pci_init_amd74xx, ata66_amd74xx, ide_init_amd74xx, ide_dmacapable_amd74xx, {{0x40,0x01,0x01}, {0x40,0x02,0x02}}, ON_BOARD, 0 }, + {PCI_VENDOR_ID_PDC, PCI_DEVICE_ID_PDC_1841, pci_init_pdcadma, ata66_pdcadma, ide_init_pdcadma, ide_dmacapable_pdcadma, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, + {PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_1, pci_init_slc90e66, ata66_slc90e66, ide_init_slc90e66, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4IDE, pci_init_svwks, ata66_svwks, ide_init_svwks, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, pci_init_svwks, ata66_svwks, ide_init_svwks, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_IT8172G, pci_init_it8172, NULL, ide_init_it8172, NULL, {{0x00,0x00,0x00}, {0x40,0x00,0x01}}, ON_BOARD, 0 }, + {0, 0, NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }}; /* * This allows offboard ide-pci cards the enable a BIOS, verify interrupt * settings of split-mirror pci-config space, place chipset into init-mode, * and/or preserve an interrupt if the card is not native ide support. */ -static unsigned int __init ide_special_settings (struct pci_dev *dev, const char *name) +static unsigned int __init trust_pci_irq(struct pci_dev *dev) { - switch(dev->device) { - case PCI_DEVICE_ID_TTI_HPT366: - case PCI_DEVICE_ID_PROMISE_20246: - case PCI_DEVICE_ID_PROMISE_20262: - case PCI_DEVICE_ID_PROMISE_20265: - case PCI_DEVICE_ID_PROMISE_20267: - case PCI_DEVICE_ID_PROMISE_20268: - case PCI_DEVICE_ID_PROMISE_20268R: - case PCI_DEVICE_ID_PROMISE_20269: - case PCI_DEVICE_ID_PROMISE_20275: - case PCI_DEVICE_ID_ARTOP_ATP850UF: - case PCI_DEVICE_ID_ARTOP_ATP860: - case PCI_DEVICE_ID_ARTOP_ATP860R: - return dev->irq; - default: - break; + if (dev->vendor == PCI_VENDOR_ID_TTI && dev->device == PCI_DEVICE_ID_TTI_HPT366) + return dev->irq; + else if (dev->vendor == PCI_VENDOR_ID_PROMISE) { + switch(dev->device) { + case PCI_DEVICE_ID_PROMISE_20246: + case PCI_DEVICE_ID_PROMISE_20262: + case PCI_DEVICE_ID_PROMISE_20265: + case PCI_DEVICE_ID_PROMISE_20267: + case PCI_DEVICE_ID_PROMISE_20268: + case PCI_DEVICE_ID_PROMISE_20268R: + case PCI_DEVICE_ID_PROMISE_20269: + case PCI_DEVICE_ID_PROMISE_20275: + return dev->irq; + } + } else if (dev->vendor == PCI_VENDOR_ID_ARTOP) { + switch(dev->device) { + case PCI_DEVICE_ID_ARTOP_ATP850UF: + case PCI_DEVICE_ID_ARTOP_ATP860: + case PCI_DEVICE_ID_ARTOP_ATP860R: + return dev->irq; + } } return 0; } @@ -491,7 +383,7 @@ static unsigned int __init ide_special_settings (struct pci_dev *dev, const char * Match a PCI IDE port against an entry in ide_hwifs[], * based on io_base port if possible. */ -static ide_hwif_t __init *ide_match_hwif (unsigned long io_base, byte bootable, const char *name) +static ide_hwif_t __init *lookup_hwif (unsigned long io_base, byte bootable, const char *name) { int h; ide_hwif_t *hwif; @@ -553,7 +445,7 @@ static ide_hwif_t __init *ide_match_hwif (unsigned long io_base, byte bootable, return NULL; } -static int __init ide_setup_pci_baseregs (struct pci_dev *dev, const char *name) +static int __init setup_pci_baseregs (struct pci_dev *dev, const char *name) { byte reg, progif = 0; @@ -566,7 +458,7 @@ static int __init ide_setup_pci_baseregs (struct pci_dev *dev, const char *name) return 1; } printk("%s: placing both ports into native PCI mode\n", name); - (void) pci_write_config_byte(dev, PCI_CLASS_PROG, progif|5); + pci_write_config_byte(dev, PCI_CLASS_PROG, progif|5); if (pci_read_config_byte(dev, PCI_CLASS_PROG, &progif) || (progif & 5) != 5) { printk("%s: rewrite of PROGIF failed, wanted 0x%04x, got 0x%04x\n", name, progif|5, progif); return 1; @@ -588,23 +480,211 @@ static int __init ide_setup_pci_baseregs (struct pci_dev *dev, const char *name) } /* - * ide_setup_pci_device() looks at the primary/secondary interfaces - * on a PCI IDE device and, if they are enabled, prepares the IDE driver - * for use with them. This generic code works for most PCI chipsets. + * Setup a particular port on an ATA host controller. * - * One thing that is not standardized is the location of the - * primary/secondary interface "enable/disable" bits. For chipsets that - * we "know" about, this information is in the ide_pci_device_t struct; - * for all other chipsets, we just assume both interfaces are enabled. + * This get's called once for the master and for the slave interface. */ -static void __init ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d) +static int __init setup_host_channel(struct pci_dev *dev, + ide_pci_device_t *d, + int port, + u8 class_rev, + int pciirq, ide_hwif_t **mate, + int autodma, + unsigned short *pcicmd) { - unsigned int port, at_least_one_hwif_enabled = 0, autodma = 0, pciirq = 0; - unsigned short pcicmd = 0, tried_config = 0; - byte tmp = 0; - ide_hwif_t *hwif, *mate = NULL; + unsigned long base = 0; + unsigned long ctl = 0; + ide_pci_enablebit_t *e = &(d->enablebits[port]); + ide_hwif_t *hwif; + + u8 tmp; + if (port == 1) { + + /* If this is a Promise FakeRaid controller, the 2nd controller + * will be marked as disabled while it is actually there and + * enabled by the bios for raid purposes. Skip the normal "is + * it enabled" test for those. + */ + if ((d->vendor == PCI_VENDOR_ID_PROMISE && d->device == PCI_DEVICE_ID_PROMISE_20265) || + (d->vendor == PCI_VENDOR_ID_PROMISE && d->device == PCI_DEVICE_ID_PROMISE_20262)) + goto controller_ok; + } + + /* Test whatever the port is enabled. + */ + + if (e->reg) { + if (pci_read_config_byte(dev, e->reg, &tmp)) + return 0; /* error! */ + if ((tmp & e->mask) != e->val) + return 0; + } + + if (port == 1) { + /* Nothing to be done for the second port. */ + if ((d->vendor == PCI_VENDOR_ID_TTI && d->device == PCI_DEVICE_ID_TTI_HPT366) + && (class_rev < 0x03)) + return 0; + } +controller_ok: + if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE || (dev->class & (port ? 4 : 1)) != 0) { + ctl = dev->resource[(2 * port) + 1].start; + base = dev->resource[2 * port].start; + if (!(ctl & PCI_BASE_ADDRESS_IO_MASK) || !(base & PCI_BASE_ADDRESS_IO_MASK)) { + printk(KERN_WARNING "%s: error: IO reported as MEM by BIOS!\n", dev->name); + /* try it with the default values */ + ctl = 0; + base = 0; + } + } + if (ctl && !base) { + printk(KERN_WARNING "%s: error: missing MEM base info from BIOS!\n", dev->name); + /* we will still try to get along with the default */ + } + if (base && !ctl) { + printk(KERN_WARNING "%s: error: missing IO base info from BIOS!\n", dev->name); + /* we will still try to get along with the default */ + } + + /* Fill in the default values: */ + if (!ctl) + ctl = port ? 0x374 : 0x3f4; + if (!base) + base = port ? 0x170 : 0x1f0; + + if ((hwif = lookup_hwif(base, d->bootable, dev->name)) == NULL) + return -ENOMEM; /* no room in ide_hwifs[] */ + + if (hwif->io_ports[IDE_DATA_OFFSET] != base) { + ide_init_hwif_ports(&hwif->hw, base, (ctl | 2), NULL); + memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports)); + hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET]; + } + + hwif->chipset = ide_pci; + hwif->pci_dev = dev; + hwif->channel = port; + if (!hwif->irq) + hwif->irq = pciirq; + + if (*mate) { + hwif->mate = *mate; + (*mate)->mate = hwif; + if (d->vendor == PCI_VENDOR_ID_ARTOP && d->device == PCI_DEVICE_ID_ARTOP_ATP850UF) { + hwif->serialized = 1; + (*mate)->serialized = 1; + } + } + + if ((d->vendor == PCI_VENDOR_ID_UMC && d->device == PCI_DEVICE_ID_UMC_UM8886A) || + (d->vendor == PCI_VENDOR_ID_UMC && d->device == PCI_DEVICE_ID_UMC_UM8886BF) || + (d->vendor == PCI_VENDOR_ID_UMC && d->device == PCI_DEVICE_ID_UMC_UM8673F)) { + + /* Fixed IRQ wiring */ + hwif->irq = hwif->channel ? 15 : 14; + goto no_dma; + } + if ((d->vendor == PCI_VENDOR_ID_INTEL && d->device == PCI_DEVICE_ID_INTEL_82371MX) || + (d->vendor == PCI_VENDOR_ID_PDC && d->device == PCI_DEVICE_ID_PDC_1841)) + goto no_dma; + + /* Check whatever this interface is UDMA4 mode capable. */ + if (hwif->udma_four) { + printk("%s: warning: ATA-66/100 forced bit set!\n", dev->name); + } else { + if (d->ata66_check) + hwif->udma_four = d->ata66_check(hwif); + } +#ifdef CONFIG_BLK_DEV_IDEDMA + if ((d->vendor == PCI_VENDOR_ID_SI && d->device == PCI_DEVICE_ID_SI_5513) || + (d->vendor == PCI_VENDOR_ID_ARTOP && d->device == PCI_DEVICE_ID_ARTOP_ATP860) || + (d->vendor == PCI_VENDOR_ID_INTEL && d->device == PCI_DEVICE_ID_INTEL_82451NX) || + (d->vendor == PCI_VENDOR_ID_TTI && d->device == PCI_DEVICE_ID_TTI_HPT343) || + (d->vendor == PCI_VENDOR_ID_VIA && d->device == PCI_DEVICE_ID_VIA_82C561) || + (d->vendor == PCI_VENDOR_ID_VIA && d->device == PCI_DEVICE_ID_VIA_82C576_1) || + (d->vendor == PCI_VENDOR_ID_VIA && d->device == PCI_DEVICE_ID_VIA_82C586_1)) + autodma = 0; + + if (autodma) + hwif->autodma = 1; + + if ((d->vendor == PCI_VENDOR_ID_PROMISE && d->device == PCI_DEVICE_ID_PROMISE_20246) || + (d->vendor == PCI_VENDOR_ID_PROMISE && d->device == PCI_DEVICE_ID_PROMISE_20262) || + (d->vendor == PCI_VENDOR_ID_PROMISE && d->device == PCI_DEVICE_ID_PROMISE_20265) || + (d->vendor == PCI_VENDOR_ID_PROMISE && d->device == PCI_DEVICE_ID_PROMISE_20267) || + (d->vendor == PCI_VENDOR_ID_PROMISE && d->device == PCI_DEVICE_ID_PROMISE_20268) || + (d->vendor == PCI_VENDOR_ID_PROMISE && d->device == PCI_DEVICE_ID_PROMISE_20268R) || + (d->vendor == PCI_VENDOR_ID_PROMISE && d->device == PCI_DEVICE_ID_PROMISE_20269) || + (d->vendor == PCI_VENDOR_ID_PROMISE && d->device == PCI_DEVICE_ID_PROMISE_20275) || + (d->vendor == PCI_VENDOR_ID_ARTOP && d->device == PCI_DEVICE_ID_ARTOP_ATP850UF) || + (d->vendor == PCI_VENDOR_ID_ARTOP && d->device == PCI_DEVICE_ID_ARTOP_ATP860) || + (d->vendor == PCI_VENDOR_ID_ARTOP && d->device == PCI_DEVICE_ID_ARTOP_ATP860R) || + (d->vendor == PCI_VENDOR_ID_TTI && d->device == PCI_DEVICE_ID_TTI_HPT343) || + (d->vendor == PCI_VENDOR_ID_TTI && d->device == PCI_DEVICE_ID_TTI_HPT366) || + (d->vendor == PCI_VENDOR_ID_CYRIX && d->device == PCI_DEVICE_ID_CYRIX_5530_IDE) || + (d->vendor == PCI_VENDOR_ID_CONTAQ && d->device == PCI_DEVICE_ID_CONTAQ_82C693) || + (d->vendor == PCI_VENDOR_ID_CMD && d->device == PCI_DEVICE_ID_CMD_646) || + (d->vendor == PCI_VENDOR_ID_CMD && d->device == PCI_DEVICE_ID_CMD_648) || + (d->vendor == PCI_VENDOR_ID_CMD && d->device == PCI_DEVICE_ID_CMD_649) || + (d->vendor == PCI_VENDOR_ID_CMD && d->device == PCI_DEVICE_ID_CMD_680) || + (d->vendor == PCI_VENDOR_ID_SERVERWORKS && d->device == PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) || + ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && (dev->class & 0x80))) { + unsigned long dma_base; + + dma_base = ide_get_or_set_dma_base(hwif, (!*mate && d->extra) ? d->extra : 0, dev->name); + if (dma_base && !(*pcicmd & PCI_COMMAND_MASTER)) { + + /* + * Set up BM-DMA capability (PnP BIOS should have done this already) + */ + if (!(d->vendor == PCI_VENDOR_ID_CYRIX && d->device == PCI_DEVICE_ID_CYRIX_5530_IDE)) + hwif->autodma = 0; /* default DMA off if we had to configure it here */ + pci_write_config_word(dev, PCI_COMMAND, *pcicmd | PCI_COMMAND_MASTER); + if (pci_read_config_word(dev, PCI_COMMAND, pcicmd) || !(*pcicmd & PCI_COMMAND_MASTER)) { + printk("%s: %s error updating PCICMD\n", hwif->name, dev->name); + dma_base = 0; + } + } + if (dma_base) { + if (d->dma_init) + d->dma_init(hwif, dma_base); + else /* FIXME: use a generic device descriptor instead */ + ide_setup_dma(hwif, dma_base, 8); + } else { + printk("%s: %s Bus-Master DMA was disabled by BIOS\n", hwif->name, dev->name); + } + } +#endif +no_dma: + if (d->init_hwif) /* Call chipset-specific routine for each enabled hwif */ + d->init_hwif(hwif); + + *mate = hwif; + + /* we are done */ + + return 0; +} + +/* + * Looks at the primary/secondary chanells on a PCI IDE device and, if they + * are enabled, prepares the IDE driver for use with them. This generic code + * works for most PCI chipsets. + * + * One thing that is not standardized is the location of the primary/secondary + * interface "enable/disable" bits. For chipsets that we "know" about, this + * information is in the ide_pci_device_t struct; for all other chipsets, we + * just assume both interfaces are enabled. + */ + +static void __init setup_pci_device(struct pci_dev *dev, ide_pci_device_t *d) +{ + int autodma = 0; + int pciirq = 0; + unsigned short pcicmd = 0; + unsigned short tried_config = 0; + ide_hwif_t *mate = NULL; unsigned int class_rev; - static int secondpdc = 0; #ifdef CONFIG_IDEDMA_AUTO if (!noautodma) @@ -612,18 +692,18 @@ static void __init ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t * #endif if (d->init_hwif == IDE_NO_DRIVER) { - printk(KERN_WARNING "%s: detected chipset, but driver not compiled in!\n", d->name); + printk(KERN_WARNING "%s: detected chipset, but driver not compiled in!\n", dev->name); d->init_hwif = NULL; } if (pci_enable_device(dev)) { - printk(KERN_WARNING "%s: (ide_setup_pci_device:) Could not enable device.\n", d->name); + printk(KERN_WARNING "%s: Could not enable PCI device.\n", dev->name); return; } check_if_enabled: if (pci_read_config_word(dev, PCI_COMMAND, &pcicmd)) { - printk("%s: error accessing PCI regs\n", d->name); + printk("%s: error accessing PCI regs\n", dev->name); return; } if (!(pcicmd & PCI_COMMAND_IO)) { /* is device disabled? */ @@ -635,42 +715,38 @@ check_if_enabled: * but we'll eventually ignore it again if no drives respond. */ if (tried_config++ - || ide_setup_pci_baseregs(dev, d->name) + || setup_pci_baseregs(dev, dev->name) || pci_write_config_word(dev, PCI_COMMAND, pcicmd | PCI_COMMAND_IO)) { - printk("%s: device disabled (BIOS)\n", d->name); + printk("%s: device disabled (BIOS)\n", dev->name); return; } autodma = 0; /* default DMA off if we had to configure it here */ goto check_if_enabled; } if (tried_config) - printk("%s: device enabled (Linux)\n", d->name); + printk("%s: device enabled (Linux)\n", dev->name); pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); class_rev &= 0xff; - if (IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT34X)) { - /* see comments in hpt34x.c on why..... */ - char *chipset_names[] = {"HPT343", "HPT345"}; - strcpy(d->name, chipset_names[(pcicmd & PCI_COMMAND_MEMORY) ? 1 : 0]); + if (d->vendor == PCI_VENDOR_ID_TTI && PCI_DEVICE_ID_TTI_HPT343) { + /* see comments in hpt34x.c to see why... */ d->bootable = (pcicmd & PCI_COMMAND_MEMORY) ? OFF_BOARD : NEVER_BOARD; } - printk("%s: chipset revision %d\n", d->name, class_rev); + printk("%s: chipset revision %d\n", dev->name, class_rev); /* * Can we trust the reported IRQ? */ pciirq = dev->irq; - - if (dev->class >> 8 == PCI_CLASS_STORAGE_RAID) - { + + if (dev->class >> 8 == PCI_CLASS_STORAGE_RAID) { /* By rights we want to ignore these, but the Promise Fastrak people have some strange ideas about proprietary so we have to act otherwise on those. The supertrak however we need to skip */ - if (IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20265)) - { + if (d->vendor == PCI_VENDOR_ID_PROMISE && d->device == PCI_DEVICE_ID_PROMISE_20265) { printk(KERN_INFO "ide: Found promise 20265 in RAID mode.\n"); if(dev->bus->self && dev->bus->self->vendor == PCI_VENDOR_ID_INTEL && dev->bus->self->device == PCI_DEVICE_ID_INTEL_I960) @@ -679,180 +755,43 @@ check_if_enabled: return; } } - /* Its attached to something else, just a random bridge. + /* Its attached to something else, just a random bridge. Suspect a fastrak and fall through */ } if ((dev->class & ~(0xfa)) != ((PCI_CLASS_STORAGE_IDE << 8) | 5)) { - printk("%s: not 100%% native mode: will probe irqs later\n", d->name); + printk("%s: not 100%% native mode: will probe irqs later\n", dev->name); /* * This allows offboard ide-pci cards the enable a BIOS, * verify interrupt settings of split-mirror pci-config * space, place chipset into init-mode, and/or preserve * an interrupt if the card is not native ide support. */ - pciirq = (d->init_chipset) ? d->init_chipset(dev, d->name) : ide_special_settings(dev, d->name); + if (d->init_chipset) + pciirq = d->init_chipset(dev); + else + pciirq = trust_pci_irq(dev); } else if (tried_config) { - printk("%s: will probe irqs later\n", d->name); + printk("%s: will probe irqs later\n", dev->name); pciirq = 0; } else if (!pciirq) { - printk("%s: bad irq (%d): will probe later\n", d->name, pciirq); + printk("%s: bad irq (%d): will probe later\n", dev->name, pciirq); pciirq = 0; } else { if (d->init_chipset) - (void) d->init_chipset(dev, d->name); + d->init_chipset(dev); #ifdef __sparc__ printk("%s: 100%% native mode on irq %s\n", - d->name, __irq_itoa(pciirq)); + dev->name, __irq_itoa(pciirq)); #else - printk("%s: 100%% native mode on irq %d\n", d->name, pciirq); + printk("%s: 100%% native mode on irq %d\n", dev->name, pciirq); #endif } /* - * Set up the IDE ports + * Set up IDE chanells. First the primary, then the secondary. */ - for (port = 0; port <= 1; ++port) { - unsigned long base = 0, ctl = 0; - ide_pci_enablebit_t *e = &(d->enablebits[port]); - - /* - * If this is a Promise FakeRaid controller, the 2nd controller will be marked as - * disabled while it is actually there and enabled by the bios for raid purposes. - * Skip the normal "is it enabled" test for those. - */ - if ((IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20265)) && (secondpdc++==1) && (port==1) ) - goto controller_ok; - if ((IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20262)) && (secondpdc++==1) && (port==1) ) - goto controller_ok; - - if (e->reg && (pci_read_config_byte(dev, e->reg, &tmp) || (tmp & e->mask) != e->val)) - continue; /* port not enabled */ -controller_ok: - if (IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT366) && (port) && (class_rev < 0x03)) - return; - if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE || (dev->class & (port ? 4 : 1)) != 0) { - ctl = dev->resource[(2*port)+1].start; - base = dev->resource[2*port].start; - if (!(ctl & PCI_BASE_ADDRESS_IO_MASK) || - !(base & PCI_BASE_ADDRESS_IO_MASK)) { - printk("%s: IO baseregs (BIOS) are reported as MEM, report to .\n", d->name); -#if 0 - /* FIXME! This really should check that it really gets the IO/MEM part right! */ - continue; -#endif - } - } - if ((ctl && !base) || (base && !ctl)) { - printk("%s: inconsistent baseregs (BIOS) for port %d, skipping\n", d->name, port); - continue; - } - if (!ctl) - ctl = port ? 0x374 : 0x3f4; /* use default value */ - if (!base) - base = port ? 0x170 : 0x1f0; /* use default value */ - if ((hwif = ide_match_hwif(base, d->bootable, d->name)) == NULL) - continue; /* no room in ide_hwifs[] */ - if (hwif->io_ports[IDE_DATA_OFFSET] != base) { - ide_init_hwif_ports(&hwif->hw, base, (ctl | 2), NULL); - memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports)); - hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET]; - } - hwif->chipset = ide_pci; - hwif->pci_dev = dev; - hwif->pci_devid = d->devid; - hwif->channel = port; - if (!hwif->irq) - hwif->irq = pciirq; - if (mate) { - hwif->mate = mate; - mate->mate = hwif; - if (IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6210)) { - hwif->serialized = 1; - mate->serialized = 1; - } - } - if (IDE_PCI_DEVID_EQ(d->devid, DEVID_UM8886A) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_UM8886BF) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_UM8673F)) { - hwif->irq = hwif->channel ? 15 : 14; - goto bypass_umc_dma; - } - if (IDE_PCI_DEVID_EQ(d->devid, DEVID_MPIIX)) - goto bypass_piix_dma; - if (IDE_PCI_DEVID_EQ(d->devid, DEVID_PDCADMA)) - goto bypass_legacy_dma; - if (hwif->udma_four) { - printk("%s: ATA-66/100 forced bit set (WARNING)!!\n", d->name); - } else { - hwif->udma_four = (d->ata66_check) ? d->ata66_check(hwif) : 0; - } -#ifdef CONFIG_BLK_DEV_IDEDMA - if (IDE_PCI_DEVID_EQ(d->devid, DEVID_SIS5513) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6260) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_PIIX4NX) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT34X) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_VIA_IDE) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_MR_IDE) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_VP_IDE)) - autodma = 0; - if (autodma) - hwif->autodma = 1; - - if (IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20246) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20262) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20265) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20267) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20268) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20268R) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20269) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20275) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6210) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6260) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6260R) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT34X) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT366) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_CS5530) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_CY82C693) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_CMD646) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_CMD648) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_CMD649) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_CMD680) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_OSB4) || - ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && (dev->class & 0x80))) { - unsigned long dma_base = ide_get_or_set_dma_base(hwif, (!mate && d->extra) ? d->extra : 0, d->name); - if (dma_base && !(pcicmd & PCI_COMMAND_MASTER)) { - /* - * Set up BM-DMA capability (PnP BIOS should have done this) - */ - if (!IDE_PCI_DEVID_EQ(d->devid, DEVID_CS5530)) - hwif->autodma = 0; /* default DMA off if we had to configure it here */ - (void) pci_write_config_word(dev, PCI_COMMAND, pcicmd | PCI_COMMAND_MASTER); - if (pci_read_config_word(dev, PCI_COMMAND, &pcicmd) || !(pcicmd & PCI_COMMAND_MASTER)) { - printk("%s: %s error updating PCICMD\n", hwif->name, d->name); - dma_base = 0; - } - } - if (dma_base) { - if (d->dma_init) { - d->dma_init(hwif, dma_base); - } else { - ide_setup_dma(hwif, dma_base, 8); - } - } else { - printk("%s: %s Bus-Master DMA disabled (BIOS)\n", hwif->name, d->name); - } - } -#endif /* CONFIG_BLK_DEV_IDEDMA */ -bypass_legacy_dma: -bypass_piix_dma: -bypass_umc_dma: - if (d->init_hwif) /* Call chipset-specific routine for each enabled hwif */ - d->init_hwif(hwif); - mate = hwif; - at_least_one_hwif_enabled = 1; - } - if (!at_least_one_hwif_enabled) - printk("%s: neither IDE port enabled (BIOS)\n", d->name); + setup_host_channel(dev, d, 0, class_rev, pciirq, &mate, autodma, &pcicmd); + setup_host_channel(dev, d, 1, class_rev, pciirq, &mate, autodma, &pcicmd); } static void __init pdc20270_device_order_fixup (struct pci_dev *dev, ide_pci_device_t *d) @@ -884,13 +823,13 @@ static void __init pdc20270_device_order_fixup (struct pci_dev *dev, ide_pci_dev } } - printk("%s: IDE controller on PCI bus %02x dev %02x\n", d->name, dev->bus->number, dev->devfn); - ide_setup_pci_device(dev, d); + printk("%s: IDE controller on PCI bus %02x dev %02x\n", dev->name, dev->bus->number, dev->devfn); + setup_pci_device(dev, d); if (!dev2) return; d2 = d; - printk("%s: IDE controller on PCI bus %02x dev %02x\n", d2->name, dev2->bus->number, dev2->devfn); - ide_setup_pci_device(dev2, d2); + printk("%s: IDE controller on PCI bus %02x dev %02x\n", dev2->name, dev2->bus->number, dev2->devfn); + setup_pci_device(dev2, d2); } static void __init hpt366_device_order_fixup (struct pci_dev *dev, ide_pci_device_t *d) @@ -899,7 +838,6 @@ static void __init hpt366_device_order_fixup (struct pci_dev *dev, ide_pci_devic ide_pci_device_t *d2; unsigned char pin1 = 0, pin2 = 0; unsigned int class_rev; - char *chipset_names[] = {"HPT366", "HPT366", "HPT368", "HPT370", "HPT370A"}; if (PCI_FUNC(dev->devfn) & 1) return; @@ -907,12 +845,10 @@ static void __init hpt366_device_order_fixup (struct pci_dev *dev, ide_pci_devic pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); class_rev &= 0xff; - strcpy(d->name, chipset_names[class_rev]); - switch(class_rev) { case 4: - case 3: printk("%s: IDE controller on PCI slot %s\n", d->name, dev->slot_name); - ide_setup_pci_device(dev, d); + case 3: printk("%s: IDE controller on PCI slot %s\n", dev->name, dev->slot_name); + setup_pci_device(dev, d); return; default: break; } @@ -929,7 +865,7 @@ static void __init hpt366_device_order_fixup (struct pci_dev *dev, ide_pci_devic hpt363_shared_irq = (dev->irq == dev2->irq) ? 1 : 0; if (hpt363_shared_pin && hpt363_shared_irq) { d->bootable = ON_BOARD; - printk("%s: onboard version of chipset, pin1=%d pin2=%d\n", d->name, pin1, pin2); + printk("%s: onboard version of chipset, pin1=%d pin2=%d\n", dev->name, pin1, pin2); #if 0 /* I forgot why I did this once, but it fixed something. */ pci_write_config_byte(dev2, PCI_INTERRUPT_PIN, dev->irq); @@ -940,48 +876,55 @@ static void __init hpt366_device_order_fixup (struct pci_dev *dev, ide_pci_devic break; } } - printk("%s: IDE controller on PCI slot %s\n", d->name, dev->slot_name); - ide_setup_pci_device(dev, d); + printk("%s: IDE controller on PCI slot %s\n", dev->name, dev->slot_name); + setup_pci_device(dev, d); if (!dev2) return; d2 = d; - printk("%s: IDE controller on PCI slot %s\n", d2->name, dev2->slot_name); - ide_setup_pci_device(dev2, d2); + printk("%s: IDE controller on PCI slot %s\n", dev2->name, dev2->slot_name); + setup_pci_device(dev2, d2); } /* - * ide_scan_pcibus() gets invoked at boot time from ide.c. - * It finds all PCI IDE controllers and calls ide_setup_pci_device for them. + * This finds all PCI IDE controllers and calls appriopriate initialization + * functions for them. */ -void __init ide_scan_pcidev (struct pci_dev *dev) +static void __init ide_scan_pcidev(struct pci_dev *dev) { - ide_pci_devid_t devid; + unsigned short vendor; + unsigned short device; ide_pci_device_t *d; - devid.vid = dev->vendor; - devid.did = dev->device; - for (d = ide_pci_chipsets; d->devid.vid && !IDE_PCI_DEVID_EQ(d->devid, devid); ++d); + vendor = dev->vendor; + device = dev->device; + + /* Look up the chipset information. + */ + d = pci_chipsets; + while (d->vendor && !(d->vendor == vendor && d->device == device)) + ++d; + if (d->init_hwif == IDE_IGNORE) - printk("%s: ignored by ide_scan_pci_device() (uses own driver)\n", d->name); - else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_OPTI621V) && !(PCI_FUNC(dev->devfn) & 1)) + printk("%s: has been ignored PCI bus scan\n", dev->name); + else if ((d->vendor == PCI_VENDOR_ID_OPTI && d->device == PCI_DEVICE_ID_OPTI_82C558) && !(PCI_FUNC(dev->devfn) & 1)) return; - else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_CY82C693) && (!(PCI_FUNC(dev->devfn) & 1) || !((dev->class >> 8) == PCI_CLASS_STORAGE_IDE))) + else if ((d->vendor == PCI_VENDOR_ID_CONTAQ && d->device == PCI_DEVICE_ID_CONTAQ_82C693) && (!(PCI_FUNC(dev->devfn) & 1) || !((dev->class >> 8) == PCI_CLASS_STORAGE_IDE))) return; /* CY82C693 is more than only a IDE controller */ - else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_ITE8172G) && (!(PCI_FUNC(dev->devfn) & 1) || !((dev->class >> 8) == PCI_CLASS_STORAGE_IDE))) + else if ((d->vendor == PCI_VENDOR_ID_ITE && d->device == PCI_DEVICE_ID_ITE_IT8172G) && (!(PCI_FUNC(dev->devfn) & 1) || !((dev->class >> 8) == PCI_CLASS_STORAGE_IDE))) return; /* IT8172G is also more than only an IDE controller */ - else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_UM8886A) && !(PCI_FUNC(dev->devfn) & 1)) + else if ((d->vendor == PCI_VENDOR_ID_UMC && d->device == PCI_DEVICE_ID_UMC_UM8886A) && !(PCI_FUNC(dev->devfn) & 1)) return; /* UM8886A/BF pair */ - else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT366)) + else if ((d->vendor == PCI_VENDOR_ID_TTI && d->device == PCI_DEVICE_ID_TTI_HPT366)) hpt366_device_order_fixup(dev, d); - else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20268R)) + else if (d->vendor == PCI_VENDOR_ID_PROMISE && d->device == PCI_DEVICE_ID_PROMISE_20268R) pdc20270_device_order_fixup(dev, d); - else if (!IDE_PCI_DEVID_EQ(d->devid, IDE_PCI_DEVID_NULL) || (dev->class >> 8) == PCI_CLASS_STORAGE_IDE) { - if (IDE_PCI_DEVID_EQ(d->devid, IDE_PCI_DEVID_NULL)) - printk("%s: unknown IDE controller on PCI slot %s, VID=%04x, DID=%04x\n", - d->name, dev->slot_name, devid.vid, devid.did); + else if (!(d->vendor == 0 && d->device == 0) || (dev->class >> 8) == PCI_CLASS_STORAGE_IDE) { + if (d->vendor == 0 && d->device == 0) + printk("%s: unknown IDE controller on PCI slot %s, vendor=%04x, device=%04x\n", + dev->name, dev->slot_name, vendor, device); else - printk("%s: IDE controller on PCI slot %s\n", d->name, dev->slot_name); - ide_setup_pci_device(dev, d); + printk("%s: IDE controller on PCI slot %s\n", dev->name, dev->slot_name); + setup_pci_device(dev, d); } } diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c index 77af606a4aff..a60eb63a6192 100644 --- a/drivers/ide/ide-proc.c +++ b/drivers/ide/ide-proc.c @@ -127,242 +127,8 @@ extern byte via_proc; int (*via_display_info)(char *, char **, off_t, int) = NULL; #endif /* CONFIG_BLK_DEV_VIA82CXXX */ -static int ide_getxdigit(char c) -{ - int digit; - if (isdigit(c)) - digit = c - '0'; - else if (isxdigit(c)) - digit = tolower(c) - 'a' + 10; - else - digit = -1; - return digit; -} - -static int xx_xx_parse_error (const char *data, unsigned long len, const char *msg) -{ - char errbuf[16]; - int i; - if (len >= sizeof(errbuf)) - len = sizeof(errbuf) - 1; - for (i = 0; i < len; ++i) { - char c = data[i]; - if (!c || c == '\n') - c = '\0'; - else if (iscntrl(c)) - c = '?'; - errbuf[i] = c; - } - errbuf[i] = '\0'; - printk("proc_ide: error: %s: '%s'\n", msg, errbuf); - return -EINVAL; -} - static struct proc_dir_entry * proc_ide_root = NULL; -static int proc_ide_write_config - (struct file *file, const char *buffer, unsigned long count, void *data) -{ - ide_hwif_t *hwif = data; - int for_real = 0; - unsigned long startn = 0, n, flags; - const char *start = NULL, *msg = NULL; - - if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) - return -EACCES; - /* - * Skip over leading whitespace - */ - while (count && isspace(*buffer)) { - --count; - ++buffer; - } - /* - * Do one full pass to verify all parameters, - * then do another to actually write the regs. - */ - save_flags(flags); /* all CPUs */ - do { - const char *p; - if (for_real) { - unsigned long timeout = jiffies + (3 * HZ); - ide_hwgroup_t *mygroup = (ide_hwgroup_t *)(hwif->hwgroup); - ide_hwgroup_t *mategroup = NULL; - if (hwif->mate && hwif->mate->hwgroup) - mategroup = (ide_hwgroup_t *)(hwif->mate->hwgroup); - cli(); /* all CPUs; ensure all writes are done together */ - while (test_bit(IDE_BUSY, &mygroup->flags) || (mategroup && test_bit(IDE_BUSY, &mategroup->flags))) { - sti(); /* all CPUs */ - if (0 < (signed long)(jiffies - timeout)) { - printk("/proc/ide/%s/config: channel(s) busy, cannot write\n", hwif->name); - restore_flags(flags); /* all CPUs */ - return -EBUSY; - } - cli(); /* all CPUs */ - } - } - p = buffer; - n = count; - while (n > 0) { - int d, digits; - unsigned int reg = 0, val = 0, is_pci; - start = p; - startn = n--; - switch (*p++) { - case 'R': is_pci = 0; - break; - case 'P': is_pci = 1; -#ifdef CONFIG_BLK_DEV_IDEPCI - if (hwif->pci_dev && !IDE_PCI_DEVID_EQ(hwif->pci_devid, IDE_PCI_DEVID_NULL)) - break; -#endif /* CONFIG_BLK_DEV_IDEPCI */ - msg = "not a PCI device"; - goto parse_error; - default: msg = "expected 'R' or 'P'"; - goto parse_error; - } - digits = 0; - while (n > 0 && (d = ide_getxdigit(*p)) >= 0) { - reg = (reg << 4) | d; - --n; - ++p; - ++digits; - } - if (!digits || (digits > 4) || (is_pci && reg > 0xff)) { - msg = "bad/missing register number"; - goto parse_error; - } - if (n-- == 0 || *p++ != ':') { - msg = "missing ':'"; - goto parse_error; - } - digits = 0; - while (n > 0 && (d = ide_getxdigit(*p)) >= 0) { - val = (val << 4) | d; - --n; - ++p; - ++digits; - } - if (digits != 2 && digits != 4 && digits != 8) { - msg = "bad data, 2/4/8 digits required"; - goto parse_error; - } - if (n > 0 && !isspace(*p)) { - msg = "expected whitespace after data"; - goto parse_error; - } - while (n > 0 && isspace(*p)) { - --n; - ++p; - } -#ifdef CONFIG_BLK_DEV_IDEPCI - if (is_pci && (reg & ((digits >> 1) - 1))) { - msg = "misaligned access"; - goto parse_error; - } -#endif /* CONFIG_BLK_DEV_IDEPCI */ - if (for_real) { -#if 0 - printk("proc_ide_write_config: type=%c, reg=0x%x, val=0x%x, digits=%d\n", is_pci ? "PCI" : "non-PCI", reg, val, digits); -#endif - if (is_pci) { -#ifdef CONFIG_BLK_DEV_IDEPCI - int rc = 0; - struct pci_dev *dev = hwif->pci_dev; - switch (digits) { - case 2: msg = "byte"; - rc = pci_write_config_byte(dev, reg, val); - break; - case 4: msg = "word"; - rc = pci_write_config_word(dev, reg, val); - break; - case 8: msg = "dword"; - rc = pci_write_config_dword(dev, reg, val); - break; - } - if (rc) { - restore_flags(flags); /* all CPUs */ - printk("proc_ide_write_config: error writing %s at bus %02x dev %02x reg 0x%x value 0x%x\n", - msg, dev->bus->number, dev->devfn, reg, val); - printk("proc_ide_write_config: error %d\n", rc); - return -EIO; - } -#endif /* CONFIG_BLK_DEV_IDEPCI */ - } else { /* not pci */ -#if !defined(__mc68000__) && !defined(CONFIG_APUS) - -/* - * Geert Uytterhoeven - * - * unless you can explain me what it really does. - * On m68k, we don't have outw() and outl() yet, - * and I need a good reason to implement it. - * - * BTW, IMHO the main remaining portability problem with the IDE driver - * is that it mixes IO (ioport) and MMIO (iomem) access on different platforms. - * - * I think all accesses should be done using - * - * ide_in[bwl](ide_device_instance, offset) - * ide_out[bwl](ide_device_instance, value, offset) - * - * so the architecture specific code can #define ide_{in,out}[bwl] to the - * appropriate function. - * - */ - switch (digits) { - case 2: outb(val, reg); - break; - case 4: outw(val, reg); - break; - case 8: outl(val, reg); - break; - } -#endif /* !__mc68000__ && !CONFIG_APUS */ - } - } - } - } while (!for_real++); - restore_flags(flags); /* all CPUs */ - return count; -parse_error: - restore_flags(flags); /* all CPUs */ - printk("parse error\n"); - return xx_xx_parse_error(start, startn, msg); -} - -static int proc_ide_read_config - (char *page, char **start, off_t off, int count, int *eof, void *data) -{ - char *out = page; - int len; - -#ifdef CONFIG_BLK_DEV_IDEPCI - ide_hwif_t *hwif = data; - struct pci_dev *dev = hwif->pci_dev; - if (!IDE_PCI_DEVID_EQ(hwif->pci_devid, IDE_PCI_DEVID_NULL) && dev && dev->bus) { - int reg = 0; - - out += sprintf(out, "pci bus %02x device %02x vid %04x did %04x channel %d\n", - dev->bus->number, dev->devfn, hwif->pci_devid.vid, hwif->pci_devid.did, hwif->channel); - do { - byte val; - int rc = pci_read_config_byte(dev, reg, &val); - if (rc) { - printk("proc_ide_read_config: error %d reading bus %02x dev %02x reg 0x%02x\n", - rc, dev->bus->number, dev->devfn, reg); - out += sprintf(out, "??%c", (++reg & 0xf) ? ' ' : '\n'); - } else - out += sprintf(out, "%02x%c", val, (++reg & 0xf) ? ' ' : '\n'); - } while (reg < 0x100); - } else -#endif /* CONFIG_BLK_DEV_IDEPCI */ - out += sprintf(out, "(none)\n"); - len = out - page; - PROC_IDE_READ_RETURN(page,start,off,count,eof,len); -} - - static int ide_getdigit(char c) { int digit; @@ -785,7 +551,6 @@ void destroy_proc_ide_drives(ide_hwif_t *hwif) static ide_proc_entry_t hwif_entries[] = { { "channel", S_IFREG|S_IRUGO, proc_ide_read_channel, NULL }, - { "config", S_IFREG|S_IRUGO|S_IWUSR,proc_ide_read_config, proc_ide_write_config }, { "mate", S_IFREG|S_IRUGO, proc_ide_read_mate, NULL }, { "model", S_IFREG|S_IRUGO, proc_ide_read_imodel, NULL }, { NULL, 0, NULL, NULL } diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c index b972f0cb58ee..61532dbbefa2 100644 --- a/drivers/ide/ide-taskfile.c +++ b/drivers/ide/ide-taskfile.c @@ -42,6 +42,24 @@ #define DTF(x...) #endif +/* + * for now, taskfile requests are special :/ + */ +static inline char *ide_map_rq(struct request *rq, unsigned long *flags) +{ + if (rq->bio) + return bio_kmap_irq(rq->bio, flags) + ide_rq_offset(rq); + else + return rq->buffer + task_rq_offset(rq); +} + +static inline void ide_unmap_rq(struct request *rq, char *to, + unsigned long *flags) +{ + if (rq->bio) + bio_kunmap_irq(to, flags); +} + inline u32 task_read_24 (ide_drive_t *drive) { return (IN_BYTE(IDE_HCYL_REG)<<16) | @@ -1137,7 +1155,7 @@ ide_startstop_t bio_mulout_intr (ide_drive_t *drive) nsect = mcount; mcount -= nsect; - buffer = ide_map_buffer(rq, &flags); + buffer = bio_kmap_irq(rq->bio, &flags) + ide_rq_offset(rq); rq->sector += nsect; rq->nr_sectors -= nsect; rq->current_nr_sectors -= nsect; @@ -1161,7 +1179,7 @@ ide_startstop_t bio_mulout_intr (ide_drive_t *drive) * re-entering us on the last transfer. */ taskfile_output_data(drive, buffer, nsect * SECTOR_WORDS); - ide_unmap_buffer(buffer, &flags); + bio_kunmap_irq(buffer, &flags); } while (mcount); drive->io_32bit = io_32bit; diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index a34c94881618..ba30830ca97f 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -1781,8 +1781,8 @@ void ide_intr (int irq, void *dev_id, struct pt_regs *regs) * so in that case we just ignore it and hope it goes away. */ #ifdef CONFIG_BLK_DEV_IDEPCI - if (IDE_PCI_DEVID_EQ(hwif->pci_devid, IDE_PCI_DEVID_NULL)) -#endif /* CONFIG_BLK_DEV_IDEPCI */ + if (hwif->pci_dev && !hwif->pci_dev->vendor) +#endif { /* * Probably not a shared PCI interrupt, @@ -1794,7 +1794,7 @@ void ide_intr (int irq, void *dev_id, struct pt_regs *regs) /* * Whack the status register, just in case we have a leftover pending IRQ. */ - (void) IN_BYTE(hwif->io_ports[IDE_STATUS_OFFSET]); + IN_BYTE(hwif->io_ports[IDE_STATUS_OFFSET]); #endif /* CONFIG_BLK_DEV_IDEPCI */ } goto out_lock; @@ -2304,7 +2304,6 @@ void ide_unregister (unsigned int index) hwif->udma_four = old_hwif.udma_four; #ifdef CONFIG_BLK_DEV_IDEPCI hwif->pci_dev = old_hwif.pci_dev; - hwif->pci_devid = old_hwif.pci_devid; #endif /* CONFIG_BLK_DEV_IDEPCI */ hwif->straight8 = old_hwif.straight8; hwif->hwif_data = old_hwif.hwif_data; @@ -2650,61 +2649,6 @@ void ide_delay_50ms (void) #endif /* CONFIG_BLK_DEV_IDECS */ } -int ide_reinit_drive (ide_drive_t *drive) -{ - switch (drive->media) { -#ifdef CONFIG_BLK_DEV_IDECD - case ide_cdrom: - { - extern int ide_cdrom_reinit(ide_drive_t *drive); - if (ide_cdrom_reinit(drive)) - return 1; - break; - } -#endif /* CONFIG_BLK_DEV_IDECD */ -#ifdef CONFIG_BLK_DEV_IDEDISK - case ide_disk: - { - extern int idedisk_reinit(ide_drive_t *drive); - if (idedisk_reinit(drive)) - return 1; - break; - } -#endif /* CONFIG_BLK_DEV_IDEDISK */ -#ifdef CONFIG_BLK_DEV_IDEFLOPPY - case ide_floppy: - { - extern int idefloppy_reinit(ide_drive_t *drive); - if (idefloppy_reinit(drive)) - return 1; - break; - } -#endif /* CONFIG_BLK_DEV_IDEFLOPPY */ -#ifdef CONFIG_BLK_DEV_IDETAPE - case ide_tape: - { - extern int idetape_reinit(ide_drive_t *drive); - if (idetape_reinit(drive)) - return 1; - break; - } -#endif /* CONFIG_BLK_DEV_IDETAPE */ -#ifdef CONFIG_BLK_DEV_IDESCSI -/* - * { - * extern int idescsi_reinit(ide_drive_t *drive); - * if (idescsi_reinit(drive)) - * return 1; - * break; - * } - */ -#endif /* CONFIG_BLK_DEV_IDESCSI */ - default: - return 1; - } - return 0; -} - static int ide_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { @@ -3559,20 +3503,20 @@ void __init ide_init_builtin_drivers (void) * Attempt to match drivers for the available drives */ #ifdef CONFIG_BLK_DEV_IDEDISK - (void) idedisk_init(); + idedisk_init(); #endif /* CONFIG_BLK_DEV_IDEDISK */ #ifdef CONFIG_BLK_DEV_IDECD - (void) ide_cdrom_init(); + ide_cdrom_init(); #endif /* CONFIG_BLK_DEV_IDECD */ #ifdef CONFIG_BLK_DEV_IDETAPE - (void) idetape_init(); + idetape_init(); #endif /* CONFIG_BLK_DEV_IDETAPE */ #ifdef CONFIG_BLK_DEV_IDEFLOPPY - (void) idefloppy_init(); + idefloppy_init(); #endif /* CONFIG_BLK_DEV_IDEFLOPPY */ #ifdef CONFIG_BLK_DEV_IDESCSI #ifdef CONFIG_SCSI - (void) idescsi_init(); + idescsi_init(); #else #warning ide scsi-emulation selected but no SCSI-subsystem in kernel #endif @@ -3672,6 +3616,9 @@ ide_drive_t *ide_scan_devices (byte media, const char *name, ide_driver_t *drive return NULL; } +/* + * This is in fact registering a drive not a driver. + */ int ide_register_subdriver (ide_drive_t *drive, ide_driver_t *driver) { unsigned long flags; @@ -3832,7 +3779,6 @@ EXPORT_SYMBOL(ide_unregister); EXPORT_SYMBOL(ide_setup_ports); EXPORT_SYMBOL(get_info_ptr); EXPORT_SYMBOL(current_capacity); -EXPORT_SYMBOL(ide_reinit_drive); static int ide_notify_reboot (struct notifier_block *this, unsigned long event, void *x) { diff --git a/drivers/ide/it8172.c b/drivers/ide/it8172.c index e40952e085a9..ca28b30bd148 100644 --- a/drivers/ide/it8172.c +++ b/drivers/ide/it8172.c @@ -53,7 +53,6 @@ static int it8172_tune_chipset (ide_drive_t *drive, byte speed); static int it8172_config_drive_for_dma (ide_drive_t *drive); static int it8172_dmaproc(ide_dma_action_t func, ide_drive_t *drive); #endif -unsigned int __init pci_init_it8172 (struct pci_dev *dev, const char *name); void __init ide_init_it8172 (ide_hwif_t *hwif); @@ -232,7 +231,7 @@ static int it8172_dmaproc(ide_dma_action_t func, ide_drive_t *drive) #endif /* defined(CONFIG_BLK_DEV_IDEDMA) && (CONFIG_IT8172_TUNING) */ -unsigned int __init pci_init_it8172 (struct pci_dev *dev, const char *name) +unsigned int __init pci_init_it8172 (struct pci_dev *dev) { unsigned char progif; diff --git a/drivers/ide/pdc202xx.c b/drivers/ide/pdc202xx.c index b614fd319bc6..6931c47b7aaf 100644 --- a/drivers/ide/pdc202xx.c +++ b/drivers/ide/pdc202xx.c @@ -1102,7 +1102,7 @@ static int pdc202xx_tristate (ide_drive_t * drive, int state) return 0; } -unsigned int __init pci_init_pdc202xx (struct pci_dev *dev, const char *name) +unsigned int __init pci_init_pdc202xx(struct pci_dev *dev) { unsigned long high_16 = pci_resource_start(dev, 4); byte udma_speed_flag = IN_BYTE(high_16 + 0x001f); @@ -1112,7 +1112,7 @@ unsigned int __init pci_init_pdc202xx (struct pci_dev *dev, const char *name) if (dev->resource[PCI_ROM_RESOURCE].start) { pci_write_config_dword(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE); - printk("%s: ROM enabled at 0x%08lx\n", name, dev->resource[PCI_ROM_RESOURCE].start); + printk("%s: ROM enabled at 0x%08lx\n", dev->name, dev->resource[PCI_ROM_RESOURCE].start); } switch (dev->device) { @@ -1151,7 +1151,7 @@ unsigned int __init pci_init_pdc202xx (struct pci_dev *dev, const char *name) pci_read_config_byte(dev, (PCI_INTERRUPT_LINE)|0x80, &irq2); /* 0xbc */ if (irq != irq2) { pci_write_config_byte(dev, (PCI_INTERRUPT_LINE)|0x80, irq); /* 0xbc */ - printk("%s: pci-config space interrupt mirror fixed.\n", name); + printk("%s: pci-config space interrupt mirror fixed.\n", dev->name); } } break; @@ -1163,14 +1163,14 @@ unsigned int __init pci_init_pdc202xx (struct pci_dev *dev, const char *name) printk("%s: (U)DMA Burst Bit %sABLED " \ "Primary %s Mode " \ "Secondary %s Mode.\n", - name, + dev->name, (udma_speed_flag & 1) ? "EN" : "DIS", (primary_mode & 1) ? "MASTER" : "PCI", (secondary_mode & 1) ? "MASTER" : "PCI" ); #ifdef CONFIG_PDC202XX_BURST if (!(udma_speed_flag & 1)) { - printk("%s: FORCING BURST BIT 0x%02x -> 0x%02x ", name, udma_speed_flag, (udma_speed_flag|1)); + printk("%s: FORCING BURST BIT 0x%02x -> 0x%02x ", dev->name, udma_speed_flag, (udma_speed_flag|1)); OUT_BYTE(udma_speed_flag|1, high_16 + 0x001f); printk("%sCTIVE\n", (IN_BYTE(high_16 + 0x001f) & 1) ? "A" : "INA"); } @@ -1179,14 +1179,14 @@ unsigned int __init pci_init_pdc202xx (struct pci_dev *dev, const char *name) #ifdef CONFIG_PDC202XX_MASTER if (!(primary_mode & 1)) { printk("%s: FORCING PRIMARY MODE BIT 0x%02x -> 0x%02x ", - name, primary_mode, (primary_mode|1)); + dev->name, primary_mode, (primary_mode|1)); OUT_BYTE(primary_mode|1, high_16 + 0x001a); printk("%s\n", (IN_BYTE(high_16 + 0x001a) & 1) ? "MASTER" : "PCI"); } if (!(secondary_mode & 1)) { printk("%s: FORCING SECONDARY MODE BIT 0x%02x -> 0x%02x ", - name, secondary_mode, (secondary_mode|1)); + dev->name, secondary_mode, (secondary_mode|1)); OUT_BYTE(secondary_mode|1, high_16 + 0x001b); printk("%s\n", (IN_BYTE(high_16 + 0x001b) & 1) ? "MASTER" : "PCI"); } diff --git a/drivers/ide/pdc4030.c b/drivers/ide/pdc4030.c index ea690a7159b8..c1d42562685f 100644 --- a/drivers/ide/pdc4030.c +++ b/drivers/ide/pdc4030.c @@ -332,14 +332,14 @@ read_next: if (nsect > sectors_avail) nsect = sectors_avail; sectors_avail -= nsect; - to = ide_map_buffer(rq, &flags); + to = bio_kmap_irq(rq->bio, &flags) + ide_rq_offset(rq); ata_input_data(drive, to, nsect * SECTOR_WORDS); #ifdef DEBUG_READ printk(KERN_DEBUG "%s: promise_read: sectors(%ld-%ld), " "buf=0x%08lx, rem=%ld\n", drive->name, rq->sector, rq->sector+nsect-1, (unsigned long) to, rq->nr_sectors-nsect); #endif - ide_unmap_buffer(to, &flags); + bio_kunmap_irq(to, &flags); rq->sector += nsect; rq->errors = 0; rq->nr_sectors -= nsect; @@ -437,7 +437,7 @@ int promise_multwrite (ide_drive_t *drive, unsigned int mcount) nsect = mcount; mcount -= nsect; - buffer = ide_map_buffer(rq, &flags); + buffer = bio_kmap_irq(rq->bio, flags) + ide_rq_offset(rq); rq->sector += nsect; rq->nr_sectors -= nsect; rq->current_nr_sectors -= nsect; @@ -461,7 +461,7 @@ int promise_multwrite (ide_drive_t *drive, unsigned int mcount) * re-entering us on the last transfer. */ taskfile_output_data(drive, buffer, nsect<<7); - ide_unmap_buffer(buffer, &flags); + bio_kunmap_irq(buffer, &flags); } while (mcount); return 0; diff --git a/drivers/ide/pdcadma.c b/drivers/ide/pdcadma.c index c699f714ee55..cc6b7af7772f 100644 --- a/drivers/ide/pdcadma.c +++ b/drivers/ide/pdcadma.c @@ -71,7 +71,7 @@ int pdcadma_dmaproc (ide_dma_action_t func, ide_drive_t *drive) } #endif /* CONFIG_BLK_DEV_IDEDMA */ -unsigned int __init pci_init_pdcadma (struct pci_dev *dev, const char *name) +unsigned int __init pci_init_pdcadma(struct pci_dev *dev) { #if defined(DISPLAY_PDCADMA_TIMINGS) && defined(CONFIG_PROC_FS) if (!pdcadma_proc) { diff --git a/drivers/ide/piix.c b/drivers/ide/piix.c index 25025d71f293..c419f70992c6 100644 --- a/drivers/ide/piix.c +++ b/drivers/ide/piix.c @@ -451,7 +451,7 @@ static int piix_dmaproc(ide_dma_action_t func, ide_drive_t *drive) } #endif /* defined(CONFIG_BLK_DEV_IDEDMA) && (CONFIG_PIIX_TUNING) */ -unsigned int __init pci_init_piix (struct pci_dev *dev, const char *name) +unsigned int __init pci_init_piix(struct pci_dev *dev) { #if defined(DISPLAY_PIIX_TIMINGS) && defined(CONFIG_PROC_FS) if (!piix_proc) { diff --git a/drivers/ide/serverworks.c b/drivers/ide/serverworks.c index 8776d20c618f..5c056b4c5ebc 100644 --- a/drivers/ide/serverworks.c +++ b/drivers/ide/serverworks.c @@ -547,7 +547,7 @@ static int svwks_dmaproc(ide_dma_action_t func, ide_drive_t *drive) } #endif /* CONFIG_BLK_DEV_IDEDMA */ -unsigned int __init pci_init_svwks (struct pci_dev *dev, const char *name) +unsigned int __init pci_init_svwks(struct pci_dev *dev) { unsigned int reg; byte btr; diff --git a/drivers/ide/sis5513.c b/drivers/ide/sis5513.c index 53c53a54a36a..7ddcdabf2290 100644 --- a/drivers/ide/sis5513.c +++ b/drivers/ide/sis5513.c @@ -567,7 +567,7 @@ int sis5513_dmaproc (ide_dma_action_t func, ide_drive_t *drive) } #endif /* CONFIG_BLK_DEV_IDEDMA */ -unsigned int __init pci_init_sis5513 (struct pci_dev *dev, const char *name) +unsigned int __init pci_init_sis5513(struct pci_dev *dev) { struct pci_dev *host; int i = 0; diff --git a/drivers/ide/sl82c105.c b/drivers/ide/sl82c105.c index 30bc38167e54..63bc2219421a 100644 --- a/drivers/ide/sl82c105.c +++ b/drivers/ide/sl82c105.c @@ -223,7 +223,7 @@ static unsigned int sl82c105_bridge_revision(struct pci_dev *dev) /* * Enable the PCI device */ -unsigned int __init pci_init_sl82c105(struct pci_dev *dev, const char *msg) +unsigned int __init pci_init_sl82c105(struct pci_dev *dev) { unsigned char ctrl_stat; diff --git a/drivers/ide/slc90e66.c b/drivers/ide/slc90e66.c index 75a15e48d6d9..d9d602b7de4d 100644 --- a/drivers/ide/slc90e66.c +++ b/drivers/ide/slc90e66.c @@ -347,7 +347,7 @@ static int slc90e66_dmaproc(ide_dma_action_t func, ide_drive_t *drive) } #endif /* CONFIG_BLK_DEV_IDEDMA */ -unsigned int __init pci_init_slc90e66 (struct pci_dev *dev, const char *name) +unsigned int __init pci_init_slc90e66(struct pci_dev *dev) { #if defined(DISPLAY_SLC90E66_TIMINGS) && defined(CONFIG_PROC_FS) if (!slc90e66_proc) { diff --git a/drivers/ide/via82cxxx.c b/drivers/ide/via82cxxx.c index e7742397422b..5cea98f02071 100644 --- a/drivers/ide/via82cxxx.c +++ b/drivers/ide/via82cxxx.c @@ -393,7 +393,7 @@ int via82cxxx_dmaproc(ide_dma_action_t func, ide_drive_t *drive) * and initialize its drive independent registers. */ -unsigned int __init pci_init_via82cxxx(struct pci_dev *dev, const char *name) +unsigned int __init pci_init_via82cxxx(struct pci_dev *dev) { struct pci_dev *isa = NULL; unsigned char t, v; diff --git a/include/linux/ide.h b/include/linux/ide.h index 8746e02a9d9a..a72fcbbc051c 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -521,16 +521,6 @@ typedef void (ide_rw_proc_t) (ide_drive_t *, ide_dma_action_t); */ typedef int (ide_busproc_t) (ide_drive_t *, int); -#ifdef CONFIG_BLK_DEV_IDEPCI -typedef struct ide_pci_devid_s { - unsigned short vid; - unsigned short did; -} ide_pci_devid_t; - -#define IDE_PCI_DEVID_NULL ((ide_pci_devid_t){0,0}) -#define IDE_PCI_DEVID_EQ(a,b) (a.vid == b.vid && a.did == b.did) -#endif /* CONFIG_BLK_DEV_IDEPCI */ - typedef struct hwif_s { struct hwif_s *next; /* for linked-list in ide_hwgroup_t */ struct hwgroup_s *hwgroup; /* actually (ide_hwgroup_t *) */ @@ -575,8 +565,7 @@ typedef struct hwif_s { byte channel; /* for dual-port chips: 0=primary, 1=secondary */ #ifdef CONFIG_BLK_DEV_IDEPCI struct pci_dev *pci_dev; /* for pci chipsets */ - ide_pci_devid_t pci_devid; /* for pci chipsets: {VID,DID} */ -#endif /* CONFIG_BLK_DEV_IDEPCI */ +#endif #if (DISK_RECOVERY_TIME > 0) unsigned long last_time; /* time when previous rq was done */ #endif @@ -850,34 +839,6 @@ typedef enum { #define task_rq_offset(rq) \ (((rq)->nr_sectors - (rq)->current_nr_sectors) * SECTOR_SIZE) -extern inline void *ide_map_buffer(struct request *rq, unsigned long *flags) -{ - return bio_kmap_irq(rq->bio, flags) + ide_rq_offset(rq); -} - -extern inline void ide_unmap_buffer(char *buffer, unsigned long *flags) -{ - bio_kunmap_irq(buffer, flags); -} - -/* - * for now, taskfile requests are special :/ - */ -extern inline char *ide_map_rq(struct request *rq, unsigned long *flags) -{ - if (rq->bio) - return ide_map_buffer(rq, flags); - else - return rq->buffer + task_rq_offset(rq); -} - -extern inline void ide_unmap_rq(struct request *rq, char *buf, - unsigned long *flags) -{ - if (rq->bio) - ide_unmap_buffer(buf, flags); -} - /* * This function issues a special IDE device request * onto the request queue. @@ -1027,8 +988,6 @@ void ide_init_subdrivers (void); extern struct block_device_operations ide_fops[]; extern ide_proc_entry_t generic_subdriver_entries[]; -extern int ide_reinit_drive (ide_drive_t *drive); - #ifdef CONFIG_BLK_DEV_IDE /* Probe for devices attached to the systems host controllers. */ @@ -1069,7 +1028,7 @@ extern int ide_replace_subdriver(ide_drive_t *drive, const char *driver); # define OFF_BOARD NEVER_BOARD #endif /* CONFIG_BLK_DEV_OFFBOARD */ -void ide_scan_pcibus (int scan_direction) __init; +void __init ide_scan_pcibus(int scan_direction); #endif #ifdef CONFIG_BLK_DEV_IDEDMA #define BAD_DMA_DRIVE 0 -- cgit v1.2.3 From b62bbbcb76be3e67c17f092cb9f502d92548c14d Mon Sep 17 00:00:00 2001 From: Martin Dalecki Date: Wed, 27 Feb 2002 20:15:30 -0800 Subject: [PATCH] 2.5.6-pre1 IDE clean 13a This is finally moving the ide-pci.c file into a shape where the host chip detection lists can finally be moved to where they belong - into the particular chipset specific files. This is accomplished, by a rather obivous removal of macro magic, which was just making entries to the global device type list nonfunctional, instead of making them conditional on the corresponding CONFIG_BLHA options. The second thing was to add a flag field to the device recognition list, which made it possible to compress many of the multi || chip id conditionals go away. The only other file affected is ide.h - here is the change in the size of the name field, which apparently slipped through ide-clean-12... --- drivers/ide/ide-pci.c | 381 ++++++++++++++++++++------------------------------ include/linux/ide.h | 2 +- 2 files changed, 151 insertions(+), 232 deletions(-) (limited to 'include/linux') diff --git a/drivers/ide/ide-pci.c b/drivers/ide/ide-pci.c index 2727e85cdc1c..f93985160bff 100644 --- a/drivers/ide/ide-pci.c +++ b/drivers/ide/ide-pci.c @@ -44,11 +44,6 @@ extern unsigned int pci_init_aec62xx(struct pci_dev *); extern unsigned int ata66_aec62xx(ide_hwif_t *); extern void ide_init_aec62xx(ide_hwif_t *); extern void ide_dmacapable_aec62xx(ide_hwif_t *, unsigned long); -#else -# define pci_init_aec62xx NULL -# define ata66_aec62xx NULL -# define ide_init_aec62xx IDE_NO_DRIVER -# define ide_dmacapable_aec62xx NULL #endif #ifdef CONFIG_BLK_DEV_ALI15X3 @@ -56,11 +51,6 @@ extern unsigned int pci_init_ali15x3(struct pci_dev *); extern unsigned int ata66_ali15x3(ide_hwif_t *); extern void ide_init_ali15x3(ide_hwif_t *); extern void ide_dmacapable_ali15x3(ide_hwif_t *, unsigned long); -#else -# define pci_init_ali15x3 NULL -# define ata66_ali15x3 NULL -# define ide_init_ali15x3 IDE_NO_DRIVER -# define ide_dmacapable_ali15x3 NULL #endif #ifdef CONFIG_BLK_DEV_AMD74XX @@ -68,11 +58,6 @@ extern unsigned int pci_init_amd74xx(struct pci_dev *); extern unsigned int ata66_amd74xx(ide_hwif_t *); extern void ide_init_amd74xx(ide_hwif_t *); extern void ide_dmacapable_amd74xx(ide_hwif_t *, unsigned long); -#else -# define pci_init_amd74xx NULL -# define ata66_amd74xx NULL -# define ide_init_amd74xx IDE_NO_DRIVER -# define ide_dmacapable_amd74xx NULL #endif #ifdef CONFIG_BLK_DEV_CMD64X @@ -80,38 +65,21 @@ extern unsigned int pci_init_cmd64x(struct pci_dev *); extern unsigned int ata66_cmd64x(ide_hwif_t *); extern void ide_init_cmd64x(ide_hwif_t *); extern void ide_dmacapable_cmd64x(ide_hwif_t *, unsigned long); -#else -# define pci_init_cmd64x NULL -# define ata66_cmd64x NULL -# ifdef __sparc_v9__ -# define ide_init_cmd64x IDE_IGNORE -# else -# define ide_init_cmd64x IDE_NO_DRIVER -# endif #endif #ifdef CONFIG_BLK_DEV_CY82C693 extern unsigned int pci_init_cy82c693(struct pci_dev *); extern void ide_init_cy82c693(ide_hwif_t *); -#else -# define pci_init_cy82c693 NULL -# define ide_init_cy82c693 IDE_NO_DRIVER #endif #ifdef CONFIG_BLK_DEV_CS5530 extern unsigned int pci_init_cs5530(struct pci_dev *); extern void ide_init_cs5530(ide_hwif_t *); -#else -# define pci_init_cs5530 NULL -# define ide_init_cs5530 IDE_NO_DRIVER #endif #ifdef CONFIG_BLK_DEV_HPT34X extern unsigned int pci_init_hpt34x(struct pci_dev *); extern void ide_init_hpt34x(ide_hwif_t *); -#else -# define pci_init_hpt34x NULL -# define ide_init_hpt34x IDE_IGNORE #endif #ifdef CONFIG_BLK_DEV_HPT366 @@ -123,25 +91,17 @@ extern unsigned int ata66_hpt366(ide_hwif_t *); extern void ide_init_hpt366(ide_hwif_t *); extern void ide_dmacapable_hpt366(ide_hwif_t *, unsigned long); #else +/* FIXME: those have to be killed */ static byte hpt363_shared_irq; static byte hpt363_shared_pin; - -# define pci_init_hpt366 NULL -# define ata66_hpt366 NULL -# define ide_init_hpt366 IDE_NO_DRIVER -# define ide_dmacapable_hpt366 NULL #endif #ifdef CONFIG_BLK_DEV_NS87415 extern void ide_init_ns87415(ide_hwif_t *); -#else -# define ide_init_ns87415 IDE_IGNORE #endif #ifdef CONFIG_BLK_DEV_OPTI621 extern void ide_init_opti621(ide_hwif_t *); -#else -# define ide_init_opti621 IDE_NO_DRIVER #endif #ifdef CONFIG_BLK_DEV_PDC_ADMA @@ -149,97 +109,55 @@ extern unsigned int pci_init_pdcadma(struct pci_dev *); extern unsigned int ata66_pdcadma(ide_hwif_t *); extern void ide_init_pdcadma(ide_hwif_t *); extern void ide_dmacapable_pdcadma(ide_hwif_t *, unsigned long); -#else -# define pci_init_pdcadma NULL -# define ata66_pdcadma NULL -# define ide_init_pdcadma IDE_IGNORE -# define ide_dmacapable_pdcadma NULL #endif #ifdef CONFIG_BLK_DEV_PDC202XX extern unsigned int pci_init_pdc202xx(struct pci_dev *); extern unsigned int ata66_pdc202xx(ide_hwif_t *); extern void ide_init_pdc202xx(ide_hwif_t *); -#else -# define pci_init_pdc202xx NULL -# define ata66_pdc202xx NULL -# define ide_init_pdc202xx IDE_IGNORE #endif #ifdef CONFIG_BLK_DEV_PIIX extern unsigned int pci_init_piix(struct pci_dev *); extern unsigned int ata66_piix(ide_hwif_t *); extern void ide_init_piix(ide_hwif_t *); -#else -# define pci_init_piix NULL -# define ata66_piix NULL -# define ide_init_piix IDE_NO_DRIVER #endif #ifdef CONFIG_BLK_DEV_IT8172 extern unsigned int pci_init_it8172(struct pci_dev *); - -/* We assume that this function has not been added to the global setup lists - * due to a patch merge error. - */ -extern unsigned int ata66_it8172(ide_hwif_t *); extern void ide_init_it8172(ide_hwif_t *); -#else -# define pci_init_it8172 NULL -# define ata66_it8172 NULL -# define ide_init_it8172 IDE_NO_DRIVER #endif #ifdef CONFIG_BLK_DEV_RZ1000 extern void ide_init_rz1000(ide_hwif_t *); -#else -# define ide_init_rz1000 IDE_IGNORE #endif #ifdef CONFIG_BLK_DEV_SVWKS extern unsigned int pci_init_svwks(struct pci_dev *); extern unsigned int ata66_svwks(ide_hwif_t *); extern void ide_init_svwks(ide_hwif_t *); -#else -# define pci_init_svwks NULL -# define ata66_svwks NULL -# define ide_init_svwks IDE_NO_DRIVER #endif #ifdef CONFIG_BLK_DEV_SIS5513 extern unsigned int pci_init_sis5513(struct pci_dev *); extern unsigned int ata66_sis5513(ide_hwif_t *); extern void ide_init_sis5513(ide_hwif_t *); -#else -# define pci_init_sis5513 NULL -# define ata66_sis5513 NULL -# define ide_init_sis5513 IDE_NO_DRIVER #endif #ifdef CONFIG_BLK_DEV_SLC90E66 extern unsigned int pci_init_slc90e66(struct pci_dev *); extern unsigned int ata66_slc90e66(ide_hwif_t *); extern void ide_init_slc90e66(ide_hwif_t *); -#else -# define pci_init_slc90e66 NULL -# define ata66_slc90e66 NULL -# define ide_init_slc90e66 IDE_NO_DRIVER #endif #ifdef CONFIG_BLK_DEV_SL82C105 extern unsigned int pci_init_sl82c105(struct pci_dev *); extern void dma_init_sl82c105(ide_hwif_t *, unsigned long); extern void ide_init_sl82c105(ide_hwif_t *); -#else -# define pci_init_sl82c105 NULL -# define dma_init_sl82c105 NULL -# define ide_init_sl82c105 IDE_IGNORE #endif #ifdef CONFIG_BLK_DEV_TRM290 extern void ide_init_trm290(ide_hwif_t *); -#else -# define ide_init_trm290 IDE_IGNORE #endif #ifdef CONFIG_BLK_DEV_VIA82CXXX @@ -247,11 +165,6 @@ extern unsigned int pci_init_via82cxxx(struct pci_dev *); extern unsigned int ata66_via82cxxx(ide_hwif_t *); extern void ide_init_via82cxxx(ide_hwif_t *); extern void ide_dmacapable_via82cxxx(ide_hwif_t *, unsigned long); -#else -# define pci_init_via82cxxx NULL -# define ata66_via82cxxx NULL -# define ide_init_via82cxxx IDE_NO_DRIVER -# define ide_dmacapable_via82cxxx NULL #endif typedef struct ide_pci_enablebit_s { @@ -260,6 +173,17 @@ typedef struct ide_pci_enablebit_s { byte val; /* value of masked reg when "enabled" */ } ide_pci_enablebit_t; +/* Flags used to untangle quirk handling. + */ +#define ATA_F_DMA 0x01 +#define ATA_F_NODMA 0x02 /* no DMA mode supported at all */ +#define ATA_F_NOADMA 0x04 /* DMA has to be enabled explicitely */ +#define ATA_F_FIXIRQ 0x08 /* fixed irq wiring */ +#define ATA_F_SER 0x10 /* serialize on first and second channel interrupts */ +#define ATA_F_IRQ 0x20 /* trust IRQ information from config */ +#define ATA_F_PHACK 0x40 /* apply PROMISE hacks */ +#define ATA_F_HPTHACK 0x80 /* apply HPT366 hacks */ + typedef struct ide_pci_device_s { unsigned short vendor; unsigned short device; @@ -268,114 +192,139 @@ typedef struct ide_pci_device_s { void (*init_hwif)(ide_hwif_t *hwif); void (*dma_init)(ide_hwif_t *hwif, unsigned long dmabase); ide_pci_enablebit_t enablebits[2]; - byte bootable; + unsigned int bootable; unsigned int extra; + unsigned int flags; } ide_pci_device_t; static ide_pci_device_t pci_chipsets[] __initdata = { - {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371FB_0, NULL, NULL, ide_init_piix, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371FB_1, NULL, NULL, ide_init_piix, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371MX, NULL, NULL, ide_init_piix, NULL, {{0x6D,0x80,0x80}, {0x6F,0x80,0x80}}, ON_BOARD, 0 }, - {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_1, pci_init_piix, NULL, ide_init_piix, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB, pci_init_piix, NULL, ide_init_piix, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_1, pci_init_piix, NULL, ide_init_piix, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_1, pci_init_piix, NULL, ide_init_piix, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_1, pci_init_piix, ata66_piix, ide_init_piix, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82372FB_1, pci_init_piix, ata66_piix, ide_init_piix, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82451NX, pci_init_piix, NULL, ide_init_piix, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_9, pci_init_piix, ata66_piix, ide_init_piix, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_8, pci_init_piix, ata66_piix, ide_init_piix, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_10, pci_init_piix, ata66_piix, ide_init_piix, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C561, NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C576_1, pci_init_via82cxxx, ata66_via82cxxx, ide_init_via82cxxx, ide_dmacapable_via82cxxx, {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, ON_BOARD, 0 }, - {PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1, pci_init_via82cxxx, ata66_via82cxxx, ide_init_via82cxxx, ide_dmacapable_via82cxxx, {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, ON_BOARD, 0 }, -#ifdef CONFIG_PDC202XX_FORCE - {PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20246, pci_init_pdc202xx, NULL, ide_init_pdc202xx, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 16 }, - {PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20262, pci_init_pdc202xx, ata66_pdc202xx, ide_init_pdc202xx, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 48 }, - {PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20265, pci_init_pdc202xx, ata66_pdc202xx, ide_init_pdc202xx, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 48 }, - {PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20267, pci_init_pdc202xx, ata66_pdc202xx, ide_init_pdc202xx, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 48 }, -#else /* !CONFIG_PDC202XX_FORCE */ - {PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20246, pci_init_pdc202xx, NULL, ide_init_pdc202xx, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 16 }, - {PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20262, pci_init_pdc202xx, ata66_pdc202xx, ide_init_pdc202xx, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 48 }, - {PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20265, pci_init_pdc202xx, ata66_pdc202xx, ide_init_pdc202xx, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 48 }, - {PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20267, pci_init_pdc202xx, ata66_pdc202xx, ide_init_pdc202xx, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 48 }, -#endif - {PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20268, pci_init_pdc202xx, ata66_pdc202xx, ide_init_pdc202xx, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, +#ifdef CONFIG_BLK_DEV_PIIX + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371FB_0, NULL, NULL, ide_init_piix, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0, 0 }, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371FB_1, NULL, NULL, ide_init_piix, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0, 0 }, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371MX, NULL, NULL, ide_init_piix, NULL, {{0x6D,0x80,0x80}, {0x6F,0x80,0x80}}, ON_BOARD, 0, ATA_F_NODMA }, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_1, pci_init_piix, NULL, ide_init_piix, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0, 0 }, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB, pci_init_piix, NULL, ide_init_piix, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0, 0 }, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_1, pci_init_piix, NULL, ide_init_piix, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0, 0 }, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_1, pci_init_piix, NULL, ide_init_piix, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0, 0 }, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_1, pci_init_piix, ata66_piix, ide_init_piix, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0, 0 }, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82372FB_1, pci_init_piix, ata66_piix, ide_init_piix, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0, 0 }, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82451NX, pci_init_piix, NULL, ide_init_piix, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0, ATA_F_NOADMA }, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_9, pci_init_piix, ata66_piix, ide_init_piix, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0, 0 }, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_8, pci_init_piix, ata66_piix, ide_init_piix, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0, 0 }, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_10, pci_init_piix, ata66_piix, ide_init_piix, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0, 0 }, +#endif +#ifdef CONFIG_BLK_DEV_VIA82CXXX + {PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C576_1, pci_init_via82cxxx, ata66_via82cxxx, ide_init_via82cxxx, ide_dmacapable_via82cxxx, {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, ON_BOARD, 0, ATA_F_NOADMA }, + {PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1, pci_init_via82cxxx, ata66_via82cxxx, ide_init_via82cxxx, ide_dmacapable_via82cxxx, {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, ON_BOARD, 0, ATA_F_NOADMA }, +#endif +#ifdef CONFIG_BLK_DEV_PDC202XX +# ifdef CONFIG_PDC202XX_FORCE + {PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20246, pci_init_pdc202xx, NULL, ide_init_pdc202xx, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 16, ATA_F_IRQ | ATA_F_DMA }, + {PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20262, pci_init_pdc202xx, ata66_pdc202xx, ide_init_pdc202xx, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 48, ATA_F_IRQ | ATA_F_PHACK | ATA_F_DMA}, + {PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20265, pci_init_pdc202xx, ata66_pdc202xx, ide_init_pdc202xx, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 48, ATA_F_IRQ | ATA_F_PHACK | ATA_F_DMA}, + {PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20267, pci_init_pdc202xx, ata66_pdc202xx, ide_init_pdc202xx, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 48, ATA_F_IRQ | ATA_F_DMA }, +# else + {PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20246, pci_init_pdc202xx, NULL, ide_init_pdc202xx, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 16, ATA_F_IRQ | ATA_F_DMA }, + {PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20262, pci_init_pdc202xx, ata66_pdc202xx, ide_init_pdc202xx, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 48, ATA_F_IRQ | ATA_F_PHACK | ATA_F_DMA }, + {PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20265, pci_init_pdc202xx, ata66_pdc202xx, ide_init_pdc202xx, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 48, ATA_F_IRQ | ATA_F_PHACK | ATA_F_DMA }, + {PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20267, pci_init_pdc202xx, ata66_pdc202xx, ide_init_pdc202xx, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 48, ATA_F_IRQ | ATA_F_DMA }, +# endif + {PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20268, pci_init_pdc202xx, ata66_pdc202xx, ide_init_pdc202xx, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0, ATA_F_IRQ | ATA_F_DMA }, /* Promise used a different PCI ident for the raid card apparently to try and prevent Linux detecting it and using our own raid code. We want to detect it for the ataraid drivers, so we have to list both here.. */ - {PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20268R, pci_init_pdc202xx, ata66_pdc202xx, ide_init_pdc202xx, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, - {PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20269, pci_init_pdc202xx, ata66_pdc202xx, ide_init_pdc202xx, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, - {PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20275, pci_init_pdc202xx, ata66_pdc202xx, ide_init_pdc202xx, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, - {PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1000, NULL, NULL, ide_init_rz1000, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1001, NULL, NULL, ide_init_rz1000, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_SAMURAI_IDE, NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_640, NULL, NULL, IDE_IGNORE, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87410, NULL, NULL, NULL, NULL, {{0x43,0x08,0x08}, {0x47,0x08,0x08}}, ON_BOARD, 0 }, - {PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5513, pci_init_sis5513, ata66_sis5513, ide_init_sis5513, NULL, {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, ON_BOARD, 0 }, - {PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_643, pci_init_cmd64x, NULL, ide_init_cmd64x, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_646, pci_init_cmd64x, NULL, ide_init_cmd64x, NULL, {{0x00,0x00,0x00}, {0x51,0x80,0x80}}, ON_BOARD, 0 }, - {PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_648, pci_init_cmd64x, ata66_cmd64x, ide_init_cmd64x, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_649, pci_init_cmd64x, ata66_cmd64x, ide_init_cmd64x, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_680, pci_init_cmd64x, ata66_cmd64x, ide_init_cmd64x, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {PCI_VENDOR_ID_HOLTEK, PCI_DEVICE_ID_HOLTEK_6565, NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C621, NULL, NULL, ide_init_opti621, NULL, {{0x45,0x80,0x00}, {0x40,0x08,0x00}}, ON_BOARD, 0 }, - {PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C825, NULL, NULL, ide_init_opti621, NULL, {{0x45,0x80,0x00}, {0x40,0x08,0x00}}, ON_BOARD, 0 }, - {PCI_VENDOR_ID_TEKRAM, PCI_DEVICE_ID_TEKRAM_DC290, NULL, NULL, ide_init_trm290, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87415, NULL, NULL, ide_init_ns87415, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP850UF, pci_init_aec62xx, NULL, ide_init_aec62xx, ide_dmacapable_aec62xx, {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, OFF_BOARD, 0 }, - {PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP860, pci_init_aec62xx, ata66_aec62xx, ide_init_aec62xx, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, NEVER_BOARD, 0 }, - {PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP860R, pci_init_aec62xx, ata66_aec62xx, ide_init_aec62xx, NULL, {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, OFF_BOARD, 0 }, - {PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105, pci_init_sl82c105, NULL, ide_init_sl82c105, dma_init_sl82c105, {{0x40,0x01,0x01}, {0x40,0x10,0x10}}, ON_BOARD, 0 }, - {PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8673F, NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886A, NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886BF, NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT343, pci_init_hpt34x, NULL, ide_init_hpt34x, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, NEVER_BOARD, 16 }, - {PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT366, pci_init_hpt366, ata66_hpt366, ide_init_hpt366, ide_dmacapable_hpt366, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 240 }, - {PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5229, pci_init_ali15x3, ata66_ali15x3, ide_init_ali15x3, ide_dmacapable_ali15x3, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {PCI_VENDOR_ID_CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693, pci_init_cy82c693, NULL, ide_init_cy82c693, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {PCI_VENDOR_ID_HINT, PCI_DEVICE_ID_HINT, NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_IDE, pci_init_cs5530, NULL, ide_init_cs5530, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_COBRA_7401, NULL, NULL, NULL, ide_dmacapable_amd74xx, {{0x40,0x01,0x01}, {0x40,0x02,0x02}}, ON_BOARD, 0 }, - {PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7409, pci_init_amd74xx, ata66_amd74xx, ide_init_amd74xx, ide_dmacapable_amd74xx, {{0x40,0x01,0x01}, {0x40,0x02,0x02}}, ON_BOARD, 0 }, - {PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7411, pci_init_amd74xx, ata66_amd74xx, ide_init_amd74xx, ide_dmacapable_amd74xx, {{0x40,0x01,0x01}, {0x40,0x02,0x02}}, ON_BOARD, 0 }, - {PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7441, pci_init_amd74xx, ata66_amd74xx, ide_init_amd74xx, ide_dmacapable_amd74xx, {{0x40,0x01,0x01}, {0x40,0x02,0x02}}, ON_BOARD, 0 }, - {PCI_VENDOR_ID_PDC, PCI_DEVICE_ID_PDC_1841, pci_init_pdcadma, ata66_pdcadma, ide_init_pdcadma, ide_dmacapable_pdcadma, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, - {PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_1, pci_init_slc90e66, ata66_slc90e66, ide_init_slc90e66, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4IDE, pci_init_svwks, ata66_svwks, ide_init_svwks, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, pci_init_svwks, ata66_svwks, ide_init_svwks, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_IT8172G, pci_init_it8172, NULL, ide_init_it8172, NULL, {{0x00,0x00,0x00}, {0x40,0x00,0x01}}, ON_BOARD, 0 }, - {0, 0, NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }}; + {PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20268R, pci_init_pdc202xx, ata66_pdc202xx, ide_init_pdc202xx, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0, ATA_F_IRQ | ATA_F_DMA }, + {PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20269, pci_init_pdc202xx, ata66_pdc202xx, ide_init_pdc202xx, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0, ATA_F_IRQ | ATA_F_DMA }, + {PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20275, pci_init_pdc202xx, ata66_pdc202xx, ide_init_pdc202xx, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0, ATA_F_IRQ | ATA_F_DMA }, +#endif +#ifdef CONFIG_BLK_DEV_RZ1000 + {PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1000, NULL, NULL, ide_init_rz1000, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 }, + {PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1001, NULL, NULL, ide_init_rz1000, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 }, +#endif +#ifdef CONFIG_BLK_DEV_SIS5513 + {PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5513, pci_init_sis5513, ata66_sis5513, ide_init_sis5513, NULL, {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, ON_BOARD, 0, ATA_F_NOADMA }, +#endif +#ifdef CONFIG_BLK_DEV_CMD64X + {PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_643, pci_init_cmd64x, NULL, ide_init_cmd64x, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 }, + {PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_646, pci_init_cmd64x, NULL, ide_init_cmd64x, NULL, {{0x00,0x00,0x00}, {0x51,0x80,0x80}}, ON_BOARD, 0, ATA_F_DMA }, + {PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_648, pci_init_cmd64x, ata66_cmd64x, ide_init_cmd64x, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, ATA_F_DMA }, + {PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_649, pci_init_cmd64x, ata66_cmd64x, ide_init_cmd64x, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, ATA_F_DMA }, + {PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_680, pci_init_cmd64x, ata66_cmd64x, ide_init_cmd64x, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, ATA_F_DMA }, +#endif +#ifdef CONFIG_BLK_DEV_OPTI621 + {PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C621, NULL, NULL, ide_init_opti621, NULL, {{0x45,0x80,0x00}, {0x40,0x08,0x00}}, ON_BOARD, 0, 0 }, + {PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C825, NULL, NULL, ide_init_opti621, NULL, {{0x45,0x80,0x00}, {0x40,0x08,0x00}}, ON_BOARD, 0, 0 }, +#endif +#ifdef CONFIG_BLK_DEV_TRM290 + {PCI_VENDOR_ID_TEKRAM, PCI_DEVICE_ID_TEKRAM_DC290, NULL, NULL, ide_init_trm290, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 }, +#endif +#ifdef CONFIG_BLK_DEV_NS87415 + {PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87415, NULL, NULL, ide_init_ns87415, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 }, +#endif +#ifdef CONFIG_BLK_DEV_AEC62XX + {PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP850UF, pci_init_aec62xx, NULL, ide_init_aec62xx, ide_dmacapable_aec62xx, {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, OFF_BOARD, 0, ATA_F_SER | ATA_F_IRQ | ATA_F_DMA }, + {PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP860, pci_init_aec62xx, ata66_aec62xx, ide_init_aec62xx, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, NEVER_BOARD, 0, ATA_F_IRQ | ATA_F_NOADMA | ATA_F_DMA }, + {PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP860R, pci_init_aec62xx, ata66_aec62xx, ide_init_aec62xx, NULL, {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, OFF_BOARD, 0, ATA_F_IRQ | ATA_F_DMA }, +#endif +#ifdef CONFIG_BLK_DEV_SL82C105 + {PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105, pci_init_sl82c105, NULL, ide_init_sl82c105, dma_init_sl82c105, {{0x40,0x01,0x01}, {0x40,0x10,0x10}}, ON_BOARD, 0, 0 }, +#endif +#ifdef CONFIG_BLK_DEV_HPT34X + {PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT343, pci_init_hpt34x, NULL, ide_init_hpt34x, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, NEVER_BOARD, 16, ATA_F_NOADMA | ATA_F_DMA }, +#endif +#ifdef CONFIG_BLK_DEV_HPT366 + {PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT366, pci_init_hpt366, ata66_hpt366, ide_init_hpt366, ide_dmacapable_hpt366, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 240, ATA_F_IRQ | ATA_F_HPTHACK | ATA_F_DMA }, +#endif +#ifdef CONFIG_BLK_DEV_ALI15X3 + {PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5229, pci_init_ali15x3, ata66_ali15x3, ide_init_ali15x3, ide_dmacapable_ali15x3, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 }, +#endif +#ifdef CONFIG_BLK_DEV_CY82C693 + {PCI_VENDOR_ID_CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693, pci_init_cy82c693, NULL, ide_init_cy82c693, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, ATA_F_DMA }, +#endif +#ifdef CONFIG_BLK_DEV_CS5530 + {PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_IDE, pci_init_cs5530, NULL, ide_init_cs5530, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, ATA_F_DMA }, +#endif +#ifdef CONFIG_BLK_DEV_AMD74XX + {PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_COBRA_7401, NULL, NULL, NULL, ide_dmacapable_amd74xx, {{0x40,0x01,0x01}, {0x40,0x02,0x02}}, ON_BOARD, 0, 0 }, + {PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7409, pci_init_amd74xx, ata66_amd74xx, ide_init_amd74xx, ide_dmacapable_amd74xx, {{0x40,0x01,0x01}, {0x40,0x02,0x02}}, ON_BOARD, 0, 0 }, + {PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7411, pci_init_amd74xx, ata66_amd74xx, ide_init_amd74xx, ide_dmacapable_amd74xx, {{0x40,0x01,0x01}, {0x40,0x02,0x02}}, ON_BOARD, 0, 0 }, + {PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7441, pci_init_amd74xx, ata66_amd74xx, ide_init_amd74xx, ide_dmacapable_amd74xx, {{0x40,0x01,0x01}, {0x40,0x02,0x02}}, ON_BOARD, 0, 0 }, +#endif +#ifdef CONFIG_BLK_DEV_PDC_ADMA + {PCI_VENDOR_ID_PDC, PCI_DEVICE_ID_PDC_1841, pci_init_pdcadma, ata66_pdcadma, ide_init_pdcadma, ide_dmacapable_pdcadma, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0, ATA_F_NODMA }, +#endif +#ifdef CONFIG_BLK_DEV_SLC90E66 + {PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_1, pci_init_slc90e66, ata66_slc90e66, ide_init_slc90e66, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0, 0 }, +#endif +#ifdef CONFIG_BLK_DEV_SVWKS + {PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4IDE, pci_init_svwks, ata66_svwks, ide_init_svwks, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, ATA_F_DMA }, + {PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, pci_init_svwks, ata66_svwks, ide_init_svwks, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 }, +#endif +#ifdef CONFIG_BLK_DEV_IT8172 + {PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_IT8172G, pci_init_it8172, NULL, ide_init_it8172, NULL, {{0x00,0x00,0x00}, {0x40,0x00,0x01}}, ON_BOARD, 0, 0 }, +#endif + /* Those are id's of chips we don't deal currently with. */ + {PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_SAMURAI_IDE, NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 }, + {PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_640, NULL, NULL, IDE_IGNORE, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 }, + {PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87410, NULL, NULL, NULL, NULL, {{0x43,0x08,0x08}, {0x47,0x08,0x08}}, ON_BOARD, 0, 0 }, + {PCI_VENDOR_ID_HINT, PCI_DEVICE_ID_HINT, NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 }, + {PCI_VENDOR_ID_HOLTEK, PCI_DEVICE_ID_HOLTEK_6565, NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 }, + {PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8673F, NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, ATA_F_FIXIRQ }, + {PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886A, NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, ATA_F_FIXIRQ }, + {PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886BF, NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, ATA_F_FIXIRQ }, + {PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C561, NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, ATA_F_NOADMA }, + {0, 0, NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }}; /* * This allows offboard ide-pci cards the enable a BIOS, verify interrupt * settings of split-mirror pci-config space, place chipset into init-mode, * and/or preserve an interrupt if the card is not native ide support. */ -static unsigned int __init trust_pci_irq(struct pci_dev *dev) +static unsigned int __init trust_pci_irq(ide_pci_device_t *d, struct pci_dev *dev) { - if (dev->vendor == PCI_VENDOR_ID_TTI && dev->device == PCI_DEVICE_ID_TTI_HPT366) + if (d->flags & ATA_F_IRQ) return dev->irq; - else if (dev->vendor == PCI_VENDOR_ID_PROMISE) { - switch(dev->device) { - case PCI_DEVICE_ID_PROMISE_20246: - case PCI_DEVICE_ID_PROMISE_20262: - case PCI_DEVICE_ID_PROMISE_20265: - case PCI_DEVICE_ID_PROMISE_20267: - case PCI_DEVICE_ID_PROMISE_20268: - case PCI_DEVICE_ID_PROMISE_20268R: - case PCI_DEVICE_ID_PROMISE_20269: - case PCI_DEVICE_ID_PROMISE_20275: - return dev->irq; - } - } else if (dev->vendor == PCI_VENDOR_ID_ARTOP) { - switch(dev->device) { - case PCI_DEVICE_ID_ARTOP_ATP850UF: - case PCI_DEVICE_ID_ARTOP_ATP860: - case PCI_DEVICE_ID_ARTOP_ATP860R: - return dev->irq; - } - } + return 0; } @@ -505,14 +454,12 @@ static int __init setup_host_channel(struct pci_dev *dev, * enabled by the bios for raid purposes. Skip the normal "is * it enabled" test for those. */ - if ((d->vendor == PCI_VENDOR_ID_PROMISE && d->device == PCI_DEVICE_ID_PROMISE_20265) || - (d->vendor == PCI_VENDOR_ID_PROMISE && d->device == PCI_DEVICE_ID_PROMISE_20262)) + if (d->flags & ATA_F_PHACK) goto controller_ok; } /* Test whatever the port is enabled. */ - if (e->reg) { if (pci_read_config_byte(dev, e->reg, &tmp)) return 0; /* error! */ @@ -520,10 +467,10 @@ static int __init setup_host_channel(struct pci_dev *dev, return 0; } + /* Nothing to be done for the second port. + */ if (port == 1) { - /* Nothing to be done for the second port. */ - if ((d->vendor == PCI_VENDOR_ID_TTI && d->device == PCI_DEVICE_ID_TTI_HPT366) - && (class_rev < 0x03)) + if ((d->flags & ATA_F_HPTHACK) && (class_rev < 0x03)) return 0; } controller_ok: @@ -567,25 +514,23 @@ controller_ok: if (!hwif->irq) hwif->irq = pciirq; + /* Setup the mate interface if we have two channels. + */ if (*mate) { hwif->mate = *mate; (*mate)->mate = hwif; - if (d->vendor == PCI_VENDOR_ID_ARTOP && d->device == PCI_DEVICE_ID_ARTOP_ATP850UF) { + if (d->flags & ATA_F_SER) { hwif->serialized = 1; (*mate)->serialized = 1; } } - if ((d->vendor == PCI_VENDOR_ID_UMC && d->device == PCI_DEVICE_ID_UMC_UM8886A) || - (d->vendor == PCI_VENDOR_ID_UMC && d->device == PCI_DEVICE_ID_UMC_UM8886BF) || - (d->vendor == PCI_VENDOR_ID_UMC && d->device == PCI_DEVICE_ID_UMC_UM8673F)) { - - /* Fixed IRQ wiring */ + /* Hard wired IRQ lines on UMC chips and no DMA transfers.*/ + if (d->flags & ATA_F_FIXIRQ) { hwif->irq = hwif->channel ? 15 : 14; goto no_dma; } - if ((d->vendor == PCI_VENDOR_ID_INTEL && d->device == PCI_DEVICE_ID_INTEL_82371MX) || - (d->vendor == PCI_VENDOR_ID_PDC && d->device == PCI_DEVICE_ID_PDC_1841)) + if (d->flags & ATA_F_NODMA) goto no_dma; /* Check whatever this interface is UDMA4 mode capable. */ @@ -596,39 +541,13 @@ controller_ok: hwif->udma_four = d->ata66_check(hwif); } #ifdef CONFIG_BLK_DEV_IDEDMA - if ((d->vendor == PCI_VENDOR_ID_SI && d->device == PCI_DEVICE_ID_SI_5513) || - (d->vendor == PCI_VENDOR_ID_ARTOP && d->device == PCI_DEVICE_ID_ARTOP_ATP860) || - (d->vendor == PCI_VENDOR_ID_INTEL && d->device == PCI_DEVICE_ID_INTEL_82451NX) || - (d->vendor == PCI_VENDOR_ID_TTI && d->device == PCI_DEVICE_ID_TTI_HPT343) || - (d->vendor == PCI_VENDOR_ID_VIA && d->device == PCI_DEVICE_ID_VIA_82C561) || - (d->vendor == PCI_VENDOR_ID_VIA && d->device == PCI_DEVICE_ID_VIA_82C576_1) || - (d->vendor == PCI_VENDOR_ID_VIA && d->device == PCI_DEVICE_ID_VIA_82C586_1)) + if (d->flags & ATA_F_NOADMA) autodma = 0; if (autodma) hwif->autodma = 1; - if ((d->vendor == PCI_VENDOR_ID_PROMISE && d->device == PCI_DEVICE_ID_PROMISE_20246) || - (d->vendor == PCI_VENDOR_ID_PROMISE && d->device == PCI_DEVICE_ID_PROMISE_20262) || - (d->vendor == PCI_VENDOR_ID_PROMISE && d->device == PCI_DEVICE_ID_PROMISE_20265) || - (d->vendor == PCI_VENDOR_ID_PROMISE && d->device == PCI_DEVICE_ID_PROMISE_20267) || - (d->vendor == PCI_VENDOR_ID_PROMISE && d->device == PCI_DEVICE_ID_PROMISE_20268) || - (d->vendor == PCI_VENDOR_ID_PROMISE && d->device == PCI_DEVICE_ID_PROMISE_20268R) || - (d->vendor == PCI_VENDOR_ID_PROMISE && d->device == PCI_DEVICE_ID_PROMISE_20269) || - (d->vendor == PCI_VENDOR_ID_PROMISE && d->device == PCI_DEVICE_ID_PROMISE_20275) || - (d->vendor == PCI_VENDOR_ID_ARTOP && d->device == PCI_DEVICE_ID_ARTOP_ATP850UF) || - (d->vendor == PCI_VENDOR_ID_ARTOP && d->device == PCI_DEVICE_ID_ARTOP_ATP860) || - (d->vendor == PCI_VENDOR_ID_ARTOP && d->device == PCI_DEVICE_ID_ARTOP_ATP860R) || - (d->vendor == PCI_VENDOR_ID_TTI && d->device == PCI_DEVICE_ID_TTI_HPT343) || - (d->vendor == PCI_VENDOR_ID_TTI && d->device == PCI_DEVICE_ID_TTI_HPT366) || - (d->vendor == PCI_VENDOR_ID_CYRIX && d->device == PCI_DEVICE_ID_CYRIX_5530_IDE) || - (d->vendor == PCI_VENDOR_ID_CONTAQ && d->device == PCI_DEVICE_ID_CONTAQ_82C693) || - (d->vendor == PCI_VENDOR_ID_CMD && d->device == PCI_DEVICE_ID_CMD_646) || - (d->vendor == PCI_VENDOR_ID_CMD && d->device == PCI_DEVICE_ID_CMD_648) || - (d->vendor == PCI_VENDOR_ID_CMD && d->device == PCI_DEVICE_ID_CMD_649) || - (d->vendor == PCI_VENDOR_ID_CMD && d->device == PCI_DEVICE_ID_CMD_680) || - (d->vendor == PCI_VENDOR_ID_SERVERWORKS && d->device == PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) || - ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && (dev->class & 0x80))) { + if ((d->flags & ATA_F_DMA) || ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && (dev->class & 0x80))) { unsigned long dma_base; dma_base = ide_get_or_set_dma_base(hwif, (!*mate && d->extra) ? d->extra : 0, dev->name); @@ -769,7 +688,7 @@ check_if_enabled: if (d->init_chipset) pciirq = d->init_chipset(dev); else - pciirq = trust_pci_irq(dev); + pciirq = trust_pci_irq(d, dev); } else if (tried_config) { printk("%s: will probe irqs later\n", dev->name); pciirq = 0; @@ -799,9 +718,9 @@ static void __init pdc20270_device_order_fixup (struct pci_dev *dev, ide_pci_dev struct pci_dev *dev2 = NULL, *findev; ide_pci_device_t *d2; - if ((dev->bus->self && - dev->bus->self->vendor == PCI_VENDOR_ID_DEC) && - (dev->bus->self->device == PCI_DEVICE_ID_DEC_21150)) { + if (dev->bus->self && + dev->bus->self->vendor == PCI_VENDOR_ID_DEC && + dev->bus->self->device == PCI_DEVICE_ID_DEC_21150) { if (PCI_SLOT(dev->devfn) & 2) { return; } @@ -855,8 +774,8 @@ static void __init hpt366_device_order_fixup (struct pci_dev *dev, ide_pci_devic pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin1); pci_for_each_dev(findev) { - if ((findev->vendor == dev->vendor) && - (findev->device == dev->device) && + if (findev->vendor == dev->vendor && + findev->device == dev->device && ((findev->devfn - dev->devfn) == 1) && (PCI_FUNC(findev->devfn) & 1)) { dev2 = findev; @@ -905,7 +824,7 @@ static void __init ide_scan_pcidev(struct pci_dev *dev) ++d; if (d->init_hwif == IDE_IGNORE) - printk("%s: has been ignored PCI bus scan\n", dev->name); + printk("%s: has been ignored by PCI bus scan\n", dev->name); else if ((d->vendor == PCI_VENDOR_ID_OPTI && d->device == PCI_DEVICE_ID_OPTI_82C558) && !(PCI_FUNC(dev->devfn) & 1)) return; else if ((d->vendor == PCI_VENDOR_ID_CONTAQ && d->device == PCI_DEVICE_ID_CONTAQ_82C693) && (!(PCI_FUNC(dev->devfn) & 1) || !((dev->class >> 8) == PCI_CLASS_STORAGE_IDE))) @@ -914,7 +833,7 @@ static void __init ide_scan_pcidev(struct pci_dev *dev) return; /* IT8172G is also more than only an IDE controller */ else if ((d->vendor == PCI_VENDOR_ID_UMC && d->device == PCI_DEVICE_ID_UMC_UM8886A) && !(PCI_FUNC(dev->devfn) & 1)) return; /* UM8886A/BF pair */ - else if ((d->vendor == PCI_VENDOR_ID_TTI && d->device == PCI_DEVICE_ID_TTI_HPT366)) + else if (d->flags & ATA_F_HPTHACK) hpt366_device_order_fixup(dev, d); else if (d->vendor == PCI_VENDOR_ID_PROMISE && d->device == PCI_DEVICE_ID_PROMISE_20268R) pdc20270_device_order_fixup(dev, d); diff --git a/include/linux/ide.h b/include/linux/ide.h index a72fcbbc051c..c35f531eeb4e 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -551,7 +551,7 @@ typedef struct hwif_s { struct proc_dir_entry *proc; /* /proc/ide/ directory entry */ int irq; /* our irq number */ byte major; /* our major number */ - char name[6]; /* name of interface, eg. "ide0" */ + char name[80]; /* name of interface */ byte index; /* 0 for ide0; 1 for ide1; ... */ hwif_chipset_t chipset; /* sub-module for tuning.. */ unsigned noprobe : 1; /* don't probe for this interface */ -- cgit v1.2.3 From 48ba6e981971315be2610d57be73b501a66c996e Mon Sep 17 00:00:00 2001 From: Martin Dalecki Date: Wed, 27 Feb 2002 20:15:37 -0800 Subject: [PATCH] 2.5.6-pre1 IDE clean 14 Most importantly this patch is making ide.c use the new automagic for module initialization lists and further preparing the rest of the code in question here for proper module separation. Despite this the CMOS probe has been removed as well... *Iff*, which I don't expect, this breaks anything it can be reintroduced easely. During this effort an actual bug in the initialization of the main module has been uncovered as well. a quite serious BUG has been tagged in ide-scsi.c as well, but as far as now I just didn't get along to actually fixing it. (The patch is big enough as it is). Details follow: - Kill *unused* ide_media_verbose() funciton. - Remove the unnecessary media and supports_dma fields from ide_driver_t. - Remove the global name field from ide_driver_t struct by pushing it down to the places where it's actually used. - Remove the unused hwif_data field from ide_hwif_t. - Push the supports_dsc_overlap condition up to the level where it belongs: disk type as well. - Make the initialization of ide main ide.c work with the new module initialization auto-magic instead of calling it explicitly in ll_rw_block.c This prevents the ide_init() from being called twice. We have BTW. renamed it to ata_module_init(), since ata is more adequate then ide and xxx_module_init corresponds better to the naming conventions used elsewhere throughout the kernel. This BUG was there before any ide-clean. It was worked around by a magic variable preventing the second call to succeed. We have removed this variable in one of the previous patches and thus uncovered it. - Kill proc_ide_read_driver() and proc_ide_write_driver(). The drivers already report on syslog which drives they have taken care of. (Or at least they should). In esp. the proc_ide_write_driver() was just too offending for me. Beleve it or not the purpose of it was to *request a particular* driver for a device, by echoing some magic values to a magic file... More importantly this "back door" was getting in the way of a properly done modularization of the IDE stuff. - Made some not externally used functions static or not EXPORT-ed. - Provide the start of a proper modularization between the main module and drivers for particular device types. Changing the name-space polluting DRIVER() macro to ata_ops() showed how inconsistently the busy (read: module busy!) field from ide_driver_t is currently used across the different device type modules. This has to be fixed soon. - Make the ide code use the similar device type ID numbers as the SCSI code :-). This is just tedious, but it will help in a distant feature. It helps reading the code anyway. - Mark repettitive code with /* ATA-PATTERN */ comments for later consolidation at places where we did came across it. - Various comments and notes added where some explanations was missing. --- drivers/block/ll_rw_blk.c | 3 - drivers/ide/aec62xx.c | 7 +- drivers/ide/alim15x3.c | 10 +- drivers/ide/amd74xx.c | 1 - drivers/ide/cmd64x.c | 10 +- drivers/ide/cs5530.c | 1 - drivers/ide/hpt34x.c | 5 +- drivers/ide/hpt366.c | 5 +- drivers/ide/ht6560b.c | 2 +- drivers/ide/ide-cd.c | 36 +++--- drivers/ide/ide-disk.c | 33 +++-- drivers/ide/ide-dma.c | 6 +- drivers/ide/ide-features.c | 16 --- drivers/ide/ide-floppy.c | 41 +++---- drivers/ide/ide-geometry.c | 102 ++------------- drivers/ide/ide-probe.c | 131 ++++++++------------ drivers/ide/ide-proc.c | 85 +++---------- drivers/ide/ide-tape.c | 105 ++-------------- drivers/ide/ide-taskfile.c | 2 +- drivers/ide/ide.c | 300 ++++++++++++++++++++++++--------------------- drivers/ide/ns87415.c | 2 +- drivers/ide/pdc202xx.c | 12 +- drivers/ide/pdcadma.c | 1 - drivers/ide/piix.c | 1 - drivers/ide/qd65xx.c | 2 +- drivers/ide/serverworks.c | 1 - drivers/ide/sis5513.c | 2 +- drivers/ide/slc90e66.c | 1 - drivers/ide/trm290.c | 2 +- drivers/scsi/ide-scsi.c | 69 ++++------- include/linux/ide.h | 92 ++++++++------ 31 files changed, 414 insertions(+), 672 deletions(-) (limited to 'include/linux') diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c index b42f7b77363c..a1cc083e75f5 100644 --- a/drivers/block/ll_rw_blk.c +++ b/drivers/block/ll_rw_blk.c @@ -1697,9 +1697,6 @@ int __init blk_dev_init(void) blk_max_low_pfn = max_low_pfn; blk_max_pfn = max_pfn; -#if defined(CONFIG_IDE) && defined(CONFIG_BLK_DEV_IDE) - ide_init(); /* this MUST precede hd_init */ -#endif #if defined(CONFIG_IDE) && defined(CONFIG_BLK_DEV_HD) hd_init(); #endif diff --git a/drivers/ide/aec62xx.c b/drivers/ide/aec62xx.c index 545d6a4de567..31f8da63e189 100644 --- a/drivers/ide/aec62xx.c +++ b/drivers/ide/aec62xx.c @@ -48,7 +48,6 @@ static int aec62xx_get_info(char *, char **, off_t, int); extern int (*aec62xx_display_info)(char *, char **, off_t, int); /* ide-proc.c */ -extern char *ide_media_verbose(ide_drive_t *); static struct pci_dev *bmide_dev; static int aec62xx_get_info (char *buffer, char **addr, off_t offset, int count) @@ -310,8 +309,8 @@ static int config_aec6210_chipset_for_dma (ide_drive_t *drive, byte ultra) unsigned long dma_base = hwif->dma_base; byte speed = -1; - if (drive->media != ide_disk) - return ((int) ide_dma_off_quietly); + if (drive->type != ATA_DISK) + return ide_dma_off_quietly; if (((id->dma_ultra & 0x0010) || (id->dma_ultra & 0x0008) || @@ -356,7 +355,7 @@ static int config_aec6260_chipset_for_dma (ide_drive_t *drive, byte ultra) byte speed = -1; byte ultra66 = eighty_ninty_three(drive); - if (drive->media != ide_disk) + if (drive->type != ATA_DISK) return ((int) ide_dma_off_quietly); if ((id->dma_ultra & 0x0010) && (ultra) && (ultra66)) { diff --git a/drivers/ide/alim15x3.c b/drivers/ide/alim15x3.c index 727161449214..5cef9e737a2b 100644 --- a/drivers/ide/alim15x3.c +++ b/drivers/ide/alim15x3.c @@ -278,7 +278,7 @@ static void ali15x3_tune_drive (ide_drive_t *drive, byte pio) * PIO mode => ATA FIFO on, ATAPI FIFO off */ pci_read_config_byte(dev, portFIFO, &cd_dma_fifo); - if (drive->media==ide_disk) { + if (drive->type == ATA_DISK) { if (hwif->index) { pci_write_config_byte(dev, portFIFO, (cd_dma_fifo & 0x0F) | 0x50); } else { @@ -424,9 +424,9 @@ static byte ali15x3_can_ultra (ide_drive_t *drive) } else if ((m5229_revision < 0xC2) && #ifndef CONFIG_WDC_ALI15X3 ((chip_is_1543c_e && strstr(id->model, "WDC ")) || - (drive->media!=ide_disk))) { + (drive->type != ATA_DISK))) { #else /* CONFIG_WDC_ALI15X3 */ - (drive->media!=ide_disk)) { + (drive->type != ATA_DISK)) { #endif /* CONFIG_WDC_ALI15X3 */ return 0; } else { @@ -441,7 +441,7 @@ static int ali15x3_config_drive_for_dma(ide_drive_t *drive) ide_dma_action_t dma_func = ide_dma_on; byte can_ultra_dma = ali15x3_can_ultra(drive); - if ((m5229_revision<=0x20) && (drive->media!=ide_disk)) + if ((m5229_revision<=0x20) && (drive->type != ATA_DISK)) return hwif->dmaproc(ide_dma_off_quietly, drive); if ((id != NULL) && ((id->capability & 1) != 0) && hwif->autodma) { @@ -494,7 +494,7 @@ static int ali15x3_dmaproc (ide_dma_action_t func, ide_drive_t *drive) case ide_dma_check: return ali15x3_config_drive_for_dma(drive); case ide_dma_write: - if ((m5229_revision < 0xC2) && (drive->media != ide_disk)) + if ((m5229_revision < 0xC2) && (drive->type != ATA_DISK)) return 1; /* try PIO instead of DMA */ break; default: diff --git a/drivers/ide/amd74xx.c b/drivers/ide/amd74xx.c index 0e185381d026..8cb8d70fb68a 100644 --- a/drivers/ide/amd74xx.c +++ b/drivers/ide/amd74xx.c @@ -34,7 +34,6 @@ static int amd74xx_get_info(char *, char **, off_t, int); extern int (*amd74xx_display_info)(char *, char **, off_t, int); /* ide-proc.c */ -extern char *ide_media_verbose(ide_drive_t *); static struct pci_dev *bmide_dev; static int amd74xx_get_info (char *buffer, char **addr, off_t offset, int count) diff --git a/drivers/ide/cmd64x.c b/drivers/ide/cmd64x.c index feeb938221c5..e81a9d194745 100644 --- a/drivers/ide/cmd64x.c +++ b/drivers/ide/cmd64x.c @@ -88,7 +88,6 @@ static int cmd64x_get_info(char *, char **, off_t, int); static int cmd680_get_info(char *, char **, off_t, int); extern int (*cmd64x_display_info)(char *, char **, off_t, int); /* ide-proc.c */ -extern char *ide_media_verbose(ide_drive_t *); static struct pci_dev *bmide_dev; static int cmd64x_get_info (char *buffer, char **addr, off_t offset, int count) @@ -448,7 +447,8 @@ static int cmd64x_tune_chipset (ide_drive_t *drive, byte speed) u8 regU = 0; u8 regD = 0; - if ((drive->media != ide_disk) && (speed < XFER_SW_DMA_0)) return 1; + if ((drive->type != ATA_DISK) && (speed < XFER_SW_DMA_0)) + return 1; (void) pci_read_config_byte(dev, pciD, ®D); (void) pci_read_config_byte(dev, pciU, ®U); @@ -641,8 +641,8 @@ static int config_cmd64x_chipset_for_dma (ide_drive_t *drive, unsigned int rev, break; } - if (drive->media != ide_disk) { - cmdprintk("CMD64X: drive->media != ide_disk at double check, inital check failed!!\n"); + if (drive->type != ATA_DISK) { + cmdprintk("CMD64X: drive is not a disk at double check, inital check failed!!\n"); return ((int) ide_dma_off); } @@ -788,7 +788,7 @@ static int cmd64x_config_drive_for_dma (ide_drive_t *drive) } if ((id != NULL) && ((id->capability & 1) != 0) && - hwif->autodma && (drive->media == ide_disk)) { + hwif->autodma && (drive->type == ATA_DISK)) { /* Consult the list of known "bad" drives */ if (ide_dmaproc(ide_dma_bad_drive, drive)) { dma_func = ide_dma_off; diff --git a/drivers/ide/cs5530.c b/drivers/ide/cs5530.c index ac5ce9924e31..44a44eba60b5 100644 --- a/drivers/ide/cs5530.c +++ b/drivers/ide/cs5530.c @@ -37,7 +37,6 @@ static int cs5530_get_info(char *, char **, off_t, int); extern int (*cs5530_display_info)(char *, char **, off_t, int); /* ide-proc.c */ -extern char *ide_media_verbose(ide_drive_t *); static struct pci_dev *bmide_dev; static int cs5530_get_info (char *buffer, char **addr, off_t offset, int count) diff --git a/drivers/ide/hpt34x.c b/drivers/ide/hpt34x.c index 6254a113075a..ccaac6f65a57 100644 --- a/drivers/ide/hpt34x.c +++ b/drivers/ide/hpt34x.c @@ -56,7 +56,6 @@ static int hpt34x_get_info(char *, char **, off_t, int); extern int (*hpt34x_display_info)(char *, char **, off_t, int); /* ide-proc.c */ -extern char *ide_media_verbose(ide_drive_t *); static struct pci_dev *bmide_dev; static int hpt34x_get_info (char *buffer, char **addr, off_t offset, int count) @@ -210,7 +209,7 @@ static int config_chipset_for_dma (ide_drive_t *drive, byte ultra) struct hd_driveid *id = drive->id; byte speed = 0x00; - if (drive->media != ide_disk) + if (drive->type != ATA_DISK) return ((int) ide_dma_off_quietly); hpt34x_clear_chipset(drive); @@ -333,7 +332,7 @@ int hpt34x_dmaproc (ide_dma_action_t func, ide_drive_t *drive) outb(reading, dma_base); /* specify r/w */ outb(inb(dma_base+2)|6, dma_base+2); /* clear INTR & ERROR flags */ drive->waiting_for_dma = 1; - if (drive->media != ide_disk) + if (drive->type != ATA_DISK) return 0; ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL); /* issue cmd to drive */ OUT_BYTE((reading == 9) ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG); diff --git a/drivers/ide/hpt366.c b/drivers/ide/hpt366.c index 092f57bfe980..b2374dd4b76a 100644 --- a/drivers/ide/hpt366.c +++ b/drivers/ide/hpt366.c @@ -355,7 +355,6 @@ extern char *ide_xfer_verbose (byte xfer_rate); #if defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS) static int hpt366_get_info(char *, char **, off_t, int); extern int (*hpt366_display_info)(char *, char **, off_t, int); /* ide-proc.c */ -extern char *ide_media_verbose(ide_drive_t *); static int hpt366_get_info (char *buffer, char **addr, off_t offset, int count) { @@ -579,7 +578,7 @@ static void hpt370_tune_chipset (ide_drive_t *drive, byte speed) static int hpt3xx_tune_chipset (ide_drive_t *drive, byte speed) { - if ((drive->media != ide_disk) && (speed < XFER_SW_DMA_0)) + if ((drive->type != ATA_DISK) && (speed < XFER_SW_DMA_0)) return -1; if (!drive->init_speed) @@ -664,7 +663,7 @@ static int config_chipset_for_dma (ide_drive_t *drive) byte ultra66 = eighty_ninty_three(drive); int rval; - if ((drive->media != ide_disk) && (speed < XFER_SW_DMA_0)) + if ((drive->type != ATA_DISK) && (speed < XFER_SW_DMA_0)) return ((int) ide_dma_off_quietly); if ((id->dma_ultra & 0x0020) && diff --git a/drivers/ide/ht6560b.c b/drivers/ide/ht6560b.c index e0eab96ad629..59dacf6266ed 100644 --- a/drivers/ide/ht6560b.c +++ b/drivers/ide/ht6560b.c @@ -143,7 +143,7 @@ static void ht6560b_selectproc (ide_drive_t *drive) if (select != current_select || timing != current_timing) { current_select = select; current_timing = timing; - if (drive->media != ide_disk || !drive->present) + if (drive->type != ATA_DISK || !drive->present) select |= HT_PREFETCH_MODE; (void) inb(HT_CONFIG_PORT); (void) inb(HT_CONFIG_PORT); diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 07f6f767b166..3266e7ef0721 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -2906,14 +2906,10 @@ int ide_cdrom_cleanup(ide_drive_t *drive) return 0; } -int ide_cdrom_reinit (ide_drive_t *drive); - -static ide_driver_t ide_cdrom_driver = { - name: "ide-cdrom", - media: ide_cdrom, - busy: 0, - supports_dma: 1, - supports_dsc_overlap: 1, +static int ide_cdrom_reinit (ide_drive_t *drive); + +static struct ata_operations ide_cdrom_driver = { + owner: THIS_MODULE, cleanup: ide_cdrom_cleanup, standby: NULL, flushcache: NULL, @@ -2937,7 +2933,7 @@ char *ignore = NULL; MODULE_PARM(ignore, "s"); MODULE_DESCRIPTION("ATAPI CD-ROM Driver"); -int ide_cdrom_reinit (ide_drive_t *drive) +static int ide_cdrom_reinit (ide_drive_t *drive) { struct cdrom_info *info; int failed = 0; @@ -2955,14 +2951,17 @@ int ide_cdrom_reinit (ide_drive_t *drive) } memset (info, 0, sizeof (struct cdrom_info)); drive->driver_data = info; - DRIVER(drive)->busy++; + + /* ATA-PATTERN */ + ata_ops(drive)->busy++; if (ide_cdrom_setup (drive)) { - DRIVER(drive)->busy--; + ata_ops(drive)->busy--; if (ide_cdrom_cleanup (drive)) printk ("%s: ide_cdrom_cleanup failed in ide_cdrom_init\n", drive->name); return 1; } - DRIVER(drive)->busy--; + ata_ops(drive)->busy--; + failed--; revalidate_drives(); @@ -2975,7 +2974,7 @@ static void __exit ide_cdrom_exit(void) ide_drive_t *drive; int failed = 0; - while ((drive = ide_scan_devices (ide_cdrom, ide_cdrom_driver.name, &ide_cdrom_driver, failed)) != NULL) + while ((drive = ide_scan_devices(ATA_ROM, "ide-cdrom", &ide_cdrom_driver, failed)) != NULL) if (ide_cdrom_cleanup (drive)) { printk ("%s: cleanup_module() called while still busy\n", drive->name); failed++; @@ -2989,7 +2988,7 @@ int ide_cdrom_init(void) int failed = 0; MOD_INC_USE_COUNT; - while ((drive = ide_scan_devices (ide_cdrom, ide_cdrom_driver.name, NULL, failed++)) != NULL) { + while ((drive = ide_scan_devices (ATA_ROM, "ide-cdrom", NULL, failed++)) != NULL) { /* skip drives that we were told to ignore */ if (ignore != NULL) { if (strstr(ignore, drive->name)) { @@ -3013,14 +3012,17 @@ int ide_cdrom_init(void) } memset (info, 0, sizeof (struct cdrom_info)); drive->driver_data = info; - DRIVER(drive)->busy++; + + /* ATA-PATTERN */ + ata_ops(drive)->busy++; if (ide_cdrom_setup (drive)) { - DRIVER(drive)->busy--; + ata_ops(drive)->busy--; if (ide_cdrom_cleanup (drive)) printk ("%s: ide_cdrom_cleanup failed in ide_cdrom_init\n", drive->name); continue; } - DRIVER(drive)->busy--; + ata_ops(drive)->busy--; + failed--; } revalidate_drives(); diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index a3bf789fbf2d..fb4350c2e7e4 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -1053,17 +1053,13 @@ static int idedisk_cleanup (ide_drive_t *drive) return ide_unregister_subdriver(drive); } -int idedisk_reinit(ide_drive_t *drive); +static int idedisk_reinit(ide_drive_t *drive); /* * IDE subdriver functions, registered with ide.c */ -static ide_driver_t idedisk_driver = { - name: "ide-disk", - media: ide_disk, - busy: 0, - supports_dma: 1, - supports_dsc_overlap: 0, +static struct ata_operations idedisk_driver = { + owner: THIS_MODULE, cleanup: idedisk_cleanup, standby: do_idedisk_standby, flushcache: do_idedisk_flushcache, @@ -1083,7 +1079,7 @@ static ide_driver_t idedisk_driver = { MODULE_DESCRIPTION("ATA DISK Driver"); -int idedisk_reinit (ide_drive_t *drive) +static int idedisk_reinit(ide_drive_t *drive) { int failed = 0; @@ -1093,15 +1089,16 @@ int idedisk_reinit (ide_drive_t *drive) printk (KERN_ERR "ide-disk: %s: Failed to register the driver with ide.c\n", drive->name); return 1; } - DRIVER(drive)->busy++; + + ata_ops(drive)->busy++; idedisk_setup(drive); if ((!drive->head || drive->head > 16) && !drive->select.b.lba) { printk(KERN_ERR "%s: INVALID GEOMETRY: %d PHYSICAL HEADS?\n", drive->name, drive->head); - (void) idedisk_cleanup(drive); - DRIVER(drive)->busy--; + idedisk_cleanup(drive); + ata_ops(drive)->busy--; return 1; } - DRIVER(drive)->busy--; + ata_ops(drive)->busy--; failed--; revalidate_drives(); @@ -1114,7 +1111,7 @@ static void __exit idedisk_exit (void) ide_drive_t *drive; int failed = 0; - while ((drive = ide_scan_devices (ide_disk, idedisk_driver.name, &idedisk_driver, failed)) != NULL) { + while ((drive = ide_scan_devices(ATA_DISK, "ide-disk", &idedisk_driver, failed)) != NULL) { if (idedisk_cleanup (drive)) { printk (KERN_ERR "%s: cleanup_module() called while still busy\n", drive->name); failed++; @@ -1134,20 +1131,20 @@ int idedisk_init (void) int failed = 0; MOD_INC_USE_COUNT; - while ((drive = ide_scan_devices (ide_disk, idedisk_driver.name, NULL, failed++)) != NULL) { + while ((drive = ide_scan_devices(ATA_DISK, "ide-disk", NULL, failed++)) != NULL) { if (ide_register_subdriver (drive, &idedisk_driver)) { printk (KERN_ERR "ide-disk: %s: Failed to register the driver with ide.c\n", drive->name); continue; } - DRIVER(drive)->busy++; + ata_ops(drive)->busy++; idedisk_setup(drive); if ((!drive->head || drive->head > 16) && !drive->select.b.lba) { printk(KERN_ERR "%s: INVALID GEOMETRY: %d PHYSICAL HEADS?\n", drive->name, drive->head); - (void) idedisk_cleanup(drive); - DRIVER(drive)->busy--; + idedisk_cleanup(drive); + ata_ops(drive)->busy--; continue; } - DRIVER(drive)->busy--; + ata_ops(drive)->busy--; failed--; } revalidate_drives(); diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c index e2876f5e28d0..c1c61cb8acc6 100644 --- a/drivers/ide/ide-dma.c +++ b/drivers/ide/ide-dma.c @@ -470,7 +470,7 @@ static int config_drive_for_dma (ide_drive_t *drive) ide_hwif_t *hwif = HWIF(drive); #ifdef CONFIG_IDEDMA_ONLYDISK - if (drive->media != ide_disk) + if (drive->type != ATA_DISK) config_allows_dma = 0; #endif @@ -555,7 +555,7 @@ static void ide_toggle_bounce(ide_drive_t *drive, int on) { u64 addr = BLK_BOUNCE_HIGH; - if (on && drive->media == ide_disk && HWIF(drive)->highmem) { + if (on && drive->type == ATA_DISK && HWIF(drive)->highmem) { if (!PCI_DMA_BUS_IS_PHYS) addr = BLK_BOUNCE_ANY; else @@ -613,7 +613,7 @@ int ide_dmaproc (ide_dma_action_t func, ide_drive_t *drive) outb(reading, dma_base); /* specify r/w */ outb(inb(dma_base+2)|6, dma_base+2); /* clear INTR & ERROR flags */ drive->waiting_for_dma = 1; - if (drive->media != ide_disk) + if (drive->type != ATA_DISK) return 0; #ifdef CONFIG_BLK_DEV_IDEDMA_TIMEOUT ide_set_handler(drive, &ide_dma_intr, 2*WAIT_CMD, NULL); /* issue cmd to drive */ diff --git a/drivers/ide/ide-features.c b/drivers/ide/ide-features.c index 8510e66c199c..840abbaff138 100644 --- a/drivers/ide/ide-features.c +++ b/drivers/ide/ide-features.c @@ -69,22 +69,6 @@ char *ide_xfer_verbose (byte xfer_rate) } } -/* - * - */ -char *ide_media_verbose (ide_drive_t *drive) -{ - switch (drive->media) { - case ide_scsi: return("scsi "); - case ide_disk: return("disk "); - case ide_optical: return("optical"); - case ide_cdrom: return("cdrom "); - case ide_tape: return("tape "); - case ide_floppy: return("floppy "); - default: return("???????"); - } -} - /* * A Verbose noise maker for debugging on the attempted dmaing calls. */ diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index 2ded4cb94373..24de2a826a96 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -1826,14 +1826,6 @@ static int idefloppy_media_change (ide_drive_t *drive) return test_and_clear_bit (IDEFLOPPY_MEDIA_CHANGED, &floppy->flags); } -/* - * Revalidate the new media. Should set blk_size[] - */ -static void idefloppy_revalidate (ide_drive_t *drive) -{ - ide_revalidate_drive(drive); -} - /* * Return the current floppy capacity to ide.c. */ @@ -2046,17 +2038,13 @@ static ide_proc_entry_t idefloppy_proc[] = { #endif /* CONFIG_PROC_FS */ -int idefloppy_reinit(ide_drive_t *drive); +static int idefloppy_reinit(ide_drive_t *drive); /* * IDE subdriver functions, registered with ide.c */ -static ide_driver_t idefloppy_driver = { - name: "ide-floppy", - media: ide_floppy, - busy: 0, - supports_dma: 1, - supports_dsc_overlap: 0, +static struct ata_operations idefloppy_driver = { + owner: THIS_MODULE, cleanup: idefloppy_cleanup, standby: NULL, flushcache: NULL, @@ -2066,7 +2054,7 @@ static ide_driver_t idefloppy_driver = { open: idefloppy_open, release: idefloppy_release, media_change: idefloppy_media_change, - revalidate: idefloppy_revalidate, + revalidate: ide_revalidate_drive, pre_reset: NULL, capacity: idefloppy_capacity, special: NULL, @@ -2074,13 +2062,13 @@ static ide_driver_t idefloppy_driver = { driver_reinit: idefloppy_reinit, }; -int idefloppy_reinit (ide_drive_t *drive) +static int idefloppy_reinit (ide_drive_t *drive) { idefloppy_floppy_t *floppy; int failed = 0; MOD_INC_USE_COUNT; - while ((drive = ide_scan_devices (ide_floppy, idefloppy_driver.name, NULL, failed++)) != NULL) { + while ((drive = ide_scan_devices(ATA_FLOPPY, "ide-floppy", NULL, failed++)) != NULL) { if (!idefloppy_identify_device (drive, drive->id)) { printk (KERN_ERR "ide-floppy: %s: not supported by this version of ide-floppy\n", drive->name); continue; @@ -2098,9 +2086,12 @@ int idefloppy_reinit (ide_drive_t *drive) kfree (floppy); continue; } - DRIVER(drive)->busy++; + + /* ATA-PATTERN */ + ata_ops(drive)->busy++; idefloppy_setup (drive, floppy); - DRIVER(drive)->busy--; + ata_ops(drive)->busy--; + failed--; } revalidate_drives(); @@ -2115,7 +2106,7 @@ static void __exit idefloppy_exit (void) ide_drive_t *drive; int failed = 0; - while ((drive = ide_scan_devices (ide_floppy, idefloppy_driver.name, &idefloppy_driver, failed)) != NULL) { + while ((drive = ide_scan_devices(ATA_FLOPPY, "ide-floppy", &idefloppy_driver, failed)) != NULL) { if (idefloppy_cleanup (drive)) { printk ("%s: cleanup_module() called while still busy\n", drive->name); failed++; @@ -2141,7 +2132,7 @@ int idefloppy_init (void) printk("ide-floppy driver " IDEFLOPPY_VERSION "\n"); MOD_INC_USE_COUNT; - while ((drive = ide_scan_devices (ide_floppy, idefloppy_driver.name, NULL, failed++)) != NULL) { + while ((drive = ide_scan_devices (ATA_FLOPPY, "ide-floppy", NULL, failed++)) != NULL) { if (!idefloppy_identify_device (drive, drive->id)) { printk (KERN_ERR "ide-floppy: %s: not supported by this version of ide-floppy\n", drive->name); continue; @@ -2159,9 +2150,11 @@ int idefloppy_init (void) kfree (floppy); continue; } - DRIVER(drive)->busy++; + /* ATA-PATTERN */ + ata_ops(drive)->busy++; idefloppy_setup (drive, floppy); - DRIVER(drive)->busy--; + ata_ops(drive)->busy--; + failed--; } revalidate_drives(); diff --git a/drivers/ide/ide-geometry.c b/drivers/ide/ide-geometry.c index 5f21651c1785..fc38389c53a6 100644 --- a/drivers/ide/ide-geometry.c +++ b/drivers/ide/ide-geometry.c @@ -1,94 +1,16 @@ /* * linux/drivers/ide/ide-geometry.c + * + * Sun Feb 24 23:13:03 CET 2002: Patch by Andries Brouwer to remove the + * confused CMOS probe applied. This is solving more problems then it my + * (unexpectedly) introduce. */ + #include #include #include #include -#ifdef CONFIG_BLK_DEV_IDE - -/* - * We query CMOS about hard disks : it could be that we have a SCSI/ESDI/etc - * controller that is BIOS compatible with ST-506, and thus showing up in our - * BIOS table, but not register compatible, and therefore not present in CMOS. - * - * Furthermore, we will assume that our ST-506 drives are the primary - * drives in the system -- the ones reflected as drive 1 or 2. The first - * drive is stored in the high nibble of CMOS byte 0x12, the second in the low - * nibble. This will be either a 4 bit drive type or 0xf indicating use byte - * 0x19 for an 8 bit type, drive 1, 0x1a for drive 2 in CMOS. A non-zero value - * means we have an AT controller hard disk for that drive. - * - * Of course, there is no guarantee that either drive is actually on the - * "primary" IDE interface, but we don't bother trying to sort that out here. - * If a drive is not actually on the primary interface, then these parameters - * will be ignored. This results in the user having to supply the logical - * drive geometry as a boot parameter for each drive not on the primary i/f. - */ -/* - * The only "perfect" way to handle this would be to modify the setup.[cS] code - * to do BIOS calls Int13h/Fn08h and Int13h/Fn48h to get all of the drive info - * for us during initialization. I have the necessary docs -- any takers? -ml - */ -/* - * I did this, but it doesnt work - there is no reasonable way to find the - * correspondence between the BIOS numbering of the disks and the Linux - * numbering. -aeb - * - * The code below is bad. One of the problems is that drives 1 and 2 - * may be SCSI disks (even when IDE disks are present), so that - * the geometry we read here from BIOS is attributed to the wrong disks. - * Consequently, also the former "drive->present = 1" below was a mistake. - * - * Eventually the entire routine below should be removed. - * - * 17-OCT-2000 rjohnson@analogic.com Added spin-locks for reading CMOS - * chip. - */ - -void probe_cmos_for_drives (ide_hwif_t *hwif) -{ -#ifdef __i386__ - extern struct drive_info_struct drive_info; - byte cmos_disks, *BIOS = (byte *) &drive_info; - int unit; - unsigned long flags; - -#ifdef CONFIG_BLK_DEV_PDC4030 - if (hwif->chipset == ide_pdc4030 && hwif->channel != 0) - return; -#endif /* CONFIG_BLK_DEV_PDC4030 */ - spin_lock_irqsave(&rtc_lock, flags); - cmos_disks = CMOS_READ(0x12); - spin_unlock_irqrestore(&rtc_lock, flags); - /* Extract drive geometry from CMOS+BIOS if not already setup */ - for (unit = 0; unit < MAX_DRIVES; ++unit) { - ide_drive_t *drive = &hwif->drives[unit]; - - if ((cmos_disks & (0xf0 >> (unit*4))) - && !drive->present && !drive->nobios) { - unsigned short cyl = *(unsigned short *)BIOS; - unsigned char head = *(BIOS+2); - unsigned char sect = *(BIOS+14); - if (cyl > 0 && head > 0 && sect > 0 && sect < 64) { - drive->cyl = drive->bios_cyl = cyl; - drive->head = drive->bios_head = head; - drive->sect = drive->bios_sect = sect; - drive->ctl = *(BIOS+8); - } else { - printk("hd%c: C/H/S=%d/%d/%d from BIOS ignored\n", - unit+'a', cyl, head, sect); - } - } - - BIOS += 16; - } -#endif -} -#endif /* CONFIG_BLK_DEV_IDE */ - - #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) extern ide_drive_t * get_info_ptr(kdev_t); @@ -105,14 +27,14 @@ ontrack(ide_drive_t *drive, int heads, unsigned int *c, int *h, int *s) { unsigned long total; /* - * The specs say: take geometry as obtained from Identify, - * compute total capacity C*H*S from that, and truncate to - * 1024*255*63. Now take S=63, H the first in the sequence - * 4, 8, 16, 32, 64, 128, 255 such that 63*H*1024 >= total. - * [Please tell aeb@cwi.nl in case this computes a - * geometry different from what OnTrack uses.] + * The specs say: take geometry as obtained from Identify, compute + * total capacity C*H*S from that, and truncate to 1024*255*63. Now + * take S=63, H the first in the sequence 4, 8, 16, 32, 64, 128, 255 + * such that 63*H*1024 >= total. [Please tell aeb@cwi.nl in case this + * computes a geometry different from what OnTrack uses.] */ - total = DRIVER(drive)->capacity(drive); + + total = ata_ops(drive)->capacity(drive); *s = 63; diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 838157105788..37fbf82d2dc2 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -130,17 +130,17 @@ static inline void do_identify (ide_drive_t *drive, byte cmd) } #endif /* CONFIG_BLK_DEV_PDC4030 */ switch (type) { - case ide_floppy: + case ATA_FLOPPY: if (!strstr(id->model, "CD-ROM")) { if (!strstr(id->model, "oppy") && !strstr(id->model, "poyp") && !strstr(id->model, "ZIP")) printk("cdrom or floppy?, assuming "); - if (drive->media != ide_cdrom) { + if (drive->type != ATA_ROM) { printk ("FLOPPY"); break; } } - type = ide_cdrom; /* Early cdrom models used zero */ - case ide_cdrom: + type = ATA_ROM; /* Early cdrom models used zero */ + case ATA_ROM: drive->removable = 1; #ifdef CONFIG_PPC /* kludge for Apple PowerBook internal zip */ @@ -152,10 +152,10 @@ static inline void do_identify (ide_drive_t *drive, byte cmd) #endif printk ("CD/DVD-ROM"); break; - case ide_tape: + case ATA_TAPE: printk ("TAPE"); break; - case ide_optical: + case ATA_MOD: printk ("OPTICAL"); drive->removable = 1; break; @@ -164,7 +164,7 @@ static inline void do_identify (ide_drive_t *drive, byte cmd) break; } printk (" drive\n"); - drive->media = type; + drive->type = type; return; } @@ -184,7 +184,7 @@ static inline void do_identify (ide_drive_t *drive, byte cmd) mate->noprobe = 1; } } - drive->media = ide_disk; + drive->type = ATA_DISK; printk("ATA DISK drive\n"); QUIRK_LIST(HWIF(drive),drive); return; @@ -327,12 +327,12 @@ static int do_probe (ide_drive_t *drive, byte cmd) int rc; ide_hwif_t *hwif = HWIF(drive); if (drive->present) { /* avoid waiting for inappropriate probes */ - if ((drive->media != ide_disk) && (cmd == WIN_IDENTIFY)) + if ((drive->type != ATA_DISK) && (cmd == WIN_IDENTIFY)) return 4; } #ifdef DEBUG - printk("probing for %s: present=%d, media=%d, probetype=%s\n", - drive->name, drive->present, drive->media, + printk("probing for %s: present=%d, type=%d, probetype=%s\n", + drive->name, drive->present, drive->type, (cmd == WIN_IDENTIFY) ? "ATA" : "ATAPI"); #endif ide_delay_50ms(); /* needed for some systems (e.g. crw9624 as drive0 with disk as slave) */ @@ -421,10 +421,10 @@ static inline void probe_for_drive (ide_drive_t *drive) if (!drive->present) return; /* drive not found */ if (drive->id == NULL) { /* identification failed? */ - if (drive->media == ide_disk) { + if (drive->type == ATA_DISK) { printk ("%s: non-IDE drive, CHS=%d/%d/%d\n", drive->name, drive->cyl, drive->head, drive->sect); - } else if (drive->media == ide_cdrom) { + } else if (drive->type == ATA_ROM) { printk("%s: ATAPI cdrom (?)\n", drive->name); } else { drive->present = 0; /* nuke it */ @@ -481,33 +481,31 @@ static void hwif_register (ide_hwif_t *hwif) ((unsigned long)hwif->io_ports[IDE_STATUS_OFFSET])) { ide_request_region(hwif->io_ports[IDE_DATA_OFFSET], 8, hwif->name); hwif->straight8 = 1; - goto jump_straight8; - } - - if (hwif->io_ports[IDE_DATA_OFFSET]) - ide_request_region(hwif->io_ports[IDE_DATA_OFFSET], 1, hwif->name); - if (hwif->io_ports[IDE_ERROR_OFFSET]) - ide_request_region(hwif->io_ports[IDE_ERROR_OFFSET], 1, hwif->name); - if (hwif->io_ports[IDE_NSECTOR_OFFSET]) - ide_request_region(hwif->io_ports[IDE_NSECTOR_OFFSET], 1, hwif->name); - if (hwif->io_ports[IDE_SECTOR_OFFSET]) - ide_request_region(hwif->io_ports[IDE_SECTOR_OFFSET], 1, hwif->name); - if (hwif->io_ports[IDE_LCYL_OFFSET]) - ide_request_region(hwif->io_ports[IDE_LCYL_OFFSET], 1, hwif->name); - if (hwif->io_ports[IDE_HCYL_OFFSET]) - ide_request_region(hwif->io_ports[IDE_HCYL_OFFSET], 1, hwif->name); - if (hwif->io_ports[IDE_SELECT_OFFSET]) - ide_request_region(hwif->io_ports[IDE_SELECT_OFFSET], 1, hwif->name); - if (hwif->io_ports[IDE_STATUS_OFFSET]) - ide_request_region(hwif->io_ports[IDE_STATUS_OFFSET], 1, hwif->name); - -jump_straight8: + } else { + if (hwif->io_ports[IDE_DATA_OFFSET]) + ide_request_region(hwif->io_ports[IDE_DATA_OFFSET], 1, hwif->name); + if (hwif->io_ports[IDE_ERROR_OFFSET]) + ide_request_region(hwif->io_ports[IDE_ERROR_OFFSET], 1, hwif->name); + if (hwif->io_ports[IDE_NSECTOR_OFFSET]) + ide_request_region(hwif->io_ports[IDE_NSECTOR_OFFSET], 1, hwif->name); + if (hwif->io_ports[IDE_SECTOR_OFFSET]) + ide_request_region(hwif->io_ports[IDE_SECTOR_OFFSET], 1, hwif->name); + if (hwif->io_ports[IDE_LCYL_OFFSET]) + ide_request_region(hwif->io_ports[IDE_LCYL_OFFSET], 1, hwif->name); + if (hwif->io_ports[IDE_HCYL_OFFSET]) + ide_request_region(hwif->io_ports[IDE_HCYL_OFFSET], 1, hwif->name); + if (hwif->io_ports[IDE_SELECT_OFFSET]) + ide_request_region(hwif->io_ports[IDE_SELECT_OFFSET], 1, hwif->name); + if (hwif->io_ports[IDE_STATUS_OFFSET]) + ide_request_region(hwif->io_ports[IDE_STATUS_OFFSET], 1, hwif->name); + + } if (hwif->io_ports[IDE_CONTROL_OFFSET]) ide_request_region(hwif->io_ports[IDE_CONTROL_OFFSET], 1, hwif->name); #if defined(CONFIG_AMIGA) || defined(CONFIG_MAC) if (hwif->io_ports[IDE_IRQ_OFFSET]) ide_request_region(hwif->io_ports[IDE_IRQ_OFFSET], 1, hwif->name); -#endif /* (CONFIG_AMIGA) || (CONFIG_MAC) */ +#endif } /* @@ -521,13 +519,6 @@ static void probe_hwif (ide_hwif_t *hwif) if (hwif->noprobe) return; -#ifdef CONFIG_BLK_DEV_IDE - if (hwif->io_ports[IDE_DATA_OFFSET] == HD_DATA) { - extern void probe_cmos_for_drives(ide_hwif_t *); - - probe_cmos_for_drives (hwif); - } -#endif if ((hwif->chipset != ide_4drives || !hwif->mate->present) && #if CONFIG_BLK_DEV_PDC4030 @@ -545,7 +536,7 @@ static void probe_hwif (ide_hwif_t *hwif) } if (!msgout) printk("%s: ports already in use, skipping probe\n", hwif->name); - return; + return; } __save_flags(flags); /* local CPU only */ @@ -796,60 +787,51 @@ static int init_irq (ide_hwif_t *hwif) static void init_gendisk (ide_hwif_t *hwif) { struct gendisk *gd; - unsigned int unit, units, minors, i; + unsigned int unit, minors, i; extern devfs_handle_t ide_devfs_handle; -#if 1 - units = MAX_DRIVES; -#else - /* figure out maximum drive number on the interface */ - for (units = MAX_DRIVES; units > 0; --units) { - if (hwif->drives[units-1].present) - break; - } -#endif - - minors = units * (1<sizes = kmalloc (minors * sizeof(int), GFP_KERNEL); if (!gd->sizes) goto err_kmalloc_gd_sizes; + gd->part = kmalloc (minors * sizeof(struct hd_struct), GFP_KERNEL); if (!gd->part) goto err_kmalloc_gd_part; + memset(gd->part, 0, minors * sizeof(struct hd_struct)); + blksize_size[hwif->major] = kmalloc (minors*sizeof(int), GFP_KERNEL); if (!blksize_size[hwif->major]) goto err_kmalloc_bs; - - memset(gd->part, 0, minors * sizeof(struct hd_struct)); - for (i = 0; i < minors; ++i) blksize_size[hwif->major][i] = BLOCK_SIZE; - for (unit = 0; unit < units; ++unit) + + for (unit = 0; unit < MAX_DRIVES; ++unit) hwif->drives[unit].part = &gd->part[unit << PARTN_BITS]; gd->major = hwif->major; /* our major device number */ gd->major_name = IDE_MAJOR_NAME; /* treated special in genhd.c */ gd->minor_shift = PARTN_BITS; /* num bits for partitions */ - gd->nr_real = units; /* current num real drives */ + gd->nr_real = MAX_DRIVES; /* current num real drives */ gd->next = NULL; /* linked list of major devs */ gd->fops = ide_fops; /* file operations */ - gd->de_arr = kmalloc (sizeof *gd->de_arr * units, GFP_KERNEL); - gd->flags = kmalloc (sizeof *gd->flags * units, GFP_KERNEL); + gd->de_arr = kmalloc(sizeof(*gd->de_arr) * MAX_DRIVES, GFP_KERNEL); + gd->flags = kmalloc(sizeof(*gd->flags) * MAX_DRIVES, GFP_KERNEL); if (gd->de_arr) - memset (gd->de_arr, 0, sizeof *gd->de_arr * units); + memset(gd->de_arr, 0, sizeof(*gd->de_arr) * MAX_DRIVES); if (gd->flags) - memset (gd->flags, 0, sizeof *gd->flags * units); + memset(gd->flags, 0, sizeof(*gd->flags) * MAX_DRIVES); hwif->gd = gd; add_gendisk(gd); - for (unit = 0; unit < units; ++unit) { -#if 1 - char name[64]; + for (unit = 0; unit < MAX_DRIVES; ++unit) { + char name[80]; ide_add_generic_settings(hwif->drives + unit); hwif->drives[unit].dn = ((hwif->channel ? 2 : 0) + unit); sprintf (name, "host%d/bus%d/target%d/lun%d", @@ -858,19 +840,6 @@ static void init_gendisk (ide_hwif_t *hwif) hwif->channel, unit, hwif->drives[unit].lun); if (hwif->drives[unit].present) hwif->drives[unit].de = devfs_mk_dir(ide_devfs_handle, name, NULL); -#else - if (hwif->drives[unit].present) { - char name[64]; - - ide_add_generic_settings(hwif->drives + unit); - hwif->drives[unit].dn = ((hwif->channel ? 2 : 0) + unit); - sprintf (name, "host%d/bus%d/target%d/lun%d", - (hwif->channel && hwif->mate) ? hwif->mate->index : hwif->index, - hwif->channel, unit, hwif->drives[unit].lun); - hwif->drives[unit].de = - devfs_mk_dir (ide_devfs_handle, name, NULL); - } -#endif } return; @@ -881,7 +850,7 @@ err_kmalloc_gd_part: err_kmalloc_gd_sizes: kfree(gd); err_kmalloc_gd: - printk(KERN_WARNING "(ide::init_gendisk) Out of memory\n"); + printk(KERN_CRIT "(ide::init_gendisk) Out of memory\n"); return; } diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c index a60eb63a6192..468d91c2ac1c 100644 --- a/drivers/ide/ide-proc.c +++ b/drivers/ide/ide-proc.c @@ -202,7 +202,7 @@ static int proc_ide_get_identify(ide_drive_t *drive, byte *buf) memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr)); taskfile.sector_count = 0x01; - taskfile.command = (drive->media == ide_disk) ? WIN_IDENTIFY : WIN_PIDENTIFY ; + taskfile.command = (drive->type == ATA_DISK) ? WIN_IDENTIFY : WIN_PIDENTIFY ; return ide_wait_taskfile(drive, &taskfile, &hobfile, buf); } @@ -346,9 +346,9 @@ parse_error: int proc_ide_read_capacity (char *page, char **start, off_t off, int count, int *eof, void *data) { - ide_drive_t *drive = data; - ide_driver_t *driver = drive->driver; - int len; + ide_drive_t *drive = data; + struct ata_operations *driver = drive->driver; + int len; if (!driver) len = sprintf(page, "(none)\n"); @@ -381,58 +381,31 @@ static int proc_ide_read_dmodel PROC_IDE_READ_RETURN(page,start,off,count,eof,len); } -static int proc_ide_read_driver - (char *page, char **start, off_t off, int count, int *eof, void *data) -{ - ide_drive_t *drive = (ide_drive_t *) data; - ide_driver_t *driver = drive->driver; - int len; - - if (!driver) - len = sprintf(page, "(none)\n"); - else - len = sprintf(page, "%s\n", driver->name); - PROC_IDE_READ_RETURN(page,start,off,count,eof,len); -} - -static int proc_ide_write_driver - (struct file *file, const char *buffer, unsigned long count, void *data) -{ - ide_drive_t *drive = data; - - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - if (ide_replace_subdriver(drive, buffer)) - return -EINVAL; - return count; -} - static int proc_ide_read_media (char *page, char **start, off_t off, int count, int *eof, void *data) { ide_drive_t *drive = data; - const char *media; + const char *type; int len; - switch (drive->media) { - case ide_disk: media = "disk\n"; + switch (drive->type) { + case ATA_DISK: type = "disk\n"; break; - case ide_cdrom: media = "cdrom\n"; + case ATA_ROM: type = "cdrom\n"; break; - case ide_tape: media = "tape\n"; + case ATA_TAPE: type = "tape\n"; break; - case ide_floppy:media = "floppy\n"; + case ATA_FLOPPY:type = "floppy\n"; break; - default: media = "UNKNOWN\n"; + default: type = "UNKNOWN\n"; break; } - strcpy(page,media); - len = strlen(media); + strcpy(page,type); + len = strlen(type); PROC_IDE_READ_RETURN(page,start,off,count,eof,len); } static ide_proc_entry_t generic_drive_entries[] = { - { "driver", S_IFREG|S_IRUGO, proc_ide_read_driver, proc_ide_write_driver }, { "identify", S_IFREG|S_IRUSR, proc_ide_read_identify, NULL }, { "media", S_IFREG|S_IRUGO, proc_ide_read_media, NULL }, { "model", S_IFREG|S_IRUGO, proc_ide_read_dmodel, NULL }, @@ -476,7 +449,7 @@ static void create_proc_ide_drives(ide_hwif_t *hwif) for (d = 0; d < MAX_DRIVES; d++) { ide_drive_t *drive = &hwif->drives[d]; - ide_driver_t *driver = drive->driver; + struct ata_operations *driver = drive->driver; if (!drive->present) continue; @@ -497,35 +470,9 @@ static void create_proc_ide_drives(ide_hwif_t *hwif) } } -void recreate_proc_ide_device(ide_hwif_t *hwif, ide_drive_t *drive) -{ - struct proc_dir_entry *ent; - struct proc_dir_entry *parent = hwif->proc; - char name[64]; - - if (drive->present && !drive->proc) { - drive->proc = proc_mkdir(drive->name, parent); - if (drive->proc) - ide_add_proc_entries(drive->proc, generic_drive_entries, drive); - -/* - * assume that we have these already, however, should test FIXME! - * if (driver) { - * ide_add_proc_entries(drive->proc, generic_subdriver_entries, drive); - * ide_add_proc_entries(drive->proc, driver->proc, drive); - * } - * - */ - sprintf(name,"ide%d/%s", (drive->name[2]-'a')/2, drive->name); - ent = proc_symlink(drive->name, proc_ide_root, name); - if (!ent) - return; - } -} - -void destroy_proc_ide_device(ide_hwif_t *hwif, ide_drive_t *drive) +static void destroy_proc_ide_device(ide_hwif_t *hwif, ide_drive_t *drive) { - ide_driver_t *driver = drive->driver; + struct ata_operations *driver = drive->driver; if (drive->proc) { if (driver) diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index cc7f5d132703..e5d85ae7d381 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -6098,8 +6098,11 @@ static int idetape_cleanup (ide_drive_t *drive) } idetape_chrdevs[minor].drive = NULL; restore_flags (flags); /* all CPUs (overkill?) */ - DRIVER(drive)->busy = 0; - (void) ide_unregister_subdriver (drive); + + /* FIXME: this appears to be totally wrong! */ + ata_ops(drive)->busy = 0; + + ide_unregister_subdriver (drive); drive->driver_data = NULL; devfs_unregister (tape->de_r); devfs_unregister (tape->de_n); @@ -6137,17 +6140,13 @@ static ide_proc_entry_t idetape_proc[] = { #endif -int idetape_reinit(ide_drive_t *drive); +static int idetape_reinit(ide_drive_t *drive); /* * IDE subdriver functions, registered with ide.c */ -static ide_driver_t idetape_driver = { - name: "ide-tape", - media: ide_tape, - busy: 1, - supports_dma: 1, - supports_dsc_overlap: 1, +static struct ata_operations idetape_driver = { + owner: THIS_MODULE, cleanup: idetape_cleanup, standby: NULL, flushcache: NULL, @@ -6176,90 +6175,10 @@ static struct file_operations idetape_fops = { release: idetape_chrdev_release, }; -int idetape_reinit (ide_drive_t *drive) +/* This will propably just go entierly away... */ +static int idetape_reinit (ide_drive_t *drive) { -#if 0 - idetape_tape_t *tape; - int minor, failed = 0, supported = 0; -/* DRIVER(drive)->busy++; */ - MOD_INC_USE_COUNT; -#if ONSTREAM_DEBUG - printk(KERN_INFO "ide-tape: MOD_INC_USE_COUNT in idetape_init\n"); -#endif - if (!idetape_chrdev_present) - for (minor = 0; minor < MAX_HWIFS * MAX_DRIVES; minor++ ) - idetape_chrdevs[minor].drive = NULL; - - if ((drive = ide_scan_devices (ide_tape, idetape_driver.name, NULL, failed++)) == NULL) { - revalidate_drives(); - MOD_DEC_USE_COUNT; -#if ONSTREAM_DEBUG - printk(KERN_INFO "ide-tape: MOD_DEC_USE_COUNT in idetape_init\n"); -#endif - return 0; - } - if (!idetape_chrdev_present && - devfs_register_chrdev (IDETAPE_MAJOR, "ht", &idetape_fops)) { - printk (KERN_ERR "ide-tape: Failed to register character device interface\n"); - MOD_DEC_USE_COUNT; -#if ONSTREAM_DEBUG - printk(KERN_INFO "ide-tape: MOD_DEC_USE_COUNT in idetape_init\n"); -#endif - return -EBUSY; - } - do { - if (!idetape_identify_device (drive, drive->id)) { - printk (KERN_ERR "ide-tape: %s: not supported by this version of ide-tape\n", drive->name); - continue; - } - if (drive->scsi) { - if (strstr(drive->id->model, "OnStream DI-30")) { - printk("ide-tape: ide-scsi emulation is not supported for %s.\n", drive->id->model); - } else { - printk("ide-tape: passing drive %s to ide-scsi emulation.\n", drive->name); - continue; - } - } - tape = (idetape_tape_t *) kmalloc (sizeof (idetape_tape_t), GFP_KERNEL); - if (tape == NULL) { - printk (KERN_ERR "ide-tape: %s: Can't allocate a tape structure\n", drive->name); - continue; - } - if (ide_register_subdriver (drive, &idetape_driver)) { - printk (KERN_ERR "ide-tape: %s: Failed to register the driver with ide.c\n", drive->name); - kfree (tape); - continue; - } - for (minor = 0; idetape_chrdevs[minor].drive != NULL; minor++); - idetape_setup (drive, tape, minor); - idetape_chrdevs[minor].drive = drive; - tape->de_r = - devfs_register (drive->de, "mt", DEVFS_FL_DEFAULT, - HWIF(drive)->major, minor, - S_IFCHR | S_IRUGO | S_IWUGO, - &idetape_fops, NULL); - tape->de_n = - devfs_register (drive->de, "mtn", DEVFS_FL_DEFAULT, - HWIF(drive)->major, minor + 128, - S_IFCHR | S_IRUGO | S_IWUGO, - &idetape_fops, NULL); - devfs_register_tape (tape->de_r); - supported++; failed--; - } while ((drive = ide_scan_devices (ide_tape, idetape_driver.name, NULL, failed++)) != NULL); - if (!idetape_chrdev_present && !supported) { - devfs_unregister_chrdev (IDETAPE_MAJOR, "ht"); - } else - idetape_chrdev_present = 1; - revalidate_drives(); - MOD_DEC_USE_COUNT; -#if ONSTREAM_DEBUG - printk(KERN_INFO "ide-tape: MOD_DEC_USE_COUNT in idetape_init\n"); -#endif - - return 0; -#else return 1; -#endif } MODULE_DESCRIPTION("ATAPI Streaming TAPE Driver"); @@ -6294,7 +6213,7 @@ int idetape_init (void) for (minor = 0; minor < MAX_HWIFS * MAX_DRIVES; minor++ ) idetape_chrdevs[minor].drive = NULL; - if ((drive = ide_scan_devices (ide_tape, idetape_driver.name, NULL, failed++)) == NULL) { + if ((drive = ide_scan_devices(ATA_TAPE, "ide-tape", NULL, failed++)) == NULL) { revalidate_drives(); MOD_DEC_USE_COUNT; #if ONSTREAM_DEBUG @@ -6349,7 +6268,7 @@ int idetape_init (void) &idetape_fops, NULL); devfs_register_tape (tape->de_r); supported++; failed--; - } while ((drive = ide_scan_devices (ide_tape, idetape_driver.name, NULL, failed++)) != NULL); + } while ((drive = ide_scan_devices(ATA_TAPE, "ide-tape", NULL, failed++)) != NULL); if (!idetape_chrdev_present && !supported) { devfs_unregister_chrdev (IDETAPE_MAJOR, "ht"); } else diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c index 61532dbbefa2..75fa398fc363 100644 --- a/drivers/ide/ide-taskfile.c +++ b/drivers/ide/ide-taskfile.c @@ -648,7 +648,7 @@ ide_startstop_t taskfile_error (ide_drive_t *drive, const char *msg, byte stat) if (rq->errors >= ERROR_MAX) { if (drive->driver != NULL) - DRIVER(drive)->end_request(0, HWGROUP(drive)); + ata_ops(drive)->end_request(0, HWGROUP(drive)); else ide_end_request(drive, 0); } else { diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index ba30830ca97f..944f69636012 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -1,6 +1,4 @@ /* - * linux/drivers/ide/ide.c Version 6.31 June 9, 2000 - * * Copyright (C) 1994-1998 Linus Torvalds & authors (see below) */ @@ -114,17 +112,12 @@ * Native ATA-100 support * Prep for Cascades Project * Version 6.32 4GB highmem support for DMA, and mapping of those for - * PIO transfer (Jens Axboe) + * PIO transfer (Jens Axboe) * * Some additional driver compile-time options are in ./include/linux/ide.h - * - * To do, in likely order of completion: - * - modify kernel to obtain BIOS geometry for drives on 2nd/3rd/4th i/f - * */ -#define REVISION "Revision: 6.32" -#define VERSION "Id: ide.c 6.32 2001/05/24" +#define VERSION "7.0.0" #undef REALLY_SLOW_IO /* most systems can safely undef this */ @@ -254,8 +247,6 @@ static struct ide_pio_info { /* default maximum number of failures */ #define IDE_DEFAULT_MAX_FAILURES 1 -static const byte ide_hwif_to_major[] = { IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR, IDE4_MAJOR, IDE5_MAJOR, IDE6_MAJOR, IDE7_MAJOR, IDE8_MAJOR, IDE9_MAJOR }; - static int idebus_parameter; /* holds the "idebus=" parameter */ int system_bus_speed; /* holds what we think is VESA/PCI bus speed */ static int initializing; /* set while initializing built-in drivers */ @@ -418,6 +409,11 @@ static inline void set_recovery_timer (ide_hwif_t *hwif) */ static void init_hwif_data (unsigned int index) { + static const byte ide_major[] = { + IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR, IDE4_MAJOR, + IDE5_MAJOR, IDE6_MAJOR, IDE7_MAJOR, IDE8_MAJOR, IDE9_MAJOR + }; + unsigned int unit; hw_regs_t hw; ide_hwif_t *hwif = &ide_hwifs[index]; @@ -436,16 +432,13 @@ static void init_hwif_data (unsigned int index) if (hwif->io_ports[IDE_DATA_OFFSET] == HD_DATA) hwif->noprobe = 1; /* may be overridden by ide_setup() */ #endif /* CONFIG_BLK_DEV_HD */ - hwif->major = ide_hwif_to_major[index]; - hwif->name[0] = 'i'; - hwif->name[1] = 'd'; - hwif->name[2] = 'e'; - hwif->name[3] = '0' + index; + hwif->major = ide_major[index]; + sprintf(hwif->name, "ide%d", index); hwif->bus_state = BUSSTATE_ON; for (unit = 0; unit < MAX_DRIVES; ++unit) { ide_drive_t *drive = &hwif->drives[unit]; - drive->media = ide_disk; + drive->type = ATA_DISK; drive->select.all = (unit<<4)|0xa0; drive->hwif = hwif; drive->ctl = 0x08; @@ -453,9 +446,7 @@ static void init_hwif_data (unsigned int index) drive->bad_wstat = BAD_W_STAT; drive->special.b.recalibrate = 1; drive->special.b.set_geometry = 1; - drive->name[0] = 'h'; - drive->name[1] = 'd'; - drive->name[2] = 'a' + (index * MAX_DRIVES) + unit; + sprintf(drive->name, "hd%c", 'a' + (index * MAX_DRIVES) + unit); drive->max_failures = IDE_DEFAULT_MAX_FAILURES; init_waitqueue_head(&drive->wqueue); } @@ -591,19 +582,18 @@ void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler, } /* - * current_capacity() returns the capacity (in sectors) of a drive - * according to its current geometry/LBA settings. + * The capacity of a drive according to its current geometry/LBA settings in + * sectors. */ unsigned long current_capacity (ide_drive_t *drive) { - if (!drive->present) + if (!drive->present || !drive->driver) return 0; - if (drive->driver != NULL) - return DRIVER(drive)->capacity(drive); - return 0; + return ata_ops(drive)->capacity(drive); } extern struct block_device_operations ide_fops[]; + /* * ide_geninit() is called exactly *once* for each interface. */ @@ -617,7 +607,7 @@ void ide_geninit (ide_hwif_t *hwif) if (!drive->present) continue; - if (drive->media!=ide_disk && drive->media!=ide_floppy) + if (drive->type != ATA_DISK && drive->type != ATA_FLOPPY) continue; register_disk(gd,mk_kdev(hwif->major,unit<driver != NULL) - DRIVER(drive)->pre_reset(drive); + ata_ops(drive)->pre_reset(drive); if (!drive->keep_settings) { if (drive->using_dma) { @@ -769,7 +759,7 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi) __cli(); /* local CPU only */ /* For an ATAPI device, first try an ATAPI SRST. */ - if (drive->media != ide_disk && !do_not_try_atapi) { + if (drive->type != ATA_DISK && !do_not_try_atapi) { pre_reset(drive); SELECT_DRIVE(hwif,drive); udelay (20); @@ -938,7 +928,7 @@ byte ide_dump_status (ide_drive_t *drive, const char *msg, byte stat) err = GET_ERR(); printk("%s: %s: error=0x%02x", drive->name, msg, err); #if FANCY_STATUS_DUMPS - if (drive->media == ide_disk) { + if (drive->type == ATA_DISK) { printk(" { "); if (err & ABRT_ERR) printk("DriveStatusError "); if (err & ICRC_ERR) printk("%s", (err & ABRT_ERR) ? "BadCRC " : "BadSector "); @@ -997,7 +987,7 @@ static void try_to_flush_leftover_data (ide_drive_t *drive) { int i = (drive->mult_count ? drive->mult_count : 1) * SECTOR_WORDS; - if (drive->media != ide_disk) + if (drive->type != ATA_DISK) return; while (i > 0) { u32 buffer[16]; @@ -1033,7 +1023,7 @@ ide_startstop_t ide_error (ide_drive_t *drive, const char *msg, byte stat) if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr)) { /* other bits are useless when BUSY */ rq->errors |= ERROR_RESET; } else { - if (drive->media == ide_disk && (stat & ERR_STAT)) { + if (drive->type == ATA_DISK && (stat & ERR_STAT)) { /* err has different meaning on cdrom and tape */ if (err == ABRT_ERR) { if (drive->select.b.lba && IN_BYTE(IDE_COMMAND_REG) == WIN_SPECIFY) @@ -1053,8 +1043,9 @@ ide_startstop_t ide_error (ide_drive_t *drive, const char *msg, byte stat) OUT_BYTE(WIN_IDLEIMMEDIATE,IDE_COMMAND_REG); /* force an abort */ if (rq->errors >= ERROR_MAX) { + /* ATA-PATTERN */ if (drive->driver != NULL) - DRIVER(drive)->end_request(drive, 0); + ata_ops(drive)->end_request(drive, 0); else ide_end_request(drive, 0); } else { @@ -1126,7 +1117,7 @@ static ide_startstop_t do_special (ide_drive_t *drive) if (tuneproc != NULL) tuneproc(drive, drive->tune_req); } else if (drive->driver != NULL) { - return DRIVER(drive)->special(drive); + return ata_ops(drive)->special(drive); } else if (s->all) { printk("%s: bad special flag: 0x%02x\n", drive->name, s->all); s->all = 0; @@ -1324,8 +1315,8 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq) block = rq->sector; /* Strange disk manager remap */ - if ((rq->flags & REQ_CMD) && - (drive->media == ide_disk || drive->media == ide_floppy)) { + if ((rq->flags & REQ_CMD) && + (drive->type == ATA_DISK || drive->type == ATA_FLOPPY)) { block += drive->sect0; } /* Yecch - this will shift the entire interval, @@ -1340,7 +1331,7 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq) SELECT_DRIVE(hwif, drive); if (ide_wait_stat(&startstop, drive, drive->ready_stat, BUSY_STAT|DRQ_STAT, WAIT_READY)) { - printk("%s: drive not ready for command\n", drive->name); + printk(KERN_WARNING "%s: drive not ready for command\n", drive->name); return startstop; } if (!drive->special.all) { @@ -1348,16 +1339,16 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq) return execute_drive_cmd(drive, rq); if (drive->driver != NULL) { - return (DRIVER(drive)->do_request(drive, rq, block)); + return ata_ops(drive)->do_request(drive, rq, block); } - printk("%s: media type %d not supported\n", - drive->name, drive->media); + printk(KERN_WARNING "%s: device type %d not supported\n", + drive->name, drive->type); goto kill_rq; } return do_special(drive); kill_rq: if (drive->driver != NULL) - DRIVER(drive)->end_request(drive, 0); + ata_ops(drive)->end_request(drive, 0); else ide_end_request(drive, 0); return ide_stopped; @@ -1987,8 +1978,8 @@ int ide_revalidate_disk (kdev_t i_rdev) if (res) goto leave; - if (DRIVER(drive)->revalidate) - DRIVER(drive)->revalidate(drive); + if (ata_ops(drive)->revalidate) + ata_ops(drive)->revalidate(drive); leave: drive->busy = 0; @@ -2014,7 +2005,7 @@ void revalidate_drives (void) if (drive->revalidate) { drive->revalidate = 0; if (!initializing) - (void) ide_revalidate_disk(mk_kdev(hwif->major, unit<major, unit<driver == NULL) ide_driver_module(); + + /* Request a particular device type module. + * + * FIXME: The function which should rather requests the drivers is + * ide_driver_module(), since it seems illogical and even a bit + * dangerous to delay this until open time! + */ + #ifdef CONFIG_KMOD if (drive->driver == NULL) { - if (drive->media == ide_disk) - (void) request_module("ide-disk"); - if (drive->media == ide_cdrom) - (void) request_module("ide-cd"); - if (drive->media == ide_tape) - (void) request_module("ide-tape"); - if (drive->media == ide_floppy) - (void) request_module("ide-floppy"); + switch (drive->type) { + case ATA_DISK: + request_module("ide-disk"); + break; + case ATA_ROM: + request_module("ide-cd"); + break; + case ATA_TAPE: + request_module("ide-tape"); + break; + case ATA_FLOPPY: + request_module("ide-floppy"); + break; #if defined(CONFIG_BLK_DEV_IDESCSI) && defined(CONFIG_SCSI) - if (drive->media == ide_scsi) - (void) request_module("ide-scsi"); -#endif /* defined(CONFIG_BLK_DEV_IDESCSI) && defined(CONFIG_SCSI) */ + case ATA_SCSI: + request_module("ide-scsi"); + break; +#endif + default: + /* nothing to be done about it */ ; + } } #endif /* CONFIG_KMOD */ while (drive->busy) sleep_on(&drive->wqueue); drive->usage++; if (drive->driver != NULL) - return DRIVER(drive)->open(inode, filp, drive); + return ata_ops(drive)->open(inode, filp, drive); printk ("%s: driver not present\n", drive->name); drive->usage--; return -ENXIO; @@ -2084,27 +2092,11 @@ static int ide_release (struct inode * inode, struct file * file) if ((drive = get_info_ptr(inode->i_rdev)) != NULL) { drive->usage--; if (drive->driver != NULL) - DRIVER(drive)->release(inode, file, drive); + ata_ops(drive)->release(inode, file, drive); } return 0; } -int ide_replace_subdriver (ide_drive_t *drive, const char *driver) -{ - if (!drive->present || drive->busy || drive->usage) - goto abort; - if (drive->driver != NULL && DRIVER(drive)->cleanup(drive)) - goto abort; - strncpy(drive->driver_req, driver, 9); - ide_driver_module(); - drive->driver_req[0] = 0; - ide_driver_module(); - if (DRIVER(drive) && !strcmp(DRIVER(drive)->name, driver)) - return 0; -abort: - return 1; -} - #ifdef CONFIG_PROC_FS ide_proc_entry_t generic_subdriver_entries[] = { { "capacity", S_IFREG|S_IRUGO, proc_ide_read_capacity, NULL }, @@ -2172,7 +2164,7 @@ void ide_unregister (unsigned int index) continue; if (drive->busy || drive->usage) goto abort; - if (drive->driver != NULL && DRIVER(drive)->cleanup(drive)) + if (drive->driver != NULL && ata_ops(drive)->cleanup(drive)) goto abort; } hwif->present = 0; @@ -2306,7 +2298,6 @@ void ide_unregister (unsigned int index) hwif->pci_dev = old_hwif.pci_dev; #endif /* CONFIG_BLK_DEV_IDEPCI */ hwif->straight8 = old_hwif.straight8; - hwif->hwif_data = old_hwif.hwif_data; abort: restore_flags(flags); /* all CPUs */ } @@ -2562,7 +2553,7 @@ static int set_io_32bit(ide_drive_t *drive, int arg) static int set_using_dma (ide_drive_t *drive, int arg) { - if (!drive->driver || !DRIVER(drive)->supports_dma) + if (!drive->driver) return -EPERM; if (!drive->id || !(drive->id->capability & 1) || !HWIF(drive)->dmaproc) return -EPERM; @@ -2690,7 +2681,9 @@ static int ide_ioctl (struct inode *inode, struct file *file, { struct hd_geometry *loc = (struct hd_geometry *) arg; unsigned short bios_cyl = drive->bios_cyl; /* truncate */ - if (!loc || (drive->media != ide_disk && drive->media != ide_floppy)) return -EINVAL; + + if (!loc || (drive->type != ATA_DISK && drive->type != ATA_FLOPPY)) + return -EINVAL; if (put_user(drive->bios_head, (byte *) &loc->heads)) return -EFAULT; if (put_user(drive->bios_sect, (byte *) &loc->sectors)) return -EFAULT; if (put_user(bios_cyl, (unsigned short *) &loc->cylinders)) return -EFAULT; @@ -2702,7 +2695,9 @@ static int ide_ioctl (struct inode *inode, struct file *file, case HDIO_GETGEO_BIG: { struct hd_big_geometry *loc = (struct hd_big_geometry *) arg; - if (!loc || (drive->media != ide_disk && drive->media != ide_floppy)) return -EINVAL; + + if (!loc || (drive->type != ATA_DISK && drive->type != ATA_FLOPPY)) + return -EINVAL; if (put_user(drive->bios_head, (byte *) &loc->heads)) return -EFAULT; if (put_user(drive->bios_sect, (byte *) &loc->sectors)) return -EFAULT; @@ -2715,7 +2710,8 @@ static int ide_ioctl (struct inode *inode, struct file *file, case HDIO_GETGEO_BIG_RAW: { struct hd_big_geometry *loc = (struct hd_big_geometry *) arg; - if (!loc || (drive->media != ide_disk && drive->media != ide_floppy)) return -EINVAL; + if (!loc || (drive->type != ATA_DISK && drive->type != ATA_FLOPPY)) + return -EINVAL; if (put_user(drive->head, (byte *) &loc->heads)) return -EFAULT; if (put_user(drive->sect, (byte *) &loc->sectors)) return -EFAULT; if (put_user(drive->cyl, (unsigned int *) &loc->cylinders)) return -EFAULT; @@ -2750,15 +2746,15 @@ static int ide_ioctl (struct inode *inode, struct file *file, case HDIO_DRIVE_TASKFILE: if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) return -EACCES; - switch(drive->media) { - case ide_disk: + switch(drive->type) { + case ATA_DISK: return ide_taskfile_ioctl(drive, inode, file, cmd, arg); #ifdef CONFIG_PKT_TASK_IOCTL - case ide_cdrom: - case ide_tape: - case ide_floppy: + case ATA_CDROM: + case ATA_TAPE: + case ATA_FLOPPY: return pkt_taskfile_ioctl(drive, inode, file, cmd, arg); -#endif /* CONFIG_PKT_TASK_IOCTL */ +#endif default: return -ENOMSG; } @@ -2791,12 +2787,11 @@ static int ide_ioctl (struct inode *inode, struct file *file, return 0; case HDIO_SET_NICE: if (!capable(CAP_SYS_ADMIN)) return -EACCES; - if (drive->driver == NULL) - return -EPERM; if (arg != (arg & ((1 << IDE_NICE_DSC_OVERLAP) | (1 << IDE_NICE_1)))) return -EPERM; drive->dsc_overlap = (arg >> IDE_NICE_DSC_OVERLAP) & 1; - if (drive->dsc_overlap && !DRIVER(drive)->supports_dsc_overlap) { + /* Only CD-ROM's and tapes support DSC overlap. */ + if (drive->dsc_overlap && !(drive->type == ATA_ROM || drive->type == ATA_TAPE)) { drive->dsc_overlap = 0; return -EPERM; } @@ -2872,7 +2867,7 @@ static int ide_ioctl (struct inode *inode, struct file *file, default: if (drive->driver != NULL) - return DRIVER(drive)->ioctl(drive, inode, file, cmd, arg); + return ata_ops(drive)->ioctl(drive, inode, file, cmd, arg); return -EPERM; } } @@ -2884,7 +2879,7 @@ static int ide_check_media_change (kdev_t i_rdev) if ((drive = get_info_ptr(i_rdev)) == NULL) return -ENODEV; if (drive->driver != NULL) - return DRIVER(drive)->media_change(drive); + return ata_ops(drive)->media_change(drive); return 0; } @@ -3068,7 +3063,6 @@ int __init ide_setup (char *s) const char max_drive = 'a' + ((MAX_HWIFS * MAX_DRIVES) - 1); const char max_hwif = '0' + (MAX_HWIFS - 1); - if (strncmp(s,"hd",2) == 0 && s[2] == '=') /* hd= is for hd.c */ return 0; /* driver and not us */ @@ -3146,7 +3140,7 @@ int __init ide_setup (char *s) goto done; case -4: /* "cdrom" */ drive->present = 1; - drive->media = ide_cdrom; + drive->type = ATA_ROM; hwif->noprobe = 0; goto done; case -5: /* "serialize" */ @@ -3183,7 +3177,7 @@ int __init ide_setup (char *s) goto bad_option; #endif /* defined(CONFIG_BLK_DEV_IDESCSI) && defined(CONFIG_SCSI) */ case 3: /* cyl,head,sect */ - drive->media = ide_disk; + drive->type = ATA_DISK; drive->cyl = drive->bios_cyl = vals[0]; drive->head = drive->bios_head = vals[1]; drive->sect = drive->bios_sect = vals[2]; @@ -3485,7 +3479,7 @@ void __init ide_init_builtin_drivers (void) } #endif /* __mc68000__ || CONFIG_APUS */ - (void) ideprobe_init(); + ideprobe_init(); #if defined(__mc68000__) || defined(CONFIG_APUS) if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET]) { @@ -3500,27 +3494,27 @@ void __init ide_init_builtin_drivers (void) #endif /* - * Attempt to match drivers for the available drives + * Initialize all device type driver modules. */ #ifdef CONFIG_BLK_DEV_IDEDISK idedisk_init(); -#endif /* CONFIG_BLK_DEV_IDEDISK */ +#endif #ifdef CONFIG_BLK_DEV_IDECD ide_cdrom_init(); -#endif /* CONFIG_BLK_DEV_IDECD */ +#endif #ifdef CONFIG_BLK_DEV_IDETAPE idetape_init(); -#endif /* CONFIG_BLK_DEV_IDETAPE */ +#endif #ifdef CONFIG_BLK_DEV_IDEFLOPPY idefloppy_init(); -#endif /* CONFIG_BLK_DEV_IDEFLOPPY */ +#endif #ifdef CONFIG_BLK_DEV_IDESCSI #ifdef CONFIG_SCSI idescsi_init(); #else #warning ide scsi-emulation selected but no SCSI-subsystem in kernel #endif -#endif /* CONFIG_BLK_DEV_IDESCSI */ +#endif } static int default_cleanup (ide_drive_t *drive) @@ -3596,7 +3590,10 @@ static int default_driver_reinit (ide_drive_t *drive) return 0; } -ide_drive_t *ide_scan_devices (byte media, const char *name, ide_driver_t *driver, int n) +/* + * Lookup IDE devices, which requested a particular deriver + */ +ide_drive_t *ide_scan_devices(byte type, const char *name, struct ata_operations *driver, int n) { unsigned int unit, index, i; @@ -3609,7 +3606,7 @@ ide_drive_t *ide_scan_devices (byte media, const char *name, ide_driver_t *drive char *req = drive->driver_req; if (*req && !strstr(name, req)) continue; - if (drive->present && drive->media == media && drive->driver == driver && ++i > n) + if (drive->present && drive->type == type && drive->driver == driver && ++i > n) return drive; } } @@ -3619,7 +3616,7 @@ ide_drive_t *ide_scan_devices (byte media, const char *name, ide_driver_t *drive /* * This is in fact registering a drive not a driver. */ -int ide_register_subdriver (ide_drive_t *drive, ide_driver_t *driver) +int ide_register_subdriver(ide_drive_t *drive, struct ata_operations *driver) { unsigned long flags; @@ -3663,18 +3660,24 @@ int ide_register_subdriver (ide_drive_t *drive, ide_driver_t *driver) driver->driver_reinit = default_driver_reinit; restore_flags(flags); /* all CPUs */ + /* FIXME: Check what this magic number is supposed to be about? */ if (drive->autotune != 2) { - if (driver->supports_dma && HWIF(drive)->dmaproc != NULL) { + if (HWIF(drive)->dmaproc != NULL) { + /* - * Force DMAing for the beginning of the check. - * Some chipsets appear to do interesting things, - * if not checked and cleared. + * Force DMAing for the beginning of the check. Some + * chipsets appear to do interesting things, if not + * checked and cleared. + * * PARANOIA!!! */ - (void) (HWIF(drive)->dmaproc(ide_dma_off_quietly, drive)); - (void) (HWIF(drive)->dmaproc(ide_dma_check, drive)); + + HWIF(drive)->dmaproc(ide_dma_off_quietly, drive); + HWIF(drive)->dmaproc(ide_dma_check, drive); } - drive->dsc_overlap = (drive->next != drive && driver->supports_dsc_overlap); + /* Only CD-ROMs and tape drives support DSC overlap. */ + drive->dsc_overlap = (drive->next != drive + && (drive->type == ATA_ROM || drive->type == ATA_TAPE)); drive->nice1 = 1; } drive->revalidate = 1; @@ -3686,13 +3689,13 @@ int ide_register_subdriver (ide_drive_t *drive, ide_driver_t *driver) return 0; } -int ide_unregister_subdriver (ide_drive_t *drive) +int ide_unregister_subdriver(ide_drive_t *drive) { unsigned long flags; save_flags(flags); /* all CPUs */ cli(); /* all CPUs */ - if (drive->usage || drive->busy || drive->driver == NULL || DRIVER(drive)->busy) { + if (drive->usage || drive->busy || drive->driver == NULL || ata_ops(drive)->busy) { restore_flags(flags); /* all CPUs */ return 1; } @@ -3700,7 +3703,7 @@ int ide_unregister_subdriver (ide_drive_t *drive) pnpide_init(0); #endif /* CONFIG_BLK_DEV_ISAPNP */ #ifdef CONFIG_PROC_FS - ide_remove_proc_entries(drive->proc, DRIVER(drive)->proc); + ide_remove_proc_entries(drive->proc, ata_ops(drive)->proc); ide_remove_proc_entries(drive->proc, generic_subdriver_entries); #endif auto_remove_settings(drive); @@ -3709,6 +3712,29 @@ int ide_unregister_subdriver (ide_drive_t *drive) return 0; } + +/* + * Register an ATA driver for a particular device type. + */ + +int register_ata_driver(unsigned int type, struct ata_operations *driver) +{ + return 0; +} + +EXPORT_SYMBOL(register_ata_driver); + +/* + * Unregister an ATA driver for a particular device type. + */ + +int unregister_ata_driver(unsigned int type, struct ata_operations *driver) +{ + return 0; +} + +EXPORT_SYMBOL(unregister_ata_driver); + struct block_device_operations ide_fops[] = {{ owner: THIS_MODULE, open: ide_open, @@ -3731,10 +3757,8 @@ EXPORT_SYMBOL(ide_lock); EXPORT_SYMBOL(drive_is_flashcard); EXPORT_SYMBOL(ide_timer_expiry); EXPORT_SYMBOL(ide_intr); -EXPORT_SYMBOL(ide_fops); EXPORT_SYMBOL(ide_get_queue); EXPORT_SYMBOL(ide_add_generic_settings); -EXPORT_SYMBOL(ide_devfs_handle); EXPORT_SYMBOL(do_ide_request); /* * Driver module @@ -3742,7 +3766,6 @@ EXPORT_SYMBOL(do_ide_request); EXPORT_SYMBOL(ide_scan_devices); EXPORT_SYMBOL(ide_register_subdriver); EXPORT_SYMBOL(ide_unregister_subdriver); -EXPORT_SYMBOL(ide_replace_subdriver); EXPORT_SYMBOL(ide_set_handler); EXPORT_SYMBOL(ide_dump_status); EXPORT_SYMBOL(ide_error); @@ -3766,9 +3789,6 @@ EXPORT_SYMBOL(ide_stall_queue); EXPORT_SYMBOL(ide_add_proc_entries); EXPORT_SYMBOL(ide_remove_proc_entries); EXPORT_SYMBOL(proc_ide_read_geometry); -EXPORT_SYMBOL(create_proc_ide_interfaces); -EXPORT_SYMBOL(recreate_proc_ide_device); -EXPORT_SYMBOL(destroy_proc_ide_device); #endif EXPORT_SYMBOL(ide_add_setting); EXPORT_SYMBOL(ide_remove_setting); @@ -3809,10 +3829,10 @@ static int ide_notify_reboot (struct notifier_block *this, unsigned long event, /* set the drive to standby */ printk("%s ", drive->name); if (event != SYS_RESTART) - if (drive->driver != NULL && DRIVER(drive)->standby(drive)) - continue; + if (drive->driver != NULL && ata_ops(drive)->standby(drive)) + continue; - if (drive->driver != NULL && DRIVER(drive)->cleanup(drive)) + if (drive->driver != NULL && ata_ops(drive)->cleanup(drive)) continue; } } @@ -3827,13 +3847,14 @@ static struct notifier_block ide_notifier = { }; /* - * This is gets invoked once during initialization, to set *everything* up + * This is the global initialization entry point. */ -int __init ide_init(void) +static int __init ata_module_init(void) { int i; - printk(KERN_INFO "Uniform Multi-Platform E-IDE driver " REVISION "\n"); + printk(KERN_INFO "Uniform Multi-Platform E-IDE driver ver.:" VERSION "\n"); + ide_devfs_handle = devfs_mk_dir (NULL, "ide", NULL); /* Initialize system bus speed. @@ -3859,7 +3880,9 @@ int __init ide_init(void) init_ide_data (); initializing = 1; + ide_init_builtin_drivers(); + initializing = 0; for (i = 0; i < MAX_HWIFS; ++i) { @@ -3872,8 +3895,7 @@ int __init ide_init(void) return 0; } -#ifdef MODULE -char *options = NULL; +static char *options = NULL; MODULE_PARM(options,"s"); MODULE_LICENSE("GPL"); @@ -3884,40 +3906,44 @@ static void __init parse_options (char *line) if (line == NULL || !*line) return; while ((line = next) != NULL) { - if ((next = strchr(line,' ')) != NULL) + if ((next = strchr(line,' ')) != NULL) *next++ = 0; if (!ide_setup(line)) printk ("Unknown option '%s'\n", line); } } -int init_module (void) +static int __init init_ata (void) { parse_options(options); - return ide_init(); + return ata_module_init(); } -void cleanup_module (void) +static void __exit cleanup_ata (void) { int index; unregister_reboot_notifier(&ide_notifier); for (index = 0; index < MAX_HWIFS; ++index) { ide_unregister(index); -#if defined(CONFIG_BLK_DEV_IDEDMA) && !defined(CONFIG_DMA_NONPCI) +# if defined(CONFIG_BLK_DEV_IDEDMA) && !defined(CONFIG_DMA_NONPCI) if (ide_hwifs[index].dma_base) (void) ide_release_dma(&ide_hwifs[index]); -#endif /* (CONFIG_BLK_DEV_IDEDMA) && !(CONFIG_DMA_NONPCI) */ +# endif /* (CONFIG_BLK_DEV_IDEDMA) && !(CONFIG_DMA_NONPCI) */ } -#ifdef CONFIG_PROC_FS +# ifdef CONFIG_PROC_FS proc_ide_destroy(); -#endif +# endif devfs_unregister (ide_devfs_handle); } -#else /* !MODULE */ +module_init(init_ata); +module_exit(cleanup_ata); +#ifndef MODULE + +/* command line option parser */ __setup("", ide_setup); -#endif /* MODULE */ +#endif diff --git a/drivers/ide/ns87415.c b/drivers/ide/ns87415.c index 1837f01e0edf..c29dd4a5655f 100644 --- a/drivers/ide/ns87415.c +++ b/drivers/ide/ns87415.c @@ -103,7 +103,7 @@ static int ns87415_dmaproc(ide_dma_action_t func, ide_drive_t *drive) ns87415_prepare_drive(drive, 0); /* DMA failed: select PIO xfer */ return 1; case ide_dma_check: - if (drive->media != ide_disk) + if (drive->type != ATA_DISK) return ide_dmaproc(ide_dma_off_quietly, drive); /* Fallthrough... */ default: diff --git a/drivers/ide/pdc202xx.c b/drivers/ide/pdc202xx.c index 6931c47b7aaf..a4d784a8d36d 100644 --- a/drivers/ide/pdc202xx.c +++ b/drivers/ide/pdc202xx.c @@ -63,7 +63,6 @@ static int pdc202xx_get_info(char *, char **, off_t, int); extern int (*pdc202xx_display_info)(char *, char **, off_t, int); /* ide-proc.c */ -extern char *ide_media_verbose(ide_drive_t *); static struct pci_dev *bmide_dev; char *pdc202xx_pio_verbose (u32 drive_pci) @@ -412,7 +411,8 @@ static int pdc202xx_tune_chipset (ide_drive_t *drive, byte speed) default: return -1; } - if ((drive->media != ide_disk) && (speed < XFER_SW_DMA_0)) return -1; + if ((drive->type != ATA_DISK) && (speed < XFER_SW_DMA_0)) + return -1; pci_read_config_dword(dev, drive_pci, &drive_conf); pci_read_config_byte(dev, (drive_pci), &AP); @@ -820,7 +820,8 @@ static int config_chipset_for_dma (ide_drive_t *drive, byte ultra) } if (jumpbit) { - if (drive->media != ide_disk) return ide_dma_off_quietly; + if (drive->type != ATA_DISK) + return ide_dma_off_quietly; if (id->capability & 4) { /* IORDY_EN & PREFETCH_EN */ OUT_BYTE((iordy + adj), indexreg); OUT_BYTE((IN_BYTE(datareg)|0x03), datareg); @@ -869,13 +870,14 @@ static int config_chipset_for_dma (ide_drive_t *drive, byte ultra) chipset_is_set: - if (drive->media != ide_disk) return ide_dma_off_quietly; + if (drive->type != ATA_DISK) + return ide_dma_off_quietly; pci_read_config_byte(dev, (drive_pci), &AP); if (id->capability & 4) /* IORDY_EN */ pci_write_config_byte(dev, (drive_pci), AP|IORDY_EN); pci_read_config_byte(dev, (drive_pci), &AP); - if (drive->media == ide_disk) /* PREFETCH_EN */ + if (drive->type == ATA_DISK) /* PREFETCH_EN */ pci_write_config_byte(dev, (drive_pci), AP|PREFETCH_EN); jumpbit_is_set: diff --git a/drivers/ide/pdcadma.c b/drivers/ide/pdcadma.c index cc6b7af7772f..fcb0c85db45c 100644 --- a/drivers/ide/pdcadma.c +++ b/drivers/ide/pdcadma.c @@ -34,7 +34,6 @@ static int pdcadma_get_info(char *, char **, off_t, int); extern int (*pdcadma_display_info)(char *, char **, off_t, int); /* ide-proc.c */ -extern char *ide_media_verbose(ide_drive_t *); static struct pci_dev *bmide_dev; static int pdcadma_get_info (char *buffer, char **addr, off_t offset, int count) diff --git a/drivers/ide/piix.c b/drivers/ide/piix.c index c419f70992c6..c517f2d947c3 100644 --- a/drivers/ide/piix.c +++ b/drivers/ide/piix.c @@ -77,7 +77,6 @@ static int piix_get_info(char *, char **, off_t, int); extern int (*piix_display_info)(char *, char **, off_t, int); /* ide-proc.c */ -extern char *ide_media_verbose(ide_drive_t *); static struct pci_dev *bmide_dev; static int piix_get_info (char *buffer, char **addr, off_t offset, int count) diff --git a/drivers/ide/qd65xx.c b/drivers/ide/qd65xx.c index 2cd2430f040a..b22afe68b319 100644 --- a/drivers/ide/qd65xx.c +++ b/drivers/ide/qd65xx.c @@ -293,7 +293,7 @@ static void qd6580_tune_drive (ide_drive_t *drive, byte pio) printk(KERN_INFO "%s: PIO mode%d\n",drive->name,pio); } - if (!HWIF(drive)->channel && drive->media != ide_disk) { + if (!HWIF(drive)->channel && drive->type != ATA_DISK) { qd_write_reg(0x5f,QD_CONTROL_PORT); printk(KERN_WARNING "%s: ATAPI: disabled read-ahead FIFO and post-write buffer on %s.\n",drive->name,HWIF(drive)->name); } diff --git a/drivers/ide/serverworks.c b/drivers/ide/serverworks.c index 5c056b4c5ebc..a87861ac0b22 100644 --- a/drivers/ide/serverworks.c +++ b/drivers/ide/serverworks.c @@ -105,7 +105,6 @@ static byte svwks_revision = 0; static int svwks_get_info(char *, char **, off_t, int); extern int (*svwks_display_info)(char *, char **, off_t, int); /* ide-proc.c */ -extern char *ide_media_verbose(ide_drive_t *); static int svwks_get_info (char *buffer, char **addr, off_t offset, int count) { diff --git a/drivers/ide/sis5513.c b/drivers/ide/sis5513.c index 7ddcdabf2290..df31eb71fc72 100644 --- a/drivers/ide/sis5513.c +++ b/drivers/ide/sis5513.c @@ -238,7 +238,7 @@ static void config_drive_art_rwp (ide_drive_t *drive) byte rw_prefetch = (0x11 << drive->dn); pci_read_config_byte(dev, 0x4b, ®4bh); - if (drive->media != ide_disk) + if (drive->type != ATA_DISK) return; if ((reg4bh & rw_prefetch) != rw_prefetch) diff --git a/drivers/ide/slc90e66.c b/drivers/ide/slc90e66.c index d9d602b7de4d..1c93ecc99ace 100644 --- a/drivers/ide/slc90e66.c +++ b/drivers/ide/slc90e66.c @@ -60,7 +60,6 @@ static int slc90e66_get_info(char *, char **, off_t, int); extern int (*slc90e66_display_info)(char *, char **, off_t, int); /* ide-proc.c */ -extern char *ide_media_verbose(ide_drive_t *); static struct pci_dev *bmide_dev; static int slc90e66_get_info (char *buffer, char **addr, off_t offset, int count) diff --git a/drivers/ide/trm290.c b/drivers/ide/trm290.c index c1aa3fb4eddc..70dffe8906e8 100644 --- a/drivers/ide/trm290.c +++ b/drivers/ide/trm290.c @@ -192,7 +192,7 @@ static int trm290_dmaproc (ide_dma_action_t func, ide_drive_t *drive) outl(hwif->dmatable_dma|reading|writing, hwif->dma_base); drive->waiting_for_dma = 1; outw((count * 2) - 1, hwif->dma_base+2); /* start DMA */ - if (drive->media != ide_disk) + if (drive->type != ATA_DISK) return 0; ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL); OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG); diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c index bf6941762f70..23d59b702500 100644 --- a/drivers/scsi/ide-scsi.c +++ b/drivers/scsi/ide-scsi.c @@ -182,7 +182,7 @@ static inline void idescsi_transform_pc1 (ide_drive_t *drive, idescsi_pc_t *pc) if (!test_bit(PC_TRANSFORM, &pc->flags)) return; - if (drive->media == ide_cdrom || drive->media == ide_optical) { + if (drive->type == ATA_ROM || drive->type == ATA_MOD) { if (c[0] == READ_6 || c[0] == WRITE_6) { c[8] = c[4]; c[5] = c[3]; c[4] = c[2]; c[3] = c[1] & 0x1f; c[2] = 0; c[1] &= 0xe0; @@ -221,7 +221,7 @@ static inline void idescsi_transform_pc2 (ide_drive_t *drive, idescsi_pc_t *pc) if (!test_bit(PC_TRANSFORM, &pc->flags)) return; - if (drive->media == ide_cdrom || drive->media == ide_optical) { + if (drive->type == ATA_ROM || drive->type == ATA_MOD) { if (pc->c[0] == MODE_SENSE_10 && sc[0] == MODE_SENSE) { scsi_buf[0] = atapi_buf[1]; /* Mode data length */ scsi_buf[1] = atapi_buf[2]; /* Medium type */ @@ -508,7 +508,8 @@ static void idescsi_add_settings(ide_drive_t *drive) */ static void idescsi_setup (ide_drive_t *drive, idescsi_scsi_t *scsi, int id) { - DRIVER(drive)->busy++; + ata_ops(drive)->busy++; + idescsi_drives[id] = drive; drive->driver_data = scsi; drive->ready_stat = 0; @@ -535,17 +536,13 @@ static int idescsi_cleanup (ide_drive_t *drive) return 0; } -int idescsi_reinit(ide_drive_t *drive); +static int idescsi_reinit(ide_drive_t *drive); /* * IDE subdriver functions, registered with ide.c */ -static ide_driver_t idescsi_driver = { - name: "ide-scsi", - media: ide_scsi, - busy: 0, - supports_dma: 1, - supports_dsc_overlap: 0, +static struct ata_operations idescsi_driver = { + owner: THIS_MODULE, cleanup: idescsi_cleanup, standby: NULL, flushcache: NULL, @@ -563,50 +560,20 @@ static ide_driver_t idescsi_driver = { driver_reinit: idescsi_reinit, }; -int idescsi_reinit (ide_drive_t *drive) +static int idescsi_reinit (ide_drive_t *drive) { -#if 0 - idescsi_scsi_t *scsi; - byte media[] = {TYPE_DISK, TYPE_TAPE, TYPE_PROCESSOR, TYPE_WORM, TYPE_ROM, TYPE_SCANNER, TYPE_MOD, 255}; - int i, failed, id; - - if (!idescsi_initialized) - return 0; - for (i = 0; i < MAX_HWIFS * MAX_DRIVES; i++) - idescsi_drives[i] = NULL; - - MOD_INC_USE_COUNT; - for (i = 0; media[i] != 255; i++) { - failed = 0; - while ((drive = ide_scan_devices (media[i], idescsi_driver.name, NULL, failed++)) != NULL) { - - if ((scsi = (idescsi_scsi_t *) kmalloc (sizeof (idescsi_scsi_t), GFP_KERNEL)) == NULL) { - printk (KERN_ERR "ide-scsi: %s: Can't allocate a scsi structure\n", drive->name); - continue; - } - if (ide_register_subdriver (drive, &idescsi_driver)) { - printk (KERN_ERR "ide-scsi: %s: Failed to register the driver with ide.c\n", drive->name); - kfree (scsi); - continue; - } - for (id = 0; id < MAX_HWIFS * MAX_DRIVES && idescsi_drives[id]; id++); - idescsi_setup (drive, scsi, id); - failed--; - } - } - revalidate_drives(); - MOD_DEC_USE_COUNT; -#endif return 0; } /* * idescsi_init will register the driver for each scsi. */ -int idescsi_init (void) +static int idescsi_init(void) { ide_drive_t *drive; idescsi_scsi_t *scsi; + /* FIXME: The following is just plain wrong, since those are definitely *not* the + * media types supported by the ATA layer */ byte media[] = {TYPE_DISK, TYPE_TAPE, TYPE_PROCESSOR, TYPE_WORM, TYPE_ROM, TYPE_SCANNER, TYPE_MOD, 255}; int i, failed, id; @@ -618,7 +585,7 @@ int idescsi_init (void) MOD_INC_USE_COUNT; for (i = 0; media[i] != 255; i++) { failed = 0; - while ((drive = ide_scan_devices (media[i], idescsi_driver.name, NULL, failed++)) != NULL) { + while ((drive = ide_scan_devices (media[i], "ide-scsi", NULL, failed++)) != NULL) { if ((scsi = (idescsi_scsi_t *) kmalloc (sizeof (idescsi_scsi_t), GFP_KERNEL)) == NULL) { printk (KERN_ERR "ide-scsi: %s: Can't allocate a scsi structure\n", drive->name); @@ -666,7 +633,7 @@ int idescsi_release (struct Scsi_Host *host) for (id = 0; id < MAX_HWIFS * MAX_DRIVES; id++) { drive = idescsi_drives[id]; if (drive) - DRIVER(drive)->busy--; + ata_ops(drive)->busy--; } return 0; } @@ -896,9 +863,17 @@ static void __exit exit_idescsi_module(void) int i, failed; scsi_unregister_host(&idescsi_template); + + /* FIXME: The media types scanned here have literally nothing to do + * with the media types used by the overall ATA code! + * + * This is basically showing us, that there is something wrong with the + * ide_scan_devices function. + */ + for (i = 0; media[i] != 255; i++) { failed = 0; - while ((drive = ide_scan_devices (media[i], idescsi_driver.name, &idescsi_driver, failed)) != NULL) + while ((drive = ide_scan_devices (media[i], "ide-scsi", &idescsi_driver, failed)) != NULL) if (idescsi_cleanup (drive)) { printk ("%s: exit_idescsi_module() called while still busy\n", drive->name); failed++; diff --git a/include/linux/ide.h b/include/linux/ide.h index c35f531eeb4e..30f881404625 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -1,9 +1,7 @@ #ifndef _IDE_H #define _IDE_H /* - * linux/include/linux/ide.h - * - * Copyright (C) 1994-1998 Linus Torvalds & authors + * Copyright (C) 1994-2002 Linus Torvalds & authors */ #include @@ -350,12 +348,13 @@ void ide_setup_ports( hw_regs_t *hw, * Now for the data we need to maintain per-drive: ide_drive_t */ -#define ide_scsi 0x21 -#define ide_disk 0x20 -#define ide_optical 0x7 -#define ide_cdrom 0x5 -#define ide_tape 0x1 -#define ide_floppy 0x0 +#define ATA_DISK 0x20 +#define ATA_TAPE 0x01 +#define ATA_ROM 0x05 /* CD-ROM */ +#define ATA_MOD 0x07 /* optical */ +#define ATA_FLOPPY 0x00 +#define ATA_SCSI 0x21 +#define ATA_NO_LUN 0x7f typedef union { unsigned all : 8; /* all of the bits together */ @@ -371,7 +370,14 @@ typedef union { struct ide_settings_s; typedef struct ide_drive_s { - request_queue_t queue; /* request queue */ + char type; /* distingiush different devices: disk, cdrom, tape, floppy, ... */ + + /* NOTE: If we had proper separation between channel and host chip, we + * could move this to the chanell and many sync problems would + * magically just go away. + */ + request_queue_t queue; /* per device request queue */ + struct ide_drive_s *next; /* circular list of hwgroup drives */ unsigned long sleep; /* sleep until this time */ unsigned long service_start; /* time we started last request */ @@ -406,7 +412,6 @@ typedef struct ide_drive_s { unsigned ata_flash : 1; /* 1=present, 0=default */ unsigned addressing; /* : 2; 0=28-bit, 1=48-bit, 2=64-bit */ byte scsi; /* 0=default, 1=skip current ide-subdriver for ide-scsi emulation */ - byte media; /* disk, cdrom, tape, floppy, ... */ select_t select; /* basic drive/head select reg value */ byte ctl; /* "normal" value for IDE_CONTROL_REG */ byte ready_stat; /* min status value for drive ready */ @@ -432,7 +437,7 @@ typedef struct ide_drive_s { struct hd_driveid *id; /* drive model identification info */ struct hd_struct *part; /* drive partition table */ char name[4]; /* drive name, such as "hda" */ - struct ide_driver_s *driver; /* (ide_driver_t *) */ + struct ata_operations *driver; void *driver_data; /* extra driver data */ devfs_handle_t de; /* directory for device */ struct proc_dir_entry *proc; /* /proc/ide/ directory entry */ @@ -570,7 +575,6 @@ typedef struct hwif_s { unsigned long last_time; /* time when previous rq was done */ #endif byte straight8; /* Alan's straight 8 check */ - void *hwif_data; /* extra hwif data */ ide_busproc_t *busproc; /* driver soft-power interface */ byte bus_state; /* power state of the IDE bus */ struct device device; /* global device tree handle */ @@ -663,8 +667,6 @@ typedef struct { #ifdef CONFIG_PROC_FS void proc_ide_create(void); void proc_ide_destroy(void); -void recreate_proc_ide_device(ide_hwif_t *, ide_drive_t *); -void destroy_proc_ide_device(ide_hwif_t *, ide_drive_t *); void destroy_proc_ide_drives(ide_hwif_t *); void create_proc_ide_interfaces(void); void ide_add_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t *p, void *data); @@ -692,32 +694,54 @@ read_proc_t proc_ide_read_geometry; #endif /* - * Subdrivers support. + * This structure describes the operations possible on a particular device type + * (CD-ROM, tape, DISK and so on). + * + * This is the main hook for device type support submodules. */ -typedef struct ide_driver_s { - const char *name; - byte media; - unsigned busy : 1; - unsigned supports_dma : 1; - unsigned supports_dsc_overlap : 1; + +struct ata_operations { + struct module *owner; + unsigned busy: 1; /* FIXME: this will go soon away... */ int (*cleanup)(ide_drive_t *); int (*standby)(ide_drive_t *); int (*flushcache)(ide_drive_t *); ide_startstop_t (*do_request)(ide_drive_t *, struct request *, unsigned long); int (*end_request)(ide_drive_t *drive, int uptodate); + int (*ioctl)(ide_drive_t *, struct inode *, struct file *, unsigned int, unsigned long); int (*open)(struct inode *, struct file *, ide_drive_t *); void (*release)(struct inode *, struct file *, ide_drive_t *); int (*media_change)(ide_drive_t *); void (*revalidate)(ide_drive_t *); + void (*pre_reset)(ide_drive_t *); unsigned long (*capacity)(ide_drive_t *); ide_startstop_t (*special)(ide_drive_t *); ide_proc_entry_t *proc; int (*driver_reinit)(ide_drive_t *); -} ide_driver_t; +}; + +/* Alas, no aliases. Too much hassle with bringing module.h everywhere */ +#define ata_get(ata) \ + (((ata) && (ata)->owner) \ + ? ( try_inc_mod_count((ata)->owner) ? (ata) : NULL ) \ + : (ata)) + +#define ata_put(ata) \ +do { \ + if ((ata) && (ata)->owner) \ + __MOD_DEC_USE_COUNT((ata)->owner); \ +} while(0) -#define DRIVER(drive) ((drive)->driver) + +/* FIXME: Actually implement and use them as soon as possible! to make the + * ide_scan_devices() go away! */ + +extern int unregister_ata_driver(unsigned int type, struct ata_operations *driver); +extern int register_ata_driver(unsigned int type, struct ata_operations *driver); + +#define ata_ops(drive) ((drive)->driver) /* * ide_hwifs[] is the master data structure used to keep track @@ -994,30 +1018,24 @@ extern ide_proc_entry_t generic_subdriver_entries[]; extern int ideprobe_init (void); #endif #ifdef CONFIG_BLK_DEV_IDEDISK -extern int idedisk_reinit (ide_drive_t *drive); extern int idedisk_init (void); -#endif /* CONFIG_BLK_DEV_IDEDISK */ +#endif #ifdef CONFIG_BLK_DEV_IDECD -extern int ide_cdrom_reinit (ide_drive_t *drive); extern int ide_cdrom_init (void); -#endif /* CONFIG_BLK_DEV_IDECD */ +#endif #ifdef CONFIG_BLK_DEV_IDETAPE -extern int idetape_reinit (ide_drive_t *drive); extern int idetape_init (void); -#endif /* CONFIG_BLK_DEV_IDETAPE */ +#endif #ifdef CONFIG_BLK_DEV_IDEFLOPPY -extern int idefloppy_reinit (ide_drive_t *drive); extern int idefloppy_init (void); -#endif /* CONFIG_BLK_DEV_IDEFLOPPY */ +#endif #ifdef CONFIG_BLK_DEV_IDESCSI -extern int idescsi_reinit (ide_drive_t *drive); extern int idescsi_init (void); -#endif /* CONFIG_BLK_DEV_IDESCSI */ +#endif -ide_drive_t *ide_scan_devices (byte media, const char *name, ide_driver_t *driver, int n); -extern int ide_register_subdriver(ide_drive_t *drive, ide_driver_t *driver); +ide_drive_t *ide_scan_devices (byte media, const char *name, struct ata_operations *driver, int n); +extern int ide_register_subdriver(ide_drive_t *drive, struct ata_operations *driver); extern int ide_unregister_subdriver(ide_drive_t *drive); -extern int ide_replace_subdriver(ide_drive_t *drive, const char *driver); #ifdef CONFIG_BLK_DEV_IDEPCI #define ON_BOARD 1 -- cgit v1.2.3 From d5d282821983781ca3bee0c56921413665422fe5 Mon Sep 17 00:00:00 2001 From: Tim Waugh Date: Wed, 27 Feb 2002 20:19:29 -0800 Subject: [PATCH] 2.5.6-pre1: parport and O_NONBLOCK This patch makes lp and ppdev do the Right Thing regarding O_NONBLOCK. 2002-01-04 Tim Waugh * include/linux/parport.h: Define a special inactivity timeout meaning 'caller wants to use O_NONBLOCK'. * drivers/char/lp.c: Support O_NONBLOCK properly. * drivers/char/ppdev.c: Likewise. * drivers/parport/parport_pc.c: Likewise. * drivers/parport/ChangeLog: Updated. --- drivers/char/lp.c | 67 ++++++++++++++++++++++++++++++++++++++++---- drivers/char/ppdev.c | 53 +++++++++++++++++++++++------------ drivers/parport/ChangeLog | 7 +++++ drivers/parport/parport_pc.c | 15 ++++++---- include/linux/parport.h | 3 ++ 5 files changed, 115 insertions(+), 30 deletions(-) (limited to 'include/linux') diff --git a/drivers/char/lp.c b/drivers/char/lp.c index fa63e667d2dd..0718d9a8762a 100644 --- a/drivers/char/lp.c +++ b/drivers/char/lp.c @@ -270,7 +270,7 @@ static int lp_check_status(int minor) return error; } -static int lp_wait_ready(int minor) +static int lp_wait_ready(int minor, int nonblock) { int error = 0; @@ -281,7 +281,7 @@ static int lp_wait_ready(int minor) do { error = lp_check_status (minor); - if (error && (LP_F(minor) & LP_ABORT)) + if (error && (nonblock || (LP_F(minor) & LP_ABORT))) break; if (signal_pending (current)) { error = -EINTR; @@ -300,6 +300,8 @@ static ssize_t lp_write(struct file * file, const char * buf, ssize_t retv = 0; ssize_t written; size_t copy_size = count; + int nonblock = ((file->f_flags & O_NONBLOCK) || + (LP_F(minor) & LP_ABORT)); #ifdef LP_STATS if (jiffies-lp_table[minor].lastcall > LP_TIME(minor)) @@ -326,9 +328,10 @@ static ssize_t lp_write(struct file * file, const char * buf, lp_table[minor].best_mode); parport_set_timeout (lp_table[minor].dev, - lp_table[minor].timeout); + (nonblock ? PARPORT_INACTIVITY_O_NONBLOCK + : lp_table[minor].timeout)); - if ((retv = lp_wait_ready (minor)) == 0) + if ((retv = lp_wait_ready (minor, nonblock)) == 0) do { /* Write the data. */ written = parport_write (port, kbuf, copy_size); @@ -354,12 +357,16 @@ static ssize_t lp_write(struct file * file, const char * buf, IEEE1284_MODE_COMPAT); lp_table[minor].current_mode = IEEE1284_MODE_COMPAT; - error = lp_wait_ready (minor); + error = lp_wait_ready (minor, nonblock); if (error) { if (retv == 0) retv = error; break; + } else if (nonblock) { + if (retv == 0) + retv = -EAGAIN; + break; } parport_yield_blocking (lp_table[minor].dev); @@ -407,6 +414,8 @@ static ssize_t lp_read(struct file * file, char * buf, struct parport *port = lp_table[minor].dev->port; ssize_t retval = 0; char *kbuf = lp_table[minor].lp_buffer; + int nonblock = ((file->f_flags & O_NONBLOCK) || + (LP_F(minor) & LP_ABORT)); if (count > LP_BUFFER_SIZE) count = LP_BUFFER_SIZE; @@ -415,7 +424,53 @@ static ssize_t lp_read(struct file * file, char * buf, return -EINTR; lp_claim_parport_or_block (&lp_table[minor]); - retval = parport_read (port, kbuf, count); + + parport_set_timeout (lp_table[minor].dev, + (nonblock ? PARPORT_INACTIVITY_O_NONBLOCK + : lp_table[minor].timeout)); + + parport_negotiate (lp_table[minor].dev->port, IEEE1284_MODE_COMPAT); + if (parport_negotiate (lp_table[minor].dev->port, + IEEE1284_MODE_NIBBLE)) { + retval = -EIO; + goto out; + } + + while (retval == 0) { + retval = parport_read (port, kbuf, count); + + if (retval > 0) + break; + + if (nonblock) { + retval = -EAGAIN; + break; + } + + /* Wait for data. */ + + if (lp_table[minor].dev->port->irq == PARPORT_IRQ_NONE) { + parport_negotiate (lp_table[minor].dev->port, + IEEE1284_MODE_COMPAT); + lp_error (minor); + if (parport_negotiate (lp_table[minor].dev->port, + IEEE1284_MODE_NIBBLE)) { + retval = -EIO; + goto out; + } + } else + interruptible_sleep_on_timeout (&lp_table[minor].waitq, + LP_TIMEOUT_POLLED); + + if (signal_pending (current)) { + retval = -ERESTARTSYS; + break; + } + + cond_resched (); + } + parport_negotiate (lp_table[minor].dev->port, IEEE1284_MODE_COMPAT); + out: lp_release_parport (&lp_table[minor]); if (retval > 0 && copy_to_user (buf, kbuf, retval)) diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c index 6dc3fc6556cc..e5b94dbe05d1 100644 --- a/drivers/char/ppdev.c +++ b/drivers/char/ppdev.c @@ -4,7 +4,7 @@ * This is the code behind /dev/parport* -- it allows a user-space * application to use the parport subsystem. * - * Copyright (C) 1998-2000 Tim Waugh + * Copyright (C) 1998-2000, 2002 Tim Waugh * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -80,6 +80,7 @@ struct pp_struct { unsigned char irqctl; struct ieee1284_info state; struct ieee1284_info saved_state; + long default_inactivity; }; /* pp_struct.flags bitfields */ @@ -107,7 +108,6 @@ static ssize_t pp_read (struct file * file, char * buf, size_t count, struct pp_struct *pp = file->private_data; char * kbuffer; ssize_t bytes_read = 0; - ssize_t got = 0; struct parport *pport; int mode; @@ -125,8 +125,13 @@ static ssize_t pp_read (struct file * file, char * buf, size_t count, pport = pp->pdev->port; mode = pport->ieee1284.mode & ~(IEEE1284_DEVICEID | IEEE1284_ADDR); - while (bytes_read < count) { - ssize_t need = min_t(unsigned long, count - bytes_read, PP_BUFFER_SIZE); + parport_set_timeout (pp->pdev, + (file->f_flags & O_NONBLOCK) ? + PARPORT_INACTIVITY_O_NONBLOCK : + pp->default_inactivity); + + while (bytes_read == 0) { + ssize_t need = min_t(unsigned long, count, PP_BUFFER_SIZE); if (mode == IEEE1284_MODE_EPP) { /* various specials for EPP mode */ @@ -144,35 +149,32 @@ static ssize_t pp_read (struct file * file, char * buf, size_t count, } else { fn = pport->ops->epp_read_data; } - got = (*fn)(pport, kbuffer, need, flags); + bytes_read = (*fn)(pport, kbuffer, need, flags); } else { - got = parport_read (pport, kbuffer, need); + bytes_read = parport_read (pport, kbuffer, need); } - if (got <= 0) { - if (!bytes_read) { - bytes_read = got; - } + if (bytes_read != 0) break; - } - if (copy_to_user (buf + bytes_read, kbuffer, got)) { - bytes_read = -EFAULT; + if (file->f_flags & O_NONBLOCK) { + bytes_read = -EAGAIN; break; } - bytes_read += got; - if (signal_pending (current)) { - if (!bytes_read) { - bytes_read = -EINTR; - } + bytes_read = -ERESTARTSYS; break; } cond_resched(); } + parport_set_timeout (pp->pdev, pp->default_inactivity); + + if (bytes_read > 0 && copy_to_user (buf, kbuffer, bytes_read)) + bytes_read = -EFAULT; + kfree (kbuffer); pp_enable_irq (pp); return bytes_read; @@ -203,6 +205,11 @@ static ssize_t pp_write (struct file * file, const char * buf, size_t count, pport = pp->pdev->port; mode = pport->ieee1284.mode & ~(IEEE1284_DEVICEID | IEEE1284_ADDR); + parport_set_timeout (pp->pdev, + (file->f_flags & O_NONBLOCK) ? + PARPORT_INACTIVITY_O_NONBLOCK : + pp->default_inactivity); + while (bytes_written < count) { ssize_t n = min_t(unsigned long, count - bytes_written, PP_BUFFER_SIZE); @@ -233,6 +240,12 @@ static ssize_t pp_write (struct file * file, const char * buf, size_t count, bytes_written += wrote; + if (file->f_flags & O_NONBLOCK) { + if (!bytes_written) + bytes_written = -EAGAIN; + break; + } + if (signal_pending (current)) { if (!bytes_written) { bytes_written = -EINTR; @@ -243,6 +256,8 @@ static ssize_t pp_write (struct file * file, const char * buf, size_t count, cond_resched(); } + parport_set_timeout (pp->pdev, pp->default_inactivity); + kfree (kbuffer); pp_enable_irq (pp); return bytes_written; @@ -352,6 +367,8 @@ static int pp_ioctl(struct inode *inode, struct file *file, pp->saved_state.phase = info->phase; info->mode = pp->state.mode; info->phase = pp->state.phase; + pp->default_inactivity = parport_set_timeout (pp->pdev, 0); + parport_set_timeout (pp->pdev, pp->default_inactivity); return 0; } diff --git a/drivers/parport/ChangeLog b/drivers/parport/ChangeLog index 2e60fb2a2888..36cfb8ef2ddd 100644 --- a/drivers/parport/ChangeLog +++ b/drivers/parport/ChangeLog @@ -1,3 +1,10 @@ +2002-01-20 Tim Waugh + + * parport_pc.c (parport_pc_compat_write_block_pio, + parport_pc_ecp_write_block_pio, parport_pc_ecp_read_block_pio): + Use the default implementations if the caller wants to use + O_NONBLOCK. + 2002-02-25 Tim Waugh * parport_pc.c: Make sure that priv->ctr_writable includes IntEn diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c index 6e20bd624e72..3e45aa4cdd40 100644 --- a/drivers/parport/parport_pc.c +++ b/drivers/parport/parport_pc.c @@ -818,8 +818,9 @@ size_t parport_pc_compat_write_block_pio (struct parport *port, long int expire; const struct parport_pc_private *priv = port->physport->private_data; - /* Special case: a timeout of zero means we cannot call schedule(). */ - if (!port->physport->cad->timeout) + /* Special case: a timeout of zero means we cannot call schedule(). + * Also if O_NONBLOCK is set then use the default implementation. */ + if (port->physport->cad->timeout <= PARPORT_INACTIVITY_O_NONBLOCK) return parport_ieee1284_write_compat (port, buf, length, flags); @@ -894,8 +895,9 @@ size_t parport_pc_ecp_write_block_pio (struct parport *port, long int expire; const struct parport_pc_private *priv = port->physport->private_data; - /* Special case: a timeout of zero means we cannot call schedule(). */ - if (!port->physport->cad->timeout) + /* Special case: a timeout of zero means we cannot call schedule(). + * Also if O_NONBLOCK is set then use the default implementation. */ + if (port->physport->cad->timeout <= PARPORT_INACTIVITY_O_NONBLOCK) return parport_ieee1284_ecp_write_data (port, buf, length, flags); @@ -1014,8 +1016,9 @@ size_t parport_pc_ecp_read_block_pio (struct parport *port, DPRINTK (KERN_DEBUG "parport_pc: parport_pc_ecp_read_block_pio\n"); dump_parport_state ("enter fcn", port); - /* Special case: a timeout of zero means we cannot call schedule(). */ - if (!port->cad->timeout) + /* Special case: a timeout of zero means we cannot call schedule(). + * Also if O_NONBLOCK is set then use the default implementation. */ + if (port->cad->timeout <= PARPORT_INACTIVITY_O_NONBLOCK) return parport_ieee1284_ecp_read_data (port, buf, length, flags); diff --git a/include/linux/parport.h b/include/linux/parport.h index ce82bcdb5e1a..a41c6be7810e 100644 --- a/include/linux/parport.h +++ b/include/linux/parport.h @@ -459,7 +459,10 @@ extern void parport_ieee1284_interrupt (int, void *, struct pt_regs *); extern int parport_negotiate (struct parport *, int mode); extern ssize_t parport_write (struct parport *, const void *buf, size_t len); extern ssize_t parport_read (struct parport *, void *buf, size_t len); + +#define PARPORT_INACTIVITY_O_NONBLOCK 1 extern long parport_set_timeout (struct pardevice *, long inactivity); + extern int parport_wait_event (struct parport *, long timeout); extern int parport_wait_peripheral (struct parport *port, unsigned char mask, -- cgit v1.2.3 From 7155112cbcab15e2e34809c97c89907b8fa8013e Mon Sep 17 00:00:00 2001 From: Alexander Viro Date: Wed, 27 Feb 2002 20:23:33 -0800 Subject: [PATCH] (1/7) kdev_t removals * new function - fsync_bdev() (analog of fsync_dev(), but takes struct block_device * instead of kdev_t. Callers of fsync_dev() that have struct block_device in question are using fsync_bdev() now. * old code for fsync_dev(NODEV) had been moved to sys_sync(). Other callers of fsync_dev(NODEV) are calling sys_sync() now. * fsync_dev() became a wrapper fro fsync_bdev(). * sync_dev() (not used anywhere in the tree) is gone. * i2oblock.c had fsync_dev() called in ->release(). Removed. * s390/block/xparm.c was doing fsync_dev() on its devices in cleanup_module(). Removed. --- drivers/block/amiflop.c | 2 +- drivers/char/sysrq.c | 4 ++-- drivers/macintosh/via-pmu.c | 6 +++--- drivers/macintosh/via-pmu68k.c | 2 +- drivers/md/lvm.c | 2 +- drivers/md/md.c | 7 +++--- drivers/message/i2o/i2o_block.c | 3 --- drivers/mtd/mtdblock.c | 2 +- drivers/mtd/mtdblock_ro.c | 2 +- drivers/mtd/nftlcore.c | 2 +- drivers/s390/block/xpram.c | 7 ++---- fs/buffer.c | 47 +++++++++++++++++++++-------------------- include/linux/fs.h | 2 +- kernel/ksyms.c | 2 +- 14 files changed, 43 insertions(+), 47 deletions(-) (limited to 'include/linux') diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c index c2e353b88d9e..125bd19d0d45 100644 --- a/drivers/block/amiflop.c +++ b/drivers/block/amiflop.c @@ -1514,7 +1514,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp, rel_fdc(); return -EBUSY; } - fsync_dev(inode->i_rdev); + fsync_bdev(inode->i_bdev); if (fd_motor_on(drive) == 0) { rel_fdc(); return -ENODEV; diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c index 9c28836d874b..e76db4ed8ea4 100644 --- a/drivers/char/sysrq.c +++ b/drivers/char/sysrq.c @@ -161,7 +161,7 @@ static void go_sync(struct super_block *sb, int remount_flag) } file_list_unlock(); DQUOT_OFF(sb); - fsync_dev(sb->s_dev); + fsync_bdev(sb->s_bdev); flags = MS_RDONLY; if (sb->s_op && sb->s_op->remount_fs) { ret = sb->s_op->remount_fs(sb, &flags, NULL); @@ -174,7 +174,7 @@ static void go_sync(struct super_block *sb, int remount_flag) } else printk("nothing to do\n"); } else { /* Sync only */ - fsync_dev(sb->s_dev); + fsync_bdev(sb->s_bdev); printk("OK\n"); } console_loglevel = orig_loglevel; diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c index ae2644f6adfd..3118256c45f0 100644 --- a/drivers/macintosh/via-pmu.c +++ b/drivers/macintosh/via-pmu.c @@ -1434,7 +1434,7 @@ int __openfirmware powerbook_sleep_G3(void) * BenH: Moved to _after_ sleep request and changed video * drivers to vmalloc() during sleep request. This way, all * vmalloc's are done before actual sleep of block drivers */ - fsync_dev(0); + sys_sync(); /* Sleep can fail now. May not be very robust but useful for debugging */ ret = broadcast_sleep(PBOOK_SLEEP_NOW, PBOOK_WAKE); @@ -1589,7 +1589,7 @@ int __openfirmware powerbook_sleep_Core99(void) * BenH: Moved to _after_ sleep request and changed video * drivers to vmalloc() during sleep request. This way, all * vmalloc's are done before actual sleep of block drivers */ - fsync_dev(0); + sys_sync(); /* Sleep can fail now. May not be very robust but useful for debugging */ ret = broadcast_sleep(PBOOK_SLEEP_NOW, PBOOK_WAKE); @@ -1764,7 +1764,7 @@ int __openfirmware powerbook_sleep_3400(void) * BenH: Moved to _after_ sleep request and changed video * drivers to vmalloc() during sleep request. This way, all * vmalloc's are done before actual sleep of block drivers */ - fsync_dev(0); + sys_sync(); /* Sleep can fail now. May not be very robust but useful for debugging */ ret = broadcast_sleep(PBOOK_SLEEP_NOW, PBOOK_WAKE); diff --git a/drivers/macintosh/via-pmu68k.c b/drivers/macintosh/via-pmu68k.c index 5ac40964db11..75ce19134f38 100644 --- a/drivers/macintosh/via-pmu68k.c +++ b/drivers/macintosh/via-pmu68k.c @@ -916,7 +916,7 @@ int __openfirmware powerbook_sleep(void) /* Sync the disks. */ /* XXX It would be nice to have some way to ensure that * nobody is dirtying any new buffers while we wait. */ - fsync_dev(0); + sys_sync(); /* Turn off the display backlight */ save_backlight = backlight_enabled; diff --git a/drivers/md/lvm.c b/drivers/md/lvm.c index d5ceb3f570d7..0d6c2447f677 100644 --- a/drivers/md/lvm.c +++ b/drivers/md/lvm.c @@ -878,7 +878,7 @@ static int lvm_blk_ioctl(struct inode *inode, struct file *file, P_IOCTL("BLKFLSBUF\n"); - fsync_dev(inode->i_rdev); + fsync_bdev(inode->i_bdev); invalidate_buffers(inode->i_rdev); break; diff --git a/drivers/md/md.c b/drivers/md/md.c index 0dee93d325f0..3bbbc201f4ee 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -890,7 +890,8 @@ static mdk_rdev_t * find_rdev_all(kdev_t dev) static int write_disk_sb(mdk_rdev_t * rdev) { - struct address_space *mapping = rdev->bdev->bd_inode->i_mapping; + struct block_device *bdev = rdev->bdev; + struct address_space *mapping = bdev->bd_inode->i_mapping; struct page *page; unsigned offs; int error; @@ -929,7 +930,7 @@ static int write_disk_sb(mdk_rdev_t * rdev) } printk(KERN_INFO "(write) %s's sb offset: %ld\n", partition_name(dev), sb_offset); - fsync_dev(dev); + fsync_bdev(bdev); page = grab_cache_page(mapping, sb_offset/(PAGE_CACHE_SIZE/BLOCK_SIZE)); offs = sb_offset % (PAGE_CACHE_SIZE/BLOCK_SIZE); if (!page) @@ -946,7 +947,7 @@ static int write_disk_sb(mdk_rdev_t * rdev) UnlockPage(page); wait_on_page(page); page_cache_release(page); - fsync_dev(dev); + fsync_bdev(bdev); skip: return 0; unlock: diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c index 538cbfccf121..243b962d66ab 100644 --- a/drivers/message/i2o/i2o_block.c +++ b/drivers/message/i2o/i2o_block.c @@ -1137,9 +1137,6 @@ static int i2ob_release(struct inode *inode, struct file *file) if(!dev->i2odev) return 0; - /* Sync the device so we don't get errors */ - fsync_dev(inode->i_rdev); - if (dev->refcnt <= 0) printk(KERN_ALERT "i2ob_release: refcount(%d) <= 0\n", dev->refcnt); dev->refcnt--; diff --git a/drivers/mtd/mtdblock.c b/drivers/mtd/mtdblock.c index a45dfabe9494..8dfec3a98ea9 100644 --- a/drivers/mtd/mtdblock.c +++ b/drivers/mtd/mtdblock.c @@ -540,7 +540,7 @@ static int mtdblock_ioctl(struct inode * inode, struct file * file, if(!capable(CAP_SYS_ADMIN)) return -EACCES; #endif - fsync_dev(inode->i_rdev); + fsync_bdev(inode->i_bdev); invalidate_buffers(inode->i_rdev); down(&mtdblk->cache_sem); write_cached_data(mtdblk); diff --git a/drivers/mtd/mtdblock_ro.c b/drivers/mtd/mtdblock_ro.c index d12c8832e0e7..79f4a0132a2a 100644 --- a/drivers/mtd/mtdblock_ro.c +++ b/drivers/mtd/mtdblock_ro.c @@ -221,7 +221,7 @@ static int mtdblock_ioctl(struct inode * inode, struct file * file, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) if(!capable(CAP_SYS_ADMIN)) return -EACCES; #endif - fsync_dev(inode->i_rdev); + fsync_bdev(inode->i_bdev); invalidate_buffers(inode->i_rdev); if (mtd->sync) mtd->sync(mtd); diff --git a/drivers/mtd/nftlcore.c b/drivers/mtd/nftlcore.c index aa149911b4e5..7b41b62ad37c 100644 --- a/drivers/mtd/nftlcore.c +++ b/drivers/mtd/nftlcore.c @@ -795,7 +795,7 @@ static int nftl_ioctl(struct inode * inode, struct file * file, unsigned int cmd } case BLKFLSBUF: if (!capable(CAP_SYS_ADMIN)) return -EACCES; - fsync_dev(inode->i_rdev); + fsync_bdev(inode->i_bdev); invalidate_buffers(inode->i_rdev); if (nftl->mtd->sync) nftl->mtd->sync(nftl->mtd); diff --git a/drivers/s390/block/xpram.c b/drivers/s390/block/xpram.c index 63116ecc76fd..7e91ea6b2035 100644 --- a/drivers/s390/block/xpram.c +++ b/drivers/s390/block/xpram.c @@ -654,7 +654,7 @@ int xpram_ioctl (struct inode *inode, struct file *filp, (u64 *) arg); case BLKFLSBUF: /* flush, 0x1261 */ - fsync_dev(inode->i_rdev); + fsync_bdev(inode->i_bdev); if ( capable(CAP_SYS_ADMIN) )invalidate_buffers(inode->i_rdev); return 0; @@ -1191,10 +1191,7 @@ void cleanup_module(void) { int i; - /* first of all, flush it all and reset all the data structures */ - - for (i=0; ibd_dev)); + if (sb) { + int res = fsync_super(sb); + drop_super(sb); + return res; + } + return fsync_no_super(bdev); } asmlinkage long sys_sync(void) { - fsync_dev(NODEV); + sync_buffers(NODEV, 0); + + lock_kernel(); + sync_inodes(NODEV); + DQUOT_SYNC(NULL); + sync_supers(NODEV); + unlock_kernel(); + + sync_buffers(NODEV, 1); return 0; } diff --git a/include/linux/fs.h b/include/linux/fs.h index 89208aabe5b8..f9399b56d73d 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1216,8 +1216,8 @@ extern void sync_inodes(kdev_t); extern void sync_unlocked_inodes(void); extern void write_inode_now(struct inode *, int); extern int sync_buffers(kdev_t, int); -extern void sync_dev(kdev_t); extern int fsync_dev(kdev_t); +extern int fsync_bdev(struct block_device *); extern int fsync_super(struct super_block *); extern int fsync_no_super(struct block_device *); extern void sync_inodes_sb(struct super_block *); diff --git a/kernel/ksyms.c b/kernel/ksyms.c index 30bb84d5c19d..2225f68de55e 100644 --- a/kernel/ksyms.c +++ b/kernel/ksyms.c @@ -181,6 +181,7 @@ EXPORT_SYMBOL(invalidate_device); EXPORT_SYMBOL(invalidate_inode_pages); EXPORT_SYMBOL(truncate_inode_pages); EXPORT_SYMBOL(fsync_dev); +EXPORT_SYMBOL(fsync_bdev); EXPORT_SYMBOL(fsync_no_super); EXPORT_SYMBOL(permission); EXPORT_SYMBOL(vfs_permission); @@ -311,7 +312,6 @@ EXPORT_SYMBOL(blk_dev); EXPORT_SYMBOL(is_read_only); EXPORT_SYMBOL(set_device_ro); EXPORT_SYMBOL(bmap); -EXPORT_SYMBOL(sync_dev); EXPORT_SYMBOL(devfs_register_partitions); EXPORT_SYMBOL(blkdev_open); EXPORT_SYMBOL(blkdev_get); -- cgit v1.2.3 From 2d849bd1d1d00c9d953ed642c3e8f251fca65344 Mon Sep 17 00:00:00 2001 From: Alexander Viro Date: Wed, 27 Feb 2002 20:23:39 -0800 Subject: [PATCH] (2/7) kdev_t removals * all remaining callers of sync_inodes() and sync_supers() pass NODEV as an argument, so we can make them void(void). Dead code removed. --- fs/buffer.c | 6 +++--- fs/inode.c | 16 ++++------------ fs/super.c | 12 +----------- include/linux/fs.h | 4 ++-- 4 files changed, 10 insertions(+), 28 deletions(-) (limited to 'include/linux') diff --git a/fs/buffer.c b/fs/buffer.c index e330e7ed6213..421e4388e0f7 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -368,9 +368,9 @@ asmlinkage long sys_sync(void) sync_buffers(NODEV, 0); lock_kernel(); - sync_inodes(NODEV); + sync_inodes(); DQUOT_SYNC(NULL); - sync_supers(NODEV); + sync_supers(); unlock_kernel(); sync_buffers(NODEV, 1); @@ -2617,7 +2617,7 @@ static int sync_old_buffers(void) { lock_kernel(); sync_unlocked_inodes(); - sync_supers(NODEV); + sync_supers(); unlock_kernel(); for (;;) { diff --git a/fs/inode.c b/fs/inode.c index 2c0852cbeaf6..b7db8ac27f80 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -419,23 +419,15 @@ restart: * writes them out, and puts them back on the normal list. */ -void sync_inodes(kdev_t dev) +void sync_inodes(void) { struct super_block * s; - /* * Search the super_blocks array for the device(s) to sync. */ - if (!kdev_none(dev)) { - if ((s = get_super(dev)) != NULL) { - sync_inodes_sb(s); - drop_super(s); - } - } else { - while ((s = get_super_to_sync()) != NULL) { - sync_inodes_sb(s); - drop_super(s); - } + while ((s = get_super_to_sync()) != NULL) { + sync_inodes_sb(s); + drop_super(s); } } diff --git a/fs/super.c b/fs/super.c index b722653292d4..948cdc93188c 100644 --- a/fs/super.c +++ b/fs/super.c @@ -499,19 +499,9 @@ static inline void write_super(struct super_block *sb) * hold up the sync while mounting a device. (The newly * mounted device won't need syncing.) */ -void sync_supers(kdev_t dev) +void sync_supers(void) { struct super_block * sb; - - if (!kdev_none(dev)) { - sb = get_super(dev); - if (sb) { - if (sb->s_dirt) - write_super(sb); - drop_super(sb); - } - return; - } restart: spin_lock(&sb_lock); sb = sb_entry(super_blocks.next); diff --git a/include/linux/fs.h b/include/linux/fs.h index f9399b56d73d..a39d861d25a3 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1212,7 +1212,7 @@ extern void invalidate_inode_buffers(struct inode *); #define destroy_buffers(dev) __invalidate_buffers((dev), 1) extern void invalidate_bdev(struct block_device *, int); extern void __invalidate_buffers(kdev_t dev, int); -extern void sync_inodes(kdev_t); +extern void sync_inodes(void); extern void sync_unlocked_inodes(void); extern void write_inode_now(struct inode *, int); extern int sync_buffers(kdev_t, int); @@ -1234,7 +1234,7 @@ static inline int fsync_inode_data_buffers(struct inode *inode) extern int inode_has_buffers(struct inode *); extern int filemap_fdatasync(struct address_space *); extern int filemap_fdatawait(struct address_space *); -extern void sync_supers(kdev_t); +extern void sync_supers(void); extern int bmap(struct inode *, int); extern int notify_change(struct dentry *, struct iattr *); extern int permission(struct inode *, int); -- cgit v1.2.3 From de6d0d2b5fbed267bae8f55edefbf7d86135f7c2 Mon Sep 17 00:00:00 2001 From: Alexander Viro Date: Wed, 27 Feb 2002 20:23:44 -0800 Subject: [PATCH] (3/7) kdev_t removals * sync_buffers() split in two functions (sync_buffers() and sync_all_buffers()). Callers of sync_buffers(NODEV) are using the latter, those who actually pass a device - the former. * sync_buffers() switched from kdev_t to struct block_device *. --- fs/block_dev.c | 4 ++-- fs/buffer.c | 44 ++++++++++++++++++++++++++++++++------------ include/linux/fs.h | 2 +- 3 files changed, 35 insertions(+), 15 deletions(-) (limited to 'include/linux') diff --git a/fs/block_dev.c b/fs/block_dev.c index 09f1f8306ce7..9f8923c0103c 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -94,7 +94,7 @@ int set_blocksize(kdev_t dev, int size) /* Ok, we're actually changing the blocksize.. */ bdev = bdget(kdev_t_to_nr(dev)); - sync_buffers(dev, 2); + sync_buffers(bdev, 2); blksize_size[major(dev)][minor(dev)] = size; bdev->bd_inode->i_blkbits = blksize_bits(size); kill_bdev(bdev); @@ -198,7 +198,7 @@ static int __block_fsync(struct inode * inode) int ret, err; ret = filemap_fdatasync(inode->i_mapping); - err = sync_buffers(inode->i_rdev, 1); + err = sync_buffers(inode->i_bdev, 1); if (err && !ret) ret = err; err = filemap_fdatawait(inode->i_mapping); diff --git a/fs/buffer.c b/fs/buffer.c index 421e4388e0f7..e50f626af5cf 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -298,10 +298,15 @@ static int wait_for_locked_buffers(kdev_t dev, int index, int refile) * We will ultimately want to put these in a separate list, but for * now we search all of the lists for dirty buffers. */ -int sync_buffers(kdev_t dev, int wait) +int sync_buffers(struct block_device *bdev, int wait) { int err = 0; + kdev_t dev; + + if (!bdev) + return 0; + dev = to_kdev_t(bdev->bd_dev); /* One pass for no-wait, three for wait: * 0) write out all dirty, unlocked buffers; * 1) wait for all dirty locked buffers; @@ -317,10 +322,28 @@ int sync_buffers(kdev_t dev, int wait) return err; } +int sync_all_buffers(int wait) +{ + int err = 0; + + /* One pass for no-wait, three for wait: + * 0) write out all dirty, unlocked buffers; + * 1) wait for all dirty locked buffers; + * 2) write out all dirty, unlocked buffers; + * 2) wait for completion by waiting for all buffers to unlock. + */ + write_unlocked_buffers(NODEV); + if (wait) { + err = wait_for_locked_buffers(NODEV, BUF_DIRTY, 0); + write_unlocked_buffers(NODEV); + err |= wait_for_locked_buffers(NODEV, BUF_LOCKED, 1); + } + return err; +} + int fsync_super(struct super_block *sb) { - kdev_t dev = sb->s_dev; - sync_buffers(dev, 0); + sync_buffers(sb->s_bdev, 0); lock_kernel(); sync_inodes_sb(sb); @@ -331,14 +354,13 @@ int fsync_super(struct super_block *sb) unlock_super(sb); unlock_kernel(); - return sync_buffers(dev, 1); + return sync_buffers(sb->s_bdev, 1); } int fsync_no_super(struct block_device *bdev) { - kdev_t dev = to_kdev_t(bdev->bd_dev); - sync_buffers(dev, 0); - return sync_buffers(dev, 1); + sync_buffers(bdev, 0); + return sync_buffers(bdev, 1); } int fsync_dev(kdev_t dev) @@ -365,7 +387,7 @@ int fsync_bdev(struct block_device *bdev) asmlinkage long sys_sync(void) { - sync_buffers(NODEV, 0); + sync_all_buffers(0); lock_kernel(); sync_inodes(); @@ -373,7 +395,7 @@ asmlinkage long sys_sync(void) sync_supers(); unlock_kernel(); - sync_buffers(NODEV, 1); + sync_all_buffers(1); return 0; } @@ -385,7 +407,6 @@ int file_fsync(struct file *filp, struct dentry *dentry, int datasync) { struct inode * inode = dentry->d_inode; struct super_block * sb; - kdev_t dev; int ret; lock_kernel(); @@ -400,8 +421,7 @@ int file_fsync(struct file *filp, struct dentry *dentry, int datasync) unlock_super(sb); /* .. finally sync the buffers to disk */ - dev = inode->i_dev; - ret = sync_buffers(dev, 1); + ret = sync_buffers(sb->s_bdev, 1); unlock_kernel(); return ret; } diff --git a/include/linux/fs.h b/include/linux/fs.h index a39d861d25a3..414bf25bea5f 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1215,7 +1215,7 @@ extern void __invalidate_buffers(kdev_t dev, int); extern void sync_inodes(void); extern void sync_unlocked_inodes(void); extern void write_inode_now(struct inode *, int); -extern int sync_buffers(kdev_t, int); +extern int sync_buffers(struct block_device *, int); extern int fsync_dev(kdev_t); extern int fsync_bdev(struct block_device *); extern int fsync_super(struct super_block *); -- cgit v1.2.3 From 94982b1e033ad4e680e63450ce3f54ea0634dd46 Mon Sep 17 00:00:00 2001 From: Alexander Viro Date: Wed, 27 Feb 2002 20:24:00 -0800 Subject: [PATCH] (6/7) kdev_t removals * in intermezzo a bunch of places where we are comparing ->s_dev are replaced with comparing pointers to superblocks. --- fs/intermezzo/cache.c | 24 +++++++++++------------- fs/intermezzo/inode.c | 2 +- fs/intermezzo/presto.c | 4 ++-- fs/intermezzo/super.c | 6 +++--- fs/intermezzo/vfs.c | 6 +++--- include/linux/intermezzo_fs.h | 3 +-- 6 files changed, 21 insertions(+), 24 deletions(-) (limited to 'include/linux') diff --git a/fs/intermezzo/cache.c b/fs/intermezzo/cache.c index 0526fd33a351..7c3d32d4152f 100644 --- a/fs/intermezzo/cache.c +++ b/fs/intermezzo/cache.c @@ -44,16 +44,15 @@ #define CACHES_MASK CACHES_SIZE - 1 static struct list_head presto_caches[CACHES_SIZE]; -static inline int presto_cache_hash(kdev_t dev) +static inline int presto_cache_hash(struct super_block *sb) { - return (CACHES_MASK) & ((0x000F & (kdev_val(dev))) + ((0x0F00 & (kdev_val(dev))) >>8)); + return (CACHES_MASK) & ((unsigned long)sb / L1_CACHE_BYTES); } -inline void presto_cache_add(struct presto_cache *cache, kdev_t dev) +inline void presto_cache_add(struct presto_cache *cache, struct super_block *sb) { list_add(&cache->cache_chain, - &presto_caches[presto_cache_hash(dev)]); - cache->cache_dev = dev; + &presto_caches[presto_cache_hash(sb)]); } inline void presto_init_cache_hash(void) @@ -65,17 +64,16 @@ inline void presto_init_cache_hash(void) } /* map a device to a cache */ -struct presto_cache *presto_find_cache(kdev_t dev) +struct presto_cache *presto_find_cache(struct super_block *sb) { struct presto_cache *cache; struct list_head *lh, *tmp; - lh = tmp = &(presto_caches[presto_cache_hash(dev)]); + lh = tmp = &(presto_caches[presto_cache_hash(sb)]); while ( (tmp = lh->next) != lh ) { cache = list_entry(tmp, struct presto_cache, cache_chain); - if ( kdev_same(cache->cache_dev, dev) ) { + if (cache->cache_sb == sb) return cache; - } } return NULL; } @@ -87,10 +85,10 @@ struct presto_cache *presto_get_cache(struct inode *inode) struct presto_cache *cache; /* find the correct presto_cache here, based on the device */ - cache = presto_find_cache(inode->i_dev); + cache = presto_find_cache(inode->i_sb); if ( !cache ) { - printk("WARNING: no presto cache for dev %x, ino %ld\n", - kdev_val(inode->i_dev), inode->i_ino); + printk("WARNING: no presto cache for dev %s, ino %ld\n", + inode->i_sb->s_id, inode->i_ino); EXIT; return NULL; } @@ -174,7 +172,7 @@ int presto_ispresto(struct inode *inode) cache = presto_get_cache(inode); if ( !cache ) return 0; - return (kdev_same(inode->i_dev, cache->cache_dev)); + return (inode->i_sb == cache->cache_sb); } /* setup a cache structure when we need one */ diff --git a/fs/intermezzo/inode.c b/fs/intermezzo/inode.c index d756dcfc096d..111721845226 100644 --- a/fs/intermezzo/inode.c +++ b/fs/intermezzo/inode.c @@ -113,7 +113,7 @@ void presto_put_super(struct super_block *sb) struct list_head *lh; ENTRY; - cache = presto_find_cache(sb->s_dev); + cache = presto_find_cache(sb); if (!cache) { EXIT; goto exit; diff --git a/fs/intermezzo/presto.c b/fs/intermezzo/presto.c index ad89030bec0d..8c0d22467901 100644 --- a/fs/intermezzo/presto.c +++ b/fs/intermezzo/presto.c @@ -71,8 +71,8 @@ int presto_i2m(struct inode *inode) cache = presto_get_cache(inode); CDEBUG(D_PSDEV, "\n"); if ( !cache ) { - printk("PRESTO: BAD: cannot find cache for dev %x, ino %ld\n", - kdev_val(inode->i_dev), inode->i_ino); + printk("PRESTO: BAD: cannot find cache for dev %s, ino %ld\n", + inode->i_sb->s_id, inode->i_ino); EXIT; return -1; } diff --git a/fs/intermezzo/super.c b/fs/intermezzo/super.c index 7081dbdd22c6..de9d181359dc 100644 --- a/fs/intermezzo/super.c +++ b/fs/intermezzo/super.c @@ -39,7 +39,7 @@ long presto_kmemory = 0; #endif extern struct presto_cache *presto_init_cache(void); -extern inline void presto_cache_add(struct presto_cache *cache, kdev_t dev); +extern inline void presto_cache_add(struct presto_cache *cache, struct super_block *sb); extern inline void presto_init_cache_hash(void); int presto_remount(struct super_block *, int *, char *); @@ -325,7 +325,7 @@ struct super_block * presto_read_super(struct super_block * presto_sb, filter_setup_journal_ops(cache->cache_filter, cache->cache_type); /* we now know the dev of the cache: hash the cache */ - presto_cache_add(cache, mysb->s_dev); + presto_cache_add(cache, mysb); /* make sure we have our own super operations: mysb still contains the cache operations */ @@ -402,7 +402,7 @@ int presto_remount(struct super_block * sb, int *flags, char *data) } } - cache = presto_find_cache(sb->s_dev); + cache = presto_find_cache(sb); if (!cache) { printk(__FUNCTION__ ": cannot find cache on remount\n"); err = -ENODEV; diff --git a/fs/intermezzo/vfs.c b/fs/intermezzo/vfs.c index f8fbdc96352d..2af4d255852f 100644 --- a/fs/intermezzo/vfs.c +++ b/fs/intermezzo/vfs.c @@ -602,7 +602,7 @@ int presto_do_link(struct presto_file_set *fset, struct dentry *old_dentry, goto exit_lock; error = -EXDEV; - if (!kdev_same(dir->d_inode->i_dev, inode->i_dev)) + if (dir->d_inode->i_sb != inode->i_sb) goto exit_lock; /* @@ -1609,7 +1609,7 @@ int presto_rename_dir(struct presto_file_set *fset, struct dentry *old_parent, if (error) return error; - if (!kdev_same(new_dir->i_dev, old_dir->i_dev)) + if (new_dir->i_sb != old_dir->i_sb) return -EXDEV; if (!new_dentry->d_inode) @@ -1690,7 +1690,7 @@ int presto_rename_other(struct presto_file_set *fset, struct dentry *old_parent, if (error) return error; - if (!kdev_same(new_dir->i_dev, old_dir->i_dev)) + if (new_dir->i_sb != old_dir->i_sb) return -EXDEV; if (!new_dentry->d_inode) diff --git a/include/linux/intermezzo_fs.h b/include/linux/intermezzo_fs.h index 240dd8f24fe6..a0fe6dbc4622 100644 --- a/include/linux/intermezzo_fs.h +++ b/include/linux/intermezzo_fs.h @@ -68,7 +68,7 @@ struct kml_fsdata }; /* super.c */ -struct presto_cache *presto_find_cache(kdev_t dev) ; +struct presto_cache *presto_find_cache(struct super_block *sb) ; extern struct file_system_type presto_fs_type; extern int init_intermezzo_fs(void); @@ -89,7 +89,6 @@ struct presto_cache { int cache_flags; char *cache_root_fileset; /* fileset mounted on cache "/" */ - kdev_t cache_dev; /* underlying block device */ struct super_block *cache_sb; struct dentry *cache_mtde; /* unix mtpt of cache XXX NOT VALID XXX */ char *cache_mtpt; /* again */ -- cgit v1.2.3